From d467cd6844b9736418e1f447d8c01307044e0e8d Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 6 Aug 2021 00:50:23 +0800 Subject: improve find_package --- .../modules/package/manager/xmake/find_package.lua | 34 +++++++++------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/xmake/modules/package/manager/xmake/find_package.lua b/xmake/modules/package/manager/xmake/find_package.lua index dab32de33..9f565c2b1 100644 --- a/xmake/modules/package/manager/xmake/find_package.lua +++ b/xmake/modules/package/manager/xmake/find_package.lua @@ -73,38 +73,32 @@ function _find_package_from_repo(name, opt) local links = {} local linkdirs = {} local libfiles = {} - for _, linkdir in ipairs(vars.linkdirs) do - table.insert(linkdirs, path.join(installdir, linkdir)) - end if vars.links then table.join2(links, vars.links) - end - if not vars.linkdirs or not vars.links then + else + -- we scan links automatically local found = false - for _, file in ipairs(os.files(path.join(installdir, "lib", "*"))) do - if file:endswith(".lib") or file:endswith(".a") then - found = true - if not vars.linkdirs then - table.insert(linkdirs, path.directory(file)) - end - if not vars.links then + for _, libdir in ipairs(vars.linkdirs or "lib") do + for _, file in ipairs(os.files(path.join(installdir, libdir, "*"))) do + if file:endswith(".lib") or file:endswith(".a") then + found = true table.insert(links, target.linkname(path.filename(file))) end end - end - if not found then - for _, file in ipairs(os.files(path.join(installdir, "lib", "*"))) do - if file:endswith(".so") or file:endswith(".dylib") then - if not vars.linkdirs then - table.insert(linkdirs, path.directory(file)) - end - if not vars.links then + if not found then + for _, file in ipairs(os.files(path.join(installdir, "lib", "*"))) do + if file:endswith(".so") or file:endswith(".dylib") then table.insert(links, target.linkname(path.filename(file))) end end end end end + if #links > 0 then + for _, libdir in ipairs(vars.linkdirs or "lib") do + table.insert(linkdirs, path.join(installdir, libdir)) + end + end if opt.plat == "windows" then for _, file in ipairs(os.files(path.join(installdir, "lib", "*.dll"))) do result.shared = true -- cgit v1.3.1 From 776f5e79c7396497ad0bb2f45cf939f5d4f9ddca Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 6 Aug 2021 13:30:15 +0800 Subject: Update package.lua --- xmake/core/package/package.lua | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 28473c2bf..fefa4eb17 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -255,12 +255,17 @@ function _instance:artifacts_set(artifacts_info) if not manifest then os.raise("package(%s): load manifest.txt failed when installing artifacts!", package:displayname()) end - local vars = manifest.vars - if vars then - for k, v in pairs(vars) do + if manifest.vars then + for k, v in pairs(manifest.vars) do package:set(k, v) end end + if manifest.envs then + local envs = self:envs() + for k, v in pairs(manifest.envs) do + envs[k] = v + end + end end) self._IS_PRECOMPILED = true end -- cgit v1.3.1 From 5bbd1907fea3c0a1745d925ed967f1ecfee46a84 Mon Sep 17 00:00:00 2001 From: Hoildkv <42310255+xq114@users.noreply.github.com> Date: Sat, 7 Aug 2021 00:14:54 +0800 Subject: fix cuda ccbin auto-detection on windows --- xmake/toolchains/cuda/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/toolchains/cuda/xmake.lua b/xmake/toolchains/cuda/xmake.lua index ca25dcb74..29079d656 100644 --- a/xmake/toolchains/cuda/xmake.lua +++ b/xmake/toolchains/cuda/xmake.lua @@ -28,7 +28,7 @@ toolchain("cuda") -- set toolset set_toolset("cu", "nvcc", "clang") set_toolset("culd", "nvcc") - set_toolset("cu-ccbin", "$(env CXX)", "$(env CC)", "clang", "gcc") + set_toolset("cu-ccbin", "$(env CXX)", "$(env CC)") -- bind msvc environments, because nvcc will call cl.exe on_load(function (toolchain) -- cgit v1.3.1 From bd6724a7494e88a3c78961d2b68319958efb277f Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 7 Aug 2021 00:37:59 +0800 Subject: improve rule --- xmake/core/project/target.lua | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 3eed0cdad..ac9b63a0c 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -1116,11 +1116,15 @@ function _instance:filerules(sourcefile) if not key2rules then key2rules = {} for _, r in pairs(table.wrap(self:rules())) do - for _, sourcekind in ipairs(table.wrap(r:get("sourcekinds"))) do + -- we can also get sourcekinds from add_rules("xxx", {sourcekinds = "cxx"}) + local rule_sourcekinds = self:extraconf("rules", r:name(), "sourcekinds") or r:get("sourcekinds") + for _, sourcekind in ipairs(table.wrap(rule_sourcekinds)) do key2rules[sourcekind] = key2rules[sourcekind] or {} table.insert(key2rules[sourcekind], r) end - for _, extension in ipairs(table.wrap(r:get("extensions"))) do + -- we can also get extensions from add_rules("xxx", {extensions = ".cpp"}) + local rule_extensions = self:extraconf("rules", r:name(), "extensions") or r:get("extensions") + for _, extension in ipairs(table.wrap(rule_extensions)) do extension = extension:lower() key2rules[extension] = key2rules[extension] or {} table.insert(key2rules[extension], r) @@ -1130,13 +1134,26 @@ function _instance:filerules(sourcefile) end -- get target rules from the given sourcekind or extension + local rules_override = {} local filename = path.filename(sourcefile):lower() for _, r in ipairs(table.wrap(key2rules[path.extension(filename, 2)] or - key2rules[path.extension(filename)] or - key2rules[self:sourcekind_of(filename)])) do - table.insert(rules, r) + key2rules[path.extension(filename)])) do + if self:extraconf("rules", r:name(), "override") then + table.insert(rules_override, r) + else + table.insert(rules, r) + end + end + for _, r in ipairs(table.wrap(key2rules[self:sourcekind_of(filename)])) do + if self:extraconf("rules", r:name(), "override") then + table.insert(rules_override, r) + else + table.insert(rules, r) + end end - return rules + + -- we will use overrided rules first, e.g. add_rules("xxx", {override = true}) + return #rules_override > 0 and rules_override or rules end -- get the config info of the given source file -- cgit v1.3.1 From c31dca026e2fd927b0719a03adf4d346f1be4662 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 7 Aug 2021 00:42:17 +0800 Subject: improve bin2c test --- tests/projects/other/bin2c/xmake.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/projects/other/bin2c/xmake.lua b/tests/projects/other/bin2c/xmake.lua index b5517a54e..b4c71e705 100644 --- a/tests/projects/other/bin2c/xmake.lua +++ b/tests/projects/other/bin2c/xmake.lua @@ -2,9 +2,9 @@ add_rules("mode.debug", "mode.release") target("test") set_kind("binary") - add_rules("utils.bin2c", {linewidth = 16}) + add_rules("utils.bin2c", {linewidth = 16, extensions = {".bin", ".png"}}) add_files("src/*.c") add_files("src/*.bin") - add_files("src/*.png", {rules = "utils.bin2c"}) + add_files("src/*.png") -- cgit v1.3.1 From 53f3581ce3d32547ac15c69d4a52933ad3835848 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 7 Aug 2021 09:01:07 +0800 Subject: Update test.lua --- tests/projects/other/bin2c/test.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/projects/other/bin2c/test.lua b/tests/projects/other/bin2c/test.lua index b57362078..5644bd34c 100644 --- a/tests/projects/other/bin2c/test.lua +++ b/tests/projects/other/bin2c/test.lua @@ -1,3 +1,3 @@ function main(t) - t:build() +-- t:build() end -- cgit v1.3.1 From b88ee0743509944ac9cb1c54bf2feed7d4c596b5 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 7 Aug 2021 15:19:54 +0800 Subject: Update xmake.lua --- xmake/rules/utils/bin2c/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/utils/bin2c/xmake.lua b/xmake/rules/utils/bin2c/xmake.lua index 12db55192..5110ea2fd 100644 --- a/xmake/rules/utils/bin2c/xmake.lua +++ b/xmake/rules/utils/bin2c/xmake.lua @@ -36,7 +36,7 @@ rule("utils.bin2c") table.insert(argv, "-w") table.insert(argv, tostring(linewidth)) end - batchcmds:vrunv(os.programfile(), argv) + batchcmds:vrunv(os.programfile(), argv, {envs = {XMAKE_SKIP_HISTORY = "y"}}) -- add deps batchcmds:add_depfiles(sourcefile_bin) -- cgit v1.3.1 From b82ffd74db0a424c9c94b3e499c6be7e94f558e2 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 7 Aug 2021 15:20:35 +0800 Subject: Update test.lua --- tests/projects/other/bin2c/test.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/projects/other/bin2c/test.lua b/tests/projects/other/bin2c/test.lua index 5644bd34c..b57362078 100644 --- a/tests/projects/other/bin2c/test.lua +++ b/tests/projects/other/bin2c/test.lua @@ -1,3 +1,3 @@ function main(t) --- t:build() + t:build() end -- cgit v1.3.1 From ae33b24ea5ecb6608168e869bb8ee94e0f674c98 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 7 Aug 2021 22:27:28 +0800 Subject: improve package --- xmake/actions/package/local/main.lua | 1 - xmake/actions/package/remote/main.lua | 17 +++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/xmake/actions/package/local/main.lua b/xmake/actions/package/local/main.lua index 21c807091..74bb1cfa1 100644 --- a/xmake/actions/package/local/main.lua +++ b/xmake/actions/package/local/main.lua @@ -32,7 +32,6 @@ function _get_linkdeps(target) for _, depname in ipairs(target:get("deps")) do local dep = project.target(depname) if not ((target:is_binary() or target:is_shared()) and dep:is_static()) then - table.join2(linkdeps, _get_linkdeps(dep)) table.insert(linkdeps, dep:name()) end end diff --git a/xmake/actions/package/remote/main.lua b/xmake/actions/package/remote/main.lua index 064141b56..b38fa6626 100644 --- a/xmake/actions/package/remote/main.lua +++ b/xmake/actions/package/remote/main.lua @@ -26,6 +26,18 @@ import("core.project.config") import("core.project.project") import("lib.luajit.bit") +-- get link deps +function _get_linkdeps(target) + local linkdeps = {} + for _, depname in ipairs(target:get("deps")) do + local dep = project.target(depname) + if not ((target:is_binary() or target:is_shared()) and dep:is_static()) then + table.insert(linkdeps, dep:name()) + end + end + return linkdeps +end + -- package remote function _package_remote(target) @@ -41,10 +53,7 @@ function _package_remote(target) -- generate xmake.lua local file = io.open(path.join(packagedir, "xmake.lua"), "w") if file then - local deps = {} - for _, dep in ipairs(target:orderdeps()) do - table.insert(deps, dep:name()) - end + local deps = _get_linkdeps(target) file:print("package(\"%s\")", packagename) if target:is_binary() then file:print(" set_kind(\"binary\")") -- cgit v1.3.1 From 119b04dfa9e6971f324ba65d94737ad7eb31bc83 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 10 Aug 2021 00:50:52 +0800 Subject: support to run snippets --- tests/apis/check_xxx/config.h.in | 2 + tests/apis/check_xxx/xmake.lua | 4 + xmake/core/base/interpreter.lua | 17 ++- xmake/core/base/scopeinfo.lua | 16 ++- xmake/core/project/option.lua | 150 +++++++++++++++++++++----- xmake/includes/check_csnippets.lua | 30 +++++- xmake/includes/check_cxxsnippets.lua | 30 +++++- xmake/modules/lib/detect/check_cxsnippets.lua | 53 ++++++--- 8 files changed, 255 insertions(+), 47 deletions(-) diff --git a/tests/apis/check_xxx/config.h.in b/tests/apis/check_xxx/config.h.in index c5e178b44..0c7d9ebf8 100644 --- a/tests/apis/check_xxx/config.h.in +++ b/tests/apis/check_xxx/config.h.in @@ -8,3 +8,5 @@ ${define HAS_SETJMP} ${define HAS_CONSTEXPR} ${define HAS_CONSEXPR_AND_STATIC_ASSERT} ${define HAS_SSE2} +${define HAS_LONG_8} +${define PTR_SIZE} diff --git a/tests/apis/check_xxx/xmake.lua b/tests/apis/check_xxx/xmake.lua index a2a5fa0b1..2a9916954 100644 --- a/tests/apis/check_xxx/xmake.lua +++ b/tests/apis/check_xxx/xmake.lua @@ -13,6 +13,8 @@ target("test") check_ctypes("HAS_WCHAR", "wchar_t") check_cincludes("HAS_STRING_H", "string.h") + check_csnippets("HAS_INT_4", "return (sizeof(int) == 4)? 0 : -1;", {tryrun = true}) + check_csnippets("INT_SIZE", 'printf("%d", sizeof(int)); return 0;', {output = true, number = true}) configvar_check_cincludes("HAS_STRING_AND_STDIO_H", {"string.h", "stdio.h"}) configvar_check_ctypes("HAS_WCHAR_AND_FLOAT", {"wchar_t", "float"}) configvar_check_links("HAS_PTHREAD", {"pthread", "m", "dl"}) @@ -21,3 +23,5 @@ target("test") configvar_check_features("HAS_CONSTEXPR", "cxx_constexpr", {languages = "c++11"}) configvar_check_features("HAS_CONSEXPR_AND_STATIC_ASSERT", {"cxx_constexpr", "c_static_assert"}, {languages = "c++11"}) configvar_check_cflags("HAS_SSE2", "-msse2") + configvar_check_csnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true}) + configvar_check_csnippets("PTR_SIZE", 'printf("%d", sizeof(void*)); return 0;', {output = true, number = true}) diff --git a/xmake/core/base/interpreter.lua b/xmake/core/base/interpreter.lua index 2f26e20ce..ecfcc7270 100644 --- a/xmake/core/base/interpreter.lua +++ b/xmake/core/base/interpreter.lua @@ -1225,13 +1225,19 @@ function interpreter:api_register_set_dictionary(scope_kind, ...) assert(self) -- define implementation - local implementation = function (self, scope, name, dict_or_key, value) + local implementation = function (self, scope, name, dict_or_key, value, extra_config) -- check if type(dict_or_key) == "table" then scope[name] = dict_or_key elseif type(dict_or_key) == "string" and value ~= nil then scope[name] = {[dict_or_key] = value} + -- save extra config + if extra_config and table.is_dictionary(extra_config) then + scope["__extra_" .. name] = scope["__extra_" .. name] or {} + local extrascope = scope["__extra_" .. name] + extrascope[dict_or_key] = extra_config + end else -- error os.raise("set_%s(%s): invalid value type!", name, type(dict)) @@ -1249,14 +1255,21 @@ function interpreter:api_register_add_dictionary(scope_kind, ...) assert(self) -- define implementation - local implementation = function (self, scope, name, dict_or_key, value) + local implementation = function (self, scope, name, dict_or_key, value, extra_config) -- check scope[name] = scope[name] or {} if type(dict_or_key) == "table" then table.join2(scope[name], dict_or_key) + extra_config = value elseif type(dict_or_key) == "string" and value ~= nil then scope[name][dict_or_key] = value + -- save extra config + if extra_config and table.is_dictionary(extra_config) then + scope["__extra_" .. name] = scope["__extra_" .. name] or {} + local extrascope = scope["__extra_" .. name] + extrascope[dict_or_key] = extra_config + end else -- error os.raise("add_%s(%s): invalid value type!", name, type(dict)) diff --git a/xmake/core/base/scopeinfo.lua b/xmake/core/base/scopeinfo.lua index 70755e14a..1f07e236f 100644 --- a/xmake/core/base/scopeinfo.lua +++ b/xmake/core/base/scopeinfo.lua @@ -238,7 +238,7 @@ function _instance:_api_add_keyvalues(name, key, ...) end -- set the api dictionary to the scope info -function _instance:_api_set_dictionary(name, dict_or_key, value) +function _instance:_api_set_dictionary(name, dict_or_key, value, extra_config) -- get the scope info local scope = self._INFO @@ -252,6 +252,12 @@ function _instance:_api_set_dictionary(name, dict_or_key, value) scope[name] = dict elseif type(dict_or_key) == "string" and value ~= nil then scope[name] = {[dict_or_key] = self:_api_handle(value)} + -- save extra config + if extra_config and table.is_dictionary(extra_config) then + scope["__extra_" .. name] = scope["__extra_" .. name] or {} + local extrascope = scope["__extra_" .. name] + extrascope[dict_or_key] = extra_config + end else -- error os.raise("%s:set(%s, ...): invalid value type!", self:kind(), name, type(dict)) @@ -259,7 +265,7 @@ function _instance:_api_set_dictionary(name, dict_or_key, value) end -- add the api dictionary to the scope info -function _instance:_api_add_dictionary(name, dict_or_key, value) +function _instance:_api_add_dictionary(name, dict_or_key, value, extra_config) -- get the scope info local scope = self._INFO @@ -274,6 +280,12 @@ function _instance:_api_add_dictionary(name, dict_or_key, value) table.join2(scope[name], dict) elseif type(dict_or_key) == "string" and value ~= nil then scope[name][dict_or_key] = self:_api_handle(value) + -- save extra config + if extra_config and table.is_dictionary(extra_config) then + scope["__extra_" .. name] = scope["__extra_" .. name] or {} + local extrascope = scope["__extra_" .. name] + extrascope[dict_or_key] = extra_config + end else -- error os.raise("%s:add(%s, ...): invalid value type!", self:kind(), name, type(dict)) diff --git a/xmake/core/project/option.lua b/xmake/core/project/option.lua index 93d25990f..e9a2ef20d 100644 --- a/xmake/core/project/option.lua +++ b/xmake/core/project/option.lua @@ -68,22 +68,23 @@ function _instance:_clear() option._cache():set(self:name(), nil) end --- check option conditions -function _instance:_do_check() +-- check snippets +function _instance:_do_check_cxsnippts(snippets) -- import check_cxsnippets() self._check_cxsnippets = self._check_cxsnippets or sandbox_module.import("lib.detect.check_cxsnippets", {anonymous = true}) -- check for c and c++ - local passed = nil + local passed = 0 + local result_output for _, kind in ipairs({"c", "cxx"}) do -- get conditions - local links = self:get("links") - local snippets = self:get(kind .. "snippets") - local types = self:get(kind .. "types") - local funcs = self:get(kind .. "funcs") - local includes = self:get(kind .. "includes") + local links = self:get("links") + local snippets = self:get(kind .. "snippets") + local types = self:get(kind .. "types") + local funcs = self:get(kind .. "funcs") + local includes = self:get(kind .. "includes") -- TODO it is deprecated local snippet = self:get(kind .. "snippet") @@ -100,23 +101,98 @@ function _instance:_do_check() sourcekind = "cc" end - -- check it - local ok, results_or_errors = sandbox.load(self._check_cxsnippets, snippets, {target = self, sourcekind = sourcekind, types = types, funcs = funcs, includes = includes}) - if not ok then - return false, results_or_errors + -- split snippets + local snippets_build = {} + local snippets_tryrun = {} + local snippets_output = {} + if snippets then + for name, snippet in pairs(snippets) do + if self:extraconf(kind .. "snippets", name, "output") then + snippets_output[name] = snippet + elseif self:extraconf(kind .. "snippets", name, "tryrun") then + snippets_tryrun[name] = snippet + else + snippets_build[name] = snippet + end + end + if #table.keys(snippets_output) > 1 then + return false, -1, string.format("option(%s): only support for only one snippet with output!", self:name()) + end + end + + -- check snippets (run with output) + if #table.keys(snippets_output) > 0 then + local ok, results_or_errors, output = sandbox.load(self._check_cxsnippets, snippets_output, { + target = self, + sourcekind = sourcekind, + types = types, + funcs = funcs, + includes = includes, + tryrun = true, output = true}) + if not ok then + return false, -1, results_or_errors + end + + -- passed or no passed? + if results_or_errors then + passed = 1 + result_output = output + else + passed = -1 + break + end end - -- passed? - if results_or_errors then - passed = true - else - passed = false - break + -- check snippets (run only) + if passed == 0 and #table.keys(snippets_tryrun) > 0 then + local ok, results_or_errors = sandbox.load(self._check_cxsnippets, snippets_tryrun, { + target = self, + sourcekind = sourcekind, + types = types, + funcs = funcs, + includes = includes, + tryrun = true}) + if not ok then + return false, -1, results_or_errors + end + + -- passed or no passed? + if results_or_errors then + passed = 1 + else + passed = -1 + break + end + end + + -- check snippets (build only) + if passed == 0 or #table.keys(snippets_build) > 0 then + local ok, results_or_errors = sandbox.load(self._check_cxsnippets, snippets_build, { + target = self, + sourcekind = sourcekind, + types = types, + funcs = funcs, + includes = includes}) + if not ok then + return false, -1, results_or_errors + end + + -- passed or no passed? + if results_or_errors then + passed = 1 + else + passed = -1 + break + end end end end + return true, passed, result_output +end - -- check features +-- check features +function _instance:_do_check_features() + local passed = 0 local features = self:get("features") if features then @@ -127,23 +203,49 @@ function _instance:_do_check() features = table.wrap(features) local features_supported = self._core_tool_compiler.has_features(features, {target = self}) if features_supported and #features_supported == #features then - passed = true + passed = 1 end -- trace if baseoption.get("verbose") or baseoption.get("diagnosis") then for _, feature in ipairs(features) do - utils.cprint("${dim}checking for feature(%s) ... %s", feature, passed and "${color.success}${text.success}" or "${color.nothing}${text.nothing}") + utils.cprint("${dim}checking for feature(%s) ... %s", feature, passed > 0 and "${color.success}${text.success}" or "${color.nothing}${text.nothing}") end end end + return true, passed +end - -- enable this option if be passed +-- check option conditions +function _instance:_do_check() + + -- check snippets + local ok, passed, errors = self:_do_check_cxsnippts() + if not ok then + return false, errors + end + + -- get snippet output + local output if passed then - self:enable(true) + output = errors end - -- ok + -- check features + if passed == 0 then + ok, passed, errors = self:_do_check_features() + if not ok then + return false, errors + end + end + + -- enable this option if be passed + if passed > 0 then + self:enable(true) + if output then + self:set_value(output) + end + end return true end diff --git a/xmake/includes/check_csnippets.lua b/xmake/includes/check_csnippets.lua index 6cd4ccdc9..06fdc842e 100644 --- a/xmake/includes/check_csnippets.lua +++ b/xmake/includes/check_csnippets.lua @@ -23,13 +23,17 @@ -- e.g. -- -- check_csnippets("HAS_STATIC_ASSERT", "_Static_assert(1, \"\");", {includes = "stdio.h"}) +-- check_csnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true}) +-- check_csnippets("PTR_SIZE", 'printf("%d", sizeof(void*)); return 0;', {output = true, number = true}) -- function check_csnippets(definition, snippets, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) option(optname) - add_csnippets(definition, snippets) - add_defines(definition) + add_csnippets(definition, snippets, {tryrun = opt.tryrun, output = opt.output}) + if not opt.output then + add_defines(definition) + end if opt.links then add_links(opt.links) end @@ -51,6 +55,17 @@ function check_csnippets(definition, snippets, opt) if opt.warnings then set_warnings(opt.warnings) end + if opt.output then + after_check(function (option) + if option:value() then + if opt.number then + option:add("defines", definition .. "=" .. tonumber(option:value())) + else + option:add("defines", definition .. "=\"" .. option:value() .. "\"") + end + end + end) + end option_end() add_options(optname) end @@ -60,13 +75,15 @@ end -- e.g. -- -- configvar_check_csnippets("HAS_STATIC_ASSERT", "_Static_assert(1, \"\");", {includes = "stdio.h"}) +-- configvar_check_csnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true}) +-- configvar_check_csnippets("PTR_SIZE", 'printf("%d", sizeof(void*)); return 0;', {output = true, number = true}) -- function configvar_check_csnippets(definition, snippets, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) option(optname) - add_csnippets(definition, snippets) + add_csnippets(definition, snippets, {tryrun = opt.tryrun, output = opt.output}) set_configvar(defname, defval or 1) if opt.links then add_links(opt.links) @@ -89,6 +106,13 @@ function configvar_check_csnippets(definition, snippets, opt) if opt.warnings then set_warnings(opt.warnings) end + if opt.output then + after_check(function (option) + if option:value() then + option:set("configvar", defname, opt.number and tonumber(option:value()) or option:value()) + end + end) + end option_end() add_options(optname) end diff --git a/xmake/includes/check_cxxsnippets.lua b/xmake/includes/check_cxxsnippets.lua index 2e906100b..8f0f6f64d 100644 --- a/xmake/includes/check_cxxsnippets.lua +++ b/xmake/includes/check_cxxsnippets.lua @@ -23,13 +23,17 @@ -- e.g. -- -- check_cxxsnippets("HAS_STATIC_ASSERT", "static_assert(1, \"\");") +-- check_csnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true}) +-- check_csnippets("PTR_SIZE", 'printf("%d", sizeof(void*)); return 0;', {output = true, number = true}) -- function check_cxxsnippets(definition, snippets, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) option(optname) - add_cxxsnippets(definition, snippets) - add_defines(definition) + add_cxxsnippets(definition, snippets, {tryrun = opt.tryrun, output = opt.output}) + if not opt.output then + add_defines(definition) + end if opt.links then add_links(opt.links) end @@ -51,6 +55,17 @@ function check_cxxsnippets(definition, snippets, opt) if opt.warnings then set_warnings(opt.warnings) end + if opt.output then + after_check(function (option) + if option:value() then + if opt.number then + option:add("defines", definition .. "=" .. tonumber(option:value())) + else + option:add("defines", definition .. "=\"" .. option:value() .. "\"") + end + end + end) + end option_end() add_options(optname) end @@ -60,13 +75,15 @@ end -- e.g. -- -- configvar_check_cxxsnippets("HAS_STATIC_ASSERT", "static_assert(1, \"\");") +-- configvar_check_cxxsnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true}) +-- configvar_check_cxxsnippets("PTR_SIZE", 'printf("%d", sizeof(void*)); return 0;', {output = true, number = true}) -- function configvar_check_cxxsnippets(definition, snippets, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) option(optname) - add_cxxsnippets(definition, snippets) + add_cxxsnippets(definition, snippets, {tryrun = opt.tryrun, output = opt.output}) set_configvar(defname, defval or 1) if opt.links then add_links(opt.links) @@ -89,6 +106,13 @@ function configvar_check_cxxsnippets(definition, snippets, opt) if opt.warnings then set_warnings(opt.warnings) end + if opt.output then + after_check(function (option) + if option:value() then + option:set("configvar", defname, opt.number and tonumber(option:value()) or option:value()) + end + end) + end option_end() add_options(optname) end diff --git a/xmake/modules/lib/detect/check_cxsnippets.lua b/xmake/modules/lib/detect/check_cxsnippets.lua index aa728e27b..5352301b0 100644 --- a/xmake/modules/lib/detect/check_cxsnippets.lua +++ b/xmake/modules/lib/detect/check_cxsnippets.lua @@ -77,7 +77,11 @@ function _sourcecode(snippets, opt) -- add includes local sourcecode = "" - for _, include in ipairs(opt.includes) do + local includes = table.wrap(opt.includes) + if opt.tryrun and opt.output then + table.insert(includes, "stdio.h") + end + for _, include in ipairs(includes) do sourcecode = format("%s\n#include <%s>", sourcecode, include) end sourcecode = sourcecode .. "\n" @@ -88,11 +92,13 @@ function _sourcecode(snippets, opt) end sourcecode = sourcecode .. "\n" - -- add snippets - for _, snippet in pairs(snippets) do - sourcecode = sourcecode .. "\n" .. snippet + -- add snippets (build only) + if not opt.tryrun then + for _, snippet in pairs(snippets) do + sourcecode = sourcecode .. "\n" .. snippet + end + sourcecode = sourcecode .. "\n" end - sourcecode = sourcecode .. "\n" -- enter main function sourcecode = sourcecode .. "int main(int argc, char** argv)\n{\n" @@ -102,10 +108,19 @@ function _sourcecode(snippets, opt) sourcecode = format("%s\n %s;", sourcecode, _funccode(funcinfo)) end - -- leave main function - sourcecode = sourcecode .. "\n return 0;\n}\n" - - -- done + -- add snippets (tryrun) + if opt.tryrun then + for _, snippet in pairs(snippets) do + sourcecode = sourcecode .. "\n" .. snippet + end + if opt.output then + sourcecode = sourcecode .. "\nfflush(stdout);\n" + end + sourcecode = sourcecode .. "\n}\n" -- we need return exit code in snippet + else + -- leave main function + sourcecode = sourcecode .. "\n return 0;\n}\n" + end return sourcecode end @@ -116,7 +131,8 @@ end -- e.g. -- { verbose = false, target = [target|option], sourcekind = "[cc|cxx]" -- , types = {"wchar_t", "char*"}, includes = "stdio.h", funcs = {"sigsetjmp", "sigsetjmp((void*)0, 0)"} --- , configs = {defines = "xx", cxflags = ""}} +-- , configs = {defines = "xx", cxflags = ""} +-- , tryrun = true, output = true} -- -- funcs: -- sigsetjmp @@ -189,19 +205,30 @@ function main(snippets, opt) -- @note cannot cache result, all conditions will be changed -- attempt to compile it local errors = nil - local ok = try + local ok, output = try { function () if option.get("diagnosis") then cprint("${dim}> %s", compiler.compcmd(sourcefile, objectfile, opt)) end compiler.compile(sourcefile, objectfile, opt) - if #links > 0 then + if #links > 0 or opt.tryrun then if option.get("diagnosis") then cprint("${dim}> %s", linker.linkcmd("binary", {"cc", "cxx"}, objectfile, binaryfile, opt)) end linker.link("binary", {"cc", "cxx"}, objectfile, binaryfile, opt) end + if opt.tryrun then + if opt.output then + local output = os.iorun(binaryfile) + if output then + output = output:trim() + end + return true, output + else + os.vrun(binaryfile) + end + end return true end, catch { function (errs) errors = errs end } @@ -238,6 +265,6 @@ function main(snippets, opt) if errors and option.get("diagnosis") and #tostring(errors) > 0 then cprint("${color.warning}checkinfo:${clear dim} %s", errors) end - return ok + return ok, output end -- cgit v1.3.1 From ae334d9bc2c8b3c9e5595789db51561c238ec1dc Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 10 Aug 2021 22:33:43 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 756b3021d..bd50adf44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * [#1534](https://github.com/xmake-io/xmake/issues/1534): Support to compile Vala lanuage project * [#1544](https://github.com/xmake-io/xmake/issues/1544): Add utils.bin2c rule to generate header from binary file +* [#1547](https://github.com/xmake-io/xmake/issues/1547): Support to run and get output of c/c++ snippets in option ### Change @@ -1057,6 +1058,7 @@ * [#1534](https://github.com/xmake-io/xmake/issues/1534): 新增对 Vala 语言的支持 * [#1544](https://github.com/xmake-io/xmake/issues/1544): 添加 utils.bin2c 规则去自动从二进制资源文件产生 .h 头文件并引入到 C/C++ 代码中 +* [#1547](https://github.com/xmake-io/xmake/issues/1547): option/snippets 支持运行检测模式,并且可以获取输出 ### 改进 -- cgit v1.3.1 From 726000c395eb190fcec40e2d60d2059aeddac196 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 10 Aug 2021 22:37:09 +0800 Subject: fix depend.lua for link --- xmake/modules/core/project/depend.lua | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/xmake/modules/core/project/depend.lua b/xmake/modules/core/project/depend.lua index cb25db359..89a517c07 100644 --- a/xmake/modules/core/project/depend.lua +++ b/xmake/modules/core/project/depend.lua @@ -78,8 +78,8 @@ end function is_changed(dependinfo, opt) -- empty depend info? always be changed - local files = dependinfo.files or {} - local values = dependinfo.values or {} + local files = table.wrap(dependinfo.files) + local values = table.wrap(dependinfo.values) if #files == 0 and #values == 0 then return true end @@ -102,7 +102,7 @@ function is_changed(dependinfo, opt) -- check the dependent values are changed? local depvalues = values - local optvalues = opt.values or {} + local optvalues = table.wrap(opt.values) if #depvalues ~= #optvalues then return true end @@ -124,8 +124,11 @@ function is_changed(dependinfo, opt) end -- check the dependent files list are changed? - local optfiles = opt.files - if optfiles then + if opt.files then + local optfiles = table.wrap(opt.files) + if #files ~= #optfiles then + return true + end for idx, file in ipairs(files) do if file ~= optfiles[idx] then return true @@ -178,7 +181,7 @@ function on_changed(callback, opt) -- need build this object? -- @note we use mtime(dependfile) instead of mtime(objectfile) to ensure the object file is is fully compiled. -- @see https://github.com/xmake-io/xmake/issues/748 - if not is_changed(dependinfo, {lastmtime = opt.lastmtime or os.mtime(dependfile), values = opt.values}) then + if not is_changed(dependinfo, {lastmtime = opt.lastmtime or os.mtime(dependfile), values = opt.values, files = opt.files}) then return end -- cgit v1.3.1 From facf6f5b7be2266ca86015cafab3fe787cc18f94 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 10 Aug 2021 22:42:35 +0800 Subject: check circular deps --- xmake/core/project/project.lua | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 3ff962d7c..831c603bf 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -215,13 +215,22 @@ end -- -- orderdeps: c -> b -> a -- -function project._load_deps(instance, instances, deps, orderdeps) - - -- get dep instances +function project._load_deps(instance, instances, deps, orderdeps, depspath) for _, dep in ipairs(table.wrap(instance:get("deps"))) do local depinst = instances[dep] if depinst then - project._load_deps(depinst, instances, deps, orderdeps) + local depspath_sub + if depspath then + for idx, name in ipairs(depspath) do + if name == dep then + local circular_deps = table.slice(depspath, idx) + table.insert(circular_deps, dep) + os.raise("circular dependency(%s) detected!", table.concat(circular_deps, ", ")) + end + end + depspath_sub = table.join(depspath, dep) + end + project._load_deps(depinst, instances, deps, orderdeps, depspath_sub) if not deps[dep] then deps[dep] = depinst table.insert(orderdeps, depinst) @@ -316,7 +325,7 @@ function project._load_rules() for _, instance in pairs(instances) do instance._DEPS = instance._DEPS or {} instance._ORDERDEPS = instance._ORDERDEPS or {} - project._load_deps(instance, instances, instance._DEPS, instance._ORDERDEPS) + project._load_deps(instance, instances, instance._DEPS, instance._ORDERDEPS, {instance:name()}) end return rules end @@ -403,7 +412,7 @@ function project._load_targets() -- load deps t._DEPS = t._DEPS or {} t._ORDERDEPS = t._ORDERDEPS or {} - project._load_deps(t, targets, t._DEPS, t._ORDERDEPS) + project._load_deps(t, targets, t._DEPS, t._ORDERDEPS, {t:name()}) -- load rules from target and language -- @@ -547,7 +556,7 @@ function project._load_options(disable_filter) for _, opt in pairs(options) do opt._DEPS = opt._DEPS or {} opt._ORDERDEPS = opt._ORDERDEPS or {} - project._load_deps(opt, options, opt._DEPS, opt._ORDERDEPS) + project._load_deps(opt, options, opt._DEPS, opt._ORDERDEPS, {opt:name()}) end -- ok? -- cgit v1.3.1 From 19dced6cce6982590d18250bfd876dc8691c0ddb Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 10 Aug 2021 23:19:09 +0800 Subject: fix batchcmds --- xmake/modules/private/utils/batchcmds.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xmake/modules/private/utils/batchcmds.lua b/xmake/modules/private/utils/batchcmds.lua index 371735321..946135a87 100644 --- a/xmake/modules/private/utils/batchcmds.lua +++ b/xmake/modules/private/utils/batchcmds.lua @@ -128,21 +128,21 @@ end -- run command: os.cp function _runcmd_cp(cmd, opt) if not opt.dryrun then - os.cp(opt.srcpath, opt.dstpath, opt.opt) + os.cp(cmd.srcpath, cmd.dstpath, opt.opt) end end -- run command: os.mv function _runcmd_mv(cmd, opt) if not opt.dryrun then - os.mv(opt.srcpath, opt.dstpath, opt.opt) + os.mv(cmd.srcpath, cmd.dstpath, opt.opt) end end -- run command: os.ln function _runcmd_ln(cmd, opt) if not opt.dryrun then - os.ln(opt.srcpath, opt.dstpath, opt.opt) + os.ln(cmd.srcpath, cmd.dstpath, opt.opt) end end -- cgit v1.3.1 From 4c42d820fb5a29f2a935557bddb39830f8676c14 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 11 Aug 2021 00:37:48 +0800 Subject: improve find 7z for mingw/msys --- xmake/modules/detect/tools/find_7z.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xmake/modules/detect/tools/find_7z.lua b/xmake/modules/detect/tools/find_7z.lua index b441c2200..ce1a04f4a 100644 --- a/xmake/modules/detect/tools/find_7z.lua +++ b/xmake/modules/detect/tools/find_7z.lua @@ -55,6 +55,11 @@ function main(opt) program = find_program("7za", opt) end + -- find it from msys/mingw, it is only a shell script + if not program and is_subhost("msys") then + program = find_program("sh 7z", opt) + end + -- find program version local version = nil if program and opt and opt.version then -- cgit v1.3.1 From 406f1e2f66be1263636646667e8ce8aba0acee5a Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 11 Aug 2021 15:53:43 +0800 Subject: Update cmake_importfiles.lua --- xmake/modules/target/action/install/cmake_importfiles.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/target/action/install/cmake_importfiles.lua b/xmake/modules/target/action/install/cmake_importfiles.lua index 12d044251..0c27a72fd 100644 --- a/xmake/modules/target/action/install/cmake_importfiles.lua +++ b/xmake/modules/target/action/install/cmake_importfiles.lua @@ -37,7 +37,7 @@ function _install_cmake_importfile(target, installdir, filename, opt) -- get import file path local projectname = project.name() or target:name() local importfile_src = path.join(os.programdir(), "scripts", "cmake_importfiles", filename) - local importfile_dst = path.join(installdir, opt and opt.libdir or "lib", "cmake", projectname, (filename:gsub("xxx", projectname))) + local importfile_dst = path.join(installdir, opt and opt.libdir or "lib", "cmake", projectname, (filename:gsub("xxx", target:name()))) -- trace vprint("generating %s ..", importfile_dst) -- cgit v1.3.1 From e61891e35b9269e68c99dcad42a72c778b5fdebe Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 11 Aug 2021 16:20:05 +0800 Subject: Update project.lua --- xmake/core/project/project.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 831c603bf..fafc254bf 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -1091,7 +1091,12 @@ end -- get the mtimes function project.mtimes() - return project.interpreter():mtimes() + local mtimes = project._MTIMES + if not mtimes then + mtimes = project.interpreter():mtimes() + project._MTIMES = mtimes + end + return mtimes end -- get the project menu -- cgit v1.3.1 From a6f859c98508d1113807cbe71ae29c7ecf6ba474 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 11 Aug 2021 16:26:35 +0800 Subject: Update cmake_importfiles.lua --- xmake/modules/target/action/install/cmake_importfiles.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/target/action/install/cmake_importfiles.lua b/xmake/modules/target/action/install/cmake_importfiles.lua index 0c27a72fd..12d044251 100644 --- a/xmake/modules/target/action/install/cmake_importfiles.lua +++ b/xmake/modules/target/action/install/cmake_importfiles.lua @@ -37,7 +37,7 @@ function _install_cmake_importfile(target, installdir, filename, opt) -- get import file path local projectname = project.name() or target:name() local importfile_src = path.join(os.programdir(), "scripts", "cmake_importfiles", filename) - local importfile_dst = path.join(installdir, opt and opt.libdir or "lib", "cmake", projectname, (filename:gsub("xxx", target:name()))) + local importfile_dst = path.join(installdir, opt and opt.libdir or "lib", "cmake", projectname, (filename:gsub("xxx", projectname))) -- trace vprint("generating %s ..", importfile_dst) -- cgit v1.3.1 From 82839efc0adea5d263e2c19711efe3f1bf2e2681 Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Wed, 11 Aug 2021 19:49:15 +0800 Subject: generate cmake import files for multiple targets --- .../target/action/install/cmake_importfiles.lua | 78 +++++++++++++++++++--- xmake/scripts/cmake_importfiles/xxxTargets.cmake | 2 +- 2 files changed, 71 insertions(+), 9 deletions(-) diff --git a/xmake/modules/target/action/install/cmake_importfiles.lua b/xmake/modules/target/action/install/cmake_importfiles.lua index 12d044251..d311f19ce 100644 --- a/xmake/modules/target/action/install/cmake_importfiles.lua +++ b/xmake/modules/target/action/install/cmake_importfiles.lua @@ -25,14 +25,14 @@ import("core.project.project") function _get_builtinvars(target, installdir) return {TARGETNAME = target:name(), PROJECTNAME = project.name() or target:name(), - TARGETFILENAME = path.filename(target:targetfile()), + TARGETFILENAME = path.filename(target:targetfile()):replace("dll", "lib"), TARGETKIND = target:is_shared() and "SHARED" or "STATIC", PACKAGE_VERSION = target:get("version") or "1.0.0", TARGET_PTRBYTES = target:is_arch("x86", "i386") and "4" or "8"} end --- install cmake import file -function _install_cmake_importfile(target, installdir, filename, opt) +-- install cmake config file +function _install_cmake_configfile(target, installdir, filename, opt) -- get import file path local projectname = project.name() or target:name() @@ -45,6 +45,68 @@ function _install_cmake_importfile(target, installdir, filename, opt) -- get the builtin variables local builtinvars = _get_builtinvars(target, installdir) + -- copy and replace builtin variables + local content = io.readfile(importfile_src) + if content then + content = content:split("#######################+#")[1] + content = content:gsub("(@(.-)@)", function(_, variable) + variable = variable:trim() + local value = builtinvars[variable] + return type(value) == "function" and value() or value + end) + io.writefile(importfile_dst, content) + end +end + +-- append target to cmake config file +function _append_cmake_configfile(target, installdir, filename, opt) + + -- get import file path + local projectname = project.name() or target:name() + local importfile_src = path.join(os.programdir(), "scripts", "cmake_importfiles", filename) + local importfile_dst = path.join(installdir, opt and opt.libdir or "lib", "cmake", projectname, (filename:gsub("xxx", projectname))) + + -- get the builtin variables + local builtinvars = _get_builtinvars(target, installdir) + + -- generate the file if not exist / file is outdated + if not os.isfile(importfile_dst) or os.mtime(importfile_dst) < os.mtime(target:targetfile()) then + _install_cmake_configfile(target, installdir, filename, opt) + end + + -- copy and replace builtin variables + local content = io.readfile(importfile_src) + local dst_content = io.readfile(importfile_dst) + if content then + content = content:split("#######################+#")[2] + content = content:gsub("(@(.-)@)", function(_, variable) + variable = variable:trim() + local value = builtinvars[variable] + return type(value) == "function" and value() or value + end) + content = content:trim() + + -- check if the target already exists + if not dst_content:match(format("%sTargets.cmake", target:name())) then + io.writefile(importfile_dst, dst_content:trim() .. "\n\n" .. content .. "\n") + end + end +end + +-- install cmake target file +function _install_cmake_targetfile(target, installdir, filename, opt) + + -- get import file path + local projectname = project.name() or target:name() + local importfile_src = path.join(os.programdir(), "scripts", "cmake_importfiles", filename) + local importfile_dst = path.join(installdir, opt and opt.libdir or "lib", "cmake", projectname, (filename:gsub("xxx", target:name()))) + + -- trace + vprint("generating %s ..", importfile_dst) + + -- get the builtin variables + local builtinvars = _get_builtinvars(target, installdir) + -- copy and replace builtin variables local content = io.readfile(importfile_src) if content then @@ -71,13 +133,13 @@ function main(target, opt) end -- do install - _install_cmake_importfile(target, installdir, "xxxConfig.cmake", opt) - _install_cmake_importfile(target, installdir, "xxxConfigVersion.cmake", opt) - _install_cmake_importfile(target, installdir, "xxxTargets.cmake", opt) + _append_cmake_configfile(target, installdir, "xxxConfig.cmake", opt) + _install_cmake_configfile(target, installdir, "xxxConfigVersion.cmake", opt) + _install_cmake_targetfile(target, installdir, "xxxTargets.cmake", opt) if is_mode("debug") then - _install_cmake_importfile(target, installdir, "xxxTargets-debug.cmake", opt) + _install_cmake_targetfile(target, installdir, "xxxTargets-debug.cmake", opt) else - _install_cmake_importfile(target, installdir, "xxxTargets-release.cmake", opt) + _install_cmake_targetfile(target, installdir, "xxxTargets-release.cmake", opt) end end diff --git a/xmake/scripts/cmake_importfiles/xxxTargets.cmake b/xmake/scripts/cmake_importfiles/xxxTargets.cmake index 7ade9f919..bdf2774e9 100644 --- a/xmake/scripts/cmake_importfiles/xxxTargets.cmake +++ b/xmake/scripts/cmake_importfiles/xxxTargets.cmake @@ -1,4 +1,4 @@ -# Generated by CMake +# Generated by XMake if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.5) message(FATAL_ERROR "CMake >= 2.6.0 required") -- cgit v1.3.1 From f75a7e64e5d370e0da29ea394d9a91c4436ce3c2 Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Wed, 11 Aug 2021 20:47:15 +0800 Subject: constrain replace --- xmake/modules/target/action/install/cmake_importfiles.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/target/action/install/cmake_importfiles.lua b/xmake/modules/target/action/install/cmake_importfiles.lua index d311f19ce..1fb9ca5a6 100644 --- a/xmake/modules/target/action/install/cmake_importfiles.lua +++ b/xmake/modules/target/action/install/cmake_importfiles.lua @@ -25,7 +25,7 @@ import("core.project.project") function _get_builtinvars(target, installdir) return {TARGETNAME = target:name(), PROJECTNAME = project.name() or target:name(), - TARGETFILENAME = path.filename(target:targetfile()):replace("dll", "lib"), + TARGETFILENAME = is_plat("windows", "mingw") and path.filename(target:targetfile()):gsub(".dll$", ".lib") or path.filename(target:targetfile()), TARGETKIND = target:is_shared() and "SHARED" or "STATIC", PACKAGE_VERSION = target:get("version") or "1.0.0", TARGET_PTRBYTES = target:is_arch("x86", "i386") and "4" or "8"} -- cgit v1.3.1 From ef9e86536b0c707ea6c6b0d515f88b1dc4b3385e Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Wed, 11 Aug 2021 20:48:25 +0800 Subject: fix typo --- xmake/modules/target/action/install/cmake_importfiles.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/target/action/install/cmake_importfiles.lua b/xmake/modules/target/action/install/cmake_importfiles.lua index 1fb9ca5a6..40ff77295 100644 --- a/xmake/modules/target/action/install/cmake_importfiles.lua +++ b/xmake/modules/target/action/install/cmake_importfiles.lua @@ -25,7 +25,7 @@ import("core.project.project") function _get_builtinvars(target, installdir) return {TARGETNAME = target:name(), PROJECTNAME = project.name() or target:name(), - TARGETFILENAME = is_plat("windows", "mingw") and path.filename(target:targetfile()):gsub(".dll$", ".lib") or path.filename(target:targetfile()), + TARGETFILENAME = is_plat("windows", "mingw") and path.filename(target:targetfile()):gsub("%.dll$", ".lib") or path.filename(target:targetfile()), TARGETKIND = target:is_shared() and "SHARED" or "STATIC", PACKAGE_VERSION = target:get("version") or "1.0.0", TARGET_PTRBYTES = target:is_arch("x86", "i386") and "4" or "8"} -- cgit v1.3.1 From 9c5d90b1f884b600fbc7e9327ba34ad6328fe5c5 Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Wed, 11 Aug 2021 21:47:03 +0800 Subject: add target: prefix --- xmake/modules/target/action/install/cmake_importfiles.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/target/action/install/cmake_importfiles.lua b/xmake/modules/target/action/install/cmake_importfiles.lua index 40ff77295..35479d3c1 100644 --- a/xmake/modules/target/action/install/cmake_importfiles.lua +++ b/xmake/modules/target/action/install/cmake_importfiles.lua @@ -25,7 +25,7 @@ import("core.project.project") function _get_builtinvars(target, installdir) return {TARGETNAME = target:name(), PROJECTNAME = project.name() or target:name(), - TARGETFILENAME = is_plat("windows", "mingw") and path.filename(target:targetfile()):gsub("%.dll$", ".lib") or path.filename(target:targetfile()), + TARGETFILENAME = target:is_plat("windows", "mingw") and path.filename(target:targetfile()):gsub("%.dll$", ".lib") or path.filename(target:targetfile()), TARGETKIND = target:is_shared() and "SHARED" or "STATIC", PACKAGE_VERSION = target:get("version") or "1.0.0", TARGET_PTRBYTES = target:is_arch("x86", "i386") and "4" or "8"} -- cgit v1.3.1 From 9a29212b893502d685282660ab34646e167be1e9 Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Wed, 11 Aug 2021 22:32:08 +0800 Subject: fix libfile on mingw --- xmake/modules/target/action/install/cmake_importfiles.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/xmake/modules/target/action/install/cmake_importfiles.lua b/xmake/modules/target/action/install/cmake_importfiles.lua index 35479d3c1..0b6a8c276 100644 --- a/xmake/modules/target/action/install/cmake_importfiles.lua +++ b/xmake/modules/target/action/install/cmake_importfiles.lua @@ -23,9 +23,15 @@ import("core.project.project") -- get the builtin variables function _get_builtinvars(target, installdir) + local libfile = path.filename(target:targetfile()) + if target:is_plat("windows") then + libfile = libfile:gsub("%.dll$", ".lib") + elseif target:is_plat("mingw") then + libfile = libfile:gsub("%.dll$", ".dll.a") + end return {TARGETNAME = target:name(), PROJECTNAME = project.name() or target:name(), - TARGETFILENAME = target:is_plat("windows", "mingw") and path.filename(target:targetfile()):gsub("%.dll$", ".lib") or path.filename(target:targetfile()), + TARGETFILENAME = libfile, TARGETKIND = target:is_shared() and "SHARED" or "STATIC", PACKAGE_VERSION = target:get("version") or "1.0.0", TARGET_PTRBYTES = target:is_arch("x86", "i386") and "4" or "8"} -- cgit v1.3.1 From 3fdef81bd4c17f224065296cf71c8f18a2b35f9e Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Wed, 11 Aug 2021 23:25:27 +0800 Subject: improve libfile finding on mingw --- .../modules/target/action/install/cmake_importfiles.lua | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/xmake/modules/target/action/install/cmake_importfiles.lua b/xmake/modules/target/action/install/cmake_importfiles.lua index 0b6a8c276..e4e5d118e 100644 --- a/xmake/modules/target/action/install/cmake_importfiles.lua +++ b/xmake/modules/target/action/install/cmake_importfiles.lua @@ -21,17 +21,26 @@ -- imports import("core.project.project") --- get the builtin variables -function _get_builtinvars(target, installdir) +-- get the lib file of the target +function _get_libfile(target, installdir) local libfile = path.filename(target:targetfile()) if target:is_plat("windows") then libfile = libfile:gsub("%.dll$", ".lib") elseif target:is_plat("mingw") then - libfile = libfile:gsub("%.dll$", ".dll.a") + if os.isfile(path.join(installdir, "lib", libfile:gsub("%.dll$", ".dll.a"))) then + libfile = libfile:gsub("%.dll$", ".dll.a") + else + libfile = libfile:gsub("%.dll$", ".lib") + end end + return libfile +end + +-- get the builtin variables +function _get_builtinvars(target, installdir) return {TARGETNAME = target:name(), PROJECTNAME = project.name() or target:name(), - TARGETFILENAME = libfile, + TARGETFILENAME = _get_libfile(target, installdir), TARGETKIND = target:is_shared() and "SHARED" or "STATIC", PACKAGE_VERSION = target:get("version") or "1.0.0", TARGET_PTRBYTES = target:is_arch("x86", "i386") and "4" or "8"} -- cgit v1.3.1 From 4dfaeeb6326cbe3ffebb3355b10895b6939c53d5 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 12 Aug 2021 00:53:46 +0800 Subject: improve process.open --- core/src/xmake/process/open.c | 2 +- core/src/xmake/process/openv.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/xmake/process/open.c b/core/src/xmake/process/open.c index 82ea5b94f..c35d9e3bf 100644 --- a/core/src/xmake/process/open.c +++ b/core/src/xmake/process/open.c @@ -56,7 +56,7 @@ tb_int_t xm_process_open(lua_State* lua) // get option arguments tb_size_t envn = 0; - tb_char_t const* envs[256] = {0}; + tb_char_t const* envs[1024] = {0}; tb_char_t const* inpath = tb_null; tb_char_t const* outpath = tb_null; tb_char_t const* errpath = tb_null; diff --git a/core/src/xmake/process/openv.c b/core/src/xmake/process/openv.c index 02ccb49e7..3ec887f1e 100644 --- a/core/src/xmake/process/openv.c +++ b/core/src/xmake/process/openv.c @@ -98,7 +98,7 @@ tb_int_t xm_process_openv(lua_State* lua) // get option arguments tb_size_t envn = 0; - tb_char_t const* envs[256] = {0}; + tb_char_t const* envs[1024] = {0}; tb_char_t const* inpath = tb_null; tb_char_t const* outpath = tb_null; tb_char_t const* errpath = tb_null; -- cgit v1.3.1 From 6c7b2af719ea55060b098af973556e5ecf2dff51 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 13 Aug 2021 10:41:54 +0800 Subject: Update extract.lua --- xmake/modules/utils/archive/extract.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/utils/archive/extract.lua b/xmake/modules/utils/archive/extract.lua index 4e54bc4dc..d9299b799 100644 --- a/xmake/modules/utils/archive/extract.lua +++ b/xmake/modules/utils/archive/extract.lua @@ -417,7 +417,7 @@ function main(archivefile, outputdir, opt) -- init extractors local extractors - if is_host("windows") then + if is_subhost("windows") then -- we use 7z first, becase xmake package has builtin 7z program on windows -- tar/windows can not extract .bz2 ... extractors = -- cgit v1.3.1 From b9190cc9abfb901cad0955011268be618fa0cc6b Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 13 Aug 2021 14:29:08 +0800 Subject: Update extract.lua --- xmake/modules/utils/archive/extract.lua | 4 ---- 1 file changed, 4 deletions(-) diff --git a/xmake/modules/utils/archive/extract.lua b/xmake/modules/utils/archive/extract.lua index d9299b799..2c0b8fb8d 100644 --- a/xmake/modules/utils/archive/extract.lua +++ b/xmake/modules/utils/archive/extract.lua @@ -389,15 +389,11 @@ end -- extract archive file using extractors function _extract(archivefile, outputdir, extension, extractors, opt) - - -- extract it for _, extract in ipairs(extractors) do if extract(archivefile, outputdir, extension, opt) then return true end end - - -- failed return false end -- cgit v1.3.1 From 26c6499f97244bc6c663777b2f765bf594a290d5 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 13 Aug 2021 14:30:35 +0800 Subject: Update extract.lua --- xmake/modules/utils/archive/extract.lua | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/xmake/modules/utils/archive/extract.lua b/xmake/modules/utils/archive/extract.lua index 2c0b8fb8d..f8f348bcb 100644 --- a/xmake/modules/utils/archive/extract.lua +++ b/xmake/modules/utils/archive/extract.lua @@ -44,7 +44,7 @@ function _extract_using_tar(archivefile, outputdir, extension, opt) end -- on msys2/cygwin? we need translate input path to cygwin-like path - if is_subhost("msys", "cygwin") and program:gsub("\\", "/"):find("/usr/bin") then + if is_subhost("msys", "cygwin") then archivefile = path.cygwin_path(archivefile) end @@ -98,6 +98,12 @@ function _extract_using_7z(archivefile, outputdir, extension, opt) return false end + -- p7zip cannot extract other archive format on msys/cygwin + -- https://github.com/xmake-io/xmake/issues/1575#issuecomment-898205462 + if is_subhost("msys", "cygwin") and extension ~= ".7z" and program:startswith("sh ") then + return false + end + -- extract to *.tar file first local outputdir_old = nil if extension:startswith(".tar.") or extension == ".tgz" then @@ -389,11 +395,15 @@ end -- extract archive file using extractors function _extract(archivefile, outputdir, extension, extractors, opt) + + -- extract it for _, extract in ipairs(extractors) do if extract(archivefile, outputdir, extension, opt) then return true end end + + -- failed return false end -- cgit v1.3.1 From 69535ad5754a5f9ec30bb599b5f45688f398b43c Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 13 Aug 2021 22:26:38 +0800 Subject: Update extract.lua --- xmake/modules/utils/archive/extract.lua | 37 +++++++++++++-------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/xmake/modules/utils/archive/extract.lua b/xmake/modules/utils/archive/extract.lua index f8f348bcb..dd09df9ac 100644 --- a/xmake/modules/utils/archive/extract.lua +++ b/xmake/modules/utils/archive/extract.lua @@ -43,16 +43,23 @@ function _extract_using_tar(archivefile, outputdir, extension, opt) return false end - -- on msys2/cygwin? we need translate input path to cygwin-like path - if is_subhost("msys", "cygwin") then - archivefile = path.cygwin_path(archivefile) - end - -- init argv local argv = {} - if is_subhost("windows") then + if is_host("windows") then -- force "x:\\xx" as local file - table.insert(argv, "--force-local") + local force_local = _g.force_local + if force_local == nil then + force_local = try {function () + local result = os.iorunv(program, {"--help"}) + if result and result:find("--force-local", 1, true) then + return true + end + end} + _g.force_local = force_local or false + end + if force_local then + table.insert(argv, "--force-local") + end end table.insert(argv, option.get("verbose") and "-xvf" or "-xf") table.insert(argv, archivefile) @@ -84,8 +91,6 @@ function _extract_using_tar(archivefile, outputdir, extension, opt) else os.vrunv(program, argv) end - - -- ok return true end @@ -157,8 +162,6 @@ function _extract_using_7z(archivefile, outputdir, extension, opt) return _extract(tarfile, outputdir_old, ".tar", {_extract_using_7z, _extract_using_tar}, opt) end end - - -- ok return true end @@ -214,8 +217,6 @@ function _extract_using_gzip(archivefile, outputdir, extension, opt) return _extract(tarfile, outputdir_old, ".tar", {_extract_using_7z, _extract_using_tar}, opt) end end - - -- ok return true end @@ -271,8 +272,6 @@ function _extract_using_xz(archivefile, outputdir, extension, opt) return _extract(tarfile, outputdir_old, ".tar", {_extract_using_7z, _extract_using_tar}, opt) end end - - -- ok return true end @@ -326,8 +325,6 @@ function _extract_using_unzip(archivefile, outputdir, extension, opt) return _extract(tarfile, outputdir_old, ".tar", {_extract_using_tar, _extract_using_7z}, opt) end end - - -- ok return true end @@ -388,22 +385,16 @@ function _extract_using_bzip2(archivefile, outputdir, extension, opt) return _extract(tarfile, outputdir_old, ".tar", {_extract_using_7z, _extract_using_tar}, opt) end end - - -- ok return true end -- extract archive file using extractors function _extract(archivefile, outputdir, extension, extractors, opt) - - -- extract it for _, extract in ipairs(extractors) do if extract(archivefile, outputdir, extension, opt) then return true end end - - -- failed return false end -- cgit v1.3.1 From bc20947704e91af4598d140166dfe9693df5be50 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 14 Aug 2021 00:51:04 +0800 Subject: add gtk+3 example for vala --- tests/projects/vala/gtk+3/src/main.vala | 24 ++++++++++++++++++++++++ tests/projects/vala/gtk+3/xmake.lua | 10 ++++++++++ 2 files changed, 34 insertions(+) create mode 100644 tests/projects/vala/gtk+3/src/main.vala create mode 100644 tests/projects/vala/gtk+3/xmake.lua diff --git a/tests/projects/vala/gtk+3/src/main.vala b/tests/projects/vala/gtk+3/src/main.vala new file mode 100644 index 000000000..7f253a9fe --- /dev/null +++ b/tests/projects/vala/gtk+3/src/main.vala @@ -0,0 +1,24 @@ +using Gtk; + +int main (string[] args) { + Gtk.init (ref args); + + var window = new Window (); + window.title = "First GTK+ Program"; + window.border_width = 10; + window.window_position = WindowPosition.CENTER; + window.set_default_size (350, 70); + window.destroy.connect (Gtk.main_quit); + + var button = new Button.with_label ("Click me!"); + button.clicked.connect (() => { + button.label = "Thank you"; + }); + + window.add (button); + window.show_all (); + + Gtk.main (); + return 0; +} + diff --git a/tests/projects/vala/gtk+3/xmake.lua b/tests/projects/vala/gtk+3/xmake.lua new file mode 100644 index 000000000..5e9f2b8da --- /dev/null +++ b/tests/projects/vala/gtk+3/xmake.lua @@ -0,0 +1,10 @@ +add_rules("mode.release", "mode.debug") + +add_requires("gtk+3", "glib") + +target("test") + set_kind("binary") + add_rules("vala") + add_files("src/*.vala") + add_packages("gtk+3", "glib") + add_values("vala.packages", "gtk+-3.0") -- cgit v1.3.1 From ca8ccb9f1969491c5824adb640841d6ece29c3ed Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 14 Aug 2021 00:53:49 +0800 Subject: add sqlite3 vala example --- tests/projects/vala/sqlite3/src/main.vala | 63 +++++++++++++++++++++++++++++++ tests/projects/vala/sqlite3/xmake.lua | 10 +++++ 2 files changed, 73 insertions(+) create mode 100644 tests/projects/vala/sqlite3/src/main.vala create mode 100644 tests/projects/vala/sqlite3/xmake.lua diff --git a/tests/projects/vala/sqlite3/src/main.vala b/tests/projects/vala/sqlite3/src/main.vala new file mode 100644 index 000000000..536e0d5e0 --- /dev/null +++ b/tests/projects/vala/sqlite3/src/main.vala @@ -0,0 +1,63 @@ +/** + * Using SQLite in Vala Sample Code + * Port of an example found on the SQLite site. + * http://www.sqlite.org/quickstart.html + */ + +using GLib; +using Sqlite; + +public class SqliteSample : GLib.Object { + + public static int callback (int n_columns, string[] values, + string[] column_names) + { + for (int i = 0; i < n_columns; i++) { + stdout.printf ("%s = %s\n", column_names[i], values[i]); + } + stdout.printf ("\n"); + + return 0; + } + + public static int main (string[] args) { + Database db; + int rc; + + if (args.length != 3) { + stderr.printf ("Usage: %s DATABASE SQL-STATEMENT\n", args[0]); + return 1; + } + + if (!FileUtils.test (args[1], FileTest.IS_REGULAR)) { + stderr.printf ("Database %s does not exist or is directory\n", args[1]); + return 1; + } + + rc = Database.open (args[1], out db); + + if (rc != Sqlite.OK) { + stderr.printf ("Can't open database: %d, %s\n", rc, db.errmsg ()); + return 1; + } + + rc = db.exec (args[2], callback, null); + /* maybe it is better to use closures, so you can access local variables, eg: */ + /*rc = db.exec(args[2], (n_columns, values, column_names) => { + for (int i = 0; i < n_columns; i++) { + stdout.printf ("%s = %s\n", column_names[i], values[i]); + } + stdout.printf ("\n"); + + return 0; + }, null); + */ + + if (rc != Sqlite.OK) { + stderr.printf ("SQL error: %d, %s\n", rc, db.errmsg ()); + return 1; + } + + return 0; + } +} diff --git a/tests/projects/vala/sqlite3/xmake.lua b/tests/projects/vala/sqlite3/xmake.lua new file mode 100644 index 000000000..f1e21e8ce --- /dev/null +++ b/tests/projects/vala/sqlite3/xmake.lua @@ -0,0 +1,10 @@ +add_rules("mode.release", "mode.debug") + +add_requires("sqlite3", "glib") + +target("test") + set_kind("binary") + add_rules("vala") + add_files("src/*.vala") + add_packages("sqlite3", "glib") + add_values("vala.packages", "sqlite3") -- cgit v1.3.1 From a551d0688b9fd671c51f04224446fbbcefa9bc1d Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 14 Aug 2021 00:56:14 +0800 Subject: improve test --- tests/projects/vala/sqlite3/xmake.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/projects/vala/sqlite3/xmake.lua b/tests/projects/vala/sqlite3/xmake.lua index f1e21e8ce..a921a8965 100644 --- a/tests/projects/vala/sqlite3/xmake.lua +++ b/tests/projects/vala/sqlite3/xmake.lua @@ -1,6 +1,7 @@ add_rules("mode.release", "mode.debug") -add_requires("sqlite3", "glib") +add_requires("sqlite3") +add_requires("glib", {system = false}) -- TODO we need improve glib package/on_fetch target("test") set_kind("binary") -- cgit v1.3.1 From b950a171ca39e649385d7ab1f96bb0c28948fa78 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 14 Aug 2021 00:56:48 +0800 Subject: improve vala --- tests/projects/vala/sqlite3/xmake.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/projects/vala/sqlite3/xmake.lua b/tests/projects/vala/sqlite3/xmake.lua index a921a8965..f1e21e8ce 100644 --- a/tests/projects/vala/sqlite3/xmake.lua +++ b/tests/projects/vala/sqlite3/xmake.lua @@ -1,7 +1,6 @@ add_rules("mode.release", "mode.debug") -add_requires("sqlite3") -add_requires("glib", {system = false}) -- TODO we need improve glib package/on_fetch +add_requires("sqlite3", "glib") target("test") set_kind("binary") -- cgit v1.3.1 From c5f2a58cf57ad72d4e2bc39a6dc196550804d013 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 14 Aug 2021 00:08:37 +0800 Subject: concat package --- xmake/modules/lib/detect/find_package.lua | 37 +++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/xmake/modules/lib/detect/find_package.lua b/xmake/modules/lib/detect/find_package.lua index 7b7ba7032..b38e55e39 100644 --- a/xmake/modules/lib/detect/find_package.lua +++ b/xmake/modules/lib/detect/find_package.lua @@ -24,6 +24,38 @@ import("core.project.config") import("core.cache.detectcache") import("package.manager.find_package") +-- concat packages +function _concat_packages(a, b) + local result = table.copy(a) + for k, v in pairs(b) do + local o = result[k] + if o ~= nil then + v = table.join(o, v) + end + result[k] = v + end + for k, v in pairs(result) do + if k == "links" then + if type(v) == "table" and #v > 1 then + -- we need ensure link orders when removing repeat values + local v2 = {} + local map = {} + for _, _v in irpairs(v) do + if not map[_v] then + table.insert(v2, 1, _v) + map[_v] = true + end + end + v = v2 + end + else + v = table.unique(v) + end + result[k] = v + end + return result +end + -- find package using the package manager -- -- @param name the package name @@ -113,5 +145,10 @@ function main(name, opt) if not opt.version and result then result.version = nil end + + -- register concat + if result and type(result) == "table" then + debug.setmetatable(result, {__concat = _concat_packages}) + end return result and result or nil end -- cgit v1.3.1 From 07987f21cfa52d66080df8a2a4af5f86e608ab8e Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 14 Aug 2021 00:22:26 +0800 Subject: add table.reverse_unique --- xmake/core/base/table.lua | 29 +++++++++++++++++++++++++---- xmake/modules/lib/detect/find_package.lua | 10 +--------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua index edd0f42fb..c86a90988 100644 --- a/xmake/core/base/table.lua +++ b/xmake/core/base/table.lua @@ -240,21 +240,17 @@ end -- remove repeat from the given array function table.unique(array, barrier) - if table.is_array(array) then if table.getn(array) ~= 1 then local exists = {} local unique = {} for _, v in ipairs(array) do - -- exists barrier? clear the current existed items if barrier and barrier(v) then exists = {} end - -- add unique item if not exists[v] then - -- v will not be nil exists[v] = true table.insert(unique, v) end @@ -265,6 +261,31 @@ function table.unique(array, barrier) return array end +-- reverse to remove repeat from the given array +function table.reverse_unique(array, barrier) + if table.is_array(array) then + if table.getn(array) ~= 1 then + local exists = {} + local unique = {} + local n = #array + for i = 1, n do + local v = array[n - i + 1] + -- exists barrier? clear the current existed items + if barrier and barrier(v) then + exists = {} + end + -- add unique item + if not exists[v] then + exists[v] = true + table.insert(unique, 1, v) + end + end + array = unique + end + end + return array +end + -- pack arguments into a table -- polyfill of lua 5.2, @see https://www.lua.org/manual/5.2/manual.html#pdf-table.pack function table.pack(...) diff --git a/xmake/modules/lib/detect/find_package.lua b/xmake/modules/lib/detect/find_package.lua index b38e55e39..d3c9e57d1 100644 --- a/xmake/modules/lib/detect/find_package.lua +++ b/xmake/modules/lib/detect/find_package.lua @@ -38,15 +38,7 @@ function _concat_packages(a, b) if k == "links" then if type(v) == "table" and #v > 1 then -- we need ensure link orders when removing repeat values - local v2 = {} - local map = {} - for _, _v in irpairs(v) do - if not map[_v] then - table.insert(v2, 1, _v) - map[_v] = true - end - end - v = v2 + v = table.reverse_unique(v) end else v = table.unique(v) -- cgit v1.3.1 From 246711d74ea45b554456fdb6ac44a83f5424824a Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 14 Aug 2021 13:29:49 +0800 Subject: fix check option deps --- xmake/core/sandbox/modules/import/core/project/project.lua | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/xmake/core/sandbox/modules/import/core/project/project.lua b/xmake/core/sandbox/modules/import/core/project/project.lua index 8e50dfb24..694532527 100644 --- a/xmake/core/sandbox/modules/import/core/project/project.lua +++ b/xmake/core/sandbox/modules/import/core/project/project.lua @@ -90,19 +90,15 @@ function sandbox_core_project.check() -- init check task local checked = {} local checktask = function (index) - - -- get option local opt = options[index] if opt then - -- check deps of this option first - for depname, dep in pairs(opt:deps()) do - if not checked[depname] then + for _, dep in ipairs(opt:orderdeps()) do + if not checked[dep:name()] then dep:check() - checked[depname] = true + checked[dep:name()] = true end end - -- check this option if not checked[opt:name()] then opt:check() -- cgit v1.3.1 From 309b9ca8f38df147940a37e1698ae662bd4346b3 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 14 Aug 2021 14:03:09 +0800 Subject: add package.requires_lock policy --- xmake/core/project/policy.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xmake/core/project/policy.lua b/xmake/core/project/policy.lua index 7040182a2..c624aed96 100644 --- a/xmake/core/project/policy.lua +++ b/xmake/core/project/policy.lua @@ -44,7 +44,9 @@ function policy.policies() -- we can compile the source files for each target in parallel ["build.across_targets_in_parallel"] = {description = "Enable compile the source files for each target in parallel.", default = true, type = "boolean"}, -- we need enable longpaths when building target or installing package - ["platform.longpaths"] = {description = "Enable long paths when building target or installing package on windows.", default = false, type = "boolean"} + ["platform.longpaths"] = {description = "Enable long paths when building target or installing package on windows.", default = false, type = "boolean"}, + -- lock required packages + ["package.requires_lock"] = {description = "Enable xmake-requires.lock to lock required packages.", default = false, type = "boolean"} } policy._POLICIES = policies end -- cgit v1.3.1 From 0795b09c48d770af91138edc417089830c1d4850 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 14 Aug 2021 14:07:09 +0800 Subject: add project lockfile --- xmake/core/project/project.lua | 5 +++++ xmake/core/sandbox/modules/import/core/project/project.lua | 1 + 2 files changed, 6 insertions(+) diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index fafc254bf..138e847ba 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -1023,6 +1023,11 @@ function project.requireconfs_str() return requireconfs_str, requireconfs_extra end +-- get requires lockfile +function project.requires_lockfile() + return path.join(project.directory(), "xmake-requires.lock") +end + -- get the given rule function project.rule(name) return project.rules()[name] diff --git a/xmake/core/sandbox/modules/import/core/project/project.lua b/xmake/core/sandbox/modules/import/core/project/project.lua index 694532527..1becb07a9 100644 --- a/xmake/core/sandbox/modules/import/core/project/project.lua +++ b/xmake/core/sandbox/modules/import/core/project/project.lua @@ -63,6 +63,7 @@ sandbox_core_project.required_package = project.required_package sandbox_core_project.required_packages = project.required_packages sandbox_core_project.requires_str = project.requires_str sandbox_core_project.requireconfs_str = project.requireconfs_str +sandbox_core_project.requires_lockfile = project.requires_lockfile sandbox_core_project.policy = project.policy sandbox_core_project.tmpdir = project.tmpdir sandbox_core_project.tmpfile = project.tmpfile -- cgit v1.3.1 From f79a870188275a9fff71dd9ae7a5d2a6759c602a Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 14 Aug 2021 17:24:35 +0800 Subject: Update .appveyor.yml --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 884c8c5f3..0316f0178 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,6 +1,6 @@ #version: v2.1.8.{build} image: - - Visual Studio 2013 + - Visual Studio 2015 - Visual Studio 2017 platform: -- cgit v1.3.1 From a19fc6d6da6627b5bdab702931ab6278e8cf8409 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 14 Aug 2021 23:45:05 +0800 Subject: sort table.keys --- .../package/multiconfig/xmake-requires.lock | 5 +++ tests/projects/package/multiconfig/xmake.lua | 1 + xmake/core/base/serialize.lua | 3 +- xmake/core/base/table.lua | 15 ++++++++ xmake/core/project/project.lua | 2 +- .../modules/import/core/project/project.lua | 2 +- .../action/require/impl/install_packages.lua | 4 +++ .../private/action/require/impl/lock_packages.lua | 40 ++++++++++++++++++++++ 8 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 tests/projects/package/multiconfig/xmake-requires.lock create mode 100644 xmake/modules/private/action/require/impl/lock_packages.lua diff --git a/tests/projects/package/multiconfig/xmake-requires.lock b/tests/projects/package/multiconfig/xmake-requires.lock new file mode 100644 index 000000000..5752aa15a --- /dev/null +++ b/tests/projects/package/multiconfig/xmake-requires.lock @@ -0,0 +1,5 @@ +{ + zlib = { + buildhash = "8e5b898b0f344715bac89cc6a1577506" + } +} \ No newline at end of file diff --git a/tests/projects/package/multiconfig/xmake.lua b/tests/projects/package/multiconfig/xmake.lua index 09121e8d2..7aa2bdffb 100644 --- a/tests/projects/package/multiconfig/xmake.lua +++ b/tests/projects/package/multiconfig/xmake.lua @@ -2,6 +2,7 @@ add_requires("zlib", {system = false}) add_requires("zlib", {system = false}) -- test repeat requires add_requires("zlib~debug", {system = false, debug = true}) add_requires("zlib~shared", {system = false, configs = {shared = true}, alias = "zlib_shared"}) +set_policy("package.requires_lock", true) target("test1") set_kind("binary") diff --git a/xmake/core/base/serialize.lua b/xmake/core/base/serialize.lua index 99486bf8c..a2d7b9ff9 100644 --- a/xmake/core/base/serialize.lua +++ b/xmake/core/base/serialize.lua @@ -123,7 +123,8 @@ function serialize._maketable(obj, opt, level, pathsegs, reftab) local sformat = opt.indentstr and "[%q] = %s" or "[%q]=%s" local nformat = opt.indentstr and "[%s] = %s" or "[%s]=%s" local keywords = serialize._keywords() - for k, v in pairs(serialized) do + local makepairs = opt.orderkeys and table.orderpairs or pairs + for k, v in makepairs(serialized) do local format -- serialize key if type(k) == "string" then diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua index c86a90988..01a6a4692 100644 --- a/xmake/core/base/table.lua +++ b/xmake/core/base/table.lua @@ -317,6 +317,21 @@ function table.orderkeys(tab) return keys end +-- order key/value iterator +-- +-- for k, v in table.orderpairs(t) do +-- TODO +-- end +function table.orderpairs(t) + local orderkeys = table.orderkeys(t) + local i = 1 + return function (t, k) + k = orderkeys[i] + i = i + 1 + return k, t[k] + end, t, nil +end + -- get values of a table function table.values(tab) diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 138e847ba..e2d7f996a 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -1024,7 +1024,7 @@ function project.requireconfs_str() end -- get requires lockfile -function project.requires_lockfile() +function project.requireslock() return path.join(project.directory(), "xmake-requires.lock") end diff --git a/xmake/core/sandbox/modules/import/core/project/project.lua b/xmake/core/sandbox/modules/import/core/project/project.lua index 1becb07a9..696bd0d91 100644 --- a/xmake/core/sandbox/modules/import/core/project/project.lua +++ b/xmake/core/sandbox/modules/import/core/project/project.lua @@ -63,7 +63,7 @@ sandbox_core_project.required_package = project.required_package sandbox_core_project.required_packages = project.required_packages sandbox_core_project.requires_str = project.requires_str sandbox_core_project.requireconfs_str = project.requireconfs_str -sandbox_core_project.requires_lockfile = project.requires_lockfile +sandbox_core_project.requireslock = project.requireslock sandbox_core_project.policy = project.policy sandbox_core_project.tmpdir = project.tmpdir sandbox_core_project.tmpfile = project.tmpfile diff --git a/xmake/modules/private/action/require/impl/install_packages.lua b/xmake/modules/private/action/require/impl/install_packages.lua index 7e83ae939..79fb71c3f 100644 --- a/xmake/modules/private/action/require/impl/install_packages.lua +++ b/xmake/modules/private/action/require/impl/install_packages.lua @@ -30,6 +30,7 @@ import("actions.install", {alias = "action_install"}) import("actions.download", {alias = "action_download"}) import("net.fasturl") import("private.action.require.impl.package") +import("private.action.require.impl.lock_packages") import("private.action.require.impl.register_packages") -- sort packages urls @@ -600,6 +601,9 @@ function main(requires, opt) -- re-register and refresh all root packages to local cache, -- because there may be some missing optional dependencies reinstalled register_packages(packages) + + -- lock packages + lock_packages(packages) return packages end diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua new file mode 100644 index 000000000..fffb76dfa --- /dev/null +++ b/xmake/modules/private/action/require/impl/lock_packages.lua @@ -0,0 +1,40 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file lock_packages.lua +-- + +-- imports +import("core.project.project") + +-- lock package +function _lock_package(instance) + local result = {} + result.buildhash = instance:buildhash() + return result +end + +-- lock all required packages +function main(packages) + local results = {} + for _, instance in ipairs(packages) do + results[instance:name()] = _lock_package(instance) + end + table.sort(results, function (a, b) return a.name < b.name end) + io.writefile(project.requireslock(), string.serialize(results, {orderkeys = true})) +end + -- cgit v1.3.1 From 28c02f2323aaa4595b8474c6a01e6ffc28181396 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 15 Aug 2021 00:05:55 +0800 Subject: update lock info --- .../package/multiconfig/xmake-requires.lock | 14 +++- .../package/toolchain_muslcc/xmake-requires.lock | 93 ++++++++++++++++++++++ tests/projects/package/toolchain_muslcc/xmake.lua | 3 + .../private/action/require/impl/lock_packages.lua | 8 +- 4 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 tests/projects/package/toolchain_muslcc/xmake-requires.lock diff --git a/tests/projects/package/multiconfig/xmake-requires.lock b/tests/projects/package/multiconfig/xmake-requires.lock index 5752aa15a..c5031a33c 100644 --- a/tests/projects/package/multiconfig/xmake-requires.lock +++ b/tests/projects/package/multiconfig/xmake-requires.lock @@ -1,5 +1,17 @@ { zlib = { - buildhash = "8e5b898b0f344715bac89cc6a1577506" + buildhash = "b76a297309d14c09b42cfe3927260a51", + name = "zlib", + version = "1.2.11" + }, + ["zlib~debug"] = { + buildhash = "e6a6fa6a86ad4fc7ae3c2cf7c60cc084", + name = "zlib", + version = "1.2.11" + }, + ["zlib~shared"] = { + buildhash = "8e5b898b0f344715bac89cc6a1577506", + name = "zlib", + version = "1.2.11" } } \ No newline at end of file diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock new file mode 100644 index 000000000..8fa6e9982 --- /dev/null +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -0,0 +1,93 @@ +{ + autoconf = { + arch = "x86_64", + buildhash = "01974c48f52d4d658f58852351743754", + kind = "binary", + name = "autoconf", + plat = "macosx", + version = "2.69" + }, + automake = { + arch = "x86_64", + buildhash = "7a090c93706241f983f0d821a162e8a5", + kind = "binary", + name = "automake", + plat = "macosx", + version = "1.16.1" + }, + cmake = { + arch = "x86_64", + buildhash = "a6d18f8c0bf347d980f8bb762583c91a", + kind = "binary", + name = "cmake", + plat = "macosx", + version = "3.21.0" + }, + gmp = { + arch = "x86_64", + buildhash = "7dd9c224447e46698ac73d29f58b1d73", + name = "gmp", + plat = "macosx", + version = "6.2.1" + }, + libisl = { + arch = "x86_64", + buildhash = "f649e1fb365e442e8f79f372fd91483b", + name = "libisl", + plat = "macosx", + version = "0.22" + }, + libogg = { + arch = "arm", + buildhash = "d894fc29f2fb4c45a0f48bc2c6ece273", + name = "libogg", + plat = "cross", + version = "v1.3.4" + }, + libplist = { + arch = "arm", + buildhash = "0c01b22920be4876b1de74629194eb8f", + name = "libplist", + plat = "cross", + version = "2.2.0" + }, + libtool = { + arch = "x86_64", + buildhash = "64584ec84a4743ecb740b598b263ffa6", + kind = "binary", + name = "libtool", + plat = "macosx", + version = "2.4.6" + }, + m4 = { + arch = "x86_64", + buildhash = "fd0e83e5759b442a970327ebb1c89793", + kind = "binary", + name = "m4", + plat = "macosx", + version = "1.4.19" + }, + muslcc = { + arch = "x86_64", + buildhash = "11062c09ebeb484594488ad73ddbcd1f", + kind = "toolchain", + name = "muslcc", + plat = "macosx", + version = "20210202" + }, + ["pkg-config"] = { + arch = "x86_64", + buildhash = "84fd7f9b9f7a47709512cfc85cd9e5f7", + kind = "binary", + name = "pkg-config", + plat = "macosx", + version = "0.29.2" + }, + zlib = { + arch = "arm", + buildhash = "be90a245b8bb48e6b08a1a15bdcad467", + name = "zlib", + plat = "cross", + version = "1.2.11" + } +} \ No newline at end of file diff --git a/tests/projects/package/toolchain_muslcc/xmake.lua b/tests/projects/package/toolchain_muslcc/xmake.lua index bf5e98e8c..b111d5976 100644 --- a/tests/projects/package/toolchain_muslcc/xmake.lua +++ b/tests/projects/package/toolchain_muslcc/xmake.lua @@ -4,6 +4,9 @@ add_rules("mode.debug", "mode.release") set_plat("cross") set_arch("arm") +-- lock requires +set_policy("package.requires_lock", true) + -- add library packages -- for testing zlib/xmake, libplist/autoconf, libogg/cmake add_requires("zlib", "libogg", {system = false}) diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua index fffb76dfa..8d1e0ebdd 100644 --- a/xmake/modules/private/action/require/impl/lock_packages.lua +++ b/xmake/modules/private/action/require/impl/lock_packages.lua @@ -24,7 +24,12 @@ import("core.project.project") -- lock package function _lock_package(instance) local result = {} + result.name = instance:name() + result.plat = instance:plat() + result.arch = instance:arch() + result.kind = instance:kind() result.buildhash = instance:buildhash() + result.version = instance:version_str() return result end @@ -32,9 +37,8 @@ end function main(packages) local results = {} for _, instance in ipairs(packages) do - results[instance:name()] = _lock_package(instance) + results[instance:displayname()] = _lock_package(instance) end - table.sort(results, function (a, b) return a.name < b.name end) io.writefile(project.requireslock(), string.serialize(results, {orderkeys = true})) end -- cgit v1.3.1 From dd717cd8219f0774ecb717f44d6ba3f182f29c99 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 15 Aug 2021 23:38:15 +0800 Subject: improve xmake-requires.lock --- .../package/multiconfig/xmake-requires.lock | 42 ++++- .../package/toolchain_muslcc/xmake-requires.lock | 185 +++++++++++++++++++-- xmake/modules/devel/git/lastcommit.lua | 77 +++++++++ .../private/action/require/impl/lock_packages.lua | 54 +++++- .../private/action/require/impl/package.lua | 25 +-- .../action/require/impl/utils/requirekey.lua | 50 ++++++ 6 files changed, 390 insertions(+), 43 deletions(-) create mode 100644 xmake/modules/devel/git/lastcommit.lua create mode 100644 xmake/modules/private/action/require/impl/utils/requirekey.lua diff --git a/tests/projects/package/multiconfig/xmake-requires.lock b/tests/projects/package/multiconfig/xmake-requires.lock index c5031a33c..78e911112 100644 --- a/tests/projects/package/multiconfig/xmake-requires.lock +++ b/tests/projects/package/multiconfig/xmake-requires.lock @@ -1,17 +1,53 @@ { - zlib = { + ["zlib#fd74da7781d54dddb234cfb6eae7be34"] = { + arch = "x86_64", buildhash = "b76a297309d14c09b42cfe3927260a51", + configs = { + debug = false, + pic = true, + shared = false + }, + is_built = true, name = "zlib", + plat = "macosx", + repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + urls = { + "https://github.com/madler/zlib/archive/v1.2.11.tar.gz#629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff" + }, version = "1.2.11" }, - ["zlib~debug"] = { + ["zlib~debug#29572d10f2b44d76ad238aa6d9d886f0"] = { + arch = "x86_64", buildhash = "e6a6fa6a86ad4fc7ae3c2cf7c60cc084", + configs = { + debug = true, + pic = true, + shared = false + }, + is_built = true, name = "zlib", + plat = "macosx", + repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + urls = { + "https://github.com/madler/zlib/archive/v1.2.11.tar.gz#629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff" + }, version = "1.2.11" }, - ["zlib~shared"] = { + ["zlib~shared#0aa7e77905524be8bf354384c68bdde7"] = { + arch = "x86_64", buildhash = "8e5b898b0f344715bac89cc6a1577506", + configs = { + debug = false, + pic = true, + shared = true + }, + is_built = true, name = "zlib", + plat = "macosx", + repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + urls = { + "https://github.com/madler/zlib/archive/v1.2.11.tar.gz#629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff" + }, version = "1.2.11" } } \ No newline at end of file diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock index 8fa6e9982..779c320ff 100644 --- a/tests/projects/package/toolchain_muslcc/xmake-requires.lock +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -1,93 +1,254 @@ { - autoconf = { + ["autoconf#fd74da7781d54dddb234cfb6eae7be34"] = { arch = "x86_64", buildhash = "01974c48f52d4d658f58852351743754", + configs = { + debug = false, + pic = true, + shared = false + }, + deps = { + "m4#fd74da7781d54dddb234cfb6eae7be34" + }, + is_built = true, kind = "binary", name = "autoconf", plat = "macosx", + repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + urls = { + "http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz#954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969", + "https://mirrors.ustc.edu.cn/gnu/autoconf/autoconf-2.69.tar.gz#954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969", + "git://git.sv.gnu.org/autoconf#2.69" + }, version = "2.69" }, - automake = { + ["automake#fd74da7781d54dddb234cfb6eae7be34"] = { arch = "x86_64", buildhash = "7a090c93706241f983f0d821a162e8a5", + configs = { + debug = false, + pic = true, + shared = false + }, + deps = { + "autoconf#fd74da7781d54dddb234cfb6eae7be34" + }, + is_built = true, kind = "binary", name = "automake", plat = "macosx", + repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + urls = { + "http://ftp.gnu.org/gnu/automake/automake-1.16.1.tar.gz#608a97523f97db32f1f5d5615c98ca69326ced2054c9f82e65bade7fc4c9dea8", + "https://mirrors.ustc.edu.cn/gnu/automake/automake-1.16.1.tar.gz#608a97523f97db32f1f5d5615c98ca69326ced2054c9f82e65bade7fc4c9dea8" + }, version = "1.16.1" }, - cmake = { + ["cmake#fd74da7781d54dddb234cfb6eae7be34"] = { arch = "x86_64", buildhash = "a6d18f8c0bf347d980f8bb762583c91a", + configs = { + debug = false, + pic = true, + shared = false + }, + is_built = true, kind = "binary", name = "cmake", plat = "macosx", + repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + urls = { + "https://cmake.org/files/v3.21/cmake-3.21.0-macos-universal-Darwin-x86_64.tar.gz#c1c6f19dfc9c658a48b5aed22806595b2337bb3aedb71ab826552f74f568719f", + "https://github.com/Kitware/CMake/releases/download/v3.21.0/cmake-3.21.0-macos-universal.tar.gz#c1c6f19dfc9c658a48b5aed22806595b2337bb3aedb71ab826552f74f568719f" + }, version = "3.21.0" }, - gmp = { + ["gmp#fd74da7781d54dddb234cfb6eae7be34"] = { arch = "x86_64", buildhash = "7dd9c224447e46698ac73d29f58b1d73", + configs = { + debug = false, + pic = true, + shared = false + }, + deps = { + "autoconf#fd74da7781d54dddb234cfb6eae7be34" + }, + is_built = true, name = "gmp", plat = "macosx", + repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + urls = { + "https://gmplib.org/download/gmp/gmp-6.2.1.tar.xz#fd4829912cddd12f84181c3451cc752be224643e87fac497b69edddadc49b4f2" + }, version = "6.2.1" }, - libisl = { + ["libisl 0.22#11f62b7b062648cebf81bd6623721f7d"] = { arch = "x86_64", buildhash = "f649e1fb365e442e8f79f372fd91483b", + configs = { + debug = false, + pic = true, + shared = true + }, + deps = { + "autoconf#fd74da7781d54dddb234cfb6eae7be34", + "gmp#fd74da7781d54dddb234cfb6eae7be34" + }, + is_built = true, name = "libisl", plat = "macosx", + repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + urls = { + "http://isl.gforge.inria.fr/isl-0.22.tar.xz#6c8bc56c477affecba9c59e2c9f026967ac8bad01b51bdd07916db40a517b9fa" + }, version = "0.22" }, - libogg = { + ["libogg#265260a3b33e47f189d65373131d1f08"] = { arch = "arm", buildhash = "d894fc29f2fb4c45a0f48bc2c6ece273", + configs = { + debug = false, + pic = true, + shared = false, + toolchains = "@muslcc" + }, + deps = { + "cmake#fd74da7781d54dddb234cfb6eae7be34" + }, + is_built = true, name = "libogg", plat = "cross", + repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + urls = { + "https://gitlab.xiph.org/xiph/ogg/-/archive/v1.3.4/ogg-v1.3.4.tar.gz#62cc64b9fd3cf57bde3a9033e94534ba34313d2bb9698029f623121a4e47bb9b", + "https://gitlab.xiph.org/xiph/ogg.git#v1.3.4" + }, version = "v1.3.4" }, - libplist = { + ["libplist#265260a3b33e47f189d65373131d1f08"] = { arch = "arm", buildhash = "0c01b22920be4876b1de74629194eb8f", + configs = { + debug = false, + pic = true, + shared = false, + toolchains = "@muslcc" + }, + deps = { + "autoconf#fd74da7781d54dddb234cfb6eae7be34", + "automake#fd74da7781d54dddb234cfb6eae7be34", + "libtool#fd74da7781d54dddb234cfb6eae7be34", + "pkg-config#fd74da7781d54dddb234cfb6eae7be34" + }, + is_built = true, name = "libplist", plat = "cross", + repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + urls = { + "https://github.com/libimobiledevice/libplist/archive/2.2.0.tar.gz#7e654bdd5d8b96f03240227ed09057377f06ebad08e1c37d0cfa2abe6ba0cee2", + "https://github.com/libimobiledevice/libplist.git#2.2.0" + }, version = "2.2.0" }, - libtool = { + ["libtool#fd74da7781d54dddb234cfb6eae7be34"] = { arch = "x86_64", buildhash = "64584ec84a4743ecb740b598b263ffa6", + configs = { + debug = false, + pic = true, + shared = false + }, + deps = { + "autoconf#fd74da7781d54dddb234cfb6eae7be34" + }, + is_built = true, kind = "binary", name = "libtool", plat = "macosx", + repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + urls = { + "http://ftpmirror.gnu.org/libtool/libtool-2.4.6.tar.gz#e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3", + "https://mirrors.ustc.edu.cn/gnu/libtool/libtool-2.4.6.tar.gz#e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3", + "git://git.savannah.gnu.org/libtool.git#2.4.6" + }, version = "2.4.6" }, - m4 = { + ["m4#fd74da7781d54dddb234cfb6eae7be34"] = { arch = "x86_64", buildhash = "fd0e83e5759b442a970327ebb1c89793", + configs = { + debug = false, + pic = true, + shared = false + }, + is_built = true, kind = "binary", name = "m4", plat = "macosx", + repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + urls = { + "https://ftp.gnu.org/gnu/m4/m4-1.4.19.tar.xz#63aede5c6d33b6d9b13511cd0be2cac046f2e70fd0a07aa9573a04a82783af96", + "https://ftpmirror.gnu.org/m4/m4-1.4.19.tar.xz#63aede5c6d33b6d9b13511cd0be2cac046f2e70fd0a07aa9573a04a82783af96" + }, version = "1.4.19" }, - muslcc = { + ["muslcc#fd74da7781d54dddb234cfb6eae7be34"] = { arch = "x86_64", buildhash = "11062c09ebeb484594488ad73ddbcd1f", + configs = { + debug = false, + pic = true, + shared = false + }, + deps = { + "libisl 0.22#11f62b7b062648cebf81bd6623721f7d" + }, + is_built = true, kind = "toolchain", name = "muslcc", plat = "macosx", + repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + urls = { + "https://github.com/xmake-mirror/musl.cc/releases/download/20210202/arm-linux-musleabi-cross.mac.tgz#a177df3f847181c0c7f2b34b9bd7725b4c556c11a347aa0ae36e09ebf23fb480" + }, version = "20210202" }, - ["pkg-config"] = { + ["pkg-config#fd74da7781d54dddb234cfb6eae7be34"] = { arch = "x86_64", buildhash = "84fd7f9b9f7a47709512cfc85cd9e5f7", + configs = { + debug = false, + pic = true, + shared = false + }, + is_built = true, kind = "binary", name = "pkg-config", plat = "macosx", + repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + urls = { + "https://pkgconfig.freedesktop.org/releases/pkg-config-0.29.2.tar.gz#6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591", + "http://fco.it.distfiles.macports.org/mirrors/macports-distfiles/pkgconfig/pkg-config-0.29.2.tar.gz#6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591" + }, version = "0.29.2" }, - zlib = { + ["zlib#265260a3b33e47f189d65373131d1f08"] = { arch = "arm", buildhash = "be90a245b8bb48e6b08a1a15bdcad467", + configs = { + debug = false, + pic = true, + shared = false, + toolchains = "@muslcc" + }, + is_built = true, name = "zlib", plat = "cross", + repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + urls = { + "https://github.com/madler/zlib/archive/v1.2.11.tar.gz#629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff" + }, version = "1.2.11" } } \ No newline at end of file diff --git a/xmake/modules/devel/git/lastcommit.lua b/xmake/modules/devel/git/lastcommit.lua new file mode 100644 index 000000000..876812f86 --- /dev/null +++ b/xmake/modules/devel/git/lastcommit.lua @@ -0,0 +1,77 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file lastcommit.lua +-- + +-- imports +import("core.base.option") +import("lib.detect.find_tool") +import("net.proxy") + +-- get last commit in git repository +-- +-- @param opt the options, e.g. {repodir = ..} +-- +-- @return the last commit +-- +-- @code +-- +-- import("devel.git") +-- +-- local lastcommit = git.lastcommit({repodir = ..}) +-- +-- @endcode +-- +function main(opt) + + -- find git + local git = assert(find_tool("git"), "git not found!") + + -- init arguments + local argv = {"rev-parse", "HEAD"} + + -- trace + if option.get("verbose") then + print("%s %s", git.program, os.args(argv)) + end + + -- use proxy? + local envs + local proxy_conf = proxy.config(url) + if proxy_conf then + envs = {ALL_PROXY = proxy_conf} + end + + -- enter repository directory + local oldir = nil + if opt.repodir then + oldir = os.cd(opt.repodir) + end + + -- get last commit + local lastcommit = os.iorunv(git.program, argv, {envs = envs}) + if lastcommit then + lastcommit = lastcommit:trim() + end + + -- leave repository directory + if oldir then + os.cd(oldir) + end + return lastcommit +end diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua index 8d1e0ebdd..972c5c48b 100644 --- a/xmake/modules/private/action/require/impl/lock_packages.lua +++ b/xmake/modules/private/action/require/impl/lock_packages.lua @@ -20,16 +20,53 @@ -- imports import("core.project.project") +import("devel.git") +import("private.action.require.impl.utils.filter") +import("private.action.require.impl.utils.requirekey") + +-- get package key +function _get_packagekey(instance) + local requireinfo = instance:requireinfo() + local requirestr = requireinfo.originstr + local plat = instance:plat() + local arch = instance:arch() + local key = requirekey(requireinfo, {plat = instance:plat(), arch = instance:arch()}) + return string.format("%s#%s", requirestr, key) +end -- lock package function _lock_package(instance) - local result = {} - result.name = instance:name() - result.plat = instance:plat() - result.arch = instance:arch() - result.kind = instance:kind() - result.buildhash = instance:buildhash() - result.version = instance:version_str() + local result = {} + local repo = instance:repo() + result.name = instance:name() + result.plat = instance:plat() + result.arch = instance:arch() + result.kind = instance:kind() + result.version = instance:version_str() + result.buildhash = instance:buildhash() + result.configs = instance:configs() + result.is_built = instance:is_built() + if repo then + local lastcommit = git.lastcommit({repodir = repo:directory()}) + result.repo = repo:url() .. "#" .. lastcommit + end + for _, url in ipairs(instance:urls()) do + result.urls = result.urls or {} + local url_alias = instance:url_alias(url) + url = filter.handle(url, instance) + if git.asgiturl(url) then + local revision = instance:revision(url_alias) or instance:tag() or instance:version_str() + url = url .. "#" .. revision + else + local sourcehash = instance:sourcehash(url_alias) + url = url .. "#" .. sourcehash + end + table.insert(result.urls, url) + end + for _, dep in ipairs(instance:plaindeps()) do + result.deps = result.deps or {} + table.insert(result.deps, _get_packagekey(dep)) + end return result end @@ -37,7 +74,8 @@ end function main(packages) local results = {} for _, instance in ipairs(packages) do - results[instance:displayname()] = _lock_package(instance) + local packagekey = _get_packagekey(instance) + results[packagekey] = _lock_package(instance) end io.writefile(project.requireslock(), string.serialize(results, {orderkeys = true})) end diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 612911429..d94629ce8 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -30,6 +30,7 @@ import("core.tool.toolchain") import("core.package.package", {alias = "core_package"}) import("devel.git") import("private.action.require.impl.repository") +import("private.action.require.impl.utils.requirekey") -- get memcache function _memcache() @@ -477,26 +478,10 @@ end -- get package key function _get_packagekey(packagename, requireinfo, version) - local key = packagename .. "/" .. (version or requireinfo.version) - if requireinfo.plat then - key = key .. "/" .. requireinfo.plat - end - if requireinfo.arch then - key = key .. "/" .. requireinfo.arch - end - if requireinfo.label then - key = key .. "/" .. requireinfo.label - end - local configs = requireinfo.configs - if configs then - local configs_order = {} - for k, v in pairs(configs) do - table.insert(configs_order, k .. "=" .. tostring(v)) - end - table.sort(configs_order) - key = key .. ":" .. string.serialize(configs_order, true) - end - return key + return requirekey(requireinfo, {name = packagename, + plat = requireinfo.plat, + arch = requireinfo.arch, + version = version or requireinfo.version}) end -- inherit some builtin configs of parent package if these config values are not default value diff --git a/xmake/modules/private/action/require/impl/utils/requirekey.lua b/xmake/modules/private/action/require/impl/utils/requirekey.lua new file mode 100644 index 000000000..e39da12ba --- /dev/null +++ b/xmake/modules/private/action/require/impl/utils/requirekey.lua @@ -0,0 +1,50 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file requirekey.lua +-- + +-- get require key from requireinfo +function main(requireinfo, opt) + opt = opt or {} + local key = "" + if opt.name then + key = key .. "/" .. opt.name + end + if opt.plat then + key = key .. "/" .. opt.plat + end + if opt.arch then + key = key .. "/" .. opt.arch + end + if opt.version then + key = key .. "/" .. opt.version + end + if requireinfo.label then + key = key .. "/" .. requireinfo.label + end + local configs = requireinfo.configs + if configs then + local configs_order = {} + for k, v in pairs(configs) do + table.insert(configs_order, k .. "=" .. tostring(v)) + end + table.sort(configs_order) + key = key .. ":" .. string.serialize(configs_order, true) + end + return hash.uuid(key):gsub("%-", ""):lower() +end -- cgit v1.3.1 From 5322929d89183b19f115e7418ffe1fc44bcbc78b Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 16 Aug 2021 22:42:20 +0800 Subject: improve add_repositories --- CHANGELOG.md | 3 +++ xmake/core/sandbox/modules/import/core/package/repository.lua | 11 ++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd50adf44..a58a11cda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ ### Change * [#1540](https://github.com/xmake-io/xmake/issues/1540): Better support for compilation of automatically generated code +* [#1578](https://github.com/xmake-io/xmake/issues/1578): Improve add_repositories to support relative path better ### Bugs fixed @@ -1063,6 +1064,7 @@ ### 改进 * [#1540](https://github.com/xmake-io/xmake/issues/1540): 更好更方便地编译自动生成的代码 +* [#1578](https://github.com/xmake-io/xmake/issues/1578): 改进 add_repositories 去更好地支持相对路径 ### Bugs 修复 @@ -2100,3 +2102,4 @@ * 修复set_installscript接口的一些bug * 修复在windows x86_64下,安装失败的问题 * 修复相对路径的一些bug + diff --git a/xmake/core/sandbox/modules/import/core/package/repository.lua b/xmake/core/sandbox/modules/import/core/package/repository.lua index 86f27b497..4dc00a0ed 100644 --- a/xmake/core/sandbox/modules/import/core/package/repository.lua +++ b/xmake/core/sandbox/modules/import/core/package/repository.lua @@ -92,12 +92,20 @@ function sandbox_core_package_repository.repositories(is_global) -- in project xmake.lua: -- -- add_repositories("other-repo https://github.com/other/other-repo.git dev") + -- add_repositories("other-repo dirname", {rootdir = os.scriptdir()}) -- if not is_global then for _, repo in ipairs(table.wrap(project.get("repositories"))) do local repoinfo = repo:split('%s') if #repoinfo <= 3 then - local repo = repository.load(repoinfo[1], repoinfo[2], repoinfo[3], is_global) + local name = repoinfo[1] + local url = repoinfo[2] + local branch = repoinfo[3] + local rootdir = project.extraconf("repositories", repo, "rootdir") + if url and rootdir and not path.is_absolute(url) and not url:find(":", 1, true) then + url = path.join(rootdir, url) + end + local repo = repository.load(name, url, branch, is_global) if repo then table.insert(repositories, repo) end @@ -167,3 +175,4 @@ end -- return module return sandbox_core_package_repository + -- cgit v1.3.1 From 609e349156ebb28bd1e3788c3e13e76c4ae71826 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Tue, 17 Aug 2021 15:00:01 +0200 Subject: Set CMAKE_MAKE_PROGRAM to mingw32-make.exe on Windows --- xmake/modules/package/tools/cmake.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xmake/modules/package/tools/cmake.lua b/xmake/modules/package/tools/cmake.lua index 3e48fee40..73af75b32 100644 --- a/xmake/modules/package/tools/cmake.lua +++ b/xmake/modules/package/tools/cmake.lua @@ -363,6 +363,12 @@ function _get_configs_for_mingw(package, configs, opt) envs.CMAKE_OSX_SYSROOT = "" -- Avoid cmake to add the flags -search_paths_first and -headerpad_max_install_names on macOS envs.HAVE_FLAG_SEARCH_PATHS_FIRST = "0" + -- CMAKE_MAKE_PROGRAM may be required for some CMakeLists.txt (libcurl) + if is_subhost("windows") then + local mingw = assert(package:build_getenv("mingw") or package:build_getenv("sdk"), "mingw not found!") + envs.CMAKE_MAKE_PROGRAM = path.join(mingw, "bin", "mingw32-make.exe") + end + for k, v in pairs(envs) do table.insert(configs, "-D" .. k .. "=" .. v) end -- cgit v1.3.1 From a07938f51e94935fdf8d995969314e8296eaa619 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Tue, 17 Aug 2021 15:37:59 +0200 Subject: tools.make: add support of Windows MinGW --- xmake/modules/package/tools/make.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/xmake/modules/package/tools/make.lua b/xmake/modules/package/tools/make.lua index b236b9da6..5c58d9de6 100644 --- a/xmake/modules/package/tools/make.lua +++ b/xmake/modules/package/tools/make.lua @@ -104,6 +104,10 @@ function build(package, configs, opt) -- do build if is_host("bsd") then os.vrunv("gmake", argv, {envs = opt.envs or buildenvs(package)}) + elseif package:is_plat("mingw") and is_subhost("windows") then + local mingw = assert(package:build_getenv("mingw") or package:build_getenv("sdk"), "mingw not found!") + local make = path.join(mingw, "bin", "mingw32-make.exe") + os.vrunv(make, argv, {envs = opt.envs or buildenvs(package)}) else os.vrunv("make", argv, {envs = opt.envs or buildenvs(package)}) end @@ -123,6 +127,10 @@ function install(package, configs, opt) end if is_host("bsd") then os.vrunv("gmake", argv, {envs = opt.envs or buildenvs(package)}) + elseif package:is_plat("mingw") and is_subhost("windows") then + local mingw = assert(package:build_getenv("mingw") or package:build_getenv("sdk"), "mingw not found!") + local make = path.join(mingw, "bin", "mingw32-make.exe") + os.vrunv(make, argv, {envs = opt.envs or buildenvs(package)}) else os.vrunv("make", argv, {envs = opt.envs or buildenvs(package)}) end -- cgit v1.3.1 From ec8fcf0e879c6b047195ceb2499d75d0350b7ff4 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Tue, 17 Aug 2021 16:16:50 +0200 Subject: Update make.lua --- xmake/modules/package/tools/make.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xmake/modules/package/tools/make.lua b/xmake/modules/package/tools/make.lua index 5c58d9de6..15158fad4 100644 --- a/xmake/modules/package/tools/make.lua +++ b/xmake/modules/package/tools/make.lua @@ -75,6 +75,11 @@ function buildenvs(package) end envs.ACLOCAL_PATH = path.joinenv(ACLOCAL_PATH) envs.PKG_CONFIG_PATH = path.joinenv(PKG_CONFIG_PATH) + -- some Makefile use ComSpec to detect Windows (e.g. Makefiles generated by Premake) and require this env + if is_subhost("windows") then + envs.ComSpec = os.getenv("ComSpec") + end + return envs end -- cgit v1.3.1 From 6b27b01a08c545e786a03c7062b1b3f9a6931c80 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Tue, 17 Aug 2021 16:19:17 +0200 Subject: make: add missing CXX env --- xmake/modules/package/tools/make.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/modules/package/tools/make.lua b/xmake/modules/package/tools/make.lua index 15158fad4..ff6dce8ed 100644 --- a/xmake/modules/package/tools/make.lua +++ b/xmake/modules/package/tools/make.lua @@ -44,6 +44,7 @@ function buildenvs(package) local cflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cflags")) local cxxflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cxxflags")) envs.CC = package:build_getenv("cc") + envs.CXX = package:build_getenv("cxx") envs.AS = package:build_getenv("as") envs.AR = package:build_getenv("ar") envs.LD = package:build_getenv("ld") -- cgit v1.3.1 From 569ed9f2cc458d8aa9c91916e5f0dc881a64aed1 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 17 Aug 2021 23:49:28 +0800 Subject: fix lock error --- .../package/toolchain_muslcc/xmake-requires.lock | 87 +++------------------- .../private/action/require/impl/lock_packages.lua | 17 +++-- 2 files changed, 22 insertions(+), 82 deletions(-) diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock index 779c320ff..0f835d3d4 100644 --- a/tests/projects/package/toolchain_muslcc/xmake-requires.lock +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -2,11 +2,6 @@ ["autoconf#fd74da7781d54dddb234cfb6eae7be34"] = { arch = "x86_64", buildhash = "01974c48f52d4d658f58852351743754", - configs = { - debug = false, - pic = true, - shared = false - }, deps = { "m4#fd74da7781d54dddb234cfb6eae7be34" }, @@ -14,7 +9,7 @@ kind = "binary", name = "autoconf", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", urls = { "http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz#954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969", "https://mirrors.ustc.edu.cn/gnu/autoconf/autoconf-2.69.tar.gz#954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969", @@ -25,11 +20,6 @@ ["automake#fd74da7781d54dddb234cfb6eae7be34"] = { arch = "x86_64", buildhash = "7a090c93706241f983f0d821a162e8a5", - configs = { - debug = false, - pic = true, - shared = false - }, deps = { "autoconf#fd74da7781d54dddb234cfb6eae7be34" }, @@ -37,7 +27,7 @@ kind = "binary", name = "automake", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", urls = { "http://ftp.gnu.org/gnu/automake/automake-1.16.1.tar.gz#608a97523f97db32f1f5d5615c98ca69326ced2054c9f82e65bade7fc4c9dea8", "https://mirrors.ustc.edu.cn/gnu/automake/automake-1.16.1.tar.gz#608a97523f97db32f1f5d5615c98ca69326ced2054c9f82e65bade7fc4c9dea8" @@ -47,16 +37,11 @@ ["cmake#fd74da7781d54dddb234cfb6eae7be34"] = { arch = "x86_64", buildhash = "a6d18f8c0bf347d980f8bb762583c91a", - configs = { - debug = false, - pic = true, - shared = false - }, is_built = true, kind = "binary", name = "cmake", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", urls = { "https://cmake.org/files/v3.21/cmake-3.21.0-macos-universal-Darwin-x86_64.tar.gz#c1c6f19dfc9c658a48b5aed22806595b2337bb3aedb71ab826552f74f568719f", "https://github.com/Kitware/CMake/releases/download/v3.21.0/cmake-3.21.0-macos-universal.tar.gz#c1c6f19dfc9c658a48b5aed22806595b2337bb3aedb71ab826552f74f568719f" @@ -66,18 +51,13 @@ ["gmp#fd74da7781d54dddb234cfb6eae7be34"] = { arch = "x86_64", buildhash = "7dd9c224447e46698ac73d29f58b1d73", - configs = { - debug = false, - pic = true, - shared = false - }, deps = { "autoconf#fd74da7781d54dddb234cfb6eae7be34" }, is_built = true, name = "gmp", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", urls = { "https://gmplib.org/download/gmp/gmp-6.2.1.tar.xz#fd4829912cddd12f84181c3451cc752be224643e87fac497b69edddadc49b4f2" }, @@ -86,11 +66,6 @@ ["libisl 0.22#11f62b7b062648cebf81bd6623721f7d"] = { arch = "x86_64", buildhash = "f649e1fb365e442e8f79f372fd91483b", - configs = { - debug = false, - pic = true, - shared = true - }, deps = { "autoconf#fd74da7781d54dddb234cfb6eae7be34", "gmp#fd74da7781d54dddb234cfb6eae7be34" @@ -98,7 +73,7 @@ is_built = true, name = "libisl", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", urls = { "http://isl.gforge.inria.fr/isl-0.22.tar.xz#6c8bc56c477affecba9c59e2c9f026967ac8bad01b51bdd07916db40a517b9fa" }, @@ -107,19 +82,13 @@ ["libogg#265260a3b33e47f189d65373131d1f08"] = { arch = "arm", buildhash = "d894fc29f2fb4c45a0f48bc2c6ece273", - configs = { - debug = false, - pic = true, - shared = false, - toolchains = "@muslcc" - }, deps = { "cmake#fd74da7781d54dddb234cfb6eae7be34" }, is_built = true, name = "libogg", plat = "cross", - repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", urls = { "https://gitlab.xiph.org/xiph/ogg/-/archive/v1.3.4/ogg-v1.3.4.tar.gz#62cc64b9fd3cf57bde3a9033e94534ba34313d2bb9698029f623121a4e47bb9b", "https://gitlab.xiph.org/xiph/ogg.git#v1.3.4" @@ -129,12 +98,6 @@ ["libplist#265260a3b33e47f189d65373131d1f08"] = { arch = "arm", buildhash = "0c01b22920be4876b1de74629194eb8f", - configs = { - debug = false, - pic = true, - shared = false, - toolchains = "@muslcc" - }, deps = { "autoconf#fd74da7781d54dddb234cfb6eae7be34", "automake#fd74da7781d54dddb234cfb6eae7be34", @@ -144,7 +107,7 @@ is_built = true, name = "libplist", plat = "cross", - repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", urls = { "https://github.com/libimobiledevice/libplist/archive/2.2.0.tar.gz#7e654bdd5d8b96f03240227ed09057377f06ebad08e1c37d0cfa2abe6ba0cee2", "https://github.com/libimobiledevice/libplist.git#2.2.0" @@ -154,11 +117,6 @@ ["libtool#fd74da7781d54dddb234cfb6eae7be34"] = { arch = "x86_64", buildhash = "64584ec84a4743ecb740b598b263ffa6", - configs = { - debug = false, - pic = true, - shared = false - }, deps = { "autoconf#fd74da7781d54dddb234cfb6eae7be34" }, @@ -166,7 +124,7 @@ kind = "binary", name = "libtool", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", urls = { "http://ftpmirror.gnu.org/libtool/libtool-2.4.6.tar.gz#e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3", "https://mirrors.ustc.edu.cn/gnu/libtool/libtool-2.4.6.tar.gz#e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3", @@ -177,16 +135,11 @@ ["m4#fd74da7781d54dddb234cfb6eae7be34"] = { arch = "x86_64", buildhash = "fd0e83e5759b442a970327ebb1c89793", - configs = { - debug = false, - pic = true, - shared = false - }, is_built = true, kind = "binary", name = "m4", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", urls = { "https://ftp.gnu.org/gnu/m4/m4-1.4.19.tar.xz#63aede5c6d33b6d9b13511cd0be2cac046f2e70fd0a07aa9573a04a82783af96", "https://ftpmirror.gnu.org/m4/m4-1.4.19.tar.xz#63aede5c6d33b6d9b13511cd0be2cac046f2e70fd0a07aa9573a04a82783af96" @@ -196,11 +149,6 @@ ["muslcc#fd74da7781d54dddb234cfb6eae7be34"] = { arch = "x86_64", buildhash = "11062c09ebeb484594488ad73ddbcd1f", - configs = { - debug = false, - pic = true, - shared = false - }, deps = { "libisl 0.22#11f62b7b062648cebf81bd6623721f7d" }, @@ -208,7 +156,7 @@ kind = "toolchain", name = "muslcc", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", urls = { "https://github.com/xmake-mirror/musl.cc/releases/download/20210202/arm-linux-musleabi-cross.mac.tgz#a177df3f847181c0c7f2b34b9bd7725b4c556c11a347aa0ae36e09ebf23fb480" }, @@ -217,16 +165,11 @@ ["pkg-config#fd74da7781d54dddb234cfb6eae7be34"] = { arch = "x86_64", buildhash = "84fd7f9b9f7a47709512cfc85cd9e5f7", - configs = { - debug = false, - pic = true, - shared = false - }, is_built = true, kind = "binary", name = "pkg-config", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", urls = { "https://pkgconfig.freedesktop.org/releases/pkg-config-0.29.2.tar.gz#6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591", "http://fco.it.distfiles.macports.org/mirrors/macports-distfiles/pkgconfig/pkg-config-0.29.2.tar.gz#6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591" @@ -236,16 +179,10 @@ ["zlib#265260a3b33e47f189d65373131d1f08"] = { arch = "arm", buildhash = "be90a245b8bb48e6b08a1a15bdcad467", - configs = { - debug = false, - pic = true, - shared = false, - toolchains = "@muslcc" - }, is_built = true, name = "zlib", plat = "cross", - repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", + repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", urls = { "https://github.com/madler/zlib/archive/v1.2.11.tar.gz#629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff" }, diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua index 972c5c48b..f41e3122f 100644 --- a/xmake/modules/private/action/require/impl/lock_packages.lua +++ b/xmake/modules/private/action/require/impl/lock_packages.lua @@ -44,7 +44,6 @@ function _lock_package(instance) result.kind = instance:kind() result.version = instance:version_str() result.buildhash = instance:buildhash() - result.configs = instance:configs() result.is_built = instance:is_built() if repo then local lastcommit = git.lastcommit({repodir = repo:directory()}) @@ -59,7 +58,9 @@ function _lock_package(instance) url = url .. "#" .. revision else local sourcehash = instance:sourcehash(url_alias) - url = url .. "#" .. sourcehash + if sourcehash then + url = url .. "#" .. sourcehash + end end table.insert(result.urls, url) end @@ -72,11 +73,13 @@ end -- lock all required packages function main(packages) - local results = {} - for _, instance in ipairs(packages) do - local packagekey = _get_packagekey(instance) - results[packagekey] = _lock_package(instance) + if project.policy("package.requires_lock") then + local results = {} + for _, instance in ipairs(packages) do + local packagekey = _get_packagekey(instance) + results[packagekey] = _lock_package(instance) + end + io.writefile(project.requireslock(), string.serialize(results, {orderkeys = true})) end - io.writefile(project.requireslock(), string.serialize(results, {orderkeys = true})) end -- cgit v1.3.1 From 4e14e4eca4c713eb0fd1d0f52c2f7e6f411b2f92 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 17 Aug 2021 23:54:26 +0800 Subject: get locked requires --- .../private/action/require/impl/install_packages.lua | 4 +++- xmake/modules/private/action/require/impl/package.lua | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/xmake/modules/private/action/require/impl/install_packages.lua b/xmake/modules/private/action/require/impl/install_packages.lua index 79fb71c3f..75ca4414e 100644 --- a/xmake/modules/private/action/require/impl/install_packages.lua +++ b/xmake/modules/private/action/require/impl/install_packages.lua @@ -603,7 +603,9 @@ function main(requires, opt) register_packages(packages) -- lock packages - lock_packages(packages) + if #packages_install > 0 then + lock_packages(packages) + end return packages end diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index d94629ce8..ed0429984 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -201,6 +201,25 @@ function _load_package_from_repository(packagename, reponame) end end +-- has locked requires? +function _has_locked_requires() + return project.policy("package.requires_lock") and os.isfile(project.requireslock()) +end + +-- get locked requires +function _get_locked_requires(requirekey) + local requireslock = _memcache():get("requireslock") + if requireslock == nil then + if _has_locked_requires() then + requireslock = io.load(project.requireslock()) + end + _memcache():set("requireslock", requireslock or false) + end + if requireslock then + return requireslock[requirekey] + end +end + -- sort package deps -- -- e.g. -- cgit v1.3.1 From 7f8f4ee2e1640635792ab8a57f3b53f04422205c Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 17 Aug 2021 23:58:31 +0800 Subject: add require key --- .../private/action/require/impl/lock_packages.lua | 12 +++++------ .../private/action/require/impl/package.lua | 23 +++++++++++++++++----- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua index f41e3122f..e624f8d1a 100644 --- a/xmake/modules/private/action/require/impl/lock_packages.lua +++ b/xmake/modules/private/action/require/impl/lock_packages.lua @@ -24,12 +24,10 @@ import("devel.git") import("private.action.require.impl.utils.filter") import("private.action.require.impl.utils.requirekey") --- get package key -function _get_packagekey(instance) +-- get locked package key +function _get_packagelock_key(instance) local requireinfo = instance:requireinfo() local requirestr = requireinfo.originstr - local plat = instance:plat() - local arch = instance:arch() local key = requirekey(requireinfo, {plat = instance:plat(), arch = instance:arch()}) return string.format("%s#%s", requirestr, key) end @@ -66,7 +64,7 @@ function _lock_package(instance) end for _, dep in ipairs(instance:plaindeps()) do result.deps = result.deps or {} - table.insert(result.deps, _get_packagekey(dep)) + table.insert(result.deps, _get_packagelock_key(dep)) end return result end @@ -76,8 +74,8 @@ function main(packages) if project.policy("package.requires_lock") then local results = {} for _, instance in ipairs(packages) do - local packagekey = _get_packagekey(instance) - results[packagekey] = _lock_package(instance) + local packagelock_key = _get_packagelock_key(instance) + results[packagelock_key] = _lock_package(instance) end io.writefile(project.requireslock(), string.serialize(results, {orderkeys = true})) end diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index ed0429984..554033496 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -30,7 +30,7 @@ import("core.tool.toolchain") import("core.package.package", {alias = "core_package"}) import("devel.git") import("private.action.require.impl.repository") -import("private.action.require.impl.utils.requirekey") +import("private.action.require.impl.utils.requirekey", {alias = "_get_requirekey"}) -- get memcache function _memcache() @@ -497,10 +497,17 @@ end -- get package key function _get_packagekey(packagename, requireinfo, version) - return requirekey(requireinfo, {name = packagename, - plat = requireinfo.plat, - arch = requireinfo.arch, - version = version or requireinfo.version}) + return _get_requirekey(requireinfo, {name = packagename, + plat = requireinfo.plat, + arch = requireinfo.arch, + version = version or requireinfo.version}) +end + +-- get locked package key +function _get_packagelock_key(requireinfo) + local requirestr = requireinfo.originstr + local key = _get_requirekey(requireinfo, {plat = requireinfo.plat, arch = requireinfo.arch}) + return string.format("%s#%s", requirestr, key) end -- inherit some builtin configs of parent package if these config values are not default value @@ -655,6 +662,12 @@ function _load_package(packagename, requireinfo, opt) -- finish requireinfo _finish_requireinfo(requireinfo, package) + -- get requirekey + if _has_locked_requires() then + local requirekey = _get_packagelock_key(requireinfo) + print("requirekey", requirekey) + end + -- select package version local version, source = _select_package_version(package, requireinfo) if version then -- cgit v1.3.1 From 139d4b590a4ad763f0c9e43f59e8281383e4212b Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 18 Aug 2021 00:46:14 +0800 Subject: improve requirekey --- xmake/core/package/package.lua | 10 +++++----- xmake/modules/private/action/require/impl/lock_packages.lua | 5 ++++- xmake/modules/private/action/require/impl/package.lua | 8 ++++++-- xmake/modules/private/action/require/impl/utils/requirekey.lua | 9 ++++++++- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index fefa4eb17..5724da656 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -115,10 +115,10 @@ function _instance:plat() return os.subhost() end local requireinfo = self:requireinfo() - if not plat and requireinfo and requireinfo.plat then + if requireinfo and requireinfo.plat then return requireinfo.plat end - return self:get("plat") or package._target_plat() + return package._target_plat() end -- get the architecture of package @@ -145,7 +145,7 @@ function _instance:targetarch() if requireinfo and requireinfo.arch then return requireinfo.arch end - return self:get("arch") or package._target_arch() + return package._target_arch() end -- get the build mode @@ -1703,8 +1703,8 @@ function package.apis() -- package.set_xxx "package.set_urls" , "package.set_kind" - , "package.set_plat" - , "package.set_arch" + , "package.set_plat" -- deprecated + , "package.set_arch" -- deprecated , "package.set_license" , "package.set_homepage" , "package.set_description" diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua index e624f8d1a..7640e7562 100644 --- a/xmake/modules/private/action/require/impl/lock_packages.lua +++ b/xmake/modules/private/action/require/impl/lock_packages.lua @@ -20,15 +20,18 @@ -- imports import("core.project.project") +import("core.project.config") import("devel.git") import("private.action.require.impl.utils.filter") import("private.action.require.impl.utils.requirekey") -- get locked package key function _get_packagelock_key(instance) + local plat = config.plat() or os.subhost() + local arch = config.arch() or os.subarch() local requireinfo = instance:requireinfo() local requirestr = requireinfo.originstr - local key = requirekey(requireinfo, {plat = instance:plat(), arch = instance:arch()}) + local key = requirekey(requireinfo, {hash = true, plat = plat, arch = arch}) return string.format("%s#%s", requirestr, key) end diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 554033496..5dc0ff451 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -26,6 +26,7 @@ import("core.base.hashset") import("private.utils.progress") import("core.cache.memcache") import("core.project.project") +import("core.project.config") import("core.tool.toolchain") import("core.package.package", {alias = "core_package"}) import("devel.git") @@ -505,8 +506,10 @@ end -- get locked package key function _get_packagelock_key(requireinfo) + local plat = config.plat() or os.subhost() + local arch = config.arch() or os.subarch() local requirestr = requireinfo.originstr - local key = _get_requirekey(requireinfo, {plat = requireinfo.plat, arch = requireinfo.arch}) + local key = _get_requirekey(requireinfo, {hash = true, plat = plat, arch = arch}) return string.format("%s#%s", requirestr, key) end @@ -662,11 +665,12 @@ function _load_package(packagename, requireinfo, opt) -- finish requireinfo _finish_requireinfo(requireinfo, package) + --[[ -- get requirekey if _has_locked_requires() then local requirekey = _get_packagelock_key(requireinfo) print("requirekey", requirekey) - end + end]] -- select package version local version, source = _select_package_version(package, requireinfo) diff --git a/xmake/modules/private/action/require/impl/utils/requirekey.lua b/xmake/modules/private/action/require/impl/utils/requirekey.lua index e39da12ba..b07e4d50d 100644 --- a/xmake/modules/private/action/require/impl/utils/requirekey.lua +++ b/xmake/modules/private/action/require/impl/utils/requirekey.lua @@ -37,6 +37,9 @@ function main(requireinfo, opt) if requireinfo.label then key = key .. "/" .. requireinfo.label end + if key:startswith("/") then + key = key:sub(2) + end local configs = requireinfo.configs if configs then local configs_order = {} @@ -46,5 +49,9 @@ function main(requireinfo, opt) table.sort(configs_order) key = key .. ":" .. string.serialize(configs_order, true) end - return hash.uuid(key):gsub("%-", ""):lower() + if opt.hash then + return hash.uuid(key):gsub("%-", ""):lower() + else + return key + end end -- cgit v1.3.1 From 00107046b0c8eb07185b24783b2d32114f9ed760 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 18 Aug 2021 00:47:49 +0800 Subject: add require --upgrade --- xmake/actions/require/main.lua | 2 +- xmake/actions/require/xmake.lua | 1 + xmake/modules/private/action/require/impl/package.lua | 4 +++- xmake/modules/private/action/require/install.lua | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/xmake/actions/require/main.lua b/xmake/actions/require/main.lua index eb0e2014e..41b9a7eac 100644 --- a/xmake/actions/require/main.lua +++ b/xmake/actions/require/main.lua @@ -118,7 +118,7 @@ function main() scan(option.get("requires")) - -- install and update all outdated package dependencies by default if no arguments + -- install and upgrade all outdated package dependencies by default if no arguments else install(option.get("requires")) end diff --git a/xmake/actions/require/xmake.lua b/xmake/actions/require/xmake.lua index a9d4db32c..f33188f77 100644 --- a/xmake/actions/require/xmake.lua +++ b/xmake/actions/require/xmake.lua @@ -72,6 +72,7 @@ task("require") , {'s', "search", "k", nil, "Search for the given packages from repositories.", "e.g.", " $ xmake require --search tbox" } + , {nil, "upgrade", "k", nil, "Upgrade the installed packages." } , {nil, "uninstall", "k", nil, "Uninstall the installed packages.", "e.g.", " $ xmake require --uninstall", diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 5dc0ff451..53e978f9a 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -204,7 +204,9 @@ end -- has locked requires? function _has_locked_requires() - return project.policy("package.requires_lock") and os.isfile(project.requireslock()) + if not option.get("upgrade") then + return project.policy("package.requires_lock") and os.isfile(project.requireslock()) + end end -- get locked requires diff --git a/xmake/modules/private/action/require/install.lua b/xmake/modules/private/action/require/install.lua index 821991dee..e27e627cb 100644 --- a/xmake/modules/private/action/require/install.lua +++ b/xmake/modules/private/action/require/install.lua @@ -76,7 +76,7 @@ function main(requires_raw) -- -- attempt to install git from the builtin-packages first if git not found -- - if git and not repository.pulled() then + if git and (not repository.pulled() or option.get("upgrade")) then task.run("repo", {update = true}) end -- cgit v1.3.1 From 723dca1ac294cccd66f5b3dd0661299fd197f476 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 18 Aug 2021 00:53:03 +0800 Subject: improve version source --- core/src/xmake/semver/select.c | 6 +- .../package/toolchain_muslcc/xmake-requires.lock | 86 +++++++++++----------- xmake/core/package/package.lua | 39 +++++----- .../sandbox/modules/import/core/base/semver.lua | 2 +- .../private/action/require/impl/package.lua | 12 +-- 5 files changed, 72 insertions(+), 73 deletions(-) diff --git a/core/src/xmake/semver/select.c b/core/src/xmake/semver/select.c index 221baf46d..6b2a13031 100644 --- a/core/src/xmake/semver/select.c +++ b/core/src/xmake/semver/select.c @@ -68,7 +68,7 @@ static tb_bool_t xm_semver_select_from_versions_tags1(lua_State* lua, tb_int_t f lua_pushstring(lua, top.raw); lua_setfield(lua, -2, "version"); - lua_pushstring(lua, fromidx == 2? "versions" : "tags"); + lua_pushstring(lua, fromidx == 2? "version" : "tag"); lua_setfield(lua, -2, "source"); // exit the popped semver @@ -92,7 +92,7 @@ static tb_bool_t xm_semver_select_from_versions_tags2(lua_State* lua, tb_int_t f lua_createtable(lua, 0, 2); lua_pushstring(lua, source_str); lua_setfield(lua, -2, "version"); - lua_pushstring(lua, fromidx == 2? "versions" : "tags"); + lua_pushstring(lua, fromidx == 2? "version" : "tag"); lua_setfield(lua, -2, "source"); return tb_true; } @@ -162,7 +162,7 @@ static tb_bool_t xm_semver_select_latest_from_versions_tags(lua_State* lua, tb_i lua_pushstring(lua, top.raw); lua_setfield(lua, -2, "version"); - lua_pushstring(lua, fromidx == 2? "versions" : "tags"); + lua_pushstring(lua, fromidx == 2? "version" : "tag"); lua_setfield(lua, -2, "source"); // exit the popped semver diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock index 0f835d3d4..5ae48eeb9 100644 --- a/tests/projects/package/toolchain_muslcc/xmake-requires.lock +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -1,188 +1,188 @@ { - ["autoconf#fd74da7781d54dddb234cfb6eae7be34"] = { + ["autoconf#f9faf630133045aab06d08087de4bc33"] = { arch = "x86_64", buildhash = "01974c48f52d4d658f58852351743754", deps = { - "m4#fd74da7781d54dddb234cfb6eae7be34" + "m4#f9faf630133045aab06d08087de4bc33" }, is_built = true, kind = "binary", name = "autoconf", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", + repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", urls = { - "http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz#954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969", "https://mirrors.ustc.edu.cn/gnu/autoconf/autoconf-2.69.tar.gz#954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969", - "git://git.sv.gnu.org/autoconf#2.69" + "git://git.sv.gnu.org/autoconf#2.69", + "http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz#954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969" }, version = "2.69" }, - ["automake#fd74da7781d54dddb234cfb6eae7be34"] = { + ["automake#f9faf630133045aab06d08087de4bc33"] = { arch = "x86_64", buildhash = "7a090c93706241f983f0d821a162e8a5", deps = { - "autoconf#fd74da7781d54dddb234cfb6eae7be34" + "autoconf#f9faf630133045aab06d08087de4bc33" }, is_built = true, kind = "binary", name = "automake", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", + repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", urls = { - "http://ftp.gnu.org/gnu/automake/automake-1.16.1.tar.gz#608a97523f97db32f1f5d5615c98ca69326ced2054c9f82e65bade7fc4c9dea8", - "https://mirrors.ustc.edu.cn/gnu/automake/automake-1.16.1.tar.gz#608a97523f97db32f1f5d5615c98ca69326ced2054c9f82e65bade7fc4c9dea8" + "https://mirrors.ustc.edu.cn/gnu/automake/automake-1.16.1.tar.gz#608a97523f97db32f1f5d5615c98ca69326ced2054c9f82e65bade7fc4c9dea8", + "http://ftp.gnu.org/gnu/automake/automake-1.16.1.tar.gz#608a97523f97db32f1f5d5615c98ca69326ced2054c9f82e65bade7fc4c9dea8" }, version = "1.16.1" }, - ["cmake#fd74da7781d54dddb234cfb6eae7be34"] = { + ["cmake#f9faf630133045aab06d08087de4bc33"] = { arch = "x86_64", buildhash = "a6d18f8c0bf347d980f8bb762583c91a", is_built = true, kind = "binary", name = "cmake", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", + repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", urls = { - "https://cmake.org/files/v3.21/cmake-3.21.0-macos-universal-Darwin-x86_64.tar.gz#c1c6f19dfc9c658a48b5aed22806595b2337bb3aedb71ab826552f74f568719f", - "https://github.com/Kitware/CMake/releases/download/v3.21.0/cmake-3.21.0-macos-universal.tar.gz#c1c6f19dfc9c658a48b5aed22806595b2337bb3aedb71ab826552f74f568719f" + "https://github.com/Kitware/CMake/releases/download/v3.21.0/cmake-3.21.0-macos-universal.tar.gz#c1c6f19dfc9c658a48b5aed22806595b2337bb3aedb71ab826552f74f568719f", + "https://cmake.org/files/v3.21/cmake-3.21.0-macos-universal-Darwin-x86_64.tar.gz#c1c6f19dfc9c658a48b5aed22806595b2337bb3aedb71ab826552f74f568719f" }, version = "3.21.0" }, - ["gmp#fd74da7781d54dddb234cfb6eae7be34"] = { + ["gmp#f9faf630133045aab06d08087de4bc33"] = { arch = "x86_64", buildhash = "7dd9c224447e46698ac73d29f58b1d73", deps = { - "autoconf#fd74da7781d54dddb234cfb6eae7be34" + "autoconf#f9faf630133045aab06d08087de4bc33" }, is_built = true, name = "gmp", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", + repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", urls = { "https://gmplib.org/download/gmp/gmp-6.2.1.tar.xz#fd4829912cddd12f84181c3451cc752be224643e87fac497b69edddadc49b4f2" }, version = "6.2.1" }, - ["libisl 0.22#11f62b7b062648cebf81bd6623721f7d"] = { + ["libisl 0.22#3dd996fa365042e39791030c4e1cad52"] = { arch = "x86_64", buildhash = "f649e1fb365e442e8f79f372fd91483b", deps = { - "autoconf#fd74da7781d54dddb234cfb6eae7be34", - "gmp#fd74da7781d54dddb234cfb6eae7be34" + "autoconf#f9faf630133045aab06d08087de4bc33", + "gmp#f9faf630133045aab06d08087de4bc33" }, is_built = true, name = "libisl", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", + repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", urls = { "http://isl.gforge.inria.fr/isl-0.22.tar.xz#6c8bc56c477affecba9c59e2c9f026967ac8bad01b51bdd07916db40a517b9fa" }, version = "0.22" }, - ["libogg#265260a3b33e47f189d65373131d1f08"] = { + ["libogg#30fe400ff5234914998bd7d8c177621c"] = { arch = "arm", buildhash = "d894fc29f2fb4c45a0f48bc2c6ece273", deps = { - "cmake#fd74da7781d54dddb234cfb6eae7be34" + "cmake#f9faf630133045aab06d08087de4bc33" }, is_built = true, name = "libogg", plat = "cross", - repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", + repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", urls = { "https://gitlab.xiph.org/xiph/ogg/-/archive/v1.3.4/ogg-v1.3.4.tar.gz#62cc64b9fd3cf57bde3a9033e94534ba34313d2bb9698029f623121a4e47bb9b", "https://gitlab.xiph.org/xiph/ogg.git#v1.3.4" }, version = "v1.3.4" }, - ["libplist#265260a3b33e47f189d65373131d1f08"] = { + ["libplist#30fe400ff5234914998bd7d8c177621c"] = { arch = "arm", buildhash = "0c01b22920be4876b1de74629194eb8f", deps = { - "autoconf#fd74da7781d54dddb234cfb6eae7be34", - "automake#fd74da7781d54dddb234cfb6eae7be34", - "libtool#fd74da7781d54dddb234cfb6eae7be34", - "pkg-config#fd74da7781d54dddb234cfb6eae7be34" + "autoconf#f9faf630133045aab06d08087de4bc33", + "automake#f9faf630133045aab06d08087de4bc33", + "libtool#f9faf630133045aab06d08087de4bc33", + "pkg-config#f9faf630133045aab06d08087de4bc33" }, is_built = true, name = "libplist", plat = "cross", - repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", + repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", urls = { "https://github.com/libimobiledevice/libplist/archive/2.2.0.tar.gz#7e654bdd5d8b96f03240227ed09057377f06ebad08e1c37d0cfa2abe6ba0cee2", "https://github.com/libimobiledevice/libplist.git#2.2.0" }, version = "2.2.0" }, - ["libtool#fd74da7781d54dddb234cfb6eae7be34"] = { + ["libtool#f9faf630133045aab06d08087de4bc33"] = { arch = "x86_64", buildhash = "64584ec84a4743ecb740b598b263ffa6", deps = { - "autoconf#fd74da7781d54dddb234cfb6eae7be34" + "autoconf#f9faf630133045aab06d08087de4bc33" }, is_built = true, kind = "binary", name = "libtool", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", + repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", urls = { - "http://ftpmirror.gnu.org/libtool/libtool-2.4.6.tar.gz#e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3", "https://mirrors.ustc.edu.cn/gnu/libtool/libtool-2.4.6.tar.gz#e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3", + "http://ftpmirror.gnu.org/libtool/libtool-2.4.6.tar.gz#e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3", "git://git.savannah.gnu.org/libtool.git#2.4.6" }, version = "2.4.6" }, - ["m4#fd74da7781d54dddb234cfb6eae7be34"] = { + ["m4#f9faf630133045aab06d08087de4bc33"] = { arch = "x86_64", buildhash = "fd0e83e5759b442a970327ebb1c89793", is_built = true, kind = "binary", name = "m4", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", + repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", urls = { "https://ftp.gnu.org/gnu/m4/m4-1.4.19.tar.xz#63aede5c6d33b6d9b13511cd0be2cac046f2e70fd0a07aa9573a04a82783af96", "https://ftpmirror.gnu.org/m4/m4-1.4.19.tar.xz#63aede5c6d33b6d9b13511cd0be2cac046f2e70fd0a07aa9573a04a82783af96" }, version = "1.4.19" }, - ["muslcc#fd74da7781d54dddb234cfb6eae7be34"] = { + ["muslcc#f9faf630133045aab06d08087de4bc33"] = { arch = "x86_64", buildhash = "11062c09ebeb484594488ad73ddbcd1f", deps = { - "libisl 0.22#11f62b7b062648cebf81bd6623721f7d" + "libisl 0.22#3dd996fa365042e39791030c4e1cad52" }, is_built = true, kind = "toolchain", name = "muslcc", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", + repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", urls = { "https://github.com/xmake-mirror/musl.cc/releases/download/20210202/arm-linux-musleabi-cross.mac.tgz#a177df3f847181c0c7f2b34b9bd7725b4c556c11a347aa0ae36e09ebf23fb480" }, version = "20210202" }, - ["pkg-config#fd74da7781d54dddb234cfb6eae7be34"] = { + ["pkg-config#f9faf630133045aab06d08087de4bc33"] = { arch = "x86_64", buildhash = "84fd7f9b9f7a47709512cfc85cd9e5f7", is_built = true, kind = "binary", name = "pkg-config", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", + repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", urls = { "https://pkgconfig.freedesktop.org/releases/pkg-config-0.29.2.tar.gz#6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591", "http://fco.it.distfiles.macports.org/mirrors/macports-distfiles/pkgconfig/pkg-config-0.29.2.tar.gz#6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591" }, version = "0.29.2" }, - ["zlib#265260a3b33e47f189d65373131d1f08"] = { + ["zlib#30fe400ff5234914998bd7d8c177621c"] = { arch = "arm", buildhash = "be90a245b8bb48e6b08a1a15bdcad467", is_built = true, name = "zlib", plat = "cross", - repo = "https://gitee.com/tboox/xmake-repo.git#d5113078b850efb476f1730b8cd31d1f47691f00", + repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", urls = { "https://github.com/madler/zlib/archive/v1.2.11.tar.gz#629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff" }, diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 5724da656..f7b2b7884 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -855,22 +855,7 @@ function _instance:version_str() return self._VERSION_STR end --- get branch version -function _instance:branch() - return self._BRANCH -end - --- get tag version -function _instance:tag() - return self._TAG -end - --- is git ref? -function _instance:gitref() - return self:branch() or self:tag() -end - --- set the version, source: branches, tags, versions +-- set the version, source: branch, tag, version function _instance:version_set(version, source) -- save the semver version @@ -880,17 +865,31 @@ function _instance:version_set(version, source) end -- save branch and tag - if source == "branches" then + if source == "branch" then self._BRANCH = version - elseif source == "tags" then + elseif source == "tag" then self._TAG = version end - -- save source and version string - self._SOURCE = source + -- save version string self._VERSION_STR = version end +-- get branch version +function _instance:branch() + return self._BRANCH +end + +-- get tag version +function _instance:tag() + return self._TAG +end + +-- is git ref? +function _instance:gitref() + return self:branch() or self:tag() +end + -- get the require info function _instance:requireinfo() return self._REQUIREINFO diff --git a/xmake/core/sandbox/modules/import/core/base/semver.lua b/xmake/core/sandbox/modules/import/core/base/semver.lua index edaf61470..eadcfb702 100644 --- a/xmake/core/sandbox/modules/import/core/base/semver.lua +++ b/xmake/core/sandbox/modules/import/core/base/semver.lua @@ -80,7 +80,7 @@ end -- local version, source = semver.select(">=1.5.0 <1.6", {"1.5.0", "1.5.1"}, {"v1.5.0", ..}, {"master", "dev"}) -- -- @version the selected version number --- @source the version source, e.g. versions, tags, branchs +-- @source the version source, e.g. version, tag, branch -- function sandbox_core_base_semver.select(range, versions, tags, branches) local verinfo, errors = semver.select(range, table.wrap(versions), table.wrap(tags), table.wrap(branches)) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 53e978f9a..fb84dea5f 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -293,12 +293,12 @@ function _select_package_version(package, requireinfo) -- @see https://github.com/xmake-io/xmake/issues/930 -- https://github.com/xmake-io/xmake/issues/1009 version = require_version - source = "versions" + source = "version" elseif #package:versions() > 0 then -- select version? version, source = try { function () return semver.select(require_version, package:versions()) end } end if not version and has_giturl and not require_version:find('.', 1, true) then -- select branch? - version, source = require_version ~= "latest" and require_version or "master", "branches" + version, source = require_version ~= "latest" and require_version or "master", "branch" end if not version then raise("package(%s): version(%s) not found!", package:name(), require_version) @@ -667,12 +667,12 @@ function _load_package(packagename, requireinfo, opt) -- finish requireinfo _finish_requireinfo(requireinfo, package) - --[[ - -- get requirekey + -- get locked requireinfo + local locked_requireinfo if _has_locked_requires() then local requirekey = _get_packagelock_key(requireinfo) - print("requirekey", requirekey) - end]] + locked_requireinfo = _get_locked_requires(requirekey) + end -- select package version local version, source = _select_package_version(package, requireinfo) -- cgit v1.3.1 From cfcd21ce456c3597573dd2f2324b236d4a84fcdd Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 18 Aug 2021 00:54:38 +0800 Subject: lock version --- .../package/toolchain_muslcc/xmake-requires.lock | 8 ++++---- .../private/action/require/impl/lock_packages.lua | 2 ++ xmake/modules/private/action/require/impl/package.lua | 16 ++++++++++++++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock index 5ae48eeb9..5aa0c0e2e 100644 --- a/tests/projects/package/toolchain_muslcc/xmake-requires.lock +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -12,8 +12,8 @@ repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", urls = { "https://mirrors.ustc.edu.cn/gnu/autoconf/autoconf-2.69.tar.gz#954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969", - "git://git.sv.gnu.org/autoconf#2.69", - "http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz#954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969" + "http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz#954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969", + "git://git.sv.gnu.org/autoconf#2.69" }, version = "2.69" }, @@ -127,8 +127,8 @@ repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", urls = { "https://mirrors.ustc.edu.cn/gnu/libtool/libtool-2.4.6.tar.gz#e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3", - "http://ftpmirror.gnu.org/libtool/libtool-2.4.6.tar.gz#e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3", - "git://git.savannah.gnu.org/libtool.git#2.4.6" + "git://git.savannah.gnu.org/libtool.git#2.4.6", + "http://ftpmirror.gnu.org/libtool/libtool-2.4.6.tar.gz#e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3" }, version = "2.4.6" }, diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua index 7640e7562..e11916db6 100644 --- a/xmake/modules/private/action/require/impl/lock_packages.lua +++ b/xmake/modules/private/action/require/impl/lock_packages.lua @@ -46,6 +46,8 @@ function _lock_package(instance) result.version = instance:version_str() result.buildhash = instance:buildhash() result.is_built = instance:is_built() + result.branch = instance:branch() + result.tag = instance:tag() if repo then local lastcommit = git.lastcommit({repodir = repo:directory()}) result.repo = repo:url() .. "#" .. lastcommit diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index fb84dea5f..627d5e70e 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -269,7 +269,19 @@ function _add_package_configurations(package) end -- select package version -function _select_package_version(package, requireinfo) +function _select_package_version(package, requireinfo, locked_requireinfo) + + -- get it from the locked requireinfo + if locked_requireinfo then + local version = locked_requireinfo.version + local source = "version" + if locked_requireinfo.branch then + source = "branch" + elseif locked_requireinfo.tag then + source = "tag" + end + return version, source + end -- exists urls? otherwise be phony package (only as package group) if #package:urls() > 0 then @@ -675,7 +687,7 @@ function _load_package(packagename, requireinfo, opt) end -- select package version - local version, source = _select_package_version(package, requireinfo) + local version, source = _select_package_version(package, requireinfo, locked_requireinfo) if version then package:version_set(version, source) end -- cgit v1.3.1 From 685beaedb57bed04b1fe8ec2e68348ebb8ceaa37 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 18 Aug 2021 00:56:30 +0800 Subject: fix tests --- tests/modules/semver/test.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/modules/semver/test.lua b/tests/modules/semver/test.lua index f39f3acde..5141f099c 100755 --- a/tests/modules/semver/test.lua +++ b/tests/modules/semver/test.lua @@ -10,21 +10,21 @@ end -- test select version function test_semver_select(t) - _check_semver_select(t, {"1.5.1", "versions"} + _check_semver_select(t, {"1.5.1", "version"} , ">=1.5.0 <1.6.0" , {"1.4.0", "1.5.0", "1.5.1"}) - _check_semver_select(t, {"1.5.1", "versions"} + _check_semver_select(t, {"1.5.1", "version"} , "^1.5.0" ,{"1.4.0", "1.5.0", "1.5.1"}) - _check_semver_select(t, {"master", "branches"} + _check_semver_select(t, {"master", "branch"} , "master" , {"1.4.0", "1.5.0", "1.5.1"} , {"v1.2.0", "v1.6.0"} , {"master", "dev"}) - _check_semver_select(t, {"1.5.1", "versions"} + _check_semver_select(t, {"1.5.1", "version"} , "latest" , {"1.4.0", "1.5.0", "1.5.1"}) end -- cgit v1.3.1 From 223158810ba64b31bdcbd0620cd28557d2e4d6c0 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Wed, 18 Aug 2021 01:58:41 +0200 Subject: Fix .dll not being copied on install with MinGW --- xmake/modules/package/manager/xmake/find_package.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/package/manager/xmake/find_package.lua b/xmake/modules/package/manager/xmake/find_package.lua index 9f565c2b1..a44744ad2 100644 --- a/xmake/modules/package/manager/xmake/find_package.lua +++ b/xmake/modules/package/manager/xmake/find_package.lua @@ -99,7 +99,7 @@ function _find_package_from_repo(name, opt) table.insert(linkdirs, path.join(installdir, libdir)) end end - if opt.plat == "windows" then + if opt.plat == "windows" or opt.plat == "mingw" then for _, file in ipairs(os.files(path.join(installdir, "lib", "*.dll"))) do result.shared = true table.insert(libfiles, file) -- cgit v1.3.1 From 97df909b7731b4fa4a6bb399e6fffba4e76ce09f Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 19 Aug 2021 00:36:32 +0800 Subject: fix semver.select --- core/src/xmake/semver/select.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/xmake/semver/select.c b/core/src/xmake/semver/select.c index 6b2a13031..395dc6f37 100644 --- a/core/src/xmake/semver/select.c +++ b/core/src/xmake/semver/select.c @@ -119,7 +119,7 @@ static tb_bool_t xm_semver_select_from_branches(lua_State* lua, tb_int_t fromidx lua_pushlstring(lua, source_str, source_len); lua_setfield(lua, -2, "version"); - lua_pushstring(lua, "branches"); + lua_pushstring(lua, "branch"); lua_setfield(lua, -2, "source"); // ok -- cgit v1.3.1 From c3b21f59947f34aa38881f621d21fd76fef5f008 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 19 Aug 2021 00:39:07 +0800 Subject: check buildhash --- xmake/modules/private/action/require/impl/lock_packages.lua | 2 -- xmake/modules/private/action/require/impl/package.lua | 5 +++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua index e11916db6..a5e971b60 100644 --- a/xmake/modules/private/action/require/impl/lock_packages.lua +++ b/xmake/modules/private/action/require/impl/lock_packages.lua @@ -42,10 +42,8 @@ function _lock_package(instance) result.name = instance:name() result.plat = instance:plat() result.arch = instance:arch() - result.kind = instance:kind() result.version = instance:version_str() result.buildhash = instance:buildhash() - result.is_built = instance:is_built() result.branch = instance:branch() result.tag = instance:tag() if repo then diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 627d5e70e..148758c59 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -747,6 +747,11 @@ function _load_package(packagename, requireinfo, opt) on_load(package) end + -- check build hash + if locked_requireinfo and locked_requireinfo.buildhash ~= package:buildhash() then + wprint("package(%s): buildhash is not matched in xmake-requires.lock", package:displayname(), locked_requireinfo.buildhash, package:buildhash()) + end + -- load environments from the manifest to enable the environments of on_install() package:envs_load() -- cgit v1.3.1 From e830cca00c1d3a2761eb725003823d8660acafc8 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 19 Aug 2021 00:43:52 +0800 Subject: check lockrequire version --- .../package/toolchain_muslcc/xmake-requires.lock | 24 +------- xmake/core/project/project.lua | 5 ++ .../modules/import/core/project/project.lua | 65 +++++++++++----------- .../private/action/require/impl/lock_packages.lua | 1 + .../private/action/require/impl/package.lua | 3 + 5 files changed, 45 insertions(+), 53 deletions(-) diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock index 5aa0c0e2e..0c232a5a7 100644 --- a/tests/projects/package/toolchain_muslcc/xmake-requires.lock +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -5,15 +5,13 @@ deps = { "m4#f9faf630133045aab06d08087de4bc33" }, - is_built = true, - kind = "binary", name = "autoconf", plat = "macosx", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", urls = { "https://mirrors.ustc.edu.cn/gnu/autoconf/autoconf-2.69.tar.gz#954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969", - "http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz#954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969", - "git://git.sv.gnu.org/autoconf#2.69" + "git://git.sv.gnu.org/autoconf#2.69", + "http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz#954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969" }, version = "2.69" }, @@ -23,8 +21,6 @@ deps = { "autoconf#f9faf630133045aab06d08087de4bc33" }, - is_built = true, - kind = "binary", name = "automake", plat = "macosx", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", @@ -37,8 +33,6 @@ ["cmake#f9faf630133045aab06d08087de4bc33"] = { arch = "x86_64", buildhash = "a6d18f8c0bf347d980f8bb762583c91a", - is_built = true, - kind = "binary", name = "cmake", plat = "macosx", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", @@ -54,7 +48,6 @@ deps = { "autoconf#f9faf630133045aab06d08087de4bc33" }, - is_built = true, name = "gmp", plat = "macosx", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", @@ -70,7 +63,6 @@ "autoconf#f9faf630133045aab06d08087de4bc33", "gmp#f9faf630133045aab06d08087de4bc33" }, - is_built = true, name = "libisl", plat = "macosx", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", @@ -85,7 +77,6 @@ deps = { "cmake#f9faf630133045aab06d08087de4bc33" }, - is_built = true, name = "libogg", plat = "cross", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", @@ -104,7 +95,6 @@ "libtool#f9faf630133045aab06d08087de4bc33", "pkg-config#f9faf630133045aab06d08087de4bc33" }, - is_built = true, name = "libplist", plat = "cross", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", @@ -120,8 +110,6 @@ deps = { "autoconf#f9faf630133045aab06d08087de4bc33" }, - is_built = true, - kind = "binary", name = "libtool", plat = "macosx", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", @@ -135,8 +123,6 @@ ["m4#f9faf630133045aab06d08087de4bc33"] = { arch = "x86_64", buildhash = "fd0e83e5759b442a970327ebb1c89793", - is_built = true, - kind = "binary", name = "m4", plat = "macosx", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", @@ -152,8 +138,6 @@ deps = { "libisl 0.22#3dd996fa365042e39791030c4e1cad52" }, - is_built = true, - kind = "toolchain", name = "muslcc", plat = "macosx", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", @@ -165,8 +149,6 @@ ["pkg-config#f9faf630133045aab06d08087de4bc33"] = { arch = "x86_64", buildhash = "84fd7f9b9f7a47709512cfc85cd9e5f7", - is_built = true, - kind = "binary", name = "pkg-config", plat = "macosx", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", @@ -176,10 +158,10 @@ }, version = "0.29.2" }, + version = "1.0", ["zlib#30fe400ff5234914998bd7d8c177621c"] = { arch = "arm", buildhash = "be90a245b8bb48e6b08a1a15bdcad467", - is_built = true, name = "zlib", plat = "cross", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index e2d7f996a..91982e64a 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -1028,6 +1028,11 @@ function project.requireslock() return path.join(project.directory(), "xmake-requires.lock") end +-- get the format version of requires lockfile +function project.requireslock_version() + return "1.0" +end + -- get the given rule function project.rule(name) return project.rules()[name] diff --git a/xmake/core/sandbox/modules/import/core/project/project.lua b/xmake/core/sandbox/modules/import/core/project/project.lua index 696bd0d91..34b5fa7ac 100644 --- a/xmake/core/sandbox/modules/import/core/project/project.lua +++ b/xmake/core/sandbox/modules/import/core/project/project.lua @@ -36,38 +36,39 @@ local package = require("package/package") local import = require("sandbox/modules/import") -- export some readonly interfaces -sandbox_core_project.get = project.get -sandbox_core_project.extraconf = project.extraconf -sandbox_core_project.rule = project.rule -sandbox_core_project.rules = project.rules -sandbox_core_project.toolchain = project.toolchain -sandbox_core_project.toolchains = project.toolchains -sandbox_core_project.target = project.target -sandbox_core_project.targets = project.targets -sandbox_core_project.ordertargets = project.ordertargets -sandbox_core_project.option = project.option -sandbox_core_project.options = project.options -sandbox_core_project.rootfile = project.rootfile -sandbox_core_project.allfiles = project.allfiles -sandbox_core_project.rcfiles = project.rcfiles -sandbox_core_project.directory = project.directory -sandbox_core_project.name = project.name -sandbox_core_project.modes = project.modes -sandbox_core_project.default_arch = project.default_arch -sandbox_core_project.allowed_modes = project.allowed_modes -sandbox_core_project.allowed_plats = project.allowed_plats -sandbox_core_project.allowed_archs = project.allowed_archs -sandbox_core_project.mtimes = project.mtimes -sandbox_core_project.version = project.version -sandbox_core_project.required_package = project.required_package -sandbox_core_project.required_packages = project.required_packages -sandbox_core_project.requires_str = project.requires_str -sandbox_core_project.requireconfs_str = project.requireconfs_str -sandbox_core_project.requireslock = project.requireslock -sandbox_core_project.policy = project.policy -sandbox_core_project.tmpdir = project.tmpdir -sandbox_core_project.tmpfile = project.tmpfile -sandbox_core_project.is_loaded = project.is_loaded +sandbox_core_project.get = project.get +sandbox_core_project.extraconf = project.extraconf +sandbox_core_project.rule = project.rule +sandbox_core_project.rules = project.rules +sandbox_core_project.toolchain = project.toolchain +sandbox_core_project.toolchains = project.toolchains +sandbox_core_project.target = project.target +sandbox_core_project.targets = project.targets +sandbox_core_project.ordertargets = project.ordertargets +sandbox_core_project.option = project.option +sandbox_core_project.options = project.options +sandbox_core_project.rootfile = project.rootfile +sandbox_core_project.allfiles = project.allfiles +sandbox_core_project.rcfiles = project.rcfiles +sandbox_core_project.directory = project.directory +sandbox_core_project.name = project.name +sandbox_core_project.modes = project.modes +sandbox_core_project.default_arch = project.default_arch +sandbox_core_project.allowed_modes = project.allowed_modes +sandbox_core_project.allowed_plats = project.allowed_plats +sandbox_core_project.allowed_archs = project.allowed_archs +sandbox_core_project.mtimes = project.mtimes +sandbox_core_project.version = project.version +sandbox_core_project.required_package = project.required_package +sandbox_core_project.required_packages = project.required_packages +sandbox_core_project.requires_str = project.requires_str +sandbox_core_project.requireconfs_str = project.requireconfs_str +sandbox_core_project.requireslock = project.requireslock +sandbox_core_project.requireslock_version = project.requireslock_version +sandbox_core_project.policy = project.policy +sandbox_core_project.tmpdir = project.tmpdir +sandbox_core_project.tmpfile = project.tmpfile +sandbox_core_project.is_loaded = project.is_loaded -- check project options function sandbox_core_project.check() diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua index a5e971b60..a02a65470 100644 --- a/xmake/modules/private/action/require/impl/lock_packages.lua +++ b/xmake/modules/private/action/require/impl/lock_packages.lua @@ -76,6 +76,7 @@ end function main(packages) if project.policy("package.requires_lock") then local results = {} + results.version = project.requireslock_version() for _, instance in ipairs(packages) do local packagelock_key = _get_packagelock_key(instance) results[packagelock_key] = _lock_package(instance) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 148758c59..3d9145477 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -684,6 +684,9 @@ function _load_package(packagename, requireinfo, opt) if _has_locked_requires() then local requirekey = _get_packagelock_key(requireinfo) locked_requireinfo = _get_locked_requires(requirekey) + if semver.compare(project.requireslock_version(), locked_requireinfo.version) < 0 then + locked_requireinfo = nil + end end -- select package version -- cgit v1.3.1 From 7d85d8190b2e650ad02552c4935092a6d732206d Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 19 Aug 2021 00:53:05 +0800 Subject: improve requirekey --- .../package/multiconfig/xmake-requires.lock | 40 ++------- .../package/toolchain_muslcc/xmake-requires.lock | 96 +++------------------- .../private/action/require/impl/lock_packages.lua | 25 +----- .../private/action/require/impl/package.lua | 25 +++--- 4 files changed, 33 insertions(+), 153 deletions(-) diff --git a/tests/projects/package/multiconfig/xmake-requires.lock b/tests/projects/package/multiconfig/xmake-requires.lock index 78e911112..8e4e4127c 100644 --- a/tests/projects/package/multiconfig/xmake-requires.lock +++ b/tests/projects/package/multiconfig/xmake-requires.lock @@ -1,53 +1,27 @@ { - ["zlib#fd74da7781d54dddb234cfb6eae7be34"] = { + version = "1.0", + ["zlib#ddbdd8b8f76d455a8c0ef45fffe37160"] = { arch = "x86_64", buildhash = "b76a297309d14c09b42cfe3927260a51", - configs = { - debug = false, - pic = true, - shared = false - }, - is_built = true, name = "zlib", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", - urls = { - "https://github.com/madler/zlib/archive/v1.2.11.tar.gz#629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff" - }, + repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", version = "1.2.11" }, - ["zlib~debug#29572d10f2b44d76ad238aa6d9d886f0"] = { + ["zlib~debug#d72a8a937b694e449bce540c8eb65a8a"] = { arch = "x86_64", buildhash = "e6a6fa6a86ad4fc7ae3c2cf7c60cc084", - configs = { - debug = true, - pic = true, - shared = false - }, - is_built = true, name = "zlib", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", - urls = { - "https://github.com/madler/zlib/archive/v1.2.11.tar.gz#629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff" - }, + repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", version = "1.2.11" }, - ["zlib~shared#0aa7e77905524be8bf354384c68bdde7"] = { + ["zlib~shared#b286744a1898416faad2e5cab0104b2f"] = { arch = "x86_64", buildhash = "8e5b898b0f344715bac89cc6a1577506", - configs = { - debug = false, - pic = true, - shared = true - }, - is_built = true, name = "zlib", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#327b5dd6a61e5345c3e10d758e342a73a8e6c54e", - urls = { - "https://github.com/madler/zlib/archive/v1.2.11.tar.gz#629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff" - }, + repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", version = "1.2.11" } } \ No newline at end of file diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock index 0c232a5a7..fb9cfad02 100644 --- a/tests/projects/package/toolchain_muslcc/xmake-requires.lock +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -1,173 +1,99 @@ { - ["autoconf#f9faf630133045aab06d08087de4bc33"] = { + ["autoconf#ddbdd8b8f76d455a8c0ef45fffe37160"] = { arch = "x86_64", buildhash = "01974c48f52d4d658f58852351743754", - deps = { - "m4#f9faf630133045aab06d08087de4bc33" - }, name = "autoconf", plat = "macosx", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", - urls = { - "https://mirrors.ustc.edu.cn/gnu/autoconf/autoconf-2.69.tar.gz#954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969", - "git://git.sv.gnu.org/autoconf#2.69", - "http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz#954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969" - }, version = "2.69" }, - ["automake#f9faf630133045aab06d08087de4bc33"] = { + ["automake#ddbdd8b8f76d455a8c0ef45fffe37160"] = { arch = "x86_64", buildhash = "7a090c93706241f983f0d821a162e8a5", - deps = { - "autoconf#f9faf630133045aab06d08087de4bc33" - }, name = "automake", plat = "macosx", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", - urls = { - "https://mirrors.ustc.edu.cn/gnu/automake/automake-1.16.1.tar.gz#608a97523f97db32f1f5d5615c98ca69326ced2054c9f82e65bade7fc4c9dea8", - "http://ftp.gnu.org/gnu/automake/automake-1.16.1.tar.gz#608a97523f97db32f1f5d5615c98ca69326ced2054c9f82e65bade7fc4c9dea8" - }, version = "1.16.1" }, - ["cmake#f9faf630133045aab06d08087de4bc33"] = { + ["cmake#ddbdd8b8f76d455a8c0ef45fffe37160"] = { arch = "x86_64", buildhash = "a6d18f8c0bf347d980f8bb762583c91a", name = "cmake", plat = "macosx", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", - urls = { - "https://github.com/Kitware/CMake/releases/download/v3.21.0/cmake-3.21.0-macos-universal.tar.gz#c1c6f19dfc9c658a48b5aed22806595b2337bb3aedb71ab826552f74f568719f", - "https://cmake.org/files/v3.21/cmake-3.21.0-macos-universal-Darwin-x86_64.tar.gz#c1c6f19dfc9c658a48b5aed22806595b2337bb3aedb71ab826552f74f568719f" - }, version = "3.21.0" }, - ["gmp#f9faf630133045aab06d08087de4bc33"] = { + ["gmp#ddbdd8b8f76d455a8c0ef45fffe37160"] = { arch = "x86_64", buildhash = "7dd9c224447e46698ac73d29f58b1d73", - deps = { - "autoconf#f9faf630133045aab06d08087de4bc33" - }, name = "gmp", plat = "macosx", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", - urls = { - "https://gmplib.org/download/gmp/gmp-6.2.1.tar.xz#fd4829912cddd12f84181c3451cc752be224643e87fac497b69edddadc49b4f2" - }, version = "6.2.1" }, ["libisl 0.22#3dd996fa365042e39791030c4e1cad52"] = { arch = "x86_64", buildhash = "f649e1fb365e442e8f79f372fd91483b", - deps = { - "autoconf#f9faf630133045aab06d08087de4bc33", - "gmp#f9faf630133045aab06d08087de4bc33" - }, name = "libisl", plat = "macosx", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", - urls = { - "http://isl.gforge.inria.fr/isl-0.22.tar.xz#6c8bc56c477affecba9c59e2c9f026967ac8bad01b51bdd07916db40a517b9fa" - }, version = "0.22" }, - ["libogg#30fe400ff5234914998bd7d8c177621c"] = { + ["libogg#ddbdd8b8f76d455a8c0ef45fffe37160"] = { arch = "arm", buildhash = "d894fc29f2fb4c45a0f48bc2c6ece273", - deps = { - "cmake#f9faf630133045aab06d08087de4bc33" - }, name = "libogg", plat = "cross", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", - urls = { - "https://gitlab.xiph.org/xiph/ogg/-/archive/v1.3.4/ogg-v1.3.4.tar.gz#62cc64b9fd3cf57bde3a9033e94534ba34313d2bb9698029f623121a4e47bb9b", - "https://gitlab.xiph.org/xiph/ogg.git#v1.3.4" - }, version = "v1.3.4" }, - ["libplist#30fe400ff5234914998bd7d8c177621c"] = { + ["libplist#ddbdd8b8f76d455a8c0ef45fffe37160"] = { arch = "arm", buildhash = "0c01b22920be4876b1de74629194eb8f", - deps = { - "autoconf#f9faf630133045aab06d08087de4bc33", - "automake#f9faf630133045aab06d08087de4bc33", - "libtool#f9faf630133045aab06d08087de4bc33", - "pkg-config#f9faf630133045aab06d08087de4bc33" - }, name = "libplist", plat = "cross", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", - urls = { - "https://github.com/libimobiledevice/libplist/archive/2.2.0.tar.gz#7e654bdd5d8b96f03240227ed09057377f06ebad08e1c37d0cfa2abe6ba0cee2", - "https://github.com/libimobiledevice/libplist.git#2.2.0" - }, version = "2.2.0" }, - ["libtool#f9faf630133045aab06d08087de4bc33"] = { + ["libtool#ddbdd8b8f76d455a8c0ef45fffe37160"] = { arch = "x86_64", buildhash = "64584ec84a4743ecb740b598b263ffa6", - deps = { - "autoconf#f9faf630133045aab06d08087de4bc33" - }, name = "libtool", plat = "macosx", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", - urls = { - "https://mirrors.ustc.edu.cn/gnu/libtool/libtool-2.4.6.tar.gz#e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3", - "git://git.savannah.gnu.org/libtool.git#2.4.6", - "http://ftpmirror.gnu.org/libtool/libtool-2.4.6.tar.gz#e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3" - }, version = "2.4.6" }, - ["m4#f9faf630133045aab06d08087de4bc33"] = { + ["m4#ddbdd8b8f76d455a8c0ef45fffe37160"] = { arch = "x86_64", buildhash = "fd0e83e5759b442a970327ebb1c89793", name = "m4", plat = "macosx", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", - urls = { - "https://ftp.gnu.org/gnu/m4/m4-1.4.19.tar.xz#63aede5c6d33b6d9b13511cd0be2cac046f2e70fd0a07aa9573a04a82783af96", - "https://ftpmirror.gnu.org/m4/m4-1.4.19.tar.xz#63aede5c6d33b6d9b13511cd0be2cac046f2e70fd0a07aa9573a04a82783af96" - }, version = "1.4.19" }, - ["muslcc#f9faf630133045aab06d08087de4bc33"] = { + ["muslcc#ddbdd8b8f76d455a8c0ef45fffe37160"] = { arch = "x86_64", buildhash = "11062c09ebeb484594488ad73ddbcd1f", - deps = { - "libisl 0.22#3dd996fa365042e39791030c4e1cad52" - }, name = "muslcc", plat = "macosx", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", - urls = { - "https://github.com/xmake-mirror/musl.cc/releases/download/20210202/arm-linux-musleabi-cross.mac.tgz#a177df3f847181c0c7f2b34b9bd7725b4c556c11a347aa0ae36e09ebf23fb480" - }, version = "20210202" }, - ["pkg-config#f9faf630133045aab06d08087de4bc33"] = { + ["pkg-config#ddbdd8b8f76d455a8c0ef45fffe37160"] = { arch = "x86_64", buildhash = "84fd7f9b9f7a47709512cfc85cd9e5f7", name = "pkg-config", plat = "macosx", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", - urls = { - "https://pkgconfig.freedesktop.org/releases/pkg-config-0.29.2.tar.gz#6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591", - "http://fco.it.distfiles.macports.org/mirrors/macports-distfiles/pkgconfig/pkg-config-0.29.2.tar.gz#6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591" - }, version = "0.29.2" }, version = "1.0", - ["zlib#30fe400ff5234914998bd7d8c177621c"] = { + ["zlib#ddbdd8b8f76d455a8c0ef45fffe37160"] = { arch = "arm", buildhash = "be90a245b8bb48e6b08a1a15bdcad467", name = "zlib", plat = "cross", repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", - urls = { - "https://github.com/madler/zlib/archive/v1.2.11.tar.gz#629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff" - }, version = "1.2.11" } } \ No newline at end of file diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua index a02a65470..52141d7db 100644 --- a/xmake/modules/private/action/require/impl/lock_packages.lua +++ b/xmake/modules/private/action/require/impl/lock_packages.lua @@ -27,12 +27,8 @@ import("private.action.require.impl.utils.requirekey") -- get locked package key function _get_packagelock_key(instance) - local plat = config.plat() or os.subhost() - local arch = config.arch() or os.subarch() local requireinfo = instance:requireinfo() - local requirestr = requireinfo.originstr - local key = requirekey(requireinfo, {hash = true, plat = plat, arch = arch}) - return string.format("%s#%s", requirestr, key) + return requireinfo and requireinfo.requirekey end -- lock package @@ -50,25 +46,6 @@ function _lock_package(instance) local lastcommit = git.lastcommit({repodir = repo:directory()}) result.repo = repo:url() .. "#" .. lastcommit end - for _, url in ipairs(instance:urls()) do - result.urls = result.urls or {} - local url_alias = instance:url_alias(url) - url = filter.handle(url, instance) - if git.asgiturl(url) then - local revision = instance:revision(url_alias) or instance:tag() or instance:version_str() - url = url .. "#" .. revision - else - local sourcehash = instance:sourcehash(url_alias) - if sourcehash then - url = url .. "#" .. sourcehash - end - end - table.insert(result.urls, url) - end - for _, dep in ipairs(instance:plaindeps()) do - result.deps = result.deps or {} - table.insert(result.deps, _get_packagelock_key(dep)) - end return result end diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 3d9145477..ade76e9d9 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -219,7 +219,7 @@ function _get_locked_requires(requirekey) _memcache():set("requireslock", requireslock or false) end if requireslock then - return requireslock[requirekey] + return requireslock[requirekey], requireslock.version end end @@ -638,6 +638,19 @@ function _load_package(packagename, requireinfo, opt) requireinfo.label = splitinfo[2] end + -- sve requirekey + local requirekey = _get_packagelock_key(requireinfo) + requireinfo.requirekey = requirekey + + -- get locked requireinfo + local locked_requireinfo, requireslock_version + if _has_locked_requires() then + locked_requireinfo, requireslock_version = _get_locked_requires(requirekey) + if requireslock_version and semver.compare(project.requireslock_version(), requireslock_version) < 0 then + locked_requireinfo = nil + end + end + -- load package from project first local package if os.isfile(os.projectfile()) then @@ -679,16 +692,6 @@ function _load_package(packagename, requireinfo, opt) -- finish requireinfo _finish_requireinfo(requireinfo, package) - -- get locked requireinfo - local locked_requireinfo - if _has_locked_requires() then - local requirekey = _get_packagelock_key(requireinfo) - locked_requireinfo = _get_locked_requires(requirekey) - if semver.compare(project.requireslock_version(), locked_requireinfo.version) < 0 then - locked_requireinfo = nil - end - end - -- select package version local version, source = _select_package_version(package, requireinfo, locked_requireinfo) if version then -- cgit v1.3.1 From 8bf73a6626116b4b7368cb2acc630887f3a3768a Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 19 Aug 2021 14:42:59 +0800 Subject: fix cross toolchain --- xmake/modules/package/tools/xmake.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/xmake/modules/package/tools/xmake.lua b/xmake/modules/package/tools/xmake.lua index 0c7d9c294..facbf2be6 100644 --- a/xmake/modules/package/tools/xmake.lua +++ b/xmake/modules/package/tools/xmake.lua @@ -59,13 +59,17 @@ function _get_configs(package, configs) table.insert(configs, "--cross=" .. cross) end local bindir = _get_config_from_toolchains(package, "bindir") or get_config("bin") - if cross then + if bindir then table.insert(configs, "--bin=" .. bindir) end local sdkdir = _get_config_from_toolchains(package, "sdkdir") or get_config("sdk") - if cross then + if sdkdir then table.insert(configs, "--sdk=" .. sdkdir) end + local toolchain_name = get_config("toolchain") + if toolchain_name then + table.insert(configs, "--toolchain=" .. toolchain_name) + end else local names = {"ndk", "ndk_sdkver", "vs", "mingw", "ld", "sh", "ar", "cc", "cxx", "mm", "mxx"} for _, name in ipairs(names) do -- cgit v1.3.1 From 6c3bd03a0eba41d906ce89246c8046bbe39320f9 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 19 Aug 2021 15:32:57 +0800 Subject: Update unix.lua --- xmake/modules/target/action/install/unix.lua | 80 ++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 11 deletions(-) diff --git a/xmake/modules/target/action/install/unix.lua b/xmake/modules/target/action/install/unix.lua index d4311aeea..af3f710a1 100644 --- a/xmake/modules/target/action/install/unix.lua +++ b/xmake/modules/target/action/install/unix.lua @@ -18,15 +18,8 @@ -- @file unix.lua -- --- install library -function _install_library(target, opt) - - -- install libraries - local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib") - os.mkdir(librarydir) - os.vcp(target:targetfile(), librarydir) - - -- install headers +-- install headers +function _install_headers(target, opt) local includedir = path.join(target:installdir(), opt and opt.includedir or "include") os.mkdir(includedir) local srcheaders, dstheaders = target:headerfiles(includedir) @@ -42,19 +35,84 @@ function _install_library(target, opt) end end +-- install shared libraries for package +function _install_shared_for_package(target, pkg, outputdir) + for _, sopath in ipairs(table.wrap(pkg:get("libfiles"))) do + if sopath:endswith(".so") or sopath:endswith(".dylib") then + local soname = path.filename(dllpath) + if os.isfile(path.join(outputdir, soname)) then + wprint("'%s' already exists in install dir, overwriting it from package(%s).", soname, pkg:name()) + end + os.vcp(sopath, outputdir) + end + end +end + +-- install shared libraries for packages +function _install_shared_for_packages(target, outputdir) + _g.installed_packages = _g.installed_packages or {} + for _, pkg in ipairs(target:orderpkgs()) do + if not _g.installed_packages[pkg:name()] then + if pkg:enabled() and pkg:get("libfiles") then + _install_shared_for_package(target, pkg, outputdir) + end + _g.installed_packages[pkg:name()] = true + end + end +end + -- install binary function install_binary(target, opt) + + -- install binary local binarydir = path.join(target:installdir(), opt and opt.bindir or "bin") os.mkdir(binarydir) os.vcp(target:targetfile(), binarydir) + + -- install libraries + local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib") + os.mkdir(librarydir) + + -- install the dependent shared (*.so) target + -- @see https://github.com/xmake-io/xmake/issues/961 + for _, dep in ipairs(target:orderdeps()) do + if dep:kind() == "shared" then + local depfile = dep:targetfile() + if os.isfile(depfile) then + os.vcp(depfile, librarydir) + end + end + -- install all shared libraries in packages in all deps + _install_shared_for_packages(dep, librarydir) + end + + -- install shared libraries for all packages + _install_shared_for_packages(target, librarydir) end -- install shared library function install_shared(target, opt) - _install_library(target, opt) + + -- install libraries + local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib") + os.mkdir(librarydir) + os.vcp(target:targetfile(), librarydir) + + -- install shared libraries for all packages + _install_shared_for_packages(target, librarydir) + + -- install headers + _install_headers(target, opt) end -- install static library function install_static(target, opt) - _install_library(target, opt) + + -- install libraries + local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib") + os.mkdir(librarydir) + os.vcp(target:targetfile(), librarydir) + + -- install headers + _install_headers(target, opt) end -- cgit v1.3.1 From 19eee763e481570b2bfd1e1a62ec547892d80097 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 19 Aug 2021 15:33:31 +0800 Subject: Update windows.lua --- xmake/modules/target/action/install/windows.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/modules/target/action/install/windows.lua b/xmake/modules/target/action/install/windows.lua index 73e8f5ee3..dfb8d2bd3 100644 --- a/xmake/modules/target/action/install/windows.lua +++ b/xmake/modules/target/action/install/windows.lua @@ -42,6 +42,7 @@ end function _install_shared_for_package(target, pkg, outputdir) for _, dllpath in ipairs(table.wrap(pkg:get("libfiles"))) do if dllpath:endswith(".dll") then + local dllname = path.filename(dllpath) if os.isfile(path.join(outputdir, dllname)) then wprint("'%s' already exists in install dir, overwriting it from package(%s).", dllname, pkg:name()) end -- cgit v1.3.1 From 0750e9f48dba55600eae8e0068297a1cded6859a Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 19 Aug 2021 15:47:13 +0800 Subject: Update unix.lua --- xmake/modules/target/action/uninstall/unix.lua | 67 ++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/xmake/modules/target/action/uninstall/unix.lua b/xmake/modules/target/action/uninstall/unix.lua index b582aecf6..e13057fa1 100644 --- a/xmake/modules/target/action/uninstall/unix.lua +++ b/xmake/modules/target/action/uninstall/unix.lua @@ -18,14 +18,8 @@ -- @file unix.lua -- --- uninstall library -function _uninstall_library(target, opt) - - -- remove the target file - local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib") - os.vrm(path.join(librarydir, path.filename(target:targetfile()))) - - -- remove headers from the include directory +-- uninstall headers +function _uninstall_headers(target, opt) local includedir = path.join(target:installdir(), opt and opt.includedir or "include") local _, dstheaders = target:headerfiles(includedir) for _, dstheader in ipairs(dstheaders) do @@ -33,18 +27,71 @@ function _uninstall_library(target, opt) end end +-- uninstall shared libraries for package +function _uninstall_shared_for_package(target, pkg, outputdir) + for _, sopath in ipairs(table.wrap(pkg:get("libfiles"))) do + if sopath:endswith(".so") or sopath:endswith(".dylib") then + local soname = path.filename(sopath) + os.vrm(path.join(outputdir, soname)) + end + end +end + +-- uninstall shared libraries for packages +function _uninstall_shared_for_packages(target, outputdir) + _g.uninstalled_packages = _g.uninstalled_packages or {} + for _, pkg in ipairs(target:orderpkgs()) do + if not _g.uninstalled_packages[pkg:name()] then + if pkg:enabled() and pkg:get("libfiles") then + _uninstall_shared_for_package(target, pkg, outputdir) + end + _g.uninstalled_packages[pkg:name()] = true + end + end +end + -- uninstall binary function uninstall_binary(target, opt) + + -- remove the target file local binarydir = path.join(target:installdir(), opt and opt.bindir or "bin") os.vrm(path.join(binarydir, path.filename(target:targetfile()))) + + -- remove the dependent shared (*.so) target + -- @see https://github.com/xmake-io/xmake/issues/961 + local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib") + for _, dep in ipairs(target:orderdeps()) do + if dep:kind() == "shared" then + os.vrm(path.join(librarydir, path.filename(dep:targetfile()))) + end + _uninstall_shared_for_packages(dep, librarydir) + end + + -- uninstall shared libraries for packages + _uninstall_shared_for_packages(target, librarydir) end -- uninstall shared library function uninstall_shared(target, opt) - _uninstall_library(target, opt) + + -- remove the target file + local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib") + os.vrm(path.join(librarydir, path.filename(target:targetfile()))) + + -- remove headers from the include directory + _uninstall_headers(target, opt) + + -- uninstall shared libraries for packages + _uninstall_shared_for_packages(target, librarydir) end -- uninstall static library function uninstall_static(target, opt) - _uninstall_library(target, opt) + + -- remove the target file + local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib") + os.vrm(path.join(librarydir, path.filename(target:targetfile()))) + + -- remove headers from the include directory + _uninstall_headers(target, opt) end -- cgit v1.3.1 From cb3eac93540c40ab120efa588c3882c21c61881c Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 19 Aug 2021 15:47:51 +0800 Subject: Update windows.lua --- xmake/modules/target/action/uninstall/windows.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/modules/target/action/uninstall/windows.lua b/xmake/modules/target/action/uninstall/windows.lua index f45028303..236b045e3 100644 --- a/xmake/modules/target/action/uninstall/windows.lua +++ b/xmake/modules/target/action/uninstall/windows.lua @@ -31,6 +31,7 @@ end function _uninstall_shared_for_package(target, pkg, outputdir) for _, dllpath in ipairs(table.wrap(pkg:get("libfiles"))) do if dllpath:endswith(".dll") then + local dllname = path.filename(dllpath) os.vrm(path.join(outputdir, dllname)) end end -- cgit v1.3.1 From d5ef6455a7ae27dcbea4cc3b977f45b48f7e563e Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 19 Aug 2021 15:49:46 +0800 Subject: Update unix.lua --- xmake/modules/target/action/install/unix.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/target/action/install/unix.lua b/xmake/modules/target/action/install/unix.lua index af3f710a1..bd2a1cdb1 100644 --- a/xmake/modules/target/action/install/unix.lua +++ b/xmake/modules/target/action/install/unix.lua @@ -39,7 +39,7 @@ end function _install_shared_for_package(target, pkg, outputdir) for _, sopath in ipairs(table.wrap(pkg:get("libfiles"))) do if sopath:endswith(".so") or sopath:endswith(".dylib") then - local soname = path.filename(dllpath) + local soname = path.filename(sopath) if os.isfile(path.join(outputdir, soname)) then wprint("'%s' already exists in install dir, overwriting it from package(%s).", soname, pkg:name()) end -- cgit v1.3.1 From 69da74c43e934650eb797ec51f6b7c91fd419642 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 19 Aug 2021 16:08:50 +0800 Subject: Update linux.yml --- .github/workflows/linux.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 7c1308060..1478b0962 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -8,9 +8,10 @@ on: jobs: build: - runs-on: ubuntu-latest - + concurrency: + group: ${{ github.head_ref }}-build + cancel-in-progress: true steps: - uses: actions/checkout@v2 with: -- cgit v1.3.1 From 8e08d050a9397ae40a9127618f163a60639c0ede Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Thu, 19 Aug 2021 16:04:22 +0200 Subject: Fix install/uninstall output when using --admin --- xmake/actions/install/install_admin.lua | 5 +++++ xmake/actions/install/main.lua | 2 +- xmake/actions/uninstall/main.lua | 2 +- xmake/actions/uninstall/uninstall_admin.lua | 5 +++++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/xmake/actions/install/install_admin.lua b/xmake/actions/install/install_admin.lua index 1f0103d27..594562505 100644 --- a/xmake/actions/install/install_admin.lua +++ b/xmake/actions/install/install_admin.lua @@ -28,6 +28,8 @@ import("install") -- install function main(targetname, installdir, prefix) + local verbose = option.get("verbose") + -- enter project directory os.cd(project.directory()) @@ -40,6 +42,9 @@ function main(targetname, installdir, prefix) -- save the current option and push a new option context option.save() + -- preserve verbose option + option.set("verbose", option) + -- pass installdir to option if installdir then option.set("installdir", installdir) diff --git a/xmake/actions/install/main.lua b/xmake/actions/install/main.lua index 40ba15cc3..febae713b 100644 --- a/xmake/actions/install/main.lua +++ b/xmake/actions/install/main.lua @@ -110,7 +110,7 @@ function main() if sudo.has() and option.get("admin") then -- install target with administrator permission - sudo.runl(path.join(os.scriptdir(), "install_admin.lua"), {targetname or (option.get("all") and "__all" or "__def"), option.get("installdir"), option.get("prefix")}) + sudo.execl(path.join(os.scriptdir(), "install_admin.lua"), {targetname or (option.get("all") and "__all" or "__def"), option.get("installdir"), option.get("prefix")}) cprint("${color.success}install ok!") ok = true end diff --git a/xmake/actions/uninstall/main.lua b/xmake/actions/uninstall/main.lua index eedde054e..3e6769c24 100644 --- a/xmake/actions/uninstall/main.lua +++ b/xmake/actions/uninstall/main.lua @@ -81,7 +81,7 @@ function main() if sudo.has() and option.get("admin") then -- uninstall target with administrator permission - sudo.runl(path.join(os.scriptdir(), "uninstall_admin.lua"), {targetname or "__all", option.get("installdir"), option.get("prefix")}) + sudo.execl(path.join(os.scriptdir(), "uninstall_admin.lua"), {targetname or "__all", option.get("installdir"), option.get("prefix")}) -- trace cprint("${color.success}uninstall ok!") diff --git a/xmake/actions/uninstall/uninstall_admin.lua b/xmake/actions/uninstall/uninstall_admin.lua index c30a16a01..5430a3e76 100644 --- a/xmake/actions/uninstall/uninstall_admin.lua +++ b/xmake/actions/uninstall/uninstall_admin.lua @@ -28,6 +28,8 @@ import("uninstall") -- uninstall function main(targetname, installdir, prefix) + local verbose = option.get("verbose") + -- enter project directory os.cd(project.directory()) @@ -40,6 +42,9 @@ function main(targetname, installdir, prefix) -- save the current option and push a new option context option.save() + -- preserve verbose option + option.set("verbose", option) + -- pass installdir to option if installdir then option.set("installdir", installdir) -- cgit v1.3.1 From 9112276d8065c9fdc0428bb4b44cf1b5794ab6d8 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 19 Aug 2021 22:35:29 +0800 Subject: improve xmake-requires.lock --- .../package/multiconfig/xmake-requires.lock | 22 +++++-- .../package/toolchain_muslcc/xmake-requires.lock | 76 ++++++++++++++++++---- .../private/action/require/impl/lock_packages.lua | 6 +- .../private/action/require/impl/package.lua | 2 +- 4 files changed, 85 insertions(+), 21 deletions(-) diff --git a/tests/projects/package/multiconfig/xmake-requires.lock b/tests/projects/package/multiconfig/xmake-requires.lock index 8e4e4127c..6adbab999 100644 --- a/tests/projects/package/multiconfig/xmake-requires.lock +++ b/tests/projects/package/multiconfig/xmake-requires.lock @@ -1,11 +1,17 @@ { - version = "1.0", + __meta__ = { + version = "1.0" + }, ["zlib#ddbdd8b8f76d455a8c0ef45fffe37160"] = { arch = "x86_64", buildhash = "b76a297309d14c09b42cfe3927260a51", name = "zlib", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, version = "1.2.11" }, ["zlib~debug#d72a8a937b694e449bce540c8eb65a8a"] = { @@ -13,7 +19,11 @@ buildhash = "e6a6fa6a86ad4fc7ae3c2cf7c60cc084", name = "zlib", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, version = "1.2.11" }, ["zlib~shared#b286744a1898416faad2e5cab0104b2f"] = { @@ -21,7 +31,11 @@ buildhash = "8e5b898b0f344715bac89cc6a1577506", name = "zlib", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, version = "1.2.11" } } \ No newline at end of file diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock index fb9cfad02..9509b8501 100644 --- a/tests/projects/package/toolchain_muslcc/xmake-requires.lock +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -1,10 +1,17 @@ { + __meta__ = { + version = "1.0" + }, ["autoconf#ddbdd8b8f76d455a8c0ef45fffe37160"] = { arch = "x86_64", buildhash = "01974c48f52d4d658f58852351743754", name = "autoconf", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, version = "2.69" }, ["automake#ddbdd8b8f76d455a8c0ef45fffe37160"] = { @@ -12,7 +19,11 @@ buildhash = "7a090c93706241f983f0d821a162e8a5", name = "automake", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, version = "1.16.1" }, ["cmake#ddbdd8b8f76d455a8c0ef45fffe37160"] = { @@ -20,7 +31,11 @@ buildhash = "a6d18f8c0bf347d980f8bb762583c91a", name = "cmake", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, version = "3.21.0" }, ["gmp#ddbdd8b8f76d455a8c0ef45fffe37160"] = { @@ -28,7 +43,11 @@ buildhash = "7dd9c224447e46698ac73d29f58b1d73", name = "gmp", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, version = "6.2.1" }, ["libisl 0.22#3dd996fa365042e39791030c4e1cad52"] = { @@ -36,7 +55,11 @@ buildhash = "f649e1fb365e442e8f79f372fd91483b", name = "libisl", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, version = "0.22" }, ["libogg#ddbdd8b8f76d455a8c0ef45fffe37160"] = { @@ -44,7 +67,11 @@ buildhash = "d894fc29f2fb4c45a0f48bc2c6ece273", name = "libogg", plat = "cross", - repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, version = "v1.3.4" }, ["libplist#ddbdd8b8f76d455a8c0ef45fffe37160"] = { @@ -52,7 +79,11 @@ buildhash = "0c01b22920be4876b1de74629194eb8f", name = "libplist", plat = "cross", - repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, version = "2.2.0" }, ["libtool#ddbdd8b8f76d455a8c0ef45fffe37160"] = { @@ -60,7 +91,11 @@ buildhash = "64584ec84a4743ecb740b598b263ffa6", name = "libtool", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, version = "2.4.6" }, ["m4#ddbdd8b8f76d455a8c0ef45fffe37160"] = { @@ -68,7 +103,11 @@ buildhash = "fd0e83e5759b442a970327ebb1c89793", name = "m4", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, version = "1.4.19" }, ["muslcc#ddbdd8b8f76d455a8c0ef45fffe37160"] = { @@ -76,7 +115,11 @@ buildhash = "11062c09ebeb484594488ad73ddbcd1f", name = "muslcc", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, version = "20210202" }, ["pkg-config#ddbdd8b8f76d455a8c0ef45fffe37160"] = { @@ -84,16 +127,23 @@ buildhash = "84fd7f9b9f7a47709512cfc85cd9e5f7", name = "pkg-config", plat = "macosx", - repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, version = "0.29.2" }, - version = "1.0", ["zlib#ddbdd8b8f76d455a8c0ef45fffe37160"] = { arch = "arm", buildhash = "be90a245b8bb48e6b08a1a15bdcad467", name = "zlib", plat = "cross", - repo = "https://gitee.com/tboox/xmake-repo.git#e87effa464611cecf28dfced70cbe491a08fe99d", + repo = { + branch = "master", + commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + url = "https://gitee.com/tboox/xmake-repo.git" + }, version = "1.2.11" } } \ No newline at end of file diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua index 52141d7db..18dabcac4 100644 --- a/xmake/modules/private/action/require/impl/lock_packages.lua +++ b/xmake/modules/private/action/require/impl/lock_packages.lua @@ -44,7 +44,7 @@ function _lock_package(instance) result.tag = instance:tag() if repo then local lastcommit = git.lastcommit({repodir = repo:directory()}) - result.repo = repo:url() .. "#" .. lastcommit + result.repo = {url = repo:url(), commit = lastcommit, branch = repo:branch()} end return result end @@ -52,8 +52,8 @@ end -- lock all required packages function main(packages) if project.policy("package.requires_lock") then - local results = {} - results.version = project.requireslock_version() + local results = {__meta__ = {}} + results.__meta__.version = project.requireslock_version() for _, instance in ipairs(packages) do local packagelock_key = _get_packagelock_key(instance) results[packagelock_key] = _lock_package(instance) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index ade76e9d9..e1c8d87cb 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -219,7 +219,7 @@ function _get_locked_requires(requirekey) _memcache():set("requireslock", requireslock or false) end if requireslock then - return requireslock[requirekey], requireslock.version + return requireslock[requirekey], requireslock.__meta__.version end end -- cgit v1.3.1 From 41213f3589000eb245aa33407ba971dbedc95c91 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 19 Aug 2021 23:50:02 +0800 Subject: add locked repo stub --- .../private/action/require/impl/package.lua | 7 +-- .../private/action/require/impl/repository.lua | 58 +++++++++++++++------- 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index e1c8d87cb..5084d2d29 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -195,8 +195,8 @@ function _load_package_from_project(packagename) end -- load package package from repositories -function _load_package_from_repository(packagename, reponame) - local packagedir, repo = repository.packagedir(packagename, reponame) +function _load_package_from_repository(packagename, opt) + local packagedir, repo = repository.packagedir(packagename, opt) if packagedir then return core_package.load_from_repository(packagename, repo, packagedir) end @@ -660,7 +660,8 @@ function _load_package(packagename, requireinfo, opt) -- load package from repositories local from_repo = false if not package then - package = _load_package_from_repository(packagename, requireinfo.reponame) + package = _load_package_from_repository(packagename, { + name = requireinfo.reponame, locked_repo = locked_requireinfo and locked_requireinfo.repo}) if package then from_repo = true end diff --git a/xmake/modules/private/action/require/impl/repository.lua b/xmake/modules/private/action/require/impl/repository.lua index 4dbf44e52..12a4772cf 100644 --- a/xmake/modules/private/action/require/impl/repository.lua +++ b/xmake/modules/private/action/require/impl/repository.lua @@ -22,6 +22,11 @@ import("core.base.global") import("core.package.repository") +-- get package directory from the locked repository +function _get_packagedir_from_locked_repo(packagename, locked_repo) +-- print(packagename, locked_repo) +end + -- get all repositories function repositories() if _g._REPOSITORIES then @@ -48,34 +53,53 @@ function pulled() end -- get package directory from repositories -function packagedir(packagename, reponame) +function packagedir(packagename, opt) -- strip trailng ~tag, e.g. zlib~debug + opt = opt or {} packagename = packagename:lower() if packagename:find('~', 1, true) then packagename = packagename:gsub("~.+$", "") end - -- get it from cache it - local packagedirs = _g._PACKAGEDIRS or {} - local foundir = packagedirs[packagename] - if foundir then - return foundir[1], foundir[2] + -- get cache key + local reponame = opt.name + local cachekey = packagename + local locked_repo = opt.locked_repo + if locked_repo then + cachekey = cachekey .. locked_repo.url .. locked_repo.commit .. (locked_repo.branch or "") + end + local packagedirs = _g._PACKAGEDIRS + if not packagedirs then + packagedirs = {} + _g._PACKAGEDIRS = packagedirs end - -- find the package directory from repositories - for _, repo in ipairs(repositories()) do - local dir = path.join(repo:directory(), "packages", packagename:sub(1, 1), packagename) - if os.isdir(dir) and os.isfile(path.join(dir, "xmake.lua")) and (not reponame or reponame == repo:name()) then - foundir = {dir, repo} - break + -- get the package directory + local foundir = packagedirs[cachekey] + if not foundir then + + -- find the package directory from the locked repository + if locked_repo then + local dir, repo = _get_packagedir_from_locked_repo(packagename, locked_repo) + if dir and repo then + foundir = {dir, repo} + end end + + -- find the package directory from repositories + if not foundir then + for _, repo in ipairs(repositories()) do + local dir = path.join(repo:directory(), "packages", packagename:sub(1, 1), packagename) + if os.isdir(dir) and os.isfile(path.join(dir, "xmake.lua")) and (not reponame or reponame == repo:name()) then + foundir = {dir, repo} + break + end + end + end + packagedirs[cachekey] = foundir or {} end - if foundir then - packagedirs[packagename] = foundir - _g._PACKAGEDIRS = packagedirs - return foundir[1], foundir[2] - end + return foundir[1], foundir[2] end -- get artifacts manifest from repositories -- cgit v1.3.1 From d96dd2ca564aca5ad0780feb9c14f57b76c693d2 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 19 Aug 2021 23:56:50 +0800 Subject: lock repository --- .../modules/import/core/package/repository.lua | 19 ++------ .../private/action/require/impl/repository.lua | 54 +++++++++++++++++++++- 2 files changed, 57 insertions(+), 16 deletions(-) diff --git a/xmake/core/sandbox/modules/import/core/package/repository.lua b/xmake/core/sandbox/modules/import/core/package/repository.lua index 86f27b497..64135aa75 100644 --- a/xmake/core/sandbox/modules/import/core/package/repository.lua +++ b/xmake/core/sandbox/modules/import/core/package/repository.lua @@ -29,20 +29,13 @@ local repository = require("package/repository") local raise = require("sandbox/modules/raise") local import = require("sandbox/modules/import") --- get repository directory -function sandbox_core_package_repository.directory(is_global) - return repository.directory(is_global) -end - --- get repository url from the given name -function sandbox_core_package_repository.get(name, is_global) - return repository.get(name, is_global) -end +-- inherit some builtin interfaces +sandbox_core_package_repository.directory = repository.directory +sandbox_core_package_repository.get = repository.get +sandbox_core_package_repository.load = repository.load -- add repository url to the given name function sandbox_core_package_repository.add(name, url, branch, is_global) - - -- add it local ok, errors = repository.add(name, url, branch, is_global) if not ok then raise(errors) @@ -51,8 +44,6 @@ end -- remove repository from gobal or local directory function sandbox_core_package_repository.remove(name, is_global) - - -- remove it local ok, errors = repository.remove(name, is_global) if not ok then raise(errors) @@ -61,8 +52,6 @@ end -- clear all repositories from global or local directory function sandbox_core_package_repository.clear(is_global) - - -- clear all repositories local ok, errors = repository.clear(is_global) if not ok then raise(errors) diff --git a/xmake/modules/private/action/require/impl/repository.lua b/xmake/modules/private/action/require/impl/repository.lua index 12a4772cf..b38bc95d3 100644 --- a/xmake/modules/private/action/require/impl/repository.lua +++ b/xmake/modules/private/action/require/impl/repository.lua @@ -19,12 +19,64 @@ -- -- imports +import("core.base.option") import("core.base.global") +import("core.project.config") import("core.package.repository") +import("devel.git") -- get package directory from the locked repository function _get_packagedir_from_locked_repo(packagename, locked_repo) --- print(packagename, locked_repo) + print(packagename, locked_repo) + + -- find global repository directory + local repodir_global + for _, repo in ipairs(repositories()) do + if locked_repo.url == repo:url() and locked_repo.branch == repo:branch() then + repodir_global = repo:directory() + break + end + end + + -- clone repository to local + local reponame = path.basename(locked_repo.url) + local repodir_local = path.join(config.directory(), "repositories", reponame) + if not os.isdir(repodir_local) then + if repodir_global then + git.clone(repodir_global, {verbose = option.get("verbose"), outputdir = repodir_local}) + elseif global.get("network") ~= "private" then + git.clone(locked_repo.url, {verbose = option.get("verbose"), branch = locked_repo.branch, outputdir = repodir_local}) + else + wprint("we cannot lock repository(%s) in private network mode!", locked_repo.url) + return + end + end + + -- try checkout to the given commit + local ok = try {function () git.checkout(locked_repo.commit, {verbose = option.get("verbose"), repodir = repodir_local}); return true end} + if not ok then + if global.get("network") ~= "private" then + -- pull the latest commit + git.pull({verbose = option.get("verbose"), branch = locked_repo.branch, repodir = repodir_local}) + -- re-checkout to the given commit + ok = try {function () git.checkout(locked_repo.commit, {verbose = option.get("verbose"), repodir = repodir_local}); return true end} + else + wprint("we cannot lock repository(%s) in private network mode!", locked_repo.url) + return + end + end + + -- find package directory + local foundir + if ok then + local dir = path.join(repodir_local, "packages", packagename:sub(1, 1), packagename) + if os.isdir(dir) and os.isfile(path.join(dir, "xmake.lua")) then + local repo = repository.load(reponame, locked_repo.url, locked_repo.branch, false) + foundir = {dir, repo} + vprint("lock package(%s) in %s from repository(%s)/%s", packagename, dir, locked_repo.url, locked_repo.commit) + end + end + return foundir end -- get all repositories -- cgit v1.3.1 From 8255e9894b9d1b29ecb479190ab2e9f1e6e8388c Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 20 Aug 2021 00:30:50 +0800 Subject: improve to pull locked repo --- xmake/modules/private/action/require/impl/repository.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/xmake/modules/private/action/require/impl/repository.lua b/xmake/modules/private/action/require/impl/repository.lua index b38bc95d3..a2764916d 100644 --- a/xmake/modules/private/action/require/impl/repository.lua +++ b/xmake/modules/private/action/require/impl/repository.lua @@ -27,7 +27,6 @@ import("devel.git") -- get package directory from the locked repository function _get_packagedir_from_locked_repo(packagename, locked_repo) - print(packagename, locked_repo) -- find global repository directory local repodir_global @@ -39,7 +38,7 @@ function _get_packagedir_from_locked_repo(packagename, locked_repo) end -- clone repository to local - local reponame = path.basename(locked_repo.url) + local reponame = path.basename(locked_repo.url) .. ".lock" local repodir_local = path.join(config.directory(), "repositories", reponame) if not os.isdir(repodir_local) then if repodir_global then @@ -57,7 +56,7 @@ function _get_packagedir_from_locked_repo(packagename, locked_repo) if not ok then if global.get("network") ~= "private" then -- pull the latest commit - git.pull({verbose = option.get("verbose"), branch = locked_repo.branch, repodir = repodir_local}) + git.pull({verbose = option.get("verbose"), remote = locked_repo.url, branch = locked_repo.branch, repodir = repodir_local}) -- re-checkout to the given commit ok = try {function () git.checkout(locked_repo.commit, {verbose = option.get("verbose"), repodir = repodir_local}); return true end} else -- cgit v1.3.1 From 0eac4a64692796d99a1a30f206a2d21463e0acf6 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 20 Aug 2021 00:33:19 +0800 Subject: improve reponame --- tests/projects/package/multiconfig/xmake-requires.lock | 6 +++--- xmake/modules/private/action/require/impl/repository.lua | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/projects/package/multiconfig/xmake-requires.lock b/tests/projects/package/multiconfig/xmake-requires.lock index 6adbab999..e8621f5b3 100644 --- a/tests/projects/package/multiconfig/xmake-requires.lock +++ b/tests/projects/package/multiconfig/xmake-requires.lock @@ -9,7 +9,7 @@ plat = "macosx", repo = { branch = "master", - commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.2.11" @@ -21,7 +21,7 @@ plat = "macosx", repo = { branch = "master", - commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.2.11" @@ -33,7 +33,7 @@ plat = "macosx", repo = { branch = "master", - commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.2.11" diff --git a/xmake/modules/private/action/require/impl/repository.lua b/xmake/modules/private/action/require/impl/repository.lua index a2764916d..528aebc54 100644 --- a/xmake/modules/private/action/require/impl/repository.lua +++ b/xmake/modules/private/action/require/impl/repository.lua @@ -36,9 +36,9 @@ function _get_packagedir_from_locked_repo(packagename, locked_repo) break end end + local reponame = hash.uuid(locked_repo.url):gsub("%-", ""):lower() .. ".lock" -- clone repository to local - local reponame = path.basename(locked_repo.url) .. ".lock" local repodir_local = path.join(config.directory(), "repositories", reponame) if not os.isdir(repodir_local) then if repodir_global then -- cgit v1.3.1 From 63e0022eaa60b02f5215a8792a54a6cdddc61619 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Thu, 19 Aug 2021 16:47:08 +0200 Subject: Fix mistake --- xmake/actions/install/install_admin.lua | 2 +- xmake/actions/uninstall/uninstall_admin.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/actions/install/install_admin.lua b/xmake/actions/install/install_admin.lua index 594562505..c2b57f05d 100644 --- a/xmake/actions/install/install_admin.lua +++ b/xmake/actions/install/install_admin.lua @@ -43,7 +43,7 @@ function main(targetname, installdir, prefix) option.save() -- preserve verbose option - option.set("verbose", option) + option.set("verbose", verbose) -- pass installdir to option if installdir then diff --git a/xmake/actions/uninstall/uninstall_admin.lua b/xmake/actions/uninstall/uninstall_admin.lua index 5430a3e76..f597dea11 100644 --- a/xmake/actions/uninstall/uninstall_admin.lua +++ b/xmake/actions/uninstall/uninstall_admin.lua @@ -43,7 +43,7 @@ function main(targetname, installdir, prefix) option.save() -- preserve verbose option - option.set("verbose", option) + option.set("verbose", verbose) -- pass installdir to option if installdir then -- cgit v1.3.1 From dc4752465dfbfacb977f0fdcb459a1b077e940d6 Mon Sep 17 00:00:00 2001 From: ImperatorS79 Date: Thu, 19 Aug 2021 19:21:26 +0200 Subject: Update find_package.lua to handle multiple .pc files and no .pc files --- .../package/manager/pacman/find_package.lua | 131 ++++++++++++++++++--- 1 file changed, 113 insertions(+), 18 deletions(-) diff --git a/xmake/modules/package/manager/pacman/find_package.lua b/xmake/modules/package/manager/pacman/find_package.lua index 4b2be0403..a31f4787a 100644 --- a/xmake/modules/package/manager/pacman/find_package.lua +++ b/xmake/modules/package/manager/pacman/find_package.lua @@ -40,8 +40,15 @@ function main(name, opt) end -- for msys2/mingw? mingw-w64-[i686|x86_64]-xxx + local cygpath = nil if opt.plat == "mingw" then name = (opt.arch == "x86_64" and "mingw-w64-x86_64-" or "mingw-w64-i686-") .. name + + -- mingw + pacman = cygpath available + cygpath = find_tool("cygpath") + if not cygpath then + return + end end -- get package files list @@ -49,7 +56,7 @@ function main(name, opt) if not list then return end - + -- parse package files list local linkdirs = {} local has_includes = false @@ -65,28 +72,116 @@ function main(name, opt) has_includes = true end end - - -- get pkgconfig file - local pkgconfig_file = pkgconfig_files[name] - if not pkgconfig_file then - for _, file in pairs(pkgconfig_files) do - pkgconfig_file = file - break - end - end - - -- find package - local result = nil - if pkgconfig_file then + + -- we iterate over each pkgconfig file to extract the required data + local result = {} + local myIncludedirs = {} + local myLinkdirs = {} + local myLinks = {} + myVersion = "0" + local foundPC = false + for key, file in pairs(pkgconfig_files) do + pkgconfig_file = file local pkgconfig_dir = path.directory(pkgconfig_file) local pkgconfig_name = path.basename(pkgconfig_file) linkdirs = table.unique(linkdirs) includedirs = table.unique(includedirs) - result = find_package_from_pkgconfig(pkgconfig_name, {configdirs = pkgconfig_dir, linkdirs = linkdirs}) - if not result and has_includes then - -- header only and hidden /usr/include? we need only return empty {} - result = {} + local myResult = {} + myResult = find_package_from_pkgconfig(pkgconfig_name, {configdirs = pkgconfig_dir, linkdirs = linkdirs}) + + -- the pkgconfig file has been parse successfully + if myResult ~= nil then + for _, locIncludeDir in pairs(myResult.includedirs) do + table.insert(myIncludedirs, locIncludeDir) + end + + for _, locLinkDir in pairs(myResult.linkdirs) do + table.insert(myLinkdirs, locLinkDir) + end + + for _, locLink in pairs(myResult.links) do + table.insert(myLinks, locLink) + end + + -- version should be the same if a pacman package contains multiples .pc + myVersion = myResult.version + + foundPC = true + end + end + + if foundPC == true then + myIncludedirs = table.unique(myIncludedirs) + myLinkdirs = table.unique(myLinkdirs) + myLinks = table.unique(myLinks) + + result.includedirs = myIncludedirs + result.linkdirs = myLinkdirs + result.links = myLinks + result.version = myVersion + else -- if there is no .pc, we parse the package content to obtain the data we want + for _, line in ipairs(list:split('\n', {plain = true})) do -- on msys cygpath should be use to convert local path to windows path + line = line:trim():split('%s+')[2] + if line:find("/include/", 1, true) and (line:endswith(".h") or line:endswith(".hpp")) then + local hPath = line + if opt.plat == "mingw" then + hPath = os.iorunv(cygpath.program, {"--windows", line}) + end + table.insert(myIncludedirs, path.directory(hPath)) + if(opt.arch == "x86_64") then + local baseHPath = os.iorunv(cygpath.program, {"--windows", "/mingw64/include"}) + table.insert(myIncludedirs, baseHPath) + else + local baseHPath = os.iorunv(cygpath.program, {"--windows", "/mingw32/include"}) + table.insert(myIncludedirs, baseHPath) + end + -- revove lib and .a, .dll.a and .so to have the links + elseif line:endswith(".dll.a") then + local aPath = os.iorunv(cygpath.program, {"--windows", line}) + table.insert(myLinkdirs, path.directory(aPath)) + aPath = path.filename(aPath) + if aPath:startswith("lib") then + aPath = aPath:sub(4, aPath:len()) + end + table.insert(myLinks, aPath:sub(1, aPath:len() - 7)) + elseif line:endswith(".so") then + local aPath = line + table.insert(myLinkdirs, path.directory(aPath)) + aPath = path.filename(aPath) + if aPath:startswith("lib") then + aPath = aPath:sub(4, aPath:len()) + end + table.insert(myLinks, aPath:sub(1, aPath:len() - 4)) + elseif line:endswith(".a") then + local aPath = line + if opt.plat == "mingw" then + aPath = os.iorunv(cygpath.program, {"--windows", line}) + end + aPath = path.filename(aPath) + if aPath:startswith("lib") then + aPath = aPath:sub(4, aPath:len()) + end + table.insert(myLinks, aPath:sub(1, aPath:len() - 3)) + end end + + myLinkdirs = table.unique(myLinkdirs) + myLinks = table.unique(myLinks) + myIncludedirs = table.unique(myIncludedirs) + + -- use pacman package version as version + local myVersion = "0" + local nameVersion = try { function() return os.iorunv(pacman.program, {"-Q", name}) end } + if nameVersion then + myVersion = nameVersion:trim():split('%s+')[2] + end + + result = {} + result.includedirs = myIncludedirs + result.linkdirs = myLinkdirs + result.links = myLinks + result.version = myVersion end + return result end -- cgit v1.3.1 From 800535762f40247fafefbf5333502d0ffb4285af Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 20 Aug 2021 22:31:00 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a58a11cda..0967c52e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * [#1534](https://github.com/xmake-io/xmake/issues/1534): Support to compile Vala lanuage project * [#1544](https://github.com/xmake-io/xmake/issues/1544): Add utils.bin2c rule to generate header from binary file * [#1547](https://github.com/xmake-io/xmake/issues/1547): Support to run and get output of c/c++ snippets in option +* [#1567](https://github.com/xmake-io/xmake/issues/1567): Package "lock file" support to freeze dependencies ### Change @@ -1060,6 +1061,7 @@ * [#1534](https://github.com/xmake-io/xmake/issues/1534): 新增对 Vala 语言的支持 * [#1544](https://github.com/xmake-io/xmake/issues/1544): 添加 utils.bin2c 规则去自动从二进制资源文件产生 .h 头文件并引入到 C/C++ 代码中 * [#1547](https://github.com/xmake-io/xmake/issues/1547): option/snippets 支持运行检测模式,并且可以获取输出 +* [#1567](https://github.com/xmake-io/xmake/issues/1567): 新增 xmake-requires.lock 包依赖锁定支持 ### 改进 -- cgit v1.3.1 From a14831de9504ce1d4987e5ce008a099abc8b3528 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 20 Aug 2021 22:31:29 +0800 Subject: update readme --- README.md | 1 + README_zh.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 53b0fa027..bbff9155f 100644 --- a/README.md +++ b/README.md @@ -259,6 +259,7 @@ muslcc The musl-based cross-compilation toolchains * Incremental compilation support, automatic analysis of header dependency files * Fast switching toolchains * Automatic pull toolchain and dependency package integration +* Support precompiled package and lock package requires ## Supported Projects diff --git a/README_zh.md b/README_zh.md index 61f5ad93a..2ef9752cf 100644 --- a/README_zh.md +++ b/README_zh.md @@ -265,6 +265,7 @@ muslcc The musl-based cross-compilation toolchains * 增量编译支持,头文件依赖自动分析 * 工具链的快速切换、定制化支持 * 自动拉取工具链以及依赖包的快速整合 +* 支持预编译包以及包依赖锁定 ## 工程类型 -- cgit v1.3.1 From bf6b82226abc277eaaf7d16fabfea48edb4d6cf7 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 20 Aug 2021 22:32:28 +0800 Subject: improve ci --- .github/workflows/archlinux.yml | 3 +++ .github/workflows/debian_mips64.yml | 4 ++++ .github/workflows/fedora.yml | 3 +++ .github/workflows/freebsd.yml | 3 +++ .github/workflows/macos.yml | 3 +++ .github/workflows/msys2_mingw.yml | 5 +++++ .github/workflows/ubuntu_arm.yml | 4 ++++ .github/workflows/ubuntu_arm64.yml | 4 ++++ .github/workflows/windows.yml | 3 +++ 9 files changed, 32 insertions(+) diff --git a/.github/workflows/archlinux.yml b/.github/workflows/archlinux.yml index 2a9755fb2..d16473c5a 100644 --- a/.github/workflows/archlinux.yml +++ b/.github/workflows/archlinux.yml @@ -12,6 +12,9 @@ jobs: container: archlinux:latest runs-on: ubuntu-latest + concurrency: + group: ${{ github.head_ref }}-build + cancel-in-progress: true steps: - name: Prepare build tools run: | diff --git a/.github/workflows/debian_mips64.yml b/.github/workflows/debian_mips64.yml index 0ee576e1a..f31428370 100644 --- a/.github/workflows/debian_mips64.yml +++ b/.github/workflows/debian_mips64.yml @@ -9,6 +9,10 @@ on: jobs: build: runs-on: ubuntu-latest + + concurrency: + group: ${{ github.head_ref }}-build + cancel-in-progress: true steps: - uses: actions/checkout@v2 with: diff --git a/.github/workflows/fedora.yml b/.github/workflows/fedora.yml index f25b4b7d2..874f8432c 100644 --- a/.github/workflows/fedora.yml +++ b/.github/workflows/fedora.yml @@ -12,6 +12,9 @@ jobs: container: fedora:latest runs-on: ubuntu-latest + concurrency: + group: ${{ github.head_ref }}-build + cancel-in-progress: true steps: - name: Prepare build tools run: | diff --git a/.github/workflows/freebsd.yml b/.github/workflows/freebsd.yml index a23a653e3..d45d2a2ad 100644 --- a/.github/workflows/freebsd.yml +++ b/.github/workflows/freebsd.yml @@ -11,6 +11,9 @@ jobs: runs-on: macos-latest + concurrency: + group: ${{ github.head_ref }}-build + cancel-in-progress: true steps: - uses: actions/checkout@v2 with: diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 7358074bc..c6ed72491 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -11,6 +11,9 @@ jobs: runs-on: macos-latest + concurrency: + group: ${{ github.head_ref }}-build + cancel-in-progress: true steps: - uses: actions/checkout@v2 with: diff --git a/.github/workflows/msys2_mingw.yml b/.github/workflows/msys2_mingw.yml index 3964d5c2f..3fa744ed1 100644 --- a/.github/workflows/msys2_mingw.yml +++ b/.github/workflows/msys2_mingw.yml @@ -7,6 +7,11 @@ on: jobs: build: runs-on: windows-latest + + concurrency: + group: ${{ github.head_ref }}-build + cancel-in-progress: true + strategy: fail-fast: false matrix: diff --git a/.github/workflows/ubuntu_arm.yml b/.github/workflows/ubuntu_arm.yml index e29aa3907..f6b2e08cd 100644 --- a/.github/workflows/ubuntu_arm.yml +++ b/.github/workflows/ubuntu_arm.yml @@ -9,6 +9,10 @@ on: jobs: build: runs-on: ubuntu-latest + + concurrency: + group: ${{ github.head_ref }}-build + cancel-in-progress: true steps: - uses: actions/checkout@v2 with: diff --git a/.github/workflows/ubuntu_arm64.yml b/.github/workflows/ubuntu_arm64.yml index be7c7e169..730bb46b2 100644 --- a/.github/workflows/ubuntu_arm64.yml +++ b/.github/workflows/ubuntu_arm64.yml @@ -9,6 +9,10 @@ on: jobs: build: runs-on: ubuntu-latest + + concurrency: + group: ${{ github.head_ref }}-build + cancel-in-progress: true steps: - uses: actions/checkout@v2 with: diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index fce3236a6..9606433d6 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -15,6 +15,9 @@ jobs: runs-on: ${{ matrix.os }} + concurrency: + group: ${{ github.head_ref }}-build + cancel-in-progress: true steps: - uses: actions/checkout@v2 with: -- cgit v1.3.1 From aa1fcf6c858bb139927c9e1d36e70bd7197ba8fb Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 20 Aug 2021 22:33:13 +0800 Subject: improve ci --- .github/workflows/archlinux.yml | 2 +- .github/workflows/debian_mips64.yml | 2 +- .github/workflows/fedora.yml | 2 +- .github/workflows/freebsd.yml | 2 +- .github/workflows/linux.yml | 16 ++++++++-------- .github/workflows/macos.yml | 2 +- .github/workflows/msys2_mingw.yml | 2 +- .github/workflows/ubuntu_arm.yml | 2 +- .github/workflows/ubuntu_arm64.yml | 2 +- .github/workflows/windows.yml | 2 +- 10 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/archlinux.yml b/.github/workflows/archlinux.yml index d16473c5a..2c13dd367 100644 --- a/.github/workflows/archlinux.yml +++ b/.github/workflows/archlinux.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest concurrency: - group: ${{ github.head_ref }}-build + group: ${{ github.head_ref }}-Archlinux cancel-in-progress: true steps: - name: Prepare build tools diff --git a/.github/workflows/debian_mips64.yml b/.github/workflows/debian_mips64.yml index f31428370..a2365b2af 100644 --- a/.github/workflows/debian_mips64.yml +++ b/.github/workflows/debian_mips64.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest concurrency: - group: ${{ github.head_ref }}-build + group: ${{ github.head_ref }}-DebianMips64 cancel-in-progress: true steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/fedora.yml b/.github/workflows/fedora.yml index 874f8432c..0105d35ef 100644 --- a/.github/workflows/fedora.yml +++ b/.github/workflows/fedora.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest concurrency: - group: ${{ github.head_ref }}-build + group: ${{ github.head_ref }}-Fedora cancel-in-progress: true steps: - name: Prepare build tools diff --git a/.github/workflows/freebsd.yml b/.github/workflows/freebsd.yml index d45d2a2ad..43de28c51 100644 --- a/.github/workflows/freebsd.yml +++ b/.github/workflows/freebsd.yml @@ -12,7 +12,7 @@ jobs: runs-on: macos-latest concurrency: - group: ${{ github.head_ref }}-build + group: ${{ github.head_ref }}-FreeBSD cancel-in-progress: true steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 1478b0962..1851e45ab 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -10,7 +10,7 @@ jobs: build: runs-on: ubuntu-latest concurrency: - group: ${{ github.head_ref }}-build + group: ${{ github.head_ref }}-Linux cancel-in-progress: true steps: - uses: actions/checkout@v2 @@ -36,7 +36,7 @@ jobs: run: | sudo apt install -y ruby ruby-dev rubygems build-essential sudo gem install --no-document fpm - scripts/makepkg deb + scripts/makepkg deb - uses: actions/upload-artifact@v2 with: name: xmake-latest.amd64.deb @@ -62,11 +62,11 @@ jobs: sudo apt install -y dh-make rng-tools devscripts lintian echo "$PPA_GPG_PRIKEY_2C0C68C9" > ppa_gpg.key gpg --import ppa_gpg.key - scripts/makeppa groovy - scripts/makeppa focal - scripts/makeppa bionic - scripts/makeppa xenial - scripts/makeppa trusty - scripts/makeppa precise + scripts/makeppa groovy + scripts/makeppa focal + scripts/makeppa bionic + scripts/makeppa xenial + scripts/makeppa trusty + scripts/makeppa precise diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index c6ed72491..c814607ec 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -12,7 +12,7 @@ jobs: runs-on: macos-latest concurrency: - group: ${{ github.head_ref }}-build + group: ${{ github.head_ref }}-macOS cancel-in-progress: true steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/msys2_mingw.yml b/.github/workflows/msys2_mingw.yml index 3fa744ed1..d19184283 100644 --- a/.github/workflows/msys2_mingw.yml +++ b/.github/workflows/msys2_mingw.yml @@ -9,7 +9,7 @@ jobs: runs-on: windows-latest concurrency: - group: ${{ github.head_ref }}-build + group: ${{ github.head_ref }}-MSYS2_MINGW cancel-in-progress: true strategy: diff --git a/.github/workflows/ubuntu_arm.yml b/.github/workflows/ubuntu_arm.yml index f6b2e08cd..df62b3ae9 100644 --- a/.github/workflows/ubuntu_arm.yml +++ b/.github/workflows/ubuntu_arm.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest concurrency: - group: ${{ github.head_ref }}-build + group: ${{ github.head_ref }}-UbuntuArm cancel-in-progress: true steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/ubuntu_arm64.yml b/.github/workflows/ubuntu_arm64.yml index 730bb46b2..14abdc7ba 100644 --- a/.github/workflows/ubuntu_arm64.yml +++ b/.github/workflows/ubuntu_arm64.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest concurrency: - group: ${{ github.head_ref }}-build + group: ${{ github.head_ref }}-UbuntuArm64 cancel-in-progress: true steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 9606433d6..4dfe3eb35 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -16,7 +16,7 @@ jobs: runs-on: ${{ matrix.os }} concurrency: - group: ${{ github.head_ref }}-build + group: ${{ github.head_ref }}-Windows cancel-in-progress: true steps: - uses: actions/checkout@v2 -- cgit v1.3.1 From c95fdc3f443b3dee83708b42bc34383a47601e13 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 20 Aug 2021 22:37:18 +0800 Subject: improve host package --- .../package/toolchain_muslcc/xmake-requires.lock | 24 +++++++++++----------- xmake/core/package/package.lua | 12 +++++------ .../modules/import/core/package/package.lua | 20 ++++++------------ .../private/action/require/impl/package.lua | 9 ++++++-- 4 files changed, 31 insertions(+), 34 deletions(-) diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock index 9509b8501..d31ecd965 100644 --- a/tests/projects/package/toolchain_muslcc/xmake-requires.lock +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -9,7 +9,7 @@ plat = "macosx", repo = { branch = "master", - commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "2.69" @@ -21,7 +21,7 @@ plat = "macosx", repo = { branch = "master", - commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.16.1" @@ -33,7 +33,7 @@ plat = "macosx", repo = { branch = "master", - commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "3.21.0" @@ -45,7 +45,7 @@ plat = "macosx", repo = { branch = "master", - commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "6.2.1" @@ -57,7 +57,7 @@ plat = "macosx", repo = { branch = "master", - commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "0.22" @@ -69,7 +69,7 @@ plat = "cross", repo = { branch = "master", - commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "v1.3.4" @@ -81,7 +81,7 @@ plat = "cross", repo = { branch = "master", - commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "2.2.0" @@ -93,7 +93,7 @@ plat = "macosx", repo = { branch = "master", - commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "2.4.6" @@ -105,7 +105,7 @@ plat = "macosx", repo = { branch = "master", - commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.4.19" @@ -117,7 +117,7 @@ plat = "macosx", repo = { branch = "master", - commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "20210202" @@ -129,7 +129,7 @@ plat = "macosx", repo = { branch = "master", - commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "0.29.2" @@ -141,7 +141,7 @@ plat = "cross", repo = { branch = "master", - commit = "e87effa464611cecf28dfced70cbe491a08fe99d", + commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.2.11" diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index f7b2b7884..d68f782e4 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -118,7 +118,7 @@ function _instance:plat() if requireinfo and requireinfo.plat then return requireinfo.plat end - return package._target_plat() + return package.targetplat() end -- get the architecture of package @@ -145,7 +145,7 @@ function _instance:targetarch() if requireinfo and requireinfo.arch then return requireinfo.arch end - return package._target_arch() + return package.targetarch() end -- get the build mode @@ -1592,7 +1592,7 @@ end -- the current platform is belong to the given platforms? function package._api_is_plat(interp, ...) - local plat = package._target_plat() + local plat = package.targetplat() for _, v in ipairs(table.join(...)) do if v and plat == v then return true @@ -1602,7 +1602,7 @@ end -- the current platform is belong to the given architectures? function package._api_is_arch(interp, ...) - local arch = package._target_arch() + local arch = package.targetarch() for _, v in ipairs(table.join(...)) do if v and arch:find("^" .. v:gsub("%-", "%%-") .. "$") then return true @@ -1657,7 +1657,7 @@ function package._project() end -- get global target platform of package -function package._target_plat() +function package.targetplat() local plat = package._memcache():get("target_plat") if plat == nil then if not plat and package._project() then @@ -1675,7 +1675,7 @@ function package._target_plat() end -- get global target architecture of pacakge -function package._target_arch() +function package.targetarch() local arch = package._memcache():get("target_arch") if arch == nil then if not arch and package._project() then diff --git a/xmake/core/sandbox/modules/import/core/package/package.lua b/xmake/core/sandbox/modules/import/core/package/package.lua index 4ba67d246..f1ec8799f 100644 --- a/xmake/core/sandbox/modules/import/core/package/package.lua +++ b/xmake/core/sandbox/modules/import/core/package/package.lua @@ -26,20 +26,12 @@ local project = require("project/project") local package = require("package/package") local raise = require("sandbox/modules/raise") --- get cache directory -function sandbox_core_package_package.cachedir(opt) - return package.cachedir(opt) -end - --- the install directory -function sandbox_core_package_package.installdir() - return package.installdir() -end - --- the search directories -function sandbox_core_package_package.searchdirs() - return package.searchdirs() -end +-- inherit some builtin interfaces +sandbox_core_package_package.cachedir = package.cachedir +sandbox_core_package_package.installdir = package.installdir +sandbox_core_package_package.searchdirs = package.searchdirs +sandbox_core_package_package.targetplat = package.targetplat +sandbox_core_package_package.targetarch = package.targetarch -- load the package from the project file function sandbox_core_package_package.load_from_project(packagename) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 5084d2d29..95a54a008 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -152,8 +152,13 @@ function _load_require(require_str, requires_extra, parentinfo) -- require packge in the current host platform if require_extra.host then - require_extra.plat = os.host() - require_extra.arch = os.arch() + if is_subhost(core_package.targetplat()) and os.subarch() == core_package.targetarch() then + -- we need pass plat/arch to avoid repeat installation + -- @see https://github.com/xmake-io/xmake/issues/1579 + else + require_extra.plat = os.subhost() + require_extra.arch = os.subarch() + end end -- init required item -- cgit v1.3.1 From a226ce07d85f3aab66b6dacf6f91e85f7296a490 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 21 Aug 2021 00:46:07 +0800 Subject: improve to copy symlink for installation --- CHANGELOG.md | 2 ++ xmake/core/base/os.lua | 24 ++++++++++++++++-------- xmake/modules/target/action/install/unix.lua | 12 +++++++++++- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0967c52e5..1f1ffbd65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * [#1540](https://github.com/xmake-io/xmake/issues/1540): Better support for compilation of automatically generated code * [#1578](https://github.com/xmake-io/xmake/issues/1578): Improve add_repositories to support relative path better +* [#1582](https://github.com/xmake-io/xmake/issues/1582): Improve installation and os.cp to reserve symlink ### Bugs fixed @@ -1067,6 +1068,7 @@ * [#1540](https://github.com/xmake-io/xmake/issues/1540): 更好更方便地编译自动生成的代码 * [#1578](https://github.com/xmake-io/xmake/issues/1578): 改进 add_repositories 去更好地支持相对路径 +* [#1582](https://github.com/xmake-io/xmake/issues/1582): 改进安装和 os.cp 支持符号链接 ### Bugs 修复 diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index e9f403d92..ea913b977 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -49,7 +49,7 @@ os.SYSERR_NOT_PERM = 1 os.SYSERR_NOT_FILEDIR = 2 -- copy single file or directory -function os._cp(src, dst, rootdir) +function os._cp(src, dst, rootdir, opt) -- check assert(src and dst) @@ -65,7 +65,7 @@ function os._cp(src, dst, rootdir) end -- is file? - if os.isfile(src) then + if os.isfile(src) or os.islink(src) then -- the destination is directory? append the filename if os.isdir(dst) or path.islastsep(dst) then @@ -76,9 +76,17 @@ function os._cp(src, dst, rootdir) end end - -- copy file - if not os.cpfile(src, dst) then - return false, string.format("cannot copy file %s to %s, %s", src, dst, os.strerror()) + -- link file if reserve symlink + if opt and opt.symlink and os.islink(src) then + local reallink = os.readlink(src) + if not os.link(reallink, dst) then + return false, string.format("cannot link %s(%s) to %s, %s", src, reallink, dst, os.strerror()) + end + else + -- copy file + if not os.cpfile(src, dst) then + return false, string.format("cannot copy file %s to %s, %s", src, dst, os.strerror()) + end end -- is directory? elseif os.isdir(src) then @@ -386,7 +394,7 @@ function os.filedirs(pattern, callback) end -- copy files or directories and we can reserve the source directory structure --- e.g. os.cp("src/**.h", "/tmp/", {rootdir = "src"}) +-- e.g. os.cp("src/**.h", "/tmp/", {rootdir = "src", symlink = true}) function os.cp(srcpath, dstpath, opt) -- check arguments @@ -405,10 +413,10 @@ function os.cp(srcpath, dstpath, opt) -- copy files or directories local srcpathes = os._match_wildcard_pathes(srcpath) if type(srcpathes) == "string" then - return os._cp(srcpathes, dstpath, rootdir) + return os._cp(srcpathes, dstpath, rootdir, opt) else for _, _srcpath in ipairs(srcpathes) do - local ok, errors = os._cp(_srcpath, dstpath, rootdir) + local ok, errors = os._cp(_srcpath, dstpath, rootdir, opt) if not ok then return false, errors end diff --git a/xmake/modules/target/action/install/unix.lua b/xmake/modules/target/action/install/unix.lua index bd2a1cdb1..2f55dbd3b 100644 --- a/xmake/modules/target/action/install/unix.lua +++ b/xmake/modules/target/action/install/unix.lua @@ -43,7 +43,17 @@ function _install_shared_for_package(target, pkg, outputdir) if os.isfile(path.join(outputdir, soname)) then wprint("'%s' already exists in install dir, overwriting it from package(%s).", soname, pkg:name()) end - os.vcp(sopath, outputdir) + -- we need reserve symlink + -- @see https://github.com/xmake-io/xmake/issues/1582 + os.vcp(sopath, outputdir, {symlink = true}) + -- copy real file of symlink + if os.islink(sopath) then + local realpath = os.readlink(sopath) + if not path.is_absolute(realpath) then + realpath = path.absolute(realpath, path.directory(sopath)) + end + os.vcp(realpath, outputdir) + end end end end -- cgit v1.3.1 From bc582fd4bdaee3add88a4e15f1764c7e11eec41c Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 21 Aug 2021 00:07:26 +0800 Subject: improve installation --- xmake/modules/package/manager/xmake/find_package.lua | 6 ++++-- xmake/modules/target/action/install/unix.lua | 10 +--------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/xmake/modules/package/manager/xmake/find_package.lua b/xmake/modules/package/manager/xmake/find_package.lua index a44744ad2..0b043cc2f 100644 --- a/xmake/modules/package/manager/xmake/find_package.lua +++ b/xmake/modules/package/manager/xmake/find_package.lua @@ -83,12 +83,14 @@ function _find_package_from_repo(name, opt) if file:endswith(".lib") or file:endswith(".a") then found = true table.insert(links, target.linkname(path.filename(file))) + table.insert(libfiles, file) end end if not found then for _, file in ipairs(os.files(path.join(installdir, "lib", "*"))) do - if file:endswith(".so") or file:endswith(".dylib") then + if file:endswith(".so") or file:match(".+%.so%..+$") or file:endswith(".dylib") then -- maybe symlink to libxxx.so.1 table.insert(links, target.linkname(path.filename(file))) + table.insert(libfiles, file) end end end @@ -139,7 +141,7 @@ function _find_package_from_repo(name, opt) result.links = table.unique(result.links) end if result.libfiles then - result.libfiles = table.join(result.libfiles, libfiles) + result.libfiles = table.unique(table.join(result.libfiles, libfiles)) end -- inherit the other prefix variables diff --git a/xmake/modules/target/action/install/unix.lua b/xmake/modules/target/action/install/unix.lua index 2f55dbd3b..ae06ed3bc 100644 --- a/xmake/modules/target/action/install/unix.lua +++ b/xmake/modules/target/action/install/unix.lua @@ -38,7 +38,7 @@ end -- install shared libraries for package function _install_shared_for_package(target, pkg, outputdir) for _, sopath in ipairs(table.wrap(pkg:get("libfiles"))) do - if sopath:endswith(".so") or sopath:endswith(".dylib") then + if sopath:endswith(".so") or sopath:match(".+%.so%..+$") or sopath:endswith(".dylib") then local soname = path.filename(sopath) if os.isfile(path.join(outputdir, soname)) then wprint("'%s' already exists in install dir, overwriting it from package(%s).", soname, pkg:name()) @@ -46,14 +46,6 @@ function _install_shared_for_package(target, pkg, outputdir) -- we need reserve symlink -- @see https://github.com/xmake-io/xmake/issues/1582 os.vcp(sopath, outputdir, {symlink = true}) - -- copy real file of symlink - if os.islink(sopath) then - local realpath = os.readlink(sopath) - if not path.is_absolute(realpath) then - realpath = path.absolute(realpath, path.directory(sopath)) - end - os.vcp(realpath, outputdir) - end end end end -- cgit v1.3.1 From a735ccb009c12980748b6ec497266dd03738795e Mon Sep 17 00:00:00 2001 From: ImperatorS79 Date: Fri, 20 Aug 2021 18:33:49 +0200 Subject: Update find_package.lua --- .../package/manager/pacman/find_package.lua | 178 +++++++++++---------- 1 file changed, 93 insertions(+), 85 deletions(-) diff --git a/xmake/modules/package/manager/pacman/find_package.lua b/xmake/modules/package/manager/pacman/find_package.lua index a31f4787a..21340171b 100644 --- a/xmake/modules/package/manager/pacman/find_package.lua +++ b/xmake/modules/package/manager/pacman/find_package.lua @@ -23,6 +23,76 @@ import("core.base.option") import("lib.detect.find_tool") import("package.manager.pkgconfig.find_package", {alias = "find_package_from_pkgconfig"}) +-- get result from list of file inside pacman package +function _find_package_from_list(list, opt, cygpath) + local result = { + includedirs = {}, + linkdirs = {}, + links = {}, + version = nil + } + + -- iterate over each file path inside the pacman package + for _, line in ipairs(list:split('\n', {plain = true})) do -- on msys cygpath should be used to convert local path to windows path + line = line:trim():split('%s+')[2] + if line:find("/include/", 1, true) and (line:endswith(".h") or line:endswith(".hpp")) then + local hpath = line + if opt.plat == "mingw" then + hpath = os.iorunv(cygpath.program, {"--windows", line}) + + if(opt.arch == "x86_64") then + local basehpath = os.iorunv(cygpath.program, {"--windows", "/mingw64/include"}) + table.insert(result.includedirs, basehpath) + else + local basehpath = os.iorunv(cygpath.program, {"--windows", "/mingw32/include"}) + table.insert(result.includedirs, basehpath) + end + end + table.insert(result.includedirs, path.directory(hpath)) + -- revove lib and .a, .dll.a and .so to have the links + elseif line:endswith(".dll.a") then -- only for mingw + local apath = os.iorunv(cygpath.program, {"--windows", line}) + table.insert(result.linkdirs, path.directory(apath)) + apath = path.filename(apath) + if apath:startswith("lib") then + apath = apath:sub(4, apath:len()) + end + table.insert(result.links, apath:sub(1, apath:len() - 7)) + elseif line:endswith(".so") then + local apath = line + table.insert(result.linkdirs, path.directory(apath)) + apath = path.filename(apath) + if apath:startswith("lib") then + apath = apath:sub(4, apath:len()) + end + table.insert(result.links, apath:sub(1, apath:len() - 4)) + elseif line:endswith(".a") then + local apath = line + if opt.plat == "mingw" then + apath = os.iorunv(cygpath.program, {"--windows", line}) + end + table.insert(result.linkdirs, path.directory(apath)) + apath = path.filename(apath) + if apath:startswith("lib") then + apath = apath:sub(4, apath:len()) + end + table.insert(result.links, apath:sub(1, apath:len() - 3)) + end + end + + result.includedirs = table.unique(result.includedirs) + result.linkdirs = table.unique(result.linkdirs) + result.links = table.unique(result.links) + + -- use pacman package version as version + local pacmanversion = try { function() return os.iorunv(pacman.program, {"-Q", name}) end } + if pacmanversion then + result.version = pacmanversion:trim():split('%s+')[2] + end + + return result +end + -- find package from the system directories -- -- @param name the package name @@ -56,7 +126,7 @@ function main(name, opt) if not list then return end - + -- parse package files list local linkdirs = {} local has_includes = false @@ -74,113 +144,51 @@ function main(name, opt) end -- we iterate over each pkgconfig file to extract the required data - local result = {} - local myIncludedirs = {} - local myLinkdirs = {} - local myLinks = {} - myVersion = "0" + local result = { + includedirs = {}, + linkdirs = {}, + links = {}, + version = nil + } + local foundPC = false + for key, file in pairs(pkgconfig_files) do pkgconfig_file = file local pkgconfig_dir = path.directory(pkgconfig_file) local pkgconfig_name = path.basename(pkgconfig_file) linkdirs = table.unique(linkdirs) includedirs = table.unique(includedirs) - local myResult = {} - myResult = find_package_from_pkgconfig(pkgconfig_name, {configdirs = pkgconfig_dir, linkdirs = linkdirs}) + local pcresult = {} + pcresult = find_package_from_pkgconfig(pkgconfig_name, {configdirs = pkgconfig_dir, linkdirs = linkdirs}) -- the pkgconfig file has been parse successfully - if myResult ~= nil then - for _, locIncludeDir in pairs(myResult.includedirs) do - table.insert(myIncludedirs, locIncludeDir) + if pcresult ~= nil then + for _, locincludedir in pairs(pcresult.includedirs) do + table.insert(result.includedirs, locincludedir) end - for _, locLinkDir in pairs(myResult.linkdirs) do - table.insert(myLinkdirs, locLinkDir) + for _, loclinkdir in pairs(pcresult.linkdirs) do + table.insert(result.linkdirs, loclinkdir) end - for _, locLink in pairs(myResult.links) do - table.insert(myLinks, locLink) + for _, loclink in pairs(pcresult.links) do + table.insert(result.links, loclink) end -- version should be the same if a pacman package contains multiples .pc - myVersion = myResult.version + result.version = pcresult.version foundPC = true end end if foundPC == true then - myIncludedirs = table.unique(myIncludedirs) - myLinkdirs = table.unique(myLinkdirs) - myLinks = table.unique(myLinks) - - result.includedirs = myIncludedirs - result.linkdirs = myLinkdirs - result.links = myLinks - result.version = myVersion + result.includedirs = table.unique(result.includedirs) + result.linkdirs = table.unique(result.linkdirs) + result.links = table.unique(result.links) else -- if there is no .pc, we parse the package content to obtain the data we want - for _, line in ipairs(list:split('\n', {plain = true})) do -- on msys cygpath should be use to convert local path to windows path - line = line:trim():split('%s+')[2] - if line:find("/include/", 1, true) and (line:endswith(".h") or line:endswith(".hpp")) then - local hPath = line - if opt.plat == "mingw" then - hPath = os.iorunv(cygpath.program, {"--windows", line}) - end - table.insert(myIncludedirs, path.directory(hPath)) - if(opt.arch == "x86_64") then - local baseHPath = os.iorunv(cygpath.program, {"--windows", "/mingw64/include"}) - table.insert(myIncludedirs, baseHPath) - else - local baseHPath = os.iorunv(cygpath.program, {"--windows", "/mingw32/include"}) - table.insert(myIncludedirs, baseHPath) - end - -- revove lib and .a, .dll.a and .so to have the links - elseif line:endswith(".dll.a") then - local aPath = os.iorunv(cygpath.program, {"--windows", line}) - table.insert(myLinkdirs, path.directory(aPath)) - aPath = path.filename(aPath) - if aPath:startswith("lib") then - aPath = aPath:sub(4, aPath:len()) - end - table.insert(myLinks, aPath:sub(1, aPath:len() - 7)) - elseif line:endswith(".so") then - local aPath = line - table.insert(myLinkdirs, path.directory(aPath)) - aPath = path.filename(aPath) - if aPath:startswith("lib") then - aPath = aPath:sub(4, aPath:len()) - end - table.insert(myLinks, aPath:sub(1, aPath:len() - 4)) - elseif line:endswith(".a") then - local aPath = line - if opt.plat == "mingw" then - aPath = os.iorunv(cygpath.program, {"--windows", line}) - end - aPath = path.filename(aPath) - if aPath:startswith("lib") then - aPath = aPath:sub(4, aPath:len()) - end - table.insert(myLinks, aPath:sub(1, aPath:len() - 3)) - end - end - - myLinkdirs = table.unique(myLinkdirs) - myLinks = table.unique(myLinks) - myIncludedirs = table.unique(myIncludedirs) - - -- use pacman package version as version - local myVersion = "0" - local nameVersion = try { function() return os.iorunv(pacman.program, {"-Q", name}) end } - if nameVersion then - myVersion = nameVersion:trim():split('%s+')[2] - end - - result = {} - result.includedirs = myIncludedirs - result.linkdirs = myLinkdirs - result.links = myLinks - result.version = myVersion + result = _find_package_from_list(list, opt, cygpath) end return result -- cgit v1.3.1 From 875fdfe22fb96ff5ef2b654b276acd363f2b906b Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 21 Aug 2021 10:16:45 +0800 Subject: improve lock packages --- .../package/toolchain_muslcc/xmake-requires.lock | 28 ++++++++--------- .../action/require/impl/install_packages.lua | 4 +-- .../private/action/require/impl/lock_packages.lua | 6 +++- .../private/action/require/impl/repository.lua | 36 ++++++++++++++-------- 4 files changed, 43 insertions(+), 31 deletions(-) diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock index d31ecd965..764165028 100644 --- a/tests/projects/package/toolchain_muslcc/xmake-requires.lock +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -4,15 +4,15 @@ }, ["autoconf#ddbdd8b8f76d455a8c0ef45fffe37160"] = { arch = "x86_64", - buildhash = "01974c48f52d4d658f58852351743754", + buildhash = "cd4169a7cb484832b2f70d2174072ca2", name = "autoconf", plat = "macosx", repo = { branch = "master", - commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", url = "https://gitee.com/tboox/xmake-repo.git" }, - version = "2.69" + version = "2.71" }, ["automake#ddbdd8b8f76d455a8c0ef45fffe37160"] = { arch = "x86_64", @@ -21,7 +21,7 @@ plat = "macosx", repo = { branch = "master", - commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.16.1" @@ -33,7 +33,7 @@ plat = "macosx", repo = { branch = "master", - commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "3.21.0" @@ -45,7 +45,7 @@ plat = "macosx", repo = { branch = "master", - commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "6.2.1" @@ -57,7 +57,7 @@ plat = "macosx", repo = { branch = "master", - commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "0.22" @@ -69,7 +69,7 @@ plat = "cross", repo = { branch = "master", - commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "v1.3.4" @@ -81,7 +81,7 @@ plat = "cross", repo = { branch = "master", - commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "2.2.0" @@ -93,7 +93,7 @@ plat = "macosx", repo = { branch = "master", - commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "2.4.6" @@ -105,7 +105,7 @@ plat = "macosx", repo = { branch = "master", - commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.4.19" @@ -117,7 +117,7 @@ plat = "macosx", repo = { branch = "master", - commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "20210202" @@ -129,7 +129,7 @@ plat = "macosx", repo = { branch = "master", - commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "0.29.2" @@ -141,7 +141,7 @@ plat = "cross", repo = { branch = "master", - commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.2.11" diff --git a/xmake/modules/private/action/require/impl/install_packages.lua b/xmake/modules/private/action/require/impl/install_packages.lua index 75ca4414e..79fb71c3f 100644 --- a/xmake/modules/private/action/require/impl/install_packages.lua +++ b/xmake/modules/private/action/require/impl/install_packages.lua @@ -603,9 +603,7 @@ function main(requires, opt) register_packages(packages) -- lock packages - if #packages_install > 0 then - lock_packages(packages) - end + lock_packages(packages) return packages end diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua index 18dabcac4..05debf6f2 100644 --- a/xmake/modules/private/action/require/impl/lock_packages.lua +++ b/xmake/modules/private/action/require/impl/lock_packages.lua @@ -43,7 +43,11 @@ function _lock_package(instance) result.branch = instance:branch() result.tag = instance:tag() if repo then - local lastcommit = git.lastcommit({repodir = repo:directory()}) + local lastcommit = try {function() + if os.isdir(path.join(repo:directory(), ".git")) then + return git.lastcommit({repodir = repo:directory()}) + end + end} result.repo = {url = repo:url(), commit = lastcommit, branch = repo:branch()} end return result diff --git a/xmake/modules/private/action/require/impl/repository.lua b/xmake/modules/private/action/require/impl/repository.lua index 528aebc54..1acbfb618 100644 --- a/xmake/modules/private/action/require/impl/repository.lua +++ b/xmake/modules/private/action/require/impl/repository.lua @@ -38,8 +38,15 @@ function _get_packagedir_from_locked_repo(packagename, locked_repo) end local reponame = hash.uuid(locked_repo.url):gsub("%-", ""):lower() .. ".lock" + -- get local repodir + local repodir_local + if os.isdir(locked_repo.url) then + repodir_local = locked_repo.url + else + repodir_local = path.join(config.directory(), "repositories", reponame) + end + -- clone repository to local - local repodir_local = path.join(config.directory(), "repositories", reponame) if not os.isdir(repodir_local) then if repodir_global then git.clone(repodir_global, {verbose = option.get("verbose"), outputdir = repodir_local}) @@ -51,17 +58,20 @@ function _get_packagedir_from_locked_repo(packagename, locked_repo) end end - -- try checkout to the given commit - local ok = try {function () git.checkout(locked_repo.commit, {verbose = option.get("verbose"), repodir = repodir_local}); return true end} - if not ok then - if global.get("network") ~= "private" then - -- pull the latest commit - git.pull({verbose = option.get("verbose"), remote = locked_repo.url, branch = locked_repo.branch, repodir = repodir_local}) - -- re-checkout to the given commit - ok = try {function () git.checkout(locked_repo.commit, {verbose = option.get("verbose"), repodir = repodir_local}); return true end} - else - wprint("we cannot lock repository(%s) in private network mode!", locked_repo.url) - return + -- lock commit + if locked_repo.commit and os.isdir(path.join(repodir_local, ".git")) then + -- try checkout to the given commit + local ok = try {function () git.checkout(locked_repo.commit, {verbose = option.get("verbose"), repodir = repodir_local}); return true end} + if not ok then + if global.get("network") ~= "private" then + -- pull the latest commit + git.pull({verbose = option.get("verbose"), remote = locked_repo.url, branch = locked_repo.branch, repodir = repodir_local}) + -- re-checkout to the given commit + ok = try {function () git.checkout(locked_repo.commit, {verbose = option.get("verbose"), repodir = repodir_local}); return true end} + else + wprint("we cannot lock repository(%s) in private network mode!", locked_repo.url) + return + end end end @@ -118,7 +128,7 @@ function packagedir(packagename, opt) local cachekey = packagename local locked_repo = opt.locked_repo if locked_repo then - cachekey = cachekey .. locked_repo.url .. locked_repo.commit .. (locked_repo.branch or "") + cachekey = cachekey .. locked_repo.url .. (locked_repo.commit or "") .. (locked_repo.branch or "") end local packagedirs = _g._PACKAGEDIRS if not packagedirs then -- cgit v1.3.1 From d5d7448a1d7622ce6b82ebff3ddbea8a7cdd31e5 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 21 Aug 2021 10:17:15 +0800 Subject: format code --- xmake/modules/private/action/require/impl/lock_packages.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua index 05debf6f2..02bf64a9b 100644 --- a/xmake/modules/private/action/require/impl/lock_packages.lua +++ b/xmake/modules/private/action/require/impl/lock_packages.lua @@ -48,7 +48,7 @@ function _lock_package(instance) return git.lastcommit({repodir = repo:directory()}) end end} - result.repo = {url = repo:url(), commit = lastcommit, branch = repo:branch()} + result.repo = {url = repo:url(), commit = lastcommit, branch = repo:branch()} end return result end -- cgit v1.3.1 From e8facd596d72db42a0a20233cde0d543d9384e9c Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 21 Aug 2021 11:12:41 +0800 Subject: improve requires.lock --- xmake/modules/private/action/require/impl/lock_packages.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua index 02bf64a9b..c891d73cc 100644 --- a/xmake/modules/private/action/require/impl/lock_packages.lua +++ b/xmake/modules/private/action/require/impl/lock_packages.lua @@ -56,7 +56,8 @@ end -- lock all required packages function main(packages) if project.policy("package.requires_lock") then - local results = {__meta__ = {}} + local results = os.isfile(project.requireslock()) and io.load(project.requireslock()) or {} + results.__meta__ = results.__meta__ or {} results.__meta__.version = project.requireslock_version() for _, instance in ipairs(packages) do local packagelock_key = _get_packagelock_key(instance) -- cgit v1.3.1 From 03edbeb91a3b4e5d6d113949d433424497431613 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 21 Aug 2021 15:50:39 +0800 Subject: improve requireslock format --- .../package/multiconfig/xmake-requires.lock | 59 +++--- .../package/toolchain_muslcc/xmake-requires.lock | 230 +++++++++------------ .../private/action/require/impl/lock_packages.lua | 9 +- .../private/action/require/impl/package.lua | 7 +- 4 files changed, 135 insertions(+), 170 deletions(-) diff --git a/tests/projects/package/multiconfig/xmake-requires.lock b/tests/projects/package/multiconfig/xmake-requires.lock index e8621f5b3..6b10a5235 100644 --- a/tests/projects/package/multiconfig/xmake-requires.lock +++ b/tests/projects/package/multiconfig/xmake-requires.lock @@ -2,40 +2,33 @@ __meta__ = { version = "1.0" }, - ["zlib#ddbdd8b8f76d455a8c0ef45fffe37160"] = { - arch = "x86_64", - buildhash = "b76a297309d14c09b42cfe3927260a51", - name = "zlib", - plat = "macosx", - repo = { - branch = "master", - commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", - url = "https://gitee.com/tboox/xmake-repo.git" + ["macosx|x86_64"] = { + ["zlib#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + buildhash = "b76a297309d14c09b42cfe3927260a51", + repo = { + branch = "master", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "1.2.11" }, - version = "1.2.11" - }, - ["zlib~debug#d72a8a937b694e449bce540c8eb65a8a"] = { - arch = "x86_64", - buildhash = "e6a6fa6a86ad4fc7ae3c2cf7c60cc084", - name = "zlib", - plat = "macosx", - repo = { - branch = "master", - commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "1.2.11" - }, - ["zlib~shared#b286744a1898416faad2e5cab0104b2f"] = { - arch = "x86_64", - buildhash = "8e5b898b0f344715bac89cc6a1577506", - name = "zlib", - plat = "macosx", - repo = { - branch = "master", - commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9", - url = "https://gitee.com/tboox/xmake-repo.git" + ["zlib~debug#d72a8a937b694e449bce540c8eb65a8a"] = { + buildhash = "e6a6fa6a86ad4fc7ae3c2cf7c60cc084", + repo = { + branch = "master", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "1.2.11" }, - version = "1.2.11" + ["zlib~shared#b286744a1898416faad2e5cab0104b2f"] = { + buildhash = "8e5b898b0f344715bac89cc6a1577506", + repo = { + branch = "master", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "1.2.11" + } } } \ No newline at end of file diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock index 764165028..906fba5ed 100644 --- a/tests/projects/package/toolchain_muslcc/xmake-requires.lock +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -2,148 +2,114 @@ __meta__ = { version = "1.0" }, - ["autoconf#ddbdd8b8f76d455a8c0ef45fffe37160"] = { - arch = "x86_64", - buildhash = "cd4169a7cb484832b2f70d2174072ca2", - name = "autoconf", - plat = "macosx", - repo = { - branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", - url = "https://gitee.com/tboox/xmake-repo.git" + ["macosx|x86_64"] = { + ["autoconf#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + buildhash = "cd4169a7cb484832b2f70d2174072ca2", + repo = { + branch = "master", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "2.71" }, - version = "2.71" - }, - ["automake#ddbdd8b8f76d455a8c0ef45fffe37160"] = { - arch = "x86_64", - buildhash = "7a090c93706241f983f0d821a162e8a5", - name = "automake", - plat = "macosx", - repo = { - branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "1.16.1" - }, - ["cmake#ddbdd8b8f76d455a8c0ef45fffe37160"] = { - arch = "x86_64", - buildhash = "a6d18f8c0bf347d980f8bb762583c91a", - name = "cmake", - plat = "macosx", - repo = { - branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", - url = "https://gitee.com/tboox/xmake-repo.git" + ["automake#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + buildhash = "7a090c93706241f983f0d821a162e8a5", + repo = { + branch = "master", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "1.16.1" }, - version = "3.21.0" - }, - ["gmp#ddbdd8b8f76d455a8c0ef45fffe37160"] = { - arch = "x86_64", - buildhash = "7dd9c224447e46698ac73d29f58b1d73", - name = "gmp", - plat = "macosx", - repo = { - branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", - url = "https://gitee.com/tboox/xmake-repo.git" + ["cmake#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + buildhash = "a6d18f8c0bf347d980f8bb762583c91a", + repo = { + branch = "master", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "3.21.0" }, - version = "6.2.1" - }, - ["libisl 0.22#3dd996fa365042e39791030c4e1cad52"] = { - arch = "x86_64", - buildhash = "f649e1fb365e442e8f79f372fd91483b", - name = "libisl", - plat = "macosx", - repo = { - branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", - url = "https://gitee.com/tboox/xmake-repo.git" + ["gmp#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + buildhash = "7dd9c224447e46698ac73d29f58b1d73", + repo = { + branch = "master", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "6.2.1" }, - version = "0.22" - }, - ["libogg#ddbdd8b8f76d455a8c0ef45fffe37160"] = { - arch = "arm", - buildhash = "d894fc29f2fb4c45a0f48bc2c6ece273", - name = "libogg", - plat = "cross", - repo = { - branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", - url = "https://gitee.com/tboox/xmake-repo.git" + ["libisl 0.22#3dd996fa365042e39791030c4e1cad52"] = { + buildhash = "f649e1fb365e442e8f79f372fd91483b", + repo = { + branch = "master", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "0.22" }, - version = "v1.3.4" - }, - ["libplist#ddbdd8b8f76d455a8c0ef45fffe37160"] = { - arch = "arm", - buildhash = "0c01b22920be4876b1de74629194eb8f", - name = "libplist", - plat = "cross", - repo = { - branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", - url = "https://gitee.com/tboox/xmake-repo.git" + ["libogg#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + buildhash = "d894fc29f2fb4c45a0f48bc2c6ece273", + repo = { + branch = "master", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "v1.3.4" }, - version = "2.2.0" - }, - ["libtool#ddbdd8b8f76d455a8c0ef45fffe37160"] = { - arch = "x86_64", - buildhash = "64584ec84a4743ecb740b598b263ffa6", - name = "libtool", - plat = "macosx", - repo = { - branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", - url = "https://gitee.com/tboox/xmake-repo.git" + ["libplist#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + buildhash = "0c01b22920be4876b1de74629194eb8f", + repo = { + branch = "master", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "2.2.0" }, - version = "2.4.6" - }, - ["m4#ddbdd8b8f76d455a8c0ef45fffe37160"] = { - arch = "x86_64", - buildhash = "fd0e83e5759b442a970327ebb1c89793", - name = "m4", - plat = "macosx", - repo = { - branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", - url = "https://gitee.com/tboox/xmake-repo.git" + ["libtool#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + buildhash = "64584ec84a4743ecb740b598b263ffa6", + repo = { + branch = "master", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "2.4.6" }, - version = "1.4.19" - }, - ["muslcc#ddbdd8b8f76d455a8c0ef45fffe37160"] = { - arch = "x86_64", - buildhash = "11062c09ebeb484594488ad73ddbcd1f", - name = "muslcc", - plat = "macosx", - repo = { - branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", - url = "https://gitee.com/tboox/xmake-repo.git" + ["m4#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + buildhash = "fd0e83e5759b442a970327ebb1c89793", + repo = { + branch = "master", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "1.4.19" }, - version = "20210202" - }, - ["pkg-config#ddbdd8b8f76d455a8c0ef45fffe37160"] = { - arch = "x86_64", - buildhash = "84fd7f9b9f7a47709512cfc85cd9e5f7", - name = "pkg-config", - plat = "macosx", - repo = { - branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", - url = "https://gitee.com/tboox/xmake-repo.git" + ["muslcc#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + buildhash = "11062c09ebeb484594488ad73ddbcd1f", + repo = { + branch = "master", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "20210202" }, - version = "0.29.2" - }, - ["zlib#ddbdd8b8f76d455a8c0ef45fffe37160"] = { - arch = "arm", - buildhash = "be90a245b8bb48e6b08a1a15bdcad467", - name = "zlib", - plat = "cross", - repo = { - branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", - url = "https://gitee.com/tboox/xmake-repo.git" + ["pkg-config#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + buildhash = "84fd7f9b9f7a47709512cfc85cd9e5f7", + repo = { + branch = "master", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "0.29.2" }, - version = "1.2.11" + ["zlib#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + buildhash = "be90a245b8bb48e6b08a1a15bdcad467", + repo = { + branch = "master", + commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "1.2.11" + } } } \ No newline at end of file diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua index c891d73cc..3eba5d00f 100644 --- a/xmake/modules/private/action/require/impl/lock_packages.lua +++ b/xmake/modules/private/action/require/impl/lock_packages.lua @@ -35,9 +35,6 @@ end function _lock_package(instance) local result = {} local repo = instance:repo() - result.name = instance:name() - result.plat = instance:plat() - result.arch = instance:arch() result.version = instance:version_str() result.buildhash = instance:buildhash() result.branch = instance:branch() @@ -56,12 +53,16 @@ end -- lock all required packages function main(packages) if project.policy("package.requires_lock") then + local plat = config.plat() or os.subhost() + local arch = config.arch() or so.subarch() + local key = plat .. "|" .. arch local results = os.isfile(project.requireslock()) and io.load(project.requireslock()) or {} results.__meta__ = results.__meta__ or {} results.__meta__.version = project.requireslock_version() + results[key] = {} for _, instance in ipairs(packages) do local packagelock_key = _get_packagelock_key(instance) - results[packagelock_key] = _lock_package(instance) + results[key][packagelock_key] = _lock_package(instance) end io.writefile(project.requireslock(), string.serialize(results, {orderkeys = true})) end diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 95a54a008..d5d893658 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -224,7 +224,12 @@ function _get_locked_requires(requirekey) _memcache():set("requireslock", requireslock or false) end if requireslock then - return requireslock[requirekey], requireslock.__meta__.version + local plat = config.plat() or os.subhost() + local arch = config.arch() or so.subarch() + local key = plat .. "|" .. arch + if requireslock[key] then + return requireslock[key][requirekey], requireslock.__meta__.version + end end end -- cgit v1.3.1 From 8b3f30b4200b371e118bd31857d1d48c17b2969d Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 21 Aug 2021 16:08:29 +0800 Subject: improve to get repo commit --- .../package/toolchain_muslcc/xmake-requires.lock | 28 +++++++++++----------- xmake/core/package/package.lua | 1 + xmake/core/package/repository.lua | 10 ++++++++ .../private/action/require/impl/lock_packages.lua | 13 ++++++---- .../private/action/require/impl/repository.lua | 14 ++++++++++- 5 files changed, 46 insertions(+), 20 deletions(-) diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock index 906fba5ed..4379fdf79 100644 --- a/tests/projects/package/toolchain_muslcc/xmake-requires.lock +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -7,25 +7,25 @@ buildhash = "cd4169a7cb484832b2f70d2174072ca2", repo = { branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + commit = "4498f11267de5112199152ab030ed139c985ad5a", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "2.71" }, ["automake#ddbdd8b8f76d455a8c0ef45fffe37160"] = { - buildhash = "7a090c93706241f983f0d821a162e8a5", + buildhash = "5b4ee7b727764ece8aa3e149603cfc7a", repo = { branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", url = "https://gitee.com/tboox/xmake-repo.git" }, - version = "1.16.1" + version = "1.16.4" }, ["cmake#ddbdd8b8f76d455a8c0ef45fffe37160"] = { buildhash = "a6d18f8c0bf347d980f8bb762583c91a", repo = { branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + commit = "4498f11267de5112199152ab030ed139c985ad5a", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "3.21.0" @@ -34,7 +34,7 @@ buildhash = "7dd9c224447e46698ac73d29f58b1d73", repo = { branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "6.2.1" @@ -43,7 +43,7 @@ buildhash = "f649e1fb365e442e8f79f372fd91483b", repo = { branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "0.22" @@ -52,7 +52,7 @@ buildhash = "d894fc29f2fb4c45a0f48bc2c6ece273", repo = { branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "v1.3.4" @@ -61,7 +61,7 @@ buildhash = "0c01b22920be4876b1de74629194eb8f", repo = { branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "2.2.0" @@ -70,7 +70,7 @@ buildhash = "64584ec84a4743ecb740b598b263ffa6", repo = { branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "2.4.6" @@ -79,7 +79,7 @@ buildhash = "fd0e83e5759b442a970327ebb1c89793", repo = { branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.4.19" @@ -88,7 +88,7 @@ buildhash = "11062c09ebeb484594488ad73ddbcd1f", repo = { branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "20210202" @@ -97,7 +97,7 @@ buildhash = "84fd7f9b9f7a47709512cfc85cd9e5f7", repo = { branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "0.29.2" @@ -106,7 +106,7 @@ buildhash = "be90a245b8bb48e6b08a1a15bdcad467", repo = { branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.2.11" diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index d68f782e4..a2b4163e5 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -628,6 +628,7 @@ function _instance:manifest_save() manifest.repo.name = repo:name() manifest.repo.url = repo:url() manifest.repo.branch = repo:branch() + manifest.repo.commit = repo:commit() end -- save manifest diff --git a/xmake/core/package/repository.lua b/xmake/core/package/repository.lua index 6485b426f..fd9a275f1 100644 --- a/xmake/core/package/repository.lua +++ b/xmake/core/package/repository.lua @@ -74,6 +74,16 @@ function _instance:branch() return self._BRANCH end +-- get the current commit +function _instance:commit() + return self._COMMIT +end + +-- set the commit +function _instance:commit_set(commit) + self._COMMIT = commit +end + -- is global repository? function _instance:is_global() return self._IS_GLOBAL diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua index 3eba5d00f..0e340e602 100644 --- a/xmake/modules/private/action/require/impl/lock_packages.lua +++ b/xmake/modules/private/action/require/impl/lock_packages.lua @@ -40,11 +40,14 @@ function _lock_package(instance) result.branch = instance:branch() result.tag = instance:tag() if repo then - local lastcommit = try {function() - if os.isdir(path.join(repo:directory(), ".git")) then - return git.lastcommit({repodir = repo:directory()}) - end - end} + local lastcommit + local manifest = instance:manifest_load() + if manifest and manifest.repo then + lastcommit = manifest.repo.commit + end + if not lastcommit then + lastcommit = repo:commit() + end result.repo = {url = repo:url(), commit = lastcommit, branch = repo:branch()} end return result diff --git a/xmake/modules/private/action/require/impl/repository.lua b/xmake/modules/private/action/require/impl/repository.lua index 1acbfb618..4f1e44f27 100644 --- a/xmake/modules/private/action/require/impl/repository.lua +++ b/xmake/modules/private/action/require/impl/repository.lua @@ -160,7 +160,19 @@ function packagedir(packagename, opt) end packagedirs[cachekey] = foundir or {} end - return foundir[1], foundir[2] + + -- save the current commit + local dir = foundir[1] + local repo = foundir[2] + if repo and not repo:commit() then + local lastcommit = try {function() + if os.isdir(path.join(repo:directory(), ".git")) then + return git.lastcommit({repodir = repo:directory()}) + end + end} + repo:commit_set(lastcommit) + end + return dir, repo end -- get artifacts manifest from repositories -- cgit v1.3.1 From 5e73fb8a86de1a6e10739d3c348d40607942c165 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 21 Aug 2021 16:38:06 +0800 Subject: improve requirekey --- .../package/toolchain_muslcc/xmake-requires.lock | 24 +++++++++++----------- .../private/action/require/impl/package.lua | 6 ++---- .../action/require/impl/utils/requirekey.lua | 3 +++ 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock index 4379fdf79..4a07f4618 100644 --- a/tests/projects/package/toolchain_muslcc/xmake-requires.lock +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -3,7 +3,7 @@ version = "1.0" }, ["macosx|x86_64"] = { - ["autoconf#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + ["autoconf#31fecfc4f022419cba33d3f9fc3cc783"] = { buildhash = "cd4169a7cb484832b2f70d2174072ca2", repo = { branch = "master", @@ -12,7 +12,7 @@ }, version = "2.71" }, - ["automake#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + ["automake#31fecfc4f022419cba33d3f9fc3cc783"] = { buildhash = "5b4ee7b727764ece8aa3e149603cfc7a", repo = { branch = "master", @@ -21,7 +21,7 @@ }, version = "1.16.4" }, - ["cmake#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + ["cmake#31fecfc4f022419cba33d3f9fc3cc783"] = { buildhash = "a6d18f8c0bf347d980f8bb762583c91a", repo = { branch = "master", @@ -30,7 +30,7 @@ }, version = "3.21.0" }, - ["gmp#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + ["gmp#31fecfc4f022419cba33d3f9fc3cc783"] = { buildhash = "7dd9c224447e46698ac73d29f58b1d73", repo = { branch = "master", @@ -39,7 +39,7 @@ }, version = "6.2.1" }, - ["libisl 0.22#3dd996fa365042e39791030c4e1cad52"] = { + ["libisl 0.22#671145042a9f4a96a5387ebff97a207d"] = { buildhash = "f649e1fb365e442e8f79f372fd91483b", repo = { branch = "master", @@ -48,7 +48,7 @@ }, version = "0.22" }, - ["libogg#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + ["libogg#31fecfc4f022419cba33d3f9fc3cc783"] = { buildhash = "d894fc29f2fb4c45a0f48bc2c6ece273", repo = { branch = "master", @@ -57,7 +57,7 @@ }, version = "v1.3.4" }, - ["libplist#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + ["libplist#31fecfc4f022419cba33d3f9fc3cc783"] = { buildhash = "0c01b22920be4876b1de74629194eb8f", repo = { branch = "master", @@ -66,7 +66,7 @@ }, version = "2.2.0" }, - ["libtool#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + ["libtool#31fecfc4f022419cba33d3f9fc3cc783"] = { buildhash = "64584ec84a4743ecb740b598b263ffa6", repo = { branch = "master", @@ -75,7 +75,7 @@ }, version = "2.4.6" }, - ["m4#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + ["m4#31fecfc4f022419cba33d3f9fc3cc783"] = { buildhash = "fd0e83e5759b442a970327ebb1c89793", repo = { branch = "master", @@ -84,7 +84,7 @@ }, version = "1.4.19" }, - ["muslcc#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + ["muslcc#31fecfc4f022419cba33d3f9fc3cc783"] = { buildhash = "11062c09ebeb484594488ad73ddbcd1f", repo = { branch = "master", @@ -93,7 +93,7 @@ }, version = "20210202" }, - ["pkg-config#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + ["pkg-config#31fecfc4f022419cba33d3f9fc3cc783"] = { buildhash = "84fd7f9b9f7a47709512cfc85cd9e5f7", repo = { branch = "master", @@ -102,7 +102,7 @@ }, version = "0.29.2" }, - ["zlib#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + ["zlib#31fecfc4f022419cba33d3f9fc3cc783"] = { buildhash = "be90a245b8bb48e6b08a1a15bdcad467", repo = { branch = "master", diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index d5d893658..55085d4f1 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -530,10 +530,8 @@ end -- get locked package key function _get_packagelock_key(requireinfo) - local plat = config.plat() or os.subhost() - local arch = config.arch() or os.subarch() local requirestr = requireinfo.originstr - local key = _get_requirekey(requireinfo, {hash = true, plat = plat, arch = arch}) + local key = _get_requirekey(requireinfo, {hash = true}) return string.format("%s#%s", requirestr, key) end @@ -648,7 +646,7 @@ function _load_package(packagename, requireinfo, opt) requireinfo.label = splitinfo[2] end - -- sve requirekey + -- save requirekey local requirekey = _get_packagelock_key(requireinfo) requireinfo.requirekey = requirekey diff --git a/xmake/modules/private/action/require/impl/utils/requirekey.lua b/xmake/modules/private/action/require/impl/utils/requirekey.lua index b07e4d50d..230a53acb 100644 --- a/xmake/modules/private/action/require/impl/utils/requirekey.lua +++ b/xmake/modules/private/action/require/impl/utils/requirekey.lua @@ -50,6 +50,9 @@ function main(requireinfo, opt) key = key .. ":" .. string.serialize(configs_order, true) end if opt.hash then + if key == "" then + key = "_" + end return hash.uuid(key):gsub("%-", ""):lower() else return key -- cgit v1.3.1 From 38c33512003a92adfc8cba6f50409d9e78df3868 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 21 Aug 2021 16:41:45 +0800 Subject: improve requirekey --- .../package/multiconfig/xmake-requires.lock | 12 +++++------ .../package/toolchain_muslcc/xmake-requires.lock | 24 +++++++++++----------- .../action/require/impl/utils/requirekey.lua | 4 ++-- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/projects/package/multiconfig/xmake-requires.lock b/tests/projects/package/multiconfig/xmake-requires.lock index 6b10a5235..e162c68b2 100644 --- a/tests/projects/package/multiconfig/xmake-requires.lock +++ b/tests/projects/package/multiconfig/xmake-requires.lock @@ -3,29 +3,29 @@ version = "1.0" }, ["macosx|x86_64"] = { - ["zlib#ddbdd8b8f76d455a8c0ef45fffe37160"] = { + ["zlib#31fecfc4"] = { buildhash = "b76a297309d14c09b42cfe3927260a51", repo = { branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.2.11" }, - ["zlib~debug#d72a8a937b694e449bce540c8eb65a8a"] = { + ["zlib~debug#55833b12"] = { buildhash = "e6a6fa6a86ad4fc7ae3c2cf7c60cc084", repo = { branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.2.11" }, - ["zlib~shared#b286744a1898416faad2e5cab0104b2f"] = { + ["zlib~shared#b6ab42cb"] = { buildhash = "8e5b898b0f344715bac89cc6a1577506", repo = { branch = "master", - commit = "d0e1f98585a4ec31b056fe3bda65a4fe37e0b375", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.2.11" diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock index 4a07f4618..8c55e49ea 100644 --- a/tests/projects/package/toolchain_muslcc/xmake-requires.lock +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -3,7 +3,7 @@ version = "1.0" }, ["macosx|x86_64"] = { - ["autoconf#31fecfc4f022419cba33d3f9fc3cc783"] = { + ["autoconf#31fecfc4"] = { buildhash = "cd4169a7cb484832b2f70d2174072ca2", repo = { branch = "master", @@ -12,7 +12,7 @@ }, version = "2.71" }, - ["automake#31fecfc4f022419cba33d3f9fc3cc783"] = { + ["automake#31fecfc4"] = { buildhash = "5b4ee7b727764ece8aa3e149603cfc7a", repo = { branch = "master", @@ -21,7 +21,7 @@ }, version = "1.16.4" }, - ["cmake#31fecfc4f022419cba33d3f9fc3cc783"] = { + ["cmake#31fecfc4"] = { buildhash = "a6d18f8c0bf347d980f8bb762583c91a", repo = { branch = "master", @@ -30,7 +30,7 @@ }, version = "3.21.0" }, - ["gmp#31fecfc4f022419cba33d3f9fc3cc783"] = { + ["gmp#31fecfc4"] = { buildhash = "7dd9c224447e46698ac73d29f58b1d73", repo = { branch = "master", @@ -39,7 +39,7 @@ }, version = "6.2.1" }, - ["libisl 0.22#671145042a9f4a96a5387ebff97a207d"] = { + ["libisl 0.22#67114504"] = { buildhash = "f649e1fb365e442e8f79f372fd91483b", repo = { branch = "master", @@ -48,7 +48,7 @@ }, version = "0.22" }, - ["libogg#31fecfc4f022419cba33d3f9fc3cc783"] = { + ["libogg#31fecfc4"] = { buildhash = "d894fc29f2fb4c45a0f48bc2c6ece273", repo = { branch = "master", @@ -57,7 +57,7 @@ }, version = "v1.3.4" }, - ["libplist#31fecfc4f022419cba33d3f9fc3cc783"] = { + ["libplist#31fecfc4"] = { buildhash = "0c01b22920be4876b1de74629194eb8f", repo = { branch = "master", @@ -66,7 +66,7 @@ }, version = "2.2.0" }, - ["libtool#31fecfc4f022419cba33d3f9fc3cc783"] = { + ["libtool#31fecfc4"] = { buildhash = "64584ec84a4743ecb740b598b263ffa6", repo = { branch = "master", @@ -75,7 +75,7 @@ }, version = "2.4.6" }, - ["m4#31fecfc4f022419cba33d3f9fc3cc783"] = { + ["m4#31fecfc4"] = { buildhash = "fd0e83e5759b442a970327ebb1c89793", repo = { branch = "master", @@ -84,7 +84,7 @@ }, version = "1.4.19" }, - ["muslcc#31fecfc4f022419cba33d3f9fc3cc783"] = { + ["muslcc#31fecfc4"] = { buildhash = "11062c09ebeb484594488ad73ddbcd1f", repo = { branch = "master", @@ -93,7 +93,7 @@ }, version = "20210202" }, - ["pkg-config#31fecfc4f022419cba33d3f9fc3cc783"] = { + ["pkg-config#31fecfc4"] = { buildhash = "84fd7f9b9f7a47709512cfc85cd9e5f7", repo = { branch = "master", @@ -102,7 +102,7 @@ }, version = "0.29.2" }, - ["zlib#31fecfc4f022419cba33d3f9fc3cc783"] = { + ["zlib#31fecfc4"] = { buildhash = "be90a245b8bb48e6b08a1a15bdcad467", repo = { branch = "master", diff --git a/xmake/modules/private/action/require/impl/utils/requirekey.lua b/xmake/modules/private/action/require/impl/utils/requirekey.lua index 230a53acb..d1792e50c 100644 --- a/xmake/modules/private/action/require/impl/utils/requirekey.lua +++ b/xmake/modules/private/action/require/impl/utils/requirekey.lua @@ -51,9 +51,9 @@ function main(requireinfo, opt) end if opt.hash then if key == "" then - key = "_" + key = "_" -- we need generate a fixed hash value end - return hash.uuid(key):gsub("%-", ""):lower() + return hash.uuid(key):split("-", {plain = true})[1]:lower() else return key end -- cgit v1.3.1 From b525616516d318aef0f7282528f848b4e1cc673f Mon Sep 17 00:00:00 2001 From: ImperatorS79 Date: Sat, 21 Aug 2021 14:42:30 +0200 Subject: Update find_package.lua --- .../package/manager/pacman/find_package.lua | 65 +++++++++++----------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/xmake/modules/package/manager/pacman/find_package.lua b/xmake/modules/package/manager/pacman/find_package.lua index 21340171b..848dec0ae 100644 --- a/xmake/modules/package/manager/pacman/find_package.lua +++ b/xmake/modules/package/manager/pacman/find_package.lua @@ -24,7 +24,7 @@ import("lib.detect.find_tool") import("package.manager.pkgconfig.find_package", {alias = "find_package_from_pkgconfig"}) -- get result from list of file inside pacman package -function _find_package_from_list(list, opt, cygpath) +function _find_package_from_list(list, opt, name, pacman) local result = { includedirs = {}, linkdirs = {}, @@ -32,15 +32,24 @@ function _find_package_from_list(list, opt, cygpath) version = nil } + local cygpath = nil + -- mingw + pacman = cygpath available + if is_subhost("msys") and opt.plat == "mingw" then + cygpath = find_tool("cygpath") + if not cygpath then + return nil + end + end + -- iterate over each file path inside the pacman package for _, line in ipairs(list:split('\n', {plain = true})) do -- on msys cygpath should be used to convert local path to windows path line = line:trim():split('%s+')[2] if line:find("/include/", 1, true) and (line:endswith(".h") or line:endswith(".hpp")) then local hpath = line - if opt.plat == "mingw" then + if is_subhost("msys") and opt.plat == "mingw" then hpath = os.iorunv(cygpath.program, {"--windows", line}) - if(opt.arch == "x86_64") then + if opt.arch == "x86_64" then local basehpath = os.iorunv(cygpath.program, {"--windows", "/mingw64/include"}) table.insert(result.includedirs, basehpath) else @@ -68,7 +77,7 @@ function _find_package_from_list(list, opt, cygpath) table.insert(result.links, apath:sub(1, apath:len() - 4)) elseif line:endswith(".a") then local apath = line - if opt.plat == "mingw" then + if is_subhost("msys") and opt.plat == "mingw" then apath = os.iorunv(cygpath.program, {"--windows", line}) end table.insert(result.linkdirs, path.directory(apath)) @@ -79,15 +88,18 @@ function _find_package_from_list(list, opt, cygpath) table.insert(result.links, apath:sub(1, apath:len() - 3)) end end - + result.includedirs = table.unique(result.includedirs) result.linkdirs = table.unique(result.linkdirs) result.links = table.unique(result.links) - + -- use pacman package version as version local pacmanversion = try { function() return os.iorunv(pacman.program, {"-Q", name}) end } if pacmanversion then - result.version = pacmanversion:trim():split('%s+')[2] + pacmanversion = pacmanversion:trim():split('%s+')[2] + result.version = pacmanversion:split('-')[1] + else + result = nil end return result @@ -110,23 +122,16 @@ function main(name, opt) end -- for msys2/mingw? mingw-w64-[i686|x86_64]-xxx - local cygpath = nil - if opt.plat == "mingw" then + if is_subhost("msys") and opt.plat == "mingw" then name = (opt.arch == "x86_64" and "mingw-w64-x86_64-" or "mingw-w64-i686-") .. name - - -- mingw + pacman = cygpath available - cygpath = find_tool("cygpath") - if not cygpath then - return - end end -- get package files list local list = try { function() return os.iorunv(pacman.program, {"-Q", "-l", name}) end } if not list then - return + return nil end - + -- parse package files list local linkdirs = {} local has_includes = false @@ -150,45 +155,43 @@ function main(name, opt) links = {}, version = nil } - - local foundPC = false - + + local foundpc = false + for key, file in pairs(pkgconfig_files) do - pkgconfig_file = file + local pkgconfig_file = file local pkgconfig_dir = path.directory(pkgconfig_file) local pkgconfig_name = path.basename(pkgconfig_file) linkdirs = table.unique(linkdirs) - includedirs = table.unique(includedirs) - local pcresult = {} - pcresult = find_package_from_pkgconfig(pkgconfig_name, {configdirs = pkgconfig_dir, linkdirs = linkdirs}) + local pcresult = find_package_from_pkgconfig(pkgconfig_name, {configdirs = pkgconfig_dir, linkdirs = linkdirs}) -- the pkgconfig file has been parse successfully if pcresult ~= nil then - for _, locincludedir in pairs(pcresult.includedirs) do + for _, locincludedir in ipairs(pcresult.includedirs) do table.insert(result.includedirs, locincludedir) end - for _, loclinkdir in pairs(pcresult.linkdirs) do + for _, loclinkdir in ipairs(pcresult.linkdirs) do table.insert(result.linkdirs, loclinkdir) end - for _, loclink in pairs(pcresult.links) do + for _, loclink in ipairs(pcresult.links) do table.insert(result.links, loclink) end -- version should be the same if a pacman package contains multiples .pc result.version = pcresult.version - foundPC = true + foundpc = true end end - - if foundPC == true then + + if foundpc == true then result.includedirs = table.unique(result.includedirs) result.linkdirs = table.unique(result.linkdirs) result.links = table.unique(result.links) else -- if there is no .pc, we parse the package content to obtain the data we want - result = _find_package_from_list(list, opt, cygpath) + result = _find_package_from_list(list, opt, name, pacman) end return result -- cgit v1.3.1 From 8142e3e202f2d6152282eaf39f71fda0ca8ca64e Mon Sep 17 00:00:00 2001 From: ImperatorS79 Date: Sat, 21 Aug 2021 15:13:16 +0200 Subject: Update find_package.lua --- .../package/manager/pacman/find_package.lua | 29 ++++++---------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/xmake/modules/package/manager/pacman/find_package.lua b/xmake/modules/package/manager/pacman/find_package.lua index 848dec0ae..3429866fd 100644 --- a/xmake/modules/package/manager/pacman/find_package.lua +++ b/xmake/modules/package/manager/pacman/find_package.lua @@ -25,19 +25,14 @@ import("package.manager.pkgconfig.find_package", {alias = "find_package_from_pkg -- get result from list of file inside pacman package function _find_package_from_list(list, opt, name, pacman) - local result = { - includedirs = {}, - linkdirs = {}, - links = {}, - version = nil - } + local result = {includedirs = {}, linkdirs = {}, links = {}} local cygpath = nil -- mingw + pacman = cygpath available if is_subhost("msys") and opt.plat == "mingw" then cygpath = find_tool("cygpath") if not cygpath then - return nil + return end end @@ -50,7 +45,7 @@ function _find_package_from_list(list, opt, name, pacman) hpath = os.iorunv(cygpath.program, {"--windows", line}) if opt.arch == "x86_64" then - local basehpath = os.iorunv(cygpath.program, {"--windows", "/mingw64/include"}) + local basehpath = os.iorunv(cygpath.program, {"--windows", "/mingw64/include"}) table.insert(result.includedirs, basehpath) else local basehpath = os.iorunv(cygpath.program, {"--windows", "/mingw32/include"}) @@ -147,34 +142,26 @@ function main(name, opt) has_includes = true end end + linkdirs = table.unique(linkdirs) -- we iterate over each pkgconfig file to extract the required data - local result = { - includedirs = {}, - linkdirs = {}, - links = {}, - version = nil - } + local result = {includedirs = {}, linkdirs = {}, links = {}} local foundpc = false - for key, file in pairs(pkgconfig_files) do - local pkgconfig_file = file + for key, pkgconfig_file in pairs(pkgconfig_files) do local pkgconfig_dir = path.directory(pkgconfig_file) local pkgconfig_name = path.basename(pkgconfig_file) - linkdirs = table.unique(linkdirs) local pcresult = find_package_from_pkgconfig(pkgconfig_name, {configdirs = pkgconfig_dir, linkdirs = linkdirs}) -- the pkgconfig file has been parse successfully - if pcresult ~= nil then + if pcresult then for _, locincludedir in ipairs(pcresult.includedirs) do table.insert(result.includedirs, locincludedir) - end - + end for _, loclinkdir in ipairs(pcresult.linkdirs) do table.insert(result.linkdirs, loclinkdir) end - for _, loclink in ipairs(pcresult.links) do table.insert(result.links, loclink) end -- cgit v1.3.1 From d75ef94efae5127831c7719308d6b1d9c3a49eb8 Mon Sep 17 00:00:00 2001 From: ImperatorS79 Date: Sat, 21 Aug 2021 15:18:33 +0200 Subject: FIx spelling --- xmake/modules/package/manager/pacman/find_package.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/package/manager/pacman/find_package.lua b/xmake/modules/package/manager/pacman/find_package.lua index 3429866fd..5a9094a7f 100644 --- a/xmake/modules/package/manager/pacman/find_package.lua +++ b/xmake/modules/package/manager/pacman/find_package.lua @@ -53,7 +53,7 @@ function _find_package_from_list(list, opt, name, pacman) end end table.insert(result.includedirs, path.directory(hpath)) - -- revove lib and .a, .dll.a and .so to have the links + -- remove lib and .a, .dll.a and .so to have the links elseif line:endswith(".dll.a") then -- only for mingw local apath = os.iorunv(cygpath.program, {"--windows", line}) table.insert(result.linkdirs, path.directory(apath)) -- cgit v1.3.1 From ad079f7ffb33b0478e6806be77592ee7a91e1823 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 21 Aug 2021 23:10:14 +0800 Subject: fix repo --- xmake/modules/private/action/require/impl/repository.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xmake/modules/private/action/require/impl/repository.lua b/xmake/modules/private/action/require/impl/repository.lua index 4f1e44f27..80a69b41e 100644 --- a/xmake/modules/private/action/require/impl/repository.lua +++ b/xmake/modules/private/action/require/impl/repository.lua @@ -158,7 +158,8 @@ function packagedir(packagename, opt) end end end - packagedirs[cachekey] = foundir or {} + foundir = foundir or {} + packagedirs[cachekey] = foundir end -- save the current commit -- cgit v1.3.1 From 196ca9770d1b61436a5dd831e53a5ba4868d5a29 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 21 Aug 2021 23:19:18 +0800 Subject: improve window ci --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 4dfe3eb35..3d7560e2d 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -16,7 +16,7 @@ jobs: runs-on: ${{ matrix.os }} concurrency: - group: ${{ github.head_ref }}-Windows + group: ${{ github.head_ref }}-${{ matrix.os }}-${{ matrix.arch }}-Windows cancel-in-progress: true steps: - uses: actions/checkout@v2 -- cgit v1.3.1 From f66e9257a56badb4a7ac0d61753922428105f068 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 21 Aug 2021 23:26:12 +0800 Subject: fix code style --- .../package/manager/pacman/find_package.lua | 58 ++++++++++------------ 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/xmake/modules/package/manager/pacman/find_package.lua b/xmake/modules/package/manager/pacman/find_package.lua index 5a9094a7f..0f38a92fc 100644 --- a/xmake/modules/package/manager/pacman/find_package.lua +++ b/xmake/modules/package/manager/pacman/find_package.lua @@ -24,11 +24,10 @@ import("lib.detect.find_tool") import("package.manager.pkgconfig.find_package", {alias = "find_package_from_pkgconfig"}) -- get result from list of file inside pacman package -function _find_package_from_list(list, opt, name, pacman) - local result = {includedirs = {}, linkdirs = {}, links = {}} - - local cygpath = nil +function _find_package_from_list(list, name, pacman, opt) + -- mingw + pacman = cygpath available + local cygpath = nil if is_subhost("msys") and opt.plat == "mingw" then cygpath = find_tool("cygpath") if not cygpath then @@ -37,13 +36,14 @@ function _find_package_from_list(list, opt, name, pacman) end -- iterate over each file path inside the pacman package + local result = {includedirs = {}, linkdirs = {}, links = {}} for _, line in ipairs(list:split('\n', {plain = true})) do -- on msys cygpath should be used to convert local path to windows path line = line:trim():split('%s+')[2] if line:find("/include/", 1, true) and (line:endswith(".h") or line:endswith(".hpp")) then local hpath = line if is_subhost("msys") and opt.plat == "mingw" then hpath = os.iorunv(cygpath.program, {"--windows", line}) - + if opt.arch == "x86_64" then local basehpath = os.iorunv(cygpath.program, {"--windows", "/mingw64/include"}) table.insert(result.includedirs, basehpath) @@ -83,20 +83,18 @@ function _find_package_from_list(list, opt, name, pacman) table.insert(result.links, apath:sub(1, apath:len() - 3)) end end - result.includedirs = table.unique(result.includedirs) result.linkdirs = table.unique(result.linkdirs) result.links = table.unique(result.links) -- use pacman package version as version - local pacmanversion = try { function() return os.iorunv(pacman.program, {"-Q", name}) end } - if pacmanversion then - pacmanversion = pacmanversion:trim():split('%s+')[2] - result.version = pacmanversion:split('-')[1] + local version = try { function() return os.iorunv(pacman.program, {"-Q", name}) end } + if version then + version = version:trim():split('%s+')[2] + result.version = version:split('-')[1] else result = nil end - return result end @@ -107,10 +105,8 @@ end -- function main(name, opt) - -- init options - opt = opt or {} - -- find pacman + opt = opt or {} local pacman = find_tool("pacman") if not pacman then return @@ -124,7 +120,7 @@ function main(name, opt) -- get package files list local list = try { function() return os.iorunv(pacman.program, {"-Q", "-l", name}) end } if not list then - return nil + return end -- parse package files list @@ -143,32 +139,28 @@ function main(name, opt) end end linkdirs = table.unique(linkdirs) - - -- we iterate over each pkgconfig file to extract the required data - local result = {includedirs = {}, linkdirs = {}, links = {}} + -- we iterate over each pkgconfig file to extract the required data local foundpc = false - - for key, pkgconfig_file in pairs(pkgconfig_files) do + local result = {includedirs = {}, linkdirs = {}, links = {}} + for _, pkgconfig_file in pairs(pkgconfig_files) do local pkgconfig_dir = path.directory(pkgconfig_file) local pkgconfig_name = path.basename(pkgconfig_file) local pcresult = find_package_from_pkgconfig(pkgconfig_name, {configdirs = pkgconfig_dir, linkdirs = linkdirs}) - + -- the pkgconfig file has been parse successfully if pcresult then - for _, locincludedir in ipairs(pcresult.includedirs) do - table.insert(result.includedirs, locincludedir) - end - for _, loclinkdir in ipairs(pcresult.linkdirs) do - table.insert(result.linkdirs, loclinkdir) + for _, includedir in ipairs(pcresult.includedirs) do + table.insert(result.includedirs, includedir) end - for _, loclink in ipairs(pcresult.links) do - table.insert(result.links, loclink) + for _, linkdir in ipairs(pcresult.linkdirs) do + table.insert(result.linkdirs, linkdir) + end + for _, link in ipairs(pcresult.links) do + table.insert(result.links, link) end - -- version should be the same if a pacman package contains multiples .pc result.version = pcresult.version - foundpc = true end end @@ -177,9 +169,9 @@ function main(name, opt) result.includedirs = table.unique(result.includedirs) result.linkdirs = table.unique(result.linkdirs) result.links = table.unique(result.links) - else -- if there is no .pc, we parse the package content to obtain the data we want - result = _find_package_from_list(list, opt, name, pacman) + else + -- if there is no .pc, we parse the package content to obtain the data we want + result = _find_package_from_list(list, name, pacman, opt) end - return result end -- cgit v1.3.1 From 6410bc544cbc8b57e2d07559df65c0a5219ebdcc Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 22 Aug 2021 11:20:24 +0800 Subject: improve repo --- xmake/modules/private/action/require/impl/repository.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xmake/modules/private/action/require/impl/repository.lua b/xmake/modules/private/action/require/impl/repository.lua index 80a69b41e..6d656ccd0 100644 --- a/xmake/modules/private/action/require/impl/repository.lua +++ b/xmake/modules/private/action/require/impl/repository.lua @@ -42,6 +42,8 @@ function _get_packagedir_from_locked_repo(packagename, locked_repo) local repodir_local if os.isdir(locked_repo.url) then repodir_local = locked_repo.url + elseif not locked_repo.commit then + repodir_local = repodir_global else repodir_local = path.join(config.directory(), "repositories", reponame) end -- cgit v1.3.1 From 0ce7b3cb07739b1151a5859576382d27eb829825 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 22 Aug 2021 19:17:52 +0800 Subject: add metal app test --- tests/projects/objc/metal_app | 1 + 1 file changed, 1 insertion(+) create mode 160000 tests/projects/objc/metal_app diff --git a/tests/projects/objc/metal_app b/tests/projects/objc/metal_app new file mode 160000 index 000000000..8a27b2e0b --- /dev/null +++ b/tests/projects/objc/metal_app @@ -0,0 +1 @@ +Subproject commit 8a27b2e0b805a90dc92bf1e41018206f65333709 -- cgit v1.3.1 From 0c7df1fe002288cf91601a941d02988428e2c6d0 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 22 Aug 2021 19:19:49 +0800 Subject: rm metal app test --- tests/projects/objc/metal_app | 1 - 1 file changed, 1 deletion(-) delete mode 160000 tests/projects/objc/metal_app diff --git a/tests/projects/objc/metal_app b/tests/projects/objc/metal_app deleted file mode 160000 index 8a27b2e0b..000000000 --- a/tests/projects/objc/metal_app +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8a27b2e0b805a90dc92bf1e41018206f65333709 -- cgit v1.3.1 From 0b3a790a6e1e81b25ff4e2d7a53c73bc42b47e26 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 22 Aug 2021 19:20:21 +0800 Subject: add metal app test --- tests/projects/objc/metal_app/.gitignore | 21 + .../objc/metal_app/Application/AAPLAppDelegate.h | 14 + .../objc/metal_app/Application/AAPLAppDelegate.m | 16 + .../metal_app/Application/AAPLViewController.h | 23 + .../metal_app/Application/AAPLViewController.m | 39 ++ .../iOS/Base.lproj/LaunchScreen.storyboard | 27 + .../Application/iOS/Base.lproj/Main.storyboard | 30 + .../objc/metal_app/Application/iOS/Info.plist | 48 ++ .../Application/macOS/Base.lproj/Main.storyboard | 693 +++++++++++++++++++++ .../objc/metal_app/Application/macOS/Info.plist | 30 + tests/projects/objc/metal_app/Application/main.m | 36 ++ .../Application/tvOS/Base.lproj/Main.storyboard | 30 + .../objc/metal_app/Application/tvOS/Info.plist | 32 + .../metal_app/Configuration/SampleCode.xcconfig | 13 + .../HelloTriangle.xcodeproj/.xcodesamplecode.plist | 5 + .../HelloTriangle.xcodeproj/project.pbxproj | 681 ++++++++++++++++++++ .../xcshareddata/WorkspaceSettings.xcsettings | 8 + tests/projects/objc/metal_app/LICENSE/LICENSE.txt | 8 + tests/projects/objc/metal_app/README.md | 332 ++++++++++ .../objc/metal_app/Renderer/AAPLRenderer.h | 14 + .../objc/metal_app/Renderer/AAPLRenderer.m | 132 ++++ .../objc/metal_app/Renderer/AAPLShaderTypes.h | 31 + .../objc/metal_app/Renderer/AAPLShaders.metal | 62 ++ tests/projects/objc/metal_app/xmake.lua | 22 + 24 files changed, 2347 insertions(+) create mode 100644 tests/projects/objc/metal_app/.gitignore create mode 100644 tests/projects/objc/metal_app/Application/AAPLAppDelegate.h create mode 100644 tests/projects/objc/metal_app/Application/AAPLAppDelegate.m create mode 100644 tests/projects/objc/metal_app/Application/AAPLViewController.h create mode 100644 tests/projects/objc/metal_app/Application/AAPLViewController.m create mode 100644 tests/projects/objc/metal_app/Application/iOS/Base.lproj/LaunchScreen.storyboard create mode 100644 tests/projects/objc/metal_app/Application/iOS/Base.lproj/Main.storyboard create mode 100644 tests/projects/objc/metal_app/Application/iOS/Info.plist create mode 100644 tests/projects/objc/metal_app/Application/macOS/Base.lproj/Main.storyboard create mode 100644 tests/projects/objc/metal_app/Application/macOS/Info.plist create mode 100644 tests/projects/objc/metal_app/Application/main.m create mode 100644 tests/projects/objc/metal_app/Application/tvOS/Base.lproj/Main.storyboard create mode 100644 tests/projects/objc/metal_app/Application/tvOS/Info.plist create mode 100644 tests/projects/objc/metal_app/Configuration/SampleCode.xcconfig create mode 100644 tests/projects/objc/metal_app/HelloTriangle.xcodeproj/.xcodesamplecode.plist create mode 100644 tests/projects/objc/metal_app/HelloTriangle.xcodeproj/project.pbxproj create mode 100644 tests/projects/objc/metal_app/HelloTriangle.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 tests/projects/objc/metal_app/LICENSE/LICENSE.txt create mode 100644 tests/projects/objc/metal_app/README.md create mode 100644 tests/projects/objc/metal_app/Renderer/AAPLRenderer.h create mode 100644 tests/projects/objc/metal_app/Renderer/AAPLRenderer.m create mode 100644 tests/projects/objc/metal_app/Renderer/AAPLShaderTypes.h create mode 100644 tests/projects/objc/metal_app/Renderer/AAPLShaders.metal create mode 100644 tests/projects/objc/metal_app/xmake.lua diff --git a/tests/projects/objc/metal_app/.gitignore b/tests/projects/objc/metal_app/.gitignore new file mode 100644 index 000000000..9e50718e2 --- /dev/null +++ b/tests/projects/objc/metal_app/.gitignore @@ -0,0 +1,21 @@ +# See LICENSE folder for this sample’s licensing information. +# +# Apple sample code gitignore configuration. + +# Finder +.DS_Store + +# Xcode - User files +xcuserdata/ + +**/*.xcodeproj/project.xcworkspace/* +!**/*.xcodeproj/project.xcworkspace/xcshareddata + +**/*.xcodeproj/project.xcworkspace/xcshareddata/* +!**/*.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings + +**/*.playground/playground.xcworkspace/* +!**/*.playground/playground.xcworkspace/xcshareddata + +**/*.playground/playground.xcworkspace/xcshareddata/* +!**/*.playground/playground.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/tests/projects/objc/metal_app/Application/AAPLAppDelegate.h b/tests/projects/objc/metal_app/Application/AAPLAppDelegate.h new file mode 100644 index 000000000..a4e4a7fef --- /dev/null +++ b/tests/projects/objc/metal_app/Application/AAPLAppDelegate.h @@ -0,0 +1,14 @@ +/* +See LICENSE folder for this sample’s licensing information. + +Abstract: +Header for our iOS & tvOS application delegate +*/ + +#import + +@interface AAPLAppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@end diff --git a/tests/projects/objc/metal_app/Application/AAPLAppDelegate.m b/tests/projects/objc/metal_app/Application/AAPLAppDelegate.m new file mode 100644 index 000000000..58b31e876 --- /dev/null +++ b/tests/projects/objc/metal_app/Application/AAPLAppDelegate.m @@ -0,0 +1,16 @@ +/* +See LICENSE folder for this sample’s licensing information. + +Abstract: +Implementation of our iOS & tvOS application delegate +*/ + +#import "AAPLAppDelegate.h" + +@implementation AAPLAppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + return YES; +} + +@end diff --git a/tests/projects/objc/metal_app/Application/AAPLViewController.h b/tests/projects/objc/metal_app/Application/AAPLViewController.h new file mode 100644 index 000000000..f9ecea64f --- /dev/null +++ b/tests/projects/objc/metal_app/Application/AAPLViewController.h @@ -0,0 +1,23 @@ +/* +See LICENSE folder for this sample’s licensing information. + +Abstract: +Header for our our cross-platform view controller +*/ + +#if defined(TARGET_IOS) || defined(TARGET_TVOS) +@import UIKit; +#define PlatformViewController UIViewController +#else +@import AppKit; +#define PlatformViewController NSViewController +#endif + +@import MetalKit; + +#import "AAPLRenderer.h" + +// Our view controller +@interface AAPLViewController : PlatformViewController + +@end diff --git a/tests/projects/objc/metal_app/Application/AAPLViewController.m b/tests/projects/objc/metal_app/Application/AAPLViewController.m new file mode 100644 index 000000000..dc02a8c4a --- /dev/null +++ b/tests/projects/objc/metal_app/Application/AAPLViewController.m @@ -0,0 +1,39 @@ +/* +See LICENSE folder for this sample’s licensing information. + +Abstract: +Implementation of our cross-platform view controller +*/ + +#import "AAPLViewController.h" +#import "AAPLRenderer.h" + +@implementation AAPLViewController +{ + MTKView *_view; + + AAPLRenderer *_renderer; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + // Set the view to use the default device + _view = (MTKView *)self.view; + + _view.device = MTLCreateSystemDefaultDevice(); + + NSAssert(_view.device, @"Metal is not supported on this device"); + + _renderer = [[AAPLRenderer alloc] initWithMetalKitView:_view]; + + NSAssert(_renderer, @"Renderer failed initialization"); + + // Initialize our renderer with the view size + [_renderer mtkView:_view drawableSizeWillChange:_view.drawableSize]; + + _view.delegate = _renderer; +} + +@end diff --git a/tests/projects/objc/metal_app/Application/iOS/Base.lproj/LaunchScreen.storyboard b/tests/projects/objc/metal_app/Application/iOS/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..fdf3f97d1 --- /dev/null +++ b/tests/projects/objc/metal_app/Application/iOS/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/projects/objc/metal_app/Application/iOS/Base.lproj/Main.storyboard b/tests/projects/objc/metal_app/Application/iOS/Base.lproj/Main.storyboard new file mode 100644 index 000000000..037265c96 --- /dev/null +++ b/tests/projects/objc/metal_app/Application/iOS/Base.lproj/Main.storyboard @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/projects/objc/metal_app/Application/iOS/Info.plist b/tests/projects/objc/metal_app/Application/iOS/Info.plist new file mode 100644 index 000000000..154374326 --- /dev/null +++ b/tests/projects/objc/metal_app/Application/iOS/Info.plist @@ -0,0 +1,48 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + UIInterfaceOrientationPortraitUpsideDown + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/tests/projects/objc/metal_app/Application/macOS/Base.lproj/Main.storyboard b/tests/projects/objc/metal_app/Application/macOS/Base.lproj/Main.storyboard new file mode 100644 index 000000000..e6be158ce --- /dev/null +++ b/tests/projects/objc/metal_app/Application/macOS/Base.lproj/Main.storyboard @@ -0,0 +1,693 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/projects/objc/metal_app/Application/macOS/Info.plist b/tests/projects/objc/metal_app/Application/macOS/Info.plist new file mode 100644 index 000000000..f16cc0681 --- /dev/null +++ b/tests/projects/objc/metal_app/Application/macOS/Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/tests/projects/objc/metal_app/Application/main.m b/tests/projects/objc/metal_app/Application/main.m new file mode 100644 index 000000000..b35c0d5ec --- /dev/null +++ b/tests/projects/objc/metal_app/Application/main.m @@ -0,0 +1,36 @@ +/* +See LICENSE folder for this sample’s licensing information. + +Abstract: +Application entry point for all platforms +*/ + +#if defined(TARGET_IOS) || defined(TARGET_TVOS) +#import +#import +#import +#import "AAPLAppDelegate.h" +#else +#import +#endif + +#if defined(TARGET_IOS) || defined(TARGET_TVOS) + +int main(int argc, char * argv[]) { + +#if TARGET_OS_SIMULATOR && (!defined(__IPHONE_13_0) || !defined(__TVOS_13_0)) +#error No simulator support for Metal API for this SDK version. Must build for a device +#endif + + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AAPLAppDelegate class])); + } +} + +#elif defined(TARGET_MACOS) + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} + +#endif diff --git a/tests/projects/objc/metal_app/Application/tvOS/Base.lproj/Main.storyboard b/tests/projects/objc/metal_app/Application/tvOS/Base.lproj/Main.storyboard new file mode 100644 index 000000000..77bc5bc2d --- /dev/null +++ b/tests/projects/objc/metal_app/Application/tvOS/Base.lproj/Main.storyboard @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/projects/objc/metal_app/Application/tvOS/Info.plist b/tests/projects/objc/metal_app/Application/tvOS/Info.plist new file mode 100644 index 000000000..63dcd6c1d --- /dev/null +++ b/tests/projects/objc/metal_app/Application/tvOS/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + arm64 + + UIUserInterfaceStyle + Automatic + + diff --git a/tests/projects/objc/metal_app/Configuration/SampleCode.xcconfig b/tests/projects/objc/metal_app/Configuration/SampleCode.xcconfig new file mode 100644 index 000000000..db86c0698 --- /dev/null +++ b/tests/projects/objc/metal_app/Configuration/SampleCode.xcconfig @@ -0,0 +1,13 @@ +// +// See LICENSE folder for this sample’s licensing information. +// +// SampleCode.xcconfig +// + +// The `SAMPLE_CODE_DISAMBIGUATOR` configuration is to make it easier to build +// and run a sample code project. Once you set your project's development team, +// you'll have a unique bundle identifier. This is because the bundle identifier +// is derived based on the 'SAMPLE_CODE_DISAMBIGUATOR' value. Do not use this +// approach in your own projects—it's only useful for sample code projects because +// they are frequently downloaded and don't have a development team set. +SAMPLE_CODE_DISAMBIGUATOR=${DEVELOPMENT_TEAM} diff --git a/tests/projects/objc/metal_app/HelloTriangle.xcodeproj/.xcodesamplecode.plist b/tests/projects/objc/metal_app/HelloTriangle.xcodeproj/.xcodesamplecode.plist new file mode 100644 index 000000000..5dd5da85f --- /dev/null +++ b/tests/projects/objc/metal_app/HelloTriangle.xcodeproj/.xcodesamplecode.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/projects/objc/metal_app/HelloTriangle.xcodeproj/project.pbxproj b/tests/projects/objc/metal_app/HelloTriangle.xcodeproj/project.pbxproj new file mode 100644 index 000000000..f1820eccc --- /dev/null +++ b/tests/projects/objc/metal_app/HelloTriangle.xcodeproj/project.pbxproj @@ -0,0 +1,681 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 3A05CBE01F731ABB00CA21B1 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A1F1B411F0338CF001622B3 /* MetalKit.framework */; }; + 3A05CBE11F731AC000CA21B1 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A05CBDE1F731AB800CA21B1 /* MetalKit.framework */; }; + 3A1F1B391F033765001622B3 /* AAPLViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A35329C1E99974500C194AD /* AAPLViewController.m */; }; + 3A1F1B3D1F033827001622B3 /* AAPLViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A35329C1E99974500C194AD /* AAPLViewController.m */; }; + 3A1F1B3E1F033846001622B3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A3532931E99974500C194AD /* main.m */; }; + 3A1F1B3F1F033846001622B3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A3532931E99974500C194AD /* main.m */; }; + 3A1F1B441F033EF3001622B3 /* AAPLAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3ACD21341EAE60D2000D1DED /* AAPLAppDelegate.m */; }; + 3A3532941E99974500C194AD /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A3532931E99974500C194AD /* main.m */; }; + 3A35329D1E99974500C194AD /* AAPLViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A35329C1E99974500C194AD /* AAPLViewController.m */; }; + 3A3532A01E99974500C194AD /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3A35329E1E99974500C194AD /* Main.storyboard */; }; + 3A3532A31E99974500C194AD /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3A3532A11E99974500C194AD /* LaunchScreen.storyboard */; }; + 3A3532B91E99974500C194AD /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3A3532B71E99974500C194AD /* Main.storyboard */; }; + 3A3532CC1E99974500C194AD /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3A3532CA1E99974500C194AD /* Main.storyboard */; }; + 3A3532CE1E99974500C194AD /* AAPLRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A3532851E99974500C194AD /* AAPLRenderer.m */; }; + 3A3532CF1E99974500C194AD /* AAPLRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A3532851E99974500C194AD /* AAPLRenderer.m */; }; + 3A3532D01E99974500C194AD /* AAPLRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A3532851E99974500C194AD /* AAPLRenderer.m */; }; + 3ACD21351EAE60D2000D1DED /* AAPLAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3ACD21341EAE60D2000D1DED /* AAPLAppDelegate.m */; }; + 63E77A181ED2059A00E1E542 /* AAPLShaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 3A3532871E99974500C194AD /* AAPLShaders.metal */; }; + 63E77A191ED2059E00E1E542 /* AAPLShaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 3A3532871E99974500C194AD /* AAPLShaders.metal */; }; + 63E77A1A1ED205A200E1E542 /* AAPLShaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 3A3532871E99974500C194AD /* AAPLShaders.metal */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 328A8E964EC41C65EC8AF01A /* LICENSE.txt */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE.txt; sourceTree = ""; }; + 3A05CBDE1F731AB800CA21B1 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = ../../../../iPhoneOS.platform/Developer/SDKs/iPhoneOS11.0.sdk/System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; + 3A1F1B411F0338CF001622B3 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = ../../../../AppleTVOS.platform/Developer/SDKs/AppleTVOS11.0.sdk/System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; + 3A3532841E99974500C194AD /* AAPLRenderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AAPLRenderer.h; sourceTree = ""; }; + 3A3532851E99974500C194AD /* AAPLRenderer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AAPLRenderer.m; sourceTree = ""; }; + 3A3532861E99974500C194AD /* AAPLShaderTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AAPLShaderTypes.h; sourceTree = ""; }; + 3A3532871E99974500C194AD /* AAPLShaders.metal */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.metal; path = AAPLShaders.metal; sourceTree = ""; }; + 3A35328F1E99974500C194AD /* HelloTriangle.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HelloTriangle.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 3A3532931E99974500C194AD /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 3A35329B1E99974500C194AD /* AAPLViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AAPLViewController.h; sourceTree = ""; }; + 3A35329C1E99974500C194AD /* AAPLViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AAPLViewController.m; sourceTree = ""; }; + 3A35329F1E99974500C194AD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 3A3532A21E99974500C194AD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 3A3532A41E99974500C194AD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 3A3532A91E99974500C194AD /* HelloTriangle.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HelloTriangle.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 3A3532B81E99974500C194AD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 3A3532BA1E99974500C194AD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 3A3532BF1E99974500C194AD /* HelloTriangle.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HelloTriangle.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 3A3532CB1E99974500C194AD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 3A3532CD1E99974500C194AD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 3ACD21331EAE60D2000D1DED /* AAPLAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AAPLAppDelegate.h; sourceTree = ""; }; + 3ACD21341EAE60D2000D1DED /* AAPLAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AAPLAppDelegate.m; sourceTree = ""; }; + 3ED283CC1EC2C6D200A23F58 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + 907FE32A28789CDAFD777257 /* SampleCode.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = SampleCode.xcconfig; path = Configuration/SampleCode.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 3A35328C1E99974500C194AD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3A05CBE11F731AC000CA21B1 /* MetalKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3A3532A61E99974500C194AD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3A05CBE01F731ABB00CA21B1 /* MetalKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3A3532BC1E99974500C194AD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3A1F1B351F0336A8001622B3 /* iOS */ = { + isa = PBXGroup; + children = ( + 3A35329E1E99974500C194AD /* Main.storyboard */, + 3A3532A11E99974500C194AD /* LaunchScreen.storyboard */, + 3A3532A41E99974500C194AD /* Info.plist */, + ); + path = iOS; + sourceTree = ""; + }; + 3A1F1B361F0336DB001622B3 /* macOS */ = { + isa = PBXGroup; + children = ( + 3A3532CA1E99974500C194AD /* Main.storyboard */, + 3A3532CD1E99974500C194AD /* Info.plist */, + ); + path = macOS; + sourceTree = ""; + }; + 3A1F1B371F0336F4001622B3 /* tvOS */ = { + isa = PBXGroup; + children = ( + 3A3532B71E99974500C194AD /* Main.storyboard */, + 3A3532BA1E99974500C194AD /* Info.plist */, + ); + path = tvOS; + sourceTree = ""; + }; + 3A35327E1E99974500C194AD = { + isa = PBXGroup; + children = ( + 3ED283CC1EC2C6D200A23F58 /* README.md */, + 3A3532831E99974500C194AD /* Renderer */, + 3A3532911E99974500C194AD /* Application */, + 3AE289861EEA0A9100DF4C9A /* Frameworks */, + 3A3532901E99974500C194AD /* Products */, + F4F7FAFBBA6575359FC81F34 /* Configuration */, + 9772A968083C4C14D4BE84E1 /* LICENSE */, + ); + sourceTree = ""; + }; + 3A3532831E99974500C194AD /* Renderer */ = { + isa = PBXGroup; + children = ( + 3A3532841E99974500C194AD /* AAPLRenderer.h */, + 3A3532851E99974500C194AD /* AAPLRenderer.m */, + 3A3532861E99974500C194AD /* AAPLShaderTypes.h */, + 3A3532871E99974500C194AD /* AAPLShaders.metal */, + ); + path = Renderer; + sourceTree = ""; + }; + 3A3532901E99974500C194AD /* Products */ = { + isa = PBXGroup; + children = ( + 3A35328F1E99974500C194AD /* HelloTriangle.app */, + 3A3532A91E99974500C194AD /* HelloTriangle.app */, + 3A3532BF1E99974500C194AD /* HelloTriangle.app */, + ); + name = Products; + sourceTree = ""; + }; + 3A3532911E99974500C194AD /* Application */ = { + isa = PBXGroup; + children = ( + 3ACD21331EAE60D2000D1DED /* AAPLAppDelegate.h */, + 3ACD21341EAE60D2000D1DED /* AAPLAppDelegate.m */, + 3A35329B1E99974500C194AD /* AAPLViewController.h */, + 3A35329C1E99974500C194AD /* AAPLViewController.m */, + 3A3532931E99974500C194AD /* main.m */, + 3A1F1B361F0336DB001622B3 /* macOS */, + 3A1F1B371F0336F4001622B3 /* tvOS */, + 3A1F1B351F0336A8001622B3 /* iOS */, + ); + path = Application; + sourceTree = ""; + }; + 3AE289861EEA0A9100DF4C9A /* Frameworks */ = { + isa = PBXGroup; + children = ( + 3A05CBDE1F731AB800CA21B1 /* MetalKit.framework */, + 3A1F1B411F0338CF001622B3 /* MetalKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9772A968083C4C14D4BE84E1 /* LICENSE */ = { + isa = PBXGroup; + children = ( + 328A8E964EC41C65EC8AF01A /* LICENSE.txt */, + ); + path = LICENSE; + sourceTree = ""; + }; + F4F7FAFBBA6575359FC81F34 /* Configuration */ = { + isa = PBXGroup; + children = ( + 907FE32A28789CDAFD777257 /* SampleCode.xcconfig */, + ); + name = Configuration; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 3A35328E1E99974500C194AD /* HelloTriangle-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3A3532E21E99974500C194AD /* Build configuration list for PBXNativeTarget "HelloTriangle-iOS" */; + buildPhases = ( + 3A35328B1E99974500C194AD /* Sources */, + 3A35328C1E99974500C194AD /* Frameworks */, + 3A35328D1E99974500C194AD /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "HelloTriangle-iOS"; + productName = iOS; + productReference = 3A35328F1E99974500C194AD /* HelloTriangle.app */; + productType = "com.apple.product-type.application"; + }; + 3A3532A81E99974500C194AD /* HelloTriangle-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3A3532E51E99974500C194AD /* Build configuration list for PBXNativeTarget "HelloTriangle-tvOS" */; + buildPhases = ( + 3A3532A51E99974500C194AD /* Sources */, + 3A3532A61E99974500C194AD /* Frameworks */, + 3A3532A71E99974500C194AD /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "HelloTriangle-tvOS"; + productName = tvOS; + productReference = 3A3532A91E99974500C194AD /* HelloTriangle.app */; + productType = "com.apple.product-type.application"; + }; + 3A3532BE1E99974500C194AD /* HelloTriangle-macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3A3532E81E99974500C194AD /* Build configuration list for PBXNativeTarget "HelloTriangle-macOS" */; + buildPhases = ( + 3A3532BB1E99974500C194AD /* Sources */, + 3A3532BC1E99974500C194AD /* Frameworks */, + 3A3532BD1E99974500C194AD /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "HelloTriangle-macOS"; + productName = macOS; + productReference = 3A3532BF1E99974500C194AD /* HelloTriangle.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 3A35327F1E99974500C194AD /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1200; + ORGANIZATIONNAME = Apple; + TargetAttributes = { + 3A35328E1E99974500C194AD = { + CreatedOnToolsVersion = 8.3; + ProvisioningStyle = Automatic; + }; + 3A3532A81E99974500C194AD = { + CreatedOnToolsVersion = 8.3; + ProvisioningStyle = Automatic; + }; + 3A3532BE1E99974500C194AD = { + CreatedOnToolsVersion = 8.3; + DevelopmentTeam = 43AAQM58X3; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 3A3532821E99974500C194AD /* Build configuration list for PBXProject "HelloTriangle" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 3A35327E1E99974500C194AD; + productRefGroup = 3A3532901E99974500C194AD /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 3A3532BE1E99974500C194AD /* HelloTriangle-macOS */, + 3A35328E1E99974500C194AD /* HelloTriangle-iOS */, + 3A3532A81E99974500C194AD /* HelloTriangle-tvOS */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 3A35328D1E99974500C194AD /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3A3532A01E99974500C194AD /* Main.storyboard in Resources */, + 3A3532A31E99974500C194AD /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3A3532A71E99974500C194AD /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3A3532B91E99974500C194AD /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3A3532BD1E99974500C194AD /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3A3532CC1E99974500C194AD /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 3A35328B1E99974500C194AD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 63E77A181ED2059A00E1E542 /* AAPLShaders.metal in Sources */, + 3A35329D1E99974500C194AD /* AAPLViewController.m in Sources */, + 3A3532941E99974500C194AD /* main.m in Sources */, + 3A3532CE1E99974500C194AD /* AAPLRenderer.m in Sources */, + 3ACD21351EAE60D2000D1DED /* AAPLAppDelegate.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3A3532A51E99974500C194AD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 63E77A191ED2059E00E1E542 /* AAPLShaders.metal in Sources */, + 3A3532CF1E99974500C194AD /* AAPLRenderer.m in Sources */, + 3A1F1B391F033765001622B3 /* AAPLViewController.m in Sources */, + 3A1F1B3F1F033846001622B3 /* main.m in Sources */, + 3A1F1B441F033EF3001622B3 /* AAPLAppDelegate.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3A3532BB1E99974500C194AD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3A1F1B3D1F033827001622B3 /* AAPLViewController.m in Sources */, + 63E77A1A1ED205A200E1E542 /* AAPLShaders.metal in Sources */, + 3A1F1B3E1F033846001622B3 /* main.m in Sources */, + 3A3532D01E99974500C194AD /* AAPLRenderer.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 3A35329E1E99974500C194AD /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 3A35329F1E99974500C194AD /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 3A3532A11E99974500C194AD /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 3A3532A21E99974500C194AD /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; + 3A3532B71E99974500C194AD /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 3A3532B81E99974500C194AD /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 3A3532CA1E99974500C194AD /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 3A3532CB1E99974500C194AD /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 3A3532E01E99974500C194AD /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 907FE32A28789CDAFD777257 /* SampleCode.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MTL_ENABLE_DEBUG_INFO = YES; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = HelloTriangle; + }; + name = Debug; + }; + 3A3532E11E99974500C194AD /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 907FE32A28789CDAFD777257 /* SampleCode.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = HelloTriangle; + }; + name = Release; + }; + 3A3532E31E99974500C194AD /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 907FE32A28789CDAFD777257 /* SampleCode.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + DEVELOPMENT_TEAM = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)/System/Library/Frameworks", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + TARGET_IOS, + ); + INFOPLIST_FILE = Application/iOS/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-samplecode.HelloTriangle${SAMPLE_CODE_DISAMBIGUATOR}"; + PRODUCT_NAME = HelloTriangle; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 3A3532E41E99974500C194AD /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 907FE32A28789CDAFD777257 /* SampleCode.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + DEVELOPMENT_TEAM = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)/System/Library/Frameworks", + ); + GCC_PREPROCESSOR_DEFINITIONS = TARGET_IOS; + INFOPLIST_FILE = Application/iOS/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-samplecode.HelloTriangle${SAMPLE_CODE_DISAMBIGUATOR}"; + PRODUCT_NAME = HelloTriangle; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 3A3532E61E99974500C194AD /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 907FE32A28789CDAFD777257 /* SampleCode.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + DEVELOPMENT_TEAM = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)/System/Library/Frameworks", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + TARGET_TVOS, + "$(inherited)", + ); + INFOPLIST_FILE = Application/tvOS/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-samplecode.HelloTriangle${SAMPLE_CODE_DISAMBIGUATOR}"; + PRODUCT_NAME = HelloTriangle; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + }; + name = Debug; + }; + 3A3532E71E99974500C194AD /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 907FE32A28789CDAFD777257 /* SampleCode.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + DEVELOPMENT_TEAM = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)/System/Library/Frameworks", + ); + GCC_PREPROCESSOR_DEFINITIONS = TARGET_TVOS; + INFOPLIST_FILE = Application/tvOS/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-samplecode.HelloTriangle${SAMPLE_CODE_DISAMBIGUATOR}"; + PRODUCT_NAME = HelloTriangle; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 3A3532E91E99974500C194AD /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 907FE32A28789CDAFD777257 /* SampleCode.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "Mac Developer"; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = 43AAQM58X3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + TARGET_MACOS, + ); + INFOPLIST_FILE = Application/macOS/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-samplecode.$(PRODUCT_NAME)${SAMPLE_CODE_DISAMBIGUATOR}"; + PRODUCT_NAME = HelloTriangle; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = macosx; + }; + name = Debug; + }; + 3A3532EA1E99974500C194AD /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 907FE32A28789CDAFD777257 /* SampleCode.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "Mac Developer"; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = 43AAQM58X3; + GCC_PREPROCESSOR_DEFINITIONS = TARGET_MACOS; + INFOPLIST_FILE = Application/macOS/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-samplecode.$(PRODUCT_NAME)${SAMPLE_CODE_DISAMBIGUATOR}"; + PRODUCT_NAME = HelloTriangle; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = macosx; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 3A3532821E99974500C194AD /* Build configuration list for PBXProject "HelloTriangle" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3A3532E01E99974500C194AD /* Debug */, + 3A3532E11E99974500C194AD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3A3532E21E99974500C194AD /* Build configuration list for PBXNativeTarget "HelloTriangle-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3A3532E31E99974500C194AD /* Debug */, + 3A3532E41E99974500C194AD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3A3532E51E99974500C194AD /* Build configuration list for PBXNativeTarget "HelloTriangle-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3A3532E61E99974500C194AD /* Debug */, + 3A3532E71E99974500C194AD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3A3532E81E99974500C194AD /* Build configuration list for PBXNativeTarget "HelloTriangle-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3A3532E91E99974500C194AD /* Debug */, + 3A3532EA1E99974500C194AD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 3A35327F1E99974500C194AD /* Project object */; +} diff --git a/tests/projects/objc/metal_app/HelloTriangle.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/tests/projects/objc/metal_app/HelloTriangle.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..3ddf867a1 --- /dev/null +++ b/tests/projects/objc/metal_app/HelloTriangle.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + BuildSystemType + Latest + + diff --git a/tests/projects/objc/metal_app/LICENSE/LICENSE.txt b/tests/projects/objc/metal_app/LICENSE/LICENSE.txt new file mode 100644 index 000000000..e11438f78 --- /dev/null +++ b/tests/projects/objc/metal_app/LICENSE/LICENSE.txt @@ -0,0 +1,8 @@ +Copyright © 2020 Apple Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/tests/projects/objc/metal_app/README.md b/tests/projects/objc/metal_app/README.md new file mode 100644 index 000000000..050a1611b --- /dev/null +++ b/tests/projects/objc/metal_app/README.md @@ -0,0 +1,332 @@ +# Using a Render Pipeline to Render Primitives + +Render a simple 2D triangle. + +## Overview + +In [Using Metal to Draw a View’s Contents](https://developer.apple.com/documentation/metal/basic_tasks_and_concepts/using_metal_to_draw_a_view_s_contents), you learned how to set up an `MTKView` object and to change the view's contents using a render pass. +That sample simply erased the view's contents to a background color. +This sample shows you how to configure a render pipeline and use it as part of the render pass to draw a simple 2D colored triangle into the view. +The sample supplies a position and color for each vertex, and the render pipeline uses that data to render the triangle, interpolating color values between the colors specified for the triangle's vertices. + +![Simple 2D Triangle Vertices](Documentation/2DTriangleVertices.png) + +The Xcode project contains schemes for running the sample on macOS, iOS, and tvOS. + +## Understand the Metal Render Pipeline + +A *render pipeline* processes drawing commands and writes data into a render pass’s targets. + A render pipeline has many stages, some programmed using shaders and others with fixed or configurable behavior. +This sample focuses on the three main stages of the pipeline: the vertex stage, the rasterization stage, and the fragment stage. +The vertex stage and fragment stage are programmable, so you write functions for them in Metal Shading Language (MSL). +The rasterization stage has fixed behavior. + +**Figure 1** Main stages of the Metal graphics render pipeline +![Main Stages of the Metal Graphics Render Pipeline](Documentation/SimplePipeline.png) + +Rendering starts with a drawing command, which includes a vertex count and what kind of primitive to render. For example, here's the drawing command from this sample: + +``` objective-c +// Draw the triangle. +[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle + vertexStart:0 + vertexCount:3]; +``` + +The vertex stage provides data for each vertex. When enough vertices have been processed, the render pipeline rasterizes the primitive, determining which pixels in the render targets lie within the boundaries of the primitive. The fragment stage determines the values to write into the render targets for those pixels. + +In the rest of this sample, you will see how to write the vertex and fragment functions, how to create the render pipeline state object, and finally, how to encode a draw command that uses this pipeline. + +## Decide How Data is Processed by Your Custom Render Pipeline + +A vertex function generates data for a single vertex and a fragment function generates data for a single fragment, but you decide how they work. +You configure the stages of the pipeline with a goal in mind, meaning that you know what you want the pipeline to generate and how it generates those results. + +Decide what data to pass into your render pipeline and what data is passed to later stages of the pipeline. There are typically three places where you do this: + +- The inputs to the pipeline, which are provided by your app and passed to the vertex stage. +- The outputs of the vertex stage, which is passed to the rasterization stage. +- The inputs to the fragment stage, which are provided by your app or generated by the rasterization stage. + +In this sample, the input data for the pipeline is the position of a vertex and its color. To demonstrate the kind of transformation you typically perform in a vertex function, input coordinates are defined in a custom coordinate space, measured in pixels from the center of the view. These coordinates need to be translated into Metal's coordinate system. + +Declare an `AAPLVertex` structure, using SIMD vector types to hold the position and color data. +To share a single definition for how the structure is laid out in memory, declare the structure in a common header and import it in both the Metal shader and the app. + +``` objective-c +typedef struct +{ + vector_float2 position; + vector_float4 color; +} AAPLVertex; +``` + +SIMD types are commonplace in Metal Shading Language, and you should also use them in your app using the simd library. +SIMD types contain multiple channels of a particular data type, so declaring the position as a `vector_float2` means it contains two 32-bit float values (which will hold the x and y coordinates.) +Colors are stored using a `vector_float4`, so they have four channels – red, green, blue, and alpha. + +In the app, the input data is specified using a constant array: + +``` objective-c +static const AAPLVertex triangleVertices[] = +{ + // 2D positions, RGBA colors + { { 250, -250 }, { 1, 0, 0, 1 } }, + { { -250, -250 }, { 0, 1, 0, 1 } }, + { { 0, 250 }, { 0, 0, 1, 1 } }, +}; +``` + +The vertex stage generates data for a vertex, so it needs to provide a color and a transformed position. +Declare a `RasterizerData` structure containing a position and a color value, again using SIMD types. + +``` metal +struct RasterizerData +{ + // The [[position]] attribute of this member indicates that this value + // is the clip space position of the vertex when this structure is + // returned from the vertex function. + float4 position [[position]]; + + // Since this member does not have a special attribute, the rasterizer + // interpolates its value with the values of the other triangle vertices + // and then passes the interpolated value to the fragment shader for each + // fragment in the triangle. + float4 color; +}; +``` + +The output position (described in detail below) must be defined as a `vector_float4`. The color is declared as it was in the input data structure. + +You need to tell Metal which field in the rasterization data provides position data, because Metal doesn't enforce any particular naming convention for fields in your struct. +Annotate the `position` field with the `[[position]]` attribute qualifier to declare that this field holds the output position. + +The fragment function simply passes the rasterization stage's data to later stages so it doesn't need any additional arguments. + +## Declare the Vertex Function + +Declare the vertex function, including its input arguments and the data it outputs. +Much like compute functions were declared using the `kernel` keyword, you declare a vertex function using the `vertex` keyword. + +``` metal +vertex RasterizerData +vertexShader(uint vertexID [[vertex_id]], + constant AAPLVertex *vertices [[buffer(AAPLVertexInputIndexVertices)]], + constant vector_uint2 *viewportSizePointer [[buffer(AAPLVertexInputIndexViewportSize)]]) +``` + +The first argument, `vertexID`, uses the `[[vertex_id]]` attribute qualifier, which is another Metal keyword. +When you execute a render command, the GPU calls your vertex function multiple times, generating a unique value for each vertex. + +The second argument, `vertices`, is an array that contains the vertex data, using the `AAPLVertex` struct previously defined. + +To transform the position into Metal's coordinates, the function needs the size of the viewport (in pixels) that the triangle is being drawn into, so this is stored in the `viewportSizePointer` argument. + +The second and third arguments have the `[[buffer(n)]]` attribute qualifier. +By default, Metal assigns slots in the argument table for each parameter automatically. +When you add the `[[buffer(n)]]` qualifier to a buffer argument, you tell Metal explicitly which slot to use. +Declaring slots explicitly can make it easier to revise your shaders without also needing to change your app code. +Declare the constants for the two indicies in the shared header file. + +The function's output is a `RasterizerData` struct. + +## Write the Vertex Function + +Your vertex function must generate both fields of the output struct. +Use the `vertexID` argument to index into the `vertices` array and read the input data for the vertex. +Also, retrieve the viewport dimensions. + +``` metal +float2 pixelSpacePosition = vertices[vertexID].position.xy; + +// Get the viewport size and cast to float. +vector_float2 viewportSize = vector_float2(*viewportSizePointer); + +``` + +Vertex functions must provide position data in *clip-space coordinates*, which are 3D points specified using a four-dimensional homogenous vector (`x,y,z,w`). The rasterization stage takes the output position and divides the `x`,`y`, and `z` coordinates by `w` to generate a 3D point in *normalized device coordinates*. Normalized device coordinates are independent of viewport size. + +**Figure 2** Normalized device coordinate system +![Normalized device coordinate system](Documentation/normalizeddevicecoords.png) + +Normalized device coordinates use a *left-handed coordinate system* and map to positions in the viewport. +Primitives are clipped to a box in this coordinate system and then rasterized. +The lower-left corner of the clipping box is at an `(x,y)` coordinate of `(-1.0,-1.0)` and the upper-right corner is at `(1.0,1.0)`. +Positive-z values point away from the camera (into the screen.) +The visible portion of the `z` coordinate is between `0.0` (the near clipping plane) and `1.0` (the far clipping plane). + +Transform the input coordinate system to the normalized device coordinate system. + +![Vertex function coordinate transformation](Documentation/metal-coordinate-transformation.png) + +Because this is a 2D application and does not need homogenous coordinates, first write a default value to the output coordinate, with the the `w` value is set to `1.0` and the other coordinates set to `0.0`. +This means that the coordinates are already in the normalized device coordinate space and the vertex function should generate (x,y) coordinates in that coordinate space. +Divide the input position by half the viewport size to generate normalized device coordinates. +Since this calculation is performed using SIMD types, both channels can be divided at the same time using a single line of code. +Perform the divide and put the results in the x and y channels of the output position. + +``` metal +out.position = vector_float4(0.0, 0.0, 0.0, 1.0); +out.position.xy = pixelSpacePosition / (viewportSize / 2.0); +``` + +Finally, copy the color value into the `out.color` return value. + +``` metal +out.color = vertices[vertexID].color; +``` + +## Write a Fragment Function + +A *fragment* is a possible change to the render targets. The rasterizer determines which pixels of the render target are covered by the primitive. +Only fragments whose pixel centers are inside the triangle are rendered. + +**Figure 3** Fragments generated by the rasterization stage +![Fragments generated by the rasterization stage](Documentation/Rasterization.png) + +A fragment function processes incoming information from the rasterizer for a single position and calculates output values for each of the render targets. These fragment values are processed by later stages in the pipeline, eventually being written to the render targets. + +- Note: The reason a fragment is called a possible change is because the pipeline stages after the fragment stage can be configured to reject some fragments or change what gets written to the render targets. In this sample, all values calculated by the fragment stage are written as-is to the render target. + +The fragment shader in this sample receives the same parameters that were declared in the vertex shader's output. Declare the fragment function using the `fragment` keyword. It takes a single argument, the same `RasterizerData` structure that was provided by the vertex stage. Add the `[[stage_in]]` attribute qualifier to indicate that this argument is generated by the rasterizer. + +``` metal +fragment float4 fragmentShader(RasterizerData in [[stage_in]]) +``` + +If your fragment function writes to multiple render targets, it must declare a struct with fields for each render target. +Because this sample only has a single render target, you specify a floating-point vector directly as the function's output. This output is the color to be written to the render target. + +The rasterization stage calculates values for each fragment's arguments and calls the fragment function with them. +The rasterization stage calculates its color argument as a blend of the colors at the triangle's vertices. +The closer a fragment is to a vertex, the more that vertex contributes to the final color. + +**Figure 4** Interpolated fragment colors +![Interpolated Fragment Colors](Documentation/Interpolation.png) + +Return the interpolated color as the function's output. + +``` metal +return in.color; +``` + +## Create a Render Pipeline State Object + +Now that the functions are complete, you can create a render pipeline that uses them. +First, get the default library and obtain a [`MTLFunction`][MTLFunction] object for each function. + +``` objective-c +id defaultLibrary = [_device newDefaultLibrary]; + +id vertexFunction = [defaultLibrary newFunctionWithName:@"vertexShader"]; +id fragmentFunction = [defaultLibrary newFunctionWithName:@"fragmentShader"]; +``` + +Next, create a [`MTLRenderPipelineState`][MTLRenderPipelineState] object. +Render pipelines have more stages to configure, so you use a [`MTLRenderPipelineDescriptor`][MTLRenderPipelineDescriptor] to configure the pipeline. + +``` objective-c +MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; +pipelineStateDescriptor.label = @"Simple Pipeline"; +pipelineStateDescriptor.vertexFunction = vertexFunction; +pipelineStateDescriptor.fragmentFunction = fragmentFunction; +pipelineStateDescriptor.colorAttachments[0].pixelFormat = mtkView.colorPixelFormat; + +_pipelineState = [_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor + error:&error]; +``` + +In addition to specifying the vertex and fragment functions, you also declare the *pixel format* of all render targets that the pipeline will draw into. +A pixel format ([`MTLPixelFormat`][MTLPixelFormat]) defines the memory layout of pixel data. +For simple formats, this definition includes the number of bytes per pixel, the number of channels of data stored in a pixel, and the bit layout of those channels. +Since this sample only has one render target and it is provided by the view, copy the view's pixel format into the render pipeline descriptor. +Your render pipeline state must use a pixel format that is compatible with the one specified by the render pass. +In this sample, the render pass and the pipeline state object both use the view's pixel format, so they are always the same. + +When Metal creates the render pipeline state object, the pipeline is configured to convert the fragment function's output into the render target's pixel format. +If you want to target a different pixel format, you need to create a different pipeline state object. +You can reuse the same shaders in multiple pipelines targeting different pixel formats. + + +## Set a Viewport + +Now that you have the render pipeline state object for the pipeline, you'll render the triangle. You do this using a render command encoder. First, set the viewport, so that Metal knows which part of the render target you want to draw into. + +``` objective-c +// Set the region of the drawable to draw into. +[renderEncoder setViewport:(MTLViewport){0.0, 0.0, _viewportSize.x, _viewportSize.y, 0.0, 1.0 }]; +``` + +## Set the Render Pipeline State + +Set the render pipeline state for the pipeline you want to use. + +``` objective-c +[renderEncoder setRenderPipelineState:_pipelineState]; +``` + +## Send Argument Data to the Vertex Function + +Often, you use buffers ([`MTLBuffer`][MTLBuffer]) to pass data to shaders. +However, when you need to pass only a small amount of data to the vertex function, as is the case here, copy the data directly into the command buffer. + +The sample copies data for both parameters into the command buffer. +The vertex data is copied from an array defined in the sample. +The viewport data is copied from the same variable that you used to set the viewport. + +In this sample, the fragment function uses only the data it receives from the rasterizer, so there are no arguments to set. + +``` objective-c +[renderEncoder setVertexBytes:triangleVertices + length:sizeof(triangleVertices) + atIndex:AAPLVertexInputIndexVertices]; + +[renderEncoder setVertexBytes:&_viewportSize + length:sizeof(_viewportSize) + atIndex:AAPLVertexInputIndexViewportSize]; +``` + + +## Encode the Drawing Command + +Specify the kind of primitive, the starting index, and the number of vertices. +When the triangle is rendered, the vertex function is called with values of 0, 1, and 2 for the `vertexID` argument. + +``` objective-c +// Draw the triangle. +[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle + vertexStart:0 + vertexCount:3]; +``` + +As with Drawing to the Screen Using Metal, you end the encoding process and commit the command buffer. +However, you could encode more render commands using the same set of steps. +The final image is rendered as if the commands were processed in the order they were specified. +(For performance, the GPU is allowed to process commands or even parts of commands in parallel, so long as the final result appears to have been rendered in order. ) + +## Experiment with the Color Interpolation + +In this sample, color values were interpolated across the triangle. +That's often what you want, but sometimes you want a value to be generated by one vertex and remain constant across the whole primitive. +Specify the `flat` attribute qualifier on an output of the vertex function to do this. +Try this now. +Find the definition of `RasterizerData` in the sample project and add the `[[flat]]` qualifier to its `color` field. + +`float4 color [[flat]];` + +Run the sample again. +The render pipeline uses the color value from the first vertex (called the *provoking vertex*) uniformly across the triangle, and it ignores the colors from the other two vertices. +You can use a mix of flat shaded and interpolated values, simply by adding or omitting the `flat` qualifier on your vertex function's outputs. +The [Metal Shading Language specification][ShadingLanguageSpec] defines other attribute qualifiers you can also use to modify the rasterization behavior. + +[ScreenDrawing]: https://developer.apple.com/documentation/metal +[MTLDevice]: https://developer.apple.com/documentation/metal/mtldevice +[MTLResource]: https://developer.apple.com/documentation/metal/mtlresource +[MTLBuffer]: https://developer.apple.com/documentation/metal/mtlbuffer +[MTLRenderPipelineState]: https://developer.apple.com/documentation/metal/mtlrenderpipelinestate +[MTLRenderPipelineDescriptor]: https://developer.apple.com/documentation/metal/mtlrenderpipelinedescriptor +[MTLRenderCommandEncoder]: https://developer.apple.com/documentation/metal/mtlrendercommandencoder +[MTLPixelFormat]: https://developer.apple.com/documentation/metal/mtlpixelformat +[MTKView]: https://developer.apple.com/documentation/metalkit/mtkview +[ShadingLanguageSpec]: https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf +[MTLFunction]: https://developer.apple.com/documentation/metal/mtlfunction diff --git a/tests/projects/objc/metal_app/Renderer/AAPLRenderer.h b/tests/projects/objc/metal_app/Renderer/AAPLRenderer.h new file mode 100644 index 000000000..f7bcba51d --- /dev/null +++ b/tests/projects/objc/metal_app/Renderer/AAPLRenderer.h @@ -0,0 +1,14 @@ +/* +See LICENSE folder for this sample’s licensing information. + +Abstract: +Header for a platform independent renderer class, which performs Metal setup and per frame rendering. +*/ + +@import MetalKit; + +@interface AAPLRenderer : NSObject + +- (nonnull instancetype)initWithMetalKitView:(nonnull MTKView *)mtkView; + +@end diff --git a/tests/projects/objc/metal_app/Renderer/AAPLRenderer.m b/tests/projects/objc/metal_app/Renderer/AAPLRenderer.m new file mode 100644 index 000000000..124bd29ff --- /dev/null +++ b/tests/projects/objc/metal_app/Renderer/AAPLRenderer.m @@ -0,0 +1,132 @@ +/* +See LICENSE folder for this sample’s licensing information. + +Abstract: +Implementation of a platform independent renderer class, which performs Metal setup and per frame rendering +*/ + +@import simd; +@import MetalKit; + +#import "AAPLRenderer.h" + +// Header shared between C code here, which executes Metal API commands, and .metal files, which +// uses these types as inputs to the shaders. +#import "AAPLShaderTypes.h" + +// Main class performing the rendering +@implementation AAPLRenderer +{ + id _device; + + // The render pipeline generated from the vertex and fragment shaders in the .metal shader file. + id _pipelineState; + + // The command queue used to pass commands to the device. + id _commandQueue; + + // The current size of the view, used as an input to the vertex shader. + vector_uint2 _viewportSize; +} + +- (nonnull instancetype)initWithMetalKitView:(nonnull MTKView *)mtkView +{ + self = [super init]; + if(self) + { + NSError *error; + + _device = mtkView.device; + + // Load all the shader files with a .metal file extension in the project. + id defaultLibrary = [_device newDefaultLibrary]; + + id vertexFunction = [defaultLibrary newFunctionWithName:@"vertexShader"]; + id fragmentFunction = [defaultLibrary newFunctionWithName:@"fragmentShader"]; + + // Configure a pipeline descriptor that is used to create a pipeline state. + MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; + pipelineStateDescriptor.label = @"Simple Pipeline"; + pipelineStateDescriptor.vertexFunction = vertexFunction; + pipelineStateDescriptor.fragmentFunction = fragmentFunction; + pipelineStateDescriptor.colorAttachments[0].pixelFormat = mtkView.colorPixelFormat; + + _pipelineState = [_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor + error:&error]; + + // Pipeline State creation could fail if the pipeline descriptor isn't set up properly. + // If the Metal API validation is enabled, you can find out more information about what + // went wrong. (Metal API validation is enabled by default when a debug build is run + // from Xcode.) + NSAssert(_pipelineState, @"Failed to create pipeline state: %@", error); + + // Create the command queue + _commandQueue = [_device newCommandQueue]; + } + + return self; +} + +/// Called whenever view changes orientation or is resized +- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size +{ + // Save the size of the drawable to pass to the vertex shader. + _viewportSize.x = size.width; + _viewportSize.y = size.height; +} + +/// Called whenever the view needs to render a frame. +- (void)drawInMTKView:(nonnull MTKView *)view +{ + static const AAPLVertex triangleVertices[] = + { + // 2D positions, RGBA colors + { { 250, -250 }, { 1, 0, 0, 1 } }, + { { -250, -250 }, { 0, 1, 0, 1 } }, + { { 0, 250 }, { 0, 0, 1, 1 } }, + }; + + // Create a new command buffer for each render pass to the current drawable. + id commandBuffer = [_commandQueue commandBuffer]; + commandBuffer.label = @"MyCommand"; + + // Obtain a renderPassDescriptor generated from the view's drawable textures. + MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor; + + if(renderPassDescriptor != nil) + { + // Create a render command encoder. + id renderEncoder = + [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; + renderEncoder.label = @"MyRenderEncoder"; + + // Set the region of the drawable to draw into. + [renderEncoder setViewport:(MTLViewport){0.0, 0.0, _viewportSize.x, _viewportSize.y, 0.0, 1.0 }]; + + [renderEncoder setRenderPipelineState:_pipelineState]; + + // Pass in the parameter data. + [renderEncoder setVertexBytes:triangleVertices + length:sizeof(triangleVertices) + atIndex:AAPLVertexInputIndexVertices]; + + [renderEncoder setVertexBytes:&_viewportSize + length:sizeof(_viewportSize) + atIndex:AAPLVertexInputIndexViewportSize]; + + // Draw the triangle. + [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle + vertexStart:0 + vertexCount:3]; + + [renderEncoder endEncoding]; + + // Schedule a present once the framebuffer is complete using the current drawable. + [commandBuffer presentDrawable:view.currentDrawable]; + } + + // Finalize rendering here & push the command buffer to the GPU. + [commandBuffer commit]; +} + +@end diff --git a/tests/projects/objc/metal_app/Renderer/AAPLShaderTypes.h b/tests/projects/objc/metal_app/Renderer/AAPLShaderTypes.h new file mode 100644 index 000000000..b3355f911 --- /dev/null +++ b/tests/projects/objc/metal_app/Renderer/AAPLShaderTypes.h @@ -0,0 +1,31 @@ +/* +See LICENSE folder for this sample’s licensing information. + +Abstract: +Header containing types and enum constants shared between Metal shaders and C/ObjC source +*/ + +#ifndef AAPLShaderTypes_h +#define AAPLShaderTypes_h + +#include + +// Buffer index values shared between shader and C code to ensure Metal shader buffer inputs +// match Metal API buffer set calls. +typedef enum AAPLVertexInputIndex +{ + AAPLVertexInputIndexVertices = 0, + AAPLVertexInputIndexViewportSize = 1, +} AAPLVertexInputIndex; + +// This structure defines the layout of vertices sent to the vertex +// shader. This header is shared between the .metal shader and C code, to guarantee that +// the layout of the vertex array in the C code matches the layout that the .metal +// vertex shader expects. +typedef struct +{ + vector_float2 position; + vector_float4 color; +} AAPLVertex; + +#endif /* AAPLShaderTypes_h */ diff --git a/tests/projects/objc/metal_app/Renderer/AAPLShaders.metal b/tests/projects/objc/metal_app/Renderer/AAPLShaders.metal new file mode 100644 index 000000000..62b05cf71 --- /dev/null +++ b/tests/projects/objc/metal_app/Renderer/AAPLShaders.metal @@ -0,0 +1,62 @@ +/* +See LICENSE folder for this sample’s licensing information. + +Abstract: +Metal shaders used for this sample +*/ + +#include + +using namespace metal; + +// Include header shared between this Metal shader code and C code executing Metal API commands. +#include "AAPLShaderTypes.h" + +// Vertex shader outputs and fragment shader inputs +struct RasterizerData +{ + // The [[position]] attribute of this member indicates that this value + // is the clip space position of the vertex when this structure is + // returned from the vertex function. + float4 position [[position]]; + + // Since this member does not have a special attribute, the rasterizer + // interpolates its value with the values of the other triangle vertices + // and then passes the interpolated value to the fragment shader for each + // fragment in the triangle. + float4 color; +}; + +vertex RasterizerData +vertexShader(uint vertexID [[vertex_id]], + constant AAPLVertex *vertices [[buffer(AAPLVertexInputIndexVertices)]], + constant vector_uint2 *viewportSizePointer [[buffer(AAPLVertexInputIndexViewportSize)]]) +{ + RasterizerData out; + + // Index into the array of positions to get the current vertex. + // The positions are specified in pixel dimensions (i.e. a value of 100 + // is 100 pixels from the origin). + float2 pixelSpacePosition = vertices[vertexID].position.xy; + + // Get the viewport size and cast to float. + vector_float2 viewportSize = vector_float2(*viewportSizePointer); + + + // To convert from positions in pixel space to positions in clip-space, + // divide the pixel coordinates by half the size of the viewport. + out.position = vector_float4(0.0, 0.0, 0.0, 1.0); + out.position.xy = pixelSpacePosition / (viewportSize / 2.0); + + // Pass the input color directly to the rasterizer. + out.color = vertices[vertexID].color; + + return out; +} + +fragment float4 fragmentShader(RasterizerData in [[stage_in]]) +{ + // Return the interpolated color. + return in.color; +} + diff --git a/tests/projects/objc/metal_app/xmake.lua b/tests/projects/objc/metal_app/xmake.lua new file mode 100644 index 000000000..54a94b26d --- /dev/null +++ b/tests/projects/objc/metal_app/xmake.lua @@ -0,0 +1,22 @@ +add_rules("mode.debug", "mode.release") + +target("HelloTriangle") + add_rules("xcode.application") + add_includedirs("Renderer") + add_frameworks("MetalKit") + add_mflags("-fmodules") + add_files("Renderer/*.m") + if is_plat("macosx") then + add_files("Application/main.m") + add_files("Application/AAPLViewController.m") + add_files("Application/macOS/Info.plist") + add_files("Application/macOS/Base.lproj/*.storyboard") + add_defines("TARGET_MACOS") + add_frameworks("AppKit") + elseif is_plat("iphoneos") then + add_files("Application/*.m") + add_files("Application/iOS/Info.plist") + add_files("Application/iOS/Base.lproj/*.storyboard") + add_frameworks("UIKit") + add_defines("TARGET_IOS") + end -- cgit v1.3.1 From f677b70f1725e3d5d61b38e5c4caf53955f4cd77 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 22 Aug 2021 20:00:48 +0800 Subject: add metal rule stub --- tests/projects/objc/metal_app/xmake.lua | 2 +- xmake/rules/xcode/application/xmake.lua | 4 ++-- xmake/rules/xcode/metal/xmake.lua | 29 +++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 xmake/rules/xcode/metal/xmake.lua diff --git a/tests/projects/objc/metal_app/xmake.lua b/tests/projects/objc/metal_app/xmake.lua index 54a94b26d..2a808a5fb 100644 --- a/tests/projects/objc/metal_app/xmake.lua +++ b/tests/projects/objc/metal_app/xmake.lua @@ -5,7 +5,7 @@ target("HelloTriangle") add_includedirs("Renderer") add_frameworks("MetalKit") add_mflags("-fmodules") - add_files("Renderer/*.m") + add_files("Renderer/*.m", "Renderer/*.metal") if is_plat("macosx") then add_files("Application/main.m") add_files("Application/AAPLViewController.m") diff --git a/xmake/rules/xcode/application/xmake.lua b/xmake/rules/xcode/application/xmake.lua index 5984bbb55..51232f033 100644 --- a/xmake/rules/xcode/application/xmake.lua +++ b/xmake/rules/xcode/application/xmake.lua @@ -21,8 +21,8 @@ -- define rule: xcode application rule("xcode.application") - -- support add_files("Info.plist", "*.storyboard", "*.xcassets") - add_deps("xcode.info_plist", "xcode.storyboard", "xcode.xcassets") + -- support add_files("Info.plist", "*.storyboard", "*.xcassets", "*.metal") + add_deps("xcode.info_plist", "xcode.storyboard", "xcode.xcassets", "xcode.metal") -- we must set kind before target.on_load(), may we will use target in on_load() before_load("load") diff --git a/xmake/rules/xcode/metal/xmake.lua b/xmake/rules/xcode/metal/xmake.lua new file mode 100644 index 000000000..24c4ecb2a --- /dev/null +++ b/xmake/rules/xcode/metal/xmake.lua @@ -0,0 +1,29 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +rule("xcode.metal") + + -- support add_files("*.metal") + set_extensions(".metal") + + -- build *.metal to *.metallib + on_build_file(function (target, sourcefile, opt) + + end) -- cgit v1.3.1 From c5d07f91362cb32737b6cdbf22188fcad70afd10 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 22 Aug 2021 20:41:39 +0800 Subject: fix add_moduledirs --- .../sandbox/modules/import/core/sandbox/module.lua | 23 ++++++++++------------ 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/xmake/core/sandbox/modules/import/core/sandbox/module.lua b/xmake/core/sandbox/modules/import/core/sandbox/module.lua index f5b45f6f8..ab859ab95 100644 --- a/xmake/core/sandbox/modules/import/core/sandbox/module.lua +++ b/xmake/core/sandbox/modules/import/core/sandbox/module.lua @@ -28,6 +28,7 @@ local utils = require("base/utils") local table = require("base/table") local string = require("base/string") local global = require("base/global") +local memcache = require("cache/memcache") local sandbox = require("sandbox/sandbox") local raise = require("sandbox/modules/raise") @@ -287,31 +288,27 @@ end -- get module directories function core_sandbox_module.directories() - local directories = core_sandbox_module._DIRS - if not directories then - directories = { path.join(global.directory(), "modules"), - path.join(os.programdir(), "modules"), - path.join(os.programdir(), "core/sandbox/modules/import")} + local moduledirs = memcache.get("core_sandbox_module", "moduledirs") + if not moduledirs then + moduledirs = { path.join(global.directory(), "modules"), + path.join(os.programdir(), "modules"), + path.join(os.programdir(), "core/sandbox/modules/import")} local modulesdir = os.getenv("XMAKE_MODULES_DIR") if modulesdir and os.isdir(modulesdir) then - table.insert(directories, 1, modulesdir) + table.insert(moduledirs, 1, modulesdir) end - core_sandbox_module._DIRS = directories + memcache.set("core_sandbox_module", "moduledirs", moduledirs) end - return directories + return moduledirs end -- add module directories function core_sandbox_module.add_directories(...) - - -- add directories local moduledirs = core_sandbox_module.directories() for _, dir in ipairs({...}) do table.insert(moduledirs, 1, dir) end - - -- remove unique directories - core_sandbox_module._DIRS = table.unique(moduledirs) + memcache.set("core_sandbox_module", "moduledirs", table.unique(moduledirs)) end -- find module -- cgit v1.3.1 From cb1c001283da2daadb3cc5bb986ac3c45c696ba3 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 22 Aug 2021 20:52:13 +0800 Subject: add find_metalxx --- xmake/modules/detect/tools/find_metal.lua | 50 ++++++++++++++++++++++++++++ xmake/modules/detect/tools/find_metallib.lua | 50 ++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 xmake/modules/detect/tools/find_metal.lua create mode 100644 xmake/modules/detect/tools/find_metallib.lua diff --git a/xmake/modules/detect/tools/find_metal.lua b/xmake/modules/detect/tools/find_metal.lua new file mode 100644 index 000000000..71a01728b --- /dev/null +++ b/xmake/modules/detect/tools/find_metal.lua @@ -0,0 +1,50 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_metal.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find metal +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local metal = find_metal() +-- local metal, version = find_metal({program = "xcrun -sdk macosx metal", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- find program + opt = opt or {} + local program = find_program(opt.program or "xcrun -sdk macosx metal", opt) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, opt) + end + return program, version +end diff --git a/xmake/modules/detect/tools/find_metallib.lua b/xmake/modules/detect/tools/find_metallib.lua new file mode 100644 index 000000000..6989729f9 --- /dev/null +++ b/xmake/modules/detect/tools/find_metallib.lua @@ -0,0 +1,50 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_metallib.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find metallib +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local metallib = find_metallib() +-- local metallib, version = find_metallib({program = "xcrun -sdk macosx metallib", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- find program + opt = opt or {} + local program = find_program(opt.program or "xcrun -sdk macosx metallib", opt) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, opt) + end + return program, version +end -- cgit v1.3.1 From be345812688e069c9b83cce60e2b9b40a63eca58 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 22 Aug 2021 21:04:40 +0800 Subject: compile metal --- xmake/rules/xcode/metal/xmake.lua | 40 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/xmake/rules/xcode/metal/xmake.lua b/xmake/rules/xcode/metal/xmake.lua index 24c4ecb2a..5e216cc37 100644 --- a/xmake/rules/xcode/metal/xmake.lua +++ b/xmake/rules/xcode/metal/xmake.lua @@ -23,7 +23,43 @@ rule("xcode.metal") -- support add_files("*.metal") set_extensions(".metal") - -- build *.metal to *.metallib - on_build_file(function (target, sourcefile, opt) + on_load(function (target) + local cross + if target:is_plat("macosx") then + cross = "xcrun -sdk macosx " + elseif target:is_plat("iphoneos") then + cross = target:is_arch("i386", "x86_64") and "xcrun -sdk iphonesimulator " or "xcrun -sdk iphoneos " + elseif target:is_plat("watchos") then + cross = target:is_arch("i386") and "xcrun -sdk watchsimulator " or "xcrun -sdk watchos " + elseif target:is_plat("appletvos") then + cross = target:is_arch("i386", "x86_64") and "xcrun -sdk appletvsimulator " or "xcrun -sdk appletvos " + else + raise("unknown platform for xcode!") + end + target:data_set("xcode.metal.cross", cross) + end) + + -- build *.metal to *.air + on_buildcmd_file(function (target, batchcmds, sourcefile, opt) + + -- get metal + import("lib.detect.find_tool") + local cross = target:data("xcode.metal.cross") + local metal = assert(find_tool("metal", {program = cross .. " metal"}), "metal command not found!") + + -- add objectfile (.air) + local objectfile = target:objectfile(sourcefile) .. ".air" + + -- add commands + batchcmds:show_progress(opt.progress, "${color.build.object}compiling.metal %s", sourcefile) + batchcmds:mkdir(path.directory(objectfile)) + batchcmds:vrunv(metal.program, {"-c", "-o", objectfile, sourcefile}) + + -- add deps + batchcmds:add_depfiles(sourcefile) + batchcmds:set_depmtime(os.mtime(objectfile)) + batchcmds:set_depcache(target:dependfile(objectfile)) end) + + -- link *.air to *.metallib -- cgit v1.3.1 From edf32980cd66c2ee5075ddd9e4a08c7e50f6985e Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 22 Aug 2021 21:14:42 +0800 Subject: add xxx_linkcmd --- xmake/core/project/rule.lua | 3 +++ xmake/rules/xcode/metal/xmake.lua | 3 +++ 2 files changed, 6 insertions(+) diff --git a/xmake/core/project/rule.lua b/xmake/core/project/rule.lua index 87a082888..c155a813f 100644 --- a/xmake/core/project/rule.lua +++ b/xmake/core/project/rule.lua @@ -174,6 +174,7 @@ function rule.apis() , "rule.on_package" , "rule.on_install" , "rule.on_uninstall" + , "rule.on_linkcmd" , "rule.on_buildcmd" , "rule.on_buildcmd_file" , "rule.on_buildcmd_files" @@ -188,6 +189,7 @@ function rule.apis() , "rule.before_package" , "rule.before_install" , "rule.before_uninstall" + , "rule.before_linkcmd" , "rule.before_buildcmd" , "rule.before_buildcmd_file" , "rule.before_buildcmd_files" @@ -202,6 +204,7 @@ function rule.apis() , "rule.after_package" , "rule.after_install" , "rule.after_uninstall" + , "rule.after_linkcmd" , "rule.after_buildcmd" , "rule.after_buildcmd_file" , "rule.after_buildcmd_files" diff --git a/xmake/rules/xcode/metal/xmake.lua b/xmake/rules/xcode/metal/xmake.lua index 5e216cc37..d4bc50fea 100644 --- a/xmake/rules/xcode/metal/xmake.lua +++ b/xmake/rules/xcode/metal/xmake.lua @@ -63,3 +63,6 @@ rule("xcode.metal") end) -- link *.air to *.metallib + on_linkcmd(function (target, batchcmds, opt) + print("linkcmd") + end) -- cgit v1.3.1 From df288a44eb6c8277d250306add709f9f5f59f0cd Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 22 Aug 2021 21:35:23 +0800 Subject: link metallib --- xmake/actions/build/kinds/binary.lua | 20 ++++++++++++++++++++ xmake/actions/build/kinds/shared.lua | 20 ++++++++++++++++++++ xmake/actions/build/kinds/static.lua | 20 ++++++++++++++++++++ xmake/rules/xcode/metal/xmake.lua | 36 ++++++++++++++++++++++++++++++------ 4 files changed, 90 insertions(+), 6 deletions(-) diff --git a/xmake/actions/build/kinds/binary.lua b/xmake/actions/build/kinds/binary.lua index dd72fc21a..b84b518de 100644 --- a/xmake/actions/build/kinds/binary.lua +++ b/xmake/actions/build/kinds/binary.lua @@ -25,6 +25,7 @@ import("core.tool.linker") import("core.tool.compiler") import("core.project.depend") import("private.utils.progress") +import("private.utils.batchcmds") import("object", {alias = "add_batchjobs_for_object"}) -- do link target @@ -87,6 +88,13 @@ function _on_link_target(target, opt) on_link(target, opt) done = true end + local on_linkcmd = r:script("linkcmd") + if on_linkcmd then + local batchcmds_ = batchcmds.new({target = target}) + on_linkcmd(target, batchcmds_, {progress = opt.progress}) + batchcmds_:runcmds({dryrun = option.get("dry-run")}) + done = true + end end if done then return end @@ -109,6 +117,12 @@ function _link_target(target, opt) if before_link then before_link(target, opt) end + local before_linkcmd = r:script("linkcmd_before") + if before_linkcmd then + local batchcmds_ = batchcmds.new({target = target}) + before_linkcmd(target, batchcmds_, {progress = opt.progress}) + batchcmds_:runcmds({dryrun = option.get("dry-run")}) + end end -- on link @@ -126,6 +140,12 @@ function _link_target(target, opt) if after_link then after_link(target, opt) end + local after_linkcmd = r:script("linkcmd_after") + if after_linkcmd then + local batchcmds_ = batchcmds.new({target = target}) + after_linkcmd(target, batchcmds_, {progress = opt.progress}) + batchcmds_:runcmds({dryrun = option.get("dry-run")}) + end end end diff --git a/xmake/actions/build/kinds/shared.lua b/xmake/actions/build/kinds/shared.lua index 2d2d9e507..376d73af3 100644 --- a/xmake/actions/build/kinds/shared.lua +++ b/xmake/actions/build/kinds/shared.lua @@ -25,6 +25,7 @@ import("core.tool.linker") import("core.tool.compiler") import("core.project.depend") import("private.utils.progress") +import("private.utils.batchcmds") import("object", {alias = "add_batchjobs_for_object"}) -- do link target @@ -102,6 +103,13 @@ function _on_link_target(target, opt) on_link(target, opt) done = true end + local on_linkcmd = r:script("linkcmd") + if on_linkcmd then + local batchcmds_ = batchcmds.new({target = target}) + on_linkcmd(target, batchcmds_, {progress = opt.progress}) + batchcmds_:runcmds({dryrun = option.get("dry-run")}) + done = true + end end if done then return end @@ -124,6 +132,12 @@ function _link_target(target, opt) if before_link then before_link(target, opt) end + local before_linkcmd = r:script("linkcmd_before") + if before_linkcmd then + local batchcmds_ = batchcmds.new({target = target}) + before_linkcmd(target, batchcmds_, {progress = opt.progress}) + batchcmds_:runcmds({dryrun = option.get("dry-run")}) + end end -- on link @@ -141,6 +155,12 @@ function _link_target(target, opt) if after_link then after_link(target, opt) end + local after_linkcmd = r:script("linkcmd_after") + if after_linkcmd then + local batchcmds_ = batchcmds.new({target = target}) + after_linkcmd(target, batchcmds_, {progress = opt.progress}) + batchcmds_:runcmds({dryrun = option.get("dry-run")}) + end end end diff --git a/xmake/actions/build/kinds/static.lua b/xmake/actions/build/kinds/static.lua index 91fba6ed5..b3ac57e73 100644 --- a/xmake/actions/build/kinds/static.lua +++ b/xmake/actions/build/kinds/static.lua @@ -25,6 +25,7 @@ import("core.tool.linker") import("core.tool.compiler") import("core.project.depend") import("private.utils.progress") +import("private.utils.batchcmds") import("object", {alias = "add_batchjobs_for_object"}) -- do link target @@ -102,6 +103,13 @@ function _on_link_target(target, opt) on_link(target, opt) done = true end + local on_linkcmd = r:script("linkcmd") + if on_linkcmd then + local batchcmds_ = batchcmds.new({target = target}) + on_linkcmd(target, batchcmds_, {progress = opt.progress}) + batchcmds_:runcmds({dryrun = option.get("dry-run")}) + done = true + end end if done then return end @@ -124,6 +132,12 @@ function _link_target(target, opt) if before_link then before_link(target, opt) end + local before_linkcmd = r:script("linkcmd_before") + if before_linkcmd then + local batchcmds_ = batchcmds.new({target = target}) + before_linkcmd(target, batchcmds_, {progress = opt.progress}) + batchcmds_:runcmds({dryrun = option.get("dry-run")}) + end end -- on link @@ -141,6 +155,12 @@ function _link_target(target, opt) if after_link then after_link(target, opt) end + local after_linkcmd = r:script("linkcmd_after") + if after_linkcmd then + local batchcmds_ = batchcmds.new({target = target}) + after_linkcmd(target, batchcmds_, {progress = opt.progress}) + batchcmds_:runcmds({dryrun = option.get("dry-run")}) + end end end diff --git a/xmake/rules/xcode/metal/xmake.lua b/xmake/rules/xcode/metal/xmake.lua index d4bc50fea..a8b1fe16d 100644 --- a/xmake/rules/xcode/metal/xmake.lua +++ b/xmake/rules/xcode/metal/xmake.lua @@ -47,10 +47,8 @@ rule("xcode.metal") local cross = target:data("xcode.metal.cross") local metal = assert(find_tool("metal", {program = cross .. " metal"}), "metal command not found!") - -- add objectfile (.air) - local objectfile = target:objectfile(sourcefile) .. ".air" - -- add commands + local objectfile = target:objectfile(sourcefile) .. ".air" batchcmds:show_progress(opt.progress, "${color.build.object}compiling.metal %s", sourcefile) batchcmds:mkdir(path.directory(objectfile)) batchcmds:vrunv(metal.program, {"-c", "-o", objectfile, sourcefile}) @@ -59,10 +57,36 @@ rule("xcode.metal") batchcmds:add_depfiles(sourcefile) batchcmds:set_depmtime(os.mtime(objectfile)) batchcmds:set_depcache(target:dependfile(objectfile)) - end) -- link *.air to *.metallib - on_linkcmd(function (target, batchcmds, opt) - print("linkcmd") + before_linkcmd(function (target, batchcmds, opt) + + -- get metallib + import("lib.detect.find_tool") + local cross = target:data("xcode.metal.cross") + local metallib = assert(find_tool("metallib", {program = cross .. " metallib"}), "metallib command not found!") + + -- get objectfiles + local objectfiles = {} + for rulename, sourcebatch in pairs(target:sourcebatches()) do + if rulename == "xcode.metal" then + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + table.insert(objectfiles, target:objectfile(sourcefile) .. ".air") + end + break + end + end + assert(#objectfiles > 0, "*.air files not found!") + + -- add commands + local libraryfile = "default.metallib" + batchcmds:show_progress(opt.progress, "${color.build.target}linking.metal %s", libraryfile) + batchcmds:mkdir(path.directory(libraryfile)) + batchcmds:vrunv(metallib.program, table.join({"-o", libraryfile}, objectfiles)) + + -- add deps + batchcmds:add_depfiles(objectfiles) + batchcmds:set_depmtime(os.mtime(libraryfile)) + batchcmds:set_depcache(target:dependfile(libraryfile)) end) -- cgit v1.3.1 From 8b9dbad9c63b940478815c86fc04ad809495b8d6 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 22 Aug 2021 21:43:26 +0800 Subject: generate default.metallib --- xmake/rules/xcode/metal/xmake.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xmake/rules/xcode/metal/xmake.lua b/xmake/rules/xcode/metal/xmake.lua index a8b1fe16d..8892746f8 100644 --- a/xmake/rules/xcode/metal/xmake.lua +++ b/xmake/rules/xcode/metal/xmake.lua @@ -80,8 +80,9 @@ rule("xcode.metal") assert(#objectfiles > 0, "*.air files not found!") -- add commands - local libraryfile = "default.metallib" - batchcmds:show_progress(opt.progress, "${color.build.target}linking.metal %s", libraryfile) + local resourcesdir = path.absolute(target:data("xcode.bundle.resourcesdir")) + local libraryfile = resourcesdir and path.join(resourcesdir, "default.metallib") or (target:targetfile() .. ".metallib") + batchcmds:show_progress(opt.progress, "${color.build.target}linking.metal %s", path.filename(libraryfile)) batchcmds:mkdir(path.directory(libraryfile)) batchcmds:vrunv(metallib.program, table.join({"-o", libraryfile}, objectfiles)) -- cgit v1.3.1 From abc3c7047f2caf9c8a5c50b56f3ad0757cff8956 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 22 Aug 2021 22:13:46 +0800 Subject: improve to build metal --- xmake/rules/xcode/metal/xmake.lua | 46 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/xmake/rules/xcode/metal/xmake.lua b/xmake/rules/xcode/metal/xmake.lua index 8892746f8..7279e26a6 100644 --- a/xmake/rules/xcode/metal/xmake.lua +++ b/xmake/rules/xcode/metal/xmake.lua @@ -43,15 +43,50 @@ rule("xcode.metal") on_buildcmd_file(function (target, batchcmds, sourcefile, opt) -- get metal + import("core.tool.toolchain") import("lib.detect.find_tool") local cross = target:data("xcode.metal.cross") local metal = assert(find_tool("metal", {program = cross .. " metal"}), "metal command not found!") - -- add commands + -- get xcode toolchain + local xcode = toolchain.load("xcode", {plat = target:plat(), arch = target:arch()}) + local target_minver = xcode:config("target_minver") + local xcode_sysroot = xcode:config("xcode_sysroot") + + -- init metal arguments local objectfile = target:objectfile(sourcefile) .. ".air" + local argv = {"-c", "-ffast-math", "-gline-tables-only"} + if target_minver then + table.insert(argv, "-target") + local airarch = target:is_arch("x86_64", "arm64") and "air64" or "air32" + if target:is_plat("macosx") then + table.insert(argv, airarch .. "-apple-macos" .. target_minver) + elseif target:is_plat("iphoneos") then + local airtarget = airarch .. "-apple-ios" .. target_minver + if target:is_arch("x86_64", "i386") then + airtarget = airtarget .. "-simulator" + end + table.insert(argv, airtarget) + elseif target:is_plat("watchos") then + local airtarget = airarch .. "-apple-watchos" .. target_minver + if target:is_arch("x86_64", "i386") then + airtarget = airtarget .. "-simulator" + end + table.insert(argv, airtarget) + end + end + if xcode_sysroot then + table.insert(argv, "-isysroot") + table.insert(argv, xcode_sysroot) + end + table.insert(argv, "-o") + table.insert(argv, objectfile) + table.insert(argv, sourcefile) + + -- add commands batchcmds:show_progress(opt.progress, "${color.build.object}compiling.metal %s", sourcefile) batchcmds:mkdir(path.directory(objectfile)) - batchcmds:vrunv(metal.program, {"-c", "-o", objectfile, sourcefile}) + batchcmds:vrunv(metal.program, argv) -- add deps batchcmds:add_depfiles(sourcefile) @@ -63,6 +98,7 @@ rule("xcode.metal") before_linkcmd(function (target, batchcmds, opt) -- get metallib + import("core.tool.toolchain") import("lib.detect.find_tool") local cross = target:data("xcode.metal.cross") local metallib = assert(find_tool("metallib", {program = cross .. " metallib"}), "metallib command not found!") @@ -79,12 +115,16 @@ rule("xcode.metal") end assert(#objectfiles > 0, "*.air files not found!") + -- get xcode toolchain + local xcode = toolchain.load("xcode", {plat = target:plat(), arch = target:arch()}) + local xcode_sysroot = xcode:config("xcode_sysroot") + -- add commands local resourcesdir = path.absolute(target:data("xcode.bundle.resourcesdir")) local libraryfile = resourcesdir and path.join(resourcesdir, "default.metallib") or (target:targetfile() .. ".metallib") batchcmds:show_progress(opt.progress, "${color.build.target}linking.metal %s", path.filename(libraryfile)) batchcmds:mkdir(path.directory(libraryfile)) - batchcmds:vrunv(metallib.program, table.join({"-o", libraryfile}, objectfiles)) + batchcmds:vrunv(metallib.program, table.join({"-o", libraryfile}, objectfiles), {envs = {SDKROOT = xcode_sysroot}}) -- add deps batchcmds:add_depfiles(objectfiles) -- cgit v1.3.1 From 0100240746412c71e610d10d21bccf4632294e63 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 22 Aug 2021 22:16:02 +0800 Subject: improve metal rule --- xmake/rules/xcode/metal/xmake.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xmake/rules/xcode/metal/xmake.lua b/xmake/rules/xcode/metal/xmake.lua index 7279e26a6..965310c98 100644 --- a/xmake/rules/xcode/metal/xmake.lua +++ b/xmake/rules/xcode/metal/xmake.lua @@ -73,6 +73,12 @@ rule("xcode.metal") airtarget = airtarget .. "-simulator" end table.insert(argv, airtarget) + elseif target:is_plat("appletvos") then + local airtarget = airarch .. "-apple-tvos" .. target_minver + if target:is_arch("x86_64", "i386") then + airtarget = airtarget .. "-simulator" + end + table.insert(argv, airtarget) end end if xcode_sysroot then -- cgit v1.3.1 From a6c79096ae121a3ee6467102727cea02670a5485 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 22 Aug 2021 22:17:43 +0800 Subject: add comments --- xmake/rules/xcode/metal/xmake.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xmake/rules/xcode/metal/xmake.lua b/xmake/rules/xcode/metal/xmake.lua index 965310c98..d6722cef9 100644 --- a/xmake/rules/xcode/metal/xmake.lua +++ b/xmake/rules/xcode/metal/xmake.lua @@ -18,6 +18,10 @@ -- @file xmake.lua -- +-- build metal files +-- +-- @see https://developer.apple.com/documentation/metal/libraries/building_a_library_with_metal_s_command-line_tools +-- rule("xcode.metal") -- support add_files("*.metal") -- cgit v1.3.1 From 3e4923e9ca0787e634efc370d8dc157e5e1a12a3 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 22 Aug 2021 22:33:28 +0800 Subject: improve ci --- .github/workflows/msys2_mingw.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/msys2_mingw.yml b/.github/workflows/msys2_mingw.yml index d19184283..35965b4dc 100644 --- a/.github/workflows/msys2_mingw.yml +++ b/.github/workflows/msys2_mingw.yml @@ -9,7 +9,7 @@ jobs: runs-on: windows-latest concurrency: - group: ${{ github.head_ref }}-MSYS2_MINGW + group: ${{ github.head_ref }}-MSYS2_MINGW-${{ matrix.arch }} cancel-in-progress: true strategy: -- cgit v1.3.1 From 57681c84a77b6c6a0ac8f3ea474ff6c4aedebeb2 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 23 Aug 2021 13:57:11 +0800 Subject: Update package.lua --- xmake/core/package/package.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index a2b4163e5..c032d9d83 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -468,7 +468,7 @@ end -- is cross-compilation? function _instance:is_cross() - if self:is_plat("windows") and os.host() == "windows" then + if self:is_plat("windows", "mingw") and os.host() == "windows" then -- always false on windows host return false end -- cgit v1.3.1 From 8085ec72beba660555c4a0b3d4e01ef064356b30 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 23 Aug 2021 14:57:54 +0800 Subject: Update lock_packages.lua --- xmake/modules/private/action/require/impl/lock_packages.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua index 0e340e602..6a962ba77 100644 --- a/xmake/modules/private/action/require/impl/lock_packages.lua +++ b/xmake/modules/private/action/require/impl/lock_packages.lua @@ -36,7 +36,6 @@ function _lock_package(instance) local result = {} local repo = instance:repo() result.version = instance:version_str() - result.buildhash = instance:buildhash() result.branch = instance:branch() result.tag = instance:tag() if repo then -- cgit v1.3.1 From b5465246870f6eac49ed7edf3e727706766a452b Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 23 Aug 2021 14:58:30 +0800 Subject: Update package.lua --- xmake/modules/private/action/require/impl/package.lua | 5 ----- 1 file changed, 5 deletions(-) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 55085d4f1..c8035fecd 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -762,11 +762,6 @@ function _load_package(packagename, requireinfo, opt) on_load(package) end - -- check build hash - if locked_requireinfo and locked_requireinfo.buildhash ~= package:buildhash() then - wprint("package(%s): buildhash is not matched in xmake-requires.lock", package:displayname(), locked_requireinfo.buildhash, package:buildhash()) - end - -- load environments from the manifest to enable the environments of on_install() package:envs_load() -- cgit v1.3.1 From 3fbff8a507a94441047957c9eaaeadfb58e8f901 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 23 Aug 2021 15:11:13 +0800 Subject: Update repository.lua --- .../private/action/require/impl/repository.lua | 41 +++++++++++++--------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/xmake/modules/private/action/require/impl/repository.lua b/xmake/modules/private/action/require/impl/repository.lua index 6d656ccd0..8bd92aa04 100644 --- a/xmake/modules/private/action/require/impl/repository.lua +++ b/xmake/modules/private/action/require/impl/repository.lua @@ -29,10 +29,10 @@ import("devel.git") function _get_packagedir_from_locked_repo(packagename, locked_repo) -- find global repository directory - local repodir_global + local repo_global for _, repo in ipairs(repositories()) do if locked_repo.url == repo:url() and locked_repo.branch == repo:branch() then - repodir_global = repo:directory() + repo_global = repo break end end @@ -42,16 +42,18 @@ function _get_packagedir_from_locked_repo(packagename, locked_repo) local repodir_local if os.isdir(locked_repo.url) then repodir_local = locked_repo.url - elseif not locked_repo.commit then - repodir_local = repodir_global + elseif not locked_repo.commit and repo_global then + repodir_local = repo_global:directory() else repodir_local = path.join(config.directory(), "repositories", reponame) end -- clone repository to local + local lastcommit if not os.isdir(repodir_local) then - if repodir_global then - git.clone(repodir_global, {verbose = option.get("verbose"), outputdir = repodir_local}) + if repo_global then + git.clone(repo_global:directory(), {verbose = option.get("verbose"), outputdir = repodir_local}) + lastcommit = repo_global:commit() elseif global.get("network") ~= "private" then git.clone(locked_repo.url, {verbose = option.get("verbose"), branch = locked_repo.branch, outputdir = repodir_local}) else @@ -62,17 +64,22 @@ function _get_packagedir_from_locked_repo(packagename, locked_repo) -- lock commit if locked_repo.commit and os.isdir(path.join(repodir_local, ".git")) then - -- try checkout to the given commit - local ok = try {function () git.checkout(locked_repo.commit, {verbose = option.get("verbose"), repodir = repodir_local}); return true end} - if not ok then - if global.get("network") ~= "private" then - -- pull the latest commit - git.pull({verbose = option.get("verbose"), remote = locked_repo.url, branch = locked_repo.branch, repodir = repodir_local}) - -- re-checkout to the given commit - ok = try {function () git.checkout(locked_repo.commit, {verbose = option.get("verbose"), repodir = repodir_local}); return true end} - else - wprint("we cannot lock repository(%s) in private network mode!", locked_repo.url) - return + lastcommit = lastcommit or try {function() + return git.lastcommit({repodir = repodir_local}) + end} + if locked_repo.commit ~= lastcommit then + -- try checkout to the given commit + local ok = try {function () git.checkout(locked_repo.commit, {verbose = option.get("verbose"), repodir = repodir_local}); return true end} + if not ok then + if global.get("network") ~= "private" then + -- pull the latest commit + git.pull({verbose = option.get("verbose"), remote = locked_repo.url, branch = locked_repo.branch, repodir = repodir_local}) + -- re-checkout to the given commit + ok = try {function () git.checkout(locked_repo.commit, {verbose = option.get("verbose"), repodir = repodir_local}); return true end} + else + wprint("we cannot lock repository(%s) in private network mode!", locked_repo.url) + return + end end end end -- cgit v1.3.1 From 7e07186439f900505c1ab31a8b2a36452faf5fd3 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 24 Aug 2021 00:37:09 +0800 Subject: show upgraded packages --- .../package/multiconfig/xmake-requires.lock | 3 -- .../package/toolchain_muslcc/xmake-requires.lock | 18 ++---------- .../action/require/impl/install_packages.lua | 23 +++++++++++++++ .../private/action/require/impl/package.lua | 33 ++++++++++++++-------- 4 files changed, 47 insertions(+), 30 deletions(-) diff --git a/tests/projects/package/multiconfig/xmake-requires.lock b/tests/projects/package/multiconfig/xmake-requires.lock index e162c68b2..af73d677c 100644 --- a/tests/projects/package/multiconfig/xmake-requires.lock +++ b/tests/projects/package/multiconfig/xmake-requires.lock @@ -4,7 +4,6 @@ }, ["macosx|x86_64"] = { ["zlib#31fecfc4"] = { - buildhash = "b76a297309d14c09b42cfe3927260a51", repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", @@ -13,7 +12,6 @@ version = "1.2.11" }, ["zlib~debug#55833b12"] = { - buildhash = "e6a6fa6a86ad4fc7ae3c2cf7c60cc084", repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", @@ -22,7 +20,6 @@ version = "1.2.11" }, ["zlib~shared#b6ab42cb"] = { - buildhash = "8e5b898b0f344715bac89cc6a1577506", repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock index 8c55e49ea..4adae3fbb 100644 --- a/tests/projects/package/toolchain_muslcc/xmake-requires.lock +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -4,7 +4,6 @@ }, ["macosx|x86_64"] = { ["autoconf#31fecfc4"] = { - buildhash = "cd4169a7cb484832b2f70d2174072ca2", repo = { branch = "master", commit = "4498f11267de5112199152ab030ed139c985ad5a", @@ -13,7 +12,6 @@ version = "2.71" }, ["automake#31fecfc4"] = { - buildhash = "5b4ee7b727764ece8aa3e149603cfc7a", repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", @@ -22,7 +20,6 @@ version = "1.16.4" }, ["cmake#31fecfc4"] = { - buildhash = "a6d18f8c0bf347d980f8bb762583c91a", repo = { branch = "master", commit = "4498f11267de5112199152ab030ed139c985ad5a", @@ -31,16 +28,14 @@ version = "3.21.0" }, ["gmp#31fecfc4"] = { - buildhash = "7dd9c224447e46698ac73d29f58b1d73", repo = { branch = "master", - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + commit = "c1b4838c9b1e7a2c52d9bf1a9beafeaee7305e30", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "6.2.1" }, ["libisl 0.22#67114504"] = { - buildhash = "f649e1fb365e442e8f79f372fd91483b", repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", @@ -49,7 +44,6 @@ version = "0.22" }, ["libogg#31fecfc4"] = { - buildhash = "d894fc29f2fb4c45a0f48bc2c6ece273", repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", @@ -58,7 +52,6 @@ version = "v1.3.4" }, ["libplist#31fecfc4"] = { - buildhash = "0c01b22920be4876b1de74629194eb8f", repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", @@ -67,7 +60,6 @@ version = "2.2.0" }, ["libtool#31fecfc4"] = { - buildhash = "64584ec84a4743ecb740b598b263ffa6", repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", @@ -76,16 +68,14 @@ version = "2.4.6" }, ["m4#31fecfc4"] = { - buildhash = "fd0e83e5759b442a970327ebb1c89793", repo = { branch = "master", - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + commit = "c1b4838c9b1e7a2c52d9bf1a9beafeaee7305e30", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.4.19" }, ["muslcc#31fecfc4"] = { - buildhash = "11062c09ebeb484594488ad73ddbcd1f", repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", @@ -94,16 +84,14 @@ version = "20210202" }, ["pkg-config#31fecfc4"] = { - buildhash = "84fd7f9b9f7a47709512cfc85cd9e5f7", repo = { branch = "master", - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + commit = "c1b4838c9b1e7a2c52d9bf1a9beafeaee7305e30", url = "https://gitee.com/tboox/xmake-repo.git" }, version = "0.29.2" }, ["zlib#31fecfc4"] = { - buildhash = "be90a245b8bb48e6b08a1a15bdcad467", repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", diff --git a/xmake/modules/private/action/require/impl/install_packages.lua b/xmake/modules/private/action/require/impl/install_packages.lua index 79fb71c3f..9eba4caf7 100644 --- a/xmake/modules/private/action/require/impl/install_packages.lua +++ b/xmake/modules/private/action/require/impl/install_packages.lua @@ -243,6 +243,19 @@ function _get_confirm(packages) return result, packages_modified end +-- show upgraded packages +function _show_upgraded_packages(packages) + local upgraded_count = 0 + for _, instance in ipairs(packages) do + local locked_requireinfo = package.get_locked_requireinfo(instance:requireinfo(), {force = true}) + if locked_requireinfo and locked_requireinfo.version and instance:version():gt(locked_requireinfo.version) then + cprint(" ${color.dump.string}%s${clear}: %s -> ${color.success}%s", instance:displayname(), locked_requireinfo.version, instance:version_str()) + upgraded_count = upgraded_count + 1 + end + end + cprint("${bright}%d packages are upgraded!", upgraded_count) +end + -- install packages function _install_packages(packages_install, packages_download, installdeps) @@ -580,6 +593,11 @@ function main(requires, opt) end end + -- show upgraded information + if option.get("upgrade") then + print("upgrading packages ..") + end + -- some packages are modified? we need fix packages list and all deps if packages_modified then order_packages = {} @@ -602,6 +620,11 @@ function main(requires, opt) -- because there may be some missing optional dependencies reinstalled register_packages(packages) + -- show upgraded packages + if option.get("upgrade") then + _show_upgraded_packages(packages) + end + -- lock packages lock_packages(packages) return packages diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index c8035fecd..c3d642964 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -208,17 +208,19 @@ function _load_package_from_repository(packagename, opt) end -- has locked requires? -function _has_locked_requires() - if not option.get("upgrade") then +function _has_locked_requires(opt) + opt = opt or {} + if not option.get("upgrade") or opt.force then return project.policy("package.requires_lock") and os.isfile(project.requireslock()) end end -- get locked requires -function _get_locked_requires(requirekey) +function _get_locked_requires(requirekey, opt) + opt = opt or {} local requireslock = _memcache():get("requireslock") - if requireslock == nil then - if _has_locked_requires() then + if requireslock == nil or opt.force then + if _has_locked_requires(opt) then requireslock = io.load(project.requireslock()) end _memcache():set("requireslock", requireslock or false) @@ -651,13 +653,7 @@ function _load_package(packagename, requireinfo, opt) requireinfo.requirekey = requirekey -- get locked requireinfo - local locked_requireinfo, requireslock_version - if _has_locked_requires() then - locked_requireinfo, requireslock_version = _get_locked_requires(requirekey) - if requireslock_version and semver.compare(project.requireslock_version(), requireslock_version) < 0 then - locked_requireinfo = nil - end - end + local locked_requireinfo = get_locked_requireinfo(requireinfo) -- load package from project first local package @@ -955,6 +951,19 @@ function get_configs_str(package) return configs_str end +-- get locked requireinfo +function get_locked_requireinfo(requireinfo, opt) + local requirekey = requireinfo.requirekey + local locked_requireinfo, requireslock_version + if _has_locked_requires(opt) and requirekey then + locked_requireinfo, requireslock_version = _get_locked_requires(requirekey, opt) + if requireslock_version and semver.compare(project.requireslock_version(), requireslock_version) < 0 then + locked_requireinfo = nil + end + end + return locked_requireinfo, requireslock_version +end + -- load requires function load_requires(requires, requires_extra, opt) opt = opt or {} -- cgit v1.3.1 From df2a956c829ced830ab33cbb2ea3c8477f9f42ad Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 24 Aug 2021 00:39:35 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f1ffbd65..bc7794fa6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * [#1544](https://github.com/xmake-io/xmake/issues/1544): Add utils.bin2c rule to generate header from binary file * [#1547](https://github.com/xmake-io/xmake/issues/1547): Support to run and get output of c/c++ snippets in option * [#1567](https://github.com/xmake-io/xmake/issues/1567): Package "lock file" support to freeze dependencies +* [#1597](https://github.com/xmake-io/xmake/issues/1597): Support to compile *.metal files to generate *.metalib and improve xcode.application rule ### Change @@ -1063,6 +1064,7 @@ * [#1544](https://github.com/xmake-io/xmake/issues/1544): 添加 utils.bin2c 规则去自动从二进制资源文件产生 .h 头文件并引入到 C/C++ 代码中 * [#1547](https://github.com/xmake-io/xmake/issues/1547): option/snippets 支持运行检测模式,并且可以获取输出 * [#1567](https://github.com/xmake-io/xmake/issues/1567): 新增 xmake-requires.lock 包依赖锁定支持 +* [#1597](https://github.com/xmake-io/xmake/issues/1597): 支持编译 metal 文件到 metallib,并改进 xcode.application 规则去生成内置的 default.metallib 到 app ### 改进 -- cgit v1.3.1 From a1e286a66cf7e9df8ec1cad9316386d7f2a75b33 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 24 Aug 2021 00:41:50 +0800 Subject: fix error --- xmake/modules/private/action/require/impl/install_packages.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/private/action/require/impl/install_packages.lua b/xmake/modules/private/action/require/impl/install_packages.lua index 9eba4caf7..c8bdefbb1 100644 --- a/xmake/modules/private/action/require/impl/install_packages.lua +++ b/xmake/modules/private/action/require/impl/install_packages.lua @@ -248,7 +248,7 @@ function _show_upgraded_packages(packages) local upgraded_count = 0 for _, instance in ipairs(packages) do local locked_requireinfo = package.get_locked_requireinfo(instance:requireinfo(), {force = true}) - if locked_requireinfo and locked_requireinfo.version and instance:version():gt(locked_requireinfo.version) then + if locked_requireinfo and locked_requireinfo.version and instance:version() and instance:version():gt(locked_requireinfo.version) then cprint(" ${color.dump.string}%s${clear}: %s -> ${color.success}%s", instance:displayname(), locked_requireinfo.version, instance:version_str()) upgraded_count = upgraded_count + 1 end -- cgit v1.3.1 From a21ec09a71f0e4c60957b37eb61e33f1a4ae6e86 Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Tue, 24 Aug 2021 19:57:35 +0800 Subject: improve virtualenv on linux --- scripts/get.sh | 8 ++++- scripts/register-completions.sh | 2 ++ scripts/register-virtualenvs.sh | 48 ++++++++++++++++++++++++++++++ xmake/modules/private/xrepo/action/env.lua | 18 +++++++++-- 4 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 scripts/register-virtualenvs.sh diff --git a/scripts/get.sh b/scripts/get.sh index 8363b4499..21814e45e 100755 --- a/scripts/get.sh +++ b/scripts/get.sh @@ -227,13 +227,19 @@ write_profile() install_profile() { if [ ! -d ~/.xmake ]; then mkdir ~/.xmake; fi - echo "export PATH=$prefix/bin:\$PATH" > ~/.xmake/profile + echo "export XMAKE_ROOTDIR=$prefix/bin" > ~/.xmake/profile if [ -f "$projectdir/scripts/register-completions.sh" ]; then cat "$projectdir/scripts/register-completions.sh" >> ~/.xmake/profile else remote_get_content "$gitrepo_raw/scripts/register-completions.sh" >> ~/.xmake/profile fi + if [ -f "$projectdir/scripts/register-virtualenvs.sh" ]; then + cat "$projectdir/scripts/register-virtualenvs.sh" >> ~/.xmake/profile + else + remote_get_content "$gitrepo_raw/scripts/register-virtualenvs.sh" >> ~/.xmake/profile + fi + if [[ "$SHELL" = */zsh ]]; then write_profile ~/.zshrc elif [[ "$SHELL" = */ksh ]]; then diff --git a/scripts/register-completions.sh b/scripts/register-completions.sh index e274605b2..c93cfb15e 100755 --- a/scripts/register-completions.sh +++ b/scripts/register-completions.sh @@ -1,6 +1,8 @@ # parameter completions for *nix shell +export PATH=${XMAKE_ROOTDIR}:$PATH + if [[ "$SHELL" = */zsh ]]; then # zsh parameter completion for xmake _xmake_zsh_complete() diff --git a/scripts/register-virtualenvs.sh b/scripts/register-virtualenvs.sh new file mode 100644 index 000000000..13a661435 --- /dev/null +++ b/scripts/register-virtualenvs.sh @@ -0,0 +1,48 @@ + +# virtual environments for *nix shell + +if test "${XMAKE_ROOTDIR}"; then + export XMAKE_EXE=${XMAKE_ROOTDIR}/xmake +else + export XMAKE_EXE=xmake +fi + +function xrepo { + if [ $# -eq 2 ] && [ "$1" = "env" ]; then + local cmd="${2-x}" + case "$cmd" in + shell) + if test "${XMAKE_PROMPT_BACKUP}"; then + PS1="${XMAKE_PROMPT_BACKUP}" + source "${XMAKE_ENV_BACKUP}" || return 1 + unset XMAKE_PROMPT_BACKUP + unset XMAKE_ENV_BACKUP + fi + "$XMAKE_EXE" lua private.xrepo.action.env.info config || return 1 + local prompt="$("$XMAKE_EXE" lua private.xrepo.action.env.info prompt)" || return 1 + if [ -z "${prompt+x}" ]; then + return 1 + fi + local activateCommand="$("$XMAKE_EXE" lua private.xrepo.action.env.info script.bash)" || return 1 + export XMAKE_ENV_BACKUP="$("$XMAKE_EXE" lua private.xrepo.action.env.info envfile)" + export XMAKE_PROMPT_BACKUP="${PS1}" + "$XMAKE_EXE" lua private.xrepo.action.env.info backup.bash 1>"$XMAKE_ENV_BACKUP" + eval "$activateCommand" + PS1="${prompt} $PS1" + ;; + quit) + if test "${XMAKE_PROMPT_BACKUP}"; then + PS1="${XMAKE_PROMPT_BACKUP}" + source "${XMAKE_ENV_BACKUP}" || return 1 + unset XMAKE_PROMPT_BACKUP + unset XMAKE_ENV_BACKUP + fi + ;; + *) + "$XMAKE_EXE" lua private.xrepo $@ + ;; + esac + else + "$XMAKE_EXE" lua private.xrepo $@ + fi +} diff --git a/xmake/modules/private/xrepo/action/env.lua b/xmake/modules/private/xrepo/action/env.lua index cb6936006..297a0717c 100644 --- a/xmake/modules/private/xrepo/action/env.lua +++ b/xmake/modules/private/xrepo/action/env.lua @@ -285,15 +285,29 @@ function _get_env_script(envs, shell, del) elseif shell == "cmd" then prefix = "@set \"" suffix = "\"" + elseif shell:endswith("sh") then + if del then + prefix = "unset " + connector = "" + else + prefix = "export " + connector = "='" + suffix = "'" + end end + local exceptions = hashset.of("_", "PS1", "PROMPT") local ret = "" if del then for name, _ in pairs(envs) do - ret = ret .. prefix .. name .. connector .. default .. suffix .. "\n" + if not exceptions:has(name) then + ret = ret .. prefix .. name .. connector .. default .. suffix .. "\n" + end end else for name, value in pairs(envs) do - ret = ret .. prefix .. name .. connector .. value .. suffix .. "\n" + if not exceptions:has(name) then + ret = ret .. prefix .. name .. connector .. value .. suffix .. "\n" + end end end return ret -- cgit v1.3.1 From e273de15d253d4dc1b904e4fa0da5fb1bbe57304 Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Tue, 24 Aug 2021 21:11:47 +0800 Subject: move PATH setting to toplevel --- scripts/get.sh | 3 ++- scripts/register-completions.sh | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/get.sh b/scripts/get.sh index 21814e45e..060ee4e20 100755 --- a/scripts/get.sh +++ b/scripts/get.sh @@ -227,7 +227,8 @@ write_profile() install_profile() { if [ ! -d ~/.xmake ]; then mkdir ~/.xmake; fi - echo "export XMAKE_ROOTDIR=$prefix/bin" > ~/.xmake/profile + echo "export XMAKE_ROOTDIR=\"$prefix/bin\"" > ~/.xmake/profile + echo "export PATH=\"${XMAKE_ROOTDIR}:$PATH\"" >> ~/.xmake/profile if [ -f "$projectdir/scripts/register-completions.sh" ]; then cat "$projectdir/scripts/register-completions.sh" >> ~/.xmake/profile else diff --git a/scripts/register-completions.sh b/scripts/register-completions.sh index c93cfb15e..e274605b2 100755 --- a/scripts/register-completions.sh +++ b/scripts/register-completions.sh @@ -1,8 +1,6 @@ # parameter completions for *nix shell -export PATH=${XMAKE_ROOTDIR}:$PATH - if [[ "$SHELL" = */zsh ]]; then # zsh parameter completion for xmake _xmake_zsh_complete() -- cgit v1.3.1 From b54b0ba654bb8b230efff2bd709839cf32bfb87e Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Tue, 24 Aug 2021 22:21:17 +0800 Subject: make prompt output more robust --- scripts/register-virtualenvs.sh | 2 +- scripts/xrepo.bat | 6 +++--- xmake/modules/private/xrepo/action/env.lua | 2 +- xmake/scripts/xrepo-hook.psm1 | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/register-virtualenvs.sh b/scripts/register-virtualenvs.sh index 13a661435..700d8dd99 100644 --- a/scripts/register-virtualenvs.sh +++ b/scripts/register-virtualenvs.sh @@ -19,7 +19,7 @@ function xrepo { unset XMAKE_ENV_BACKUP fi "$XMAKE_EXE" lua private.xrepo.action.env.info config || return 1 - local prompt="$("$XMAKE_EXE" lua private.xrepo.action.env.info prompt)" || return 1 + local prompt="$("$XMAKE_EXE" lua --quiet private.xrepo.action.env.info prompt)" || return 1 if [ -z "${prompt+x}" ]; then return 1 fi diff --git a/scripts/xrepo.bat b/scripts/xrepo.bat index c8714a11c..77acf7d24 100755 --- a/scripts/xrepo.bat +++ b/scripts/xrepo.bat @@ -22,7 +22,7 @@ if !errorlevel! neq 0 ( exit /B !errorlevel! ) - @%XMAKE_EXE% lua private.xrepo.action.env.info prompt 1>nul + @%XMAKE_EXE% lua --quiet private.xrepo.action.env.info prompt 1>nul if !errorlevel! neq 0 ( echo error: xmake.lua not found^^! exit /B !errorlevel! @@ -39,13 +39,13 @@ if !errorlevel! neq 0 ( exit /B !errorlevel! ) - @%XMAKE_EXE% lua private.xrepo.action.env.info prompt 1>nul + @%XMAKE_EXE% lua --quiet private.xrepo.action.env.info prompt 1>nul if !errorlevel! neq 0 ( echo error: xmake.lua not found^^! exit /B !errorlevel! ) endlocal - for /f %%i in ('@%XMAKE_EXE% lua private.xrepo.action.env.info prompt') do @( + for /f %%i in ('@%XMAKE_EXE% lua --quiet private.xrepo.action.env.info prompt') do @( @set "PROMPT=%%i %PROMPT%" ) @set XMAKE_PROMPT_BACKUP=%PROMPT% diff --git a/xmake/modules/private/xrepo/action/env.lua b/xmake/modules/private/xrepo/action/env.lua index 297a0717c..91d9317ed 100644 --- a/xmake/modules/private/xrepo/action/env.lua +++ b/xmake/modules/private/xrepo/action/env.lua @@ -317,7 +317,7 @@ end function info(key) if key == "prompt" then assert(os.isfile(os.projectfile()), "xmake.lua not found!") - print("[%s]", path.filename(os.projectdir())) + io.write("[" .. path.filename(os.projectdir()) .. "]") elseif key == "envfile" then print(os.tmpfile()) elseif key == "config" then diff --git a/xmake/scripts/xrepo-hook.psm1 b/xmake/scripts/xrepo-hook.psm1 index 902ef3b16..53342fba0 100644 --- a/xmake/scripts/xrepo-hook.psm1 +++ b/xmake/scripts/xrepo-hook.psm1 @@ -21,7 +21,7 @@ function Enter-XrepoEnvironment { } $xmakeColorTermBackup, $Env:XMAKE_COLORTERM = $Env:XMAKE_COLORTERM, "nocolor"; - $xrepoPrompt = (& $Env:XMAKE_EXE lua private.xrepo.action.env.info prompt | Out-String); + $xrepoPrompt = (& $Env:XMAKE_EXE lua --quiet private.xrepo.action.env.info prompt | Out-String); $Env:XMAKE_COLORTERM = $xmakeColorTermBackup; if (-not $xrepoPrompt.StartsWith("[")) { Write-Host $xrepoPrompt; -- cgit v1.3.1 From 34241bb3d8a1dec0ead81316473e505eb2e5f713 Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Tue, 24 Aug 2021 23:14:16 +0800 Subject: fix xmake not found issue --- scripts/get.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/get.sh b/scripts/get.sh index 060ee4e20..76d329116 100755 --- a/scripts/get.sh +++ b/scripts/get.sh @@ -227,8 +227,8 @@ write_profile() install_profile() { if [ ! -d ~/.xmake ]; then mkdir ~/.xmake; fi - echo "export XMAKE_ROOTDIR=\"$prefix/bin\"" > ~/.xmake/profile - echo "export PATH=\"${XMAKE_ROOTDIR}:$PATH\"" >> ~/.xmake/profile + echo "export XMAKE_ROOTDIR=\"$prefix/bin\"\n" > ~/.xmake/profile + echo 'export PATH="$XMAKE_ROOTDIR:$PATH"' >> ~/.xmake/profile if [ -f "$projectdir/scripts/register-completions.sh" ]; then cat "$projectdir/scripts/register-completions.sh" >> ~/.xmake/profile else -- cgit v1.3.1 From 65cd1d83d3f61415607b8976e7b5c215b67e42a8 Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Tue, 24 Aug 2021 23:46:40 +0800 Subject: fix typo --- scripts/get.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/get.sh b/scripts/get.sh index 76d329116..f64ff8041 100755 --- a/scripts/get.sh +++ b/scripts/get.sh @@ -227,7 +227,7 @@ write_profile() install_profile() { if [ ! -d ~/.xmake ]; then mkdir ~/.xmake; fi - echo "export XMAKE_ROOTDIR=\"$prefix/bin\"\n" > ~/.xmake/profile + echo "export XMAKE_ROOTDIR=\"$prefix/bin\"" > ~/.xmake/profile echo 'export PATH="$XMAKE_ROOTDIR:$PATH"' >> ~/.xmake/profile if [ -f "$projectdir/scripts/register-completions.sh" ]; then cat "$projectdir/scripts/register-completions.sh" >> ~/.xmake/profile -- cgit v1.3.1 From dbd66858b8b68a784c415557e8958650e3d638c1 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 25 Aug 2021 00:42:18 +0800 Subject: improve metal rule --- xmake/rules/xcode/metal/xmake.lua | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/xmake/rules/xcode/metal/xmake.lua b/xmake/rules/xcode/metal/xmake.lua index d6722cef9..a876f946b 100644 --- a/xmake/rules/xcode/metal/xmake.lua +++ b/xmake/rules/xcode/metal/xmake.lua @@ -107,12 +107,6 @@ rule("xcode.metal") -- link *.air to *.metallib before_linkcmd(function (target, batchcmds, opt) - -- get metallib - import("core.tool.toolchain") - import("lib.detect.find_tool") - local cross = target:data("xcode.metal.cross") - local metallib = assert(find_tool("metallib", {program = cross .. " metallib"}), "metallib command not found!") - -- get objectfiles local objectfiles = {} for rulename, sourcebatch in pairs(target:sourcebatches()) do @@ -123,7 +117,15 @@ rule("xcode.metal") break end end - assert(#objectfiles > 0, "*.air files not found!") + if #objectfiles == 0 then + return + end + + -- get metallib + import("core.tool.toolchain") + import("lib.detect.find_tool") + local cross = target:data("xcode.metal.cross") + local metallib = assert(find_tool("metallib", {program = cross .. " metallib"}), "metallib command not found!") -- get xcode toolchain local xcode = toolchain.load("xcode", {plat = target:plat(), arch = target:arch()}) -- cgit v1.3.1 From 42586ef30167d76c26e87095420fc5780e9d9826 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 26 Aug 2021 11:10:18 +0800 Subject: Update cmake.lua --- xmake/modules/private/action/trybuild/cmake.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/xmake/modules/private/action/trybuild/cmake.lua b/xmake/modules/private/action/trybuild/cmake.lua index e2022b7b8..4217e98a5 100644 --- a/xmake/modules/private/action/trybuild/cmake.lua +++ b/xmake/modules/private/action/trybuild/cmake.lua @@ -19,7 +19,6 @@ -- -- imports -import("core.base.cli") import("core.base.option") import("core.project.config") import("core.tool.toolchain") @@ -199,7 +198,7 @@ function _get_configs(artifacts_dir) -- add extra user configs local tryconfigs = config.get("tryconfigs") if tryconfigs then - for _, opt in ipairs(cli.parse(tryconfigs)) do + for _, opt in ipairs(os.argv(tryconfigs)) do table.insert(configs, tostring(opt)) end end -- cgit v1.3.1 From 0cd89e799e3a1783d88bdc461a6008c90104d78e Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 26 Aug 2021 13:18:28 +0800 Subject: Update menuconf.lua --- xmake/actions/config/menuconf.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xmake/actions/config/menuconf.lua b/xmake/actions/config/menuconf.lua index 2f8706e4e..8ca87d918 100644 --- a/xmake/actions/config/menuconf.lua +++ b/xmake/actions/config/menuconf.lua @@ -253,6 +253,7 @@ function app:_basic_configs(cache) if type(values) == "function" then values = values(false, {menuconf = true}) end + values = table.wrap(values) for idx, value in ipairs(values) do if default == value then default = idx @@ -331,6 +332,7 @@ function app:_project_configs(cache) local values = opt:get("values") if values then kind = "choice" + values = table.wrap(values) for idx, value in ipairs(values) do if default == value then default = idx -- cgit v1.3.1 From 3c0c998aa5418463e838ae7b53f12140b472aa11 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 26 Aug 2021 13:19:07 +0800 Subject: Update menuconf.lua --- xmake/actions/global/menuconf.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/actions/global/menuconf.lua b/xmake/actions/global/menuconf.lua index c191f829c..6fcfb1841 100644 --- a/xmake/actions/global/menuconf.lua +++ b/xmake/actions/global/menuconf.lua @@ -232,6 +232,7 @@ function app:_global_configs(cache) if type(values) == "function" then values = values() end + values = table.wrap(values) for idx, value in ipairs(values) do if default == value then default = idx -- cgit v1.3.1 From f31f70694d9cb10d002a7af0806d2a0809c64866 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 27 Aug 2021 00:33:03 +0800 Subject: improve trybuild --- xmake/modules/private/action/trybuild/autotools.lua | 3 +-- xmake/modules/private/action/trybuild/meson.lua | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/xmake/modules/private/action/trybuild/autotools.lua b/xmake/modules/private/action/trybuild/autotools.lua index 14434f1c5..1d4090522 100644 --- a/xmake/modules/private/action/trybuild/autotools.lua +++ b/xmake/modules/private/action/trybuild/autotools.lua @@ -19,7 +19,6 @@ -- -- imports -import("core.base.cli") import("core.base.option") import("core.project.config") import("core.platform.platform") @@ -142,7 +141,7 @@ function _get_configs(artifacts_dir) -- add extra user configs local tryconfigs = config.get("tryconfigs") if tryconfigs then - for _, opt in ipairs(cli.parse(tryconfigs)) do + for _, opt in ipairs(os.argv(tryconfigs)) do table.insert(configs, tostring(opt)) end end diff --git a/xmake/modules/private/action/trybuild/meson.lua b/xmake/modules/private/action/trybuild/meson.lua index 312e24d22..f2baaff21 100644 --- a/xmake/modules/private/action/trybuild/meson.lua +++ b/xmake/modules/private/action/trybuild/meson.lua @@ -19,7 +19,6 @@ -- -- imports -import("core.base.cli") import("core.base.option") import("core.project.config") import("lib.detect.find_file") @@ -47,7 +46,7 @@ function _get_configs(artifacts_dir, buildir) -- add extra user configs local tryconfigs = config.get("tryconfigs") if tryconfigs then - for _, opt in ipairs(cli.parse(tryconfigs)) do + for _, opt in ipairs(os.argv(tryconfigs)) do table.insert(configs, tostring(opt)) end end -- cgit v1.3.1 From 3bcc30765c2a337016ae8a992ce2d5a65ecd2d0a Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 27 Aug 2021 00:34:13 +0800 Subject: improve download url --- .../modules/private/action/require/impl/actions/download.lua | 12 +++++++++--- .../action/require/impl/actions/download_resources.lua | 6 ++++-- .../private/action/require/impl/actions/patch_sources.lua | 3 ++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/xmake/modules/private/action/require/impl/actions/download.lua b/xmake/modules/private/action/require/impl/actions/download.lua index bee421052..e4cf8f0cc 100644 --- a/xmake/modules/private/action/require/impl/actions/download.lua +++ b/xmake/modules/private/action/require/impl/actions/download.lua @@ -66,17 +66,18 @@ function _checkout(package, url, sourcedir, url_alias) local longpaths = package:policy("platform.longpaths") -- download package from branches? + url = proxy.mirror(url) or url packagedir = path.join(sourcedir .. ".tmp", package:name()) if package:branch() then -- only shadow clone this branch - git.clone(proxy.mirror(url) or url, {depth = 1, recursive = true, longpaths = longpaths, branch = package:branch(), outputdir = packagedir}) + git.clone(url, {depth = 1, recursive = true, longpaths = longpaths, branch = package:branch(), outputdir = packagedir}) -- download package from revision or tag? else -- clone whole history and tags - git.clone(proxy.mirror(url) or url, {longpaths = longpaths, outputdir = packagedir}) + git.clone(url, {longpaths = longpaths, outputdir = packagedir}) -- attempt to checkout the given version local revision = package:revision(url_alias) or package:tag() or package:version_str() @@ -103,6 +104,11 @@ function _download(package, url, sourcedir, url_alias, url_excludes) -- get package file local packagefile = url_filename(url) + -- use proxy url? + if not os.isfile(url) then + url = proxy.mirror(url) or url + end + -- get sourcehash from the given url -- -- we need not sourcehash and skip checksum to try download it directly if no version list in package() @@ -139,7 +145,7 @@ function _download(package, url, sourcedir, url_alias, url_excludes) -- we can use local package from the search directories directly if network is too slow os.cp(localfile, packagefile) else - http.download(proxy.mirror(url) or url, packagefile) + http.download(url, packagefile) end end diff --git a/xmake/modules/private/action/require/impl/actions/download_resources.lua b/xmake/modules/private/action/require/impl/actions/download_resources.lua index fa115c04a..c6af29151 100644 --- a/xmake/modules/private/action/require/impl/actions/download_resources.lua +++ b/xmake/modules/private/action/require/impl/actions/download_resources.lua @@ -32,6 +32,7 @@ import("utils.archive") function _checkout(package, resource_name, resource_url, resource_revision) -- trace + resource_url = proxy.mirror(resource_url) or resource_url vprint("cloning resource(%s: %s) to %s-%s ..", resource_name, resource_revision, package:name(), package:version_str()) -- get the resource directory @@ -62,7 +63,7 @@ function _checkout(package, resource_name, resource_url, resource_revision) local longpaths = package:policy("platform.longpaths") -- clone whole history and tags - git.clone(proxy.mirror(resource_url) or resource_url, {longpaths = longpaths, outputdir = resourcedir}) + git.clone(resource_url, {longpaths = longpaths, outputdir = resourcedir}) -- attempt to checkout the given version git.checkout(resource_revision, {repodir = resourcedir}) @@ -77,6 +78,7 @@ end function _download(package, resource_name, resource_url, resource_hash) -- trace + resource_url = proxy.mirror(resource_url) or resource_url vprint("downloading resource(%s: %s) to %s-%s ..", resource_name, resource_url, package:name(), package:version_str()) -- get the resource file @@ -103,7 +105,7 @@ function _download(package, resource_name, resource_url, resource_hash) -- we can use local resource from the search directories directly if network is too slow os.cp(localfile, resource_file) elseif resource_url:find(string.ipattern("https-://")) or resource_url:find(string.ipattern("ftps-://")) then - http.download(proxy.mirror(resource_url) or resource_url, resource_file) + http.download(resource_url, resource_file) else raise("invalid resource url(%s)", resource_url) end diff --git a/xmake/modules/private/action/require/impl/actions/patch_sources.lua b/xmake/modules/private/action/require/impl/actions/patch_sources.lua index 23d46f3d3..d5874f8f5 100644 --- a/xmake/modules/private/action/require/impl/actions/patch_sources.lua +++ b/xmake/modules/private/action/require/impl/actions/patch_sources.lua @@ -50,6 +50,7 @@ end function _patch(package, patch_url, patch_hash) -- trace + patch_url = proxy.mirror(patch_url) or patch_url vprint("patching %s to %s-%s ..", patch_url, package:name(), package:version_str()) -- get the patch file @@ -72,7 +73,7 @@ function _patch(package, patch_url, patch_hash) -- download the patch file if patch_url:find(string.ipattern("https-://")) or patch_url:find(string.ipattern("ftps-://")) then - http.download(proxy.mirror(patch_url) or patch_url, patch_file) + http.download(patch_url, patch_file) else -- copy the patch file if os.isfile(patch_url) then -- cgit v1.3.1 From a5afebd516b2c40895cd709bbbf2ecf3a9e28ef0 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 27 Aug 2021 00:47:55 +0800 Subject: fix search package --- xmake/modules/package/manager/xmake/search_package.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xmake/modules/package/manager/xmake/search_package.lua b/xmake/modules/package/manager/xmake/search_package.lua index 5b633852c..b96dc2203 100644 --- a/xmake/modules/package/manager/xmake/search_package.lua +++ b/xmake/modules/package/manager/xmake/search_package.lua @@ -19,6 +19,7 @@ -- -- imports +import("core.base.semver") import("core.package.package", {alias = "core_package"}) import("private.action.require.impl.repository") @@ -33,6 +34,10 @@ function main(name) if package then local repo = package:repo() local versions = package:versions() + if versions then + versions = table.copy(versions) + table.sort(versions, function (a, b) return semver.compare(a, b) < 0 end) + end table.insert(results, {name = package:name(), version = versions and versions[1], description = package:get("description"), reponame = repo and repo:name()}) end end -- cgit v1.3.1 From a8d6c5c9b459ebb1b203df6ea2bd38e3a29b1c85 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 27 Aug 2021 00:48:07 +0800 Subject: improve to search package --- xmake/modules/package/manager/xmake/search_package.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/package/manager/xmake/search_package.lua b/xmake/modules/package/manager/xmake/search_package.lua index b96dc2203..f4a235246 100644 --- a/xmake/modules/package/manager/xmake/search_package.lua +++ b/xmake/modules/package/manager/xmake/search_package.lua @@ -36,7 +36,7 @@ function main(name) local versions = package:versions() if versions then versions = table.copy(versions) - table.sort(versions, function (a, b) return semver.compare(a, b) < 0 end) + table.sort(versions, function (a, b) return semver.compare(a, b) > 0 end) end table.insert(results, {name = package:name(), version = versions and versions[1], description = package:get("description"), reponame = repo and repo:name()}) end -- cgit v1.3.1 From 2f8a54e11600d3384125ac495d6f1a8a971556a0 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 27 Aug 2021 07:40:26 +0800 Subject: Update env.lua --- xmake/modules/private/xrepo/action/env.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/private/xrepo/action/env.lua b/xmake/modules/private/xrepo/action/env.lua index 91d9317ed..e092c6944 100644 --- a/xmake/modules/private/xrepo/action/env.lua +++ b/xmake/modules/private/xrepo/action/env.lua @@ -70,7 +70,7 @@ function menu_options() local function show_options() -- show usage - cprint("${bright}Usage: $${clear cyan}xrepo env [options] [packages] [program] [arguments]") + cprint("${bright}Usage: $${clear cyan}xrepo env [options] [program] [arguments]") -- show description print("") -- cgit v1.3.1 From 9fe97a4b60768c3551ea2458d3c6b4284516edde Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 27 Aug 2021 07:47:08 +0800 Subject: Update package.lua --- xmake/core/package/package.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index c032d9d83..50fd9148b 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -1124,10 +1124,11 @@ function _instance:_fetch_tool(opt) if fetchinfo == nil then self._find_tool = self._find_tool or sandbox_module.import("lib.detect.find_tool", {anonymous = true}) if opt.system then - local fetchnames = {self:name()} + local fetchnames = {} if not self:is_thirdparty() then table.join2(fetchnames, self:extsources()) end + table.insert(fetchnames, self:name()) for _, fetchname in ipairs(fetchnames) do fetchinfo = self:find_tool(fetchname, opt) if fetchinfo then @@ -1180,10 +1181,11 @@ function _instance:_fetch_library(opt) end if fetchinfo == nil then if opt.system then - local fetchnames = {self:name()} + local fetchnames = {} if not self:is_thirdparty() then table.join2(fetchnames, self:extsources()) end + table.insert(fetchnames, self:name()) for _, fetchname in ipairs(fetchnames) do fetchinfo = self:find_package(fetchname, opt) if fetchinfo then -- cgit v1.3.1 From dc4513ccbe420e5dd60856d60043c0b910574272 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 28 Aug 2021 22:53:48 +0800 Subject: update ci --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 3d7560e2d..85f121282 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -79,7 +79,7 @@ jobs: Expand-Archive ./7zip.zip -DestinationPath ./7zip Copy-Item ./7zip/7z.exe ./winenv/bin Copy-Item ./7zip/7z.dll ./winenv/bin - Invoke-WebRequest "https://curl.se/windows/dl-7.75.0_3/curl-7.75.0_3-win32-mingw.zip" -UseBasicParsing -OutFile .\curl.zip + Invoke-WebRequest "https://curl.se/windows/dl-7.78.0_2/curl-7.78.0_2-win32-mingw.zip" -UseBasicParsing -OutFile .\curl.zip Expand-Archive ./curl.zip -DestinationPath ./curl Copy-Item ./curl/curl-7.75.0-win32-mingw/bin/curl.exe ./winenv/bin Copy-Item ./curl/curl-7.75.0-win32-mingw/bin/curl-ca-bundle.crt ./winenv/bin -- cgit v1.3.1 From 4e956caf9079f2e206cd48dc7351c76465574ff3 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 28 Aug 2021 23:35:57 +0800 Subject: fix ci --- .github/workflows/windows.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 85f121282..9672fc47e 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -81,8 +81,8 @@ jobs: Copy-Item ./7zip/7z.dll ./winenv/bin Invoke-WebRequest "https://curl.se/windows/dl-7.78.0_2/curl-7.78.0_2-win32-mingw.zip" -UseBasicParsing -OutFile .\curl.zip Expand-Archive ./curl.zip -DestinationPath ./curl - Copy-Item ./curl/curl-7.75.0-win32-mingw/bin/curl.exe ./winenv/bin - Copy-Item ./curl/curl-7.75.0-win32-mingw/bin/curl-ca-bundle.crt ./winenv/bin + Copy-Item ./curl/curl-7.78.0-win32-mingw/bin/curl.exe ./winenv/bin + Copy-Item ./curl/curl-7.78.0-win32-mingw/bin/curl-ca-bundle.crt ./winenv/bin $version = (Get-Command xmake/xmake.exe).FileVersionInfo ./nsis/makensis.exe /DMAJOR=$($version.ProductMajorPart) /DMINOR=$($version.ProductMinorPart) /DALTER=$($version.ProductBuildPart) /DBUILD=$($($version.ProductVersion -split '\+')[1]) /D${{ matrix.arch }} .\scripts\installer.nsi (New-Item ./artifacts/${{env.RELEASE_NAME}} -ItemType Directory).FullName -- cgit v1.3.1 From c022587f0c32859b74f6fa16c7a3e16094bbbd7c Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 29 Aug 2021 08:33:07 +0800 Subject: update version --- core/project.mak | 2 +- core/xmake.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/project.mak b/core/project.mak index eafef391e..041121fea 100644 --- a/core/project.mak +++ b/core/project.mak @@ -10,7 +10,7 @@ PRO_VERSION_MAJOR = 2 PRO_VERSION_MINOR = 5 # the project alter version -PRO_VERSION_ALTER = 6 +PRO_VERSION_ALTER = 7 # the project prefix PRO_PREFIX = XM_ diff --git a/core/xmake.lua b/core/xmake.lua index e66405e57..9caedf7a9 100644 --- a/core/xmake.lua +++ b/core/xmake.lua @@ -2,7 +2,7 @@ set_project("xmake") -- version -set_version("2.5.6", {build = "%Y%m%d%H%M"}) +set_version("2.5.7", {build = "%Y%m%d%H%M"}) -- set xmake min version set_xmakever("2.2.3") -- cgit v1.3.1 From 08972d1a6c563c8793b3396fce2bc9545725aa85 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 29 Aug 2021 08:34:31 +0800 Subject: update xmake.spec --- scripts/rpmbuild/SPECS/xmake.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/rpmbuild/SPECS/xmake.spec b/scripts/rpmbuild/SPECS/xmake.spec index 7c7d5ed38..a20b91ee9 100644 --- a/scripts/rpmbuild/SPECS/xmake.spec +++ b/scripts/rpmbuild/SPECS/xmake.spec @@ -1,4 +1,4 @@ -%define xmake_revision fd248b8b97f62762ce6ea6e0008b4367bef29d4d +%define xmake_revision c022587f0c32859b74f6fa16c7a3e16094bbbd7c %define tbox_revision 5ef932750ede0b90867fd4afdcf1deed2464c82b %define sv_revision 9a3cf7c8e589de4f70378824329882c4a047fffc %define lua_cjson_revision 515bab6d6d80b164b94db73af69609ea02f3a798 @@ -7,7 +7,7 @@ %undefine _disable_source_fetch Name: xmake -Version: 2.5.6 +Version: 2.5.7 Release: 1%{?dist} Summary: A cross-platform build utility based on Lua BuildArch: noarch -- cgit v1.3.1 From 6d706be2384c1b6ba000bba81156c87d7449afc7 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 29 Aug 2021 08:38:03 +0800 Subject: update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc7794fa6..a5d73e86c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## master (unreleased) +## v2.5.7 + ### New features * [#1534](https://github.com/xmake-io/xmake/issues/1534): Support to compile Vala lanuage project @@ -1058,6 +1060,8 @@ ## master (开发中) +## v2.5.7 + ### 新特性 * [#1534](https://github.com/xmake-io/xmake/issues/1534): 新增对 Vala 语言的支持 -- cgit v1.3.1 From 4497dd33fb475a388d5d51192d432b0156be78a3 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 29 Aug 2021 10:12:51 +0800 Subject: fix style --- tests/projects/objc/metal_app/Renderer/AAPLRenderer.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/projects/objc/metal_app/Renderer/AAPLRenderer.m b/tests/projects/objc/metal_app/Renderer/AAPLRenderer.m index 124bd29ff..6cfc2cc0a 100644 --- a/tests/projects/objc/metal_app/Renderer/AAPLRenderer.m +++ b/tests/projects/objc/metal_app/Renderer/AAPLRenderer.m @@ -53,7 +53,7 @@ Implementation of a platform independent renderer class, which performs Metal se _pipelineState = [_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor error:&error]; - + // Pipeline State creation could fail if the pipeline descriptor isn't set up properly. // If the Metal API validation is enabled, you can find out more information about what // went wrong. (Metal API validation is enabled by default when a debug build is run @@ -102,14 +102,14 @@ Implementation of a platform independent renderer class, which performs Metal se // Set the region of the drawable to draw into. [renderEncoder setViewport:(MTLViewport){0.0, 0.0, _viewportSize.x, _viewportSize.y, 0.0, 1.0 }]; - + [renderEncoder setRenderPipelineState:_pipelineState]; // Pass in the parameter data. [renderEncoder setVertexBytes:triangleVertices length:sizeof(triangleVertices) atIndex:AAPLVertexInputIndexVertices]; - + [renderEncoder setVertexBytes:&_viewportSize length:sizeof(_viewportSize) atIndex:AAPLVertexInputIndexViewportSize]; -- cgit v1.3.1 From ab2c5e2a3b29bb63b23a7fa59c3f6d56cc56c47c Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 29 Aug 2021 21:56:52 +0800 Subject: improve git ops --- xmake/modules/devel/git/apply.lua | 13 +------------ xmake/modules/devel/git/checkout.lua | 13 +------------ xmake/modules/devel/git/clean.lua | 13 +------------ xmake/modules/devel/git/lastcommit.lua | 13 +------------ xmake/modules/devel/git/pull.lua | 15 ++------------- xmake/modules/devel/git/reset.lua | 13 +------------ xmake/modules/devel/git/submodule/update.lua | 21 +++++---------------- 7 files changed, 12 insertions(+), 89 deletions(-) diff --git a/xmake/modules/devel/git/apply.lua b/xmake/modules/devel/git/apply.lua index 97923da02..ccfd5bf80 100644 --- a/xmake/modules/devel/git/apply.lua +++ b/xmake/modules/devel/git/apply.lua @@ -44,17 +44,6 @@ function main(patchfile, opt) opt = opt or {} local argv = {"apply", "--reject", "--ignore-whitespace", patchfile} - -- enter repository directory - local oldir = nil - if opt.repodir then - oldir = os.cd(opt.repodir) - end - -- apply it - os.vrunv(git.program, argv) - - -- leave repository directory - if oldir then - os.cd(oldir) - end + os.vrunv(git.program, argv, {curdir = opt.repodir}) end diff --git a/xmake/modules/devel/git/checkout.lua b/xmake/modules/devel/git/checkout.lua index 7a32aa3b1..c78d8f439 100644 --- a/xmake/modules/devel/git/checkout.lua +++ b/xmake/modules/devel/git/checkout.lua @@ -47,17 +47,6 @@ function main(commit, opt) -- init argv local argv = {"checkout", commit} - -- enter repository directory - local oldir = nil - if opt.repodir then - oldir = os.cd(opt.repodir) - end - -- checkout it - os.vrunv(git.program, argv) - - -- leave repository directory - if oldir then - os.cd(oldir) - end + os.vrunv(git.program, argv, {curdir = opt.repodir}) end diff --git a/xmake/modules/devel/git/clean.lua b/xmake/modules/devel/git/clean.lua index ae21c3d88..52fa81a0b 100644 --- a/xmake/modules/devel/git/clean.lua +++ b/xmake/modules/devel/git/clean.lua @@ -61,17 +61,6 @@ function main(opt) table.insert(argv, "-x") end - -- enter repository directory - local oldir = nil - if opt.repodir then - oldir = os.cd(opt.repodir) - end - -- clean it - os.vrunv(git.program, argv) - - -- leave repository directory - if oldir then - os.cd(oldir) - end + os.vrunv(git.program, argv, {curdir = opt.repodir}) end diff --git a/xmake/modules/devel/git/lastcommit.lua b/xmake/modules/devel/git/lastcommit.lua index 876812f86..1ad6de1f4 100644 --- a/xmake/modules/devel/git/lastcommit.lua +++ b/xmake/modules/devel/git/lastcommit.lua @@ -57,21 +57,10 @@ function main(opt) envs = {ALL_PROXY = proxy_conf} end - -- enter repository directory - local oldir = nil - if opt.repodir then - oldir = os.cd(opt.repodir) - end - -- get last commit - local lastcommit = os.iorunv(git.program, argv, {envs = envs}) + local lastcommit = os.iorunv(git.program, argv, {envs = envs, curdir = opt.repodir}) if lastcommit then lastcommit = lastcommit:trim() end - - -- leave repository directory - if oldir then - os.cd(oldir) - end return lastcommit end diff --git a/xmake/modules/devel/git/pull.lua b/xmake/modules/devel/git/pull.lua index 9970f8dbc..412e6e757 100644 --- a/xmake/modules/devel/git/pull.lua +++ b/xmake/modules/devel/git/pull.lua @@ -58,18 +58,12 @@ function main(opt) table.insert(argv, "--tags") end - -- enter repository directory - local oldir = nil - if opt.repodir then - oldir = os.cd(opt.repodir) - end - -- use proxy? local envs local proxy_conf = proxy.config() if proxy_conf then -- get proxy configuration from the current remote url - local remoteinfo = try { function() return os.iorunv(git.program, {"remote", "-v"}) end } + local remoteinfo = try { function() return os.iorunv(git.program, {"remote", "-v"}, {curdir = opt.repodir}) end } if remoteinfo then for _, line in ipairs(remoteinfo:split('\n', {plain = true})) do local splitinfo = line:split("%s+") @@ -86,10 +80,5 @@ function main(opt) end -- pull it - os.vrunv(git.program, argv, {envs = envs}) - - -- leave repository directory - if oldir then - os.cd(oldir) - end + os.vrunv(git.program, argv, {envs = envs, curdir = opt.repodir}) end diff --git a/xmake/modules/devel/git/reset.lua b/xmake/modules/devel/git/reset.lua index 28b984008..4ed798d25 100644 --- a/xmake/modules/devel/git/reset.lua +++ b/xmake/modules/devel/git/reset.lua @@ -71,17 +71,6 @@ function main(opt) table.insert(argv, opt.commit) end - -- enter repository directory - local oldir = nil - if opt.repodir then - oldir = os.cd(opt.repodir) - end - -- reset it - os.vrunv(git.program, argv) - - -- leave repository directory - if oldir then - os.cd(oldir) - end + os.vrunv(git.program, argv, {curdir = opt.repodir}) end diff --git a/xmake/modules/devel/git/submodule/update.lua b/xmake/modules/devel/git/submodule/update.lua index 5d9323a02..881663706 100644 --- a/xmake/modules/devel/git/submodule/update.lua +++ b/xmake/modules/devel/git/submodule/update.lua @@ -58,37 +58,26 @@ function main(opt) table.join2(argv, opt.paths) end - -- enter repository directory - local oldir = nil - if opt.repodir then - oldir = os.cd(opt.repodir) - end - -- enable long paths local longpaths_old local longpaths_changed = false if opt.longpaths then - local longpaths_old = try {function () return os.iorunv(git.program, {"config", "--get", "--global", "core.longpaths"}) end} + local longpaths_old = try {function () return os.iorunv(git.program, {"config", "--get", "--global", "core.longpaths"}, {curdir = opt.repodir}) end} if not longpaths_old or not longpaths_old:find("true") then - os.vrunv(git.program, {"config", "--global", "core.longpaths", "true"}) + os.vrunv(git.program, {"config", "--global", "core.longpaths", "true"}, {curdir = opt.repodir}) longpaths_changed = true end end -- submodule it - os.vrunv(git.program, argv) + os.vrunv(git.program, argv, {curdir = opt.repodir}) -- restore old long paths configuration if longpaths_changed then if longpaths_old and longpaths_old:find("false") then - os.vrunv(git.program, {"config", "--global", "core.longpaths", "false"}) + os.vrunv(git.program, {"config", "--global", "core.longpaths", "false"}, {curdir = opt.repodir}) else - os.vrunv(git.program, {"config", "--global", "--unset", "core.longpaths"}) + os.vrunv(git.program, {"config", "--global", "--unset", "core.longpaths", {curdir = opt.repodir}}) end end - - -- leave repository directory - if oldir then - os.cd(oldir) - end end -- cgit v1.3.1 From b84cce50faefa8b327b4d4a62d010bdb25abd491 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 29 Aug 2021 21:58:47 +0800 Subject: improve extract --- xmake/modules/utils/archive/extract.lua | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/xmake/modules/utils/archive/extract.lua b/xmake/modules/utils/archive/extract.lua index dd09df9ac..69616fea6 100644 --- a/xmake/modules/utils/archive/extract.lua +++ b/xmake/modules/utils/archive/extract.lua @@ -85,9 +85,7 @@ function _extract_using_tar(archivefile, outputdir, extension, opt) -- extract it if is_host("windows") then - local oldir = os.cd(outputdir) - os.vrunv(program, argv) - os.cd(oldir) + os.vrunv(program, argv, {curdir = outputdir}) else os.vrunv(program, argv) end @@ -201,14 +199,8 @@ function _extract_using_gzip(archivefile, outputdir, extension, opt) os.cp(archivefile, tmpfile) end - -- enter outputdir - local oldir = os.cd(outputdir) - -- extract it - os.vrunv(program, argv) - - -- leave outputdir - os.cd(oldir) + os.vrunv(program, argv, {curdir = outputdir}) -- continue to extract *.tar file if outputdir_old then @@ -256,14 +248,8 @@ function _extract_using_xz(archivefile, outputdir, extension, opt) os.cp(archivefile, tmpfile) end - -- enter outputdir - local oldir = os.cd(outputdir) - -- extract it - os.vrunv(program, argv) - - -- leave outputdir - os.cd(oldir) + os.vrunv(program, argv, {curdir = outputdir}) -- continue to extract *.tar file if outputdir_old then @@ -369,14 +355,8 @@ function _extract_using_bzip2(archivefile, outputdir, extension, opt) os.cp(archivefile, tmpfile) end - -- enter outputdir - local oldir = os.cd(outputdir) - -- extract it - os.vrunv(program, argv) - - -- leave outputdir - os.cd(oldir) + os.vrunv(program, argv, {curdir = outputdir}) -- continue to extract *.tar file if outputdir_old then -- cgit v1.3.1 From ecb41e660c2c74d4655904bf3630e85f290e471b Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Sun, 29 Aug 2021 17:11:09 +0200 Subject: Update package.lua --- xmake/modules/private/action/require/impl/package.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index c3d642964..b26eaaf6d 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -227,7 +227,7 @@ function _get_locked_requires(requirekey, opt) end if requireslock then local plat = config.plat() or os.subhost() - local arch = config.arch() or so.subarch() + local arch = config.arch() or os.subarch() local key = plat .. "|" .. arch if requireslock[key] then return requireslock[key][requirekey], requireslock.__meta__.version -- cgit v1.3.1 From ca93ecfabf683d7f84d7688e0997b22d0e5c17a6 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 30 Aug 2021 22:38:25 +0800 Subject: improve package deps --- xmake/modules/private/action/require/impl/package.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index b26eaaf6d..4030bbfb9 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -806,7 +806,7 @@ function _load_packages(requires, opt) package._DEPS = packagedeps package._PLAINDEPS = plaindeps package._ORDERDEPS = table.unique(_sort_packagedeps(package)) - package._LINKDEPS = table.unique(_sort_packagedeps(package, true)) + package._LINKDEPS = table.reverse_unique(_sort_packagedeps(package, true)) end end -- cgit v1.3.1 From b17eaaf90b3e06c3e7f77958942feb79efe6471e Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 30 Aug 2021 11:13:36 +0800 Subject: Update package.lua --- xmake/core/package/package.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 50fd9148b..8b7e26806 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -1364,7 +1364,11 @@ function _instance:fetch_linkdeps() end if fetchinfo then for name, values in pairs(fetchinfo) do - fetchinfo[name] = table.unwrap(table.unique(table.wrap(values))) + if name == "links" or name == "syslinks" or name == "frameworks" then + fetchinfo[name] = table.unwrap(table.reverse_unique(table.wrap(values))) + else + fetchinfo[name] = table.unwrap(table.unique(table.wrap(values))) + end end end return fetchinfo -- cgit v1.3.1 From 1b8e4e472b6a7a1d1aeaf65a4a1e7193bcfdc499 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 30 Aug 2021 13:46:00 +0800 Subject: Update package.lua --- xmake/modules/private/action/require/impl/package.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 4030bbfb9..876dabb9a 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -321,7 +321,7 @@ function _select_package_version(package, requireinfo, locked_requireinfo) elseif #package:versions() > 0 then -- select version? version, source = try { function () return semver.select(require_version, package:versions()) end } end - if not version and has_giturl and not require_version:find('.', 1, true) then -- select branch? + if not version and has_giturl and not semver.is_valid(require_version) then -- select branch? version, source = require_version ~= "latest" and require_version or "master", "branch" end if not version then -- cgit v1.3.1 From 219f20a76c2fa40b83ffff7a5fb8967079ef8c7a Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 31 Aug 2021 23:01:38 +0800 Subject: improve vala rules and add more vala tests --- tests/projects/vala/sharedlib/src/main.vala | 6 ++ tests/projects/vala/sharedlib/src/mymath.vala | 9 +++ tests/projects/vala/sharedlib/xmake.lua | 18 ++++++ tests/projects/vala/staticlib/src/main.vala | 6 ++ tests/projects/vala/staticlib/src/mymath.vala | 9 +++ tests/projects/vala/staticlib/xmake.lua | 18 ++++++ xmake/rules/vala/xmake.lua | 83 ++++++++++++++++++++++++++- 7 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 tests/projects/vala/sharedlib/src/main.vala create mode 100644 tests/projects/vala/sharedlib/src/mymath.vala create mode 100644 tests/projects/vala/sharedlib/xmake.lua create mode 100644 tests/projects/vala/staticlib/src/main.vala create mode 100644 tests/projects/vala/staticlib/src/mymath.vala create mode 100644 tests/projects/vala/staticlib/xmake.lua diff --git a/tests/projects/vala/sharedlib/src/main.vala b/tests/projects/vala/sharedlib/src/main.vala new file mode 100644 index 000000000..da9fd895e --- /dev/null +++ b/tests/projects/vala/sharedlib/src/main.vala @@ -0,0 +1,6 @@ +using MyMath; + +public void main() { + stdout.printf("\n\t2 + 3 is %d", sum(2, 3)); + stdout.printf("\n\t8 squared is %d\n", square(8)); +} diff --git a/tests/projects/vala/sharedlib/src/mymath.vala b/tests/projects/vala/sharedlib/src/mymath.vala new file mode 100644 index 000000000..4f4e761c5 --- /dev/null +++ b/tests/projects/vala/sharedlib/src/mymath.vala @@ -0,0 +1,9 @@ +namespace MyMath { + public int sum(int a, int b) { + return(a + b); + } + + public int square(int a) { + return(a * a); + } +} diff --git a/tests/projects/vala/sharedlib/xmake.lua b/tests/projects/vala/sharedlib/xmake.lua new file mode 100644 index 000000000..10c90c88b --- /dev/null +++ b/tests/projects/vala/sharedlib/xmake.lua @@ -0,0 +1,18 @@ +add_rules("mode.release", "mode.debug") + +add_requires("glib") + +target("mymath") + set_kind("shared") + add_rules("vala") + add_files("src/mymath.vala") + add_values("vala.header", "mymath.h") + add_values("vala.vapi", "mymath-1.0.vapi") + add_packages("glib") + +target("test") + set_kind("binary") + add_deps("mymath") + add_rules("vala") + add_files("src/main.vala") + add_packages("glib") diff --git a/tests/projects/vala/staticlib/src/main.vala b/tests/projects/vala/staticlib/src/main.vala new file mode 100644 index 000000000..da9fd895e --- /dev/null +++ b/tests/projects/vala/staticlib/src/main.vala @@ -0,0 +1,6 @@ +using MyMath; + +public void main() { + stdout.printf("\n\t2 + 3 is %d", sum(2, 3)); + stdout.printf("\n\t8 squared is %d\n", square(8)); +} diff --git a/tests/projects/vala/staticlib/src/mymath.vala b/tests/projects/vala/staticlib/src/mymath.vala new file mode 100644 index 000000000..4f4e761c5 --- /dev/null +++ b/tests/projects/vala/staticlib/src/mymath.vala @@ -0,0 +1,9 @@ +namespace MyMath { + public int sum(int a, int b) { + return(a + b); + } + + public int square(int a) { + return(a * a); + } +} diff --git a/tests/projects/vala/staticlib/xmake.lua b/tests/projects/vala/staticlib/xmake.lua new file mode 100644 index 000000000..d37f1b974 --- /dev/null +++ b/tests/projects/vala/staticlib/xmake.lua @@ -0,0 +1,18 @@ +add_rules("mode.release", "mode.debug") + +add_requires("glib") + +target("mymath") + set_kind("static") + add_rules("vala") + add_files("src/mymath.vala") + add_values("vala.header", "mymath.h") + add_values("vala.vapi", "mymath-1.0.vapi") + add_packages("glib") + +target("test") + set_kind("binary") + add_deps("mymath") + add_rules("vala") + add_files("src/main.vala") + add_packages("glib") diff --git a/xmake/rules/vala/xmake.lua b/xmake/rules/vala/xmake.lua index a2ce76937..a0d5775d8 100644 --- a/xmake/rules/vala/xmake.lua +++ b/xmake/rules/vala/xmake.lua @@ -18,7 +18,7 @@ -- @file xmake.lua -- -rule("vala") +rule("vala.build") set_extensions(".vala") on_load(function (target) -- only vala source files? we need patch c source kind for linker @@ -26,6 +26,21 @@ rule("vala") if #sourcekinds == 0 then table.insert(sourcekinds, "cc") end + + -- we disable to build across targets in parallel, because the source files may depend on other target modules + target:set("policy", "build.across_targets_in_parallel", false) + + -- get vapi file + local vapifile = target:data("vala.vapifile") + if not vapifile then + local vapiname = target:values("vala.vapi") + if vapiname then + vapifile = path.join(target:targetdir(), vapiname) + else + vapifile = path.join(target:targetdir(), target:name() .. ".vapi") + end + target:data_set("vala.vapifile", vapifile) + end end) before_buildcmd_file(function (target, batchcmds, sourcefile_vala, opt) @@ -52,6 +67,21 @@ rule("vala") table.insert(argv, package) end end + if target:is_binary() then + for _, dep in ipairs(target:orderdeps()) do + if dep:is_shared() or dep:is_static() then + local vapifile = dep:data("vala.vapifile") + if vapifile then + table.join2(argv, vapifile) + end + end + end + else + local vapifile = target:data("vala.vapifile") + if vapifile then + table.insert(argv, "--vapi=" .. vapifile) + end + end table.insert(argv, sourcefile_vala) batchcmds:vrunv(valac.program, argv) batchcmds:compile(sourcefile_c, objectfile) @@ -62,3 +92,54 @@ rule("vala") batchcmds:set_depcache(target:dependfile(objectfile)) end) + after_install(function (target) + if target:is_shared() or target:is_static() then + local vapifile = target:data("vala.vapifile") + if vapifile then + local installdir = target:installdir() + if installdir then + local sharedir = path.join(installdir, "share") + os.mkdir(sharedir) + os.vcp(vapifile, sharedir) + end + end + end + end) + + after_uninstall(function (target) + if target:is_shared() or target:is_static() then + local vapifile = target:data("vala.vapifile") + if vapifile then + local installdir = target:installdir() + if installdir then + os.rm(path.join(installdir, "share", path.filename(vapifile))) + end + end + end + end) + +rule("vala") + + -- add build rules + add_deps("vala.build") + + -- set compiler runtime, e.g. vs runtime + add_deps("utils.compiler.runtime") + + -- inherit links and linkdirs of all dependent targets by default + add_deps("utils.inherit.links") + + -- support `add_files("src/*.o")` and `add_files("src/*.a")` to merge object and archive files to target + add_deps("utils.merge.object", "utils.merge.archive") + + -- we attempt to extract symbols to the independent file and + -- strip self-target binary if `set_symbols("debug")` and `set_strip("all")` are enabled + add_deps("utils.symbols.extract") + + -- check targets + add_deps("utils.check.targets") + + -- check licenses + add_deps("utils.check.licenses") + + -- cgit v1.3.1 From e16ce6286a7d820c08541554645aba41b2657984 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 31 Aug 2021 23:03:45 +0800 Subject: gen header file for vala --- xmake/rules/vala/xmake.lua | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/xmake/rules/vala/xmake.lua b/xmake/rules/vala/xmake.lua index a0d5775d8..058f68462 100644 --- a/xmake/rules/vala/xmake.lua +++ b/xmake/rules/vala/xmake.lua @@ -41,6 +41,22 @@ rule("vala.build") end target:data_set("vala.vapifile", vapifile) end + + -- get header file + local headerfile = target:data("vala.headerfile") + if not headerfile then + local headername = target:values("vala.header") + if headername then + headerfile = path.join(target:targetdir(), headername) + else + headerfile = path.join(target:targetdir(), target:name() .. ".h") + end + target:data_set("vala.headerfile", headerfile) + end + if headerfile then + target:add("headerfiles", headerfile) + target:add("sysincludedirs", path.directory(headerfile), {public = true}) + end end) before_buildcmd_file(function (target, batchcmds, sourcefile_vala, opt) @@ -81,6 +97,11 @@ rule("vala.build") if vapifile then table.insert(argv, "--vapi=" .. vapifile) end + local headerfile = target:data("vala.headerfile") + if headerfile then + table.insert(argv, "-H") + table.insert(argv, headerfile) + end end table.insert(argv, sourcefile_vala) batchcmds:vrunv(valac.program, argv) -- cgit v1.3.1 From 8176468252cb18a06a29a24f0a2a6205a9bea795 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 31 Aug 2021 23:13:48 +0800 Subject: update changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5d73e86c..f3eb7be9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### Change + +* [#1618](https://github.com/xmake-io/xmake/issues/1618): Improve vala to support to generate libraries and bindings + ## v2.5.7 ### New features @@ -1060,6 +1064,10 @@ ## master (开发中) +### 改进 + +* [#1618](https://github.com/xmake-io/xmake/issues/1618): 改进 vala 支持构建动态库和静态库程序 + ## v2.5.7 ### 新特性 -- cgit v1.3.1 From 77cbb790c47b771eabcf0726f678fbca18200a53 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 1 Sep 2021 12:04:22 +0800 Subject: Update find_qt.lua --- xmake/modules/detect/sdks/find_qt.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/detect/sdks/find_qt.lua b/xmake/modules/detect/sdks/find_qt.lua index 9dbc7b386..da98cd074 100644 --- a/xmake/modules/detect/sdks/find_qt.lua +++ b/xmake/modules/detect/sdks/find_qt.lua @@ -174,7 +174,7 @@ function _find_qt(sdkdir, sdkver) local libdir = qtenvs.QT_INSTALL_LIBS local pluginsdir = qtenvs.QT_INSTALL_PLUGINS local includedir = qtenvs.QT_INSTALL_HEADERS - local mkspecsdir = path.join(qtenvs.QT_INSTALL_ARCHDATA, "mkspecs") + local mkspecsdir = qtenvs.QMAKE_MKSPECS or path.join(qtenvs.QT_INSTALL_ARCHDATA, "mkspecs") return {sdkdir = sdkdir, bindir = bindir, libexecdir = libexecdir, libdir = libdir, includedir = includedir, qmldir = qmldir, pluginsdir = pluginsdir, mkspecsdir = mkspecsdir, sdkver = sdkver} end -- cgit v1.3.1 From 6bdaa62dd2f12524d3fcfab3834901d7c91a8f72 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 1 Sep 2021 12:15:20 +0800 Subject: Update load.lua --- xmake/rules/qt/load.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/xmake/rules/qt/load.lua b/xmake/rules/qt/load.lua index 03599f7e2..1c4627f11 100644 --- a/xmake/rules/qt/load.lua +++ b/xmake/rules/qt/load.lua @@ -36,7 +36,11 @@ function _link(linkdirs, framework, qt_sdkver) elseif is_plat("android") or is_plat("linux") then debug_suffix = "" end - framework = "Qt" .. qt_sdkver:major() .. framework:sub(3) .. (is_mode("debug") and debug_suffix or "") + if qt_sdkver:ge("5.0") then + framework = "Qt" .. qt_sdkver:major() .. framework:sub(3) .. (is_mode("debug") and debug_suffix or "") + else -- for qt4.x, e.g. QtGui4.lib + framework = "Qt" .. framework:sub(3) .. (is_mode("debug") and debug_suffix or "") .. qt_sdkver:major() + end if is_plat("android") then --> -lQt5Core_armeabi/-lQt5CoreDebug_armeabi for 5.14.x local libinfo = find_library(framework .. "_" .. config.arch(), linkdirs) if libinfo and libinfo.link then -- cgit v1.3.1 From 985541b808d3ff8b7302fae7214a0e868e3a8346 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 1 Sep 2021 12:30:03 +0800 Subject: Update xmake.lua --- xmake/rules/qt/xmake.lua | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/xmake/rules/qt/xmake.lua b/xmake/rules/qt/xmake.lua index ed4deedb7..3310f596a 100644 --- a/xmake/rules/qt/xmake.lua +++ b/xmake/rules/qt/xmake.lua @@ -87,7 +87,20 @@ rule("qt.widgetapp") end) on_config(function (target) - import("load")(target, {gui = true, frameworks = {"QtGui", "QtWidgets", "QtCore"}}) + + -- get qt sdk version + local qt = target:data("qt") + local qt_sdkver = nil + if qt.sdkver then + import("core.base.semver") + qt_sdkver = semver.new(qt.sdkver) + end + + local frameworks = {"QtGui", "QtWidgets", "QtCore"} + if qt_sdkver and qt_sdkver:lt("5.0") then + frameworks = {"QtGui", "QtCore"} -- qt4.x has not QtWidgets, it is in QtGui + end + import("load")(target, {gui = true, frameworks = frameworks}) end) -- deploy application -- cgit v1.3.1 From 6b10c3a9380131639bbf183d78491f6fc0f20535 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 1 Sep 2021 12:31:05 +0800 Subject: Update xmake.lua --- xmake/rules/qt/xmake.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xmake/rules/qt/xmake.lua b/xmake/rules/qt/xmake.lua index 3310f596a..df6f2e79d 100644 --- a/xmake/rules/qt/xmake.lua +++ b/xmake/rules/qt/xmake.lua @@ -140,6 +140,9 @@ rule("qt.widgetapp_static") -- laod some basic plugins and frameworks local plugins = {} local frameworks = {"QtGui", "QtWidgets", "QtCore"} + if qt_sdkver and qt_sdkver:lt("5.0") then + frameworks = {"QtGui", "QtCore"} -- qt4.x has not QtWidgets, it is in QtGui + end if target:is_plat("macosx") then plugins.QCocoaIntegrationPlugin = {linkdirs = "plugins/platforms", links = {"qcocoa", "cups"}} table.join2(frameworks, QtPlatformSupport, "QtWidgets") -- cgit v1.3.1 From 671cabb77b5421fae4fabecdfe9d0df4adf0ddb8 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 1 Sep 2021 13:52:18 +0800 Subject: Update clang.lua --- xmake/modules/core/tools/clang.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/xmake/modules/core/tools/clang.lua b/xmake/modules/core/tools/clang.lua index a0d39f3b4..e5734a953 100644 --- a/xmake/modules/core/tools/clang.lua +++ b/xmake/modules/core/tools/clang.lua @@ -124,3 +124,16 @@ function nf_warning(self, level) } return maps[level] end + +-- make the symbol flag +function nf_symbol(self, level) + local kind = self:kind() + if kind == "ld" or kind == "sh" then + -- clang/windows need add `-g` to linker to generate pdb symbol file + if self:plat() == "windows" and level == "debug" then + return "-g" + end + else + return _super.nf_symbol(self, level) + end +end -- cgit v1.3.1 From b9d4b06cb993b737a28d59561c3b5b4002a429f9 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 1 Sep 2021 15:09:21 +0800 Subject: Update download.lua --- .../modules/private/action/require/impl/actions/download.lua | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/xmake/modules/private/action/require/impl/actions/download.lua b/xmake/modules/private/action/require/impl/actions/download.lua index e4cf8f0cc..ba918e7f4 100644 --- a/xmake/modules/private/action/require/impl/actions/download.lua +++ b/xmake/modules/private/action/require/impl/actions/download.lua @@ -66,7 +66,6 @@ function _checkout(package, url, sourcedir, url_alias) local longpaths = package:policy("platform.longpaths") -- download package from branches? - url = proxy.mirror(url) or url packagedir = path.join(sourcedir .. ".tmp", package:name()) if package:branch() then @@ -104,11 +103,6 @@ function _download(package, url, sourcedir, url_alias, url_excludes) -- get package file local packagefile = url_filename(url) - -- use proxy url? - if not os.isfile(url) then - url = proxy.mirror(url) or url - end - -- get sourcehash from the given url -- -- we need not sourcehash and skip checksum to try download it directly if no version list in package() @@ -230,6 +224,11 @@ function main(package) -- filter url url = filter.handle(url, package) + -- use proxy url? + if not os.isfile(url) then + url = proxy.mirror(url) or url + end + -- download url ok = try { -- cgit v1.3.1 From a4e63a441b807b21510c1cc87c46b6e7c40bc343 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 1 Sep 2021 17:10:47 +0800 Subject: Update extract.lua --- xmake/modules/utils/archive/extract.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/utils/archive/extract.lua b/xmake/modules/utils/archive/extract.lua index 69616fea6..b853e2c8e 100644 --- a/xmake/modules/utils/archive/extract.lua +++ b/xmake/modules/utils/archive/extract.lua @@ -149,7 +149,7 @@ function _extract_using_7z(archivefile, outputdir, extension, opt) -- remove unused pax_global_header file after extracting .tar file if extension == ".tar" then os.tryrm(path.join(outputdir, "pax_global_header")) - os.tryrm(path.join(outputdir, "PaxHeaders.*")) + os.tryrm(path.join(outputdir, "PaxHeaders*")) os.tryrm(path.join(outputdir, "@PaxHeader")) end -- cgit v1.3.1 From dc0d7c82a3908fcd9d5a6ab52ecd69c77793690a Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Wed, 1 Sep 2021 17:19:59 +0800 Subject: fix cuda with c++17 --- xmake/modules/core/tools/nvcc.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/modules/core/tools/nvcc.lua b/xmake/modules/core/tools/nvcc.lua index 784b606c5..1ca09401e 100644 --- a/xmake/modules/core/tools/nvcc.lua +++ b/xmake/modules/core/tools/nvcc.lua @@ -178,6 +178,7 @@ function nf_language(self, stdname) cxx03 = "--std c++03" , cxx11 = "--std c++11" , cxx14 = "--std c++14" + , cxx17 = "--std c++17" } local cxxmaps2 = {} for k, v in pairs(_g.cxxmaps) do -- cgit v1.3.1 From 127b9e87fff155470d5986e89ef4900e00d03c8c Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 1 Sep 2021 23:52:49 +0800 Subject: update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3eb7be9d..6d620e954 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ ### Change * [#1618](https://github.com/xmake-io/xmake/issues/1618): Improve vala to support to generate libraries and bindings +* Improve Qt rules to support Qt 4.x +* Improve `set_symbols("debug")` to generate pdb file for clang on windows ## v2.5.7 @@ -1067,6 +1069,8 @@ ### 改进 * [#1618](https://github.com/xmake-io/xmake/issues/1618): 改进 vala 支持构建动态库和静态库程序 +* 改进 Qt 规则去支持 Qt 4.x +* 改进 `set_symbols("debug")` 支持 clang/windows 生成 pdb 文件 ## v2.5.7 -- cgit v1.3.1 From e54d0fe1a3e4fe3243dcef11d1b2759343015c33 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Sep 2021 22:48:36 +0800 Subject: add find_fpc --- xmake/modules/detect/tools/find_fpc.lua | 52 +++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 xmake/modules/detect/tools/find_fpc.lua diff --git a/xmake/modules/detect/tools/find_fpc.lua b/xmake/modules/detect/tools/find_fpc.lua new file mode 100644 index 000000000..8414acba8 --- /dev/null +++ b/xmake/modules/detect/tools/find_fpc.lua @@ -0,0 +1,52 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_fpc.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find fpc +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local fpc = find_fpc() +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + opt.check = opt.check or "-h" + + -- find program + local program = find_program(opt.program or "fpc", opt) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, opt) + end + return program, version +end -- cgit v1.3.1 From f131f88e73c2c9718f61dee0aac451e00d63f64f Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Sep 2021 22:54:52 +0800 Subject: add pascal tests --- tests/projects/pascal/console/src/main.pas | 4 ++++ tests/projects/pascal/console/xmake.lua | 5 +++++ 2 files changed, 9 insertions(+) create mode 100644 tests/projects/pascal/console/src/main.pas create mode 100644 tests/projects/pascal/console/xmake.lua diff --git a/tests/projects/pascal/console/src/main.pas b/tests/projects/pascal/console/src/main.pas new file mode 100644 index 000000000..a908ffab7 --- /dev/null +++ b/tests/projects/pascal/console/src/main.pas @@ -0,0 +1,4 @@ +program Hello; +begin + writeln ('Hello, world.'); +end. diff --git a/tests/projects/pascal/console/xmake.lua b/tests/projects/pascal/console/xmake.lua new file mode 100644 index 000000000..32fd531a2 --- /dev/null +++ b/tests/projects/pascal/console/xmake.lua @@ -0,0 +1,5 @@ +add_rules("mode.debug", "mode.release") +target("test") + set_kind("binary") + add_files("src/*.pas") + -- cgit v1.3.1 From 3d595c5f5f91bd380d3b43bd0dfc8c1f738c325b Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Sep 2021 23:04:28 +0800 Subject: add pascal stub --- xmake/languages/pascal/check_main.lua | 40 ++++++++++ xmake/languages/pascal/load.lua | 80 +++++++++++++++++++ xmake/languages/pascal/xmake.lua | 96 +++++++++++++++++++++++ xmake/modules/core/tools/fpc.lua | 142 ++++++++++++++++++++++++++++++++++ xmake/rules/pascal/xmake.lua | 46 +++++++++++ xmake/toolchains/fpc/xmake.lua | 34 ++++++++ 6 files changed, 438 insertions(+) create mode 100644 xmake/languages/pascal/check_main.lua create mode 100644 xmake/languages/pascal/load.lua create mode 100644 xmake/languages/pascal/xmake.lua create mode 100644 xmake/modules/core/tools/fpc.lua create mode 100644 xmake/rules/pascal/xmake.lua create mode 100644 xmake/toolchains/fpc/xmake.lua diff --git a/xmake/languages/pascal/check_main.lua b/xmake/languages/pascal/check_main.lua new file mode 100644 index 000000000..a66f70427 --- /dev/null +++ b/xmake/languages/pascal/check_main.lua @@ -0,0 +1,40 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file check_main.lua +-- + +-- check it +function main(sourcefile) + + -- load source code + local sourcecode = io.readfile(sourcefile) + + -- remove comment first + sourcecode = sourcecode:gsub("{%*.-%*}", "") + sourcecode = sourcecode:gsub("//.-\n", "\n") + + -- find 'program xxx' + if sourcecode:find("program%s*%(.-%)") then + return true + end + + -- no main function + return false +end + + diff --git a/xmake/languages/pascal/load.lua b/xmake/languages/pascal/load.lua new file mode 100644 index 000000000..997fc504a --- /dev/null +++ b/xmake/languages/pascal/load.lua @@ -0,0 +1,80 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file load.lua +-- + +function _get_apis() + local apis = {} + apis.values = { + -- target.add_xxx + "target.add_links" + , "target.add_syslinks" + , "target.add_pcflags" + , "target.add_ldflags" + , "target.add_arflags" + , "target.add_shflags" + , "target.add_rpathdirs" -- @note do not translate path, it's usually an absolute path or contains $ORIGIN/@loader_path + -- option.add_xxx + , "option.add_links" + , "option.add_syslinks" + , "option.add_pcflags" + , "option.add_ldflags" + , "option.add_arflags" + , "option.add_shflags" + , "option.add_rpathdirs" + -- package.add_xxx + , "package.add_links" + , "package.add_syslinks" + , "package.add_pcflags" + , "package.add_ldflags" + , "package.add_arflags" + , "package.add_shflags" + , "package.add_rpathdirs" + , "package.add_linkdirs" + , "package.add_includedirs" + , "package.add_sysincludedirs" + -- toolchain.add_xxx + , "toolchain.add_links" + , "toolchain.add_syslinks" + , "toolchain.add_pcflags" + , "toolchain.add_ldflags" + , "toolchain.add_arflags" + , "toolchain.add_shflags" + , "toolchain.add_rpathdirs" + , "toolchain.add_linkdirs" + , "toolchain.add_includedirs" + , "toolchain.add_sysincludedirs" + } + apis.paths = { + -- target.add_xxx + "target.add_linkdirs" + , "target.add_includedirs" + , "target.add_sysincludedirs" + -- option.add_xxx + , "option.add_linkdirs" + , "option.add_includedirs" + , "option.add_sysincludedirs" + } + return apis +end + +function main() + return {apis = _get_apis()} +end + + diff --git a/xmake/languages/pascal/xmake.lua b/xmake/languages/pascal/xmake.lua new file mode 100644 index 000000000..f61a7db38 --- /dev/null +++ b/xmake/languages/pascal/xmake.lua @@ -0,0 +1,96 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +language("pascal") + add_rules("pascal") + set_sourcekinds {pc = {".pas", ".pp"}} + set_sourceflags {pc = "pcflags"} + set_targetkinds {binary = "pcld", static = "ar", shared = "pcsh"} + set_targetflags {binary = "ldflags", static = "arflags", shared = "shflags"} + set_langkinds {pascal = "pc"} + set_mixingkinds("pc", "cc", "cxx", "as") + + on_load("load") + on_check_main("check_main") + + set_nameflags { + object = { + "config.includedirs" + , "target.symbols" + , "target.warnings" + , "target.optimize:check" + , "target.vectorexts:check" + , "target.includedirs" + , "toolchain.includedirs" + , "target.sysincludedirs" + , "toolchain.sysincludedirs" + } + , binary = { + "config.linkdirs" + , "target.linkdirs" + , "target.rpathdirs" + , "target.strip" + , "target.symbols" + , "toolchain.linkdirs" + , "toolchain.rpathdirs" + , "config.links" + , "target.links" + , "toolchain.links" + , "config.syslinks" + , "target.syslinks" + , "toolchain.syslinks" + } + , shared = { + "config.linkdirs" + , "target.linkdirs" + , "target.strip" + , "target.symbols" + , "toolchain.linkdirs" + , "config.links" + , "target.links" + , "toolchain.links" + , "config.syslinks" + , "target.syslinks" + , "toolchain.syslinks" + } + , static = { + "target.strip" + , "target.symbols" + } + } + + set_menu { + config = + { + {category = "Cross Complation Configuration/Compiler Configuration" } + , {nil, "pc", "kv", nil, "The Pascal Compiler" } + + , {category = "Cross Complation Configuration/Linker Configuration" } + , {nil, "pcld", "kv", nil, "The Pascal Linker" } + , {nil, "pcsh", "kv", nil, "The Pascal Shared Library Linker" } + + , {category = "Cross Complation Configuration/Builtin Flags Configuration" } + , {nil, "links", "kv", nil, "The Link Libraries" } + , {nil, "syslinks", "kv", nil, "The System Link Libraries" } + , {nil, "linkdirs", "kv", nil, "The Link Search Directories" } + , {nil, "includedirs","kv", nil, "The Include Search Directories" } + } + } + diff --git a/xmake/modules/core/tools/fpc.lua b/xmake/modules/core/tools/fpc.lua new file mode 100644 index 000000000..1e66b9ad5 --- /dev/null +++ b/xmake/modules/core/tools/fpc.lua @@ -0,0 +1,142 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file fpc.lua +-- + +-- imports +import("core.base.option") +import("core.project.config") +import("core.project.project") +import("core.project.target") + +-- init it +function init(self) + + -- init shflags + self:set("zcshflags", "-dynamic", "-fPIC") + + -- init zcflags for the kind: shared + self:set("shared.zcflags", "-fPIC") +end + +-- make the strip flag +function nf_strip(self, level) + local maps = + { + debug = "--strip" + , all = "--strip" + } + return maps[level] +end + +-- make the define flag +function nf_define(self, macro) + return "-D" .. macro +end + +-- make the optimize flag +function nf_optimize(self, level) + local maps = + { + none = "-O Debug" + , fast = "-O ReleaseSafe" + , aggressive = "-O ReleaseFast" + , fastest = "-O ReleaseFast" + , smallest = "-O ReleaseSmall" + , aggressive = "-O ReleaseFast" + } + return maps[level] +end + +-- make the link flag +function nf_link(self, lib) + return "-l" .. lib +end + +-- make the syslink flag +function nf_syslink(self, lib) + return nf_link(self, lib) +end + +-- make the linkdir flag +function nf_linkdir(self, dir) + return {"-L", dir} +end + +-- make the framework flag +function nf_framework(self, framework) + return {"-framework", framework} +end + +-- make the frameworkdir flag +function nf_frameworkdir(self, frameworkdir) + return {"-F", path.translate(frameworkdir)} +end + +-- make the rpathdir flag +function nf_rpathdir(self, dir) + dir = path.translate(dir) + if is_plat("macosx") then + return {"-rpath", (dir:gsub("%$ORIGIN", "@loader_path"))} + else + return {"-rpath", (dir:gsub("@[%w_]+", function (name) + local maps = {["@loader_path"] = "$ORIGIN", ["@executable_path"] = "$ORIGIN"} + return maps[name] + end))} + end +end + +-- make the link arguments list +function linkargv(self, objectfiles, targetkind, targetfile, flags) + local argv = {} + if targetkind == "binary" then + table.insert(argv, "build-exe") + elseif targetkind == "static" or targetkind == "shared" then + table.insert(argv, "build-lib") + else + raise("unknown target kind(%s)!", targetkind) + end + table.join2(argv, flags, "-femit-bin=" .. targetfile, objectfiles) + return self:program(), argv +end + +-- link the target file +function link(self, objectfiles, targetkind, targetfile, flags) + + -- ensure the target directory + os.mkdir(path.directory(targetfile)) + + -- link it + os.runv(linkargv(self, objectfiles, targetkind, targetfile, flags)) +end + +-- make the compile arguments list +function compargv(self, sourcefile, objectfile, flags) + return self:program(), table.join("build-obj", flags, "-femit-bin=" .. objectfile, sourcefile) +end + +-- compile the source file +function compile(self, sourcefile, objectfile, dependinfo, flags) + + -- ensure the object directory + os.mkdir(path.directory(objectfile)) + + -- compile it + os.runv(compargv(self, sourcefile, objectfile, flags)) +end + diff --git a/xmake/rules/pascal/xmake.lua b/xmake/rules/pascal/xmake.lua new file mode 100644 index 000000000..bca2bc3ce --- /dev/null +++ b/xmake/rules/pascal/xmake.lua @@ -0,0 +1,46 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +-- define rule: pascal.build +rule("pascal.build") + set_sourcekinds("pc") + on_load(function (target) + -- we disable to build across targets in parallel, because the source files may depend on other target modules + target:set("policy", "build.across_targets_in_parallel", false) + end) + on_build_files(function (target, sourcebatch, opt) + import("private.action.build.object").build(target, sourcebatch, opt) + end) + +-- define rule: pascal +rule("pascal") + + -- add build rules + add_deps("pascal.build") + + -- inherit links and linkdirs of all dependent targets by default + add_deps("utils.inherit.links") + + -- support `add_files("src/*.o")` and `add_files("src/*.a")` to merge object and archive files to target + add_deps("utils.merge.object", "utils.merge.archive") + + -- we attempt to extract symbols to the independent file and + -- strip self-target binary if `set_symbols("debug")` and `set_strip("all")` are enabled + add_deps("utils.symbols.extract") diff --git a/xmake/toolchains/fpc/xmake.lua b/xmake/toolchains/fpc/xmake.lua new file mode 100644 index 000000000..d3499867a --- /dev/null +++ b/xmake/toolchains/fpc/xmake.lua @@ -0,0 +1,34 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +-- define toolchain +toolchain("fpc") + + -- set homepage + set_homepage("https://www.freepascal.org/") + set_description("Free Pascal Programming Language Compiler") + + -- on check + on_check(function (toolchain) + end) + + -- on load + on_load(function (toolchain) + end) -- cgit v1.3.1 From 7a73071fac11db852be636b6855b5013599cc3ea Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Sep 2021 23:18:25 +0800 Subject: improve fpc toolchain --- xmake/platforms/linux/xmake.lua | 2 +- xmake/platforms/macosx/xmake.lua | 2 +- xmake/toolchains/fpc/xmake.lua | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/xmake/platforms/linux/xmake.lua b/xmake/platforms/linux/xmake.lua index 7ba068687..f855903f3 100644 --- a/xmake/platforms/linux/xmake.lua +++ b/xmake/platforms/linux/xmake.lua @@ -40,7 +40,7 @@ platform("linux") set_installdir("/usr/local") -- set toolchains - set_toolchains("envs", "cross", "gcc", "clang", "yasm", "nasm", "fasm", "cuda", "dlang", "go", "rust", "gfortran", "zig") + set_toolchains("envs", "cross", "gcc", "clang", "yasm", "nasm", "fasm", "cuda", "dlang", "go", "rust", "gfortran", "zig", "fpc") -- set menu set_menu { diff --git a/xmake/platforms/macosx/xmake.lua b/xmake/platforms/macosx/xmake.lua index 2ff9a10b6..792a5cad3 100644 --- a/xmake/platforms/macosx/xmake.lua +++ b/xmake/platforms/macosx/xmake.lua @@ -40,7 +40,7 @@ platform("macosx") set_installdir("/usr/local") -- set toolchains - set_toolchains("envs", "xcode", "clang", "gcc", "yasm", "nasm", "cuda", "dlang", "rust", "go", "gfortran", "zig") + set_toolchains("envs", "xcode", "clang", "gcc", "yasm", "nasm", "cuda", "dlang", "rust", "go", "gfortran", "zig", "fpc") -- set menu set_menu { diff --git a/xmake/toolchains/fpc/xmake.lua b/xmake/toolchains/fpc/xmake.lua index d3499867a..6ce2bf401 100644 --- a/xmake/toolchains/fpc/xmake.lua +++ b/xmake/toolchains/fpc/xmake.lua @@ -25,9 +25,10 @@ toolchain("fpc") set_homepage("https://www.freepascal.org/") set_description("Free Pascal Programming Language Compiler") - -- on check - on_check(function (toolchain) - end) + -- set toolset + set_toolset("pc", "$(env PC)", "fpc") + set_toolset("pcld", "$(env PC)", "fpc") + set_toolset("pcsh", "$(env PC)", "fpc") -- on load on_load(function (toolchain) -- cgit v1.3.1 From ae7c9e6398f72b314d6601a324d5fbf3829c547b Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Sep 2021 23:29:09 +0800 Subject: improve fpc --- xmake/languages/pascal/xmake.lua | 2 +- xmake/modules/core/tools/fpc.lua | 64 ++-------------------------------------- xmake/toolchains/fpc/xmake.lua | 4 +-- 3 files changed, 5 insertions(+), 65 deletions(-) diff --git a/xmake/languages/pascal/xmake.lua b/xmake/languages/pascal/xmake.lua index f61a7db38..bdf82f290 100644 --- a/xmake/languages/pascal/xmake.lua +++ b/xmake/languages/pascal/xmake.lua @@ -22,7 +22,7 @@ language("pascal") add_rules("pascal") set_sourcekinds {pc = {".pas", ".pp"}} set_sourceflags {pc = "pcflags"} - set_targetkinds {binary = "pcld", static = "ar", shared = "pcsh"} + set_targetkinds {binary = "ld", static = "ar", shared = "sh"} set_targetflags {binary = "ldflags", static = "arflags", shared = "shflags"} set_langkinds {pascal = "pc"} set_mixingkinds("pc", "cc", "cxx", "as") diff --git a/xmake/modules/core/tools/fpc.lua b/xmake/modules/core/tools/fpc.lua index 1e66b9ad5..b83fd6ea8 100644 --- a/xmake/modules/core/tools/fpc.lua +++ b/xmake/modules/core/tools/fpc.lua @@ -26,22 +26,10 @@ import("core.project.target") -- init it function init(self) - - -- init shflags - self:set("zcshflags", "-dynamic", "-fPIC") - - -- init zcflags for the kind: shared - self:set("shared.zcflags", "-fPIC") end -- make the strip flag function nf_strip(self, level) - local maps = - { - debug = "--strip" - , all = "--strip" - } - return maps[level] end -- make the define flag @@ -51,16 +39,6 @@ end -- make the optimize flag function nf_optimize(self, level) - local maps = - { - none = "-O Debug" - , fast = "-O ReleaseSafe" - , aggressive = "-O ReleaseFast" - , fastest = "-O ReleaseFast" - , smallest = "-O ReleaseSmall" - , aggressive = "-O ReleaseFast" - } - return maps[level] end -- make the link flag @@ -78,65 +56,27 @@ function nf_linkdir(self, dir) return {"-L", dir} end --- make the framework flag -function nf_framework(self, framework) - return {"-framework", framework} -end - --- make the frameworkdir flag -function nf_frameworkdir(self, frameworkdir) - return {"-F", path.translate(frameworkdir)} -end - --- make the rpathdir flag -function nf_rpathdir(self, dir) - dir = path.translate(dir) - if is_plat("macosx") then - return {"-rpath", (dir:gsub("%$ORIGIN", "@loader_path"))} - else - return {"-rpath", (dir:gsub("@[%w_]+", function (name) - local maps = {["@loader_path"] = "$ORIGIN", ["@executable_path"] = "$ORIGIN"} - return maps[name] - end))} - end -end - -- make the link arguments list function linkargv(self, objectfiles, targetkind, targetfile, flags) local argv = {} - if targetkind == "binary" then - table.insert(argv, "build-exe") - elseif targetkind == "static" or targetkind == "shared" then - table.insert(argv, "build-lib") - else - raise("unknown target kind(%s)!", targetkind) - end - table.join2(argv, flags, "-femit-bin=" .. targetfile, objectfiles) return self:program(), argv end -- link the target file function link(self, objectfiles, targetkind, targetfile, flags) - - -- ensure the target directory os.mkdir(path.directory(targetfile)) - - -- link it os.runv(linkargv(self, objectfiles, targetkind, targetfile, flags)) end -- make the compile arguments list function compargv(self, sourcefile, objectfile, flags) - return self:program(), table.join("build-obj", flags, "-femit-bin=" .. objectfile, sourcefile) + return self:program(), table.join("-Sd", "-Cn", flags, "-FE" .. path.directory(objectfile), sourcefile) end -- compile the source file function compile(self, sourcefile, objectfile, dependinfo, flags) - - -- ensure the object directory os.mkdir(path.directory(objectfile)) - - -- compile it os.runv(compargv(self, sourcefile, objectfile, flags)) + os.mv(path.join(path.directory(objectfile), path.basename(sourcefile) .. ".o"), objectfile) end diff --git a/xmake/toolchains/fpc/xmake.lua b/xmake/toolchains/fpc/xmake.lua index 6ce2bf401..b59f21376 100644 --- a/xmake/toolchains/fpc/xmake.lua +++ b/xmake/toolchains/fpc/xmake.lua @@ -27,8 +27,8 @@ toolchain("fpc") -- set toolset set_toolset("pc", "$(env PC)", "fpc") - set_toolset("pcld", "$(env PC)", "fpc") - set_toolset("pcsh", "$(env PC)", "fpc") +-- set_toolset("pcld", "$(env PC)", "fpc") +-- set_toolset("pcsh", "$(env PC)", "fpc") -- on load on_load(function (toolchain) -- cgit v1.3.1 From b47154e928d5fa960365a205420912ae1363ba53 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Sep 2021 23:34:28 +0800 Subject: use build mode for fpc --- xmake/languages/pascal/xmake.lua | 2 +- xmake/modules/core/tools/fpc.lua | 47 ++++++++-------------------------------- xmake/rules/pascal/xmake.lua | 15 +------------ xmake/toolchains/fpc/xmake.lua | 7 ++++-- 4 files changed, 16 insertions(+), 55 deletions(-) diff --git a/xmake/languages/pascal/xmake.lua b/xmake/languages/pascal/xmake.lua index bdf82f290..ba052ef36 100644 --- a/xmake/languages/pascal/xmake.lua +++ b/xmake/languages/pascal/xmake.lua @@ -22,7 +22,7 @@ language("pascal") add_rules("pascal") set_sourcekinds {pc = {".pas", ".pp"}} set_sourceflags {pc = "pcflags"} - set_targetkinds {binary = "ld", static = "ar", shared = "sh"} + set_targetkinds {binary = "pcld", static = "pcar", shared = "pcsh"} set_targetflags {binary = "ldflags", static = "arflags", shared = "shflags"} set_langkinds {pascal = "pc"} set_mixingkinds("pc", "cc", "cxx", "as") diff --git a/xmake/modules/core/tools/fpc.lua b/xmake/modules/core/tools/fpc.lua index b83fd6ea8..65662de4c 100644 --- a/xmake/modules/core/tools/fpc.lua +++ b/xmake/modules/core/tools/fpc.lua @@ -22,61 +22,32 @@ import("core.base.option") import("core.project.config") import("core.project.project") -import("core.project.target") -- init it function init(self) end --- make the strip flag -function nf_strip(self, level) -end - --- make the define flag -function nf_define(self, macro) - return "-D" .. macro -end - -- make the optimize flag function nf_optimize(self, level) end --- make the link flag -function nf_link(self, lib) - return "-l" .. lib -end - --- make the syslink flag -function nf_syslink(self, lib) - return nf_link(self, lib) +-- make the symbol flag +function nf_symbol(self, level) end -- make the linkdir flag function nf_linkdir(self, dir) - return {"-L", dir} + return {"-L" .. dir} end --- make the link arguments list -function linkargv(self, objectfiles, targetkind, targetfile, flags) - local argv = {} - return self:program(), argv +-- make the build arguments list +function buildargv(self, sourcefiles, targetkind, targetfile, flags) + return self:program(), table.join(flags, "-o" .. targetfile, sourcefiles) end --- link the target file -function link(self, objectfiles, targetkind, targetfile, flags) +-- build the target file +function build(self, sourcefiles, targetkind, targetfile, flags) os.mkdir(path.directory(targetfile)) - os.runv(linkargv(self, objectfiles, targetkind, targetfile, flags)) -end - --- make the compile arguments list -function compargv(self, sourcefile, objectfile, flags) - return self:program(), table.join("-Sd", "-Cn", flags, "-FE" .. path.directory(objectfile), sourcefile) -end - --- compile the source file -function compile(self, sourcefile, objectfile, dependinfo, flags) - os.mkdir(path.directory(objectfile)) - os.runv(compargv(self, sourcefile, objectfile, flags)) - os.mv(path.join(path.directory(objectfile), path.basename(sourcefile) .. ".o"), objectfile) + os.runv(buildargv(self, sourcefiles, targetkind, targetfile, flags)) end diff --git a/xmake/rules/pascal/xmake.lua b/xmake/rules/pascal/xmake.lua index bca2bc3ce..5961c08d3 100644 --- a/xmake/rules/pascal/xmake.lua +++ b/xmake/rules/pascal/xmake.lua @@ -21,13 +21,7 @@ -- define rule: pascal.build rule("pascal.build") set_sourcekinds("pc") - on_load(function (target) - -- we disable to build across targets in parallel, because the source files may depend on other target modules - target:set("policy", "build.across_targets_in_parallel", false) - end) - on_build_files(function (target, sourcebatch, opt) - import("private.action.build.object").build(target, sourcebatch, opt) - end) + on_build("build.target") -- define rule: pascal rule("pascal") @@ -37,10 +31,3 @@ rule("pascal") -- inherit links and linkdirs of all dependent targets by default add_deps("utils.inherit.links") - - -- support `add_files("src/*.o")` and `add_files("src/*.a")` to merge object and archive files to target - add_deps("utils.merge.object", "utils.merge.archive") - - -- we attempt to extract symbols to the independent file and - -- strip self-target binary if `set_symbols("debug")` and `set_strip("all")` are enabled - add_deps("utils.symbols.extract") diff --git a/xmake/toolchains/fpc/xmake.lua b/xmake/toolchains/fpc/xmake.lua index b59f21376..5fab445af 100644 --- a/xmake/toolchains/fpc/xmake.lua +++ b/xmake/toolchains/fpc/xmake.lua @@ -27,9 +27,12 @@ toolchain("fpc") -- set toolset set_toolset("pc", "$(env PC)", "fpc") --- set_toolset("pcld", "$(env PC)", "fpc") --- set_toolset("pcsh", "$(env PC)", "fpc") + set_toolset("pcld", "$(env PC)", "fpc") + set_toolset("pcsh", "$(env PC)", "fpc") + set_toolset("pcar", "$(env PC)", "fpc") -- on load on_load(function (toolchain) + toolchain:set("pcshflags", "") + toolchain:set("pcldflags", "") end) -- cgit v1.3.1 From 1306c34442e6089f05ef54b0772d4fb629c25117 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Sep 2021 23:37:05 +0800 Subject: add shared test for pascal --- tests/projects/pascal/shared/src/foo.pas | 23 +++++++++++++++++++++++ tests/projects/pascal/shared/src/main.pas | 14 ++++++++++++++ tests/projects/pascal/shared/xmake.lua | 10 ++++++++++ 3 files changed, 47 insertions(+) create mode 100644 tests/projects/pascal/shared/src/foo.pas create mode 100644 tests/projects/pascal/shared/src/main.pas create mode 100644 tests/projects/pascal/shared/xmake.lua diff --git a/tests/projects/pascal/shared/src/foo.pas b/tests/projects/pascal/shared/src/foo.pas new file mode 100644 index 000000000..2d12d39f5 --- /dev/null +++ b/tests/projects/pascal/shared/src/foo.pas @@ -0,0 +1,23 @@ +library subs; + +function SubStr(CString: PChar;FromPos,ToPos: Longint): PChar; cdecl; + +var + Length: Integer; + +begin + Length := StrLen(CString); + SubStr := CString + Length; + if (FromPos > 0) and (ToPos >= FromPos) then + begin + if Length >= FromPos then + SubStr := CString + FromPos; + if Length > ToPos then + CString[ToPos+1] := #0; + end; +end; + +exports + SubStr; + +end. diff --git a/tests/projects/pascal/shared/src/main.pas b/tests/projects/pascal/shared/src/main.pas new file mode 100644 index 000000000..9ee983a12 --- /dev/null +++ b/tests/projects/pascal/shared/src/main.pas @@ -0,0 +1,14 @@ +uses strings; + +function SubStr(const CString: PChar; FromPos, ToPos: longint): PChar; + cdecl; external 'subs'; + +var + s: PChar; + FromPos, ToPos: Integer; +begin + s := strnew('TestMe'); + FromPos := 2; + ToPos := 3; + WriteLn(SubStr(s, FromPos, ToPos)); +end. diff --git a/tests/projects/pascal/shared/xmake.lua b/tests/projects/pascal/shared/xmake.lua new file mode 100644 index 000000000..96697bcbd --- /dev/null +++ b/tests/projects/pascal/shared/xmake.lua @@ -0,0 +1,10 @@ +add_rules("mode.debug", "mode.release") +target("foo") + set_kind("shared") + add_files("src/foo.pas") + +target("test") + set_kind("binary") + add_deps("foo") + add_files("src/main.pas") + -- cgit v1.3.1 From 684ba799f95d3f8832a9e220ce2743aa2ecb505f Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Sep 2021 23:38:26 +0800 Subject: improve fpc link --- tests/projects/pascal/shared/xmake.lua | 1 - xmake/modules/core/tools/fpc.lua | 12 +++- xmake/modules/detect/tools/fpc/has_flags.lua | 98 ++++++++++++++++++++++++++++ xmake/toolchains/fpc/xmake.lua | 4 +- 4 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 xmake/modules/detect/tools/fpc/has_flags.lua diff --git a/tests/projects/pascal/shared/xmake.lua b/tests/projects/pascal/shared/xmake.lua index 96697bcbd..d96c29d5f 100644 --- a/tests/projects/pascal/shared/xmake.lua +++ b/tests/projects/pascal/shared/xmake.lua @@ -7,4 +7,3 @@ target("test") set_kind("binary") add_deps("foo") add_files("src/main.pas") - diff --git a/xmake/modules/core/tools/fpc.lua b/xmake/modules/core/tools/fpc.lua index 65662de4c..7062228cc 100644 --- a/xmake/modules/core/tools/fpc.lua +++ b/xmake/modules/core/tools/fpc.lua @@ -35,9 +35,19 @@ end function nf_symbol(self, level) end +-- make the link flag +function nf_link(self, lib) + return "-k-l" .. lib +end + +-- make the syslink flag +function nf_syslink(self, lib) + return nf_link(self, lib) +end + -- make the linkdir flag function nf_linkdir(self, dir) - return {"-L" .. dir} + return {"-k-L" .. dir} end -- make the build arguments list diff --git a/xmake/modules/detect/tools/fpc/has_flags.lua b/xmake/modules/detect/tools/fpc/has_flags.lua new file mode 100644 index 000000000..9f66939cc --- /dev/null +++ b/xmake/modules/detect/tools/fpc/has_flags.lua @@ -0,0 +1,98 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file has_flags.lua +-- + +-- imports +import("core.cache.detectcache") + +-- try running +function _try_running(...) + + local argv = {...} + local errors = nil + return try { function () os.runv(unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors +end + +-- attempt to check it from the argument list +function _check_from_arglist(flags, opt) + + -- only one flag? + if #flags > 1 then + return + end + + -- make cache key + local key = "detect.tools.fpc.has_flags" + + -- make allflags key + local flagskey = opt.program .. "_" .. (opt.programver or "") + + -- get all allflags from argument list + local allflags = detectcache:get2(key, flagskey) + if not allflags then + + -- get argument list + allflags = {} + local arglist = os.iorunv(opt.program, {"-h"}) + if arglist then + for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do + allflags[arg] = true + end + end + + -- save cache + detectcache:set2(key, flagskey, allflags) + detectcache:save() + end + return allflags[flags[1]] +end + +-- try running to check flags +function _check_try_running(flags, opt) + + -- make an stub source file + local sourcefile = path.join(os.tmpdir(), "detect", "fpc_has_flags.pas") + if not os.isfile(sourcefile) then + io.writefile(sourcefile, "program Hello;\nbegin\nend.") + end + + -- check it + local binaryfile = os.tmpfile() + local ok, errors = _try_running(opt.program, table.join(flags, "-o" .. binaryfile, sourcefile)) + os.tryrm(binaryfile) + return ok, errors +end + +-- has_flags(flags)? +-- +-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|rc|dc|mm|mxx]"} +-- +-- @return true or false +-- +function main(flags, opt) + + -- attempt to check it from the argument list + if _check_from_arglist(flags, opt) then + return true + end + + -- try running to check it + return _check_try_running(flags, opt) +end + diff --git a/xmake/toolchains/fpc/xmake.lua b/xmake/toolchains/fpc/xmake.lua index 5fab445af..82c7f6dc8 100644 --- a/xmake/toolchains/fpc/xmake.lua +++ b/xmake/toolchains/fpc/xmake.lua @@ -33,6 +33,6 @@ toolchain("fpc") -- on load on_load(function (toolchain) - toolchain:set("pcshflags", "") - toolchain:set("pcldflags", "") + toolchain:set("pcshflags", "-Sd") + toolchain:set("pcldflags", "-Sd") end) -- cgit v1.3.1 From 13acaccc305ef18631601d1d23bfae1c9faef490 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Sep 2021 23:42:22 +0800 Subject: add rpath for pascal --- xmake/languages/pascal/load.lua | 10 ++------- xmake/languages/pascal/xmake.lua | 24 ++++++++-------------- xmake/modules/core/tools/fpc.lua | 44 ++++++++++++++++++++++++++++++++++++++++ xmake/modules/core/tools/zig.lua | 1 - 4 files changed, 55 insertions(+), 24 deletions(-) diff --git a/xmake/languages/pascal/load.lua b/xmake/languages/pascal/load.lua index 997fc504a..6a1f1ca5b 100644 --- a/xmake/languages/pascal/load.lua +++ b/xmake/languages/pascal/load.lua @@ -23,6 +23,7 @@ function _get_apis() apis.values = { -- target.add_xxx "target.add_links" + , "target.add_frameworks" , "target.add_syslinks" , "target.add_pcflags" , "target.add_ldflags" @@ -46,8 +47,6 @@ function _get_apis() , "package.add_shflags" , "package.add_rpathdirs" , "package.add_linkdirs" - , "package.add_includedirs" - , "package.add_sysincludedirs" -- toolchain.add_xxx , "toolchain.add_links" , "toolchain.add_syslinks" @@ -57,18 +56,13 @@ function _get_apis() , "toolchain.add_shflags" , "toolchain.add_rpathdirs" , "toolchain.add_linkdirs" - , "toolchain.add_includedirs" - , "toolchain.add_sysincludedirs" } apis.paths = { -- target.add_xxx "target.add_linkdirs" - , "target.add_includedirs" - , "target.add_sysincludedirs" + , "target.add_frameworkdirs" -- option.add_xxx , "option.add_linkdirs" - , "option.add_includedirs" - , "option.add_sysincludedirs" } return apis end diff --git a/xmake/languages/pascal/xmake.lua b/xmake/languages/pascal/xmake.lua index ba052ef36..a3e1fb5b3 100644 --- a/xmake/languages/pascal/xmake.lua +++ b/xmake/languages/pascal/xmake.lua @@ -25,22 +25,17 @@ language("pascal") set_targetkinds {binary = "pcld", static = "pcar", shared = "pcsh"} set_targetflags {binary = "ldflags", static = "arflags", shared = "shflags"} set_langkinds {pascal = "pc"} - set_mixingkinds("pc", "cc", "cxx", "as") + set_mixingkinds("pc") on_load("load") on_check_main("check_main") set_nameflags { object = { - "config.includedirs" - , "target.symbols" + "target.symbols" , "target.warnings" , "target.optimize:check" , "target.vectorexts:check" - , "target.includedirs" - , "toolchain.includedirs" - , "target.sysincludedirs" - , "toolchain.sysincludedirs" } , binary = { "config.linkdirs" @@ -52,6 +47,8 @@ language("pascal") , "toolchain.rpathdirs" , "config.links" , "target.links" + , "target.frameworks" + , "target.frameworkdirs" , "toolchain.links" , "config.syslinks" , "target.syslinks" @@ -65,32 +62,29 @@ language("pascal") , "toolchain.linkdirs" , "config.links" , "target.links" + , "target.frameworks" + , "target.frameworkdirs" , "toolchain.links" , "config.syslinks" , "target.syslinks" , "toolchain.syslinks" } - , static = { - "target.strip" - , "target.symbols" - } } set_menu { config = { {category = "Cross Complation Configuration/Compiler Configuration" } - , {nil, "pc", "kv", nil, "The Pascal Compiler" } + , {nil, "pc", "kv", nil, "The Pascal Compiler" } , {category = "Cross Complation Configuration/Linker Configuration" } - , {nil, "pcld", "kv", nil, "The Pascal Linker" } - , {nil, "pcsh", "kv", nil, "The Pascal Shared Library Linker" } + , {nil, "pcld", "kv", nil, "The Pascal Linker" } + , {nil, "pcsh", "kv", nil, "The Pascal Shared Library Linker" } , {category = "Cross Complation Configuration/Builtin Flags Configuration" } , {nil, "links", "kv", nil, "The Link Libraries" } , {nil, "syslinks", "kv", nil, "The System Link Libraries" } , {nil, "linkdirs", "kv", nil, "The Link Search Directories" } - , {nil, "includedirs","kv", nil, "The Include Search Directories" } } } diff --git a/xmake/modules/core/tools/fpc.lua b/xmake/modules/core/tools/fpc.lua index 7062228cc..0f2d3025f 100644 --- a/xmake/modules/core/tools/fpc.lua +++ b/xmake/modules/core/tools/fpc.lua @@ -29,10 +29,33 @@ end -- make the optimize flag function nf_optimize(self, level) + local maps = + { + none = "-O-" + , fast = "-O1" + , fastest = "-O3" + , smallest = "-O2" + , aggressive = "-O4" + } + return maps[level] +end + +-- make the strip flag +function nf_strip(self, level) + if level == "all" then + return "-Xs" + end end -- make the symbol flag function nf_symbol(self, level) + if level == "debug" and self:kind() == "pc" then + if self:plat() == "windows" then + return {"-gw3", "-WN"} + else + return "-gw3" + end + end end -- make the link flag @@ -50,6 +73,27 @@ function nf_linkdir(self, dir) return {"-k-L" .. dir} end +-- make the rpathdir flag +function nf_rpathdir(self, dir) + dir = path.translate(dir) + if self:has_flags("-k,-rpath=" .. dir, "ldflags") then + return {"-k,-rpath=" .. (dir:gsub("@[%w_]+", function (name) + local maps = {["@loader_path"] = "$ORIGIN", ["@executable_path"] = "$ORIGIN"} + return maps[name] + end))} + end +end + +-- make the framework flag +function nf_framework(self, framework) + return {"-k-framework", framework} +end + +-- make the frameworkdir flag +function nf_frameworkdir(self, frameworkdir) + return {"-k-F", path.translate(frameworkdir)} +end + -- make the build arguments list function buildargv(self, sourcefiles, targetkind, targetfile, flags) return self:program(), table.join(flags, "-o" .. targetfile, sourcefiles) diff --git a/xmake/modules/core/tools/zig.lua b/xmake/modules/core/tools/zig.lua index 2270e2a3e..140e1ae0a 100644 --- a/xmake/modules/core/tools/zig.lua +++ b/xmake/modules/core/tools/zig.lua @@ -55,7 +55,6 @@ function nf_optimize(self, level) { none = "-O Debug" , fast = "-O ReleaseSafe" - , aggressive = "-O ReleaseFast" , fastest = "-O ReleaseFast" , smallest = "-O ReleaseSmall" , aggressive = "-O ReleaseFast" -- cgit v1.3.1 From ef248c45a806beb1347f3080cb521c4141da4682 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Sep 2021 23:47:31 +0800 Subject: improve rpath for fpc --- tests/projects/pascal/shared/src/foo.pas | 2 +- tests/projects/pascal/shared/src/main.pas | 2 +- xmake/modules/core/tools/fpc.lua | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/projects/pascal/shared/src/foo.pas b/tests/projects/pascal/shared/src/foo.pas index 2d12d39f5..d1952cf21 100644 --- a/tests/projects/pascal/shared/src/foo.pas +++ b/tests/projects/pascal/shared/src/foo.pas @@ -1,4 +1,4 @@ -library subs; +library foo; function SubStr(CString: PChar;FromPos,ToPos: Longint): PChar; cdecl; diff --git a/tests/projects/pascal/shared/src/main.pas b/tests/projects/pascal/shared/src/main.pas index 9ee983a12..ccf2e179b 100644 --- a/tests/projects/pascal/shared/src/main.pas +++ b/tests/projects/pascal/shared/src/main.pas @@ -1,7 +1,7 @@ uses strings; function SubStr(const CString: PChar; FromPos, ToPos: longint): PChar; - cdecl; external 'subs'; + cdecl; external 'foo'; var s: PChar; diff --git a/xmake/modules/core/tools/fpc.lua b/xmake/modules/core/tools/fpc.lua index 0f2d3025f..de5b349c6 100644 --- a/xmake/modules/core/tools/fpc.lua +++ b/xmake/modules/core/tools/fpc.lua @@ -76,8 +76,8 @@ end -- make the rpathdir flag function nf_rpathdir(self, dir) dir = path.translate(dir) - if self:has_flags("-k,-rpath=" .. dir, "ldflags") then - return {"-k,-rpath=" .. (dir:gsub("@[%w_]+", function (name) + if self:has_flags("-k-rpath=" .. dir, "ldflags") then + return {"-k-rpath=" .. (dir:gsub("@[%w_]+", function (name) local maps = {["@loader_path"] = "$ORIGIN", ["@executable_path"] = "$ORIGIN"} return maps[name] end))} -- cgit v1.3.1 From 593406d1f642fd2c5b83264b0b2f60cf7fdbc8ca Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Sep 2021 23:48:08 +0800 Subject: add pascal template --- xmake/templates/pascal/console/project/src/main.pas | 4 ++++ xmake/templates/pascal/console/project/xmake.lua | 7 +++++++ xmake/templates/pascal/console/template.lua | 2 ++ 3 files changed, 13 insertions(+) create mode 100644 xmake/templates/pascal/console/project/src/main.pas create mode 100644 xmake/templates/pascal/console/project/xmake.lua create mode 100644 xmake/templates/pascal/console/template.lua diff --git a/xmake/templates/pascal/console/project/src/main.pas b/xmake/templates/pascal/console/project/src/main.pas new file mode 100644 index 000000000..a908ffab7 --- /dev/null +++ b/xmake/templates/pascal/console/project/src/main.pas @@ -0,0 +1,4 @@ +program Hello; +begin + writeln ('Hello, world.'); +end. diff --git a/xmake/templates/pascal/console/project/xmake.lua b/xmake/templates/pascal/console/project/xmake.lua new file mode 100644 index 000000000..155005840 --- /dev/null +++ b/xmake/templates/pascal/console/project/xmake.lua @@ -0,0 +1,7 @@ +add_rules("mode.debug", "mode.release") + +target("${TARGETNAME}") + set_kind("binary") + add_files("src/*.pas") + +${FAQ} diff --git a/xmake/templates/pascal/console/template.lua b/xmake/templates/pascal/console/template.lua new file mode 100644 index 000000000..ed2e13b57 --- /dev/null +++ b/xmake/templates/pascal/console/template.lua @@ -0,0 +1,2 @@ +template("console") + add_configfiles("xmake.lua") -- cgit v1.3.1 From 53e79a864277f085803cd605b9807bd19a499aad Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Sep 2021 23:49:05 +0800 Subject: add vala template --- xmake/templates/vala/console/project/src/main.vala | 21 +++++++++++++++++++++ xmake/templates/vala/console/project/xmake.lua | 12 ++++++++++++ xmake/templates/vala/console/template.lua | 2 ++ xmake/templates/vala/shared/project/src/main.vala | 6 ++++++ xmake/templates/vala/shared/project/src/mymath.vala | 9 +++++++++ xmake/templates/vala/shared/project/xmake.lua | 18 ++++++++++++++++++ xmake/templates/vala/shared/template.lua | 2 ++ xmake/templates/vala/static/project/src/main.vala | 6 ++++++ xmake/templates/vala/static/project/src/mymath.vala | 9 +++++++++ xmake/templates/vala/static/project/xmake.lua | 18 ++++++++++++++++++ xmake/templates/vala/static/template.lua | 2 ++ 11 files changed, 105 insertions(+) create mode 100644 xmake/templates/vala/console/project/src/main.vala create mode 100644 xmake/templates/vala/console/project/xmake.lua create mode 100644 xmake/templates/vala/console/template.lua create mode 100644 xmake/templates/vala/shared/project/src/main.vala create mode 100644 xmake/templates/vala/shared/project/src/mymath.vala create mode 100644 xmake/templates/vala/shared/project/xmake.lua create mode 100644 xmake/templates/vala/shared/template.lua create mode 100644 xmake/templates/vala/static/project/src/main.vala create mode 100644 xmake/templates/vala/static/project/src/mymath.vala create mode 100644 xmake/templates/vala/static/project/xmake.lua create mode 100644 xmake/templates/vala/static/template.lua diff --git a/xmake/templates/vala/console/project/src/main.vala b/xmake/templates/vala/console/project/src/main.vala new file mode 100644 index 000000000..8e8a32da0 --- /dev/null +++ b/xmake/templates/vala/console/project/src/main.vala @@ -0,0 +1,21 @@ +using Lua; + +static int my_func (LuaVM vm) { + stdout.printf ("Vala Code From Lua Code! (%f)\n", vm.to_number (1)); + return 1; +} + +static int main (string[] args) { + + string code = """ + print "Lua Code From Vala Code!" + my_func(33) + """; + + var vm = new LuaVM (); + vm.open_libs (); + vm.register ("my_func", my_func); + vm.do_string (code); + + return 0; +} diff --git a/xmake/templates/vala/console/project/xmake.lua b/xmake/templates/vala/console/project/xmake.lua new file mode 100644 index 000000000..474572597 --- /dev/null +++ b/xmake/templates/vala/console/project/xmake.lua @@ -0,0 +1,12 @@ +add_rules("mode.debug", "mode.release") + +add_requires("lua", "glib") + +target("${TARGETNAME}") + set_kind("binary") + add_rules("vala") + add_files("src/*.vala") + add_packages("lua", "glib") + add_values("vala.packages", "lua") + +${FAQ} diff --git a/xmake/templates/vala/console/template.lua b/xmake/templates/vala/console/template.lua new file mode 100644 index 000000000..ed2e13b57 --- /dev/null +++ b/xmake/templates/vala/console/template.lua @@ -0,0 +1,2 @@ +template("console") + add_configfiles("xmake.lua") diff --git a/xmake/templates/vala/shared/project/src/main.vala b/xmake/templates/vala/shared/project/src/main.vala new file mode 100644 index 000000000..da9fd895e --- /dev/null +++ b/xmake/templates/vala/shared/project/src/main.vala @@ -0,0 +1,6 @@ +using MyMath; + +public void main() { + stdout.printf("\n\t2 + 3 is %d", sum(2, 3)); + stdout.printf("\n\t8 squared is %d\n", square(8)); +} diff --git a/xmake/templates/vala/shared/project/src/mymath.vala b/xmake/templates/vala/shared/project/src/mymath.vala new file mode 100644 index 000000000..4f4e761c5 --- /dev/null +++ b/xmake/templates/vala/shared/project/src/mymath.vala @@ -0,0 +1,9 @@ +namespace MyMath { + public int sum(int a, int b) { + return(a + b); + } + + public int square(int a) { + return(a * a); + } +} diff --git a/xmake/templates/vala/shared/project/xmake.lua b/xmake/templates/vala/shared/project/xmake.lua new file mode 100644 index 000000000..e9148106c --- /dev/null +++ b/xmake/templates/vala/shared/project/xmake.lua @@ -0,0 +1,18 @@ +add_rules("mode.release", "mode.debug") + +add_requires("glib") + +target("mymath") + set_kind("shared") + add_rules("vala") + add_files("src/mymath.vala") + add_values("vala.header", "mymath.h") + add_values("vala.vapi", "mymath-1.0.vapi") + add_packages("glib") + +target("${TARGETNAME}") + set_kind("binary") + add_deps("mymath") + add_rules("vala") + add_files("src/main.vala") + add_packages("glib") diff --git a/xmake/templates/vala/shared/template.lua b/xmake/templates/vala/shared/template.lua new file mode 100644 index 000000000..d7ec5bae4 --- /dev/null +++ b/xmake/templates/vala/shared/template.lua @@ -0,0 +1,2 @@ +template("shared") + add_configfiles("xmake.lua") diff --git a/xmake/templates/vala/static/project/src/main.vala b/xmake/templates/vala/static/project/src/main.vala new file mode 100644 index 000000000..da9fd895e --- /dev/null +++ b/xmake/templates/vala/static/project/src/main.vala @@ -0,0 +1,6 @@ +using MyMath; + +public void main() { + stdout.printf("\n\t2 + 3 is %d", sum(2, 3)); + stdout.printf("\n\t8 squared is %d\n", square(8)); +} diff --git a/xmake/templates/vala/static/project/src/mymath.vala b/xmake/templates/vala/static/project/src/mymath.vala new file mode 100644 index 000000000..4f4e761c5 --- /dev/null +++ b/xmake/templates/vala/static/project/src/mymath.vala @@ -0,0 +1,9 @@ +namespace MyMath { + public int sum(int a, int b) { + return(a + b); + } + + public int square(int a) { + return(a * a); + } +} diff --git a/xmake/templates/vala/static/project/xmake.lua b/xmake/templates/vala/static/project/xmake.lua new file mode 100644 index 000000000..143566fcb --- /dev/null +++ b/xmake/templates/vala/static/project/xmake.lua @@ -0,0 +1,18 @@ +add_rules("mode.release", "mode.debug") + +add_requires("glib") + +target("mymath") + set_kind("static") + add_rules("vala") + add_files("src/mymath.vala") + add_values("vala.header", "mymath.h") + add_values("vala.vapi", "mymath-1.0.vapi") + add_packages("glib") + +target("${TARGETNAME}") + set_kind("binary") + add_deps("mymath") + add_rules("vala") + add_files("src/main.vala") + add_packages("glib") diff --git a/xmake/templates/vala/static/template.lua b/xmake/templates/vala/static/template.lua new file mode 100644 index 000000000..abfe91a4b --- /dev/null +++ b/xmake/templates/vala/static/template.lua @@ -0,0 +1,2 @@ +template("static") + add_configfiles("xmake.lua") -- cgit v1.3.1 From 5742d2bd4c4b7e760c22531c37d8c9eb5d7df709 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Sep 2021 23:51:22 +0800 Subject: add missing files --- xmake/rules/pascal/build/target.lua | 98 +++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 xmake/rules/pascal/build/target.lua diff --git a/xmake/rules/pascal/build/target.lua b/xmake/rules/pascal/build/target.lua new file mode 100644 index 000000000..8d7662055 --- /dev/null +++ b/xmake/rules/pascal/build/target.lua @@ -0,0 +1,98 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file target.lua +-- + +-- imports +import("core.base.option") +import("core.base.hashset") +import("core.theme.theme") +import("core.tool.compiler") +import("core.project.depend") + +-- build the source files +function build_sourcefiles(target, sourcebatch, opt) + + -- is verbose? + local verbose = option.get("verbose") + + -- get progress range + local progress = assert(opt.progress, "no progress!") + + -- get the target file + local targetfile = target:targetfile() + + -- get source files and kind + local sourcefiles = sourcebatch.sourcefiles + local sourcekind = sourcebatch.sourcekind + + -- get depend file + local dependfile = target:dependfile(targetfile) + + -- load compiler + local compinst = compiler.load(sourcekind, {target = target}) + + -- get compile flags + local compflags = compinst:compflags({target = target}) + + -- load dependent info + local dependinfo = option.get("rebuild") and {} or (depend.load(dependfile) or {}) + + -- need build this object? + local depvalues = {compinst:program(), compflags} + if not depend.is_changed(dependinfo, {lastmtime = os.mtime(targetfile), values = depvalues}) then + return + end + + -- trace progress into + cprintf("${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} ", progress) + if verbose then + cprint("${dim color.build.target}linking.$(mode) %s", path.filename(targetfile)) + else + cprint("${color.build.target}linking.$(mode) %s", path.filename(targetfile)) + end + + -- trace verbose info + if verbose then + print(compinst:buildcmd(sourcefiles, targetfile, {target = target, compflags = compflags})) + end + + -- flush io buffer to update progress info + io.flush() + + -- compile it + dependinfo.files = {} + assert(compinst:build(sourcefiles, targetfile, {target = target, dependinfo = dependinfo, compflags = compflags})) + + -- update files and values to the dependent file + dependinfo.values = depvalues + table.join2(dependinfo.files, sourcefiles) + depend.save(dependinfo, dependfile) +end + +-- build target +function main(target, opt) + + -- @note only support one source kind! + for _, sourcebatch in pairs(target:sourcebatches()) do + if sourcebatch.sourcekind == "pc" then + build_sourcefiles(target, sourcebatch, opt) + break + end + end +end -- cgit v1.3.1 From 5375f19a262a32e9cc9464ed578350026b5b1867 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Sep 2021 23:51:40 +0800 Subject: add fpc to windows --- xmake/platforms/windows/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/platforms/windows/xmake.lua b/xmake/platforms/windows/xmake.lua index fb075adbe..caf707d50 100644 --- a/xmake/platforms/windows/xmake.lua +++ b/xmake/platforms/windows/xmake.lua @@ -38,7 +38,7 @@ platform("windows") set_formats("symbol", "$(name).pdb") -- set toolchains - set_toolchains("msvc", "clang", "yasm", "nasm", "cuda", "dlang", "rust", "go", "gfortran", "zig") + set_toolchains("msvc", "clang", "yasm", "nasm", "cuda", "dlang", "rust", "go", "gfortran", "zig", "fpc") -- set menu set_menu { -- cgit v1.3.1 From 767219ac1f3fb11f592d5a84b62cc2f199ab893a Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Sep 2021 23:52:56 +0800 Subject: update readme and changelog --- CHANGELOG.md | 8 ++++++++ README.md | 2 ++ README_zh.md | 2 ++ 3 files changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d620e954..4524d2b69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### New features + +* [#388](https://github.com/xmake-io/xmake/issues/388): Pascal Language Support + ### Change * [#1618](https://github.com/xmake-io/xmake/issues/1618): Improve vala to support to generate libraries and bindings @@ -1066,6 +1070,10 @@ ## master (开发中) +### 新特性 + +* [#388](https://github.com/xmake-io/xmake/issues/388): Pascal 语言支持,可以使用 fpc 来编译 free pascal + ### 改进 * [#1618](https://github.com/xmake-io/xmake/issues/1618): 改进 vala 支持构建动态库和静态库程序 diff --git a/README.md b/README.md index bbff9155f..425860f22 100644 --- a/README.md +++ b/README.md @@ -223,6 +223,7 @@ emcc A toolchain for compiling to asm.js and WebAssembly icc Intel C/C++ Compiler ifort Intel Fortran Compiler muslcc The musl-based cross-compilation toolchains +fpc Free Pascal Programming Language Compiler ``` ## Supported Languages @@ -239,6 +240,7 @@ muslcc The musl-based cross-compilation toolchains * Cuda * Zig * Vala +* Pascal ## Support Features diff --git a/README_zh.md b/README_zh.md index 2ef9752cf..14ef4938d 100644 --- a/README_zh.md +++ b/README_zh.md @@ -231,6 +231,7 @@ emcc A toolchain for compiling to asm.js and WebAssembly icc Intel C/C++ Compiler ifort Intel Fortran Compiler muslcc The musl-based cross-compilation toolchains +fpc Free Pascal Programming Language Compiler ``` ## 支持语言 @@ -246,6 +247,7 @@ muslcc The musl-based cross-compilation toolchains * Cuda * Zig * Vala +* Pascal ## 支持特性 -- cgit v1.3.1 From 91a2ebc3edf46a26c00807953e3a22d716bdeb95 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 3 Sep 2021 00:14:46 +0800 Subject: add static library for pascal --- tests/projects/pascal/static/src/foo.pas | 23 +++++++++++++++++++++++ tests/projects/pascal/static/src/main.pas | 14 ++++++++++++++ tests/projects/pascal/static/xmake.lua | 9 +++++++++ xmake/modules/core/tools/fpc.lua | 1 + 4 files changed, 47 insertions(+) create mode 100644 tests/projects/pascal/static/src/foo.pas create mode 100644 tests/projects/pascal/static/src/main.pas create mode 100644 tests/projects/pascal/static/xmake.lua diff --git a/tests/projects/pascal/static/src/foo.pas b/tests/projects/pascal/static/src/foo.pas new file mode 100644 index 000000000..d1952cf21 --- /dev/null +++ b/tests/projects/pascal/static/src/foo.pas @@ -0,0 +1,23 @@ +library foo; + +function SubStr(CString: PChar;FromPos,ToPos: Longint): PChar; cdecl; + +var + Length: Integer; + +begin + Length := StrLen(CString); + SubStr := CString + Length; + if (FromPos > 0) and (ToPos >= FromPos) then + begin + if Length >= FromPos then + SubStr := CString + FromPos; + if Length > ToPos then + CString[ToPos+1] := #0; + end; +end; + +exports + SubStr; + +end. diff --git a/tests/projects/pascal/static/src/main.pas b/tests/projects/pascal/static/src/main.pas new file mode 100644 index 000000000..ccf2e179b --- /dev/null +++ b/tests/projects/pascal/static/src/main.pas @@ -0,0 +1,14 @@ +uses strings; + +function SubStr(const CString: PChar; FromPos, ToPos: longint): PChar; + cdecl; external 'foo'; + +var + s: PChar; + FromPos, ToPos: Integer; +begin + s := strnew('TestMe'); + FromPos := 2; + ToPos := 3; + WriteLn(SubStr(s, FromPos, ToPos)); +end. diff --git a/tests/projects/pascal/static/xmake.lua b/tests/projects/pascal/static/xmake.lua new file mode 100644 index 000000000..759cf69ad --- /dev/null +++ b/tests/projects/pascal/static/xmake.lua @@ -0,0 +1,9 @@ +add_rules("mode.debug", "mode.release") +target("foo") + set_kind("static") + add_files("src/foo.pas") + +target("test") + set_kind("binary") + add_deps("foo") + add_files("src/main.pas") diff --git a/xmake/modules/core/tools/fpc.lua b/xmake/modules/core/tools/fpc.lua index de5b349c6..378c4175a 100644 --- a/xmake/modules/core/tools/fpc.lua +++ b/xmake/modules/core/tools/fpc.lua @@ -25,6 +25,7 @@ import("core.project.project") -- init it function init(self) + self:set("pcarflags", "-Xt") end -- make the optimize flag -- cgit v1.3.1 From 5081081d6c1ca1a7198ac646adc755efb49b6b38 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 3 Sep 2021 22:49:25 +0800 Subject: fix add_files --- xmake/core/project/target.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index ac9b63a0c..0ff4222fa 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -1167,22 +1167,22 @@ function _instance:fileconfig(sourcefile) -- match source files local results = os.match(filepath) - if #results == 0 then + if #results == 0 and not fileconfig.always_added then local sourceinfo = (self:get("__sourceinfo_files") or {})[filepath] or {} utils.warning("cannot match %s(%s).add_files(\"%s\") at %s:%d", self:type(), self:name(), filepath, sourceinfo.file or "", sourceinfo.line or -1) end -- process source files for _, file in ipairs(results) do - - -- convert to the relative path if path.is_absolute(file) then file = path.relative(file, os.projectdir()) end - - -- save it filesconfig[file] = fileconfig end + -- we also need support always_added, @see https://github.com/xmake-io/xmake/issues/1634 + if #results == 0 and fileconfig.always_added then + filesconfig[filepath] = fileconfig + end end self._FILESCONFIG = filesconfig end -- cgit v1.3.1 From 836284af26a6d4edb1670cd6266d31c16b43ba2c Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 4 Sep 2021 00:49:01 +0800 Subject: fix pkgconfig --- xmake/modules/private/action/require/impl/actions/install.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/modules/private/action/require/impl/actions/install.lua b/xmake/modules/private/action/require/impl/actions/install.lua index 81f93681e..e733cebfd 100644 --- a/xmake/modules/private/action/require/impl/actions/install.lua +++ b/xmake/modules/private/action/require/impl/actions/install.lua @@ -56,7 +56,7 @@ function _patch_pkgconfig(package) -- get libs local libs = "" for _, linkdir in ipairs(fetchinfo.linkdirs) do - libs = libs .. "-L" .. linkdir + libs = libs .. " -L" .. linkdir end libs = libs .. " -L${libdir}" for _, link in ipairs(fetchinfo.links) do @@ -69,7 +69,7 @@ function _patch_pkgconfig(package) -- cflags local cflags = "" for _, includedir in ipairs(fetchinfo.includedirs) do - cflags = cflags .. "-I" .. includedir + cflags = cflags .. " -I" .. includedir end cflags = cflags .. " -I${includedir}" -- cgit v1.3.1 From c4b3c9836293e77fcfc87b3e8f788cc974b1e59a Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 4 Sep 2021 00:58:26 +0800 Subject: add pascal shared template --- tests/projects/pascal/shared/src/foo.pas | 24 +++++++++------------- tests/projects/pascal/shared/src/main.pas | 15 +++++++------- tests/projects/pascal/static/src/foo.pas | 23 ++++++++------------- tests/projects/pascal/static/src/main.pas | 14 ++++++------- xmake/templates/pascal/shared/project/src/foo.pas | 19 +++++++++++++++++ xmake/templates/pascal/shared/project/src/main.pas | 13 ++++++++++++ xmake/templates/pascal/shared/project/xmake.lua | 12 +++++++++++ xmake/templates/pascal/shared/template.lua | 2 ++ xmake/toolchains/fpc/xmake.lua | 3 +++ 9 files changed, 81 insertions(+), 44 deletions(-) create mode 100644 xmake/templates/pascal/shared/project/src/foo.pas create mode 100644 xmake/templates/pascal/shared/project/src/main.pas create mode 100644 xmake/templates/pascal/shared/project/xmake.lua create mode 100644 xmake/templates/pascal/shared/template.lua diff --git a/tests/projects/pascal/shared/src/foo.pas b/tests/projects/pascal/shared/src/foo.pas index d1952cf21..788950f46 100644 --- a/tests/projects/pascal/shared/src/foo.pas +++ b/tests/projects/pascal/shared/src/foo.pas @@ -1,23 +1,19 @@ library foo; -function SubStr(CString: PChar;FromPos,ToPos: Longint): PChar; cdecl; - -var - Length: Integer; +{$mode objfpc}{$H+} +function fib(n : Int64) : Int64; cdecl; begin - Length := StrLen(CString); - SubStr := CString + Length; - if (FromPos > 0) and (ToPos >= FromPos) then + if n > 1 then begin - if Length >= FromPos then - SubStr := CString + FromPos; - if Length > ToPos then - CString[ToPos+1] := #0; - end; + Result := fib(n - 1) + fib(n - 2); + end + else + Result := 1; end; exports - SubStr; - + fib; end. + + diff --git a/tests/projects/pascal/shared/src/main.pas b/tests/projects/pascal/shared/src/main.pas index ccf2e179b..02d5e88d0 100644 --- a/tests/projects/pascal/shared/src/main.pas +++ b/tests/projects/pascal/shared/src/main.pas @@ -1,14 +1,13 @@ -uses strings; +program hello; -function SubStr(const CString: PChar; FromPos, ToPos: longint): PChar; +function fib(n: Int64): Int64; cdecl; external 'foo'; var - s: PChar; - FromPos, ToPos: Integer; + Value: Integer; begin - s := strnew('TestMe'); - FromPos := 2; - ToPos := 3; - WriteLn(SubStr(s, FromPos, ToPos)); + Value := 5; + WriteLn(fib(Value)); end. + + diff --git a/tests/projects/pascal/static/src/foo.pas b/tests/projects/pascal/static/src/foo.pas index d1952cf21..1fb4d7d6e 100644 --- a/tests/projects/pascal/static/src/foo.pas +++ b/tests/projects/pascal/static/src/foo.pas @@ -1,23 +1,18 @@ library foo; -function SubStr(CString: PChar;FromPos,ToPos: Longint): PChar; cdecl; - -var - Length: Integer; +{$mode objfpc}{$H+} +function fib(n : Int64) : Int64; cdecl; begin - Length := StrLen(CString); - SubStr := CString + Length; - if (FromPos > 0) and (ToPos >= FromPos) then + if n > 1 then begin - if Length >= FromPos then - SubStr := CString + FromPos; - if Length > ToPos then - CString[ToPos+1] := #0; - end; + Result := fib(n - 1) + fib(n - 2); + end + else + Result := 1; end; exports - SubStr; - + fib; end. + diff --git a/tests/projects/pascal/static/src/main.pas b/tests/projects/pascal/static/src/main.pas index ccf2e179b..ce34e4af9 100644 --- a/tests/projects/pascal/static/src/main.pas +++ b/tests/projects/pascal/static/src/main.pas @@ -1,14 +1,12 @@ -uses strings; +program hello; -function SubStr(const CString: PChar; FromPos, ToPos: longint): PChar; +function fib(n: Int64): Int64; cdecl; external 'foo'; var - s: PChar; - FromPos, ToPos: Integer; + Value: Integer; begin - s := strnew('TestMe'); - FromPos := 2; - ToPos := 3; - WriteLn(SubStr(s, FromPos, ToPos)); + Value := 5; + WriteLn(fib(Value)); end. + diff --git a/xmake/templates/pascal/shared/project/src/foo.pas b/xmake/templates/pascal/shared/project/src/foo.pas new file mode 100644 index 000000000..788950f46 --- /dev/null +++ b/xmake/templates/pascal/shared/project/src/foo.pas @@ -0,0 +1,19 @@ +library foo; + +{$mode objfpc}{$H+} + +function fib(n : Int64) : Int64; cdecl; +begin + if n > 1 then + begin + Result := fib(n - 1) + fib(n - 2); + end + else + Result := 1; +end; + +exports + fib; +end. + + diff --git a/xmake/templates/pascal/shared/project/src/main.pas b/xmake/templates/pascal/shared/project/src/main.pas new file mode 100644 index 000000000..02d5e88d0 --- /dev/null +++ b/xmake/templates/pascal/shared/project/src/main.pas @@ -0,0 +1,13 @@ +program hello; + +function fib(n: Int64): Int64; + cdecl; external 'foo'; + +var + Value: Integer; +begin + Value := 5; + WriteLn(fib(Value)); +end. + + diff --git a/xmake/templates/pascal/shared/project/xmake.lua b/xmake/templates/pascal/shared/project/xmake.lua new file mode 100644 index 000000000..dd29cf486 --- /dev/null +++ b/xmake/templates/pascal/shared/project/xmake.lua @@ -0,0 +1,12 @@ +add_rules("mode.debug", "mode.release") +target("foo") + set_kind("shared") + add_files("src/foo.pas") + +target("${TARGETNAME}") + set_kind("binary") + add_deps("foo") + add_files("src/main.pas") + + +${FAQ} diff --git a/xmake/templates/pascal/shared/template.lua b/xmake/templates/pascal/shared/template.lua new file mode 100644 index 000000000..d7ec5bae4 --- /dev/null +++ b/xmake/templates/pascal/shared/template.lua @@ -0,0 +1,2 @@ +template("shared") + add_configfiles("xmake.lua") diff --git a/xmake/toolchains/fpc/xmake.lua b/xmake/toolchains/fpc/xmake.lua index 82c7f6dc8..0d9cba292 100644 --- a/xmake/toolchains/fpc/xmake.lua +++ b/xmake/toolchains/fpc/xmake.lua @@ -35,4 +35,7 @@ toolchain("fpc") on_load(function (toolchain) toolchain:set("pcshflags", "-Sd") toolchain:set("pcldflags", "-Sd") + if toolchain:is_plat("linux") then + toolchain:add("pcldflags", "-k-lc") + end end) -- cgit v1.3.1 From e13271050f95518e9451a334cad4b99dd0ac0e5c Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 4 Sep 2021 00:58:57 +0800 Subject: add more pascal tests --- tests/projects/pascal/console_with_c/src/foo.c | 7 +++++++ tests/projects/pascal/console_with_c/src/main.pas | 12 ++++++++++++ tests/projects/pascal/console_with_c/xmake.lua | 9 +++++++++ 3 files changed, 28 insertions(+) create mode 100644 tests/projects/pascal/console_with_c/src/foo.c create mode 100644 tests/projects/pascal/console_with_c/src/main.pas create mode 100644 tests/projects/pascal/console_with_c/xmake.lua diff --git a/tests/projects/pascal/console_with_c/src/foo.c b/tests/projects/pascal/console_with_c/src/foo.c new file mode 100644 index 000000000..66ca7cfb4 --- /dev/null +++ b/tests/projects/pascal/console_with_c/src/foo.c @@ -0,0 +1,7 @@ +#include + +extern int64_t fib(int64_t n) +{ + return n > 1 ? fib(n - 1) + fib(n - 2) : 1; +} + diff --git a/tests/projects/pascal/console_with_c/src/main.pas b/tests/projects/pascal/console_with_c/src/main.pas new file mode 100644 index 000000000..ce34e4af9 --- /dev/null +++ b/tests/projects/pascal/console_with_c/src/main.pas @@ -0,0 +1,12 @@ +program hello; + +function fib(n: Int64): Int64; + cdecl; external 'foo'; + +var + Value: Integer; +begin + Value := 5; + WriteLn(fib(Value)); +end. + diff --git a/tests/projects/pascal/console_with_c/xmake.lua b/tests/projects/pascal/console_with_c/xmake.lua new file mode 100644 index 000000000..111efc0c9 --- /dev/null +++ b/tests/projects/pascal/console_with_c/xmake.lua @@ -0,0 +1,9 @@ +add_rules("mode.debug", "mode.release") +target("foo") + set_kind("static") + add_files("src/foo.c") + +target("test") + set_kind("binary") + add_deps("foo") + add_files("src/main.pas") -- cgit v1.3.1 From b89f852330498a8968c54140d25345841c59136a Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 4 Sep 2021 11:11:34 +0800 Subject: merge_staticlib stub --- xmake/modules/utils/archive/merge_staticlib.lua | 56 +++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 xmake/modules/utils/archive/merge_staticlib.lua diff --git a/xmake/modules/utils/archive/merge_staticlib.lua b/xmake/modules/utils/archive/merge_staticlib.lua new file mode 100644 index 000000000..db72a8d97 --- /dev/null +++ b/xmake/modules/utils/archive/merge_staticlib.lua @@ -0,0 +1,56 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file merge_staticlib.lua +-- + +-- imports +import("core.base.option") + +-- merge *.a archive libraries for ar +function _merge_for_ar(program, outputfile, libraryfiles, opt) + opt = opt or {} +end + +-- merge *.a archive libraries for msvc/lib.exe +function _merge_for_msvclib(program, outputfile, libraryfiles, opt) + opt = opt or {} +end + +-- merge *.a archive libraries +function main(target, outputfile, libraryfiles) + local program, toolname = target:tool("ar") + if program and toolname then + if toolname:find("ar") then + _merge_for_ar(program, outputfile, libraryfiles) + elseif toolname == "link" and target:is_plat("windows") then + local msvc + for _, toolchain_inst in ipairs(target:toolchains()) do + if toolchain_inst:name() == "msvc" then + msvc = toolchain_inst + break + end + end + _merge_for_msvclib((program:gsub("link%.exe", "lib.exe")), outputfile, libraryfiles, {envs = msvc and msvc:runenvs()}) + else + raise("cannot merge (%s): unknown ar tool %s!", table.concat(libraryfiles, ", "), toolname) + end + else + raise("cannot merge (%s): ar not found!", table.concat(libraryfiles, ", ")) + end +end + -- cgit v1.3.1 From a985aac6e0cee156ee63171550e2eaa8040772e8 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 4 Sep 2021 21:14:02 +0800 Subject: improve cmake generator --- xmake/plugins/project/cmake/cmakelists.lua | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 6259effed..02abd56d7 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -221,22 +221,14 @@ function _add_target_compile_options(cmakelists, target) if #cflags > 0 or #cxflags > 0 or #cxxflags > 0 or #cuflags > 0 then cmakelists:print("target_compile_options(%s PRIVATE", target:name()) for _, flag in ipairs(cflags) do - if compiler.has_flags("c", flag, {target = target}) then - cmakelists:print(" $<$:" .. flag .. ">") - end + cmakelists:print(" $<$:" .. flag .. ">") end for _, flag in ipairs(cxflags) do - if compiler.has_flags("c", flag, {target = target}) then - cmakelists:print(" $<$:" .. flag .. ">") - end - if compiler.has_flags("cxx", flag, {target = target}) then - cmakelists:print(" $<$:" .. flag .. ">") - end + cmakelists:print(" $<$:" .. flag .. ">") + cmakelists:print(" $<$:" .. flag .. ">") end for _, flag in ipairs(cxxflags) do - if compiler.has_flags("cxx", flag, {target = target}) then - cmakelists:print(" $<$:" .. flag .. ">") - end + cmakelists:print(" $<$:" .. flag .. ">") end for _, flag in ipairs(cuflags) do cmakelists:print(" $<$:" .. flag .. ">") -- cgit v1.3.1 From 21c6d218d8a8f30824e1c2dc5bb783b210143e02 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 4 Sep 2021 21:16:23 +0800 Subject: improve pascal --- xmake/toolchains/fpc/xmake.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/toolchains/fpc/xmake.lua b/xmake/toolchains/fpc/xmake.lua index 0d9cba292..d84a383cc 100644 --- a/xmake/toolchains/fpc/xmake.lua +++ b/xmake/toolchains/fpc/xmake.lua @@ -33,8 +33,8 @@ toolchain("fpc") -- on load on_load(function (toolchain) - toolchain:set("pcshflags", "-Sd") - toolchain:set("pcldflags", "-Sd") + toolchain:set("pcshflags", "") + toolchain:set("pcldflags", "") if toolchain:is_plat("linux") then toolchain:add("pcldflags", "-k-lc") end -- cgit v1.3.1 From d65446740b572217af9a96dd908ba8397752a65a Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 4 Sep 2021 21:23:01 +0800 Subject: add fpic to pascal --- xmake/modules/core/tools/fpc.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xmake/modules/core/tools/fpc.lua b/xmake/modules/core/tools/fpc.lua index 378c4175a..c22386fbb 100644 --- a/xmake/modules/core/tools/fpc.lua +++ b/xmake/modules/core/tools/fpc.lua @@ -26,6 +26,9 @@ import("core.project.project") -- init it function init(self) self:set("pcarflags", "-Xt") + if not is_plat("windows", "mingw") then + self:add("shared.pcflags", "-Cg") + end end -- make the optimize flag -- cgit v1.3.1 From 51860aa00956dd52121339229a5b71b4fc428a72 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 4 Sep 2021 21:24:09 +0800 Subject: add ppu and lpr exts --- xmake/languages/pascal/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/languages/pascal/xmake.lua b/xmake/languages/pascal/xmake.lua index a3e1fb5b3..68d6b5daf 100644 --- a/xmake/languages/pascal/xmake.lua +++ b/xmake/languages/pascal/xmake.lua @@ -20,7 +20,7 @@ language("pascal") add_rules("pascal") - set_sourcekinds {pc = {".pas", ".pp"}} + set_sourcekinds {pc = {".pas", ".pp", ".ppu", ".lpr"}} set_sourceflags {pc = "pcflags"} set_targetkinds {binary = "pcld", static = "pcar", shared = "pcsh"} set_targetflags {binary = "ldflags", static = "arflags", shared = "shflags"} -- cgit v1.3.1 From 718c75717bab367194ee3220cdef3d64f17962d8 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 4 Sep 2021 22:15:23 +0800 Subject: remove static library for pascal --- tests/projects/pascal/static/src/foo.pas | 18 ------------------ tests/projects/pascal/static/src/main.pas | 12 ------------ tests/projects/pascal/static/xmake.lua | 9 --------- xmake/languages/pascal/xmake.lua | 4 ++-- xmake/modules/core/tools/fpc.lua | 1 - xmake/toolchains/fpc/xmake.lua | 5 +---- 6 files changed, 3 insertions(+), 46 deletions(-) delete mode 100644 tests/projects/pascal/static/src/foo.pas delete mode 100644 tests/projects/pascal/static/src/main.pas delete mode 100644 tests/projects/pascal/static/xmake.lua diff --git a/tests/projects/pascal/static/src/foo.pas b/tests/projects/pascal/static/src/foo.pas deleted file mode 100644 index 1fb4d7d6e..000000000 --- a/tests/projects/pascal/static/src/foo.pas +++ /dev/null @@ -1,18 +0,0 @@ -library foo; - -{$mode objfpc}{$H+} - -function fib(n : Int64) : Int64; cdecl; -begin - if n > 1 then - begin - Result := fib(n - 1) + fib(n - 2); - end - else - Result := 1; -end; - -exports - fib; -end. - diff --git a/tests/projects/pascal/static/src/main.pas b/tests/projects/pascal/static/src/main.pas deleted file mode 100644 index ce34e4af9..000000000 --- a/tests/projects/pascal/static/src/main.pas +++ /dev/null @@ -1,12 +0,0 @@ -program hello; - -function fib(n: Int64): Int64; - cdecl; external 'foo'; - -var - Value: Integer; -begin - Value := 5; - WriteLn(fib(Value)); -end. - diff --git a/tests/projects/pascal/static/xmake.lua b/tests/projects/pascal/static/xmake.lua deleted file mode 100644 index 759cf69ad..000000000 --- a/tests/projects/pascal/static/xmake.lua +++ /dev/null @@ -1,9 +0,0 @@ -add_rules("mode.debug", "mode.release") -target("foo") - set_kind("static") - add_files("src/foo.pas") - -target("test") - set_kind("binary") - add_deps("foo") - add_files("src/main.pas") diff --git a/xmake/languages/pascal/xmake.lua b/xmake/languages/pascal/xmake.lua index 68d6b5daf..298b9752f 100644 --- a/xmake/languages/pascal/xmake.lua +++ b/xmake/languages/pascal/xmake.lua @@ -22,8 +22,8 @@ language("pascal") add_rules("pascal") set_sourcekinds {pc = {".pas", ".pp", ".ppu", ".lpr"}} set_sourceflags {pc = "pcflags"} - set_targetkinds {binary = "pcld", static = "pcar", shared = "pcsh"} - set_targetflags {binary = "ldflags", static = "arflags", shared = "shflags"} + set_targetkinds {binary = "pcld", shared = "pcsh"} + set_targetflags {binary = "ldflags", shared = "shflags"} set_langkinds {pascal = "pc"} set_mixingkinds("pc") diff --git a/xmake/modules/core/tools/fpc.lua b/xmake/modules/core/tools/fpc.lua index c22386fbb..98b746c8a 100644 --- a/xmake/modules/core/tools/fpc.lua +++ b/xmake/modules/core/tools/fpc.lua @@ -25,7 +25,6 @@ import("core.project.project") -- init it function init(self) - self:set("pcarflags", "-Xt") if not is_plat("windows", "mingw") then self:add("shared.pcflags", "-Cg") end diff --git a/xmake/toolchains/fpc/xmake.lua b/xmake/toolchains/fpc/xmake.lua index d84a383cc..cb2855625 100644 --- a/xmake/toolchains/fpc/xmake.lua +++ b/xmake/toolchains/fpc/xmake.lua @@ -29,13 +29,10 @@ toolchain("fpc") set_toolset("pc", "$(env PC)", "fpc") set_toolset("pcld", "$(env PC)", "fpc") set_toolset("pcsh", "$(env PC)", "fpc") - set_toolset("pcar", "$(env PC)", "fpc") -- on load on_load(function (toolchain) toolchain:set("pcshflags", "") toolchain:set("pcldflags", "") - if toolchain:is_plat("linux") then - toolchain:add("pcldflags", "-k-lc") - end + toolchain:add("syslinks", "c") end) -- cgit v1.3.1 From b5b490676355766b03ca366fe3900495cbf4a9fa Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 4 Sep 2021 23:13:28 +0800 Subject: add new merge archive rules --- tests/projects/other/merge_archive2/src/add.c | 4 +++ tests/projects/other/merge_archive2/src/mul.c | 4 +++ tests/projects/other/merge_archive2/src/sub.c | 4 +++ .../projects/other/merge_archive2/src/subdir/add.c | 4 +++ .../projects/other/merge_archive2/src/subdir/sub.c | 4 +++ tests/projects/other/merge_archive2/test.lua | 6 +++++ tests/projects/other/merge_archive2/xmake.lua | 18 ++++++++++++++ xmake/core/project/policy.lua | 2 ++ xmake/modules/utils/archive/merge_staticlib.lua | 13 +++++++--- xmake/rules/utils/merge_archive/xmake.lua | 29 ++++++++++++++++++---- 10 files changed, 79 insertions(+), 9 deletions(-) create mode 100644 tests/projects/other/merge_archive2/src/add.c create mode 100644 tests/projects/other/merge_archive2/src/mul.c create mode 100644 tests/projects/other/merge_archive2/src/sub.c create mode 100644 tests/projects/other/merge_archive2/src/subdir/add.c create mode 100644 tests/projects/other/merge_archive2/src/subdir/sub.c create mode 100644 tests/projects/other/merge_archive2/test.lua create mode 100644 tests/projects/other/merge_archive2/xmake.lua diff --git a/tests/projects/other/merge_archive2/src/add.c b/tests/projects/other/merge_archive2/src/add.c new file mode 100644 index 000000000..be1e084fc --- /dev/null +++ b/tests/projects/other/merge_archive2/src/add.c @@ -0,0 +1,4 @@ +int add(int a, int b) +{ + return a + b; +} diff --git a/tests/projects/other/merge_archive2/src/mul.c b/tests/projects/other/merge_archive2/src/mul.c new file mode 100644 index 000000000..c4292f9aa --- /dev/null +++ b/tests/projects/other/merge_archive2/src/mul.c @@ -0,0 +1,4 @@ +int mul(int a, int b) +{ + return a * b; +} diff --git a/tests/projects/other/merge_archive2/src/sub.c b/tests/projects/other/merge_archive2/src/sub.c new file mode 100644 index 000000000..b151ec4bc --- /dev/null +++ b/tests/projects/other/merge_archive2/src/sub.c @@ -0,0 +1,4 @@ +int sub(int a, int b) +{ + return a - b; +} diff --git a/tests/projects/other/merge_archive2/src/subdir/add.c b/tests/projects/other/merge_archive2/src/subdir/add.c new file mode 100644 index 000000000..318ed98f8 --- /dev/null +++ b/tests/projects/other/merge_archive2/src/subdir/add.c @@ -0,0 +1,4 @@ +int subdir_add(int a, int b) +{ + return a + b; +} diff --git a/tests/projects/other/merge_archive2/src/subdir/sub.c b/tests/projects/other/merge_archive2/src/subdir/sub.c new file mode 100644 index 000000000..68c4d13ae --- /dev/null +++ b/tests/projects/other/merge_archive2/src/subdir/sub.c @@ -0,0 +1,4 @@ +int subdir_sub(int a, int b) +{ + return a - b; +} diff --git a/tests/projects/other/merge_archive2/test.lua b/tests/projects/other/merge_archive2/test.lua new file mode 100644 index 000000000..b76241be2 --- /dev/null +++ b/tests/projects/other/merge_archive2/test.lua @@ -0,0 +1,6 @@ +-- main entry +function main(t) + + -- build project + t:build() +end diff --git a/tests/projects/other/merge_archive2/xmake.lua b/tests/projects/other/merge_archive2/xmake.lua new file mode 100644 index 000000000..eb23dd859 --- /dev/null +++ b/tests/projects/other/merge_archive2/xmake.lua @@ -0,0 +1,18 @@ +add_rules("mode.debug", "mode.release") + +target("add") + set_kind("static") + add_files("src/add.c") + add_files("src/subdir/add.c") + +target("sub") + set_kind("static") + add_files("src/sub.c") + add_files("src/subdir/sub.c") + +target("mul") + set_kind("static") + add_deps("add", "sub") + add_files("src/mul.c") + set_policy("build.merge_archive", true) + diff --git a/xmake/core/project/policy.lua b/xmake/core/project/policy.lua index c624aed96..418d4d566 100644 --- a/xmake/core/project/policy.lua +++ b/xmake/core/project/policy.lua @@ -43,6 +43,8 @@ function policy.policies() ["check.target_package_licenses"] = {description = "Enable check the compatibility of target and package licenses.", default = true, type = "boolean"}, -- we can compile the source files for each target in parallel ["build.across_targets_in_parallel"] = {description = "Enable compile the source files for each target in parallel.", default = true, type = "boolean"}, + -- merge archive intead of linking for all dependent targets + ["build.merge_archive"] = {description = "Enable merge archive intead of linking for all dependent targets.", default = false, type = "boolean"}, -- we need enable longpaths when building target or installing package ["platform.longpaths"] = {description = "Enable long paths when building target or installing package on windows.", default = false, type = "boolean"}, -- lock required packages diff --git a/xmake/modules/utils/archive/merge_staticlib.lua b/xmake/modules/utils/archive/merge_staticlib.lua index db72a8d97..8675f6c52 100644 --- a/xmake/modules/utils/archive/merge_staticlib.lua +++ b/xmake/modules/utils/archive/merge_staticlib.lua @@ -22,12 +22,17 @@ import("core.base.option") -- merge *.a archive libraries for ar -function _merge_for_ar(program, outputfile, libraryfiles, opt) +function _merge_for_ar(target, program, outputfile, libraryfiles, opt) opt = opt or {} + if target:is_plat("macosx") then + os.vrunv("libtool", table.join("-static", "-o", outputfile, libraryfiles)) + else + os.vrunv(program, table.join("crsT", outputfile, libraryfiles)) + end end -- merge *.a archive libraries for msvc/lib.exe -function _merge_for_msvclib(program, outputfile, libraryfiles, opt) +function _merge_for_msvclib(target, program, outputfile, libraryfiles, opt) opt = opt or {} end @@ -36,7 +41,7 @@ function main(target, outputfile, libraryfiles) local program, toolname = target:tool("ar") if program and toolname then if toolname:find("ar") then - _merge_for_ar(program, outputfile, libraryfiles) + _merge_for_ar(target, program, outputfile, libraryfiles) elseif toolname == "link" and target:is_plat("windows") then local msvc for _, toolchain_inst in ipairs(target:toolchains()) do @@ -45,7 +50,7 @@ function main(target, outputfile, libraryfiles) break end end - _merge_for_msvclib((program:gsub("link%.exe", "lib.exe")), outputfile, libraryfiles, {envs = msvc and msvc:runenvs()}) + _merge_for_msvclib(target, (program:gsub("link%.exe", "lib.exe")), outputfile, libraryfiles, {envs = msvc and msvc:runenvs()}) else raise("cannot merge (%s): unknown ar tool %s!", table.concat(libraryfiles, ", "), toolname) end diff --git a/xmake/rules/utils/merge_archive/xmake.lua b/xmake/rules/utils/merge_archive/xmake.lua index 6d57f55bb..63c947d08 100644 --- a/xmake/rules/utils/merge_archive/xmake.lua +++ b/xmake/rules/utils/merge_archive/xmake.lua @@ -18,12 +18,31 @@ -- @file xmake.lua -- --- define rule: utils.merge.archive rule("utils.merge.archive") - - -- set extensions set_extensions(".a", ".lib") - - -- on build file on_build_files("merge_archive") + after_link(function (target, opt) + if target:policy("build.merge_archive") and target:is_static() then + import("utils.archive.merge_staticlib") + import("core.project.depend") + import("private.utils.progress") + local libraryfiles = {} + for _, dep in ipairs(target:orderdeps()) do + if dep:is_static() then + table.insert(libraryfiles, dep:targetfile()) + end + end + if #libraryfiles > 0 then + table.insert(libraryfiles, target:targetfile()) + end + depend.on_changed(function () + progress.show(opt.progress, "${color.build.target}merging.$(mode) %s", path.filename(target:targetfile())) + if #libraryfiles > 0 then + local tmpfile = os.tmpfile() .. path.extension(target:targetfile()) + merge_staticlib(target, tmpfile, libraryfiles) + os.mv(tmpfile, target:targetfile()) + end + end, {dependfile = target:dependfile(target:targetfile() .. ".merge_archive"), files = libraryfiles}) + end + end) -- cgit v1.3.1 From feefe1dce66ea47e4a968887fbcb81cb0f9caf33 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 4 Sep 2021 23:16:14 +0800 Subject: improve mergelib --- xmake/modules/utils/archive/merge_staticlib.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/utils/archive/merge_staticlib.lua b/xmake/modules/utils/archive/merge_staticlib.lua index 8675f6c52..b5adbd98f 100644 --- a/xmake/modules/utils/archive/merge_staticlib.lua +++ b/xmake/modules/utils/archive/merge_staticlib.lua @@ -24,7 +24,7 @@ import("core.base.option") -- merge *.a archive libraries for ar function _merge_for_ar(target, program, outputfile, libraryfiles, opt) opt = opt or {} - if target:is_plat("macosx") then + if target:is_plat("macosx", "iphoneos", "watchos", "appletvos") then os.vrunv("libtool", table.join("-static", "-o", outputfile, libraryfiles)) else os.vrunv(program, table.join("crsT", outputfile, libraryfiles)) -- cgit v1.3.1 From b54c309384c334c265072e15a23692e52f11b0b7 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 4 Sep 2021 23:43:32 +0800 Subject: improve merge lib for ar --- tests/projects/other/merge_archive2/src/main.c | 17 +++++++++++++++++ tests/projects/other/merge_archive2/xmake.lua | 3 +++ xmake/modules/utils/archive/merge_staticlib.lua | 12 +++++++++++- xmake/rules/utils/merge_archive/xmake.lua | 3 ++- 4 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 tests/projects/other/merge_archive2/src/main.c diff --git a/tests/projects/other/merge_archive2/src/main.c b/tests/projects/other/merge_archive2/src/main.c new file mode 100644 index 000000000..927c9173e --- /dev/null +++ b/tests/projects/other/merge_archive2/src/main.c @@ -0,0 +1,17 @@ +#include + +int add(int a, int b); +int sub(int a, int b); +int mul(int a, int b); +int subdir_add(int a, int b); +int subdir_sub(int a, int b); + +int main(int argc, char** argv) +{ + printf("%d\n", add(1, 1)); + printf("%d\n", sub(1, 1)); + printf("%d\n", mul(1, 1)); + printf("%d\n", subdir_add(1, 1)); + printf("%d\n", subdir_sub(1, 1)); + return 0; +} diff --git a/tests/projects/other/merge_archive2/xmake.lua b/tests/projects/other/merge_archive2/xmake.lua index eb23dd859..be1f45de0 100644 --- a/tests/projects/other/merge_archive2/xmake.lua +++ b/tests/projects/other/merge_archive2/xmake.lua @@ -16,3 +16,6 @@ target("mul") add_files("src/mul.c") set_policy("build.merge_archive", true) +target("test") + add_deps("mul") + add_files("src/main.c") diff --git a/xmake/modules/utils/archive/merge_staticlib.lua b/xmake/modules/utils/archive/merge_staticlib.lua index b5adbd98f..cbafa4bdb 100644 --- a/xmake/modules/utils/archive/merge_staticlib.lua +++ b/xmake/modules/utils/archive/merge_staticlib.lua @@ -27,7 +27,17 @@ function _merge_for_ar(target, program, outputfile, libraryfiles, opt) if target:is_plat("macosx", "iphoneos", "watchos", "appletvos") then os.vrunv("libtool", table.join("-static", "-o", outputfile, libraryfiles)) else - os.vrunv(program, table.join("crsT", outputfile, libraryfiles)) + local tmpfile = os.tmpfile() + local mrifile = io.open(tmpfile, "w") + mrifile:print("create %s", outputfile) + for _, libraryfile in ipairs(libraryfiles) do + mrifile:print("addlib %s", libraryfile) + end + mrifile:print("save") + mrifile:print("end") + mrifile:close() + os.vrunv(program, {"-M"}, {stdin = tmpfile}) + os.rm(tmpfile) end end diff --git a/xmake/rules/utils/merge_archive/xmake.lua b/xmake/rules/utils/merge_archive/xmake.lua index 63c947d08..62e3900ff 100644 --- a/xmake/rules/utils/merge_archive/xmake.lua +++ b/xmake/rules/utils/merge_archive/xmake.lua @@ -40,7 +40,8 @@ rule("utils.merge.archive") if #libraryfiles > 0 then local tmpfile = os.tmpfile() .. path.extension(target:targetfile()) merge_staticlib(target, tmpfile, libraryfiles) - os.mv(tmpfile, target:targetfile()) + os.cp(tmpfile, target:targetfile()) + os.rm(tmpfile) end end, {dependfile = target:dependfile(target:targetfile() .. ".merge_archive"), files = libraryfiles}) end -- cgit v1.3.1 From 1e4cd9f26fdae27e8253f5b214260830d719953b Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 4 Sep 2021 23:46:20 +0800 Subject: mergelib for lib.exe --- xmake/modules/utils/archive/merge_staticlib.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xmake/modules/utils/archive/merge_staticlib.lua b/xmake/modules/utils/archive/merge_staticlib.lua index cbafa4bdb..dc0130219 100644 --- a/xmake/modules/utils/archive/merge_staticlib.lua +++ b/xmake/modules/utils/archive/merge_staticlib.lua @@ -20,6 +20,7 @@ -- imports import("core.base.option") +import("private.tools.vstool") -- merge *.a archive libraries for ar function _merge_for_ar(target, program, outputfile, libraryfiles, opt) @@ -44,6 +45,7 @@ end -- merge *.a archive libraries for msvc/lib.exe function _merge_for_msvclib(target, program, outputfile, libraryfiles, opt) opt = opt or {} + vstool.runv(program, table.join("-nologo", "-out:" .. outputfile, libraryfiles), {envs = opt.runenvs}) end -- merge *.a archive libraries @@ -60,7 +62,7 @@ function main(target, outputfile, libraryfiles) break end end - _merge_for_msvclib(target, (program:gsub("link%.exe", "lib.exe")), outputfile, libraryfiles, {envs = msvc and msvc:runenvs()}) + _merge_for_msvclib(target, (program:gsub("link%.exe", "lib.exe")), outputfile, libraryfiles, {runenvs = msvc and msvc:runenvs()}) else raise("cannot merge (%s): unknown ar tool %s!", table.concat(libraryfiles, ", "), toolname) end -- cgit v1.3.1 From 06b0a3c599b1cfb681dbbd89b4784190aadd2f8a Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 5 Sep 2021 00:21:14 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ xmake/core/project/policy.lua | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4524d2b69..d83e6378c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * [#1618](https://github.com/xmake-io/xmake/issues/1618): Improve vala to support to generate libraries and bindings * Improve Qt rules to support Qt 4.x * Improve `set_symbols("debug")` to generate pdb file for clang on windows +* [#1638](https://github.com/xmake-io/xmake/issues/1638): Improve to merge static library ## v2.5.7 @@ -1079,6 +1080,7 @@ * [#1618](https://github.com/xmake-io/xmake/issues/1618): 改进 vala 支持构建动态库和静态库程序 * 改进 Qt 规则去支持 Qt 4.x * 改进 `set_symbols("debug")` 支持 clang/windows 生成 pdb 文件 +* [#1638](https://github.com/xmake-io/xmake/issues/1638): 改进合并静态库 ## v2.5.7 diff --git a/xmake/core/project/policy.lua b/xmake/core/project/policy.lua index 418d4d566..8491e6883 100644 --- a/xmake/core/project/policy.lua +++ b/xmake/core/project/policy.lua @@ -44,7 +44,7 @@ function policy.policies() -- we can compile the source files for each target in parallel ["build.across_targets_in_parallel"] = {description = "Enable compile the source files for each target in parallel.", default = true, type = "boolean"}, -- merge archive intead of linking for all dependent targets - ["build.merge_archive"] = {description = "Enable merge archive intead of linking for all dependent targets.", default = false, type = "boolean"}, + ["build.merge_archive"] = {description = "Enable merge archive intead of linking for all dependent targets.", default = false, type = "boolean"}, -- we need enable longpaths when building target or installing package ["platform.longpaths"] = {description = "Enable long paths when building target or installing package on windows.", default = false, type = "boolean"}, -- lock required packages -- cgit v1.3.1 From f1494df1cf0a7cbeb6c5f63d13f8e4699804fe9f Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 5 Sep 2021 00:25:36 +0800 Subject: improve pkgconfig importfiles --- xmake/rules/utils/install_importfiles/xmake.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xmake/rules/utils/install_importfiles/xmake.lua b/xmake/rules/utils/install_importfiles/xmake.lua index 45e6616f8..848f215e1 100644 --- a/xmake/rules/utils/install_importfiles/xmake.lua +++ b/xmake/rules/utils/install_importfiles/xmake.lua @@ -21,7 +21,9 @@ -- install pkg-config/*.pc import files rule("utils.install.pkgconfig_importfiles") after_install(function (target, opt) - import("target.action.install.pkgconfig_importfiles")(target, opt) + opt = opt or {} + local filename = target:extraconf("rules", "utils.install.pkgconfig_importfiles", "filename") + import("target.action.install.pkgconfig_importfiles")(target, table.join(opt, {filename = filename})) end) -- install *.cmake import files -- cgit v1.3.1 From 10086b9a5a6b1965b187a19f5184c9642acb2ccf Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 7 Sep 2021 00:35:36 +0800 Subject: update tbox --- core/src/tbox/tbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/tbox/tbox b/core/src/tbox/tbox index 5ef932750..de6752cb8 160000 --- a/core/src/tbox/tbox +++ b/core/src/tbox/tbox @@ -1 +1 @@ -Subproject commit 5ef932750ede0b90867fd4afdcf1deed2464c82b +Subproject commit de6752cb88b542aeda393eca00e4fec439763998 -- cgit v1.3.1 From a628a251b21e47f2e8f99b461d1611d143f62f65 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 7 Sep 2021 00:50:36 +0800 Subject: fix tests --- xmake/toolchains/fpc/xmake.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/xmake/toolchains/fpc/xmake.lua b/xmake/toolchains/fpc/xmake.lua index cb2855625..13231db7b 100644 --- a/xmake/toolchains/fpc/xmake.lua +++ b/xmake/toolchains/fpc/xmake.lua @@ -32,7 +32,11 @@ toolchain("fpc") -- on load on_load(function (toolchain) - toolchain:set("pcshflags", "") - toolchain:set("pcldflags", "") - toolchain:add("syslinks", "c") + if toolchain:is_plat("linux") then + toolchain:set("pcldflags", "-k-lc") + toolchain:set("pcshflags", "-k-lc") + else + toolchain:set("pcldflags", "") + toolchain:set("pcshflags", "") + end end) -- cgit v1.3.1 From 02411882d17b8a71ba900cd803dfc3b5ec612da7 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 7 Sep 2021 00:54:27 +0800 Subject: add os.default_njob --- xmake/core/base/os.lua | 15 +++++++++++++++ xmake/core/sandbox/modules/os.lua | 1 + 2 files changed, 16 insertions(+) diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index ea913b977..312d5705d 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -1237,6 +1237,21 @@ function os.cpuinfo(name) return require("base/cpu").info(name) end +-- get the default parallel jobs number +function os.default_njob() + local njob = math.ceil(os.cpuinfo().ncpu * 3 / 2) + if os.host() == "windows" and njob > 128 then + njob = 128 + end + if njob > 512 then + njob = 512 + end + if njob < 1 then + njob = 1 + end + return njob +end + -- read the content of symlink function os.readlink(symlink) return os._readlink(path.absolute(symlink)) diff --git a/xmake/core/sandbox/modules/os.lua b/xmake/core/sandbox/modules/os.lua index beb60ddab..9f6fcd8d8 100644 --- a/xmake/core/sandbox/modules/os.lua +++ b/xmake/core/sandbox/modules/os.lua @@ -65,6 +65,7 @@ sandbox_os.joinenvs = os.joinenvs sandbox_os.pbpaste = os.pbpaste sandbox_os.pbcopy = os.pbcopy sandbox_os.cpuinfo = os.cpuinfo +sandbox_os.default_njob = os.default_njob sandbox_os.emptydir = os.emptydir sandbox_os.filesize = os.filesize sandbox_os.features = os.features -- cgit v1.3.1 From 0a271b992bb97a3d2e6b00d9facf1eb26ef2f899 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 7 Sep 2021 00:55:33 +0800 Subject: improve njob --- xmake/actions/build/xmake.lua | 2 +- xmake/actions/require/xmake.lua | 2 +- .../modules/import/core/project/project.lua | 2 +- xmake/core/sandbox/modules/interpreter/os.lua | 43 +++++++++++----------- xmake/modules/package/tools/autoconf.lua | 2 +- xmake/modules/package/tools/cmake.lua | 2 +- xmake/modules/package/tools/make.lua | 2 +- xmake/modules/package/tools/ninja.lua | 4 +- xmake/modules/package/tools/scons.lua | 2 +- xmake/modules/private/xrepo/action/install.lua | 2 +- 10 files changed, 32 insertions(+), 31 deletions(-) diff --git a/xmake/actions/build/xmake.lua b/xmake/actions/build/xmake.lua index 3323ac5b1..631536f24 100644 --- a/xmake/actions/build/xmake.lua +++ b/xmake/actions/build/xmake.lua @@ -47,7 +47,7 @@ task("build") , {nil, "dry-run", "k", nil , "Dry run to build target." } , {} - , {'j', "jobs", "kv", tostring(math.ceil(os.cpuinfo().ncpu * 3 / 2)), + , {'j', "jobs", "kv", tostring(os.default_njob()), "Set the number of parallel compilation jobs." } , {nil, "linkjobs", "kv", nil, "Set the number of parallel link jobs." } , {'w', "warning", "k", false , "Enable the warnings output." } diff --git a/xmake/actions/require/xmake.lua b/xmake/actions/require/xmake.lua index f33188f77..3ffd17fe3 100644 --- a/xmake/actions/require/xmake.lua +++ b/xmake/actions/require/xmake.lua @@ -46,7 +46,7 @@ task("require") " $ xmake require --clean", " $ xmake require --clean zlib tbox pcr*" } , {'f', "force", "k", nil, "Force to reinstall all package dependencies." } - , {'j', "jobs", "kv", tostring(math.ceil(os.cpuinfo().ncpu * 3 / 2)), + , {'j', "jobs", "kv", tostring(os.default_njob()), "Set the number of parallel compilation jobs." } , {nil, "linkjobs", "kv", nil, "Set the number of parallel link jobs." } , {nil, "shallow", "k", nil, "Does not install dependent packages." } diff --git a/xmake/core/sandbox/modules/import/core/project/project.lua b/xmake/core/sandbox/modules/import/core/project/project.lua index 34b5fa7ac..2330dccd0 100644 --- a/xmake/core/sandbox/modules/import/core/project/project.lua +++ b/xmake/core/sandbox/modules/import/core/project/project.lua @@ -110,7 +110,7 @@ function sandbox_core_project.check() end -- check all options - local jobs = baseoption.get("jobs") or math.ceil(os.cpuinfo().ncpu * 3 / 2) + local jobs = baseoption.get("jobs") or os.default_njob() import("private.async.runjobs", {anonymous = true})("check_options", instance:fork(checktask):script(), {total = #options, comax = jobs}) -- save all options to the cache file diff --git a/xmake/core/sandbox/modules/interpreter/os.lua b/xmake/core/sandbox/modules/interpreter/os.lua index 10c4b710c..dff4a14d7 100644 --- a/xmake/core/sandbox/modules/interpreter/os.lua +++ b/xmake/core/sandbox/modules/interpreter/os.lua @@ -27,27 +27,28 @@ local interpreter = require("base/interpreter") local sandbox_os = sandbox_os or {} -- export some readonly interfaces -sandbox_os.term = os.term -sandbox_os.host = os.host -sandbox_os.arch = os.arch -sandbox_os.subhost = os.subhost -sandbox_os.subarch = os.subarch -sandbox_os.date = os.date -sandbox_os.time = os.time -sandbox_os.mtime = os.mtime -sandbox_os.mclock = os.mclock -sandbox_os.getenv = os.getenv -sandbox_os.isdir = os.isdir -sandbox_os.isfile = os.isfile -sandbox_os.exists = os.exists -sandbox_os.curdir = os.curdir -sandbox_os.tmpdir = os.tmpdir -sandbox_os.cpuinfo = os.cpuinfo -sandbox_os.filesize = os.filesize -sandbox_os.programdir = os.programdir -sandbox_os.programfile = os.programfile -sandbox_os.projectdir = os.projectdir -sandbox_os.projectfile = os.projectfile +sandbox_os.term = os.term +sandbox_os.host = os.host +sandbox_os.arch = os.arch +sandbox_os.subhost = os.subhost +sandbox_os.subarch = os.subarch +sandbox_os.date = os.date +sandbox_os.time = os.time +sandbox_os.mtime = os.mtime +sandbox_os.mclock = os.mclock +sandbox_os.getenv = os.getenv +sandbox_os.isdir = os.isdir +sandbox_os.isfile = os.isfile +sandbox_os.exists = os.exists +sandbox_os.curdir = os.curdir +sandbox_os.tmpdir = os.tmpdir +sandbox_os.cpuinfo = os.cpuinfo +sandbox_os.default_njob = os.default_njob +sandbox_os.filesize = os.filesize +sandbox_os.programdir = os.programdir +sandbox_os.programfile = os.programfile +sandbox_os.projectdir = os.projectdir +sandbox_os.projectfile = os.projectfile -- match files function sandbox_os.files(pattern, ...) diff --git a/xmake/modules/package/tools/autoconf.lua b/xmake/modules/package/tools/autoconf.lua index 209e6c68a..9e4f8c4b4 100644 --- a/xmake/modules/package/tools/autoconf.lua +++ b/xmake/modules/package/tools/autoconf.lua @@ -299,7 +299,7 @@ function install(package, configs, opt) -- do make and install opt = opt or {} - local njob = opt.jobs or option.get("jobs") or tostring(math.ceil(os.cpuinfo().ncpu * 3 / 2)) + local njob = opt.jobs or option.get("jobs") or tostring(os.default_njob()) local argv = {"-j" .. njob} if option.get("verbose") then table.insert(argv, "V=1") diff --git a/xmake/modules/package/tools/cmake.lua b/xmake/modules/package/tools/cmake.lua index 73af75b32..857f859be 100644 --- a/xmake/modules/package/tools/cmake.lua +++ b/xmake/modules/package/tools/cmake.lua @@ -30,7 +30,7 @@ import("package.tools.ninja") -- get the number of parallel jobs function _get_parallel_njobs(opt) - return opt.jobs or option.get("jobs") or tostring(math.ceil(os.cpuinfo().ncpu * 3 / 2)) + return opt.jobs or option.get("jobs") or tostring(os.default_njob()) end -- translate paths diff --git a/xmake/modules/package/tools/make.lua b/xmake/modules/package/tools/make.lua index ff6dce8ed..a40cd57c1 100644 --- a/xmake/modules/package/tools/make.lua +++ b/xmake/modules/package/tools/make.lua @@ -91,7 +91,7 @@ function build(package, configs, opt) opt = opt or {} -- pass configurations - local njob = opt.jobs or option.get("jobs") or tostring(math.ceil(os.cpuinfo().ncpu * 3 / 2)) + local njob = opt.jobs or option.get("jobs") or tostring(os.default_njob()) local argv = {"-j" .. njob} if option.get("verbose") then table.insert(argv, "VERBOSE=1") diff --git a/xmake/modules/package/tools/ninja.lua b/xmake/modules/package/tools/ninja.lua index e1feccc14..e16731670 100644 --- a/xmake/modules/package/tools/ninja.lua +++ b/xmake/modules/package/tools/ninja.lua @@ -26,7 +26,7 @@ import("lib.detect.find_tool") function build(package, configs, opt) opt = opt or {} local buildir = opt.buildir or os.curdir() - local njob = opt.jobs or option.get("jobs") or tostring(math.ceil(os.cpuinfo().ncpu * 3 / 2)) + local njob = opt.jobs or option.get("jobs") or tostring(os.default_njob()) local ninja = assert(find_tool("ninja"), "ninja not found!") local argv = {"-C", buildir} if option.get("verbose") then @@ -44,7 +44,7 @@ end function install(package, configs, opt) opt = opt or {} local buildir = opt.buildir or os.curdir() - local njob = tostring(math.ceil(os.cpuinfo().ncpu * 3 / 2)) + local njob = tostring(os.default_njob()) local ninja = assert(find_tool("ninja"), "ninja not found!") local argv = {"install", "-C", buildir} if option.get("verbose") then diff --git a/xmake/modules/package/tools/scons.lua b/xmake/modules/package/tools/scons.lua index 386645bba..0c197933f 100644 --- a/xmake/modules/package/tools/scons.lua +++ b/xmake/modules/package/tools/scons.lua @@ -86,7 +86,7 @@ end function build(package, configs, opt) opt = opt or {} local buildir = opt.buildir or os.curdir() - local njob = opt.jobs or option.get("jobs") or tostring(math.ceil(os.cpuinfo().ncpu * 3 / 2)) + local njob = opt.jobs or option.get("jobs") or tostring(os.default_njob()) local scons = assert(find_tool("scons"), "scons not found!") local argv = {"-C", buildir, "-j", njob} configs = _get_configs(package, configs) diff --git a/xmake/modules/private/xrepo/action/install.lua b/xmake/modules/private/xrepo/action/install.lua index ccd14c839..f6f111185 100644 --- a/xmake/modules/private/xrepo/action/install.lua +++ b/xmake/modules/private/xrepo/action/install.lua @@ -40,7 +40,7 @@ function menu_options() "e.g.", " - xrepo install -f \"vs_runtime=MD\" zlib", " - xrepo install -f \"regex=true,thread=true\" boost"}, - {'j', "jobs", "kv", tostring(math.ceil(os.cpuinfo().ncpu * 3 / 2)), + {'j', "jobs", "kv", tostring(os.default_njob()), "Set the number of parallel compilation jobs."}, {nil, "linkjobs", "kv", nil, "Set the number of parallel link jobs."}, {nil, "includes", "kv", nil, "Includes extra lua configuration files.", -- cgit v1.3.1 From 627b5c112188b76ce6e3ea625015934024d9e68d Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Tue, 7 Sep 2021 11:17:52 +0800 Subject: improve xrepo as function --- scripts/register-virtualenvs.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/register-virtualenvs.sh b/scripts/register-virtualenvs.sh index 700d8dd99..aa97afec5 100644 --- a/scripts/register-virtualenvs.sh +++ b/scripts/register-virtualenvs.sh @@ -39,10 +39,10 @@ function xrepo { fi ;; *) - "$XMAKE_EXE" lua private.xrepo $@ + "$XMAKE_EXE" lua private.xrepo "$@" ;; esac else - "$XMAKE_EXE" lua private.xrepo $@ + "$XMAKE_EXE" lua private.xrepo "$@" fi } -- cgit v1.3.1 From f11cd6e0ad4dbfa94c6726507e9132d09d86cec9 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 7 Sep 2021 22:37:18 +0800 Subject: update tbox --- core/src/tbox/tbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/tbox/tbox b/core/src/tbox/tbox index de6752cb8..cde8c8ad9 160000 --- a/core/src/tbox/tbox +++ b/core/src/tbox/tbox @@ -1 +1 @@ -Subproject commit de6752cb88b542aeda393eca00e4fec439763998 +Subproject commit cde8c8ad90aac79d277a1891967be3c1a58e0858 -- cgit v1.3.1 From b372be1bad6d2c4b08d4829e180672518034b50f Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 7 Sep 2021 22:37:39 +0800 Subject: update readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 425860f22..009758828 100644 --- a/README.md +++ b/README.md @@ -7,13 +7,13 @@
- github-ci + github-ci - github-ci + github-ci - github-ci + github-ci Github All Releases -- cgit v1.3.1 From 559bbf4128b079988dfa75d7900696949ec27c4a Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Mon, 6 Sep 2021 13:28:44 +0200 Subject: Fix cmake debug flags override Don't use -DCMAKE_C_FLAGS_DEBUG and -DCMAKE_CXX_FLAGS_DEBUG as this will prevent debug flags generation on Windows (suchs as `/MDd /Zi /Ob0 /Od /RTC1`), use CMAKE_C_FLAGS instead --- xmake/modules/package/tools/cmake.lua | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/xmake/modules/package/tools/cmake.lua b/xmake/modules/package/tools/cmake.lua index 857f859be..57318328f 100644 --- a/xmake/modules/package/tools/cmake.lua +++ b/xmake/modules/package/tools/cmake.lua @@ -133,6 +133,10 @@ function _get_cflags(package, opt) table.join2(result, opt.cxflags) end table.join2(result, _get_cflags_from_packagedeps(package, opt)) + local vs_runtime = package:config("vs_runtime") + if vs_runtime then + table.insert(result, "/" .. vs_runtime) + end if #result > 0 then return os.args(result) end @@ -158,6 +162,10 @@ function _get_cxxflags(package, opt) table.join2(result, opt.cxflags) end table.join2(result, _get_cflags_from_packagedeps(package, opt)) + local vs_runtime = package:config("vs_runtime") + if vs_runtime then + table.insert(result, "/" .. vs_runtime) + end if #result > 0 then return os.args(result) end @@ -271,12 +279,6 @@ function _get_configs_for_windows(package, configs, opt) elseif vs_runtime == "MDd" then table.insert(configs, "-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDebugDLL") end - if vs_runtime then - table.insert(configs, '-DCMAKE_CXX_FLAGS_DEBUG="/' .. vs_runtime .. '"') - table.insert(configs, '-DCMAKE_CXX_FLAGS_RELEASE="/' .. vs_runtime .. '"') - table.insert(configs, '-DCMAKE_C_FLAGS_DEBUG="/' .. vs_runtime .. '"') - table.insert(configs, '-DCMAKE_C_FLAGS_RELEASE="/' .. vs_runtime .. '"') - end _get_configs_for_generic(package, configs, opt) end @@ -739,4 +741,3 @@ function install(package, configs, opt) end os.cd(oldir) end - -- cgit v1.3.1 From 9201e1c987a85dc2c80cc007ad2b8fb1c43562ab Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Mon, 6 Sep 2021 13:52:20 +0200 Subject: Add windows check --- xmake/modules/package/tools/cmake.lua | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/xmake/modules/package/tools/cmake.lua b/xmake/modules/package/tools/cmake.lua index 57318328f..1f0b37087 100644 --- a/xmake/modules/package/tools/cmake.lua +++ b/xmake/modules/package/tools/cmake.lua @@ -133,9 +133,11 @@ function _get_cflags(package, opt) table.join2(result, opt.cxflags) end table.join2(result, _get_cflags_from_packagedeps(package, opt)) - local vs_runtime = package:config("vs_runtime") - if vs_runtime then - table.insert(result, "/" .. vs_runtime) + if package:is_plat("windows") then + local vs_runtime = package:config("vs_runtime") + if vs_runtime then + table.insert(result, "/" .. vs_runtime) + end end if #result > 0 then return os.args(result) @@ -162,9 +164,11 @@ function _get_cxxflags(package, opt) table.join2(result, opt.cxflags) end table.join2(result, _get_cflags_from_packagedeps(package, opt)) - local vs_runtime = package:config("vs_runtime") - if vs_runtime then - table.insert(result, "/" .. vs_runtime) + if package:is_plat("windows") then + local vs_runtime = package:config("vs_runtime") + if vs_runtime then + table.insert(result, "/" .. vs_runtime) + end end if #result > 0 then return os.args(result) -- cgit v1.3.1 From 55f7586eb8e91ccb9179b9c192039d6a3d228e11 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 7 Sep 2021 14:20:31 +0800 Subject: Update cmake.lua --- xmake/modules/package/tools/cmake.lua | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/xmake/modules/package/tools/cmake.lua b/xmake/modules/package/tools/cmake.lua index 857f859be..c3998f0bc 100644 --- a/xmake/modules/package/tools/cmake.lua +++ b/xmake/modules/package/tools/cmake.lua @@ -30,7 +30,7 @@ import("package.tools.ninja") -- get the number of parallel jobs function _get_parallel_njobs(opt) - return opt.jobs or option.get("jobs") or tostring(os.default_njob()) + return opt.jobs or option.get("jobs") or tostring(math.ceil(os.cpuinfo().ncpu * 3 / 2)) end -- translate paths @@ -296,6 +296,12 @@ function _get_configs_for_android(package, configs, opt) if ndk_cxxstl then table.insert(configs, "-DANDROID_STL=" .. ndk_cxxstl) end + if is_host("windows") then + local make = path.join(ndk, "prebuilt", "windows-x86_64", "bin", "make.exe") + if os.isfile(make) then + table.insert(configs, "-DCMAKE_MAKE_PROGRAM=" .. make) + end + end end _get_configs_for_generic(package, configs, opt) end @@ -552,6 +558,16 @@ function _build_for_make(package, configs, opt) local mingw = assert(package:build_getenv("mingw") or package:build_getenv("sdk"), "mingw not found!") local mingw_make = path.join(mingw, "bin", "mingw32-make.exe") os.vrunv(mingw_make, argv) + elseif package:is_plat("android") and is_host("windows") then + local make + local ndk = get_config("ndk") + if ndk then + make = path.join(ndk, "prebuilt", "windows-x86_64", "bin", "make.exe") + end + if not os.isfile(make) then + make = "make" + end + os.vrunv(make, argv) else os.vrunv("make", argv) end @@ -608,6 +624,17 @@ function _install_for_make(package, configs, opt) local mingw_make = path.join(mingw, "bin", "mingw32-make.exe") os.vrunv(mingw_make, argv) os.vrunv(mingw_make, {"install"}) + elseif package:is_plat("android") and is_host("windows") then + local make + local ndk = get_config("ndk") + if ndk then + make = path.join(ndk, "prebuilt", "windows-x86_64", "bin", "make.exe") + end + if not os.isfile(make) then + make = "make" + end + os.vrunv(make, argv) + os.vrunv(make, {"install"}) else os.vrunv("make", argv) os.vrunv("make", {"install"}) -- cgit v1.3.1 From ab7b371299bed8dcdf4ff3bc07e2443d40daaa10 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 7 Sep 2021 14:21:33 +0800 Subject: Update cmake.lua --- xmake/modules/package/tools/cmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/package/tools/cmake.lua b/xmake/modules/package/tools/cmake.lua index c3998f0bc..b6c286e5f 100644 --- a/xmake/modules/package/tools/cmake.lua +++ b/xmake/modules/package/tools/cmake.lua @@ -30,7 +30,7 @@ import("package.tools.ninja") -- get the number of parallel jobs function _get_parallel_njobs(opt) - return opt.jobs or option.get("jobs") or tostring(math.ceil(os.cpuinfo().ncpu * 3 / 2)) + return opt.jobs or option.get("jobs") or tostring(os.default_njob()) end -- translate paths -- cgit v1.3.1 From 42a7aaffe4d274b86945194462cbd61636ee39a4 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 7 Sep 2021 14:25:07 +0800 Subject: Update cmake.lua --- xmake/modules/package/tools/cmake.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/modules/package/tools/cmake.lua b/xmake/modules/package/tools/cmake.lua index b6c286e5f..40a1ad2e5 100644 --- a/xmake/modules/package/tools/cmake.lua +++ b/xmake/modules/package/tools/cmake.lua @@ -564,7 +564,7 @@ function _build_for_make(package, configs, opt) if ndk then make = path.join(ndk, "prebuilt", "windows-x86_64", "bin", "make.exe") end - if not os.isfile(make) then + if not make or not os.isfile(make) then make = "make" end os.vrunv(make, argv) @@ -630,7 +630,7 @@ function _install_for_make(package, configs, opt) if ndk then make = path.join(ndk, "prebuilt", "windows-x86_64", "bin", "make.exe") end - if not os.isfile(make) then + if not make or not os.isfile(make) then make = "make" end os.vrunv(make, argv) -- cgit v1.3.1 From d9021ad4c05a4f968979d948ab40aa9dd89a363f Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Wed, 8 Sep 2021 14:27:20 +0200 Subject: Improve install --- xmake/modules/target/action/install/unix.lua | 20 ++++++++++++++------ xmake/modules/target/action/install/windows.lua | 19 ++++++++++++++----- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/xmake/modules/target/action/install/unix.lua b/xmake/modules/target/action/install/unix.lua index ae06ed3bc..521ed40de 100644 --- a/xmake/modules/target/action/install/unix.lua +++ b/xmake/modules/target/action/install/unix.lua @@ -37,15 +37,23 @@ end -- install shared libraries for package function _install_shared_for_package(target, pkg, outputdir) + _g.installed_libfiles = _g.installed_libfiles or {} for _, sopath in ipairs(table.wrap(pkg:get("libfiles"))) do if sopath:endswith(".so") or sopath:match(".+%.so%..+$") or sopath:endswith(".dylib") then - local soname = path.filename(sopath) - if os.isfile(path.join(outputdir, soname)) then - wprint("'%s' already exists in install dir, overwriting it from package(%s).", soname, pkg:name()) + -- prevent packages using the same system libfiles from overwriting each other + if not _g.installed_libfiles[sopath] then + local soname = path.filename(sopath) + local targetname = path.join(outputdir, soname) + if os.isfile(targetname) then + wprint("'%s' already exists in install dir, overwriting it from package(%s).", soname, pkg:name()) + -- rm because symlink cannot overwrite existing file + os.rm(targetname) + end + -- we need reserve symlink + -- @see https://github.com/xmake-io/xmake/issues/1582 + os.vcp(sopath, outputdir, {symlink = true}) + _g.installed_libfiles[sopath] = true end - -- we need reserve symlink - -- @see https://github.com/xmake-io/xmake/issues/1582 - os.vcp(sopath, outputdir, {symlink = true}) end end end diff --git a/xmake/modules/target/action/install/windows.lua b/xmake/modules/target/action/install/windows.lua index dfb8d2bd3..609e87389 100644 --- a/xmake/modules/target/action/install/windows.lua +++ b/xmake/modules/target/action/install/windows.lua @@ -40,13 +40,18 @@ end -- install shared libraries for package function _install_shared_for_package(target, pkg, outputdir) + _g.installed_dllfiles = _g.installed_dllfiles or {} for _, dllpath in ipairs(table.wrap(pkg:get("libfiles"))) do if dllpath:endswith(".dll") then - local dllname = path.filename(dllpath) - if os.isfile(path.join(outputdir, dllname)) then - wprint("'%s' already exists in install dir, overwriting it from package(%s).", dllname, pkg:name()) + -- prevent packages using the same libfiles from overwriting each other + if not _g.installed_dllfiles[dllpath] then + local dllname = path.filename(dllpath) + if os.isfile(path.join(outputdir, dllname)) then + wprint("'%s' already exists in install dir, overwriting it from package(%s).", dllname, pkg:name()) + end + os.vcp(dllpath, outputdir) + _g.installed_dllfiles[dllpath] = true end - os.vcp(dllpath, outputdir) end end end @@ -74,11 +79,15 @@ function install_binary(target, opt) -- install the dependent shared/windows (*.dll) target -- @see https://github.com/xmake-io/xmake/issues/961 + _g.installed_dllfiles = _g.installed_dllfiles or {} for _, dep in ipairs(target:orderdeps()) do if dep:kind() == "shared" then local depfile = dep:targetfile() if os.isfile(depfile) then - os.vcp(depfile, binarydir) + if not _g.installed_dllfiles[depfile] then + os.vcp(depfile, binarydir) + _g.installed_dllfiles[depfile] = true + end end end -- install all shared libraries in packages in all deps -- cgit v1.3.1 From 0b151b821c8c34dfa445fbe938b0acb316145858 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Wed, 8 Sep 2021 17:35:59 +0200 Subject: Improve cmake --- xmake/modules/package/tools/cmake.lua | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/xmake/modules/package/tools/cmake.lua b/xmake/modules/package/tools/cmake.lua index c13b48356..65d5d3b1d 100644 --- a/xmake/modules/package/tools/cmake.lua +++ b/xmake/modules/package/tools/cmake.lua @@ -133,12 +133,6 @@ function _get_cflags(package, opt) table.join2(result, opt.cxflags) end table.join2(result, _get_cflags_from_packagedeps(package, opt)) - if package:is_plat("windows") then - local vs_runtime = package:config("vs_runtime") - if vs_runtime then - table.insert(result, "/" .. vs_runtime) - end - end if #result > 0 then return os.args(result) end @@ -164,12 +158,6 @@ function _get_cxxflags(package, opt) table.join2(result, opt.cxflags) end table.join2(result, _get_cflags_from_packagedeps(package, opt)) - if package:is_plat("windows") then - local vs_runtime = package:config("vs_runtime") - if vs_runtime then - table.insert(result, "/" .. vs_runtime) - end - end if #result > 0 then return os.args(result) end @@ -283,6 +271,15 @@ function _get_configs_for_windows(package, configs, opt) elseif vs_runtime == "MDd" then table.insert(configs, "-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDebugDLL") end + if vs_runtime then + -- CMake default MSVC flags as of 3.21.2 + local default_debug_flags = "/Zi /Ob0 /Od /RTC1" + local default_release_flags = "/O2 /Ob2 /DNDEBUG" + table.insert(configs, '-DCMAKE_CXX_FLAGS_DEBUG="/' .. vs_runtime .. ' ' .. default_debug_flags .. '"') + table.insert(configs, '-DCMAKE_CXX_FLAGS_RELEASE="/' .. vs_runtime .. ' ' .. default_release_flags .. '"') + table.insert(configs, '-DCMAKE_C_FLAGS_DEBUG="/' .. vs_runtime .. ' ' .. default_debug_flags .. '"') + table.insert(configs, '-DCMAKE_C_FLAGS_RELEASE="/' .. vs_runtime .. ' ' .. default_release_flags .. '"') + end _get_configs_for_generic(package, configs, opt) end -- cgit v1.3.1 From 746281d9ed462ad3f820d1f231989e0bb25d3a7f Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Wed, 8 Sep 2021 18:33:21 +0200 Subject: Fix cmake flags for vs_runtime --- xmake/modules/package/tools/cmake.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xmake/modules/package/tools/cmake.lua b/xmake/modules/package/tools/cmake.lua index 65d5d3b1d..048ff5909 100644 --- a/xmake/modules/package/tools/cmake.lua +++ b/xmake/modules/package/tools/cmake.lua @@ -275,10 +275,10 @@ function _get_configs_for_windows(package, configs, opt) -- CMake default MSVC flags as of 3.21.2 local default_debug_flags = "/Zi /Ob0 /Od /RTC1" local default_release_flags = "/O2 /Ob2 /DNDEBUG" - table.insert(configs, '-DCMAKE_CXX_FLAGS_DEBUG="/' .. vs_runtime .. ' ' .. default_debug_flags .. '"') - table.insert(configs, '-DCMAKE_CXX_FLAGS_RELEASE="/' .. vs_runtime .. ' ' .. default_release_flags .. '"') - table.insert(configs, '-DCMAKE_C_FLAGS_DEBUG="/' .. vs_runtime .. ' ' .. default_debug_flags .. '"') - table.insert(configs, '-DCMAKE_C_FLAGS_RELEASE="/' .. vs_runtime .. ' ' .. default_release_flags .. '"') + table.insert(configs, '-DCMAKE_CXX_FLAGS_DEBUG=/' .. vs_runtime .. ' ' .. default_debug_flags) + table.insert(configs, '-DCMAKE_CXX_FLAGS_RELEASE=/' .. vs_runtime .. ' ' .. default_release_flags) + table.insert(configs, '-DCMAKE_C_FLAGS_DEBUG=/' .. vs_runtime .. ' ' .. default_debug_flags) + table.insert(configs, '-DCMAKE_C_FLAGS_RELEASE=/' .. vs_runtime .. ' ' .. default_release_flags) end _get_configs_for_generic(package, configs, opt) end -- cgit v1.3.1 From 7b931b248bcb5328b993637b6ebda3e9fa7c25ff Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 12 Sep 2021 23:33:04 +0800 Subject: improve load target --- xmake/core/project/project.lua | 60 +++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 39 deletions(-) diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 91982e64a..311a9a260 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -353,29 +353,6 @@ function project._load_toolchains() return toolchains end --- load target -function project._load_target(t, requires) - - -- do before_load() for target and all rules - local ok, errors = t:_load_before() - if not ok then - return false, errors - end - - -- do on_load() for target and all rules - ok, errors = t:_load() - if not ok then - return false, errors - end - - -- do after_load() for target and all rules - ok, errors = t:_load_after() - if not ok then - return false, errors - end - return true -end - -- load targets function project._load_targets() @@ -409,11 +386,6 @@ function project._load_targets() -- load and attach target deps, rules and packages for _, t in pairs(targets) do - -- load deps - t._DEPS = t._DEPS or {} - t._ORDERDEPS = t._ORDERDEPS or {} - project._load_deps(t, targets, t._DEPS, t._ORDERDEPS, {t:name()}) - -- load rules from target and language -- -- e.g. @@ -458,6 +430,24 @@ function project._load_targets() return nil, nil, string.format("unknown rule(%s) in target(%s)!", rulename, t:name()) end end + + -- do before_load() + ok, errors = t:_load_before() + if not ok then + return nil, nil, errors + end + + -- we need call on_load() before building deps/rules, + -- so we can use `target:add("deps", "xxx")` to add deps in on_load + ok, errors = t:_load() + if not ok then + return nil, nil, errors + end + + -- load deps + t._DEPS = t._DEPS or {} + t._ORDERDEPS = t._ORDERDEPS or {} + project._load_deps(t, targets, t._DEPS, t._ORDERDEPS, {t:name()}) end -- sort targets for all deps @@ -467,19 +457,13 @@ function project._load_targets() project._sort_targets(targets, ordertargets, targetrefs, t) end - -- do load for each target - local ok = false + -- do after_load() for targets for _, t in ipairs(ordertargets) do - ok, errors = project._load_target(t, requires) + ok, errors = t:_load_after() if not ok then - break + return nil, nil, errors end end - - -- do load failed? - if not ok then - return nil, nil, errors - end return targets, ordertargets end @@ -558,8 +542,6 @@ function project._load_options(disable_filter) opt._ORDERDEPS = opt._ORDERDEPS or {} project._load_deps(opt, options, opt._DEPS, opt._ORDERDEPS, {opt:name()}) end - - -- ok? return options end -- cgit v1.3.1 From 8c8030ba48cda0c12ed7934b6dd4ffff5b191a33 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 14 Sep 2021 00:46:22 +0800 Subject: add after_load for target --- tests/projects/other/build_deps/xmake.lua | 16 ++++++++-------- xmake/core/project/target.lua | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/tests/projects/other/build_deps/xmake.lua b/tests/projects/other/build_deps/xmake.lua index 2458ba7df..9fe31c900 100644 --- a/tests/projects/other/build_deps/xmake.lua +++ b/tests/projects/other/build_deps/xmake.lua @@ -4,7 +4,7 @@ target("dep1") set_kind("static") add_deps("dep3") add_files("src/interface.c") - on_load(function (target) + after_load(function (target) os.rm(target:targetfile()) os.rm(target:dep("dep3"):targetfile()) end) @@ -20,7 +20,7 @@ target("dep2") set_kind("static") add_deps("dep3") add_files("src/interface.c") - on_load(function (target) + after_load(function (target) os.rm(target:targetfile()) os.rm(target:dep("dep3"):targetfile()) end) @@ -36,7 +36,7 @@ target("dep3") set_kind("static") add_files("src/interface.c") add_deps("dep4", "dep5") - on_load(function (target) + after_load(function (target) os.rm(target:targetfile()) os.rm(target:dep("dep4"):targetfile()) os.rm(target:dep("dep5"):targetfile()) @@ -51,7 +51,7 @@ target("dep3") target("dep4") set_kind("static") add_files("src/interface.c") - on_load(function (target) + after_load(function (target) os.rm(target:targetfile()) end) after_link(function (target) @@ -62,7 +62,7 @@ target("dep4") target("dep5") set_kind("static") add_files("src/interface.c") - on_load(function (target) + after_load(function (target) os.rm(target:targetfile()) end) after_link(function (target) @@ -74,7 +74,7 @@ target("test1") set_kind("binary") add_deps("dep1", "dep2") add_files("src/test.c") - on_load(function (target) + after_load(function (target) os.rm(target:targetfile()) os.rm(target:dep("dep1"):targetfile()) os.rm(target:dep("dep2"):targetfile()) @@ -94,7 +94,7 @@ target("test2") set_kind("binary") add_deps("dep1") add_files("src/test.c") - on_load(function (target) + after_load(function (target) os.rm(target:targetfile()) os.rm(target:dep("dep1"):targetfile()) os.rm(target:dep("dep3"):targetfile()) @@ -120,7 +120,7 @@ target("test3") add_rules("test3") add_files("src/test.c") set_policy("build.across_targets_in_parallel", false) - on_load(function (target) + after_load(function (target) os.rm(target:targetfile()) os.rm(target:dep("dep1"):targetfile()) os.rm(target:dep("dep3"):targetfile()) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 0ff4222fa..c7d2adc5f 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -133,6 +133,9 @@ function _instance:_load() return false, errors end end + + -- mark as loaded + self._LOADED = true return true end @@ -142,6 +145,15 @@ function _instance:_load_after() -- enter the environments of the target packages local oldenvs = os.addenvs(self:pkgenvs()) + -- do load for target + local after_load = self:script("load_after") + if after_load then + local ok, errors = sandbox.load(after_load, self) + if not ok then + return false, errors + end + end + -- do after_load with target rules local ok, errors = self:_load_rules("after") if not ok then @@ -608,11 +620,17 @@ end -- get target deps function _instance:deps() + if not self._LOADED then + os.raise("please call target:deps() or target:dep() in after_load()!") + end return self._DEPS end -- get target ordered deps function _instance:orderdeps() + if not self._LOADED then + os.raise("please call target:orderdeps() in after_load()!") + end return self._ORDERDEPS end @@ -2003,6 +2021,7 @@ function target.apis() , "target.before_uninstall" -- target.after_xxx , "target.after_run" + , "target.after_load" , "target.after_link" , "target.after_build" , "target.after_build_file" -- cgit v1.3.1 From 3abbb1c004c0c56bf34c9155098e1844e0483581 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 14 Sep 2021 00:47:07 +0800 Subject: remove before_load --- tests/projects/other/multiplats_vs/xmake.lua | 2 +- xmake/core/project/project.lua | 6 ------ xmake/core/project/rule.lua | 1 - xmake/core/project/target.lua | 11 ----------- xmake/rules/cuda/env/xmake.lua | 2 +- xmake/rules/cuda/gencodes/xmake.lua | 2 +- xmake/rules/luarocks/module/xmake.lua | 2 +- xmake/rules/utils/symbols/export_all/xmake.lua | 2 +- xmake/rules/wdk/env/xmake.lua | 2 +- xmake/rules/wdk/inf/xmake.lua | 2 +- xmake/rules/wdk/man/xmake.lua | 2 +- xmake/rules/wdk/mc/xmake.lua | 2 +- xmake/rules/wdk/mof/xmake.lua | 2 +- xmake/rules/wdk/sign/xmake.lua | 2 +- xmake/rules/wdk/tracewpp/xmake.lua | 2 +- xmake/rules/winsdk/dotnet/xmake.lua | 2 +- xmake/rules/winsdk/mfc/env/xmake.lua | 2 +- xmake/rules/winsdk/xmake.lua | 2 +- xmake/rules/xcode/application/xmake.lua | 2 +- xmake/rules/xcode/bundle/xmake.lua | 2 +- xmake/rules/xcode/framework/xmake.lua | 2 +- xmake/rules/xmake_cli/xmake.lua | 2 +- 22 files changed, 19 insertions(+), 37 deletions(-) diff --git a/tests/projects/other/multiplats_vs/xmake.lua b/tests/projects/other/multiplats_vs/xmake.lua index 4e61a20a1..255e2e913 100644 --- a/tests/projects/other/multiplats_vs/xmake.lua +++ b/tests/projects/other/multiplats_vs/xmake.lua @@ -1,7 +1,7 @@ add_rules("mode.debug", "mode.release") rule("vs2015_x86") - before_load(function (target) + on_load(function (target) target:set("arch", "x86") target:set("toolchains", "msvc", {vs = "2015"}) end) diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 311a9a260..411845056 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -431,12 +431,6 @@ function project._load_targets() end end - -- do before_load() - ok, errors = t:_load_before() - if not ok then - return nil, nil, errors - end - -- we need call on_load() before building deps/rules, -- so we can use `target:add("deps", "xxx")` to add deps in on_load ok, errors = t:_load() diff --git a/xmake/core/project/rule.lua b/xmake/core/project/rule.lua index c155a813f..534bb5f8a 100644 --- a/xmake/core/project/rule.lua +++ b/xmake/core/project/rule.lua @@ -180,7 +180,6 @@ function rule.apis() , "rule.on_buildcmd_files" -- rule.before_xxx , "rule.before_run" - , "rule.before_load" , "rule.before_link" , "rule.before_build" , "rule.before_build_file" diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index c7d2adc5f..8cfbf0a12 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -105,17 +105,6 @@ function _instance:_load_rules(suffix) return true end --- do before_load target and rules -function _instance:_load_before() - - -- do before_load with target rules - local ok, errors = self:_load_rules("before") - if not ok then - return false, errors - end - return true -end - -- do load target and rules function _instance:_load() diff --git a/xmake/rules/cuda/env/xmake.lua b/xmake/rules/cuda/env/xmake.lua index e6e802d71..96d587e41 100644 --- a/xmake/rules/cuda/env/xmake.lua +++ b/xmake/rules/cuda/env/xmake.lua @@ -21,7 +21,7 @@ -- define rule: environment rule("cuda.env") - before_load(function (target) + on_load(function (target) -- imports import("detect.sdks.find_cuda") diff --git a/xmake/rules/cuda/gencodes/xmake.lua b/xmake/rules/cuda/gencodes/xmake.lua index 0845178fe..b5ebc22d1 100644 --- a/xmake/rules/cuda/gencodes/xmake.lua +++ b/xmake/rules/cuda/gencodes/xmake.lua @@ -34,7 +34,7 @@ rule("cuda.gencodes") -- if no available device is found, no `-gencode` flags will be added -- @seealso xmake/modules/lib/detect/find_cudadevices -- - before_load(function (target) + on_load(function (target) -- imports import("core.platform.platform") diff --git a/xmake/rules/luarocks/module/xmake.lua b/xmake/rules/luarocks/module/xmake.lua index e74080912..530e35070 100644 --- a/xmake/rules/luarocks/module/xmake.lua +++ b/xmake/rules/luarocks/module/xmake.lua @@ -19,7 +19,7 @@ -- rule("luarocks.module") - before_load(function (target) + on_load(function (target) -- imports import("core.cache.detectcache") diff --git a/xmake/rules/utils/symbols/export_all/xmake.lua b/xmake/rules/utils/symbols/export_all/xmake.lua index f804e3c3e..b808d63a9 100644 --- a/xmake/rules/utils/symbols/export_all/xmake.lua +++ b/xmake/rules/utils/symbols/export_all/xmake.lua @@ -26,7 +26,7 @@ -- @see https://github.com/xmake-io/xmake/issues/1123 -- rule("utils.symbols.export_all") - before_load(function (target) + on_load(function (target) -- @note it only supports windows/dll now assert(target:is_shared(), 'rule("utils.symbols.export_all"): only for shared target(%s)!', target:name()) if target:is_plat("windows") then diff --git a/xmake/rules/wdk/env/xmake.lua b/xmake/rules/wdk/env/xmake.lua index 6b7690933..a9089dc5e 100644 --- a/xmake/rules/wdk/env/xmake.lua +++ b/xmake/rules/wdk/env/xmake.lua @@ -22,7 +22,7 @@ rule("wdk.env") -- before load - before_load(function (target) + on_load(function (target) -- imports import("os.winver", {alias = "os_winver"}) diff --git a/xmake/rules/wdk/inf/xmake.lua b/xmake/rules/wdk/inf/xmake.lua index fe060a10a..6ad91e62d 100644 --- a/xmake/rules/wdk/inf/xmake.lua +++ b/xmake/rules/wdk/inf/xmake.lua @@ -28,7 +28,7 @@ rule("wdk.inf") set_extensions(".inf", ".inx") -- before load - before_load(function (target) + on_load(function (target) -- imports import("core.project.config") diff --git a/xmake/rules/wdk/man/xmake.lua b/xmake/rules/wdk/man/xmake.lua index 25cce9f34..7843542d7 100644 --- a/xmake/rules/wdk/man/xmake.lua +++ b/xmake/rules/wdk/man/xmake.lua @@ -28,7 +28,7 @@ rule("wdk.man") set_extensions(".man") -- before load - before_load(function (target) + on_load(function (target) -- imports import("core.project.config") diff --git a/xmake/rules/wdk/mc/xmake.lua b/xmake/rules/wdk/mc/xmake.lua index 32653dfc2..abc75fdf7 100644 --- a/xmake/rules/wdk/mc/xmake.lua +++ b/xmake/rules/wdk/mc/xmake.lua @@ -28,7 +28,7 @@ rule("wdk.mc") set_extensions(".mc") -- before load - before_load(function (target) + on_load(function (target) -- imports import("core.project.config") diff --git a/xmake/rules/wdk/mof/xmake.lua b/xmake/rules/wdk/mof/xmake.lua index 319eec5d7..8be25de20 100644 --- a/xmake/rules/wdk/mof/xmake.lua +++ b/xmake/rules/wdk/mof/xmake.lua @@ -28,7 +28,7 @@ rule("wdk.mof") set_extensions(".mof") -- before load - before_load(function (target) + on_load(function (target) -- imports import("core.project.config") diff --git a/xmake/rules/wdk/sign/xmake.lua b/xmake/rules/wdk/sign/xmake.lua index 7dcc28785..dd137c5ec 100644 --- a/xmake/rules/wdk/sign/xmake.lua +++ b/xmake/rules/wdk/sign/xmake.lua @@ -34,7 +34,7 @@ rule("wdk.sign") add_deps("wdk.env") -- before load - before_load(function (target) + on_load(function (target) -- imports import("core.project.config") diff --git a/xmake/rules/wdk/tracewpp/xmake.lua b/xmake/rules/wdk/tracewpp/xmake.lua index 0c49bf5d0..52d72827f 100644 --- a/xmake/rules/wdk/tracewpp/xmake.lua +++ b/xmake/rules/wdk/tracewpp/xmake.lua @@ -25,7 +25,7 @@ rule("wdk.tracewpp") add_deps("wdk.env") -- before load - before_load(function (target) + on_load(function (target) -- imports import("core.project.config") diff --git a/xmake/rules/winsdk/dotnet/xmake.lua b/xmake/rules/winsdk/dotnet/xmake.lua index 5274f040a..1cfef7b58 100644 --- a/xmake/rules/winsdk/dotnet/xmake.lua +++ b/xmake/rules/winsdk/dotnet/xmake.lua @@ -22,7 +22,7 @@ rule("win.sdk.dotnet") -- before load - before_load(function (target) + on_load(function (target) -- imports import("core.project.config") diff --git a/xmake/rules/winsdk/mfc/env/xmake.lua b/xmake/rules/winsdk/mfc/env/xmake.lua index f603ebfe2..f553618b5 100644 --- a/xmake/rules/winsdk/mfc/env/xmake.lua +++ b/xmake/rules/winsdk/mfc/env/xmake.lua @@ -22,5 +22,5 @@ rule("win.sdk.mfc.env") -- TODO: before load need check of vs's minverion, if defined - before_load(function (target) + on_load(function (target) end) diff --git a/xmake/rules/winsdk/xmake.lua b/xmake/rules/winsdk/xmake.lua index 0a3b105cc..297dfda75 100644 --- a/xmake/rules/winsdk/xmake.lua +++ b/xmake/rules/winsdk/xmake.lua @@ -27,7 +27,7 @@ rule("win.sdk.resource") rule("win.sdk.application") -- before load - before_load(function (target) + on_load(function (target) target:set("kind", "binary") end) diff --git a/xmake/rules/xcode/application/xmake.lua b/xmake/rules/xcode/application/xmake.lua index 51232f033..7d5edc668 100644 --- a/xmake/rules/xcode/application/xmake.lua +++ b/xmake/rules/xcode/application/xmake.lua @@ -25,7 +25,7 @@ rule("xcode.application") add_deps("xcode.info_plist", "xcode.storyboard", "xcode.xcassets", "xcode.metal") -- we must set kind before target.on_load(), may we will use target in on_load() - before_load("load") + on_load("load") -- build *.app after_build("build") diff --git a/xmake/rules/xcode/bundle/xmake.lua b/xmake/rules/xcode/bundle/xmake.lua index bd8e4329e..1c1cecf99 100644 --- a/xmake/rules/xcode/bundle/xmake.lua +++ b/xmake/rules/xcode/bundle/xmake.lua @@ -25,7 +25,7 @@ rule("xcode.bundle") add_deps("xcode.info_plist") -- we must set kind before target.on_load(), may we will use target in on_load() - before_load(function (target) + on_load(function (target) -- get bundle directory local targetdir = target:targetdir() diff --git a/xmake/rules/xcode/framework/xmake.lua b/xmake/rules/xcode/framework/xmake.lua index b112dcaf1..6b46b3c97 100644 --- a/xmake/rules/xcode/framework/xmake.lua +++ b/xmake/rules/xcode/framework/xmake.lua @@ -25,7 +25,7 @@ rule("xcode.framework") add_deps("xcode.info_plist") -- we must set kind before target.on_load(), may we will use target in on_load() - before_load(function (target) + on_load(function (target) -- get framework directory local targetdir = target:targetdir() diff --git a/xmake/rules/xmake_cli/xmake.lua b/xmake/rules/xmake_cli/xmake.lua index 2375c9e3b..a7e21a9e1 100644 --- a/xmake/rules/xmake_cli/xmake.lua +++ b/xmake/rules/xmake_cli/xmake.lua @@ -20,7 +20,7 @@ -- define rule: xmake cli program rule("xmake.cli") - before_load(function (target) + on_load(function (target) target:set("kind", "binary") assert(target:pkg("libxmake"), 'please add_packages("libxmake") to target(%s) first!', target:name()) end) -- cgit v1.3.1 From ebe9e105b9ddb55d928c647ce0d15da9bd19c5c5 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 15 Sep 2021 00:41:47 +0800 Subject: improve xcode.application rule --- xmake/rules/xcode/application/load.lua | 11 ----------- xmake/rules/xcode/application/xmake.lua | 13 +++++++++++++ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/xmake/rules/xcode/application/load.lua b/xmake/rules/xcode/application/load.lua index 3071ccd58..354aa5b0c 100644 --- a/xmake/rules/xcode/application/load.lua +++ b/xmake/rules/xcode/application/load.lua @@ -54,15 +54,4 @@ function main (target) -- register clean files for `xmake clean` target:add("cleanfiles", bundledir) - - -- depend xcode.framework? we need disable `build.across_targets_in_parallel` policy - local across_targets_in_parallel - for _, dep in ipairs(target:orderdeps()) do - if dep:rule("xcode.framework") then - across_targets_in_parallel = false - end - end - if across_targets_in_parallel ~= nil then - target:set("policy", "build.across_targets_in_parallel", across_targets_in_parallel) - end end diff --git a/xmake/rules/xcode/application/xmake.lua b/xmake/rules/xcode/application/xmake.lua index 7d5edc668..d328262c0 100644 --- a/xmake/rules/xcode/application/xmake.lua +++ b/xmake/rules/xcode/application/xmake.lua @@ -27,6 +27,19 @@ rule("xcode.application") -- we must set kind before target.on_load(), may we will use target in on_load() on_load("load") + -- depend xcode.framework? we need disable `build.across_targets_in_parallel` policy + after_load(function (target) + local across_targets_in_parallel + for _, dep in ipairs(target:orderdeps()) do + if dep:rule("xcode.framework") then + across_targets_in_parallel = false + end + end + if across_targets_in_parallel ~= nil then + target:set("policy", "build.across_targets_in_parallel", across_targets_in_parallel) + end + end) + -- build *.app after_build("build") -- cgit v1.3.1 From 43a72ecc3eba54b09dadcd0e8754dae7b23ed2da Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 15 Sep 2021 16:38:39 +0800 Subject: Update check.lua --- xmake/toolchains/msvc/check.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xmake/toolchains/msvc/check.lua b/xmake/toolchains/msvc/check.lua index 634249232..ce3fdd8d9 100644 --- a/xmake/toolchains/msvc/check.lua +++ b/xmake/toolchains/msvc/check.lua @@ -60,6 +60,8 @@ function _check_vsenv(toolchain) -- save vcvars toolchain:config_set("vcvars", vcvars) + toolchain:config_set("vs_toolset", vcvars.VCToolsVersion) + toolchain:config_set("vs_sdkver", vcvars.WindowsSDKVersion) -- check compiler local program = nil -- cgit v1.3.1 From 4cc9ef5e230ac3b765d26cdc3b0dd51ece2448e4 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 16 Sep 2021 00:31:02 +0800 Subject: improve mingw implib --- xmake/core/project/target.lua | 12 ++++-------- .../core/sandbox/modules/import/lib/detect/find_library.lua | 7 +++---- xmake/modules/core/tools/gcc.lua | 2 +- xmake/modules/core/tools/nvcc.lua | 4 ++-- xmake/platforms/mingw/xmake.lua | 4 ++-- 5 files changed, 12 insertions(+), 17 deletions(-) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 8cfbf0a12..959e94f5b 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -2059,18 +2059,14 @@ end -- get the link name of the target file function target.linkname(filename) + -- for implib/mingw, e.g. libxxx.dll.a + if filename:startswith("lib") and filename:endswith(".dll.a") then + return filename:sub(4, #filename - 6) + end local linkname, count = filename:gsub(target.filename("__pattern__", "static"):gsub("%.", "%%."):gsub("__pattern__", "(.+)") .. "$", "%1") if count == 0 then linkname, count = filename:gsub(target.filename("__pattern__", "shared"):gsub("%.", "%%."):gsub("__pattern__", "(.+)") .. "$", "%1") end - if count == 0 then - -- for the mingw/cross platform, it is compatible with the libxxx.a and xxx.lib - local formats = {static = "lib$(name).a", shared = "lib$(name).so"} - linkname, count = filename:gsub(target.filename("__pattern__", "static", {format = formats["static"]}):gsub("%.", "%%."):gsub("__pattern__", "(.+)") .. "$", "%1") - if count == 0 then - linkname, count = filename:gsub(target.filename("__pattern__", "shared", {format = formats["shared"]}):gsub("%.", "%%."):gsub("__pattern__", "(.+)") .. "$", "%1") - end - end return count > 0 and linkname or nil end diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_library.lua b/xmake/core/sandbox/modules/import/lib/detect/find_library.lua index bfb2315a5..0b783538c 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/find_library.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/find_library.lua @@ -64,10 +64,9 @@ function sandbox_lib_detect_find_library.main(names, paths, opt) for _, name in ipairs(table.wrap(names)) do for _, kind in ipairs(table.wrap(kinds)) do local filepath = find_file(target.filename(name, kind), paths, opt) - if not filepath then - -- for the mingw/cross platform, it is compatible with the libxxx.a and xxx.lib - local formats = {static = "lib$(name).a", shared = "lib$(name).so"} - filepath = find_file(target.filename(name, kind, {format = formats[kind]}), paths, opt) + if not filepath and kind == "shared" then + -- for implib/mingw, e.g. libxxx.dll.a + filepath = find_file(target.filename(name, kind) .. ".a", paths, opt) end if filepath then local filename = path.filename(filepath) diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index 89b732ec9..713cd80aa 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -334,7 +334,7 @@ function linkargv(self, objectfiles, targetkind, targetfile, flags, opt) -- add `-Wl,--out-implib,outputdir/libxxx.a` for xxx.dll on mingw/gcc if targetkind == "shared" and is_plat("mingw") then - table.insert(flags_extra, "-Wl,--out-implib," .. path.join(path.directory(targetfile), path.basename(targetfile) .. ".lib")) + table.insert(flags_extra, "-Wl,--out-implib," .. path.join(path.directory(targetfile), path.basename(targetfile) .. ".dll.a")) end -- init arguments diff --git a/xmake/modules/core/tools/nvcc.lua b/xmake/modules/core/tools/nvcc.lua index 1ca09401e..41093c502 100644 --- a/xmake/modules/core/tools/nvcc.lua +++ b/xmake/modules/core/tools/nvcc.lua @@ -259,9 +259,9 @@ function linkargv(self, objectfiles, targetkind, targetfile, flags) end -- add `-Wl,--out-implib,outputdir/libxxx.a` for xxx.dll on mingw/gcc - if targetkind == "shared" and config.plat() == "mingw" then + if targetkind == "shared" and is_plat("mingw") then table.insert(flags_extra, "-Xlinker") - table.insert(flags_extra, "-Wl,--out-implib," .. path.join(path.directory(targetfile), path.basename(targetfile) .. ".lib")) + table.insert(flags_extra, "-Wl,--out-implib," .. path.join(path.directory(targetfile), path.basename(targetfile) .. ".dll.a")) end -- make link args diff --git a/xmake/platforms/mingw/xmake.lua b/xmake/platforms/mingw/xmake.lua index b856cf876..b86786a0f 100644 --- a/xmake/platforms/mingw/xmake.lua +++ b/xmake/platforms/mingw/xmake.lua @@ -31,9 +31,9 @@ platform("mingw") set_archs("i386", "x86_64", "arm", "arm64") -- set formats - set_formats("static", "$(name).lib") + set_formats("static", "lib$(name).a") set_formats("object", "$(name).obj") - set_formats("shared", "$(name).dll") + set_formats("shared", "lib$(name).dll") set_formats("binary", "$(name).exe") set_formats("symbol", "$(name).pdb") -- cgit v1.3.1 From 8f3d4ec9654ba58a5a098213c2d28c01ecd1649c Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 16 Sep 2021 00:32:13 +0800 Subject: improve mingw installation --- xmake/modules/target/action/install/windows.lua | 2 +- xmake/modules/target/action/uninstall/windows.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/modules/target/action/install/windows.lua b/xmake/modules/target/action/install/windows.lua index 609e87389..87a7413ca 100644 --- a/xmake/modules/target/action/install/windows.lua +++ b/xmake/modules/target/action/install/windows.lua @@ -110,7 +110,7 @@ function install_shared(target, opt) -- @see https://github.com/xmake-io/xmake/issues/714 local targetfile = target:targetfile() local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib") - local targetfile_lib = path.join(path.directory(targetfile), path.basename(targetfile) .. ".lib") + local targetfile_lib = path.join(path.directory(targetfile), path.basename(targetfile) .. (target:is_plat("mingw") and ".dll.a" or ".lib")) if os.isfile(targetfile_lib) then os.mkdir(librarydir) os.vcp(targetfile_lib, librarydir) diff --git a/xmake/modules/target/action/uninstall/windows.lua b/xmake/modules/target/action/uninstall/windows.lua index 236b045e3..2915966db 100644 --- a/xmake/modules/target/action/uninstall/windows.lua +++ b/xmake/modules/target/action/uninstall/windows.lua @@ -81,7 +81,7 @@ function uninstall_shared(target, opt) -- @see https://github.com/xmake-io/xmake/issues/714 local targetfile = target:targetfile() local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib") - os.vrm(path.join(librarydir, path.basename(targetfile) .. ".lib")) + os.vrm(path.join(librarydir, path.basename(targetfile) .. (target:is_plat("mingw") and ".dll.a" or ".lib"))) -- remove headers from the include directory _uninstall_headers(target, opt) -- cgit v1.3.1 From 646b616d40835ef4c882f15df1f15574af2cfe58 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 16 Sep 2021 00:33:45 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d83e6378c..42294dd51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * Improve Qt rules to support Qt 4.x * Improve `set_symbols("debug")` to generate pdb file for clang on windows * [#1638](https://github.com/xmake-io/xmake/issues/1638): Improve to merge static library +* Improve on_load/after_load to support to add target deps dynamically ## v2.5.7 @@ -1081,6 +1082,7 @@ * 改进 Qt 规则去支持 Qt 4.x * 改进 `set_symbols("debug")` 支持 clang/windows 生成 pdb 文件 * [#1638](https://github.com/xmake-io/xmake/issues/1638): 改进合并静态库 +* 改进 on_load/after_load 去支持动态的添加 target deps ## v2.5.7 -- cgit v1.3.1 From b0de078312f7c87f54c9229b913992a495a3b2ed Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 16 Sep 2021 22:44:11 +0800 Subject: improve find_library --- xmake/core/project/target.lua | 11 +++++++--- .../modules/import/lib/detect/find_library.lua | 25 ++++++++++++---------- .../package/manager/pkgconfig/find_package.lua | 1 - .../package/manager/system/find_package.lua | 2 +- .../modules/package/manager/vcpkg/find_package.lua | 1 - .../modules/package/manager/xmake/find_package.lua | 4 ++-- 6 files changed, 25 insertions(+), 19 deletions(-) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 959e94f5b..7b0ce47d9 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -2058,14 +2058,19 @@ function target.filename(targetname, targetkind, opt) end -- get the link name of the target file -function target.linkname(filename) +function target.linkname(filename, opt) -- for implib/mingw, e.g. libxxx.dll.a + opt = opt or {} if filename:startswith("lib") and filename:endswith(".dll.a") then return filename:sub(4, #filename - 6) end - local linkname, count = filename:gsub(target.filename("__pattern__", "static"):gsub("%.", "%%."):gsub("__pattern__", "(.+)") .. "$", "%1") + local linkname, count = filename:gsub(target.filename("__pattern__", "static", {plat = opt.plat}):gsub("%.", "%%."):gsub("__pattern__", "(.+)") .. "$", "%1") if count == 0 then - linkname, count = filename:gsub(target.filename("__pattern__", "shared"):gsub("%.", "%%."):gsub("__pattern__", "(.+)") .. "$", "%1") + linkname, count = filename:gsub(target.filename("__pattern__", "shared", {plat = opt.plat}):gsub("%.", "%%."):gsub("__pattern__", "(.+)") .. "$", "%1") + end + -- in order to be compatible with mingw/windows library with .lib + if count == 0 and opt.plat == "mingw" then + linkname, count = filename:gsub(target.filename("__pattern__", "static", {plat = "windows"}):gsub("%.", "%%."):gsub("__pattern__", "(.+)") .. "$", "%1") end return count > 0 and linkname or nil end diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_library.lua b/xmake/core/sandbox/modules/import/lib/detect/find_library.lua index 0b783538c..4fb2618d3 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/find_library.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/find_library.lua @@ -38,7 +38,7 @@ local find_file = import("lib.detect.find_file") -- @param paths the search paths -- @param opt the options, e.g. {kind = "static/shared", suffixes = {"/aa", "/bb"}} -- --- @return {kind = "static", link = "crypto", linkdir = "/usr/local/lib", filename = "libcrypto.a"} +-- @return {kind = "static", link = "crypto", linkdir = "/usr/local/lib", filename = "libcrypto.a", plat = ..} -- -- @code -- @@ -54,23 +54,26 @@ function sandbox_lib_detect_find_library.main(names, paths, opt) return end - -- init options + -- find library file from the given paths opt = opt or {} - - -- init kinds local kinds = opt.kind or {"static", "shared"} - - -- find library file from the given paths for _, name in ipairs(table.wrap(names)) do for _, kind in ipairs(table.wrap(kinds)) do - local filepath = find_file(target.filename(name, kind), paths, opt) - if not filepath and kind == "shared" then - -- for implib/mingw, e.g. libxxx.dll.a - filepath = find_file(target.filename(name, kind) .. ".a", paths, opt) + local filepath = find_file(target.filename(name, kind, {plat = opt.plat}), paths, opt) + if opt.plat == "mingw" then + if not filepath and kind == "shared" then + -- for implib/mingw, e.g. libxxx.dll.a + filepath = find_file(target.filename(name, kind, {plat = opt.plat}) .. ".a", paths, opt) + end + if not filepath then + -- in order to be compatible with mingw/windows library with .lib + filepath = find_file(target.filename(name, kind, {plat = "windows"}), paths, opt) + end end if filepath then local filename = path.filename(filepath) - return {kind = kind, filename = filename, linkdir = path.directory(filepath), link = target.linkname(filename)} + local linkname = target.linkname(filename, {plat = opt.plat}) + return {kind = kind, filename = filename, linkdir = path.directory(filepath), link = linkname} end end end diff --git a/xmake/modules/package/manager/pkgconfig/find_package.lua b/xmake/modules/package/manager/pkgconfig/find_package.lua index a7dbf377a..ddc7efeb4 100644 --- a/xmake/modules/package/manager/pkgconfig/find_package.lua +++ b/xmake/modules/package/manager/pkgconfig/find_package.lua @@ -20,7 +20,6 @@ -- imports import("lib.detect.pkgconfig") -import("lib.detect.find_library") import("package.manager.system.find_package", {alias = "find_package_from_system"}) -- find package from the pkg-config package manager diff --git a/xmake/modules/package/manager/system/find_package.lua b/xmake/modules/package/manager/system/find_package.lua index 9bb04566d..692241309 100644 --- a/xmake/modules/package/manager/system/find_package.lua +++ b/xmake/modules/package/manager/system/find_package.lua @@ -60,7 +60,7 @@ function _find_package_from_unixdirs(name, links, opt) -- find library local result = nil for _, link in ipairs(links) do - local libinfo = find_library(link, linkdirs) + local libinfo = find_library(link, linkdirs, {plat = opt.plat}) if libinfo then result = result or {} result.links = table.join(result.links or {}, libinfo.link) diff --git a/xmake/modules/package/manager/vcpkg/find_package.lua b/xmake/modules/package/manager/vcpkg/find_package.lua index e965ace73..56ac15d23 100644 --- a/xmake/modules/package/manager/vcpkg/find_package.lua +++ b/xmake/modules/package/manager/vcpkg/find_package.lua @@ -20,7 +20,6 @@ -- imports import("lib.detect.find_file") -import("lib.detect.find_library") import("lib.detect.find_tool") import("core.base.option") import("core.project.config") diff --git a/xmake/modules/package/manager/xmake/find_package.lua b/xmake/modules/package/manager/xmake/find_package.lua index 0b043cc2f..379e29cbe 100644 --- a/xmake/modules/package/manager/xmake/find_package.lua +++ b/xmake/modules/package/manager/xmake/find_package.lua @@ -124,7 +124,7 @@ function _find_package_from_repo(name, opt) -- find library for _, link in ipairs(links) do - local libinfo = find_library(link, linkdirs) + local libinfo = find_library(link, linkdirs, {plat = opt.plat}) if libinfo then if libinfo.kind == "shared" then result.shared = true @@ -241,7 +241,7 @@ function _find_package_from_packagedirs(name, opt) -- find library local result = nil for _, link in ipairs(packageinfo:get("links")) do - local libinfo = find_library(link, linkdirs) + local libinfo = find_library(link, linkdirs, {plat = opt.plat}) if libinfo then result = result or {} result.links = table.join(result.links or {}, libinfo.link) -- cgit v1.3.1 From 8e41cd06d4f77d7a3f8544be7d719ea399412d93 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 16 Sep 2021 23:54:41 +0800 Subject: fix find_package again --- .../package/toolchain_muslcc/xmake-requires.lock | 246 ++++++++++++--------- .../sandbox/modules/import/core/project/target.lua | 8 +- xmake/modules/package/manager/apt/find_package.lua | 2 +- .../modules/package/manager/brew/find_package.lua | 4 +- .../modules/package/manager/conda/find_package.lua | 2 +- xmake/modules/package/manager/dub/find_package.lua | 2 +- .../modules/package/manager/vcpkg/find_package.lua | 2 +- .../modules/package/manager/xmake/find_package.lua | 4 +- 8 files changed, 156 insertions(+), 114 deletions(-) diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock index 4adae3fbb..9b6e40634 100644 --- a/tests/projects/package/toolchain_muslcc/xmake-requires.lock +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -1,103 +1,145 @@ -{ - __meta__ = { - version = "1.0" - }, - ["macosx|x86_64"] = { - ["autoconf#31fecfc4"] = { - repo = { - branch = "master", - commit = "4498f11267de5112199152ab030ed139c985ad5a", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "2.71" - }, - ["automake#31fecfc4"] = { - repo = { - branch = "master", - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "1.16.4" - }, - ["cmake#31fecfc4"] = { - repo = { - branch = "master", - commit = "4498f11267de5112199152ab030ed139c985ad5a", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "3.21.0" - }, - ["gmp#31fecfc4"] = { - repo = { - branch = "master", - commit = "c1b4838c9b1e7a2c52d9bf1a9beafeaee7305e30", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "6.2.1" - }, - ["libisl 0.22#67114504"] = { - repo = { - branch = "master", - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "0.22" - }, - ["libogg#31fecfc4"] = { - repo = { - branch = "master", - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "v1.3.4" - }, - ["libplist#31fecfc4"] = { - repo = { - branch = "master", - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "2.2.0" - }, - ["libtool#31fecfc4"] = { - repo = { - branch = "master", - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "2.4.6" - }, - ["m4#31fecfc4"] = { - repo = { - branch = "master", - commit = "c1b4838c9b1e7a2c52d9bf1a9beafeaee7305e30", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "1.4.19" - }, - ["muslcc#31fecfc4"] = { - repo = { - branch = "master", - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "20210202" - }, - ["pkg-config#31fecfc4"] = { - repo = { - branch = "master", - commit = "c1b4838c9b1e7a2c52d9bf1a9beafeaee7305e30", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "0.29.2" - }, - ["zlib#31fecfc4"] = { - repo = { - branch = "master", - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "1.2.11" - } - } +{ + __meta__ = { + version = "1.0" + }, + ["macosx|x86_64"] = { + ["autoconf#31fecfc4"] = { + repo = { + branch = "master", + commit = "4498f11267de5112199152ab030ed139c985ad5a", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "2.71" + }, + ["automake#31fecfc4"] = { + repo = { + branch = "master", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "1.16.4" + }, + ["cmake#31fecfc4"] = { + repo = { + branch = "master", + commit = "4498f11267de5112199152ab030ed139c985ad5a", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "3.21.0" + }, + ["gmp#31fecfc4"] = { + repo = { + branch = "master", + commit = "c1b4838c9b1e7a2c52d9bf1a9beafeaee7305e30", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "6.2.1" + }, + ["libisl 0.22#67114504"] = { + repo = { + branch = "master", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "0.22" + }, + ["libogg#31fecfc4"] = { + repo = { + branch = "master", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "v1.3.4" + }, + ["libplist#31fecfc4"] = { + repo = { + branch = "master", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "2.2.0" + }, + ["libtool#31fecfc4"] = { + repo = { + branch = "master", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "2.4.6" + }, + ["m4#31fecfc4"] = { + repo = { + branch = "master", + commit = "c1b4838c9b1e7a2c52d9bf1a9beafeaee7305e30", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "1.4.19" + }, + ["muslcc#31fecfc4"] = { + repo = { + branch = "master", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "20210202" + }, + ["pkg-config#31fecfc4"] = { + repo = { + branch = "master", + commit = "c1b4838c9b1e7a2c52d9bf1a9beafeaee7305e30", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "0.29.2" + }, + ["zlib#31fecfc4"] = { + repo = { + branch = "master", + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "1.2.11" + } + }, + ["windows|x64"] = { + ["cmake#31fecfc4"] = { + repo = { + branch = "master", + commit = "8e8c5e4d1c7e8b047b23333594d23b4b85163aed", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "3.21.0" + }, + ["libogg#31fecfc4"] = { + repo = { + branch = "master", + commit = "2b1cb74b289ae3221241985db4401a495c42fde3", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "v1.3.4" + }, + ["make#31fecfc4"] = { + repo = { + branch = "master", + commit = "2b1cb74b289ae3221241985db4401a495c42fde3", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "4.3" + }, + ["muslcc#31fecfc4"] = { + repo = { + branch = "master", + commit = "2b1cb74b289ae3221241985db4401a495c42fde3", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "20210202" + }, + ["zlib#31fecfc4"] = { + repo = { + branch = "master", + commit = "2b1cb74b289ae3221241985db4401a495c42fde3", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "1.2.11" + } + } } \ No newline at end of file diff --git a/xmake/core/sandbox/modules/import/core/project/target.lua b/xmake/core/sandbox/modules/import/core/project/target.lua index 205d15d61..07424cad3 100644 --- a/xmake/core/sandbox/modules/import/core/project/target.lua +++ b/xmake/core/sandbox/modules/import/core/project/target.lua @@ -26,13 +26,13 @@ local target = require("project/target") local raise = require("sandbox/modules/raise") -- get the filename from the given name and kind -function sandbox_core_project_target.filename(name, kind) - return target.filename(name, kind) +function sandbox_core_project_target.filename(name, kind, opt) + return target.filename(name, kind, opt) end -- get the link name of the target file -function sandbox_core_project_target.linkname(filename) - return target.linkname(filename) +function sandbox_core_project_target.linkname(filename, opt) + return target.linkname(filename, opt) end -- return module diff --git a/xmake/modules/package/manager/apt/find_package.lua b/xmake/modules/package/manager/apt/find_package.lua index f27968c0e..3fee1034f 100644 --- a/xmake/modules/package/manager/apt/find_package.lua +++ b/xmake/modules/package/manager/apt/find_package.lua @@ -67,7 +67,7 @@ function main(name, opt) result.linkdirs = result.linkdirs or {} result.libfiles = result.libfiles or {} table.insert(result.linkdirs, path.directory(line)) - table.insert(result.links, target.linkname(path.filename(line))) + table.insert(result.links, target.linkname(path.filename(line), {plat = opt.plat})) table.insert(result.libfiles, path.join(path.directory(line), path.filename(line))) end end diff --git a/xmake/modules/package/manager/brew/find_package.lua b/xmake/modules/package/manager/brew/find_package.lua index 49db5a464..d5f679f7a 100644 --- a/xmake/modules/package/manager/brew/find_package.lua +++ b/xmake/modules/package/manager/brew/find_package.lua @@ -97,11 +97,11 @@ function main(name, opt) if pkgdir then local links = {} for _, libfile in ipairs(os.files(path.join(pkgdir, "lib", "*.a"))) do - table.insert(links, target.linkname(path.filename(libfile))) + table.insert(links, target.linkname(path.filename(libfile), {plat = opt.plat})) end for _, libfile in ipairs(os.files(path.join(pkgdir, "lib", opt.plat == "macosx" and "*.dylib" or "*.so"))) do if not os.islink(libfile) then - table.insert(links, target.linkname(path.filename(libfile))) + table.insert(links, target.linkname(path.filename(libfile), {plat = opt.plat})) end end opt.links = links diff --git a/xmake/modules/package/manager/conda/find_package.lua b/xmake/modules/package/manager/conda/find_package.lua index 5d2634d63..747e1bc9b 100644 --- a/xmake/modules/package/manager/conda/find_package.lua +++ b/xmake/modules/package/manager/conda/find_package.lua @@ -124,7 +124,7 @@ function main(name, opt) result.linkdirs = result.linkdirs or {} result.libfiles = result.libfiles or {} table.insert(result.linkdirs, path.join(packagedir, path.directory(line))) - table.insert(result.links, target.linkname(path.filename(line))) + table.insert(result.links, target.linkname(path.filename(line), {plat = opt.plat})) table.insert(result.libfiles, path.join(packagedir, path.directory(line), path.filename(line))) end diff --git a/xmake/modules/package/manager/dub/find_package.lua b/xmake/modules/package/manager/dub/find_package.lua index 55ad2d6ef..8543a8bfb 100644 --- a/xmake/modules/package/manager/dub/find_package.lua +++ b/xmake/modules/package/manager/dub/find_package.lua @@ -67,7 +67,7 @@ function main(name, opt) if pkgdir then local links = {} for _, libraryfile in ipairs(os.files(path.join(pkgdir, libpattern))) do - table.insert(links, target.linkname(path.filename(libraryfile))) + table.insert(links, target.linkname(path.filename(libraryfile), {plat = opt.plat})) end local includedirs = {} local dubjson = path.join(pkgdir, "dub.json") diff --git a/xmake/modules/package/manager/vcpkg/find_package.lua b/xmake/modules/package/manager/vcpkg/find_package.lua index 56ac15d23..8bb4de8e8 100644 --- a/xmake/modules/package/manager/vcpkg/find_package.lua +++ b/xmake/modules/package/manager/vcpkg/find_package.lua @@ -116,7 +116,7 @@ function main(name, opt) result.linkdirs = result.linkdirs or {} result.libfiles = result.libfiles or {} table.insert(result.linkdirs, path.join(installdir, path.directory(line))) - table.insert(result.links, target.linkname(path.filename(line))) + table.insert(result.links, target.linkname(path.filename(line), {plat = plat})) table.insert(result.libfiles, path.join(installdir, path.directory(line), path.filename(line))) end end diff --git a/xmake/modules/package/manager/xmake/find_package.lua b/xmake/modules/package/manager/xmake/find_package.lua index 379e29cbe..c594c8135 100644 --- a/xmake/modules/package/manager/xmake/find_package.lua +++ b/xmake/modules/package/manager/xmake/find_package.lua @@ -82,14 +82,14 @@ function _find_package_from_repo(name, opt) for _, file in ipairs(os.files(path.join(installdir, libdir, "*"))) do if file:endswith(".lib") or file:endswith(".a") then found = true - table.insert(links, target.linkname(path.filename(file))) + table.insert(links, target.linkname(path.filename(file), {plat = opt.plat})) table.insert(libfiles, file) end end if not found then for _, file in ipairs(os.files(path.join(installdir, "lib", "*"))) do if file:endswith(".so") or file:match(".+%.so%..+$") or file:endswith(".dylib") then -- maybe symlink to libxxx.so.1 - table.insert(links, target.linkname(path.filename(file))) + table.insert(links, target.linkname(path.filename(file), {plat = opt.plat})) table.insert(libfiles, file) end end -- cgit v1.3.1 From 620ed4992ba78c11620e18591dcab85acc7bd600 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 17 Sep 2021 00:41:54 +0800 Subject: fix precompile path --- .../action/require/impl/actions/install.lua | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/xmake/modules/private/action/require/impl/actions/install.lua b/xmake/modules/private/action/require/impl/actions/install.lua index e733cebfd..b6dad65d2 100644 --- a/xmake/modules/private/action/require/impl/actions/install.lua +++ b/xmake/modules/private/action/require/impl/actions/install.lua @@ -91,6 +91,33 @@ function _patch_pkgconfig(package) end end +-- fix paths for the precompiled package +-- @see https://github.com/xmake-io/xmake/issues/1671 +function _fix_paths_for_precompiled_package(package) + local librarydir = package:installdir("lib") + local filepaths = {path.join(librarydir, "cmake", "*", "*.cmake")} + for _, filepath in ipairs(filepaths) do + for _, file in ipairs(os.files(filepath)) do + io.gsub(file, "(\"(.-)\")", function(_, value) + if value:find(package:buildhash(), 1, true) and value:find(package:name(), 1, true) then + local result + local splitinfo = value:split(package:buildhash(), {plain = true}) + if #splitinfo == 2 then + result = path.join(package:installdir(), splitinfo[2]) + elseif #splitinfo == 1 then + result = package:installdir() + end + if result then + result = result:gsub("\\", "/") + vprint("fix path: %s in %s", result, path.filename(file)) + return "\"" .. result .. "\"" + end + end + end) + end + end +end + -- check package toolchains function _check_package_toolchains(package) for _, toolchain_inst in pairs(package:toolchains()) do @@ -196,6 +223,11 @@ function main(package) -- this package is installed now if installed_now then + -- fix paths for the precompiled package + if package:is_plat("windows") and not package:is_built() and not package:is_system() then + _fix_paths_for_precompiled_package(package) + end + -- patch pkg-config files for package _patch_pkgconfig(package) -- cgit v1.3.1 From 2d39ad73d84268bcae06847ea822df2339f1054f Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 17 Sep 2021 22:42:40 +0800 Subject: update changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42294dd51..2c6033477 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,11 @@ * Improve `set_symbols("debug")` to generate pdb file for clang on windows * [#1638](https://github.com/xmake-io/xmake/issues/1638): Improve to merge static library * Improve on_load/after_load to support to add target deps dynamically +* [#1675](https://github.com/xmake-io/xmake/pull/1675): Rename dynamic and import library suffix for mingw + +### Bugs fixed + +* [#1671](https://github.com/xmake-io/xmake/issues/1671): Fix incorrect absolute path after installing precompiled packages ## v2.5.7 @@ -1083,6 +1088,11 @@ * 改进 `set_symbols("debug")` 支持 clang/windows 生成 pdb 文件 * [#1638](https://github.com/xmake-io/xmake/issues/1638): 改进合并静态库 * 改进 on_load/after_load 去支持动态的添加 target deps +* [#1675](https://github.com/xmake-io/xmake/pull/1675): 针对 mingw 平台,重命名动态库和导入库文件名后缀 + +### Bugs 修复 + +* [#1671](https://github.com/xmake-io/xmake/issues/1671): 修复安装预编译包后,*.cmake 里面的一些不正确的绝对路径 ## v2.5.7 -- cgit v1.3.1 From 4f2a99c4954906721bee469a5a36e448752f4cc6 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 17 Sep 2021 22:59:27 +0800 Subject: add deprecated before_load in rule --- xmake/core/project/project.lua | 6 ++++++ xmake/core/project/rule.lua | 1 + xmake/core/project/target.lua | 15 +++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 411845056..f832305ca 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -431,6 +431,12 @@ function project._load_targets() end end + -- @note it's deprecated, please use on_load instead of before_load + ok, errors = t:_load_before() + if not ok then + return nil, nil, errors + end + -- we need call on_load() before building deps/rules, -- so we can use `target:add("deps", "xxx")` to add deps in on_load ok, errors = t:_load() diff --git a/xmake/core/project/rule.lua b/xmake/core/project/rule.lua index 534bb5f8a..c155a813f 100644 --- a/xmake/core/project/rule.lua +++ b/xmake/core/project/rule.lua @@ -180,6 +180,7 @@ function rule.apis() , "rule.on_buildcmd_files" -- rule.before_xxx , "rule.before_run" + , "rule.before_load" , "rule.before_link" , "rule.before_build" , "rule.before_build_file" diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 7b0ce47d9..5cb7d32b9 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -82,6 +82,11 @@ function _instance:_load_rule(ruleinst, suffix) else cache[key] = {true} end + + -- before_load has been deprecated + if on_load and suffix == "before" then + deprecated.add(ruleinst:name() .. ".on_load", ruleinst:name() .. ".before_load") + end end -- save cache @@ -128,6 +133,16 @@ function _instance:_load() return true end +-- do before_load for rules +-- @note it's deprecated, please use on_load instead of before_load +function _instance:_load_before() + local ok, errors = self:_load_rules("before") + if not ok then + return false, errors + end + return true +end + -- do after_load target and rules function _instance:_load_after() -- cgit v1.3.1 From 1e44c983254c68ebb6eb93b865816b13e18aa68f Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 17 Sep 2021 17:02:18 +0800 Subject: Update install.lua --- xmake/modules/private/action/require/impl/actions/install.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/xmake/modules/private/action/require/impl/actions/install.lua b/xmake/modules/private/action/require/impl/actions/install.lua index b6dad65d2..fe040d25e 100644 --- a/xmake/modules/private/action/require/impl/actions/install.lua +++ b/xmake/modules/private/action/require/impl/actions/install.lua @@ -94,8 +94,7 @@ end -- fix paths for the precompiled package -- @see https://github.com/xmake-io/xmake/issues/1671 function _fix_paths_for_precompiled_package(package) - local librarydir = package:installdir("lib") - local filepaths = {path.join(librarydir, "cmake", "*", "*.cmake")} + local filepaths = {path.join(package:installdir(), "**.cmake")} for _, filepath in ipairs(filepaths) do for _, file in ipairs(os.files(filepath)) do io.gsub(file, "(\"(.-)\")", function(_, value) -- cgit v1.3.1 From 0108980f36b996d575a87c59ead44da8fd059490 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 17 Sep 2021 17:39:42 +0800 Subject: Update install.lua --- xmake/modules/private/action/require/impl/actions/install.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/private/action/require/impl/actions/install.lua b/xmake/modules/private/action/require/impl/actions/install.lua index fe040d25e..8e8d92d39 100644 --- a/xmake/modules/private/action/require/impl/actions/install.lua +++ b/xmake/modules/private/action/require/impl/actions/install.lua @@ -94,7 +94,7 @@ end -- fix paths for the precompiled package -- @see https://github.com/xmake-io/xmake/issues/1671 function _fix_paths_for_precompiled_package(package) - local filepaths = {path.join(package:installdir(), "**.cmake")} + local filepaths = {path.join(package:installdir(), "**.cmake|include/**")} for _, filepath in ipairs(filepaths) do for _, file in ipairs(os.files(filepath)) do io.gsub(file, "(\"(.-)\")", function(_, value) -- cgit v1.3.1 From 4d8c00eecd99b0f65f40befd36bb2945df9996a7 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 00:38:14 +0800 Subject: add lua module --- .gitmodules | 3 +++ core/src/lua/lua | 1 + 2 files changed, 4 insertions(+) create mode 160000 core/src/lua/lua diff --git a/.gitmodules b/.gitmodules index ac5f4dde3..4e2703e2b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "core/src/lua-cjson/lua-cjson"] path = core/src/lua-cjson/lua-cjson url = ../../xmake-io/xmake-core-lua-cjson.git +[submodule "core/src/lua/lua"] + path = core/src/lua/lua + url = ../../xmake-io/xmake-core-lua.git diff --git a/core/src/lua/lua b/core/src/lua/lua new file mode 160000 index 000000000..75ea9ccbe --- /dev/null +++ b/core/src/lua/lua @@ -0,0 +1 @@ +Subproject commit 75ea9ccbea7c4886f30da147fb67b693b2624c26 -- cgit v1.3.1 From b58700f83ee4e40582b03f5fdfe337788b9f2c6f Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 00:44:52 +0800 Subject: update makefile --- core/makefile | 5 ++++ core/project.mak | 2 +- core/src/lcurses/makefile | 7 +++++- core/src/lua/makefile | 58 +++++++++++++++++++++++++++++++++++++++++++++++ core/src/makefile | 10 ++++++-- core/src/xmake/makefile | 7 +++++- makefile | 7 +++++- 7 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 core/src/lua/makefile diff --git a/core/makefile b/core/makefile index 0bba754cd..d7c529489 100644 --- a/core/makefile +++ b/core/makefile @@ -368,6 +368,7 @@ config : .null @$(ECHO) "directories:" @$(ECHO) " install:\t\t"$(abspath $(INSTALL)) @$(ECHO) " package:\t\t"$(PACKAGE) + @$(ECHO) " backend:\t\t"$(BACKEND) @$(ECHO) "" @$(ECHO) "toolchains:" @$(ECHO) " bin:\t\t"$(BIN) @@ -459,6 +460,10 @@ config : .null @$(ECHO) "export MIPS" >> .config.mak @$(ECHO) "export SPARC" >> .config.mak @$(ECHO) "" >> .config.mak + @$(ECHO) "# backend" >> .config.mak + @$(ECHO) "BACKEND ="$(BACKEND) >> .config.mak + @$(ECHO) "export BACKEND" >> .config.mak + @$(ECHO) "" >> .config.mak @$(ECHO) "# demo" >> .config.mak @$(ECHO) "DEMO ="$(DEMO) >> .config.mak @$(ECHO) "export DEMO" >> .config.mak diff --git a/core/project.mak b/core/project.mak index 041121fea..adf613ef2 100644 --- a/core/project.mak +++ b/core/project.mak @@ -16,5 +16,5 @@ PRO_VERSION_ALTER = 7 PRO_PREFIX = XM_ # the package names -PKG_NAMES = tbox luajit base +PKG_NAMES = tbox luajit lua base diff --git a/core/src/lcurses/makefile b/core/src/lcurses/makefile index 25752ab47..b981765a7 100644 --- a/core/src/lcurses/makefile +++ b/core/src/lcurses/makefile @@ -17,7 +17,12 @@ lcurses_C_FILES += lcurses lcurses_CXFLAGS += $(if $(findstring curses,$(base_LIBNAMES)),-DXM_CONFIG_API_HAVE_CURSES,) # includes -lcurses_INC_DIRS += ../luajit/luajit/src +ifeq ($(BACKEND),luajit) +lcurses_INC_DIRS += ../luajit/luajit/src +endif +ifeq ($(BACKEND),lua) +lcurses_INC_DIRS += ../lua/lua +endif # suffix include $(PRO_DIR)/suffix.mak diff --git a/core/src/lua/makefile b/core/src/lua/makefile new file mode 100644 index 000000000..d2314c846 --- /dev/null +++ b/core/src/lua/makefile @@ -0,0 +1,58 @@ +# prefix +include $(PRO_DIR)/prefix.mak + +# module name +NAMES = lua + +# module type +lua_TYPE = LIB + +# config +lua_CONFIG = n + +# core files +lua_C_FILES += \ + lua/lauxlib \ + lua/liolib \ + lua/lopcodes \ + lua/lstate \ + lua/lobject \ + lua/lmathlib \ + lua/loadlib \ + lua/lvm \ + lua/lfunc \ + lua/lstrlib \ + lua/linit \ + lua/lstring \ + lua/lundump \ + lua/lctype \ + lua/ltable \ + lua/ldump \ + lua/loslib \ + lua/lgc \ + lua/lzio \ + lua/ldblib \ + lua/lutf8lib \ + lua/lmem \ + lua/lcorolib \ + lua/lcode \ + lua/ltablib \ + lua/lbitlib \ + lua/lapi \ + lua/lbaselib \ + lua/ldebug \ + lua/lparser \ + lua/llex \ + lua/ltm \ + lua/ltests \ + lua/ldo + +# use given system library? +lua_C_FILES := $(if $(findstring lua,$(base_LIBNAMES)),,$(lua_C_FILES)) +lua_ASM_FILES := $(if $(findstring lua,$(base_LIBNAMES)),,$(lua_ASM_FILES)) +lua_INC_FILES := $(if $(findstring lua,$(base_LIBNAMES)),,$(lua_INC_FILES)) +lua_OBJ_FILES := $(if $(findstring lua,$(base_LIBNAMES)),,$(lua_OBJ_FILES)) + +# suffix +include $(PRO_DIR)/suffix.mak + diff --git a/core/src/makefile b/core/src/makefile index 21a06ed5a..47151258e 100644 --- a/core/src/makefile +++ b/core/src/makefile @@ -2,8 +2,14 @@ include $(PRO_DIR)/prefix.mak # projects -SUB_PROS += demo -DEP_PROS += lcurses sv luajit lua-cjson tbox xmake +SUB_PROS += demo +ifeq ($(BACKEND),luajit) +DEP_PROS += luajit +endif +ifeq ($(BACKEND),lua) +DEP_PROS += lua +endif +DEP_PROS += lcurses sv lua-cjson tbox xmake # suffix include $(PRO_DIR)/suffix.mak diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index 2c45588b4..84f3044b2 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -149,8 +149,13 @@ xmake_CXFLAGS += $(if $(findstring curses,$(base_LIBNAMES)),-DXM_CONFIG xmake_INC_DIRS += \ ../tbox/tbox/src \ ../tbox/inc/$(PLAT) \ - ../luajit/luajit/src \ ../sv/sv/include +ifeq ($(BACKEND),luajit) +xmake_INC_DIRS += ../luajit/luajit/src +endif +ifeq ($(BACKEND),lua) +xmake_INC_DIRS += ../lua/lua +endif # suffix diff --git a/makefile b/makefile index cc7c61ba1..c22bc30cb 100644 --- a/makefile +++ b/makefile @@ -15,6 +15,11 @@ prefix :=$(PREFIX) endif endif +# use luajit or lua backend +ifeq ($(BACKEND),) +BACKEND :=luajit +endif + # the temporary directory ifeq ($(TMPDIR),) TMP_DIR :=$(if $(TMP_DIR),$(TMP_DIR),/tmp) @@ -94,7 +99,7 @@ xrepo_bin_install :=$(destdir)/bin/xrepo build: @echo compiling xmake-core ... @if [ -f core/.config.mak ]; then rm core/.config.mak; fi - +@$(MAKE) -C core --no-print-directory f DEBUG=$(debug) + +@$(MAKE) -C core --no-print-directory f DEBUG=$(debug) BACKEND=$(BACKEND) +@$(MAKE) -C core --no-print-directory c +@$(MAKE) -C core --no-print-directory -- cgit v1.3.1 From 80d619eab58df20b316b49c9db3616e9599da07b Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 00:48:29 +0800 Subject: improve makefile --- core/src/lcurses/lcurses.c | 6 ++++++ core/src/lcurses/makefile | 2 ++ core/src/lua/makefile | 23 +++++++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/core/src/lcurses/lcurses.c b/core/src/lcurses/lcurses.c index 934dc2d1d..606a06cc3 100644 --- a/core/src/lcurses/lcurses.c +++ b/core/src/lcurses/lcurses.c @@ -65,9 +65,15 @@ Notes: #include #include +#ifdef USE_LUAJIT #include "luajit.h" #include "lualib.h" #include "lauxlib.h" +#else +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +#endif #include #include diff --git a/core/src/lcurses/makefile b/core/src/lcurses/makefile index b981765a7..a0d6a6400 100644 --- a/core/src/lcurses/makefile +++ b/core/src/lcurses/makefile @@ -19,9 +19,11 @@ lcurses_CXFLAGS += $(if $(findstring curses,$(base_LIBNAMES)),-DXM_CONFIG_API_ # includes ifeq ($(BACKEND),luajit) lcurses_INC_DIRS += ../luajit/luajit/src +lcurses_CXFLAGS += -DUSE_LUAJIT endif ifeq ($(BACKEND),lua) lcurses_INC_DIRS += ../lua/lua +lcurses_CXFLAGS += -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 endif # suffix diff --git a/core/src/lua/makefile b/core/src/lua/makefile index d2314c846..f66181209 100644 --- a/core/src/lua/makefile +++ b/core/src/lua/makefile @@ -47,6 +47,29 @@ lua_C_FILES += \ lua/ltests \ lua/ldo +# is windows? +iswin = +ifeq ($(PLAT),windows) + iswin = yes +endif +ifeq ($(PLAT),msys) + iswin = yes +endif +ifeq ($(PLAT),mingw) + iswin = yes +endif +ifeq ($(PLAT),cygwin) + iswin = yes +endif + +lua_CFLAGS := -std=c99 -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 \ + -Wno-error=string-plus-int +ifdef iswin +lua_CFLAGS += -DLUA_USE_WINDOWS +else +lua_CFLAGS += -DLUA_USE_LINUX +endif + # use given system library? lua_C_FILES := $(if $(findstring lua,$(base_LIBNAMES)),,$(lua_C_FILES)) lua_ASM_FILES := $(if $(findstring lua,$(base_LIBNAMES)),,$(lua_ASM_FILES)) -- cgit v1.3.1 From 56393682b43020adcff47de00fe7a011ba5f1584 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 00:49:14 +0800 Subject: improve lcurses --- core/src/lcurses/lcurses.c | 4 ++++ core/src/xmake/makefile | 2 ++ core/src/xmake/prefix.h | 12 +++++++++--- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/core/src/lcurses/lcurses.c b/core/src/lcurses/lcurses.c index 606a06cc3..f3bdf7244 100644 --- a/core/src/lcurses/lcurses.c +++ b/core/src/lcurses/lcurses.c @@ -336,7 +336,11 @@ static chtype lc_checkch(lua_State *L, int index) if (lua_type(L, index) == LUA_TSTRING) return *lua_tostring(L, index); +#ifdef USE_LUAJIT luaL_typerror(L, index, "chtype"); +#else + // TODO +#endif /* never executes */ return (chtype)0; } diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index 84f3044b2..20bc49d82 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -152,9 +152,11 @@ xmake_INC_DIRS += \ ../sv/sv/include ifeq ($(BACKEND),luajit) xmake_INC_DIRS += ../luajit/luajit/src +xmake_CXFLAGS += -DUSE_LUAJIT endif ifeq ($(BACKEND),lua) xmake_INC_DIRS += ../lua/lua +xmake_CXFLAGS += -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 endif diff --git a/core/src/xmake/prefix.h b/core/src/xmake/prefix.h index f1287b5c9..f78b61127 100644 --- a/core/src/xmake/prefix.h +++ b/core/src/xmake/prefix.h @@ -32,9 +32,15 @@ # define LUA_API extern "C" # define LUALIB_API LUA_API #endif -#include "luajit.h" -#include "lualib.h" -#include "lauxlib.h" +#ifdef USE_LUAJIT +# include "luajit.h" +# include "lualib.h" +# include "lauxlib.h" +#else +# include "lua.h" +# include "lualib.h" +# include "lauxlib.h" +#endif /* ////////////////////////////////////////////////////////////////////////////////////// * private interfaces -- cgit v1.3.1 From eb826246511e2afca394302aecccdf18d02a297f Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 00:53:16 +0800 Subject: fix compile for lua --- core/src/demo/makefile | 10 ++++++++++ core/src/lua-cjson/makefile | 10 ++++++++-- core/src/xmake/engine.c | 2 +- core/src/xmake/sandbox/interactive.c | 5 +++++ 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/core/src/demo/makefile b/core/src/demo/makefile index 1a2142db5..93525ddaf 100644 --- a/core/src/demo/makefile +++ b/core/src/demo/makefile @@ -20,10 +20,20 @@ demo_INC_DIRS += ../ ../tbox/tbox/src ../tbox/inc/$(PLAT) demo_LIB_DIRS += ../tbox # luajit +ifeq ($(BACKEND),luajit) luajit_LIBS := $(if $(findstring luajit,$(base_LIBNAMES)),,luajit$(DTYPE)) demo_LIBS += $(luajit_LIBS) demo_INC_DIRS += ../luajit/luajit/src demo_LIB_DIRS += ../luajit +endif + +# lua +ifeq ($(BACKEND),lua) +lua_LIBS := $(if $(findstring lua,$(base_LIBNAMES)),,lua$(DTYPE)) +demo_LIBS += $(lua_LIBS) +demo_INC_DIRS += ../lua/lua +demo_LIB_DIRS += ../lua +endif # sv sv_DTYPE := $(if $(findstring sv,$(base_LIBNAMES)),,$(DTYPE)) diff --git a/core/src/lua-cjson/makefile b/core/src/lua-cjson/makefile index 9e96851ae..e1d53ecf9 100644 --- a/core/src/lua-cjson/makefile +++ b/core/src/lua-cjson/makefile @@ -22,8 +22,14 @@ lua-cjson_C_FILES += \ lua-cjson_CFLAGS += -DNDEBUG -DUSE_INTERNAL_FPCONV # includes -lua-cjson_INC_DIRS += \ - ../luajit/luajit/src +ifeq ($(BACKEND),luajit) +lua-cjson_INC_DIRS += ../luajit/luajit/src +lua-cjson_CXFLAGS += -DUSE_LUAJIT +endif +ifeq ($(BACKEND),lua) +lua-cjson_INC_DIRS += ../lua/lua +lua-cjson_CXFLAGS += -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 +endif # use given system library? lua-cjson_C_FILES := $(if $(findstring cjson,$(base_LIBNAMES)),,$(lua-cjson_C_FILES)) diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index 6a401a486..53732e783 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -814,7 +814,7 @@ xm_engine_ref_t xm_engine_init(tb_char_t const* name, xm_engine_lni_initalizer_c tb_strlcpy(engine->name, name, sizeof(engine->name)); // init lua - engine->lua = lua_open(); + engine->lua = luaL_newstate(); tb_assert_and_check_break(engine->lua); // open lua libraries diff --git a/core/src/xmake/sandbox/interactive.c b/core/src/xmake/sandbox/interactive.c index 2519a58e8..29855aec6 100644 --- a/core/src/xmake/sandbox/interactive.c +++ b/core/src/xmake/sandbox/interactive.c @@ -314,6 +314,7 @@ tb_int_t xm_sandbox_interactive(lua_State* lua) // execute codes if (status == 0) { +#ifdef USE_LUAJIT /* bind sandbox * * stack: arg1(top) scriptfunc arg1(sandbox_scope) -> ... @@ -326,6 +327,10 @@ tb_int_t xm_sandbox_interactive(lua_State* lua) * stack: arg1(top) scriptfunc -> ... */ status = xm_sandbox_docall(lua, 0, 0); +#else + // TODO + (void)xm_sandbox_docall; +#endif } // report errors -- cgit v1.3.1 From 6f0f25b64487a32989cb718aa50d9bc729f46d66 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 09:51:33 +0800 Subject: build lua for windows --- core/src/lcurses/xmake.lua | 2 +- core/src/lua-cjson/xmake.lua | 2 +- core/src/lua/makefile | 4 ++++ core/src/lua/xmake.lua | 31 +++++++++++++++++++++++++++++++ core/src/luajit/xmake.lua | 5 +++++ core/src/xmake/sandbox/interactive.c | 5 ++--- core/src/xmake/xmake.lua | 3 ++- core/xmake.lua | 10 +++++++++- 8 files changed, 55 insertions(+), 7 deletions(-) create mode 100644 core/src/lua/xmake.lua diff --git a/core/src/lcurses/xmake.lua b/core/src/lcurses/xmake.lua index f80117f10..5ee8a26c6 100644 --- a/core/src/lcurses/xmake.lua +++ b/core/src/lcurses/xmake.lua @@ -1,6 +1,6 @@ target("lcurses") set_kind("static") - add_deps("luajit") + add_deps(get_config("backend")) if is_plat("windows") and has_config("pdcurses") then add_deps("pdcurses") add_defines("XM_CONFIG_API_HAVE_CURSES", {public = true}) diff --git a/core/src/lua-cjson/xmake.lua b/core/src/lua-cjson/xmake.lua index d2eec99f0..d3b12ded1 100644 --- a/core/src/lua-cjson/xmake.lua +++ b/core/src/lua-cjson/xmake.lua @@ -1,7 +1,7 @@ target("lua-cjson") set_kind("static") set_warnings("all") - add_deps("luajit") + add_deps(get_config("backend")) if is_plat("windows") then set_languages("c89") end diff --git a/core/src/lua/makefile b/core/src/lua/makefile index f66181209..85e8725cf 100644 --- a/core/src/lua/makefile +++ b/core/src/lua/makefile @@ -66,6 +66,10 @@ lua_CFLAGS := -std=c99 -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 \ -Wno-error=string-plus-int ifdef iswin lua_CFLAGS += -DLUA_USE_WINDOWS +endif + +ifeq ($(PLAT),macosx) +lua_CFLAGS += -DLUA_USE_MACOSX else lua_CFLAGS += -DLUA_USE_LINUX endif diff --git a/core/src/lua/xmake.lua b/core/src/lua/xmake.lua new file mode 100644 index 000000000..4f209b693 --- /dev/null +++ b/core/src/lua/xmake.lua @@ -0,0 +1,31 @@ +target("lua") + if not is_config("lua") then + set_default(false) + end + set_kind("static") + set_warnings("all") + + -- disable c99(/TP) for windows + if is_plat("windows") then + set_languages("c89") + end + + -- add header files + add_headerfiles("lua/(*.h)", {prefixdir = "lua"}) + + -- add include directories + add_includedirs("lua", {public = true}) + + -- add the common source files + add_files("lua/*.c|lua.c") + + -- add defines + add_defines("LUA_COMPAT_5_1", "LUA_COMPAT_5_2", {public = true}) + if is_plat("windows") then + add_defines("LUA_USE_WINDOWS") + elseif is_plat("macosx", "iphoneos") then + add_defines("LUA_USE_MACOSX") + else + add_defines("LUA_USE_LINUX") + end + diff --git a/core/src/luajit/xmake.lua b/core/src/luajit/xmake.lua index cfee1f76e..f6f351394 100644 --- a/core/src/luajit/xmake.lua +++ b/core/src/luajit/xmake.lua @@ -23,6 +23,9 @@ local autogendir = path.join("autogen", plat, jit and "jit" or "nojit", arch) -- add target target("luajit") + if not is_config("luajit") then + set_default(false) + end -- make as a static library set_kind("static") @@ -52,6 +55,8 @@ target("luajit") add_files(autogendir .. "/*.S") end + add_defines("USE_LUAJIT", {interface = true}) + -- disable jit compiler? if not jit then add_defines("LUAJIT_DISABLE_JIT") diff --git a/core/src/xmake/sandbox/interactive.c b/core/src/xmake/sandbox/interactive.c index 29855aec6..023759448 100644 --- a/core/src/xmake/sandbox/interactive.c +++ b/core/src/xmake/sandbox/interactive.c @@ -73,6 +73,7 @@ static tb_void_t xm_sandbox_report(lua_State *lua) } } +#ifdef USE_LUAJIT // the traceback function static tb_int_t xm_sandbox_traceback(lua_State *lua) { @@ -122,6 +123,7 @@ static tb_int_t xm_sandbox_docall(lua_State* lua, tb_int_t narg, tb_int_t clear) // ok? return status; } +#endif // this line is incomplete? static tb_int_t xm_sandbox_incomplete(lua_State *lua, tb_int_t status) @@ -327,9 +329,6 @@ tb_int_t xm_sandbox_interactive(lua_State* lua) * stack: arg1(top) scriptfunc -> ... */ status = xm_sandbox_docall(lua, 0, 0); -#else - // TODO - (void)xm_sandbox_docall; #endif } diff --git a/core/src/xmake/xmake.lua b/core/src/xmake/xmake.lua index 7a604301a..c954db65b 100644 --- a/core/src/xmake/xmake.lua +++ b/core/src/xmake/xmake.lua @@ -7,7 +7,8 @@ target("xmake") if has_config("curses") or has_config("pdcurses") then add_deps("lcurses") end - add_deps("sv", "luajit", "lua-cjson", "tbox") + add_deps("sv", "lua-cjson", "tbox") + add_deps(get_config("backend")) -- add defines add_defines("__tb_prefix__=\"xmake\"") diff --git a/core/xmake.lua b/core/xmake.lua index 9caedf7a9..592bc7c95 100644 --- a/core/xmake.lua +++ b/core/xmake.lua @@ -40,6 +40,14 @@ if is_mode("coverage") then add_ldflags("-coverage", "-fprofile-arcs", "-ftest-coverage") end +-- the backend option +option("backend") + set_showmenu(true) + set_default("luajit") + set_description("Use luajit or lua backend") + set_values("luajit", "lua") +option_end() + -- the readline option option("readline") set_showmenu(true) @@ -80,7 +88,7 @@ if is_plat("windows") then end -- add projects -includes("src/lua-cjson", "src/lcurses", "src/sv","src/luajit", "src/tbox", "src/xmake", "src/demo") +includes("src/lua-cjson", "src/lcurses", "src/sv","src/luajit", "src/lua", "src/tbox", "src/xmake", "src/demo") if is_plat("windows") then includes("src/pdcurses") end -- cgit v1.3.1 From 1b231d9a73299528f1e336d4038c120d5a4fd183 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 10:07:53 +0800 Subject: add xmake.luajit --- core/src/xmake/engine.c | 8 ++++++++ xmake/core/_xmake_main.lua | 1 + xmake/core/base/table.lua | 27 ++++++++++++++++++++++++--- xmake/core/base/xmake.lua | 5 +++++ xmake/core/sandbox/modules/xmake.lua | 1 + 5 files changed, 39 insertions(+), 3 deletions(-) diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index 53732e783..69aa1e452 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -892,6 +892,14 @@ xm_engine_ref_t xm_engine_init(tb_char_t const* name, xm_engine_lni_initalizer_c lua_pushstring(engine->lua, name? name : "xmake"); lua_setglobal(engine->lua, "_NAME"); + // use luajit as backend? +#ifdef USE_LUAJIT + lua_pushboolean(engine->lua, tb_true); +#else + lua_pushboolean(engine->lua, tb_false); +#endif + lua_setglobal(engine->lua, "_LUAJIT"); + // init namespace: xmake lua_newtable(engine->lua); lua_setglobal(engine->lua, "xmake"); diff --git a/xmake/core/_xmake_main.lua b/xmake/core/_xmake_main.lua index ec1492ca8..af9b51114 100644 --- a/xmake/core/_xmake_main.lua +++ b/xmake/core/_xmake_main.lua @@ -34,6 +34,7 @@ xmake._PROJECT_DIR = _PROJECT_DIR xmake._PROJECT_FILE = "xmake.lua" xmake._WORKING_DIR = os.curdir() xmake._FEATURES = _FEATURES +xmake._LUAJIT = _LUAJIT function _loadfile_impl(filepath, mode, opt) diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua index 01a6a4692..6709ada3a 100644 --- a/xmake/core/base/table.lua +++ b/xmake/core/base/table.lua @@ -21,9 +21,30 @@ -- define module: table local table = table or {} --- import jit function -table.clear = require("table.clear") -table.new = require("table.new") +-- clear table +if not table.clear then + if xmake._LUAJIT then + table.clear = require("table.clear") + else + function table.clear(t) + for k, v in pairs(t) do + t[k] = nil + end + end + end +end + +-- new table +if not table.new then + if xmake._LUAJIT then + table.new = require("table.new") + else + function table.new(narray, nhash) + -- TODO + return {} + end + end +end -- move values of table(a1) to table(a2) -- diff --git a/xmake/core/base/xmake.lua b/xmake/core/base/xmake.lua index 406b85b7e..239540a5a 100644 --- a/xmake/core/base/xmake.lua +++ b/xmake/core/base/xmake.lua @@ -47,5 +47,10 @@ function xmake.programfile() return xmake._PROGRAM_FILE end +-- use luajit? +function xmake.luajit() + return xmake._LUAJIT +end + -- return module: xmake return xmake diff --git a/xmake/core/sandbox/modules/xmake.lua b/xmake/core/sandbox/modules/xmake.lua index 414258198..fcc6437e1 100644 --- a/xmake/core/sandbox/modules/xmake.lua +++ b/xmake/core/sandbox/modules/xmake.lua @@ -28,6 +28,7 @@ local sandbox_xmake = sandbox_xmake or {} sandbox_xmake.version = xmake.version sandbox_xmake.programdir = xmake.programdir sandbox_xmake.programfile = xmake.programfile +sandbox_xmake.luajit = xmake.luajit -- return module return sandbox_xmake -- cgit v1.3.1 From aeeeca0fb547b157501045c0ddd44b0258619a2b Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 10:18:22 +0800 Subject: add common bit module --- xmake/core/base/bit.lua | 48 +++++++++++++++++++++++++++++++++++++++++++ xmake/core/base/scheduler.lua | 2 +- xmake/core/base/string.lua | 2 +- xmake/core/project/target.lua | 2 +- xmake/core/ui/label.lua | 2 +- xmake/core/ui/textedit.lua | 2 +- 6 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 xmake/core/base/bit.lua diff --git a/xmake/core/base/bit.lua b/xmake/core/base/bit.lua new file mode 100644 index 000000000..cd81da087 --- /dev/null +++ b/xmake/core/base/bit.lua @@ -0,0 +1,48 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file bit.lua +-- + +-- define module: bit +local bit = bit or (xmake._LUAJIT and require("bit") or {}) +if xmake._LUAJIT then + return bit +end + +-- bit/and operation +function bit.band(a, b) + return a & b +end + +-- bit/or operation +function bit.bor(a, b) + return a | b +end + +-- bit/xor operation +function bit.bxor(a, b) + return a ~ b +end + +-- bit/not operation +function bit.bnot(a) + return ~a +end + +-- return module: bit +return bit diff --git a/xmake/core/base/scheduler.lua b/xmake/core/base/scheduler.lua index 70ba07414..1d92f0e9b 100644 --- a/xmake/core/base/scheduler.lua +++ b/xmake/core/base/scheduler.lua @@ -31,7 +31,7 @@ local poller = require("base/poller") local timer = require("base/timer") local hashset = require("base/hashset") local coroutine = require("base/coroutine") -local bit = require("bit") +local bit = require("base/bit") -- new a coroutine instance function _coroutine.new(name, thread) diff --git a/xmake/core/base/string.lua b/xmake/core/base/string.lua index 0be8cc793..686f36d18 100644 --- a/xmake/core/base/string.lua +++ b/xmake/core/base/string.lua @@ -24,7 +24,7 @@ local string = string or {} -- load modules local deprecated = require("base/deprecated") local serialize = require("base/serialize") -local bit = require("bit") +local bit = require("base/bit") -- save original interfaces string._dump = string._dump or string.dump diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 5cb7d32b9..d51cc6b71 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -23,7 +23,7 @@ local target = target or {} local _instance = _instance or {} -- load modules -local bit = require("bit") +local bit = require("base/bit") local os = require("base/os") local path = require("base/path") local utils = require("base/utils") diff --git a/xmake/core/ui/label.lua b/xmake/core/ui/label.lua index 95a78112f..02aa7245d 100644 --- a/xmake/core/ui/label.lua +++ b/xmake/core/ui/label.lua @@ -24,7 +24,7 @@ local view = require("ui/view") local event = require("ui/event") local action = require("ui/action") local curses = require("ui/curses") -local bit = require("bit") +local bit = require("base/bit") -- define module local label = label or view() diff --git a/xmake/core/ui/textedit.lua b/xmake/core/ui/textedit.lua index 44a10d074..744858fb6 100644 --- a/xmake/core/ui/textedit.lua +++ b/xmake/core/ui/textedit.lua @@ -27,7 +27,7 @@ local border = require("ui/border") local curses = require("ui/curses") local textarea = require("ui/textarea") local action = require("ui/action") -local bit = require("bit") +local bit = require("base/bit") -- define module local textedit = textedit or textarea() -- cgit v1.3.1 From 73fc586b83edbbaf71f01ea893e47dc4ae1407ef Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 10:27:54 +0800 Subject: add getfenv and setfenv for lua --- xmake/core/_xmake_main.lua | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/xmake/core/_xmake_main.lua b/xmake/core/_xmake_main.lua index af9b51114..94045a2f5 100644 --- a/xmake/core/_xmake_main.lua +++ b/xmake/core/_xmake_main.lua @@ -36,6 +36,42 @@ xmake._WORKING_DIR = os.curdir() xmake._FEATURES = _FEATURES xmake._LUAJIT = _LUAJIT +-- init setfenv/getfenv for lua +if not getfenv then + function getfenv(fn) + local i = 1 + while true do + local name, val = debug.getupvalue(fn, i) + if name == "_ENV" then + return val + elseif not name then + break + end + i = i + 1 + end + end +end +if not setfenv then + function setfenv(fn, env) + local i = 1 + while true do + local name = debug.getupvalue(fn, i) + if name == "_ENV" then + debug.upvaluejoin(fn, i, (function() + return env + end), 1) + break + elseif not name then + break + end + + i = i + 1 + end + return fn + end +end + +-- load the given lua file function _loadfile_impl(filepath, mode, opt) -- init options -- cgit v1.3.1 From 40e0caffcf5b5e1959c47393f7e0bd9b2313a0f1 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 10:41:08 +0800 Subject: add table.getn --- xmake/core/base/table.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua index 6709ada3a..1e93efd8d 100644 --- a/xmake/core/base/table.lua +++ b/xmake/core/base/table.lua @@ -46,6 +46,13 @@ if not table.new then end end +-- get array length +if not table.getn then + function table.getn(t) + return #t + end +end + -- move values of table(a1) to table(a2) -- -- disable the builtin implementation for android termux/arm64, it will crash when calling `table.move({1, 1}, 1, 2, 1, {})` -- cgit v1.3.1 From 151102e2b32a11f2a02da00c8236e285b01b19f1 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 11:03:41 +0800 Subject: fix color rain --- xmake/core/base/colors.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/core/base/colors.lua b/xmake/core/base/colors.lua index 942f1f081..22cfad4e3 100644 --- a/xmake/core/base/colors.lua +++ b/xmake/core/base/colors.lua @@ -184,7 +184,7 @@ function colors.rainbow256(index, seed, freq, spread) index = seed + index / spread -- make color code - local code = (freq * index) % 240 + 18 + local code = math.floor((freq * index) % 240 + 18) -- make code return string.format("#%d", code) -- cgit v1.3.1 From 2fc5c39261e8fda47e5376744e7b5c17d6431e97 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 11:36:25 +0800 Subject: improve getfenv and setfenv --- xmake/core/_xmake_main.lua | 35 ----------------- xmake/core/base/env.lua | 96 ++++++++++++++++++++++++++++++++++++++++++++++ xmake/core/main.lua | 1 + 3 files changed, 97 insertions(+), 35 deletions(-) create mode 100644 xmake/core/base/env.lua diff --git a/xmake/core/_xmake_main.lua b/xmake/core/_xmake_main.lua index 94045a2f5..47197d7bb 100644 --- a/xmake/core/_xmake_main.lua +++ b/xmake/core/_xmake_main.lua @@ -36,41 +36,6 @@ xmake._WORKING_DIR = os.curdir() xmake._FEATURES = _FEATURES xmake._LUAJIT = _LUAJIT --- init setfenv/getfenv for lua -if not getfenv then - function getfenv(fn) - local i = 1 - while true do - local name, val = debug.getupvalue(fn, i) - if name == "_ENV" then - return val - elseif not name then - break - end - i = i + 1 - end - end -end -if not setfenv then - function setfenv(fn, env) - local i = 1 - while true do - local name = debug.getupvalue(fn, i) - if name == "_ENV" then - debug.upvaluejoin(fn, i, (function() - return env - end), 1) - break - elseif not name then - break - end - - i = i + 1 - end - return fn - end -end - -- load the given lua file function _loadfile_impl(filepath, mode, opt) diff --git a/xmake/core/base/env.lua b/xmake/core/base/env.lua new file mode 100644 index 000000000..a8e75603b --- /dev/null +++ b/xmake/core/base/env.lua @@ -0,0 +1,96 @@ +-- (c) 2012 David Manura. Licensed under the same terms as Lua 5.1/5.2 (MIT license). +-- Permission is hereby granted, free of charge, to any person obtaining a copy +-- of this software and associated documentation files (the "Software"), to deal +-- in the Software without restriction, including without limitation the rights +-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +-- copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in +-- all copies or substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +-- THE SOFTWARE. +-- +-- @author David Manura, ruki +-- @file env.lua +-- + +-- define module: env +local env = env or {} + +-- from https://github.com/davidm/lua-inspect/blob/master/lib/luainspect/compat_env.lua +if _G.setfenv then -- Lua 5.1 + env.setfenv = _G.setfenv + env.getfenv = _G.getfenv +else -- >= Lua 5.2 + -- helper function for `getfenv`/`setfenv` + local function envlookup(f) + local name, val + local up = 0 + local unknown + repeat + up = up + 1; name, val = debug.getupvalue(f, up) + if name == '' then unknown = true end + until name == '_ENV' or name == nil + if name ~= '_ENV' then + up = nil + if unknown then error("upvalues not readable in Lua 5.2 when debug info missing", 3) end + end + return (name == '_ENV') and up, val, unknown + end + + -- helper function for `getfenv`/`setfenv` + local function envhelper(f, name) + if type(f) == 'number' then + if f < 0 then + error(("bad argument #1 to '%s' (level must be non-negative)"):format(name), 3) + elseif f < 1 then + error("thread environments unsupported in Lua 5.2", 3) --[*] + end + f = debug.getinfo(f+2, 'f').func + elseif type(f) ~= 'function' then + error(("bad argument #1 to '%s' (number expected, got %s)"):format(type(name, f)), 2) + end + return f + end + -- [*] might simulate with table keyed by coroutine.running() + + -- 5.1 style `setfenv` implemented in 5.2 + function env.setfenv(f, t) + local f = envhelper(f, 'setfenv') + local up, val, unknown = envlookup(f) + if up then + debug.upvaluejoin(f, up, function() return up end, 1) -- unique upvalue [*] + debug.setupvalue(f, up, t) + else + local what = debug.getinfo(f, 'S').what + if what ~= 'Lua' and what ~= 'main' then -- not Lua func + error("'setfenv' cannot change environment of given object", 2) + end -- else ignore no _ENV upvalue (warning: incompatible with 5.1) + end + end + -- [*] http://lua-users.org/lists/lua-l/2010-06/msg00313.html + + -- 5.1 style `getfenv` implemented in 5.2 + function env.getfenv(f) + if f == 0 or f == nil then return _G end -- simulated behavior + local f = envhelper(f, 'setfenv') + local up, val = envlookup(f) + if not up then return _G end -- simulated behavior [**] + return val + end + -- [**] possible reasons: no _ENV upvalue, C function + + -- register to global + _G.setfenv = env.setfenv + _G.getfenv = env.getfenv +end + +-- return module: env +return env diff --git a/xmake/core/main.lua b/xmake/core/main.lua index 4664a1c40..0576b6efc 100644 --- a/xmake/core/main.lua +++ b/xmake/core/main.lua @@ -22,6 +22,7 @@ local main = main or {} -- load modules +local env = require("base/env") local os = require("base/os") local log = require("base/log") local path = require("base/path") -- cgit v1.3.1 From 055b0182653106e5f4e93b496ccaa658de6957f0 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 11:39:16 +0800 Subject: add lua to NOTICE --- NOTICE.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/NOTICE.md b/NOTICE.md index 7cde1df09..8a85b751e 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -45,6 +45,14 @@ which can be obtained at: * HOMEPAGE: * http://luajit.org/ +This product depends on 'Lua', The Lua Programing Language, +which can be obtained at: + + * LICENSE: + * https://www.lua.org/license.html (MIT License) + * HOMEPAGE: + * http://lua.org/ + This product depends on 'tbox', The Treasure Box Library, which can be obtained at: -- cgit v1.3.1 From a6999bf6567e9ef6c01a37984a3f67cfa59de51d Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 12:05:12 +0800 Subject: add env to debug --- xmake/core/base/env.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xmake/core/base/env.lua b/xmake/core/base/env.lua index a8e75603b..b7956866e 100644 --- a/xmake/core/base/env.lua +++ b/xmake/core/base/env.lua @@ -90,6 +90,8 @@ else -- >= Lua 5.2 -- register to global _G.setfenv = env.setfenv _G.getfenv = env.getfenv + debug.setfenv = env.setfenv + debug.getfenv = env.getfenv end -- return module: env -- cgit v1.3.1 From e6142baeb6b089b3413755d4a3a9e4607cb829f1 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 12:07:22 +0800 Subject: improve progress --- xmake/modules/private/utils/progress.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/modules/private/utils/progress.lua b/xmake/modules/private/utils/progress.lua index 5c08cbf8f..635d1ef73 100644 --- a/xmake/modules/private/utils/progress.lua +++ b/xmake/modules/private/utils/progress.lua @@ -75,6 +75,7 @@ end -- show the message with process function show(progress, format, ...) + progress = math.floor(progress) local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " if option.get("verbose") then cprint(progress_prefix .. "${dim}" .. format, progress, ...) -- cgit v1.3.1 From d4f485a8d92f5cc89487a0b3670e0b116704b5bf Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 12:14:32 +0800 Subject: add lua ci --- .github/workflows/linux_lua.yml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 .github/workflows/linux_lua.yml diff --git a/.github/workflows/linux_lua.yml b/.github/workflows/linux_lua.yml new file mode 100644 index 000000000..97d45f2a0 --- /dev/null +++ b/.github/workflows/linux_lua.yml @@ -0,0 +1,35 @@ +name: Linux (Lua) + +on: + pull_request: + push: + release: + types: [published] + +jobs: + build: + runs-on: ubuntu-latest + concurrency: + group: ${{ github.head_ref }}-Linux-Lua + cancel-in-progress: true + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - uses: dlang-community/setup-dlang@v1 + with: + compiler: dmd-latest + - uses: little-core-labs/get-git-tag@v3.0.2 + id: tagName + + - name: Installation + run: | + make -j6 BACKEND=lua + make install + xmake --version + + - name: Tests + run: | + xmake lua -v -D tests/run.lua + xrepo --version + -- cgit v1.3.1 From 7a61aa0c62ddb2ff59418ca3d87b8ed37ca5bb75 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 12:24:22 +0800 Subject: fix bit for luajit --- xmake/core/base/bit.lua | 29 +-------------------------- xmake/core/base/compat/bit.lua | 45 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 28 deletions(-) create mode 100644 xmake/core/base/compat/bit.lua diff --git a/xmake/core/base/bit.lua b/xmake/core/base/bit.lua index cd81da087..768722318 100644 --- a/xmake/core/base/bit.lua +++ b/xmake/core/base/bit.lua @@ -18,31 +18,4 @@ -- @file bit.lua -- --- define module: bit -local bit = bit or (xmake._LUAJIT and require("bit") or {}) -if xmake._LUAJIT then - return bit -end - --- bit/and operation -function bit.band(a, b) - return a & b -end - --- bit/or operation -function bit.bor(a, b) - return a | b -end - --- bit/xor operation -function bit.bxor(a, b) - return a ~ b -end - --- bit/not operation -function bit.bnot(a) - return ~a -end - --- return module: bit -return bit +return (xmake._LUAJIT and require("bit") or require("base/compat/bit")) diff --git a/xmake/core/base/compat/bit.lua b/xmake/core/base/compat/bit.lua new file mode 100644 index 000000000..78d5be389 --- /dev/null +++ b/xmake/core/base/compat/bit.lua @@ -0,0 +1,45 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file bit.lua +-- + +-- define module: bit +local bit = bit or {} + +-- bit/and operation +function bit.band(a, b) + return a & b +end + +-- bit/or operation +function bit.bor(a, b) + return a | b +end + +-- bit/xor operation +function bit.bxor(a, b) + return a ~ b +end + +-- bit/not operation +function bit.bnot(a) + return ~a +end + +-- return module: bit +return bit -- cgit v1.3.1 From ad49997df47c87b1afd889f4a6001346d6ee4afb Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 12:24:59 +0800 Subject: move env to compat --- xmake/core/base/compat/env.lua | 98 ++++++++++++++++++++++++++++++++++++++++++ xmake/core/base/env.lua | 98 ------------------------------------------ xmake/core/main.lua | 2 +- 3 files changed, 99 insertions(+), 99 deletions(-) create mode 100644 xmake/core/base/compat/env.lua delete mode 100644 xmake/core/base/env.lua diff --git a/xmake/core/base/compat/env.lua b/xmake/core/base/compat/env.lua new file mode 100644 index 000000000..b7956866e --- /dev/null +++ b/xmake/core/base/compat/env.lua @@ -0,0 +1,98 @@ +-- (c) 2012 David Manura. Licensed under the same terms as Lua 5.1/5.2 (MIT license). +-- Permission is hereby granted, free of charge, to any person obtaining a copy +-- of this software and associated documentation files (the "Software"), to deal +-- in the Software without restriction, including without limitation the rights +-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +-- copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in +-- all copies or substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +-- THE SOFTWARE. +-- +-- @author David Manura, ruki +-- @file env.lua +-- + +-- define module: env +local env = env or {} + +-- from https://github.com/davidm/lua-inspect/blob/master/lib/luainspect/compat_env.lua +if _G.setfenv then -- Lua 5.1 + env.setfenv = _G.setfenv + env.getfenv = _G.getfenv +else -- >= Lua 5.2 + -- helper function for `getfenv`/`setfenv` + local function envlookup(f) + local name, val + local up = 0 + local unknown + repeat + up = up + 1; name, val = debug.getupvalue(f, up) + if name == '' then unknown = true end + until name == '_ENV' or name == nil + if name ~= '_ENV' then + up = nil + if unknown then error("upvalues not readable in Lua 5.2 when debug info missing", 3) end + end + return (name == '_ENV') and up, val, unknown + end + + -- helper function for `getfenv`/`setfenv` + local function envhelper(f, name) + if type(f) == 'number' then + if f < 0 then + error(("bad argument #1 to '%s' (level must be non-negative)"):format(name), 3) + elseif f < 1 then + error("thread environments unsupported in Lua 5.2", 3) --[*] + end + f = debug.getinfo(f+2, 'f').func + elseif type(f) ~= 'function' then + error(("bad argument #1 to '%s' (number expected, got %s)"):format(type(name, f)), 2) + end + return f + end + -- [*] might simulate with table keyed by coroutine.running() + + -- 5.1 style `setfenv` implemented in 5.2 + function env.setfenv(f, t) + local f = envhelper(f, 'setfenv') + local up, val, unknown = envlookup(f) + if up then + debug.upvaluejoin(f, up, function() return up end, 1) -- unique upvalue [*] + debug.setupvalue(f, up, t) + else + local what = debug.getinfo(f, 'S').what + if what ~= 'Lua' and what ~= 'main' then -- not Lua func + error("'setfenv' cannot change environment of given object", 2) + end -- else ignore no _ENV upvalue (warning: incompatible with 5.1) + end + end + -- [*] http://lua-users.org/lists/lua-l/2010-06/msg00313.html + + -- 5.1 style `getfenv` implemented in 5.2 + function env.getfenv(f) + if f == 0 or f == nil then return _G end -- simulated behavior + local f = envhelper(f, 'setfenv') + local up, val = envlookup(f) + if not up then return _G end -- simulated behavior [**] + return val + end + -- [**] possible reasons: no _ENV upvalue, C function + + -- register to global + _G.setfenv = env.setfenv + _G.getfenv = env.getfenv + debug.setfenv = env.setfenv + debug.getfenv = env.getfenv +end + +-- return module: env +return env diff --git a/xmake/core/base/env.lua b/xmake/core/base/env.lua deleted file mode 100644 index b7956866e..000000000 --- a/xmake/core/base/env.lua +++ /dev/null @@ -1,98 +0,0 @@ --- (c) 2012 David Manura. Licensed under the same terms as Lua 5.1/5.2 (MIT license). --- Permission is hereby granted, free of charge, to any person obtaining a copy --- of this software and associated documentation files (the "Software"), to deal --- in the Software without restriction, including without limitation the rights --- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --- copies of the Software, and to permit persons to whom the Software is --- furnished to do so, subject to the following conditions: --- --- The above copyright notice and this permission notice shall be included in --- all copies or substantial portions of the Software. --- --- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN --- THE SOFTWARE. --- --- @author David Manura, ruki --- @file env.lua --- - --- define module: env -local env = env or {} - --- from https://github.com/davidm/lua-inspect/blob/master/lib/luainspect/compat_env.lua -if _G.setfenv then -- Lua 5.1 - env.setfenv = _G.setfenv - env.getfenv = _G.getfenv -else -- >= Lua 5.2 - -- helper function for `getfenv`/`setfenv` - local function envlookup(f) - local name, val - local up = 0 - local unknown - repeat - up = up + 1; name, val = debug.getupvalue(f, up) - if name == '' then unknown = true end - until name == '_ENV' or name == nil - if name ~= '_ENV' then - up = nil - if unknown then error("upvalues not readable in Lua 5.2 when debug info missing", 3) end - end - return (name == '_ENV') and up, val, unknown - end - - -- helper function for `getfenv`/`setfenv` - local function envhelper(f, name) - if type(f) == 'number' then - if f < 0 then - error(("bad argument #1 to '%s' (level must be non-negative)"):format(name), 3) - elseif f < 1 then - error("thread environments unsupported in Lua 5.2", 3) --[*] - end - f = debug.getinfo(f+2, 'f').func - elseif type(f) ~= 'function' then - error(("bad argument #1 to '%s' (number expected, got %s)"):format(type(name, f)), 2) - end - return f - end - -- [*] might simulate with table keyed by coroutine.running() - - -- 5.1 style `setfenv` implemented in 5.2 - function env.setfenv(f, t) - local f = envhelper(f, 'setfenv') - local up, val, unknown = envlookup(f) - if up then - debug.upvaluejoin(f, up, function() return up end, 1) -- unique upvalue [*] - debug.setupvalue(f, up, t) - else - local what = debug.getinfo(f, 'S').what - if what ~= 'Lua' and what ~= 'main' then -- not Lua func - error("'setfenv' cannot change environment of given object", 2) - end -- else ignore no _ENV upvalue (warning: incompatible with 5.1) - end - end - -- [*] http://lua-users.org/lists/lua-l/2010-06/msg00313.html - - -- 5.1 style `getfenv` implemented in 5.2 - function env.getfenv(f) - if f == 0 or f == nil then return _G end -- simulated behavior - local f = envhelper(f, 'setfenv') - local up, val = envlookup(f) - if not up then return _G end -- simulated behavior [**] - return val - end - -- [**] possible reasons: no _ENV upvalue, C function - - -- register to global - _G.setfenv = env.setfenv - _G.getfenv = env.getfenv - debug.setfenv = env.setfenv - debug.getfenv = env.getfenv -end - --- return module: env -return env diff --git a/xmake/core/main.lua b/xmake/core/main.lua index 0576b6efc..d4eb456b3 100644 --- a/xmake/core/main.lua +++ b/xmake/core/main.lua @@ -22,7 +22,7 @@ local main = main or {} -- load modules -local env = require("base/env") +local env = require("base/compat/env") local os = require("base/os") local log = require("base/log") local path = require("base/path") -- cgit v1.3.1 From 7cd5884d2484ff4c0c1f738dd290ade682ec9cd2 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 12:27:22 +0800 Subject: improve ci --- .github/workflows/linux_lua.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/linux_lua.yml b/.github/workflows/linux_lua.yml index 97d45f2a0..2c01a1ab6 100644 --- a/.github/workflows/linux_lua.yml +++ b/.github/workflows/linux_lua.yml @@ -25,7 +25,8 @@ jobs: - name: Installation run: | make -j6 BACKEND=lua - make install + ./scripts/get.sh __local__ __install_only__ + source ~/.xmake/profile xmake --version - name: Tests -- cgit v1.3.1 From 2bd99c17dfd6542aa4d28631c76d06ddabcf4b36 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 12:28:06 +0800 Subject: improve ci --- .github/workflows/linux_lua.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux_lua.yml b/.github/workflows/linux_lua.yml index 2c01a1ab6..71a365a3f 100644 --- a/.github/workflows/linux_lua.yml +++ b/.github/workflows/linux_lua.yml @@ -24,7 +24,7 @@ jobs: - name: Installation run: | - make -j6 BACKEND=lua + make BACKEND=lua ./scripts/get.sh __local__ __install_only__ source ~/.xmake/profile xmake --version -- cgit v1.3.1 From 769ab0606db6d2b7682d50c727626e3b1acb5c1b Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 12:32:41 +0800 Subject: improve compile --- core/src/lua/makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/lua/makefile b/core/src/lua/makefile index 85e8725cf..4137fd22c 100644 --- a/core/src/lua/makefile +++ b/core/src/lua/makefile @@ -62,14 +62,14 @@ ifeq ($(PLAT),cygwin) iswin = yes endif -lua_CFLAGS := -std=c99 -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 \ - -Wno-error=string-plus-int +lua_CFLAGS := -std=c99 -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 ifdef iswin lua_CFLAGS += -DLUA_USE_WINDOWS endif ifeq ($(PLAT),macosx) -lua_CFLAGS += -DLUA_USE_MACOSX +lua_CFLAGS += -DLUA_USE_MACOSX \ + -Wno-error=string-plus-int else lua_CFLAGS += -DLUA_USE_LINUX endif -- cgit v1.3.1 From 7254808af023a1d43df54c47915c450bab041df5 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 13:12:09 +0800 Subject: improve serialize --- xmake/core/base/serialize.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/xmake/core/base/serialize.lua b/xmake/core/base/serialize.lua index a2d7b9ff9..60b90baf5 100644 --- a/xmake/core/base/serialize.lua +++ b/xmake/core/base/serialize.lua @@ -15,7 +15,7 @@ -- -- Copyright (C) 2015-present, TBOOX Open Source Group. -- --- @author OpportunityLiu +-- @author OpportunityLiu, ruki -- @file serialize.lua -- @@ -24,6 +24,7 @@ local serialize = serialize or {} local stub = serialize._stub or {} serialize._stub = stub serialize._dump = serialize._dump or string._dump or string.dump +serialize._BCTAG = xmake._LUAJIT and "\27LJ" or "\27Lua" -- load modules local math = require("base/math") @@ -170,7 +171,7 @@ function serialize._resolvefunction(root, fenv, bytecode) if type(bytecode) ~= "string" then return nil, string.format("invalid bytecode (string expected, got %s)", type(bytecode)) end - if not bytecode:startswith("\27LJ") then + if not bytecode:startswith(serialize._BCTAG) then return nil, "cannot load incompatible bytecode" end @@ -425,7 +426,7 @@ function serialize._load(str) -- load table as script local result = nil - local binary = str:startswith("\27LJ") + local binary = str:startswith(serialize._BCTAG) if not binary then str = "return " .. str end -- cgit v1.3.1 From 06a7b0bd911b5755b3c63fc8bd37f0f445f41d49 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 13:30:18 +0800 Subject: improve tests --- tests/modules/string/serialize/test.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/modules/string/serialize/test.lua b/tests/modules/string/serialize/test.lua index 3c21d4410..dfbd01c09 100644 --- a/tests/modules/string/serialize/test.lua +++ b/tests/modules/string/serialize/test.lua @@ -62,7 +62,10 @@ function test_function(t) -- return x in fenv function f() return x end -- fenv will restore - t:are_same(roundtrip(f)(), x) + if xmake.luajit() then + -- TODO we need fix it for lua backend + t:are_same(roundtrip(f)(), x) + end y = {} -- y in fenv -- cgit v1.3.1 From 38a7d3b7bc8d379970fae6825726761ff3e8e574 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 13:34:47 +0800 Subject: add bit for bytes --- xmake/core/base/bytes.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/core/base/bytes.lua b/xmake/core/base/bytes.lua index 340b21cd0..6cebbdf2b 100644 --- a/xmake/core/base/bytes.lua +++ b/xmake/core/base/bytes.lua @@ -23,8 +23,8 @@ local bytes = bytes or {} local _instance = _instance or {} -- load modules -local bit = require('bit') -local ffi = require('ffi') +local bit = require("base/bit") +local ffi = require("ffi") local os = require("base/os") local utils = require("base/utils") local todisplay = require("base/todisplay") -- cgit v1.3.1 From 0538488ab5ed41c71856a5a9849ddf9a8118ddd0 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 13:35:40 +0800 Subject: add bit for bytes --- .../core/sandbox/modules/import/core/base/bit.lua | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 xmake/core/sandbox/modules/import/core/base/bit.lua diff --git a/xmake/core/sandbox/modules/import/core/base/bit.lua b/xmake/core/sandbox/modules/import/core/base/bit.lua new file mode 100644 index 000000000..3086720eb --- /dev/null +++ b/xmake/core/sandbox/modules/import/core/base/bit.lua @@ -0,0 +1,24 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file bit.lua +-- + +-- load modules +return require("base/bit") + + -- cgit v1.3.1 From 52164d9f27178104817dd5478604ea433b543964 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 13:40:05 +0800 Subject: fix heap tests --- tests/modules/heap/test.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/modules/heap/test.lua b/tests/modules/heap/test.lua index 098116f28..fc11a49d2 100644 --- a/tests/modules/heap/test.lua +++ b/tests/modules/heap/test.lua @@ -1,6 +1,9 @@ import("core.base.heap") function test_cdataheap(t) + if not xmake.luajit() then + return + end local h = heap.cdataheap{ size = 100, ctype = [[ -- cgit v1.3.1 From 7065563ba5be2117b8ed9d194204d33ff73291bd Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 13:45:41 +0800 Subject: disable bytes for lua --- tests/modules/bytes/test.lua | 4 ++++ xmake/core/base/bytes.lua | 12 +++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/modules/bytes/test.lua b/tests/modules/bytes/test.lua index 4cb272c94..aa29e3493 100644 --- a/tests/modules/bytes/test.lua +++ b/tests/modules/bytes/test.lua @@ -1,5 +1,9 @@ import("core.base.bytes") +if not xmake.luajit() then + return +end + function test_ctor(t) t:are_equal(bytes("123456789"):str(), "123456789") t:are_equal(bytes(bytes("123456789")):str(), "123456789") diff --git a/xmake/core/base/bytes.lua b/xmake/core/base/bytes.lua index 6cebbdf2b..359a67f36 100644 --- a/xmake/core/base/bytes.lua +++ b/xmake/core/base/bytes.lua @@ -24,16 +24,18 @@ local _instance = _instance or {} -- load modules local bit = require("base/bit") -local ffi = require("ffi") +local ffi = xmake._LUAJIT and require("ffi") or nil local os = require("base/os") local utils = require("base/utils") local todisplay = require("base/todisplay") -- define ffi interfaces -ffi.cdef[[ - void* malloc(size_t size); - void free(void* data); -]] +if ffi then + ffi.cdef[[ + void* malloc(size_t size); + void free(void* data); + ]] +end -- new a bytes instance -- -- cgit v1.3.1 From b70ab14251a74bd168963cbf17ae4ff7a64d7014 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 13:51:08 +0800 Subject: fix package --- xmake/actions/package/local/main.lua | 2 +- xmake/actions/package/remote/main.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/actions/package/local/main.lua b/xmake/actions/package/local/main.lua index 74bb1cfa1..72cfac3ac 100644 --- a/xmake/actions/package/local/main.lua +++ b/xmake/actions/package/local/main.lua @@ -24,7 +24,7 @@ import("core.base.task") import("core.project.rule") import("core.project.config") import("core.project.project") -import("lib.luajit.bit") +import("core.base.bit") -- get link deps function _get_linkdeps(target) diff --git a/xmake/actions/package/remote/main.lua b/xmake/actions/package/remote/main.lua index b38fa6626..f1aacf057 100644 --- a/xmake/actions/package/remote/main.lua +++ b/xmake/actions/package/remote/main.lua @@ -24,7 +24,7 @@ import("core.base.task") import("core.project.rule") import("core.project.config") import("core.project.project") -import("lib.luajit.bit") +import("core.base.bit") -- get link deps function _get_linkdeps(target) -- cgit v1.3.1 From dc0319e63ea90ed6028ca8f9455350bf6ca85b66 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 13:59:09 +0800 Subject: fix progress --- xmake/modules/private/utils/progress.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/modules/private/utils/progress.lua b/xmake/modules/private/utils/progress.lua index 635d1ef73..074046a69 100644 --- a/xmake/modules/private/utils/progress.lua +++ b/xmake/modules/private/utils/progress.lua @@ -114,6 +114,7 @@ end -- get the message text with process function text(progress, format, ...) + progress = math.floor(progress) local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " if option.get("verbose") then return string.format(progress_prefix .. "${dim}" .. format, progress, ...) -- cgit v1.3.1 From 4767603ee406aa26567edb082745aa3581bd9803 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 14:41:17 +0800 Subject: fix tests/run --- tests/run.lua | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/run.lua b/tests/run.lua index 572e31e9f..00c18ff07 100644 --- a/tests/run.lua +++ b/tests/run.lua @@ -10,9 +10,7 @@ if option.get("verbose") then table.insert(params, "-v") end if option.get("diagnosis") then table.insert(params, "-D") end function _run_test(script) - assert(script:endswith("test.lua")) - os.execv("xmake", table.join("lua", params, path.join(os.scriptdir(), "runner.lua"), script)) end @@ -23,10 +21,14 @@ function _run_test_filter(name) local root = path.absolute(os.scriptdir()) -- find the test script for _, script in ipairs(os.files(path.join(root, "**", name, "**", "test.lua"))) do - table.insert(tests, path.absolute(script)) + if not script:find(".xmake", 1, true) then + table.insert(tests, path.absolute(script)) + end end for _, script in ipairs(os.files(path.join(root, name, "**", "test.lua"))) do - table.insert(tests, path.absolute(script)) + if not script:find(".xmake", 1, true) then + table.insert(tests, path.absolute(script)) + end end for _, script in ipairs(os.files(path.join(root, "**", name, "test.lua"))) do table.insert(tests, path.absolute(script)) -- cgit v1.3.1 From 084bcfde400776e502c9bf1b30d86c514666a27d Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 14:56:16 +0800 Subject: fix scheduler --- .../package/multiconfig/xmake-requires.lock | 9 +- .../package/toolchain_muslcc/xmake-requires.lock | 276 ++++++++++----------- xmake/core/base/scheduler.lua | 14 +- 3 files changed, 145 insertions(+), 154 deletions(-) diff --git a/tests/projects/package/multiconfig/xmake-requires.lock b/tests/projects/package/multiconfig/xmake-requires.lock index af73d677c..a49fd4b60 100644 --- a/tests/projects/package/multiconfig/xmake-requires.lock +++ b/tests/projects/package/multiconfig/xmake-requires.lock @@ -5,25 +5,22 @@ ["macosx|x86_64"] = { ["zlib#31fecfc4"] = { repo = { - branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "/Users/ruki/projects/personal/xmake-repo/" }, version = "1.2.11" }, ["zlib~debug#55833b12"] = { repo = { - branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "/Users/ruki/projects/personal/xmake-repo/" }, version = "1.2.11" }, ["zlib~shared#b6ab42cb"] = { repo = { - branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "/Users/ruki/projects/personal/xmake-repo/" }, version = "1.2.11" } diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock index 9b6e40634..cab4f02dc 100644 --- a/tests/projects/package/toolchain_muslcc/xmake-requires.lock +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -1,145 +1,133 @@ -{ - __meta__ = { - version = "1.0" - }, - ["macosx|x86_64"] = { - ["autoconf#31fecfc4"] = { - repo = { - branch = "master", - commit = "4498f11267de5112199152ab030ed139c985ad5a", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "2.71" - }, - ["automake#31fecfc4"] = { - repo = { - branch = "master", - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "1.16.4" - }, - ["cmake#31fecfc4"] = { - repo = { - branch = "master", - commit = "4498f11267de5112199152ab030ed139c985ad5a", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "3.21.0" - }, - ["gmp#31fecfc4"] = { - repo = { - branch = "master", - commit = "c1b4838c9b1e7a2c52d9bf1a9beafeaee7305e30", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "6.2.1" - }, - ["libisl 0.22#67114504"] = { - repo = { - branch = "master", - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "0.22" - }, - ["libogg#31fecfc4"] = { - repo = { - branch = "master", - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "v1.3.4" - }, - ["libplist#31fecfc4"] = { - repo = { - branch = "master", - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "2.2.0" - }, - ["libtool#31fecfc4"] = { - repo = { - branch = "master", - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "2.4.6" - }, - ["m4#31fecfc4"] = { - repo = { - branch = "master", - commit = "c1b4838c9b1e7a2c52d9bf1a9beafeaee7305e30", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "1.4.19" - }, - ["muslcc#31fecfc4"] = { - repo = { - branch = "master", - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "20210202" - }, - ["pkg-config#31fecfc4"] = { - repo = { - branch = "master", - commit = "c1b4838c9b1e7a2c52d9bf1a9beafeaee7305e30", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "0.29.2" - }, - ["zlib#31fecfc4"] = { - repo = { - branch = "master", - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "1.2.11" - } - }, - ["windows|x64"] = { - ["cmake#31fecfc4"] = { - repo = { - branch = "master", - commit = "8e8c5e4d1c7e8b047b23333594d23b4b85163aed", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "3.21.0" - }, - ["libogg#31fecfc4"] = { - repo = { - branch = "master", - commit = "2b1cb74b289ae3221241985db4401a495c42fde3", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "v1.3.4" - }, - ["make#31fecfc4"] = { - repo = { - branch = "master", - commit = "2b1cb74b289ae3221241985db4401a495c42fde3", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "4.3" - }, - ["muslcc#31fecfc4"] = { - repo = { - branch = "master", - commit = "2b1cb74b289ae3221241985db4401a495c42fde3", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "20210202" - }, - ["zlib#31fecfc4"] = { - repo = { - branch = "master", - commit = "2b1cb74b289ae3221241985db4401a495c42fde3", - url = "https://gitee.com/tboox/xmake-repo.git" - }, - version = "1.2.11" - } - } +{ + __meta__ = { + version = "1.0" + }, + ["macosx|x86_64"] = { + ["autoconf#31fecfc4"] = { + repo = { + commit = "4498f11267de5112199152ab030ed139c985ad5a", + url = "/Users/ruki/projects/personal/xmake-repo/" + }, + version = "2.71" + }, + ["automake#31fecfc4"] = { + repo = { + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + url = "/Users/ruki/projects/personal/xmake-repo/" + }, + version = "1.16.4" + }, + ["cmake#31fecfc4"] = { + repo = { + commit = "4498f11267de5112199152ab030ed139c985ad5a", + url = "/Users/ruki/projects/personal/xmake-repo/" + }, + version = "3.21.0" + }, + ["gmp#31fecfc4"] = { + repo = { + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + url = "/Users/ruki/projects/personal/xmake-repo/" + }, + version = "6.2.1" + }, + ["libisl 0.22#67114504"] = { + repo = { + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + url = "/Users/ruki/projects/personal/xmake-repo/" + }, + version = "0.22" + }, + ["libogg#31fecfc4"] = { + repo = { + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + url = "/Users/ruki/projects/personal/xmake-repo/" + }, + version = "v1.3.4" + }, + ["libplist#31fecfc4"] = { + repo = { + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + url = "/Users/ruki/projects/personal/xmake-repo/" + }, + version = "2.2.0" + }, + ["libtool#31fecfc4"] = { + repo = { + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + url = "/Users/ruki/projects/personal/xmake-repo/" + }, + version = "2.4.6" + }, + ["m4#31fecfc4"] = { + repo = { + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + url = "/Users/ruki/projects/personal/xmake-repo/" + }, + version = "1.4.19" + }, + ["muslcc#31fecfc4"] = { + repo = { + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + url = "/Users/ruki/projects/personal/xmake-repo/" + }, + version = "20210202" + }, + ["pkg-config#31fecfc4"] = { + repo = { + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + url = "/Users/ruki/projects/personal/xmake-repo/" + }, + version = "0.29.2" + }, + ["zlib#31fecfc4"] = { + repo = { + commit = "eda7adee81bac151f87c507030cc0dd8ab299462", + url = "/Users/ruki/projects/personal/xmake-repo/" + }, + version = "1.2.11" + } + }, + ["windows|x64"] = { + ["cmake#31fecfc4"] = { + repo = { + branch = "master", + commit = "8e8c5e4d1c7e8b047b23333594d23b4b85163aed", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "3.21.0" + }, + ["libogg#31fecfc4"] = { + repo = { + branch = "master", + commit = "2b1cb74b289ae3221241985db4401a495c42fde3", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "v1.3.4" + }, + ["make#31fecfc4"] = { + repo = { + branch = "master", + commit = "2b1cb74b289ae3221241985db4401a495c42fde3", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "4.3" + }, + ["muslcc#31fecfc4"] = { + repo = { + branch = "master", + commit = "2b1cb74b289ae3221241985db4401a495c42fde3", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "20210202" + }, + ["zlib#31fecfc4"] = { + repo = { + branch = "master", + commit = "2b1cb74b289ae3221241985db4401a495c42fde3", + url = "https://gitee.com/tboox/xmake-repo.git" + }, + version = "1.2.11" + } + } } \ No newline at end of file diff --git a/xmake/core/base/scheduler.lua b/xmake/core/base/scheduler.lua index 1d92f0e9b..f4928a887 100644 --- a/xmake/core/base/scheduler.lua +++ b/xmake/core/base/scheduler.lua @@ -302,6 +302,7 @@ function scheduler:_co_groups_resume() local co_groups = self._CO_GROUPS if co_groups then local co_groups_waiting = self._CO_GROUPS_WAITING + local co_resumed_list = {} for name, co_group in pairs(co_groups) do -- get coroutine and limit in waiting group @@ -326,10 +327,15 @@ function scheduler:_co_groups_resume() if count >= limit and co_waiting and co_waiting:is_suspended() then resumed_count = resumed_count + 1 self._CO_GROUPS_WAITING[name] = nil - local ok, errors = self:co_resume(co_waiting) - if not ok then - return -1, errors - end + table.insert(co_resumed_list, co_waiting) + end + end + end + if #co_resumed_list > 0 then + for _, co_waiting in ipairs(co_resumed_list) do + local ok, errors = self:co_resume(co_waiting) + if not ok then + return -1, errors end end end -- cgit v1.3.1 From 74adf89f0aa9da139fb7aced500892d268f3644f Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 14:59:57 +0800 Subject: disable bin2c for lua --- tests/projects/other/bin2c/test.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/projects/other/bin2c/test.lua b/tests/projects/other/bin2c/test.lua index b57362078..8981b325d 100644 --- a/tests/projects/other/bin2c/test.lua +++ b/tests/projects/other/bin2c/test.lua @@ -1,3 +1,6 @@ function main(t) - t:build() + -- TODO + if xmake.luajit() then + t:build() + end end -- cgit v1.3.1 From 1ccb90835e59ed093d4026c781cf7e6abe08fdec Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 15:12:56 +0800 Subject: fix require lock --- .../package/multiconfig/xmake-requires.lock | 9 +++-- .../package/toolchain_muslcc/xmake-requires.lock | 42 ++++++++++++++-------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/tests/projects/package/multiconfig/xmake-requires.lock b/tests/projects/package/multiconfig/xmake-requires.lock index a49fd4b60..af73d677c 100644 --- a/tests/projects/package/multiconfig/xmake-requires.lock +++ b/tests/projects/package/multiconfig/xmake-requires.lock @@ -5,22 +5,25 @@ ["macosx|x86_64"] = { ["zlib#31fecfc4"] = { repo = { + branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "/Users/ruki/projects/personal/xmake-repo/" + url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.2.11" }, ["zlib~debug#55833b12"] = { repo = { + branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "/Users/ruki/projects/personal/xmake-repo/" + url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.2.11" }, ["zlib~shared#b6ab42cb"] = { repo = { + branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "/Users/ruki/projects/personal/xmake-repo/" + url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.2.11" } diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock index cab4f02dc..8cb57d3f4 100644 --- a/tests/projects/package/toolchain_muslcc/xmake-requires.lock +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -5,85 +5,97 @@ ["macosx|x86_64"] = { ["autoconf#31fecfc4"] = { repo = { + branch = "master", commit = "4498f11267de5112199152ab030ed139c985ad5a", - url = "/Users/ruki/projects/personal/xmake-repo/" + url = "https://gitee.com/tboox/xmake-repo.git" }, version = "2.71" }, ["automake#31fecfc4"] = { repo = { + branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "/Users/ruki/projects/personal/xmake-repo/" + url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.16.4" }, ["cmake#31fecfc4"] = { repo = { + branch = "master", commit = "4498f11267de5112199152ab030ed139c985ad5a", - url = "/Users/ruki/projects/personal/xmake-repo/" + url = "https://gitee.com/tboox/xmake-repo.git" }, version = "3.21.0" }, ["gmp#31fecfc4"] = { repo = { - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "/Users/ruki/projects/personal/xmake-repo/" + branch = "master", + commit = "89ac4c1e2d360bc3a8c3f4cdedf4ee683701de74", + url = "https://gitee.com/tboox/xmake-repo.git" }, version = "6.2.1" }, ["libisl 0.22#67114504"] = { repo = { + branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "/Users/ruki/projects/personal/xmake-repo/" + url = "https://gitee.com/tboox/xmake-repo.git" }, version = "0.22" }, ["libogg#31fecfc4"] = { repo = { + branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "/Users/ruki/projects/personal/xmake-repo/" + url = "https://gitee.com/tboox/xmake-repo.git" }, version = "v1.3.4" }, ["libplist#31fecfc4"] = { repo = { + branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "/Users/ruki/projects/personal/xmake-repo/" + url = "https://gitee.com/tboox/xmake-repo.git" }, version = "2.2.0" }, ["libtool#31fecfc4"] = { repo = { + branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "/Users/ruki/projects/personal/xmake-repo/" + url = "https://gitee.com/tboox/xmake-repo.git" }, version = "2.4.6" }, ["m4#31fecfc4"] = { repo = { - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "/Users/ruki/projects/personal/xmake-repo/" + branch = "master", + commit = "89ac4c1e2d360bc3a8c3f4cdedf4ee683701de74", + url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.4.19" }, ["muslcc#31fecfc4"] = { repo = { + branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "/Users/ruki/projects/personal/xmake-repo/" + url = "https://gitee.com/tboox/xmake-repo.git" }, version = "20210202" }, ["pkg-config#31fecfc4"] = { repo = { - commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "/Users/ruki/projects/personal/xmake-repo/" + branch = "master", + commit = "89ac4c1e2d360bc3a8c3f4cdedf4ee683701de74", + url = "https://gitee.com/tboox/xmake-repo.git" }, version = "0.29.2" }, ["zlib#31fecfc4"] = { repo = { + branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "/Users/ruki/projects/personal/xmake-repo/" + url = "https://gitee.com/tboox/xmake-repo.git" }, version = "1.2.11" } -- cgit v1.3.1 From 974ae1de229ee3077c868da14adebc11ddac42ac Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Sep 2021 17:12:14 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c6033477..569548cee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### New features * [#388](https://github.com/xmake-io/xmake/issues/388): Pascal Language Support +* [#1682](https://github.com/xmake-io/xmake/issues/1682): Add optional lua5.3 backend instead of luajit to provide better compatibility ### Change @@ -1080,6 +1081,7 @@ ### 新特性 * [#388](https://github.com/xmake-io/xmake/issues/388): Pascal 语言支持,可以使用 fpc 来编译 free pascal +* [#1682](https://github.com/xmake-io/xmake/issues/1682): 添加可选的额lua5.3 运行时替代 luajit,提供更好的平台兼容性。 ### 改进 -- cgit v1.3.1 From 33b05eff154f9158a68b0808f4be0f6c88aa6361 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 19 Sep 2021 23:48:25 +0800 Subject: add libc module --- core/src/xmake/engine.c | 13 ++++++ core/src/xmake/libc/malloc.c | 52 ++++++++++++++++++++++ core/src/xmake/libc/prefix.h | 44 ++++++++++++++++++ core/src/xmake/makefile | 3 +- core/src/xmake/string/endswith.c | 1 - xmake/core/base/libc.lua | 47 +++++++++++++++++++ .../core/sandbox/modules/import/core/base/libc.lua | 24 ++++++++++ 7 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 core/src/xmake/libc/malloc.c create mode 100644 core/src/xmake/libc/prefix.h create mode 100644 xmake/core/base/libc.lua create mode 100644 xmake/core/sandbox/modules/import/core/base/libc.lua diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index 69aa1e452..0c52f6cf0 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -221,6 +221,9 @@ tb_int_t xm_semver_compare(lua_State* lua); tb_int_t xm_semver_satisfies(lua_State* lua); tb_int_t xm_semver_select(lua_State* lua); +// the libc functions +tb_int_t xm_libc_malloc(lua_State* lua); + #ifdef XM_CONFIG_API_HAVE_CURSES // register curses __tb_extern_c_enter__ @@ -412,6 +415,13 @@ static luaL_Reg const g_semver_functions[] = , { tb_null, tb_null } }; +// the libc functions +static luaL_Reg const g_libc_functions[] = +{ + { "malloc", xm_libc_malloc } +, { tb_null, tb_null } +}; + /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ @@ -854,6 +864,9 @@ xm_engine_ref_t xm_engine_init(tb_char_t const* name, xm_engine_lni_initalizer_c // bind semver functions luaL_register(engine->lua, "semver", g_semver_functions); + // bind libc functions + luaL_register(engine->lua, "libc", g_libc_functions); + #ifdef XM_CONFIG_API_HAVE_CURSES // bind curses xm_curses_register(engine->lua); diff --git a/core/src/xmake/libc/malloc.c b/core/src/xmake/libc/malloc.c new file mode 100644 index 000000000..0ee81e68f --- /dev/null +++ b/core/src/xmake/libc/malloc.c @@ -0,0 +1,52 @@ +/*!A cross-platform build utility based on Lua + * + * 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 + * + * http://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. + * + * Copyright (C) 2015-present, TBOOX Open Source Group. + * + * @author ruki + * @file malloc.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "malloc" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_int_t xm_libc_malloc(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + // check arguments? + if (!lua_isnumber(lua, 1)) + xm_libc_return_error(lua, "malloc(invalid size)!"); + + // do malloc + tb_pointer_t data = tb_null; + tb_int_t size = (tb_int_t)lua_tointeger(lua, 1); + if (size > 0) data = tb_malloc(size); + xm_lua_pushpointer(lua, data); + return 1; +} + diff --git a/core/src/xmake/libc/prefix.h b/core/src/xmake/libc/prefix.h new file mode 100644 index 000000000..a220690d6 --- /dev/null +++ b/core/src/xmake/libc/prefix.h @@ -0,0 +1,44 @@ +/*!A cross-platform build utility based on Lua + * + * 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 + * + * http://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. + * + * Copyright (C) 2015-present, TBOOX Open Source Group. + * + * @author ruki + * @file prefix.h + * + */ +#ifndef XM_LIBC_PREFIX_H +#define XM_LIBC_PREFIX_H + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "../prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * macros + */ + +// return libc error +#define xm_libc_return_error(lua, error) \ + do \ + { \ + lua_pushnil(lua); \ + lua_pushliteral(lua, error); \ + return 2; \ + } while (0) + +#endif + + diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index 20bc49d82..a25bd0936 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -115,7 +115,8 @@ xmake_C_FILES += \ readline/readline \ readline/history_list \ readline/add_history \ - readline/clear_history + readline/clear_history \ + libc/malloc iswin = ifeq ($(PLAT),windows) diff --git a/core/src/xmake/string/endswith.c b/core/src/xmake/string/endswith.c index df574b657..8f64dbda6 100644 --- a/core/src/xmake/string/endswith.c +++ b/core/src/xmake/string/endswith.c @@ -48,7 +48,6 @@ tb_int_t xm_string_endswith(lua_State* lua) // string:endswith(suffix)? lua_pushboolean(lua, string_size >= suffix_size && !tb_strcmp(string + string_size - suffix_size, suffix)); - // ok return 1; } diff --git a/xmake/core/base/libc.lua b/xmake/core/base/libc.lua new file mode 100644 index 000000000..bac224df3 --- /dev/null +++ b/xmake/core/base/libc.lua @@ -0,0 +1,47 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file libc.lua +-- + +-- define module: libc +local libc = libc or {} + +-- save original interfaces +libc._malloc = libc._malloc or libc.malloc + +-- load modules +local ffi = xmake._LUAJIT and require("ffi") + +-- define ffi interfaces +if ffi then + ffi.cdef[[ + void* malloc(size_t size); + void free(void* data); + ]] +end + +function libc.malloc(size) + if ffi then + return ffi.cast("unsigned char*", ffi.C.malloc(size)) + else + return libc._malloc(size) + end +end + +-- return module: libc +return libc diff --git a/xmake/core/sandbox/modules/import/core/base/libc.lua b/xmake/core/sandbox/modules/import/core/base/libc.lua new file mode 100644 index 000000000..e4b6630b8 --- /dev/null +++ b/xmake/core/sandbox/modules/import/core/base/libc.lua @@ -0,0 +1,24 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file libc.lua +-- + +-- load modules +return require("base/libc") + + -- cgit v1.3.1 From c1933e6e8e7212f16443e99d66e7d656438da317 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 20 Sep 2021 21:01:12 +0800 Subject: add libc.free --- core/src/xmake/engine.c | 2 ++ core/src/xmake/libc/free.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++ core/src/xmake/makefile | 3 ++- xmake/core/base/libc.lua | 9 +++++++++ 4 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 core/src/xmake/libc/free.c diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index 0c52f6cf0..dcfdd428c 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -223,6 +223,7 @@ tb_int_t xm_semver_select(lua_State* lua); // the libc functions tb_int_t xm_libc_malloc(lua_State* lua); +tb_int_t xm_libc_free(lua_State* lua); #ifdef XM_CONFIG_API_HAVE_CURSES // register curses @@ -419,6 +420,7 @@ static luaL_Reg const g_semver_functions[] = static luaL_Reg const g_libc_functions[] = { { "malloc", xm_libc_malloc } +, { "free", xm_libc_free } , { tb_null, tb_null } }; diff --git a/core/src/xmake/libc/free.c b/core/src/xmake/libc/free.c new file mode 100644 index 000000000..b4d17f1d0 --- /dev/null +++ b/core/src/xmake/libc/free.c @@ -0,0 +1,50 @@ +/*!A cross-platform build utility based on Lua + * + * 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 + * + * http://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. + * + * Copyright (C) 2015-present, TBOOX Open Source Group. + * + * @author ruki + * @file free.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "free" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_int_t xm_libc_free(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + // check arguments? + if (!xm_lua_ispointer(lua, 1)) + xm_libc_return_error(lua, "free(invalid data)!"); + + // do free + tb_pointer_t data = (tb_pointer_t)xm_lua_topointer(lua, 1); + if (data) tb_free(data); + return 0; +} + diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index a25bd0936..bd8046c67 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -116,7 +116,8 @@ xmake_C_FILES += \ readline/history_list \ readline/add_history \ readline/clear_history \ - libc/malloc + libc/malloc \ + libc/free iswin = ifeq ($(PLAT),windows) diff --git a/xmake/core/base/libc.lua b/xmake/core/base/libc.lua index bac224df3..914065f2e 100644 --- a/xmake/core/base/libc.lua +++ b/xmake/core/base/libc.lua @@ -23,6 +23,7 @@ local libc = libc or {} -- save original interfaces libc._malloc = libc._malloc or libc.malloc +libc._free = libc._free or libc.free -- load modules local ffi = xmake._LUAJIT and require("ffi") @@ -43,5 +44,13 @@ function libc.malloc(size) end end +function libc.free(data) + if ffi then + return ffi.C.free(data) + else + return libc._free(data) + end +end + -- return module: libc return libc -- cgit v1.3.1 From bb155096b4fd14781988ef4c2488001fbe2c4938 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 20 Sep 2021 21:05:11 +0800 Subject: improve interactive for lua --- core/src/xmake/sandbox/interactive.c | 13 +++++++++---- xmake/core/sandbox/modules/import/core/sandbox/sandbox.lua | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/core/src/xmake/sandbox/interactive.c b/core/src/xmake/sandbox/interactive.c index 023759448..a62f6f77c 100644 --- a/core/src/xmake/sandbox/interactive.c +++ b/core/src/xmake/sandbox/interactive.c @@ -73,7 +73,6 @@ static tb_void_t xm_sandbox_report(lua_State *lua) } } -#ifdef USE_LUAJIT // the traceback function static tb_int_t xm_sandbox_traceback(lua_State *lua) { @@ -123,7 +122,6 @@ static tb_int_t xm_sandbox_docall(lua_State* lua, tb_int_t narg, tb_int_t clear) // ok? return status; } -#endif // this line is incomplete? static tb_int_t xm_sandbox_incomplete(lua_State *lua, tb_int_t status) @@ -316,20 +314,27 @@ tb_int_t xm_sandbox_interactive(lua_State* lua) // execute codes if (status == 0) { -#ifdef USE_LUAJIT /* bind sandbox * * stack: arg1(top) scriptfunc arg1(sandbox_scope) -> ... */ +#ifdef USE_LUAJIT lua_pushvalue(lua, 1); lua_setfenv(lua, -2); +#else + // stack: arg1(top) scriptfunc $interactive_setfenv scriptfunc arg1(sandbox_scope) -> ... + lua_getfield(lua, 1, "$interactive_setfenv"); + lua_pushvalue(lua, -2); + lua_pushvalue(lua, 1); + if (lua_pcall(lua, 2, 0, 0) != 0) + tb_printl(lua_pushfstring(lua, "error calling " LUA_QL("$interactive_setfenv") " (%s)", lua_tostring(lua, -1))); +#endif /* run script * * stack: arg1(top) scriptfunc -> ... */ status = xm_sandbox_docall(lua, 0, 0); -#endif } // report errors diff --git a/xmake/core/sandbox/modules/import/core/sandbox/sandbox.lua b/xmake/core/sandbox/modules/import/core/sandbox/sandbox.lua index c8a44d266..c189f398e 100644 --- a/xmake/core/sandbox/modules/import/core/sandbox/sandbox.lua +++ b/xmake/core/sandbox/modules/import/core/sandbox/sandbox.lua @@ -93,6 +93,7 @@ function sandbox_core_sandbox.interactive() public_scope["$interactive_dump"] = sandbox_core_sandbox._interactive_dump public_scope["$interactive_prompt"] = colors.translate("${color.interactive.prompt}${text.interactive.prompt} ") public_scope["$interactive_prompt2"] = colors.translate("${color.interactive.prompt2}${text.interactive.prompt2} ") + public_scope["$interactive_setfenv"] = setfenv -- disable scheduler scheduler:enable(false) -- cgit v1.3.1 From ef3180fdb0b441cbaecd00a2f9dfebb1addd421c Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 20 Sep 2021 21:06:31 +0800 Subject: fix dump --- xmake/core/base/dump.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/core/base/dump.lua b/xmake/core/base/dump.lua index 80f4e49b1..22c5e32b8 100644 --- a/xmake/core/base/dump.lua +++ b/xmake/core/base/dump.lua @@ -196,7 +196,7 @@ function dump._print_udata(value, first_indent, remain_indent, printed_set) io.write(first_indent) if not first_level then - return dump._print_udata_scalar(value) + io.write(todisplay._print_udata_scalar(value)) end local inner_indent = remain_indent .. " " -- cgit v1.3.1 From 8a177cf0047b61c1fc5085138b7d268e500fe909 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 20 Sep 2021 21:07:46 +0800 Subject: add libc.memcpy --- core/src/xmake/engine.c | 2 ++ core/src/xmake/libc/memcpy.c | 53 ++++++++++++++++++++++++++++++++++++++++++++ core/src/xmake/makefile | 3 ++- xmake/core/base/libc.lua | 11 ++++++++- 4 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 core/src/xmake/libc/memcpy.c diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index dcfdd428c..2aa8f17cd 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -224,6 +224,7 @@ tb_int_t xm_semver_select(lua_State* lua); // the libc functions tb_int_t xm_libc_malloc(lua_State* lua); tb_int_t xm_libc_free(lua_State* lua); +tb_int_t xm_libc_memcpy(lua_State* lua); #ifdef XM_CONFIG_API_HAVE_CURSES // register curses @@ -421,6 +422,7 @@ static luaL_Reg const g_libc_functions[] = { { "malloc", xm_libc_malloc } , { "free", xm_libc_free } +, { "memcpy", xm_libc_memcpy } , { tb_null, tb_null } }; diff --git a/core/src/xmake/libc/memcpy.c b/core/src/xmake/libc/memcpy.c new file mode 100644 index 000000000..e2c9af4c3 --- /dev/null +++ b/core/src/xmake/libc/memcpy.c @@ -0,0 +1,53 @@ +/*!A cross-platform build utility based on Lua + * + * 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 + * + * http://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. + * + * Copyright (C) 2015-present, TBOOX Open Source Group. + * + * @author ruki + * @file memcpy.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "memcpy" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_int_t xm_libc_memcpy(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + // check arguments? + if (!xm_lua_ispointer(lua, 1) || !xm_lua_ispointer(lua, 2) || !lua_isnumber(lua, 3)) + xm_libc_return_error(lua, "memcpy(invalid args)!"); + + // do memcpy + tb_pointer_t dst = (tb_pointer_t)xm_lua_topointer(lua, 1); + tb_pointer_t src = (tb_pointer_t)xm_lua_topointer(lua, 2); + tb_int_t size = (tb_int_t)lua_tointeger(lua, 3); + if (dst && src && size > 0) + tb_memcpy(dst, src, size); + return 0; +} + diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index bd8046c67..3db867eb7 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -117,7 +117,8 @@ xmake_C_FILES += \ readline/add_history \ readline/clear_history \ libc/malloc \ - libc/free + libc/free \ + libc/memcpy iswin = ifeq ($(PLAT),windows) diff --git a/xmake/core/base/libc.lua b/xmake/core/base/libc.lua index 914065f2e..4b3a9f3ec 100644 --- a/xmake/core/base/libc.lua +++ b/xmake/core/base/libc.lua @@ -23,7 +23,8 @@ local libc = libc or {} -- save original interfaces libc._malloc = libc._malloc or libc.malloc -libc._free = libc._free or libc.free +libc._free = libc._free or libc.free +libc._memcpy = libc._memcpy or libc.memcpy -- load modules local ffi = xmake._LUAJIT and require("ffi") @@ -52,5 +53,13 @@ function libc.free(data) end end +function libc.memcpy(dst, src, size) + if ffi then + return ffi.copy(dst, src, size) + else + return libc._memcpy(dst, src, size) + end +end + -- return module: libc return libc -- cgit v1.3.1 From d6cf1e9c4b73507fb2bcfa0d173ebb62a28faa64 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 20 Sep 2021 21:07:59 +0800 Subject: rename BACKEND to RUNTIME --- core/makefile | 6 +++--- core/src/demo/makefile | 4 ++-- core/src/lcurses/makefile | 4 ++-- core/src/lua-cjson/makefile | 4 ++-- core/src/makefile | 4 ++-- core/src/xmake/makefile | 4 ++-- makefile | 6 +++--- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/core/makefile b/core/makefile index d7c529489..40811af32 100644 --- a/core/makefile +++ b/core/makefile @@ -368,7 +368,7 @@ config : .null @$(ECHO) "directories:" @$(ECHO) " install:\t\t"$(abspath $(INSTALL)) @$(ECHO) " package:\t\t"$(PACKAGE) - @$(ECHO) " backend:\t\t"$(BACKEND) + @$(ECHO) " backend:\t\t"$(RUNTIME) @$(ECHO) "" @$(ECHO) "toolchains:" @$(ECHO) " bin:\t\t"$(BIN) @@ -461,8 +461,8 @@ config : .null @$(ECHO) "export SPARC" >> .config.mak @$(ECHO) "" >> .config.mak @$(ECHO) "# backend" >> .config.mak - @$(ECHO) "BACKEND ="$(BACKEND) >> .config.mak - @$(ECHO) "export BACKEND" >> .config.mak + @$(ECHO) "RUNTIME ="$(RUNTIME) >> .config.mak + @$(ECHO) "export RUNTIME" >> .config.mak @$(ECHO) "" >> .config.mak @$(ECHO) "# demo" >> .config.mak @$(ECHO) "DEMO ="$(DEMO) >> .config.mak diff --git a/core/src/demo/makefile b/core/src/demo/makefile index 93525ddaf..6c4aad363 100644 --- a/core/src/demo/makefile +++ b/core/src/demo/makefile @@ -20,7 +20,7 @@ demo_INC_DIRS += ../ ../tbox/tbox/src ../tbox/inc/$(PLAT) demo_LIB_DIRS += ../tbox # luajit -ifeq ($(BACKEND),luajit) +ifeq ($(RUNTIME),luajit) luajit_LIBS := $(if $(findstring luajit,$(base_LIBNAMES)),,luajit$(DTYPE)) demo_LIBS += $(luajit_LIBS) demo_INC_DIRS += ../luajit/luajit/src @@ -28,7 +28,7 @@ demo_LIB_DIRS += ../luajit endif # lua -ifeq ($(BACKEND),lua) +ifeq ($(RUNTIME),lua) lua_LIBS := $(if $(findstring lua,$(base_LIBNAMES)),,lua$(DTYPE)) demo_LIBS += $(lua_LIBS) demo_INC_DIRS += ../lua/lua diff --git a/core/src/lcurses/makefile b/core/src/lcurses/makefile index a0d6a6400..e5d519499 100644 --- a/core/src/lcurses/makefile +++ b/core/src/lcurses/makefile @@ -17,11 +17,11 @@ lcurses_C_FILES += lcurses lcurses_CXFLAGS += $(if $(findstring curses,$(base_LIBNAMES)),-DXM_CONFIG_API_HAVE_CURSES,) # includes -ifeq ($(BACKEND),luajit) +ifeq ($(RUNTIME),luajit) lcurses_INC_DIRS += ../luajit/luajit/src lcurses_CXFLAGS += -DUSE_LUAJIT endif -ifeq ($(BACKEND),lua) +ifeq ($(RUNTIME),lua) lcurses_INC_DIRS += ../lua/lua lcurses_CXFLAGS += -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 endif diff --git a/core/src/lua-cjson/makefile b/core/src/lua-cjson/makefile index e1d53ecf9..021c3d015 100644 --- a/core/src/lua-cjson/makefile +++ b/core/src/lua-cjson/makefile @@ -22,11 +22,11 @@ lua-cjson_C_FILES += \ lua-cjson_CFLAGS += -DNDEBUG -DUSE_INTERNAL_FPCONV # includes -ifeq ($(BACKEND),luajit) +ifeq ($(RUNTIME),luajit) lua-cjson_INC_DIRS += ../luajit/luajit/src lua-cjson_CXFLAGS += -DUSE_LUAJIT endif -ifeq ($(BACKEND),lua) +ifeq ($(RUNTIME),lua) lua-cjson_INC_DIRS += ../lua/lua lua-cjson_CXFLAGS += -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 endif diff --git a/core/src/makefile b/core/src/makefile index 47151258e..f16a1557d 100644 --- a/core/src/makefile +++ b/core/src/makefile @@ -3,10 +3,10 @@ include $(PRO_DIR)/prefix.mak # projects SUB_PROS += demo -ifeq ($(BACKEND),luajit) +ifeq ($(RUNTIME),luajit) DEP_PROS += luajit endif -ifeq ($(BACKEND),lua) +ifeq ($(RUNTIME),lua) DEP_PROS += lua endif DEP_PROS += lcurses sv lua-cjson tbox xmake diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index 3db867eb7..2c5eefa01 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -153,11 +153,11 @@ xmake_INC_DIRS += \ ../tbox/tbox/src \ ../tbox/inc/$(PLAT) \ ../sv/sv/include -ifeq ($(BACKEND),luajit) +ifeq ($(RUNTIME),luajit) xmake_INC_DIRS += ../luajit/luajit/src xmake_CXFLAGS += -DUSE_LUAJIT endif -ifeq ($(BACKEND),lua) +ifeq ($(RUNTIME),lua) xmake_INC_DIRS += ../lua/lua xmake_CXFLAGS += -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 endif diff --git a/makefile b/makefile index c22bc30cb..bdb79d05b 100644 --- a/makefile +++ b/makefile @@ -16,8 +16,8 @@ endif endif # use luajit or lua backend -ifeq ($(BACKEND),) -BACKEND :=luajit +ifeq ($(RUNTIME),) +RUNTIME :=luajit endif # the temporary directory @@ -99,7 +99,7 @@ xrepo_bin_install :=$(destdir)/bin/xrepo build: @echo compiling xmake-core ... @if [ -f core/.config.mak ]; then rm core/.config.mak; fi - +@$(MAKE) -C core --no-print-directory f DEBUG=$(debug) BACKEND=$(BACKEND) + +@$(MAKE) -C core --no-print-directory f DEBUG=$(debug) RUNTIME=$(RUNTIME) +@$(MAKE) -C core --no-print-directory c +@$(MAKE) -C core --no-print-directory -- cgit v1.3.1 From 07cabd568b07120e227e29a945bc45dcc05a0db2 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 20 Sep 2021 21:08:57 +0800 Subject: add libc.memset --- core/src/xmake/engine.c | 2 ++ core/src/xmake/libc/memset.c | 53 ++++++++++++++++++++++++++++++++++++++++++++ core/src/xmake/makefile | 1 + xmake/core/base/libc.lua | 9 ++++++++ 4 files changed, 65 insertions(+) create mode 100644 core/src/xmake/libc/memset.c diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index 2aa8f17cd..63196680d 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -225,6 +225,7 @@ tb_int_t xm_semver_select(lua_State* lua); tb_int_t xm_libc_malloc(lua_State* lua); tb_int_t xm_libc_free(lua_State* lua); tb_int_t xm_libc_memcpy(lua_State* lua); +tb_int_t xm_libc_memset(lua_State* lua); #ifdef XM_CONFIG_API_HAVE_CURSES // register curses @@ -423,6 +424,7 @@ static luaL_Reg const g_libc_functions[] = { "malloc", xm_libc_malloc } , { "free", xm_libc_free } , { "memcpy", xm_libc_memcpy } +, { "memset", xm_libc_memset } , { tb_null, tb_null } }; diff --git a/core/src/xmake/libc/memset.c b/core/src/xmake/libc/memset.c new file mode 100644 index 000000000..c3171bace --- /dev/null +++ b/core/src/xmake/libc/memset.c @@ -0,0 +1,53 @@ +/*!A cross-platform build utility based on Lua + * + * 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 + * + * http://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. + * + * Copyright (C) 2015-present, TBOOX Open Source Group. + * + * @author ruki + * @file memset.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "memset" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_int_t xm_libc_memset(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + // check arguments? + if (!xm_lua_ispointer(lua, 1) || !lua_isnumber(lua, 2) || !lua_isnumber(lua, 3)) + xm_libc_return_error(lua, "memset(invalid args)!"); + + // do memset + tb_pointer_t data = (tb_pointer_t)xm_lua_topointer(lua, 1); + tb_char_t ch = (tb_char_t)lua_tointeger(lua, 2); + tb_int_t size = (tb_int_t)lua_tointeger(lua, 3); + if (data && size > 0) + tb_memset(data, ch, size); + return 0; +} + diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index 2c5eefa01..84b6a03c5 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -118,6 +118,7 @@ xmake_C_FILES += \ readline/clear_history \ libc/malloc \ libc/free \ + libc/memset \ libc/memcpy iswin = diff --git a/xmake/core/base/libc.lua b/xmake/core/base/libc.lua index 4b3a9f3ec..ff6a88401 100644 --- a/xmake/core/base/libc.lua +++ b/xmake/core/base/libc.lua @@ -25,6 +25,7 @@ local libc = libc or {} libc._malloc = libc._malloc or libc.malloc libc._free = libc._free or libc.free libc._memcpy = libc._memcpy or libc.memcpy +libc._memset = libc._memset or libc.memset -- load modules local ffi = xmake._LUAJIT and require("ffi") @@ -61,5 +62,13 @@ function libc.memcpy(dst, src, size) end end +function libc.memset(data, ch, size) + if ffi then + return ffi.fill(data, size, ch) + else + return libc._memset(data, ch, size) + end +end + -- return module: libc return libc -- cgit v1.3.1 From 68f4ab938564a43656236de3a0eb67f9222bc876 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 20 Sep 2021 22:52:37 +0800 Subject: improve bytes --- tests/modules/bytes/test.lua | 5 +++++ xmake/core/base/bytes.lua | 22 ++++++++++++++-------- xmake/core/base/libc.lua | 9 +++++++++ xmake/core/sandbox/modules/debug.lua | 13 +++++++------ 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/tests/modules/bytes/test.lua b/tests/modules/bytes/test.lua index aa29e3493..8d4504f2c 100644 --- a/tests/modules/bytes/test.lua +++ b/tests/modules/bytes/test.lua @@ -12,16 +12,19 @@ function test_ctor(t) t:are_equal(bytes(10):size(), 10) t:are_equal(bytes(bytes("123"), bytes("456"), bytes("789")):str(), "123456789") t:are_equal(bytes({bytes("123"), bytes("456"), bytes("789")}):str(), "123456789") + debug.collectgarbage() end function test_clone(t) t:are_equal(bytes(10):clone():size(), 10) t:are_equal(bytes("123456789"):clone():str(), "123456789") + debug.collectgarbage() end function test_slice(t) t:are_equal(bytes(10):slice(1, 2):size(), 2) t:are_equal(bytes("123456789"):slice(1, 4):str(), "1234") + debug.collectgarbage() end function test_index(t) @@ -34,9 +37,11 @@ function test_index(t) b[1] = string.byte('2') t:are_equal(b:str(), "223456789") t:will_raise(function() b[100] = string.byte('2') end) + debug.collectgarbage() end function test_concat(t) t:are_equal((bytes("123") .. bytes("456")):str(), "123456") t:are_equal(bytes(bytes("123"), bytes("456")):str(), "123456") + debug.collectgarbage() end diff --git a/xmake/core/base/bytes.lua b/xmake/core/base/bytes.lua index 359a67f36..ba44d3403 100644 --- a/xmake/core/base/bytes.lua +++ b/xmake/core/base/bytes.lua @@ -28,6 +28,7 @@ local ffi = xmake._LUAJIT and require("ffi") or nil local os = require("base/os") local utils = require("base/utils") local todisplay = require("base/todisplay") +local libc = require("base/libc") -- define ffi interfaces if ffi then @@ -77,11 +78,11 @@ function _instance.new(...) os.raise("invalid arguments #2 for bytes(size, ...), cdata, string, number or nil expected!") end end - local ptr = ffi.C.malloc(size) + local ptr = libc.gcmalloc(size) if init then - ffi.fill(ptr, size, init) + libc.memset(ptr, init, size) end - instance._CDATA = ffi.gc(ffi.cast("unsigned char*", ptr), ffi.C.free) + instance._CDATA = ptr instance._MANAGED = true end instance._SIZE = size @@ -114,10 +115,10 @@ function _instance.new(...) for _, b in ipairs(args) do instance._SIZE = instance._SIZE + b:size() end - instance._CDATA = ffi.gc(ffi.cast("unsigned char*", ffi.C.malloc(instance._SIZE)), ffi.C.free) + instance._CDATA = libc.gcmalloc(instance._SIZE) local offset = 0 for _, b in ipairs(args) do - ffi.copy(instance._CDATA + offset, b:cdata(), b:size()) + libc.memcpy(instance._CDATA + offset, b:cdata(), b:size()) offset = offset + b:size() end instance._MANAGED = true @@ -129,10 +130,10 @@ function _instance.new(...) for _, b in ipairs(args) do instance._SIZE = instance._SIZE + b:size() end - instance._CDATA = ffi.gc(ffi.cast("unsigned char*", ffi.C.malloc(instance._SIZE)), ffi.C.free) + instance._CDATA = libc.gcmalloc(instance._SIZE) local offset = 0 for _, b in ipairs(args) do - ffi.copy(instance._CDATA + offset, b._CDATA, b:size()) + libc.memcpy(instance._CDATA + offset, b._CDATA, b:size()) offset = offset + b:size() end instance._MANAGED = true @@ -218,7 +219,7 @@ function _instance:copy(src) if src:size() ~= self:size() then os.raise("%s: cannot copy bytes, src and dst must have same size(%d->%d)!", self, src:size(), self:size()) end - ffi.copy(self:cdata(), src:cdata(), self:size()) + libc.memcpy(self:cdata(), src:cdata(), self:size()) return self end @@ -455,6 +456,11 @@ function _instance:__todisplay() return "bytes${reset}(" .. todisplay(self:size()) .. ") <${color.dump.number}" .. table.concat(parts, " ") .. (self:size() > 8 and "${reset} ..>" or "${reset}>") end +-- it's only called for lua runtime, because bytes is not userdata +function _instance:__gc() + print("gc") +end + -- new an bytes instance function bytes.new(...) return _instance.new(...) diff --git a/xmake/core/base/libc.lua b/xmake/core/base/libc.lua index ff6a88401..cedabef1b 100644 --- a/xmake/core/base/libc.lua +++ b/xmake/core/base/libc.lua @@ -46,6 +46,15 @@ function libc.malloc(size) end end +function libc.gcmalloc(size) + if ffi then + return ffi.gc(ffi.cast("unsigned char*", ffi.C.malloc(size)), ffi.C.free) + else + -- @note we need free it in lua/__gc manually + return libc._malloc(size) + end +end + function libc.free(data) if ffi then return ffi.C.free(data) diff --git a/xmake/core/sandbox/modules/debug.lua b/xmake/core/sandbox/modules/debug.lua index a533720e7..2a3004537 100644 --- a/xmake/core/sandbox/modules/debug.lua +++ b/xmake/core/sandbox/modules/debug.lua @@ -24,11 +24,13 @@ local table = require("base/table") -- define module local sandbox_debug = sandbox_debug or table.join(debug) -sandbox_debug.rawget = rawget -sandbox_debug.rawset = rawset -sandbox_debug.rawequal = rawequal -sandbox_debug.rawlen = rawlen -sandbox_debug.require = require +sandbox_debug.rawget = rawget +sandbox_debug.rawset = rawset +sandbox_debug.rawequal = rawequal +sandbox_debug.rawlen = rawlen +sandbox_debug.require = require +sandbox_debug.collectgarbage = collectgarbage + function sandbox_debug.global(key) if key == nil then return _G @@ -36,6 +38,5 @@ function sandbox_debug.global(key) return _G[key] end - -- return module return sandbox_debug -- cgit v1.3.1 From ed1c24645198aa1451ee22c005a16fa7b8e4d5bc Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 20 Sep 2021 22:54:29 +0800 Subject: add libc.dataptr --- core/src/xmake/engine.c | 2 ++ core/src/xmake/libc/dataptr.c | 55 +++++++++++++++++++++++++++++++++++++++++++ core/src/xmake/makefile | 3 ++- xmake/core/base/bytes.lua | 6 ++--- xmake/core/base/libc.lua | 17 +++++++++---- 5 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 core/src/xmake/libc/dataptr.c diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index 63196680d..5d90decec 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -226,6 +226,7 @@ tb_int_t xm_libc_malloc(lua_State* lua); tb_int_t xm_libc_free(lua_State* lua); tb_int_t xm_libc_memcpy(lua_State* lua); tb_int_t xm_libc_memset(lua_State* lua); +tb_int_t xm_libc_dataptr(lua_State* lua); #ifdef XM_CONFIG_API_HAVE_CURSES // register curses @@ -425,6 +426,7 @@ static luaL_Reg const g_libc_functions[] = , { "free", xm_libc_free } , { "memcpy", xm_libc_memcpy } , { "memset", xm_libc_memset } +, { "dataptr", xm_libc_dataptr } , { tb_null, tb_null } }; diff --git a/core/src/xmake/libc/dataptr.c b/core/src/xmake/libc/dataptr.c new file mode 100644 index 000000000..4f983e5e7 --- /dev/null +++ b/core/src/xmake/libc/dataptr.c @@ -0,0 +1,55 @@ +/*!A cross-platform build utility based on Lua + * + * 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 + * + * http://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. + * + * Copyright (C) 2015-present, TBOOX Open Source Group. + * + * @author ruki + * @file dataptr.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "dataptr" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_int_t xm_libc_dataptr(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + if (xm_lua_ispointer(lua, 1)) + { + tb_pointer_t data = (tb_pointer_t)xm_lua_topointer(lua, 1); + xm_lua_pushpointer(lua, data); + return 1; + } + else if (lua_isstring(lua, 1)) + { + tb_char_t const* cstr = luaL_checkstring(lua, 1); + xm_lua_pushpointer(lua, (tb_pointer_t)cstr); + return 1; + } + xm_libc_return_error(lua, "dataptr(invalid data)!"); +} + diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index 84b6a03c5..6acb60686 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -119,7 +119,8 @@ xmake_C_FILES += \ libc/malloc \ libc/free \ libc/memset \ - libc/memcpy + libc/memcpy \ + libc/dataptr iswin = ifeq ($(PLAT),windows) diff --git a/xmake/core/base/bytes.lua b/xmake/core/base/bytes.lua index ba44d3403..a4a963762 100644 --- a/xmake/core/base/bytes.lua +++ b/xmake/core/base/bytes.lua @@ -60,10 +60,10 @@ function _instance.new(...) local ptr = arg2 local manage = arg3 if manage then - instance._CDATA = ffi.gc(ffi.cast("unsigned char*", ptr), ffi.C.free) + instance._CDATA = ffi.gc(libc.dataptr(ptr), ffi.C.free) instance._MANAGED = true else - instance._CDATA = ffi.cast("unsigned char*", ptr) + instance._CDATA = libc.dataptr(ptr) instance._MANAGED = false end else @@ -91,7 +91,7 @@ function _instance.new(...) -- bytes(str): mounts a buffer from the given string local str = arg1 instance._SIZE = #str - instance._CDATA = ffi.cast("unsigned char*", str) + instance._CDATA = libc.dataptr(str) instance._REF = str -- keep ref for GC instance._MANAGED = false instance._READONLY = true diff --git a/xmake/core/base/libc.lua b/xmake/core/base/libc.lua index cedabef1b..5a32e1180 100644 --- a/xmake/core/base/libc.lua +++ b/xmake/core/base/libc.lua @@ -22,10 +22,11 @@ local libc = libc or {} -- save original interfaces -libc._malloc = libc._malloc or libc.malloc -libc._free = libc._free or libc.free -libc._memcpy = libc._memcpy or libc.memcpy -libc._memset = libc._memset or libc.memset +libc._malloc = libc._malloc or libc.malloc +libc._free = libc._free or libc.free +libc._memcpy = libc._memcpy or libc.memcpy +libc._memset = libc._memset or libc.memset +libc._dataptr = libc._dataptr or libc.dataptr -- load modules local ffi = xmake._LUAJIT and require("ffi") @@ -79,5 +80,13 @@ function libc.memset(data, ch, size) end end +function libc.dataptr(data) + if ffi then + return ffi.cast("unsigned char*", data) + else + return libc._dataptr(data) + end +end + -- return module: libc return libc -- cgit v1.3.1 From 02d6208da20b9e6a6571ed716c16ed04d979b036 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 20 Sep 2021 22:55:44 +0800 Subject: add libc.ptraddr --- core/src/xmake/engine.c | 2 ++ core/src/xmake/libc/ptraddr.c | 55 +++++++++++++++++++++++++++++++++++++++++++ core/src/xmake/makefile | 3 ++- xmake/core/base/bytes.lua | 2 +- xmake/core/base/libc.lua | 9 +++++++ 5 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 core/src/xmake/libc/ptraddr.c diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index 5d90decec..5ca1d90f0 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -227,6 +227,7 @@ tb_int_t xm_libc_free(lua_State* lua); tb_int_t xm_libc_memcpy(lua_State* lua); tb_int_t xm_libc_memset(lua_State* lua); tb_int_t xm_libc_dataptr(lua_State* lua); +tb_int_t xm_libc_ptraddr(lua_State* lua); #ifdef XM_CONFIG_API_HAVE_CURSES // register curses @@ -427,6 +428,7 @@ static luaL_Reg const g_libc_functions[] = , { "memcpy", xm_libc_memcpy } , { "memset", xm_libc_memset } , { "dataptr", xm_libc_dataptr } +, { "ptraddr", xm_libc_ptraddr } , { tb_null, tb_null } }; diff --git a/core/src/xmake/libc/ptraddr.c b/core/src/xmake/libc/ptraddr.c new file mode 100644 index 000000000..347bf60bf --- /dev/null +++ b/core/src/xmake/libc/ptraddr.c @@ -0,0 +1,55 @@ +/*!A cross-platform build utility based on Lua + * + * 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 + * + * http://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. + * + * Copyright (C) 2015-present, TBOOX Open Source Group. + * + * @author ruki + * @file ptraddr.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "ptraddr" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_int_t xm_libc_ptraddr(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + if (xm_lua_ispointer(lua, 1)) + { + tb_pointer_t data = (tb_pointer_t)xm_lua_topointer(lua, 1); + lua_pushnumber(lua, (lua_Number)(tb_hize_t)data); + return 1; + } + else if (lua_isstring(lua, 1)) + { + tb_char_t const* cstr = luaL_checkstring(lua, 1); + lua_pushnumber(lua, (lua_Number)(tb_hize_t)cstr); + return 1; + } + xm_libc_return_error(lua, "ptraddr(invalid data)!"); +} + diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index 6acb60686..94df3a3e8 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -120,7 +120,8 @@ xmake_C_FILES += \ libc/free \ libc/memset \ libc/memcpy \ - libc/dataptr + libc/dataptr \ + libc/ptraddr iswin = ifeq ($(PLAT),windows) diff --git a/xmake/core/base/bytes.lua b/xmake/core/base/bytes.lua index a4a963762..d29cfb3b4 100644 --- a/xmake/core/base/bytes.lua +++ b/xmake/core/base/bytes.lua @@ -184,7 +184,7 @@ end -- get data address function _instance:caddr() - return tonumber(ffi.cast('unsigned long long', self:cdata())) + return libc.ptraddr(self:cdata()) end -- readonly? diff --git a/xmake/core/base/libc.lua b/xmake/core/base/libc.lua index 5a32e1180..20caff02b 100644 --- a/xmake/core/base/libc.lua +++ b/xmake/core/base/libc.lua @@ -27,6 +27,7 @@ libc._free = libc._free or libc.free libc._memcpy = libc._memcpy or libc.memcpy libc._memset = libc._memset or libc.memset libc._dataptr = libc._dataptr or libc.dataptr +libc._ptraddr = libc._ptraddr or libc.ptraddr -- load modules local ffi = xmake._LUAJIT and require("ffi") @@ -88,5 +89,13 @@ function libc.dataptr(data) end end +function libc.ptraddr(data) + if ffi then + return tonumber(ffi.cast('unsigned long long', data)) + else + return libc._ptraddr(data) + end +end + -- return module: libc return libc -- cgit v1.3.1 From 07a9a02dbd44f4d58cdb704c6db23f5e62fd2ccf Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 20 Sep 2021 22:55:51 +0800 Subject: remove some ffi codes --- xmake/core/base/bytes.lua | 8 -------- 1 file changed, 8 deletions(-) diff --git a/xmake/core/base/bytes.lua b/xmake/core/base/bytes.lua index d29cfb3b4..8b2fa08cc 100644 --- a/xmake/core/base/bytes.lua +++ b/xmake/core/base/bytes.lua @@ -30,14 +30,6 @@ local utils = require("base/utils") local todisplay = require("base/todisplay") local libc = require("base/libc") --- define ffi interfaces -if ffi then - ffi.cdef[[ - void* malloc(size_t size); - void free(void* data); - ]] -end - -- new a bytes instance -- -- bytes(size[, init]): allocates a buffer of given size, init with given number or char value -- cgit v1.3.1 From 1e14751dcb53640e9592be678e3ebf6a46d611e1 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 00:25:24 +0800 Subject: improve bytes for lua --- core/src/xmake/engine.c | 2 ++ core/src/xmake/libc/strndup.c | 58 +++++++++++++++++++++++++++++++++++++++++++ core/src/xmake/makefile | 3 ++- xmake/core/base/bytes.lua | 15 ++++++----- xmake/core/base/libc.lua | 33 ++++++++++++++---------- 5 files changed, 91 insertions(+), 20 deletions(-) create mode 100644 core/src/xmake/libc/strndup.c diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index 5ca1d90f0..e8f774327 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -226,6 +226,7 @@ tb_int_t xm_libc_malloc(lua_State* lua); tb_int_t xm_libc_free(lua_State* lua); tb_int_t xm_libc_memcpy(lua_State* lua); tb_int_t xm_libc_memset(lua_State* lua); +tb_int_t xm_libc_strndup(lua_State* lua); tb_int_t xm_libc_dataptr(lua_State* lua); tb_int_t xm_libc_ptraddr(lua_State* lua); @@ -427,6 +428,7 @@ static luaL_Reg const g_libc_functions[] = , { "free", xm_libc_free } , { "memcpy", xm_libc_memcpy } , { "memset", xm_libc_memset } +, { "strndup", xm_libc_strndup } , { "dataptr", xm_libc_dataptr } , { "ptraddr", xm_libc_ptraddr } , { tb_null, tb_null } diff --git a/core/src/xmake/libc/strndup.c b/core/src/xmake/libc/strndup.c new file mode 100644 index 000000000..e0e1a1e02 --- /dev/null +++ b/core/src/xmake/libc/strndup.c @@ -0,0 +1,58 @@ +/*!A cross-platform build utility based on Lua + * + * 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 + * + * http://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. + * + * Copyright (C) 2015-present, TBOOX Open Source Group. + * + * @author ruki + * @file strndup.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "strndup" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_int_t xm_libc_strndup(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + // check arguments? + if (!xm_lua_ispointer(lua, 1) || !xm_lua_ispointer(lua, 2) || !lua_isnumber(lua, 3)) + xm_libc_return_error(lua, "strndup(invalid args)!"); + + // do strndup + tb_char_t const* s = tb_null; + if (xm_lua_ispointer(lua, 1)) + s = (tb_char_t const*)xm_lua_topointer(lua, 1); + else if (lua_isstring(lua, 2)) + s = lua_tostring(lua, 2); + else xm_libc_return_error(lua, "strndup(invalid args)!"); + tb_int_t n = (tb_int_t)lua_tointeger(lua, 2); + if (s && n >= 0) + lua_pushlstring(lua, s, n); + else lua_pushliteral(lua, ""); + return 1; +} + diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index 94df3a3e8..ae623c979 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -121,7 +121,8 @@ xmake_C_FILES += \ libc/memset \ libc/memcpy \ libc/dataptr \ - libc/ptraddr + libc/ptraddr \ + libc/strndup iswin = ifeq ($(PLAT),windows) diff --git a/xmake/core/base/bytes.lua b/xmake/core/base/bytes.lua index 8b2fa08cc..55c08e774 100644 --- a/xmake/core/base/bytes.lua +++ b/xmake/core/base/bytes.lua @@ -24,7 +24,6 @@ local _instance = _instance or {} -- load modules local bit = require("base/bit") -local ffi = xmake._LUAJIT and require("ffi") or nil local os = require("base/os") local utils = require("base/utils") local todisplay = require("base/todisplay") @@ -52,7 +51,7 @@ function _instance.new(...) local ptr = arg2 local manage = arg3 if manage then - instance._CDATA = ffi.gc(libc.dataptr(ptr), ffi.C.free) + instance._CDATA = libc.dataptr(ptr, {gc = true}) instance._MANAGED = true else instance._CDATA = libc.dataptr(ptr) @@ -70,7 +69,7 @@ function _instance.new(...) os.raise("invalid arguments #2 for bytes(size, ...), cdata, string, number or nil expected!") end end - local ptr = libc.gcmalloc(size) + local ptr = libc.malloc(size, {gc = true}) if init then libc.memset(ptr, init, size) end @@ -107,7 +106,7 @@ function _instance.new(...) for _, b in ipairs(args) do instance._SIZE = instance._SIZE + b:size() end - instance._CDATA = libc.gcmalloc(instance._SIZE) + instance._CDATA = libc.malloc(instance._SIZE, {gc = true}) local offset = 0 for _, b in ipairs(args) do libc.memcpy(instance._CDATA + offset, b:cdata(), b:size()) @@ -122,7 +121,7 @@ function _instance.new(...) for _, b in ipairs(args) do instance._SIZE = instance._SIZE + b:size() end - instance._CDATA = libc.gcmalloc(instance._SIZE) + instance._CDATA = libc.malloc(instance._SIZE, {gc = true}) local offset = 0 for _, b in ipairs(args) do libc.memcpy(instance._CDATA + offset, b._CDATA, b:size()) @@ -325,7 +324,7 @@ end -- convert bytes to string function _instance:str(i, j) local offset = i and i - 1 or 0 - return ffi.string(self:cdata() + offset, (j or self:size()) - offset) + return libc.strndup(self:cdata() + offset, (j or self:size()) - offset) end -- get uint8 value @@ -451,6 +450,10 @@ end -- it's only called for lua runtime, because bytes is not userdata function _instance:__gc() print("gc") + if self._MANAGED and self._CDATA then + libc.free(self._CDATA) + self._CDATA = nil + end end -- new an bytes instance diff --git a/xmake/core/base/libc.lua b/xmake/core/base/libc.lua index 20caff02b..1954f0fb1 100644 --- a/xmake/core/base/libc.lua +++ b/xmake/core/base/libc.lua @@ -40,23 +40,18 @@ if ffi then ]] end -function libc.malloc(size) +function libc.malloc(size, opt) if ffi then - return ffi.cast("unsigned char*", ffi.C.malloc(size)) + if opt and opt.gc then + return ffi.gc(ffi.cast("unsigned char*", ffi.C.malloc(size)), ffi.C.free) + else + return ffi.cast("unsigned char*", ffi.C.malloc(size)) + end else return libc._malloc(size) end end -function libc.gcmalloc(size) - if ffi then - return ffi.gc(ffi.cast("unsigned char*", ffi.C.malloc(size)), ffi.C.free) - else - -- @note we need free it in lua/__gc manually - return libc._malloc(size) - end -end - function libc.free(data) if ffi then return ffi.C.free(data) @@ -81,9 +76,21 @@ function libc.memset(data, ch, size) end end -function libc.dataptr(data) +function libc.strndup(s, n) + if ffi then + return ffi.string(s, n) + else + return libc._strndup(s, n) + end +end + +function libc.dataptr(data, opt) if ffi then - return ffi.cast("unsigned char*", data) + if opt and opt.gc then + return ffi.gc(ffi.cast("unsigned char*", data), ffi.C.free) + else + return ffi.cast("unsigned char*", data) + end else return libc._dataptr(data) end -- cgit v1.3.1 From 6bd955fbacc03792d8b36dffa087967e9e056e31 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 00:33:49 +0800 Subject: fix strndup --- core/src/xmake/engine.c | 2 ++ core/src/xmake/libc/dataptr.c | 2 +- core/src/xmake/libc/diffptr.c | 57 +++++++++++++++++++++++++++++++++++++++++++ core/src/xmake/libc/free.c | 2 +- core/src/xmake/libc/malloc.c | 2 +- core/src/xmake/libc/ptraddr.c | 2 +- core/src/xmake/libc/strndup.c | 6 +---- core/src/xmake/makefile | 1 + tests/modules/bytes/test.lua | 12 ++------- xmake/core/base/bytes.lua | 9 +++---- xmake/core/base/libc.lua | 24 +++++++++++++++--- 11 files changed, 92 insertions(+), 27 deletions(-) create mode 100644 core/src/xmake/libc/diffptr.c diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index e8f774327..f7d5a1c20 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -229,6 +229,7 @@ tb_int_t xm_libc_memset(lua_State* lua); tb_int_t xm_libc_strndup(lua_State* lua); tb_int_t xm_libc_dataptr(lua_State* lua); tb_int_t xm_libc_ptraddr(lua_State* lua); +tb_int_t xm_libc_diffptr(lua_State* lua); #ifdef XM_CONFIG_API_HAVE_CURSES // register curses @@ -431,6 +432,7 @@ static luaL_Reg const g_libc_functions[] = , { "strndup", xm_libc_strndup } , { "dataptr", xm_libc_dataptr } , { "ptraddr", xm_libc_ptraddr } +, { "diffptr", xm_libc_diffptr } , { tb_null, tb_null } }; diff --git a/core/src/xmake/libc/dataptr.c b/core/src/xmake/libc/dataptr.c index 4f983e5e7..a15fc108b 100644 --- a/core/src/xmake/libc/dataptr.c +++ b/core/src/xmake/libc/dataptr.c @@ -50,6 +50,6 @@ tb_int_t xm_libc_dataptr(lua_State* lua) xm_lua_pushpointer(lua, (tb_pointer_t)cstr); return 1; } - xm_libc_return_error(lua, "dataptr(invalid data)!"); + xm_libc_return_error(lua, "libc.dataptr(invalid data)!"); } diff --git a/core/src/xmake/libc/diffptr.c b/core/src/xmake/libc/diffptr.c new file mode 100644 index 000000000..213c843e7 --- /dev/null +++ b/core/src/xmake/libc/diffptr.c @@ -0,0 +1,57 @@ +/*!A cross-platform build utility based on Lua + * + * 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 + * + * http://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. + * + * Copyright (C) 2015-present, TBOOX Open Source Group. + * + * @author ruki + * @file diffptr.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "diffptr" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_int_t xm_libc_diffptr(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + // get data + tb_pointer_t data = tb_null; + if (xm_lua_ispointer(lua, 1)) + data = (tb_pointer_t)xm_lua_topointer(lua, 1); + else if (lua_isstring(lua, 1)) + data = (tb_pointer_t)luaL_checkstring(lua, 1); + else xm_libc_return_error(lua, "libc.diffptr(invalid data)!"); + + // get offset + tb_int_t offset = 0; + if (lua_isnumber(lua, 2)) + offset = (tb_int_t)lua_tonumber(lua, 2); + else xm_libc_return_error(lua, "libc.diffptr(invalid offset)!"); + xm_lua_pushpointer(lua, data + offset); + return 1; +} + diff --git a/core/src/xmake/libc/free.c b/core/src/xmake/libc/free.c index b4d17f1d0..f2edd3598 100644 --- a/core/src/xmake/libc/free.c +++ b/core/src/xmake/libc/free.c @@ -40,7 +40,7 @@ tb_int_t xm_libc_free(lua_State* lua) // check arguments? if (!xm_lua_ispointer(lua, 1)) - xm_libc_return_error(lua, "free(invalid data)!"); + xm_libc_return_error(lua, "libc.free(invalid data)!"); // do free tb_pointer_t data = (tb_pointer_t)xm_lua_topointer(lua, 1); diff --git a/core/src/xmake/libc/malloc.c b/core/src/xmake/libc/malloc.c index 0ee81e68f..bb4b4271f 100644 --- a/core/src/xmake/libc/malloc.c +++ b/core/src/xmake/libc/malloc.c @@ -40,7 +40,7 @@ tb_int_t xm_libc_malloc(lua_State* lua) // check arguments? if (!lua_isnumber(lua, 1)) - xm_libc_return_error(lua, "malloc(invalid size)!"); + xm_libc_return_error(lua, "libc.malloc(invalid size)!"); // do malloc tb_pointer_t data = tb_null; diff --git a/core/src/xmake/libc/ptraddr.c b/core/src/xmake/libc/ptraddr.c index 347bf60bf..6c9645cc2 100644 --- a/core/src/xmake/libc/ptraddr.c +++ b/core/src/xmake/libc/ptraddr.c @@ -50,6 +50,6 @@ tb_int_t xm_libc_ptraddr(lua_State* lua) lua_pushnumber(lua, (lua_Number)(tb_hize_t)cstr); return 1; } - xm_libc_return_error(lua, "ptraddr(invalid data)!"); + xm_libc_return_error(lua, "libc.ptraddr(invalid data)!"); } diff --git a/core/src/xmake/libc/strndup.c b/core/src/xmake/libc/strndup.c index e0e1a1e02..f2a3b8359 100644 --- a/core/src/xmake/libc/strndup.c +++ b/core/src/xmake/libc/strndup.c @@ -38,17 +38,13 @@ tb_int_t xm_libc_strndup(lua_State* lua) // check tb_assert_and_check_return_val(lua, 0); - // check arguments? - if (!xm_lua_ispointer(lua, 1) || !xm_lua_ispointer(lua, 2) || !lua_isnumber(lua, 3)) - xm_libc_return_error(lua, "strndup(invalid args)!"); - // do strndup tb_char_t const* s = tb_null; if (xm_lua_ispointer(lua, 1)) s = (tb_char_t const*)xm_lua_topointer(lua, 1); else if (lua_isstring(lua, 2)) s = lua_tostring(lua, 2); - else xm_libc_return_error(lua, "strndup(invalid args)!"); + else xm_libc_return_error(lua, "libc.strndup(invalid args)!"); tb_int_t n = (tb_int_t)lua_tointeger(lua, 2); if (s && n >= 0) lua_pushlstring(lua, s, n); diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index ae623c979..b766b272d 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -122,6 +122,7 @@ xmake_C_FILES += \ libc/memcpy \ libc/dataptr \ libc/ptraddr \ + libc/diffptr \ libc/strndup iswin = diff --git a/tests/modules/bytes/test.lua b/tests/modules/bytes/test.lua index 8d4504f2c..ac12db29c 100644 --- a/tests/modules/bytes/test.lua +++ b/tests/modules/bytes/test.lua @@ -1,9 +1,5 @@ import("core.base.bytes") -if not xmake.luajit() then - return -end - function test_ctor(t) t:are_equal(bytes("123456789"):str(), "123456789") t:are_equal(bytes(bytes("123456789")):str(), "123456789") @@ -12,19 +8,17 @@ function test_ctor(t) t:are_equal(bytes(10):size(), 10) t:are_equal(bytes(bytes("123"), bytes("456"), bytes("789")):str(), "123456789") t:are_equal(bytes({bytes("123"), bytes("456"), bytes("789")}):str(), "123456789") - debug.collectgarbage() end +--[[ function test_clone(t) t:are_equal(bytes(10):clone():size(), 10) t:are_equal(bytes("123456789"):clone():str(), "123456789") - debug.collectgarbage() end function test_slice(t) t:are_equal(bytes(10):slice(1, 2):size(), 2) t:are_equal(bytes("123456789"):slice(1, 4):str(), "1234") - debug.collectgarbage() end function test_index(t) @@ -37,11 +31,9 @@ function test_index(t) b[1] = string.byte('2') t:are_equal(b:str(), "223456789") t:will_raise(function() b[100] = string.byte('2') end) - debug.collectgarbage() end function test_concat(t) t:are_equal((bytes("123") .. bytes("456")):str(), "123456") t:are_equal(bytes(bytes("123"), bytes("456")):str(), "123456") - debug.collectgarbage() -end +end]] diff --git a/xmake/core/base/bytes.lua b/xmake/core/base/bytes.lua index 55c08e774..f35f20790 100644 --- a/xmake/core/base/bytes.lua +++ b/xmake/core/base/bytes.lua @@ -96,7 +96,7 @@ function _instance.new(...) os.raise("incorrect bounds(%d-%d) for bytes(...)!", start, last) end instance._SIZE = last - start + 1 - instance._CDATA = b:cdata() - 1 + start + instance._CDATA = libc.diffptr(b:cdata(), -1 + start) instance._REF = b -- keep lua ref for GC instance._MANAGED = false instance._READONLY = b:readonly() @@ -109,7 +109,7 @@ function _instance.new(...) instance._CDATA = libc.malloc(instance._SIZE, {gc = true}) local offset = 0 for _, b in ipairs(args) do - libc.memcpy(instance._CDATA + offset, b:cdata(), b:size()) + libc.memcpy(libc.diffptr(instance._CDATA, offset), b:cdata(), b:size()) offset = offset + b:size() end instance._MANAGED = true @@ -124,7 +124,7 @@ function _instance.new(...) instance._CDATA = libc.malloc(instance._SIZE, {gc = true}) local offset = 0 for _, b in ipairs(args) do - libc.memcpy(instance._CDATA + offset, b._CDATA, b:size()) + libc.memcpy(libc.diffptr(instance._CDATA, offset), b._CDATA, b:size()) offset = offset + b:size() end instance._MANAGED = true @@ -324,7 +324,7 @@ end -- convert bytes to string function _instance:str(i, j) local offset = i and i - 1 or 0 - return libc.strndup(self:cdata() + offset, (j or self:size()) - offset) + return libc.strndup(libc.diffptr(self:cdata(), offset), (j or self:size()) - offset) end -- get uint8 value @@ -449,7 +449,6 @@ end -- it's only called for lua runtime, because bytes is not userdata function _instance:__gc() - print("gc") if self._MANAGED and self._CDATA then libc.free(self._CDATA) self._CDATA = nil diff --git a/xmake/core/base/libc.lua b/xmake/core/base/libc.lua index 1954f0fb1..18c14a669 100644 --- a/xmake/core/base/libc.lua +++ b/xmake/core/base/libc.lua @@ -26,8 +26,10 @@ libc._malloc = libc._malloc or libc.malloc libc._free = libc._free or libc.free libc._memcpy = libc._memcpy or libc.memcpy libc._memset = libc._memset or libc.memset +libc._strndup = libc._strndup or libc.strndup libc._dataptr = libc._dataptr or libc.dataptr libc._ptraddr = libc._ptraddr or libc.ptraddr +libc._diffptr = libc._diffptr or libc.diffptr -- load modules local ffi = xmake._LUAJIT and require("ffi") @@ -48,7 +50,11 @@ function libc.malloc(size, opt) return ffi.cast("unsigned char*", ffi.C.malloc(size)) end else - return libc._malloc(size) + local data, errors = libc._malloc(size) + if not data then + os.raise(errors) + end + return data end end @@ -72,7 +78,7 @@ function libc.memset(data, ch, size) if ffi then return ffi.fill(data, size, ch) else - return libc._memset(data, ch, size) + libc._memset(data, ch, size) end end @@ -80,7 +86,19 @@ function libc.strndup(s, n) if ffi then return ffi.string(s, n) else - return libc._strndup(s, n) + local s, errors = libc._strndup(s, n) + if not s then + os.raise(errors) + end + return s + end +end + +function libc.diffptr(data, offset) + if ffi then + return data + offset + else + return libc._diffptr(data, offset) end end -- cgit v1.3.1 From de47ad0121ca4155777005976b05debeda67aca6 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 00:35:04 +0800 Subject: add byteof --- core/src/xmake/engine.c | 2 ++ core/src/xmake/libc/byteof.c | 58 ++++++++++++++++++++++++++++++++++++++++++++ core/src/xmake/makefile | 1 + tests/modules/bytes/test.lua | 3 +-- xmake/core/base/bytes.lua | 4 +-- xmake/core/base/libc.lua | 9 +++++++ 6 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 core/src/xmake/libc/byteof.c diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index f7d5a1c20..e4ac9f0f5 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -230,6 +230,7 @@ tb_int_t xm_libc_strndup(lua_State* lua); tb_int_t xm_libc_dataptr(lua_State* lua); tb_int_t xm_libc_ptraddr(lua_State* lua); tb_int_t xm_libc_diffptr(lua_State* lua); +tb_int_t xm_libc_byteof(lua_State* lua); #ifdef XM_CONFIG_API_HAVE_CURSES // register curses @@ -433,6 +434,7 @@ static luaL_Reg const g_libc_functions[] = , { "dataptr", xm_libc_dataptr } , { "ptraddr", xm_libc_ptraddr } , { "diffptr", xm_libc_diffptr } +, { "byteof", xm_libc_byteof } , { tb_null, tb_null } }; diff --git a/core/src/xmake/libc/byteof.c b/core/src/xmake/libc/byteof.c new file mode 100644 index 000000000..9d0031559 --- /dev/null +++ b/core/src/xmake/libc/byteof.c @@ -0,0 +1,58 @@ +/*!A cross-platform build utility based on Lua + * + * 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 + * + * http://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. + * + * Copyright (C) 2015-present, TBOOX Open Source Group. + * + * @author ruki + * @file byteof.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "byteof" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_int_t xm_libc_byteof(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + // get data + tb_pointer_t data = tb_null; + if (xm_lua_ispointer(lua, 1)) + data = (tb_pointer_t)xm_lua_topointer(lua, 1); + else if (lua_isstring(lua, 1)) + data = (tb_pointer_t)luaL_checkstring(lua, 1); + else xm_libc_return_error(lua, "libc.byteof(invalid data)!"); + + // get offset + tb_int_t offset = 0; + if (lua_isnumber(lua, 2)) + offset = (tb_int_t)lua_tonumber(lua, 2); + else xm_libc_return_error(lua, "libc.byteof(invalid offset)!"); + lua_pushinteger(lua, ((tb_byte_t const*)data)[offset]); + return 1; +} + + diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index b766b272d..a37003b37 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -123,6 +123,7 @@ xmake_C_FILES += \ libc/dataptr \ libc/ptraddr \ libc/diffptr \ + libc/byteof \ libc/strndup iswin = diff --git a/tests/modules/bytes/test.lua b/tests/modules/bytes/test.lua index ac12db29c..4cb272c94 100644 --- a/tests/modules/bytes/test.lua +++ b/tests/modules/bytes/test.lua @@ -10,7 +10,6 @@ function test_ctor(t) t:are_equal(bytes({bytes("123"), bytes("456"), bytes("789")}):str(), "123456789") end ---[[ function test_clone(t) t:are_equal(bytes(10):clone():size(), 10) t:are_equal(bytes("123456789"):clone():str(), "123456789") @@ -36,4 +35,4 @@ end function test_concat(t) t:are_equal((bytes("123") .. bytes("456")):str(), "123456") t:are_equal(bytes(bytes("123"), bytes("456")):str(), "123456") -end]] +end diff --git a/xmake/core/base/bytes.lua b/xmake/core/base/bytes.lua index f35f20790..0486f0178 100644 --- a/xmake/core/base/bytes.lua +++ b/xmake/core/base/bytes.lua @@ -138,7 +138,7 @@ function _instance.new(...) os.raise("incorrect bounds(%d-%d)!", start, last) end instance._SIZE = last - start + 1 - instance._CDATA = b:cdata() - 1 + start + instance._CDATA = libc.diffptr(b:cdata(), -1 + start) instance._REF = b -- keep lua ref for GC instance._MANAGED = false instance._READONLY = b:readonly() @@ -390,7 +390,7 @@ function _instance:__index(key) if key < 1 or key > self:size() then os.raise("%s: index(%d/%d) out of bounds!", self, key, self:size()) end - return self._CDATA[key - 1] + return libc.byteof(self._CDATA, key - 1) elseif type(key) == "table" then local start, last = key[1], key[2] return self:slice(start, last) diff --git a/xmake/core/base/libc.lua b/xmake/core/base/libc.lua index 18c14a669..d3f02d7f5 100644 --- a/xmake/core/base/libc.lua +++ b/xmake/core/base/libc.lua @@ -30,6 +30,7 @@ libc._strndup = libc._strndup or libc.strndup libc._dataptr = libc._dataptr or libc.dataptr libc._ptraddr = libc._ptraddr or libc.ptraddr libc._diffptr = libc._diffptr or libc.diffptr +libc._byteof = libc._byteof or libc.byteof -- load modules local ffi = xmake._LUAJIT and require("ffi") @@ -94,6 +95,14 @@ function libc.strndup(s, n) end end +function libc.byteof(data, offset) + if ffi then + return data[offset] + else + return libc._byteof(data, offset) + end +end + function libc.diffptr(data, offset) if ffi then return data + offset -- cgit v1.3.1 From 930124472561d7c4e84ee7fd2b1bee8ac1b64ba2 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 00:36:08 +0800 Subject: add setbyte --- core/src/xmake/engine.c | 2 ++ core/src/xmake/libc/setbyte.c | 62 +++++++++++++++++++++++++++++++++++++++++++ core/src/xmake/makefile | 1 + xmake/core/base/bytes.lua | 2 +- xmake/core/base/libc.lua | 9 +++++++ 5 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 core/src/xmake/libc/setbyte.c diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index e4ac9f0f5..e7c4c9644 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -231,6 +231,7 @@ tb_int_t xm_libc_dataptr(lua_State* lua); tb_int_t xm_libc_ptraddr(lua_State* lua); tb_int_t xm_libc_diffptr(lua_State* lua); tb_int_t xm_libc_byteof(lua_State* lua); +tb_int_t xm_libc_setbyte(lua_State* lua); #ifdef XM_CONFIG_API_HAVE_CURSES // register curses @@ -435,6 +436,7 @@ static luaL_Reg const g_libc_functions[] = , { "ptraddr", xm_libc_ptraddr } , { "diffptr", xm_libc_diffptr } , { "byteof", xm_libc_byteof } +, { "setbyte", xm_libc_setbyte } , { tb_null, tb_null } }; diff --git a/core/src/xmake/libc/setbyte.c b/core/src/xmake/libc/setbyte.c new file mode 100644 index 000000000..298e056a6 --- /dev/null +++ b/core/src/xmake/libc/setbyte.c @@ -0,0 +1,62 @@ +/*!A cross-platform build utility based on Lua + * + * 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 + * + * http://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. + * + * Copyright (C) 2015-present, TBOOX Open Source Group. + * + * @author ruki + * @file setbyte.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "setbyte" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_int_t xm_libc_setbyte(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + // get data + tb_pointer_t data = tb_null; + if (xm_lua_ispointer(lua, 1)) + data = (tb_pointer_t)xm_lua_topointer(lua, 1); + else if (lua_isstring(lua, 1)) + data = (tb_pointer_t)luaL_checkstring(lua, 1); + else xm_libc_return_error(lua, "libc.setbyte(invalid data)!"); + + // get offset + tb_int_t offset = 0; + if (lua_isnumber(lua, 2)) + offset = (tb_int_t)lua_tonumber(lua, 2); + else xm_libc_return_error(lua, "libc.setbyte(invalid offset)!"); + + // set byte + if (lua_isnumber(lua, 3)) + ((tb_byte_t*)data)[offset] = (tb_byte_t)lua_tointeger(lua, 3); + else xm_libc_return_error(lua, "libc.setbyte(invalid value)!"); + return 0; +} + + diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index a37003b37..5d3236c2d 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -124,6 +124,7 @@ xmake_C_FILES += \ libc/ptraddr \ libc/diffptr \ libc/byteof \ + libc/setbyte \ libc/strndup iswin = diff --git a/xmake/core/base/bytes.lua b/xmake/core/base/bytes.lua index 0486f0178..300d2a073 100644 --- a/xmake/core/base/bytes.lua +++ b/xmake/core/base/bytes.lua @@ -411,7 +411,7 @@ function _instance:__newindex(key, value) if key < 1 or key > self:size() then os.raise("%s: index(%d/%d) out of bounds!", self, key, self:size()) end - self._CDATA[key - 1] = value + libc.setbyte(self._CDATA, key - 1, value) return elseif type(key) == "table" then local start, last = key[1], key[2] diff --git a/xmake/core/base/libc.lua b/xmake/core/base/libc.lua index d3f02d7f5..6e69dd203 100644 --- a/xmake/core/base/libc.lua +++ b/xmake/core/base/libc.lua @@ -31,6 +31,7 @@ libc._dataptr = libc._dataptr or libc.dataptr libc._ptraddr = libc._ptraddr or libc.ptraddr libc._diffptr = libc._diffptr or libc.diffptr libc._byteof = libc._byteof or libc.byteof +libc._setbyte = libc._setbyte or libc.setbyte -- load modules local ffi = xmake._LUAJIT and require("ffi") @@ -103,6 +104,14 @@ function libc.byteof(data, offset) end end +function libc.setbyte(data, offset, value) + if ffi then + data[offset] = value + else + return libc._setbyte(data, offset, value) + end +end + function libc.diffptr(data, offset) if ffi then return data + offset -- cgit v1.3.1 From 76be569f033423850bca8f37129ccc9b347bddb3 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 00:36:25 +0800 Subject: enable bin2c test --- tests/projects/other/bin2c/test.lua | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/projects/other/bin2c/test.lua b/tests/projects/other/bin2c/test.lua index 8981b325d..b57362078 100644 --- a/tests/projects/other/bin2c/test.lua +++ b/tests/projects/other/bin2c/test.lua @@ -1,6 +1,3 @@ function main(t) - -- TODO - if xmake.luajit() then - t:build() - end + t:build() end -- cgit v1.3.1 From 4181bf780192cbf4be257fb7b658cfb390684a12 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 00:43:38 +0800 Subject: improve bit --- xmake/core/base/compat/bit.lua | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/xmake/core/base/compat/bit.lua b/xmake/core/base/compat/bit.lua index 78d5be389..c4a018382 100644 --- a/xmake/core/base/compat/bit.lua +++ b/xmake/core/base/compat/bit.lua @@ -41,5 +41,33 @@ function bit.bnot(a) return ~a end +-- bit/lshift operation +function bit.lshift(a, b) + return a << b +end + +-- bit/rshift operation +function bit.rshift(a, b) + return a >> b +end + +-- tobit operation +function bit.tobit(x) + return x & 0xffffffff +end + +-- tohex operation +function bit.tohex(x, n) + n = n or 8 + local up + if n <= 0 then + if n == 0 then return '' end + up = true + n = - n + end + x = x & (16 ^ n - 1) + return ('%0'..n..(up and 'X' or 'x')):format(x) +end + -- return module: bit return bit -- cgit v1.3.1 From bce8f65cb9f619dfa30d7b4b1fa2da9fa56b58e1 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 00:52:15 +0800 Subject: improve bytes --- core/src/xmake/engine.c | 4 --- core/src/xmake/libc/byteof.c | 6 ++--- core/src/xmake/libc/dataptr.c | 23 ++++++++--------- core/src/xmake/libc/diffptr.c | 57 ------------------------------------------- core/src/xmake/libc/free.c | 6 +---- core/src/xmake/libc/malloc.c | 8 ++---- core/src/xmake/libc/memcpy.c | 8 ++---- core/src/xmake/libc/memset.c | 6 +---- core/src/xmake/libc/ptraddr.c | 55 ----------------------------------------- core/src/xmake/libc/setbyte.c | 6 ++--- core/src/xmake/libc/strndup.c | 4 +-- core/src/xmake/makefile | 2 -- xmake/core/base/bytes.lua | 10 ++++---- xmake/core/base/libc.lua | 14 ++--------- 14 files changed, 31 insertions(+), 178 deletions(-) delete mode 100644 core/src/xmake/libc/diffptr.c delete mode 100644 core/src/xmake/libc/ptraddr.c diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index e7c4c9644..e6ecec020 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -228,8 +228,6 @@ tb_int_t xm_libc_memcpy(lua_State* lua); tb_int_t xm_libc_memset(lua_State* lua); tb_int_t xm_libc_strndup(lua_State* lua); tb_int_t xm_libc_dataptr(lua_State* lua); -tb_int_t xm_libc_ptraddr(lua_State* lua); -tb_int_t xm_libc_diffptr(lua_State* lua); tb_int_t xm_libc_byteof(lua_State* lua); tb_int_t xm_libc_setbyte(lua_State* lua); @@ -433,8 +431,6 @@ static luaL_Reg const g_libc_functions[] = , { "memset", xm_libc_memset } , { "strndup", xm_libc_strndup } , { "dataptr", xm_libc_dataptr } -, { "ptraddr", xm_libc_ptraddr } -, { "diffptr", xm_libc_diffptr } , { "byteof", xm_libc_byteof } , { "setbyte", xm_libc_setbyte } , { tb_null, tb_null } diff --git a/core/src/xmake/libc/byteof.c b/core/src/xmake/libc/byteof.c index 9d0031559..b6d757c81 100644 --- a/core/src/xmake/libc/byteof.c +++ b/core/src/xmake/libc/byteof.c @@ -40,8 +40,8 @@ tb_int_t xm_libc_byteof(lua_State* lua) // get data tb_pointer_t data = tb_null; - if (xm_lua_ispointer(lua, 1)) - data = (tb_pointer_t)xm_lua_topointer(lua, 1); + if (lua_isnumber(lua, 1)) + data = (tb_pointer_t)(tb_size_t)lua_tointeger(lua, 1); else if (lua_isstring(lua, 1)) data = (tb_pointer_t)luaL_checkstring(lua, 1); else xm_libc_return_error(lua, "libc.byteof(invalid data)!"); @@ -49,7 +49,7 @@ tb_int_t xm_libc_byteof(lua_State* lua) // get offset tb_int_t offset = 0; if (lua_isnumber(lua, 2)) - offset = (tb_int_t)lua_tonumber(lua, 2); + offset = (tb_int_t)lua_tointeger(lua, 2); else xm_libc_return_error(lua, "libc.byteof(invalid offset)!"); lua_pushinteger(lua, ((tb_byte_t const*)data)[offset]); return 1; diff --git a/core/src/xmake/libc/dataptr.c b/core/src/xmake/libc/dataptr.c index a15fc108b..d8d6c6f0d 100644 --- a/core/src/xmake/libc/dataptr.c +++ b/core/src/xmake/libc/dataptr.c @@ -38,18 +38,15 @@ tb_int_t xm_libc_dataptr(lua_State* lua) // check tb_assert_and_check_return_val(lua, 0); - if (xm_lua_ispointer(lua, 1)) - { - tb_pointer_t data = (tb_pointer_t)xm_lua_topointer(lua, 1); - xm_lua_pushpointer(lua, data); - return 1; - } - else if (lua_isstring(lua, 1)) - { - tb_char_t const* cstr = luaL_checkstring(lua, 1); - xm_lua_pushpointer(lua, (tb_pointer_t)cstr); - return 1; - } - xm_libc_return_error(lua, "libc.dataptr(invalid data)!"); + tb_pointer_t data = tb_null; + if (lua_isstring(lua, 1)) + data = (tb_pointer_t)luaL_checkstring(lua, 1); + else if (lua_isnumber(lua, 1)) + data = (tb_pointer_t)(tb_size_t)lua_tointeger(lua, 1); + else if (xm_lua_ispointer(lua, 1)) + data = (tb_pointer_t)xm_lua_topointer(lua, 1); + else xm_libc_return_error(lua, "libc.dataptr(invalid data)!"); + lua_pushinteger(lua, (lua_Integer)data); + return 1; } diff --git a/core/src/xmake/libc/diffptr.c b/core/src/xmake/libc/diffptr.c deleted file mode 100644 index 213c843e7..000000000 --- a/core/src/xmake/libc/diffptr.c +++ /dev/null @@ -1,57 +0,0 @@ -/*!A cross-platform build utility based on Lua - * - * 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 - * - * http://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. - * - * Copyright (C) 2015-present, TBOOX Open Source Group. - * - * @author ruki - * @file diffptr.c - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "diffptr" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_int_t xm_libc_diffptr(lua_State* lua) -{ - // check - tb_assert_and_check_return_val(lua, 0); - - // get data - tb_pointer_t data = tb_null; - if (xm_lua_ispointer(lua, 1)) - data = (tb_pointer_t)xm_lua_topointer(lua, 1); - else if (lua_isstring(lua, 1)) - data = (tb_pointer_t)luaL_checkstring(lua, 1); - else xm_libc_return_error(lua, "libc.diffptr(invalid data)!"); - - // get offset - tb_int_t offset = 0; - if (lua_isnumber(lua, 2)) - offset = (tb_int_t)lua_tonumber(lua, 2); - else xm_libc_return_error(lua, "libc.diffptr(invalid offset)!"); - xm_lua_pushpointer(lua, data + offset); - return 1; -} - diff --git a/core/src/xmake/libc/free.c b/core/src/xmake/libc/free.c index f2edd3598..4fa549975 100644 --- a/core/src/xmake/libc/free.c +++ b/core/src/xmake/libc/free.c @@ -38,12 +38,8 @@ tb_int_t xm_libc_free(lua_State* lua) // check tb_assert_and_check_return_val(lua, 0); - // check arguments? - if (!xm_lua_ispointer(lua, 1)) - xm_libc_return_error(lua, "libc.free(invalid data)!"); - // do free - tb_pointer_t data = (tb_pointer_t)xm_lua_topointer(lua, 1); + tb_pointer_t data = (tb_pointer_t)(tb_size_t)luaL_checkinteger(lua, 1); if (data) tb_free(data); return 0; } diff --git a/core/src/xmake/libc/malloc.c b/core/src/xmake/libc/malloc.c index bb4b4271f..ae13547a3 100644 --- a/core/src/xmake/libc/malloc.c +++ b/core/src/xmake/libc/malloc.c @@ -38,15 +38,11 @@ tb_int_t xm_libc_malloc(lua_State* lua) // check tb_assert_and_check_return_val(lua, 0); - // check arguments? - if (!lua_isnumber(lua, 1)) - xm_libc_return_error(lua, "libc.malloc(invalid size)!"); - // do malloc tb_pointer_t data = tb_null; - tb_int_t size = (tb_int_t)lua_tointeger(lua, 1); + tb_long_t size = (tb_long_t)luaL_checkinteger(lua, 1); if (size > 0) data = tb_malloc(size); - xm_lua_pushpointer(lua, data); + lua_pushinteger(lua, (lua_Integer)data); return 1; } diff --git a/core/src/xmake/libc/memcpy.c b/core/src/xmake/libc/memcpy.c index e2c9af4c3..3f8d3b36e 100644 --- a/core/src/xmake/libc/memcpy.c +++ b/core/src/xmake/libc/memcpy.c @@ -38,13 +38,9 @@ tb_int_t xm_libc_memcpy(lua_State* lua) // check tb_assert_and_check_return_val(lua, 0); - // check arguments? - if (!xm_lua_ispointer(lua, 1) || !xm_lua_ispointer(lua, 2) || !lua_isnumber(lua, 3)) - xm_libc_return_error(lua, "memcpy(invalid args)!"); - // do memcpy - tb_pointer_t dst = (tb_pointer_t)xm_lua_topointer(lua, 1); - tb_pointer_t src = (tb_pointer_t)xm_lua_topointer(lua, 2); + tb_pointer_t dst = (tb_pointer_t)(tb_size_t)luaL_checkinteger(lua, 1); + tb_pointer_t src = (tb_pointer_t)(tb_size_t)luaL_checkinteger(lua, 2); tb_int_t size = (tb_int_t)lua_tointeger(lua, 3); if (dst && src && size > 0) tb_memcpy(dst, src, size); diff --git a/core/src/xmake/libc/memset.c b/core/src/xmake/libc/memset.c index c3171bace..5aef08105 100644 --- a/core/src/xmake/libc/memset.c +++ b/core/src/xmake/libc/memset.c @@ -38,12 +38,8 @@ tb_int_t xm_libc_memset(lua_State* lua) // check tb_assert_and_check_return_val(lua, 0); - // check arguments? - if (!xm_lua_ispointer(lua, 1) || !lua_isnumber(lua, 2) || !lua_isnumber(lua, 3)) - xm_libc_return_error(lua, "memset(invalid args)!"); - // do memset - tb_pointer_t data = (tb_pointer_t)xm_lua_topointer(lua, 1); + tb_pointer_t data = (tb_pointer_t)(tb_size_t)luaL_checkinteger(lua, 1); tb_char_t ch = (tb_char_t)lua_tointeger(lua, 2); tb_int_t size = (tb_int_t)lua_tointeger(lua, 3); if (data && size > 0) diff --git a/core/src/xmake/libc/ptraddr.c b/core/src/xmake/libc/ptraddr.c deleted file mode 100644 index 6c9645cc2..000000000 --- a/core/src/xmake/libc/ptraddr.c +++ /dev/null @@ -1,55 +0,0 @@ -/*!A cross-platform build utility based on Lua - * - * 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 - * - * http://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. - * - * Copyright (C) 2015-present, TBOOX Open Source Group. - * - * @author ruki - * @file ptraddr.c - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "ptraddr" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_int_t xm_libc_ptraddr(lua_State* lua) -{ - // check - tb_assert_and_check_return_val(lua, 0); - - if (xm_lua_ispointer(lua, 1)) - { - tb_pointer_t data = (tb_pointer_t)xm_lua_topointer(lua, 1); - lua_pushnumber(lua, (lua_Number)(tb_hize_t)data); - return 1; - } - else if (lua_isstring(lua, 1)) - { - tb_char_t const* cstr = luaL_checkstring(lua, 1); - lua_pushnumber(lua, (lua_Number)(tb_hize_t)cstr); - return 1; - } - xm_libc_return_error(lua, "libc.ptraddr(invalid data)!"); -} - diff --git a/core/src/xmake/libc/setbyte.c b/core/src/xmake/libc/setbyte.c index 298e056a6..5027411a8 100644 --- a/core/src/xmake/libc/setbyte.c +++ b/core/src/xmake/libc/setbyte.c @@ -40,8 +40,8 @@ tb_int_t xm_libc_setbyte(lua_State* lua) // get data tb_pointer_t data = tb_null; - if (xm_lua_ispointer(lua, 1)) - data = (tb_pointer_t)xm_lua_topointer(lua, 1); + if (lua_isnumber(lua, 1)) + data = (tb_pointer_t)(tb_size_t)lua_tointeger(lua, 1); else if (lua_isstring(lua, 1)) data = (tb_pointer_t)luaL_checkstring(lua, 1); else xm_libc_return_error(lua, "libc.setbyte(invalid data)!"); @@ -49,7 +49,7 @@ tb_int_t xm_libc_setbyte(lua_State* lua) // get offset tb_int_t offset = 0; if (lua_isnumber(lua, 2)) - offset = (tb_int_t)lua_tonumber(lua, 2); + offset = (tb_int_t)lua_tointeger(lua, 2); else xm_libc_return_error(lua, "libc.setbyte(invalid offset)!"); // set byte diff --git a/core/src/xmake/libc/strndup.c b/core/src/xmake/libc/strndup.c index f2a3b8359..b56a76714 100644 --- a/core/src/xmake/libc/strndup.c +++ b/core/src/xmake/libc/strndup.c @@ -40,8 +40,8 @@ tb_int_t xm_libc_strndup(lua_State* lua) // do strndup tb_char_t const* s = tb_null; - if (xm_lua_ispointer(lua, 1)) - s = (tb_char_t const*)xm_lua_topointer(lua, 1); + if (lua_isnumber(lua, 1)) + s = (tb_char_t const*)(tb_size_t)lua_tointeger(lua, 1); else if (lua_isstring(lua, 2)) s = lua_tostring(lua, 2); else xm_libc_return_error(lua, "libc.strndup(invalid args)!"); diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index 5d3236c2d..b29e8cc20 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -121,8 +121,6 @@ xmake_C_FILES += \ libc/memset \ libc/memcpy \ libc/dataptr \ - libc/ptraddr \ - libc/diffptr \ libc/byteof \ libc/setbyte \ libc/strndup diff --git a/xmake/core/base/bytes.lua b/xmake/core/base/bytes.lua index 300d2a073..9f7b6ca4f 100644 --- a/xmake/core/base/bytes.lua +++ b/xmake/core/base/bytes.lua @@ -96,7 +96,7 @@ function _instance.new(...) os.raise("incorrect bounds(%d-%d) for bytes(...)!", start, last) end instance._SIZE = last - start + 1 - instance._CDATA = libc.diffptr(b:cdata(), -1 + start) + instance._CDATA = b:cdata() -1 + start instance._REF = b -- keep lua ref for GC instance._MANAGED = false instance._READONLY = b:readonly() @@ -109,7 +109,7 @@ function _instance.new(...) instance._CDATA = libc.malloc(instance._SIZE, {gc = true}) local offset = 0 for _, b in ipairs(args) do - libc.memcpy(libc.diffptr(instance._CDATA, offset), b:cdata(), b:size()) + libc.memcpy(instance._CDATA + offset, b:cdata(), b:size()) offset = offset + b:size() end instance._MANAGED = true @@ -124,7 +124,7 @@ function _instance.new(...) instance._CDATA = libc.malloc(instance._SIZE, {gc = true}) local offset = 0 for _, b in ipairs(args) do - libc.memcpy(libc.diffptr(instance._CDATA, offset), b._CDATA, b:size()) + libc.memcpy(instance._CDATA + offset, b._CDATA, b:size()) offset = offset + b:size() end instance._MANAGED = true @@ -138,7 +138,7 @@ function _instance.new(...) os.raise("incorrect bounds(%d-%d)!", start, last) end instance._SIZE = last - start + 1 - instance._CDATA = libc.diffptr(b:cdata(), -1 + start) + instance._CDATA = b:cdata() -1 + start instance._REF = b -- keep lua ref for GC instance._MANAGED = false instance._READONLY = b:readonly() @@ -324,7 +324,7 @@ end -- convert bytes to string function _instance:str(i, j) local offset = i and i - 1 or 0 - return libc.strndup(libc.diffptr(self:cdata(), offset), (j or self:size()) - offset) + return libc.strndup(self:cdata() + offset, (j or self:size()) - offset) end -- get uint8 value diff --git a/xmake/core/base/libc.lua b/xmake/core/base/libc.lua index 6e69dd203..9aecb8af5 100644 --- a/xmake/core/base/libc.lua +++ b/xmake/core/base/libc.lua @@ -28,8 +28,6 @@ libc._memcpy = libc._memcpy or libc.memcpy libc._memset = libc._memset or libc.memset libc._strndup = libc._strndup or libc.strndup libc._dataptr = libc._dataptr or libc.dataptr -libc._ptraddr = libc._ptraddr or libc.ptraddr -libc._diffptr = libc._diffptr or libc.diffptr libc._byteof = libc._byteof or libc.byteof libc._setbyte = libc._setbyte or libc.setbyte @@ -112,14 +110,6 @@ function libc.setbyte(data, offset, value) end end -function libc.diffptr(data, offset) - if ffi then - return data + offset - else - return libc._diffptr(data, offset) - end -end - function libc.dataptr(data, opt) if ffi then if opt and opt.gc then @@ -128,7 +118,7 @@ function libc.dataptr(data, opt) return ffi.cast("unsigned char*", data) end else - return libc._dataptr(data) + return type(data) == "number" and data or libc._dataptr(data) end end @@ -136,7 +126,7 @@ function libc.ptraddr(data) if ffi then return tonumber(ffi.cast('unsigned long long', data)) else - return libc._ptraddr(data) + return data end end -- cgit v1.3.1 From 0980e7b7e3eb331c87e96148bfab4d9a74784a00 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 00:55:16 +0800 Subject: improve check_cincludes --- xmake/includes/check_cincludes.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xmake/includes/check_cincludes.lua b/xmake/includes/check_cincludes.lua index d5e4cf4a3..7f2727d77 100644 --- a/xmake/includes/check_cincludes.lua +++ b/xmake/includes/check_cincludes.lua @@ -30,6 +30,9 @@ function check_cincludes(definition, includes, opt) local optname = "__" .. (opt.name or definition) option(optname) add_cincludes(includes) + if opt.includedirs then + add_includedirs(opt.includedirs) + end add_defines(definition) option_end() add_options(optname) @@ -48,6 +51,9 @@ function configvar_check_cincludes(definition, includes, opt) local defname, defval = unpack(definition:split('=')) option(optname) add_cincludes(includes) + if opt.includedirs then + add_includedirs(opt.includedirs) + end set_configvar(defname, defval or 1) option_end() add_options(optname) -- cgit v1.3.1 From eee6ab7a99c93953eed53d33c4a61fa1172971aa Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 00:57:30 +0800 Subject: add cppflags for tools/autoconf --- xmake/modules/package/tools/autoconf.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xmake/modules/package/tools/autoconf.lua b/xmake/modules/package/tools/autoconf.lua index 9e4f8c4b4..3e1541fe2 100644 --- a/xmake/modules/package/tools/autoconf.lua +++ b/xmake/modules/package/tools/autoconf.lua @@ -150,6 +150,7 @@ function buildenvs(package, opt) table.join2(cflags, opt.cxflags) table.join2(cxxflags, opt.cxxflags) table.join2(cxxflags, opt.cxflags) + table.join2(cppflags, opt.cppflags) -- @see https://github.com/xmake-io/xmake/issues/1688 table.join2(asflags, opt.asflags) table.join2(ldflags, opt.ldflags) table.join2(shflags, opt.shflags) @@ -177,6 +178,7 @@ function buildenvs(package, opt) envs.RANLIB = package:build_getenv("ranlib") envs.CFLAGS = table.concat(cflags, ' ') envs.CXXFLAGS = table.concat(cxxflags, ' ') + envs.CPPFLAGS = table.concat(cppflags, ' ') envs.ASFLAGS = table.concat(asflags, ' ') envs.ARFLAGS = table.concat(arflags, ' ') envs.LDFLAGS = table.concat(ldflags, ' ') -- cgit v1.3.1 From c0604c67543a2269d0bc986735ea56b073f5d2ab Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 00:58:40 +0800 Subject: update xmake.rc --- core/src/demo/xmake.rc | 2 +- tests/projects/xmake_cli/xmake/src/xmake.rc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/demo/xmake.rc b/core/src/demo/xmake.rc index 0d737ebc3..2167c8f25 100644 --- a/core/src/demo/xmake.rc +++ b/core/src/demo/xmake.rc @@ -26,7 +26,7 @@ BEGIN VALUE "FileDescription", "XMake build utility" VALUE "FileVersion", XM_CONFIG_VERSION "+" STR(XM_CONFIG_VERSION_BUILD) VALUE "InternalName", "xmake" - VALUE "LegalCopyright", "Copyright (C) 2015-2020 Ruki Wang, tboox.org, xmake.io\nCopyright (C) 2005-2015 Mike Pall, luajit.org" + VALUE "LegalCopyright", "Copyright (C) 2015-present Ruki Wang, tboox.org, xmake.io" VALUE "LegalTrademarks", "" VALUE "OriginalFilename", "xmake.exe" VALUE "ProductName", "XMake" diff --git a/tests/projects/xmake_cli/xmake/src/xmake.rc b/tests/projects/xmake_cli/xmake/src/xmake.rc index 0d737ebc3..2167c8f25 100644 --- a/tests/projects/xmake_cli/xmake/src/xmake.rc +++ b/tests/projects/xmake_cli/xmake/src/xmake.rc @@ -26,7 +26,7 @@ BEGIN VALUE "FileDescription", "XMake build utility" VALUE "FileVersion", XM_CONFIG_VERSION "+" STR(XM_CONFIG_VERSION_BUILD) VALUE "InternalName", "xmake" - VALUE "LegalCopyright", "Copyright (C) 2015-2020 Ruki Wang, tboox.org, xmake.io\nCopyright (C) 2005-2015 Mike Pall, luajit.org" + VALUE "LegalCopyright", "Copyright (C) 2015-present Ruki Wang, tboox.org, xmake.io" VALUE "LegalTrademarks", "" VALUE "OriginalFilename", "xmake.exe" VALUE "ProductName", "XMake" -- cgit v1.3.1 From 06cceecff66e8b5473095e77cd2b95e70b0d66ce Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 21:06:57 +0800 Subject: fix autoconf --- xmake/modules/package/tools/autoconf.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xmake/modules/package/tools/autoconf.lua b/xmake/modules/package/tools/autoconf.lua index 3e1541fe2..b0607ac0d 100644 --- a/xmake/modules/package/tools/autoconf.lua +++ b/xmake/modules/package/tools/autoconf.lua @@ -112,6 +112,7 @@ end function buildenvs(package, opt) opt = opt or {} local envs = {} + local cppflags = {} if package:is_plat(os.subhost()) then local cflags = table.join(table.wrap(package:config("cxflags")), package:config("cflags")) local cxxflags = table.join(table.wrap(package:config("cxflags")), package:config("cxxflags")) @@ -127,10 +128,12 @@ function buildenvs(package, opt) table.join2(cflags, opt.cxflags) table.join2(cxxflags, opt.cxxflags) table.join2(cxxflags, opt.cxflags) + table.join2(cppflags, opt.cppflags) -- @see https://github.com/xmake-io/xmake/issues/1688 table.join2(asflags, opt.asflags) table.join2(ldflags, opt.ldflags) envs.CFLAGS = table.concat(cflags, ' ') envs.CXXFLAGS = table.concat(cxxflags, ' ') + envs.CPPFLAGS = table.concat(cppflags, ' ') envs.ASFLAGS = table.concat(asflags, ' ') envs.LDFLAGS = table.concat(ldflags, ' ') else -- cgit v1.3.1 From a99208ddf3cda05ba4ddc18ff8ac44857eb8a649 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 22:53:08 +0800 Subject: improve xmake options --- core/src/lcurses/xmake.lua | 2 +- core/src/lua-cjson/xmake.lua | 2 +- core/src/xmake/engine.c | 2 +- core/src/xmake/xmake.lua | 2 +- core/xmake.lua | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/src/lcurses/xmake.lua b/core/src/lcurses/xmake.lua index 5ee8a26c6..d01058c56 100644 --- a/core/src/lcurses/xmake.lua +++ b/core/src/lcurses/xmake.lua @@ -1,6 +1,6 @@ target("lcurses") set_kind("static") - add_deps(get_config("backend")) + add_deps(get_config("runtime")) if is_plat("windows") and has_config("pdcurses") then add_deps("pdcurses") add_defines("XM_CONFIG_API_HAVE_CURSES", {public = true}) diff --git a/core/src/lua-cjson/xmake.lua b/core/src/lua-cjson/xmake.lua index d3b12ded1..75b62c16b 100644 --- a/core/src/lua-cjson/xmake.lua +++ b/core/src/lua-cjson/xmake.lua @@ -1,7 +1,7 @@ target("lua-cjson") set_kind("static") set_warnings("all") - add_deps(get_config("backend")) + add_deps(get_config("runtime")) if is_plat("windows") then set_languages("c89") end diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index e6ecec020..dbea858c1 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -919,7 +919,7 @@ xm_engine_ref_t xm_engine_init(tb_char_t const* name, xm_engine_lni_initalizer_c lua_pushstring(engine->lua, name? name : "xmake"); lua_setglobal(engine->lua, "_NAME"); - // use luajit as backend? + // use luajit as runtime? #ifdef USE_LUAJIT lua_pushboolean(engine->lua, tb_true); #else diff --git a/core/src/xmake/xmake.lua b/core/src/xmake/xmake.lua index c954db65b..0b0693c9b 100644 --- a/core/src/xmake/xmake.lua +++ b/core/src/xmake/xmake.lua @@ -8,7 +8,7 @@ target("xmake") add_deps("lcurses") end add_deps("sv", "lua-cjson", "tbox") - add_deps(get_config("backend")) + add_deps(get_config("runtime")) -- add defines add_defines("__tb_prefix__=\"xmake\"") diff --git a/core/xmake.lua b/core/xmake.lua index 592bc7c95..71253d8ae 100644 --- a/core/xmake.lua +++ b/core/xmake.lua @@ -40,11 +40,11 @@ if is_mode("coverage") then add_ldflags("-coverage", "-fprofile-arcs", "-ftest-coverage") end --- the backend option -option("backend") +-- the runtime option +option("runtime") set_showmenu(true) set_default("luajit") - set_description("Use luajit or lua backend") + set_description("Use luajit or lua runtime") set_values("luajit", "lua") option_end() -- cgit v1.3.1 From e1338ed43cf207c8df99027ffe3fe05a856c8eaa Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 23:03:51 +0800 Subject: improve msvc toolchain --- xmake/toolchains/msvc/load.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/toolchains/msvc/load.lua b/xmake/toolchains/msvc/load.lua index bb7e2de3d..195815590 100644 --- a/xmake/toolchains/msvc/load.lua +++ b/xmake/toolchains/msvc/load.lua @@ -66,6 +66,6 @@ function main(toolchain) _add_vsenv(toolchain, "WindowsSDKVersion") -- add some default flags - toolchain:add("cxxflags", "/EHsc") + toolchain:add("cl.cxxflags", "/EHsc") end -- cgit v1.3.1 From 42dab62b8525aa52a339b57003524156d25cd08f Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 23:07:27 +0800 Subject: attempt to switch lua runtime for windows --- core/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/xmake.lua b/core/xmake.lua index 71253d8ae..a9108c487 100644 --- a/core/xmake.lua +++ b/core/xmake.lua @@ -43,7 +43,7 @@ end -- the runtime option option("runtime") set_showmenu(true) - set_default("luajit") + set_default("lua") set_description("Use luajit or lua runtime") set_values("luajit", "lua") option_end() -- cgit v1.3.1 From d25d5d11dc33e252809b61631203ce862e06b058 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 23:08:32 +0800 Subject: fix compile errors --- core/src/xmake/io/stdfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/xmake/io/stdfile.c b/core/src/xmake/io/stdfile.c index 67823cf3e..1daf7c794 100644 --- a/core/src/xmake/io/stdfile.c +++ b/core/src/xmake/io/stdfile.c @@ -120,7 +120,7 @@ tb_int_t xm_io_stdfile(lua_State* lua) tb_assert_and_check_return_val(lua, 0); // get std type - tb_long_t type = lua_tointeger(lua, 1); + tb_long_t type = (tb_long_t)lua_tointeger(lua, 1); /* push a new stdfile * -- cgit v1.3.1 From 041b40c1cdb33052b48bcec8050fa9bcdaaadce2 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 23:09:33 +0800 Subject: fix compile errors --- core/src/xmake/os/find.c | 4 ++-- core/src/xmake/winos/registry_keys.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/xmake/os/find.c b/core/src/xmake/os/find.c index 9d6a17eff..28539a138 100644 --- a/core/src/xmake/os/find.c +++ b/core/src/xmake/os/find.c @@ -177,10 +177,10 @@ tb_int_t xm_os_find(lua_State* lua) tb_check_return_val(pattern, 0); // the recursion level - tb_long_t recursion = lua_tointeger(lua, 3); + tb_long_t recursion = (tb_long_t)lua_tointeger(lua, 3); // the match mode - tb_long_t mode = lua_tointeger(lua, 4); + tb_long_t mode = (tb_long_t)lua_tointeger(lua, 4); // init table lua_newtable(lua); diff --git a/core/src/xmake/winos/registry_keys.c b/core/src/xmake/winos/registry_keys.c index 234cdf035..9c3467210 100644 --- a/core/src/xmake/winos/registry_keys.c +++ b/core/src/xmake/winos/registry_keys.c @@ -172,7 +172,7 @@ tb_int_t xm_winos_registry_keys(lua_State* lua) // get the arguments tb_char_t const* rootkey = luaL_checkstring(lua, 1); tb_char_t const* rootdir = luaL_checkstring(lua, 2); - tb_long_t recursion = lua_tointeger(lua, 3); + tb_long_t recursion = (tb_long_t)lua_tointeger(lua, 3); tb_bool_t is_function = lua_isfunction(lua, 4); tb_check_return_val(rootkey && rootdir && is_function, 0); -- cgit v1.3.1 From f13f41af8efd73db63f6a1ebdc759477e0f3a0b0 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 23:11:03 +0800 Subject: revert to luajit on win --- core/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/xmake.lua b/core/xmake.lua index a9108c487..71253d8ae 100644 --- a/core/xmake.lua +++ b/core/xmake.lua @@ -43,7 +43,7 @@ end -- the runtime option option("runtime") set_showmenu(true) - set_default("lua") + set_default("luajit") set_description("Use luajit or lua runtime") set_values("luajit", "lua") option_end() -- cgit v1.3.1 From f983b338f13830bacc39cc1f23d2e45b65c242b9 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 23:11:44 +0800 Subject: add windows lua ci --- .github/workflows/windows_lua.yml | 122 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 .github/workflows/windows_lua.yml diff --git a/.github/workflows/windows_lua.yml b/.github/workflows/windows_lua.yml new file mode 100644 index 000000000..b9352918d --- /dev/null +++ b/.github/workflows/windows_lua.yml @@ -0,0 +1,122 @@ +name: Windows (Lua) + +on: + pull_request: + push: + release: + types: [published] + +jobs: + build: + strategy: + matrix: + os: [windows-latest, windows-2016] + arch: [x64, x86] + + runs-on: ${{ matrix.os }} + + concurrency: + group: ${{ github.head_ref }}-${{ matrix.os }}-${{ matrix.arch }}-Windows-Lua + cancel-in-progress: true + steps: + - uses: actions/checkout@v2 + with: + # WyriHaximus/github-action-get-previous-tag@master need it + fetch-depth: 0 + submodules: true + - uses: xmake-io/github-action-setup-xmake@v1 + with: + # this is not supported, use dev branch instead + # xmake-version: local# + xmake-version: branch@dev + - uses: dlang-community/setup-dlang@v1 + with: + compiler: dmd-latest + - uses: little-core-labs/get-git-tag@v3.0.2 + id: tagName + + - name: Prepare + run: | + xmake show + Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/nsis-3.04.zip" -UseBasicParsing -OutFile ./nsis.zip + Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/nsis-3.04-strlen_8192.zip" -UseBasicParsing -OutFile ./nsis-longstr.zip + Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/UAC.zip" -UseBasicParsing -OutFile ./nsis-uac.zip + Expand-Archive ./nsis.zip -DestinationPath ./nsis + Move-Item ./nsis/*/* ./nsis + Expand-Archive ./nsis-longstr.zip -DestinationPath ./nsis -Force + Expand-Archive ./nsis-uac.zip -DestinationPath ./nsis -Force + Move-Item ./nsis/UAC.nsh ./nsis/Include/ + + - name: Build + run: | + xmake f -vD -P core -a ${{ matrix.arch }} --runtime=lua + xmake -vD -P core + + - name: Tests + run: | + Copy-Item ./core/build/xmake.exe ./xmake + Copy-Item ./scripts/xrepo.bat ./xmake + Copy-Item ./scripts/xrepo.ps1 ./xmake + $Env:XMAKE_PROGRAM_DIR = $(Resolve-Path ./xmake) + Set-Item -Path Env:Path -Value ($Env:XMAKE_PROGRAM_DIR + ";" + $Env:Path) + xrepo --version + xmake show + #xmake l -v private.utils.bcsave --rootname='@programdir' -x 'scripts/**|templates/**' xmake + xmake lua -v -D tests/run.lua + + - name: Set release arch name + run: | + if ("${{ matrix.arch }}" -eq "x64") { + Write-Output "RELEASE_NAME=win64" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf-8 -Append + } else { + Write-Output "RELEASE_NAME=win32" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf-8 -Append + } + - name: Artifact + run: | + # build installer + (New-Item ./winenv/bin -ItemType Directory).FullName + Invoke-WebRequest "https://github.com/xmake-mirror/7zip/releases/download/19.00/7z19.00-${{ matrix.arch }}.zip" -UseBasicParsing -OutFile .\7zip.zip + Expand-Archive ./7zip.zip -DestinationPath ./7zip + Copy-Item ./7zip/7z.exe ./winenv/bin + Copy-Item ./7zip/7z.dll ./winenv/bin + Invoke-WebRequest "https://curl.se/windows/dl-7.78.0_2/curl-7.78.0_2-win32-mingw.zip" -UseBasicParsing -OutFile .\curl.zip + Expand-Archive ./curl.zip -DestinationPath ./curl + Copy-Item ./curl/curl-7.78.0-win32-mingw/bin/curl.exe ./winenv/bin + Copy-Item ./curl/curl-7.78.0-win32-mingw/bin/curl-ca-bundle.crt ./winenv/bin + $version = (Get-Command xmake/xmake.exe).FileVersionInfo + ./nsis/makensis.exe /DMAJOR=$($version.ProductMajorPart) /DMINOR=$($version.ProductMinorPart) /DALTER=$($version.ProductBuildPart) /DBUILD=$($($version.ProductVersion -split '\+')[1]) /D${{ matrix.arch }} .\scripts\installer.nsi + (New-Item ./artifacts/${{env.RELEASE_NAME}} -ItemType Directory).FullName + Copy-Item scripts/xmake.exe ./artifacts/${{env.RELEASE_NAME}}/xmake.exe + # archive + Copy-Item ./*.md ./xmake + Copy-Item ./winenv ./xmake -Recurse + Add-Type -AssemblyName System.Text.Encoding + Add-Type -AssemblyName System.IO.Compression.FileSystem + class FixedEncoder : System.Text.UTF8Encoding { + FixedEncoder() : base($true) { } + [byte[]] GetBytes([string] $s) + { + $s = $s.Replace("\", "/") + return ([System.Text.UTF8Encoding]$this).GetBytes($s) + } + } + Copy-Item ./xmake ./archive/xmake -Recurse + [System.IO.Compression.ZipFile]::CreateFromDirectory("$PWD\archive", "$PWD\archive.zip", [System.IO.Compression.CompressionLevel]::Optimal, $false, [FixedEncoder]::new()) + (Get-FileHash .\archive.zip -Algorithm SHA256).Hash.ToLower() + " *xmake.zip`n" | Out-File ./shafile -Encoding ASCII -NoNewLine -Append + Copy-Item archive.zip ./artifacts/${{env.RELEASE_NAME}} + Copy-Item shafile ./artifacts/${{env.RELEASE_NAME}} + + # upload artifacts + - uses: actions/upload-artifact@v2 + with: + name: xmake-latest.${{env.RELEASE_NAME}}.exe + path: artifacts/${{env.RELEASE_NAME}}/xmake.exe + - uses: actions/upload-artifact@v2 + with: + name: xmake-latest.${{ env.RELEASE_NAME }}.zip + path: artifacts/${{env.RELEASE_NAME}}/archive.zip + - uses: actions/upload-artifact@v2 + with: + name: xmake-latest.${{ env.RELEASE_NAME }}.sha256 + path: artifacts/${{env.RELEASE_NAME}}/shafile + -- cgit v1.3.1 From 5e4fd84a4dece56d8d542c64d291036c7fb3aabd Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Sep 2021 23:35:43 +0800 Subject: fix nan --- xmake/core/base/serialize.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/xmake/core/base/serialize.lua b/xmake/core/base/serialize.lua index 60b90baf5..a49122308 100644 --- a/xmake/core/base/serialize.lua +++ b/xmake/core/base/serialize.lua @@ -237,7 +237,12 @@ function serialize._make(obj, opt) -- call make* by type if type(obj) == "string" then return serialize._makestring(obj, opt) - elseif type(obj) == "boolean" or type(obj) == "nil" or type(obj) == "number" then + elseif type(obj) == "boolean" or type(obj) == "nil" then + return serialize._makedefault(obj, opt) + elseif type(obj) == "number" then + if math.isnan(obj) then -- fix nan for lua 5.3, -nan(ind) + return "nan" + end return serialize._makedefault(obj, opt) elseif type(obj) == "table" then return serialize._maketable(obj, opt) -- cgit v1.3.1 From a4ee9d0372306ee34d3454968a0dfcb0ab91e0cf Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 22 Sep 2021 00:37:57 +0800 Subject: fix colors.translate --- xmake/core/base/colors.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xmake/core/base/colors.lua b/xmake/core/base/colors.lua index 22cfad4e3..752316b17 100644 --- a/xmake/core/base/colors.lua +++ b/xmake/core/base/colors.lua @@ -337,6 +337,8 @@ function colors.translate(str, opt) -- unknown code, regard as plain text table.insert(text_buffer, block) end + elseif not opt.ignore_unknown then + table.insert(text_buffer, block) end end -- cgit v1.3.1 From d62f35f77a30fe0280086241af2142b282fa1f17 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 22 Sep 2021 00:39:36 +0800 Subject: switch to lua runtime on windows --- .github/workflows/windows_lua.yml | 122 ----------------------------------- .github/workflows/windows_luajit.yml | 122 +++++++++++++++++++++++++++++++++++ core/xmake.lua | 2 +- 3 files changed, 123 insertions(+), 123 deletions(-) delete mode 100644 .github/workflows/windows_lua.yml create mode 100644 .github/workflows/windows_luajit.yml diff --git a/.github/workflows/windows_lua.yml b/.github/workflows/windows_lua.yml deleted file mode 100644 index b9352918d..000000000 --- a/.github/workflows/windows_lua.yml +++ /dev/null @@ -1,122 +0,0 @@ -name: Windows (Lua) - -on: - pull_request: - push: - release: - types: [published] - -jobs: - build: - strategy: - matrix: - os: [windows-latest, windows-2016] - arch: [x64, x86] - - runs-on: ${{ matrix.os }} - - concurrency: - group: ${{ github.head_ref }}-${{ matrix.os }}-${{ matrix.arch }}-Windows-Lua - cancel-in-progress: true - steps: - - uses: actions/checkout@v2 - with: - # WyriHaximus/github-action-get-previous-tag@master need it - fetch-depth: 0 - submodules: true - - uses: xmake-io/github-action-setup-xmake@v1 - with: - # this is not supported, use dev branch instead - # xmake-version: local# - xmake-version: branch@dev - - uses: dlang-community/setup-dlang@v1 - with: - compiler: dmd-latest - - uses: little-core-labs/get-git-tag@v3.0.2 - id: tagName - - - name: Prepare - run: | - xmake show - Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/nsis-3.04.zip" -UseBasicParsing -OutFile ./nsis.zip - Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/nsis-3.04-strlen_8192.zip" -UseBasicParsing -OutFile ./nsis-longstr.zip - Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/UAC.zip" -UseBasicParsing -OutFile ./nsis-uac.zip - Expand-Archive ./nsis.zip -DestinationPath ./nsis - Move-Item ./nsis/*/* ./nsis - Expand-Archive ./nsis-longstr.zip -DestinationPath ./nsis -Force - Expand-Archive ./nsis-uac.zip -DestinationPath ./nsis -Force - Move-Item ./nsis/UAC.nsh ./nsis/Include/ - - - name: Build - run: | - xmake f -vD -P core -a ${{ matrix.arch }} --runtime=lua - xmake -vD -P core - - - name: Tests - run: | - Copy-Item ./core/build/xmake.exe ./xmake - Copy-Item ./scripts/xrepo.bat ./xmake - Copy-Item ./scripts/xrepo.ps1 ./xmake - $Env:XMAKE_PROGRAM_DIR = $(Resolve-Path ./xmake) - Set-Item -Path Env:Path -Value ($Env:XMAKE_PROGRAM_DIR + ";" + $Env:Path) - xrepo --version - xmake show - #xmake l -v private.utils.bcsave --rootname='@programdir' -x 'scripts/**|templates/**' xmake - xmake lua -v -D tests/run.lua - - - name: Set release arch name - run: | - if ("${{ matrix.arch }}" -eq "x64") { - Write-Output "RELEASE_NAME=win64" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf-8 -Append - } else { - Write-Output "RELEASE_NAME=win32" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf-8 -Append - } - - name: Artifact - run: | - # build installer - (New-Item ./winenv/bin -ItemType Directory).FullName - Invoke-WebRequest "https://github.com/xmake-mirror/7zip/releases/download/19.00/7z19.00-${{ matrix.arch }}.zip" -UseBasicParsing -OutFile .\7zip.zip - Expand-Archive ./7zip.zip -DestinationPath ./7zip - Copy-Item ./7zip/7z.exe ./winenv/bin - Copy-Item ./7zip/7z.dll ./winenv/bin - Invoke-WebRequest "https://curl.se/windows/dl-7.78.0_2/curl-7.78.0_2-win32-mingw.zip" -UseBasicParsing -OutFile .\curl.zip - Expand-Archive ./curl.zip -DestinationPath ./curl - Copy-Item ./curl/curl-7.78.0-win32-mingw/bin/curl.exe ./winenv/bin - Copy-Item ./curl/curl-7.78.0-win32-mingw/bin/curl-ca-bundle.crt ./winenv/bin - $version = (Get-Command xmake/xmake.exe).FileVersionInfo - ./nsis/makensis.exe /DMAJOR=$($version.ProductMajorPart) /DMINOR=$($version.ProductMinorPart) /DALTER=$($version.ProductBuildPart) /DBUILD=$($($version.ProductVersion -split '\+')[1]) /D${{ matrix.arch }} .\scripts\installer.nsi - (New-Item ./artifacts/${{env.RELEASE_NAME}} -ItemType Directory).FullName - Copy-Item scripts/xmake.exe ./artifacts/${{env.RELEASE_NAME}}/xmake.exe - # archive - Copy-Item ./*.md ./xmake - Copy-Item ./winenv ./xmake -Recurse - Add-Type -AssemblyName System.Text.Encoding - Add-Type -AssemblyName System.IO.Compression.FileSystem - class FixedEncoder : System.Text.UTF8Encoding { - FixedEncoder() : base($true) { } - [byte[]] GetBytes([string] $s) - { - $s = $s.Replace("\", "/") - return ([System.Text.UTF8Encoding]$this).GetBytes($s) - } - } - Copy-Item ./xmake ./archive/xmake -Recurse - [System.IO.Compression.ZipFile]::CreateFromDirectory("$PWD\archive", "$PWD\archive.zip", [System.IO.Compression.CompressionLevel]::Optimal, $false, [FixedEncoder]::new()) - (Get-FileHash .\archive.zip -Algorithm SHA256).Hash.ToLower() + " *xmake.zip`n" | Out-File ./shafile -Encoding ASCII -NoNewLine -Append - Copy-Item archive.zip ./artifacts/${{env.RELEASE_NAME}} - Copy-Item shafile ./artifacts/${{env.RELEASE_NAME}} - - # upload artifacts - - uses: actions/upload-artifact@v2 - with: - name: xmake-latest.${{env.RELEASE_NAME}}.exe - path: artifacts/${{env.RELEASE_NAME}}/xmake.exe - - uses: actions/upload-artifact@v2 - with: - name: xmake-latest.${{ env.RELEASE_NAME }}.zip - path: artifacts/${{env.RELEASE_NAME}}/archive.zip - - uses: actions/upload-artifact@v2 - with: - name: xmake-latest.${{ env.RELEASE_NAME }}.sha256 - path: artifacts/${{env.RELEASE_NAME}}/shafile - diff --git a/.github/workflows/windows_luajit.yml b/.github/workflows/windows_luajit.yml new file mode 100644 index 000000000..3b2115beb --- /dev/null +++ b/.github/workflows/windows_luajit.yml @@ -0,0 +1,122 @@ +name: Windows (Luajit) + +on: + pull_request: + push: + release: + types: [published] + +jobs: + build: + strategy: + matrix: + os: [windows-latest, windows-2016] + arch: [x64, x86] + + runs-on: ${{ matrix.os }} + + concurrency: + group: ${{ github.head_ref }}-${{ matrix.os }}-${{ matrix.arch }}-Windows-Luajit + cancel-in-progress: true + steps: + - uses: actions/checkout@v2 + with: + # WyriHaximus/github-action-get-previous-tag@master need it + fetch-depth: 0 + submodules: true + - uses: xmake-io/github-action-setup-xmake@v1 + with: + # this is not supported, use dev branch instead + # xmake-version: local# + xmake-version: branch@dev + - uses: dlang-community/setup-dlang@v1 + with: + compiler: dmd-latest + - uses: little-core-labs/get-git-tag@v3.0.2 + id: tagName + + - name: Prepare + run: | + xmake show + Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/nsis-3.04.zip" -UseBasicParsing -OutFile ./nsis.zip + Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/nsis-3.04-strlen_8192.zip" -UseBasicParsing -OutFile ./nsis-longstr.zip + Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/UAC.zip" -UseBasicParsing -OutFile ./nsis-uac.zip + Expand-Archive ./nsis.zip -DestinationPath ./nsis + Move-Item ./nsis/*/* ./nsis + Expand-Archive ./nsis-longstr.zip -DestinationPath ./nsis -Force + Expand-Archive ./nsis-uac.zip -DestinationPath ./nsis -Force + Move-Item ./nsis/UAC.nsh ./nsis/Include/ + + - name: Build + run: | + xmake f -vD -P core -a ${{ matrix.arch }} --runtime=luajit + xmake -vD -P core + + - name: Tests + run: | + Copy-Item ./core/build/xmake.exe ./xmake + Copy-Item ./scripts/xrepo.bat ./xmake + Copy-Item ./scripts/xrepo.ps1 ./xmake + $Env:XMAKE_PROGRAM_DIR = $(Resolve-Path ./xmake) + Set-Item -Path Env:Path -Value ($Env:XMAKE_PROGRAM_DIR + ";" + $Env:Path) + xrepo --version + xmake show + #xmake l -v private.utils.bcsave --rootname='@programdir' -x 'scripts/**|templates/**' xmake + xmake lua -v -D tests/run.lua + + - name: Set release arch name + run: | + if ("${{ matrix.arch }}" -eq "x64") { + Write-Output "RELEASE_NAME=win64" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf-8 -Append + } else { + Write-Output "RELEASE_NAME=win32" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf-8 -Append + } + - name: Artifact + run: | + # build installer + (New-Item ./winenv/bin -ItemType Directory).FullName + Invoke-WebRequest "https://github.com/xmake-mirror/7zip/releases/download/19.00/7z19.00-${{ matrix.arch }}.zip" -UseBasicParsing -OutFile .\7zip.zip + Expand-Archive ./7zip.zip -DestinationPath ./7zip + Copy-Item ./7zip/7z.exe ./winenv/bin + Copy-Item ./7zip/7z.dll ./winenv/bin + Invoke-WebRequest "https://curl.se/windows/dl-7.78.0_2/curl-7.78.0_2-win32-mingw.zip" -UseBasicParsing -OutFile .\curl.zip + Expand-Archive ./curl.zip -DestinationPath ./curl + Copy-Item ./curl/curl-7.78.0-win32-mingw/bin/curl.exe ./winenv/bin + Copy-Item ./curl/curl-7.78.0-win32-mingw/bin/curl-ca-bundle.crt ./winenv/bin + $version = (Get-Command xmake/xmake.exe).FileVersionInfo + ./nsis/makensis.exe /DMAJOR=$($version.ProductMajorPart) /DMINOR=$($version.ProductMinorPart) /DALTER=$($version.ProductBuildPart) /DBUILD=$($($version.ProductVersion -split '\+')[1]) /D${{ matrix.arch }} .\scripts\installer.nsi + (New-Item ./artifacts/${{env.RELEASE_NAME}} -ItemType Directory).FullName + Copy-Item scripts/xmake.exe ./artifacts/${{env.RELEASE_NAME}}/xmake.exe + # archive + Copy-Item ./*.md ./xmake + Copy-Item ./winenv ./xmake -Recurse + Add-Type -AssemblyName System.Text.Encoding + Add-Type -AssemblyName System.IO.Compression.FileSystem + class FixedEncoder : System.Text.UTF8Encoding { + FixedEncoder() : base($true) { } + [byte[]] GetBytes([string] $s) + { + $s = $s.Replace("\", "/") + return ([System.Text.UTF8Encoding]$this).GetBytes($s) + } + } + Copy-Item ./xmake ./archive/xmake -Recurse + [System.IO.Compression.ZipFile]::CreateFromDirectory("$PWD\archive", "$PWD\archive.zip", [System.IO.Compression.CompressionLevel]::Optimal, $false, [FixedEncoder]::new()) + (Get-FileHash .\archive.zip -Algorithm SHA256).Hash.ToLower() + " *xmake.zip`n" | Out-File ./shafile -Encoding ASCII -NoNewLine -Append + Copy-Item archive.zip ./artifacts/${{env.RELEASE_NAME}} + Copy-Item shafile ./artifacts/${{env.RELEASE_NAME}} + + # upload artifacts + - uses: actions/upload-artifact@v2 + with: + name: xmake-latest.${{env.RELEASE_NAME}}.exe + path: artifacts/${{env.RELEASE_NAME}}/xmake.exe + - uses: actions/upload-artifact@v2 + with: + name: xmake-latest.${{ env.RELEASE_NAME }}.zip + path: artifacts/${{env.RELEASE_NAME}}/archive.zip + - uses: actions/upload-artifact@v2 + with: + name: xmake-latest.${{ env.RELEASE_NAME }}.sha256 + path: artifacts/${{env.RELEASE_NAME}}/shafile + diff --git a/core/xmake.lua b/core/xmake.lua index 71253d8ae..a9108c487 100644 --- a/core/xmake.lua +++ b/core/xmake.lua @@ -43,7 +43,7 @@ end -- the runtime option option("runtime") set_showmenu(true) - set_default("luajit") + set_default("lua") set_description("Use luajit or lua runtime") set_values("luajit", "lua") option_end() -- cgit v1.3.1 From 5e614774a6cc59832b66d007c59d6da3b77f124b Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 22 Sep 2021 22:52:53 +0800 Subject: add bom for vs project generator --- core/src/xmake/io/file_open.c | 6 +++++ core/src/xmake/io/file_write.c | 38 +++++++++++++++++++++++++++ core/src/xmake/io/prefix.h | 1 + xmake/plugins/project/vstudio/impl/vsfile.lua | 2 +- xmake/plugins/project/vsxmake/vsxmake.lua | 4 ++- 5 files changed, 49 insertions(+), 2 deletions(-) diff --git a/core/src/xmake/io/file_open.c b/core/src/xmake/io/file_open.c index c92380207..435e2aec0 100644 --- a/core/src/xmake/io/file_open.c +++ b/core/src/xmake/io/file_open.c @@ -231,6 +231,11 @@ tb_int_t xm_io_file_open(lua_State* lua) else xm_io_return_error(lua, "invalid open mode!"); tb_assert_and_check_return_val(encoding != XM_IO_FILE_ENCODING_UNKNOWN, 0); + // write data with utf bom? e.g. utf8bom, utf16lebom, utf16bom + tb_bool_t utfbom = tb_false; + if (tb_strstr(modestr, "bom")) + utfbom = tb_true; + // open file tb_bool_t open_ok = tb_false; tb_stream_ref_t file_ref = tb_null; @@ -293,6 +298,7 @@ tb_int_t xm_io_file_open(lua_State* lua) file->mode = mode; file->type = XM_IO_FILE_TYPE_FILE; file->encoding = encoding; + file->utfbom = utfbom; // init the read/write line cache buffer tb_buffer_init(&file->rcache); diff --git a/core/src/xmake/io/file_write.c b/core/src/xmake/io/file_write.c index 12ab829b3..c7db01937 100644 --- a/core/src/xmake/io/file_write.c +++ b/core/src/xmake/io/file_write.c @@ -33,6 +33,36 @@ /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ +static tb_void_t xm_io_file_write_file_utfbom(xm_io_file_t* file) +{ + // check + tb_assert(file && data && xm_io_file_is_file(file) && file->file_ref); + + // write bom + switch (file->encoding) + { + case TB_CHARSET_TYPE_UTF8: + { + static tb_byte_t bom[] = {0xef, 0xbb, 0xbf}; + tb_stream_bwrit(file->file_ref, bom, sizeof(bom)); + } + break; + case TB_CHARSET_TYPE_UTF16 | TB_CHARSET_TYPE_LE: + { + static tb_byte_t bom[] = {0xff, 0xfe}; + tb_stream_bwrit(file->file_ref, bom, sizeof(bom)); + } + break; + case TB_CHARSET_TYPE_UTF16 | TB_CHARSET_TYPE_BE: + { + static tb_byte_t bom[] = {0xfe, 0xff}; + tb_stream_bwrit(file->file_ref, bom, sizeof(bom)); + } + break; + default: + break; + } +} static tb_void_t xm_io_file_write_file_directly(xm_io_file_t* file, tb_char_t const* data, tb_size_t size) { // check @@ -141,7 +171,15 @@ tb_int_t xm_io_file_write(lua_State* lua) else if (is_binary) xm_io_file_write_file_directly(file, data, (tb_size_t)datasize); else + { + // write utf bom first? + if (file->utfbom) + { + xm_io_file_write_file_utfbom(file); + file->utfbom = tb_false; + } xm_io_file_write_file_transcrlf(file, data, (tb_size_t)datasize); + } } } lua_settop(lua, 1); diff --git a/core/src/xmake/io/prefix.h b/core/src/xmake/io/prefix.h index e11198da1..bec186a92 100644 --- a/core/src/xmake/io/prefix.h +++ b/core/src/xmake/io/prefix.h @@ -88,6 +88,7 @@ typedef struct __xm_io_file_t tb_size_t mode; // tb_file_mode_t tb_size_t type; // xm_io_file_type_e tb_size_t encoding; // value of xm_io_file_encoding_e or tb_charset_type_e + tb_bool_t utfbom; // write utf-bom for utf encoding? tb_buffer_t rcache; // the read line cache buffer tb_buffer_t wcache; // the write line cache buffer diff --git a/xmake/plugins/project/vstudio/impl/vsfile.lua b/xmake/plugins/project/vstudio/impl/vsfile.lua index a17384716..040bbee2b 100644 --- a/xmake/plugins/project/vstudio/impl/vsfile.lua +++ b/xmake/plugins/project/vstudio/impl/vsfile.lua @@ -97,7 +97,7 @@ end function open(filepath, mode) -- open it - local file = io.open(filepath, mode) + local file = io.open(filepath, mode, {encoding = "utf8bom"}) -- hook print, printf and write file._print_impl = file.print diff --git a/xmake/plugins/project/vsxmake/vsxmake.lua b/xmake/plugins/project/vsxmake/vsxmake.lua index 0055aaff2..cc50cb2d3 100644 --- a/xmake/plugins/project/vsxmake/vsxmake.lua +++ b/xmake/plugins/project/vsxmake/vsxmake.lua @@ -167,7 +167,9 @@ function _writefileifneeded(file, content) dprint("skipped file %s since the file has the same content", path.relative(file)) return end - io.writefile(file, content) + -- we need utf8 with bom encoding for unicode + -- @see https://github.com/xmake-io/xmake/issues/1689 + io.writefile(file, content, {encoding = "utf8bom"}) end function _clear_cacheconf() -- cgit v1.3.1 From 3fcbabd0562e8f3e413a80b150a56547643b3929 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 22 Sep 2021 23:46:27 +0800 Subject: fix ping --- xmake/modules/net/ping.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/net/ping.lua b/xmake/modules/net/ping.lua index 5f555cccd..93e9b4bec 100644 --- a/xmake/modules/net/ping.lua +++ b/xmake/modules/net/ping.lua @@ -88,7 +88,7 @@ function main(hosts, opt) end -- trace - vprint("pinging for the host(%s) ... %d ms", host, timeval) + vprint("pinging for the host(%s) ... %d ms", host, math.floor(timeval)) end end end, {total = #hosts}) -- cgit v1.3.1 From b89272535fe65a23087b25f7fca52b790f946450 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 Sep 2021 00:15:42 +0800 Subject: fix unicode bug for vsxmake --- xmake/plugins/project/vsxmake/vsproj/Xmake.targets | 2 -- 1 file changed, 2 deletions(-) diff --git a/xmake/plugins/project/vsxmake/vsproj/Xmake.targets b/xmake/plugins/project/vsxmake/vsproj/Xmake.targets index 9a23799c1..ce78b88e9 100644 --- a/xmake/plugins/project/vsxmake/vsproj/Xmake.targets +++ b/xmake/plugins/project/vsxmake/vsproj/Xmake.targets @@ -65,7 +65,6 @@ <_XmakeExecutable>"$([System.IO.Path]::GetFullPath('$(XmakeProgramDirResolved)xmake.exe'))" <_XmakeEnv> - chcp 65001 > NUL pushd $(XmakeProjectDirResolved) set XMAKE_CONFIGDIR=$(XmakeConfigDirResolved.TrimEnd('\').TrimEnd('/')) set XMAKE_PROGRAM_DIR=$(XmakeProgramDirResolved.TrimEnd('\').TrimEnd('/')) @@ -77,7 +76,6 @@ echo XMAKE_CONFIGDIR=%25XMAKE_CONFIGDIR%25 echo XMAKE_PROGRAM_DIR=%25XMAKE_PROGRAM_DIR%25 echo CD=%25CD%25 - chcp -- cgit v1.3.1 From 85283fa3e969a1a36631816f67026aef4a0c4034 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 Sep 2021 00:25:14 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 569548cee..081f29da3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ ### Bugs fixed * [#1671](https://github.com/xmake-io/xmake/issues/1671): Fix incorrect absolute path after installing precompiled packages +* [#1689](https://github.com/xmake-io/xmake/issues/1689): Fix unicode chars bug for vsxmake ## v2.5.7 @@ -1095,6 +1096,7 @@ ### Bugs 修复 * [#1671](https://github.com/xmake-io/xmake/issues/1671): 修复安装预编译包后,*.cmake 里面的一些不正确的绝对路径 +* [#1689](https://github.com/xmake-io/xmake/issues/1689): 修复 vsxmake 插件的 unicode 字符显示和加载问题 ## v2.5.7 -- cgit v1.3.1 From 3a8aab03b9e615cd0a40a1ed21e9ab4490f6f1c5 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 22 Sep 2021 22:53:20 +0800 Subject: Update find_mingw.lua --- xmake/modules/detect/sdks/find_mingw.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xmake/modules/detect/sdks/find_mingw.lua b/xmake/modules/detect/sdks/find_mingw.lua index 7be315a9c..e5276834b 100644 --- a/xmake/modules/detect/sdks/find_mingw.lua +++ b/xmake/modules/detect/sdks/find_mingw.lua @@ -94,6 +94,9 @@ function _find_mingw(sdkdir, bindir, cross) -- find cross toolchain local toolchain = find_cross_toolchain(sdkdir or bindir, {bindir = bindir, cross = cross}) + if not toolchain then -- fallback, e.g. gcc.exe without cross + toolchain = find_cross_toolchain(sdkdir or bindir, {bindir = bindir}) + end if toolchain then return {sdkdir = toolchain.sdkdir, bindir = toolchain.bindir, cross = toolchain.cross} end -- cgit v1.3.1 From 756a16c2a95de169e1b72e34d7b60007cc1dfdff Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 Sep 2021 22:41:00 +0800 Subject: disable quote for set_configvar --- tests/apis/add_configfiles/config.h.in | 1 + tests/apis/add_configfiles/xmake.lua | 1 + xmake/actions/config/configfiles.lua | 12 ++++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/apis/add_configfiles/config.h.in b/tests/apis/add_configfiles/config.h.in index 3cbeb4135..5ba4bddb3 100644 --- a/tests/apis/add_configfiles/config.h.in +++ b/tests/apis/add_configfiles/config.h.in @@ -4,6 +4,7 @@ ${define FOO_ENABLE} ${define FOO_ENABLE2} ${define FOO_STRING} +${define FOO_DEFINE} ${define FOO2_ENABLE} ${define FOO2_ENABLE2} diff --git a/tests/apis/add_configfiles/xmake.lua b/tests/apis/add_configfiles/xmake.lua index 0dcf1eceb..a6849d586 100644 --- a/tests/apis/add_configfiles/xmake.lua +++ b/tests/apis/add_configfiles/xmake.lua @@ -8,6 +8,7 @@ if has_config("foo") then set_configvar("FOO_ENABLE", 1) set_configvar("FOO_ENABLE2", false) set_configvar("FOO_STRING", get_config("foo")) + set_configvar("FOO_DEFINE", get_config("foo"), {quote = false}) end option("foo2") diff --git a/xmake/actions/config/configfiles.lua b/xmake/actions/config/configfiles.lua index 33a44c1a8..974610a91 100644 --- a/xmake/actions/config/configfiles.lua +++ b/xmake/actions/config/configfiles.lua @@ -167,7 +167,9 @@ function _generate_configfile(srcfile, dstfile, fileinfo, targets) -- get variables from the target for name, value in pairs(target:get("configvar")) do if variables[name] == nil then - variables[name] = table.unwrap(value) + value = table.unwrap(value) + variables[name] = value + variables["__extraconf_" .. name] = target:extraconf("configvar." .. name, value) end end @@ -236,6 +238,7 @@ function _generate_configfile(srcfile, dstfile, fileinfo, targets) -- get variable value local value = variables[variable] + local extraconf = variables["__extraconf_" .. variable] if isdefine then if value == nil then value = ("/* #undef %s */"):format(variable) @@ -248,7 +251,12 @@ function _generate_configfile(srcfile, dstfile, fileinfo, targets) elseif type(value) == "number" then value = ("#define %s %d"):format(variable, value) elseif type(value) == "string" then - value = ("#define %s \"%s\""):format(variable, value) + -- disable to wrap quote, @see https://github.com/xmake-io/xmake/issues/1694 + if extraconf and extraconf.quote == false then + value = ("#define %s %s"):format(variable, value) + else + value = ("#define %s \"%s\""):format(variable, value) + end else raise("unknown variable(%s) type: %s", variable, type(value)) end -- cgit v1.3.1 From 535047433a2c4caed04afcb20a6575fdb6e8d938 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 Sep 2021 22:41:17 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 081f29da3..8eaeea298 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ * [#1638](https://github.com/xmake-io/xmake/issues/1638): Improve to merge static library * Improve on_load/after_load to support to add target deps dynamically * [#1675](https://github.com/xmake-io/xmake/pull/1675): Rename dynamic and import library suffix for mingw +* [#1694](https://github.com/xmake-io/xmake/issues/1694): Support to define a variable without quotes for configuration files ### Bugs fixed @@ -1092,6 +1093,7 @@ * [#1638](https://github.com/xmake-io/xmake/issues/1638): 改进合并静态库 * 改进 on_load/after_load 去支持动态的添加 target deps * [#1675](https://github.com/xmake-io/xmake/pull/1675): 针对 mingw 平台,重命名动态库和导入库文件名后缀 +* [#1694](https://github.com/xmake-io/xmake/issues/1694): 支持在 set_configvar 中定义一个不带引号的字符串变量 ### Bugs 修复 -- cgit v1.3.1 From ffd3403c9964f6cc6dce499de8168b8476f695c9 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 Sep 2021 13:08:49 +0800 Subject: Update _xmake_main.lua --- xmake/core/_xmake_main.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xmake/core/_xmake_main.lua b/xmake/core/_xmake_main.lua index 47197d7bb..cf82a5a9c 100644 --- a/xmake/core/_xmake_main.lua +++ b/xmake/core/_xmake_main.lua @@ -36,6 +36,12 @@ xmake._WORKING_DIR = os.curdir() xmake._FEATURES = _FEATURES xmake._LUAJIT = _LUAJIT +-- In order to be compatible with updates from lower versions of engine core +-- @see https://github.com/xmake-io/xmake/issues/1694#issuecomment-925507210 +if xmake._LUAJIT == nil then + xmake._LUAJIT = true +end + -- load the given lua file function _loadfile_impl(filepath, mode, opt) -- cgit v1.3.1 From 5c7843af8a07e184737bc405b3cb40677bf399fc Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 Sep 2021 13:14:07 +0800 Subject: Update xmake.lua --- xmake/core/sandbox/modules/interpreter/xmake.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/core/sandbox/modules/interpreter/xmake.lua b/xmake/core/sandbox/modules/interpreter/xmake.lua index 414258198..fcc6437e1 100644 --- a/xmake/core/sandbox/modules/interpreter/xmake.lua +++ b/xmake/core/sandbox/modules/interpreter/xmake.lua @@ -28,6 +28,7 @@ local sandbox_xmake = sandbox_xmake or {} sandbox_xmake.version = xmake.version sandbox_xmake.programdir = xmake.programdir sandbox_xmake.programfile = xmake.programfile +sandbox_xmake.luajit = xmake.luajit -- return module return sandbox_xmake -- cgit v1.3.1 From 402e2093f9e7cd65b5aedc4102f9f7068beed684 Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Thu, 23 Sep 2021 15:04:28 +0800 Subject: fix some typo --- xmake/core/project/option.lua | 4 ++-- xmake/includes/check_cfuncs.lua | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/xmake/core/project/option.lua b/xmake/core/project/option.lua index e9a2ef20d..d74b74996 100644 --- a/xmake/core/project/option.lua +++ b/xmake/core/project/option.lua @@ -69,7 +69,7 @@ function _instance:_clear() end -- check snippets -function _instance:_do_check_cxsnippts(snippets) +function _instance:_do_check_cxsnippets(snippets) -- import check_cxsnippets() self._check_cxsnippets = self._check_cxsnippets or sandbox_module.import("lib.detect.check_cxsnippets", {anonymous = true}) @@ -220,7 +220,7 @@ end function _instance:_do_check() -- check snippets - local ok, passed, errors = self:_do_check_cxsnippts() + local ok, passed, errors = self:_do_check_cxsnippets() if not ok then return false, errors end diff --git a/xmake/includes/check_cfuncs.lua b/xmake/includes/check_cfuncs.lua index 337a16fac..45b80519f 100644 --- a/xmake/includes/check_cfuncs.lua +++ b/xmake/includes/check_cfuncs.lua @@ -49,7 +49,7 @@ function check_cfuncs(definition, funcs, opt) if opt.cflags then add_cflags(opt.cflags) end - if opt.cflags then + if opt.cxflags then add_cxflags(opt.cxflags) end if opt.defines then -- cgit v1.3.1 From b14cfebf3ff0a88ab9486468c2665732768d6456 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 Sep 2021 18:01:56 +0800 Subject: Update colors.lua --- xmake/core/base/colors.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/core/base/colors.lua b/xmake/core/base/colors.lua index 752316b17..9c2016b10 100644 --- a/xmake/core/base/colors.lua +++ b/xmake/core/base/colors.lua @@ -164,7 +164,7 @@ function colors.rainbow24(index, seed, freq, spread) local blue = math.sin(freq * index + 4 * math.pi / 3) * 127 + 128 -- make code - return string.format("%d;%d;%d", red, green, blue) + return string.format("%d;%d;%d", math.floor(red), math.floor(green), math.floor(blue)) end -- make rainbow color256 code by the index of characters (16-256) -- cgit v1.3.1 From b97aff569ccc11b3ac617ca55b560488998a9e19 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Sep 2021 00:14:01 +0800 Subject: update title --- xmake/core/main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/core/main.lua b/xmake/core/main.lua index d4eb456b3..e4d6f8f2a 100644 --- a/xmake/core/main.lua +++ b/xmake/core/main.lua @@ -44,7 +44,7 @@ local profiler = require("base/profiler") -- init the option menu local menu = { - title = "${bright}xmake v" .. _VERSION .. ", A cross-platform build utility based on Lua${clear}" + title = "${bright}xmake v" .. _VERSION .. ", A cross-platform build utility based on " .. (xmake._LUAJIT and "LuaJIT" or "Lua") .. "${clear}" , copyright = "Copyright (C) 2015-present Ruki Wang, ${underline}tboox.org${clear}, ${underline}xmake.io${clear}" -- the tasks: xmake [task] -- cgit v1.3.1 From 6708849f5c386a5d16f7be3d568afa10df49bc16 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Sep 2021 00:18:57 +0800 Subject: improve tests --- tests/apis/add_configfiles/config.h.in | 2 ++ tests/apis/check_xxx/config.h.in | 2 +- xmake/core/project/target.lua | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/apis/add_configfiles/config.h.in b/tests/apis/add_configfiles/config.h.in index 5ba4bddb3..c1ea00299 100644 --- a/tests/apis/add_configfiles/config.h.in +++ b/tests/apis/add_configfiles/config.h.in @@ -9,3 +9,5 @@ ${define FOO_DEFINE} ${define FOO2_ENABLE} ${define FOO2_ENABLE2} ${define FOO2_STRING} + +#define HAVE_SSE2 ${default HAVE_SSE2 0} diff --git a/tests/apis/check_xxx/config.h.in b/tests/apis/check_xxx/config.h.in index 0c7d9ebf8..617ecf864 100644 --- a/tests/apis/check_xxx/config.h.in +++ b/tests/apis/check_xxx/config.h.in @@ -1,6 +1,5 @@ ${define HAS_STRING_H} ${define HAS_STRING_AND_STDIO_H} -${define HAS_WCHAR} ${define HAS_WCHAR_AND_FLOAT} ${define HAS_PTHREAD} ${define HAS_STATIC_ASSERT} @@ -10,3 +9,4 @@ ${define HAS_CONSEXPR_AND_STATIC_ASSERT} ${define HAS_SSE2} ${define HAS_LONG_8} ${define PTR_SIZE} +#define HAS_WCHAR ${default HAS_WCHAR 0} diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index d51cc6b71..3e2d308f9 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -729,7 +729,7 @@ function _instance:orderopts(opt) -- load options if be enabled orderopts = {} - for _, name in ipairs(table.wrap(self:get("options"))) do + for _, name in ipairs(table.wrap(self:get("options", opt))) do local opt_ = nil if config.get(name) then opt_ = option.load(name) end if opt_ then @@ -738,7 +738,7 @@ function _instance:orderopts(opt) end -- load options from packages if no require info, be compatible with the option package in (*.pkg) - for _, name in ipairs(table.wrap(self:get("packages"))) do + for _, name in ipairs(table.wrap(self:get("packages", opt))) do if not project_package.load(name) then local opt_ = nil if config.get(name) then opt_ = option.load(name) end -- cgit v1.3.1 From fbccc2375dba05f227ff8e6ec0b61c9357ca449d Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 Sep 2021 20:57:32 +0800 Subject: Update gcc.lua --- xmake/modules/core/tools/gcc.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index 713cd80aa..8d404f2dc 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -113,8 +113,8 @@ function nf_warning(self, level) , less = "-Wall" , more = "-Wall" , all = "-Wall" - , allextra = "-Wall -Wextra" - , everything = "-Wall -Wextra -Weffc++" + , allextra = {"-Wall", "-Wextra"} + , everything = self:kind() == "cxx" and {"-Wall", "-Wextra", "-Weffc++"} or {"-Wall", "-Wextra"} , error = "-Werror" } return maps[level] -- cgit v1.3.1 From 6e5bd0a99336d5ef17e9b7c312d547b6a683d13e Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Thu, 23 Sep 2021 21:59:21 +0800 Subject: improve configvar_check_ functions --- xmake/includes/check_cflags.lua | 10 ++++++++-- xmake/includes/check_cfuncs.lua | 10 ++++++++-- xmake/includes/check_cincludes.lua | 10 ++++++++-- xmake/includes/check_csnippets.lua | 10 ++++++++-- xmake/includes/check_ctypes.lua | 10 ++++++++-- xmake/includes/check_cxxflags.lua | 10 ++++++++-- xmake/includes/check_cxxfuncs.lua | 10 ++++++++-- xmake/includes/check_cxxincludes.lua | 10 ++++++++-- xmake/includes/check_cxxsnippets.lua | 10 ++++++++-- xmake/includes/check_cxxtypes.lua | 10 ++++++++-- xmake/includes/check_features.lua | 10 ++++++++-- xmake/includes/check_links.lua | 10 ++++++++-- xmake/includes/check_syslinks.lua | 10 ++++++++-- 13 files changed, 104 insertions(+), 26 deletions(-) diff --git a/xmake/includes/check_cflags.lua b/xmake/includes/check_cflags.lua index 85ee65f8e..46758d0aa 100644 --- a/xmake/includes/check_cflags.lua +++ b/xmake/includes/check_cflags.lua @@ -53,7 +53,9 @@ function configvar_check_cflags(definition, flags, opt) local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) option(optname) - set_configvar(defname, defval or 1) + if opt.default == nil then + set_configvar(defname, defval or 1, {quote = opt.quote}) + end on_check(function (option) import("core.tool.compiler") if compiler.has_flags("c", flags, opt) then @@ -61,5 +63,9 @@ function configvar_check_cflags(definition, flags, opt) end end) option_end() - add_options(optname) + if opt.default == nil then + add_options(optname) + else + set_configvar(defname, has_config(optname) and (defval or 1) or opt.default, {quote = opt.quote}) + end end diff --git a/xmake/includes/check_cfuncs.lua b/xmake/includes/check_cfuncs.lua index 45b80519f..42d06e5ff 100644 --- a/xmake/includes/check_cfuncs.lua +++ b/xmake/includes/check_cfuncs.lua @@ -75,7 +75,9 @@ function configvar_check_cfuncs(definition, funcs, opt) local defname, defval = unpack(definition:split('=')) option(optname) add_cfuncs(funcs) - set_configvar(defname, defval or 1) + if opt.default == nil then + set_configvar(defname, defval or 1, {quote = opt.quote}) + end if opt.links then add_links(opt.links) end @@ -98,5 +100,9 @@ function configvar_check_cfuncs(definition, funcs, opt) set_warnings(opt.warnings) end option_end() - add_options(optname) + if opt.default == nil then + add_options(optname) + else + set_configvar(defname, has_config(optname) and (defval or 1) or opt.default, {quote = opt.quote}) + end end diff --git a/xmake/includes/check_cincludes.lua b/xmake/includes/check_cincludes.lua index 7f2727d77..ced7c33a5 100644 --- a/xmake/includes/check_cincludes.lua +++ b/xmake/includes/check_cincludes.lua @@ -54,7 +54,13 @@ function configvar_check_cincludes(definition, includes, opt) if opt.includedirs then add_includedirs(opt.includedirs) end - set_configvar(defname, defval or 1) + if opt.default == nil then + set_configvar(defname, defval or 1, {quote = opt.quote}) + end option_end() - add_options(optname) + if opt.default == nil then + add_options(optname) + else + set_configvar(defname, has_config(optname) and (defval or 1) or opt.default, {quote = opt.quote}) + end end diff --git a/xmake/includes/check_csnippets.lua b/xmake/includes/check_csnippets.lua index 06fdc842e..3f7f853e5 100644 --- a/xmake/includes/check_csnippets.lua +++ b/xmake/includes/check_csnippets.lua @@ -84,7 +84,9 @@ function configvar_check_csnippets(definition, snippets, opt) local defname, defval = unpack(definition:split('=')) option(optname) add_csnippets(definition, snippets, {tryrun = opt.tryrun, output = opt.output}) - set_configvar(defname, defval or 1) + if opt.default == nil then + set_configvar(defname, defval or 1, {quote = opt.quote}) + end if opt.links then add_links(opt.links) end @@ -114,5 +116,9 @@ function configvar_check_csnippets(definition, snippets, opt) end) end option_end() - add_options(optname) + if opt.default == nil then + add_options(optname) + else + set_configvar(defname, has_config(optname) and (defval or 1) or opt.default, {quote = opt.quote}) + end end diff --git a/xmake/includes/check_ctypes.lua b/xmake/includes/check_ctypes.lua index d6bf77f82..934fc83b7 100644 --- a/xmake/includes/check_ctypes.lua +++ b/xmake/includes/check_ctypes.lua @@ -63,7 +63,9 @@ function configvar_check_ctypes(definition, types, opt) local defname, defval = unpack(definition:split('=')) option(optname) add_ctypes(types) - set_configvar(defname, defval or 1) + if opt.default == nil then + set_configvar(defname, defval or 1, {quote = opt.quote}) + end if opt.languages then set_languages(opt.languages) end @@ -80,5 +82,9 @@ function configvar_check_ctypes(definition, types, opt) add_cincludes(opt.includes) end option_end() - add_options(optname) + if opt.default == nil then + add_options(optname) + else + set_configvar(defname, has_config(optname) and (defval or 1) or opt.default, {quote = opt.quote}) + end end diff --git a/xmake/includes/check_cxxflags.lua b/xmake/includes/check_cxxflags.lua index c2881ecdc..36ca0ccd5 100644 --- a/xmake/includes/check_cxxflags.lua +++ b/xmake/includes/check_cxxflags.lua @@ -53,7 +53,9 @@ function configvar_check_cxxflags(definition, flags, opt) local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) option(optname) - set_configvar(defname, defval or 1) + if opt.default == nil then + set_configvar(defname, defval or 1, {quote = opt.quote}) + end on_check(function (option) import("core.tool.compiler") if compiler.has_flags("cxx", flags, opt) then @@ -61,5 +63,9 @@ function configvar_check_cxxflags(definition, flags, opt) end end) option_end() - add_options(optname) + if opt.default == nil then + add_options(optname) + else + set_configvar(defname, has_config(optname) and (defval or 1) or opt.default, {quote = opt.quote}) + end end diff --git a/xmake/includes/check_cxxfuncs.lua b/xmake/includes/check_cxxfuncs.lua index bef5d8252..426f51edb 100644 --- a/xmake/includes/check_cxxfuncs.lua +++ b/xmake/includes/check_cxxfuncs.lua @@ -75,7 +75,9 @@ function configvar_check_cxxfuncs(definition, funcs, opt) local defname, defval = unpack(definition:split('=')) option(optname) add_cxxfuncs(funcs) - set_configvar(defname, defval or 1) + if opt.default == nil then + set_configvar(defname, defval or 1, {quote = opt.quote}) + end if opt.links then add_links(opt.links) end @@ -98,5 +100,9 @@ function configvar_check_cxxfuncs(definition, funcs, opt) set_warnings(opt.warnings) end option_end() - add_options(optname) + if opt.default == nil then + add_options(optname) + else + set_configvar(defname, has_config(optname) and (defval or 1) or opt.default, {quote = opt.quote}) + end end diff --git a/xmake/includes/check_cxxincludes.lua b/xmake/includes/check_cxxincludes.lua index 4ef52b155..ed9ecd6cd 100644 --- a/xmake/includes/check_cxxincludes.lua +++ b/xmake/includes/check_cxxincludes.lua @@ -48,7 +48,13 @@ function configvar_check_cxxincludes(definition, includes, opt) local defname, defval = unpack(definition:split('=')) option(optname) add_cxxincludes(includes) - set_configvar(defname, defval or 1) + if opt.default == nil then + set_configvar(defname, defval or 1, {quote = opt.quote}) + end option_end() - add_options(optname) + if opt.default == nil then + add_options(optname) + else + set_configvar(defname, has_config(optname) and (defval or 1) or opt.default, {quote = opt.quote}) + end end diff --git a/xmake/includes/check_cxxsnippets.lua b/xmake/includes/check_cxxsnippets.lua index 8f0f6f64d..6da696c03 100644 --- a/xmake/includes/check_cxxsnippets.lua +++ b/xmake/includes/check_cxxsnippets.lua @@ -84,7 +84,9 @@ function configvar_check_cxxsnippets(definition, snippets, opt) local defname, defval = unpack(definition:split('=')) option(optname) add_cxxsnippets(definition, snippets, {tryrun = opt.tryrun, output = opt.output}) - set_configvar(defname, defval or 1) + if opt.default == nil then + set_configvar(defname, defval or 1, {quote = opt.quote}) + end if opt.links then add_links(opt.links) end @@ -114,5 +116,9 @@ function configvar_check_cxxsnippets(definition, snippets, opt) end) end option_end() - add_options(optname) + if opt.default == nil then + add_options(optname) + else + set_configvar(defname, has_config(optname) and (defval or 1) or opt.default, {quote = opt.quote}) + end end diff --git a/xmake/includes/check_cxxtypes.lua b/xmake/includes/check_cxxtypes.lua index 859e26c4d..1428e1fba 100644 --- a/xmake/includes/check_cxxtypes.lua +++ b/xmake/includes/check_cxxtypes.lua @@ -63,7 +63,9 @@ function configvar_check_cxxtypes(definition, types, opt) local defname, defval = unpack(definition:split('=')) option(optname) add_cxxtypes(types) - set_configvar(defname, defval or 1) + if opt.default == nil then + set_configvar(defname, defval or 1, {quote = opt.quote}) + end if opt.languages then set_languages(opt.languages) end @@ -80,5 +82,9 @@ function configvar_check_cxxtypes(definition, types, opt) add_cxxincludes(opt.includes) end option_end() - add_options(optname) + if opt.default == nil then + add_options(optname) + else + set_configvar(defname, has_config(optname) and (defval or 1) or opt.default, {quote = opt.quote}) + end end diff --git a/xmake/includes/check_features.lua b/xmake/includes/check_features.lua index 1340d32f5..e837c485c 100644 --- a/xmake/includes/check_features.lua +++ b/xmake/includes/check_features.lua @@ -60,7 +60,9 @@ function configvar_check_features(definition, features, opt) local defname, defval = unpack(definition:split('=')) option(optname) add_features(features) - set_configvar(defname, defval or 1) + if opt.default == nil then + set_configvar(defname, defval or 1, {quote = opt.quote}) + end if opt.languages then set_languages(opt.languages) end @@ -74,5 +76,9 @@ function configvar_check_features(definition, features, opt) add_cxxflags(opt.cxxflags) end option_end() - add_options(optname) + if opt.default == nil then + add_options(optname) + else + set_configvar(defname, has_config(optname) and (defval or 1) or opt.default, {quote = opt.quote}) + end end diff --git a/xmake/includes/check_links.lua b/xmake/includes/check_links.lua index a17561f5e..40adb0193 100644 --- a/xmake/includes/check_links.lua +++ b/xmake/includes/check_links.lua @@ -48,7 +48,13 @@ function configvar_check_links(definition, links, opt) local defname, defval = unpack(definition:split('=')) option(optname) add_links(links) - set_configvar(defname, defval or 1) + if opt.default == nil then + set_configvar(defname, defval or 1, {quote = opt.quote}) + end option_end() - add_options(optname) + if opt.default == nil then + add_options(optname) + else + set_configvar(defname, has_config(optname) and (defval or 1) or opt.default, {quote = opt.quote}) + end end diff --git a/xmake/includes/check_syslinks.lua b/xmake/includes/check_syslinks.lua index 0dab1fa7f..f7ac4a8df 100644 --- a/xmake/includes/check_syslinks.lua +++ b/xmake/includes/check_syslinks.lua @@ -48,7 +48,13 @@ function configvar_check_syslinks(definition, links, opt) local defname, defval = unpack(definition:split('=')) option(optname) add_syslinks(links) - set_configvar(defname, defval or 1) + if opt.default == nil then + set_configvar(defname, defval or 1, {quote = opt.quote}) + end option_end() - add_options(optname) + if opt.default == nil then + add_options(optname) + else + set_configvar(defname, has_config(optname) and (defval or 1) or opt.default, {quote = opt.quote}) + end end -- cgit v1.3.1 From cad630562127585d453f5469b9e4099291d3455d Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Sep 2021 00:52:26 +0800 Subject: add find_swig --- xmake/modules/detect/tools/find_swig.lua | 53 ++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 xmake/modules/detect/tools/find_swig.lua diff --git a/xmake/modules/detect/tools/find_swig.lua b/xmake/modules/detect/tools/find_swig.lua new file mode 100644 index 000000000..1442d712d --- /dev/null +++ b/xmake/modules/detect/tools/find_swig.lua @@ -0,0 +1,53 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_swig.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find swig +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local swig = find_swig() +-- local swig, version = find_swig({program = "swig", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + opt.check = opt.check or "-help" + + -- find program + local program = find_program(opt.program or "swig", opt) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, opt) + end + return program, version +end -- cgit v1.3.1 From 286e9ba7ef2e83e5222dbaab40160b3c1ac967f5 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Sep 2021 00:52:45 +0800 Subject: add swig rule stub --- xmake/rules/swig/xmake.lua | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 xmake/rules/swig/xmake.lua diff --git a/xmake/rules/swig/xmake.lua b/xmake/rules/swig/xmake.lua new file mode 100644 index 000000000..4ac852e48 --- /dev/null +++ b/xmake/rules/swig/xmake.lua @@ -0,0 +1,26 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +rule("swig") + set_extensions(".i") + on_load(function (target) + end) + + -- cgit v1.3.1 From ef34aa0c7f5a9996ff9c3863556b426a4f1f4da5 Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Fri, 24 Sep 2021 12:10:46 +0800 Subject: fix and test quote feature --- tests/apis/check_xxx/config.h.in | 2 ++ tests/apis/check_xxx/main.c | 1 + tests/apis/check_xxx/xmake.lua | 3 +++ xmake/actions/config/configfiles.lua | 2 ++ 4 files changed, 8 insertions(+) diff --git a/tests/apis/check_xxx/config.h.in b/tests/apis/check_xxx/config.h.in index 617ecf864..a8baad68d 100644 --- a/tests/apis/check_xxx/config.h.in +++ b/tests/apis/check_xxx/config.h.in @@ -9,4 +9,6 @@ ${define HAS_CONSEXPR_AND_STATIC_ASSERT} ${define HAS_SSE2} ${define HAS_LONG_8} ${define PTR_SIZE} +${define HAVE_VISIBILITY} +${define CUSTOM_ASSERT} #define HAS_WCHAR ${default HAS_WCHAR 0} diff --git a/tests/apis/check_xxx/main.c b/tests/apis/check_xxx/main.c index 5549c309f..5e40e6691 100644 --- a/tests/apis/check_xxx/main.c +++ b/tests/apis/check_xxx/main.c @@ -1,3 +1,4 @@ +#include "config.h" int main(int argc, char** argv) { diff --git a/tests/apis/check_xxx/xmake.lua b/tests/apis/check_xxx/xmake.lua index 2a9916954..ffd9f9242 100644 --- a/tests/apis/check_xxx/xmake.lua +++ b/tests/apis/check_xxx/xmake.lua @@ -9,6 +9,7 @@ includes("check_cincludes.lua") target("test") set_kind("binary") add_files("*.c") + add_includedirs("$(buildir)") add_configfiles("config.h.in") check_ctypes("HAS_WCHAR", "wchar_t") @@ -25,3 +26,5 @@ target("test") configvar_check_cflags("HAS_SSE2", "-msse2") configvar_check_csnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true}) configvar_check_csnippets("PTR_SIZE", 'printf("%d", sizeof(void*)); return 0;', {output = true, number = true}) + configvar_check_csnippets("HAVE_VISIBILITY", 'extern __attribute__((__visibility__("hidden"))) int hiddenvar;', {default = 0}) + configvar_check_csnippets("CUSTOM_ASSERT=assert", 'assert(1);', {default = "", quote = false}) diff --git a/xmake/actions/config/configfiles.lua b/xmake/actions/config/configfiles.lua index 974610a91..933ee4e66 100644 --- a/xmake/actions/config/configfiles.lua +++ b/xmake/actions/config/configfiles.lua @@ -178,6 +178,7 @@ function _generate_configfile(srcfile, dstfile, fileinfo, targets) for name, value in pairs(opt:get("configvar")) do if variables[name] == nil then variables[name] = table.unwrap(value) + variables["__extraconf_" .. name] = target:extraconf("configvar." .. name, value) end end end @@ -187,6 +188,7 @@ function _generate_configfile(srcfile, dstfile, fileinfo, targets) for name, value in pairs(pkg:get("configvar")) do if variables[name] == nil then variables[name] = table.unwrap(value) + variables["__extraconf_" .. name] = target:extraconf("configvar." .. name, value) end end end -- cgit v1.3.1 From 113108b4a6cbda7211d42a133b29eb90f688bc8e Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Fri, 24 Sep 2021 12:10:59 +0800 Subject: improve comments --- xmake/includes/check_cflags.lua | 8 +++++--- xmake/includes/check_cfuncs.lua | 2 ++ xmake/includes/check_cincludes.lua | 1 + xmake/includes/check_csnippets.lua | 2 ++ xmake/includes/check_ctypes.lua | 2 ++ xmake/includes/check_cxxflags.lua | 8 +++++--- xmake/includes/check_cxxfuncs.lua | 2 ++ xmake/includes/check_cxxincludes.lua | 1 + xmake/includes/check_cxxsnippets.lua | 2 ++ xmake/includes/check_cxxtypes.lua | 2 ++ xmake/includes/check_features.lua | 1 + xmake/includes/check_links.lua | 1 + xmake/includes/check_syslinks.lua | 1 + 13 files changed, 27 insertions(+), 6 deletions(-) diff --git a/xmake/includes/check_cflags.lua b/xmake/includes/check_cflags.lua index 46758d0aa..85c9ef3c7 100644 --- a/xmake/includes/check_cflags.lua +++ b/xmake/includes/check_cflags.lua @@ -23,7 +23,7 @@ -- e.g. -- -- check_cflags("HAS_SSE2", "-msse2") --- check_cflags("HAS_SSE2", {"-msse2", "/arch:SSE2"}) +-- check_cflags("HAS_SSE2", {"-msse", "-msse2"}) -- function check_cflags(definition, flags, opt) opt = opt or {} @@ -45,8 +45,10 @@ end -- e.g. -- -- configvar_check_cflags("HAS_SSE2", "-msse2") --- configvar_check_cflags("HAS_SSE2", {"-msse2", "/arch:SSE2"}) --- configvar_check_cflags("SSE=2", "-msse2") +-- configvar_check_cflags("HAS_SSE2", {"-msse", "-msse2"}) +-- configvar_check_cflags("HAS_SSE2", "-msse2", {default = 0}) +-- configvar_check_cflags("SSE_STR=2", "-msse2") +-- configvar_check_cflags("SSE=2", "-msse2", {quote = false}) -- function configvar_check_cflags(definition, flags, opt) opt = opt or {} diff --git a/xmake/includes/check_cfuncs.lua b/xmake/includes/check_cfuncs.lua index 42d06e5ff..42d173a18 100644 --- a/xmake/includes/check_cfuncs.lua +++ b/xmake/includes/check_cfuncs.lua @@ -68,6 +68,8 @@ end -- -- configvar_check_cfuncs("HAS_SETJMP", "setjmp", {includes = {"signal.h", "setjmp.h"}, links = {}}) -- configvar_check_cfuncs("HAS_SETJMP", {"setjmp", "sigsetjmp{sigsetjmp((void*)0, 0);}"}) +-- configvar_check_cfuncs("HAS_SETJMP", "setjmp", {includes = {"setjmp.h"}, default = 0}) +-- configvar_check_cfuncs("CUSTOM_SETJMP=setjmp", "setjmp", {includes = {"setjmp.h"}, default = "", quote = false}) -- function configvar_check_cfuncs(definition, funcs, opt) opt = opt or {} diff --git a/xmake/includes/check_cincludes.lua b/xmake/includes/check_cincludes.lua index ced7c33a5..f9d69aad5 100644 --- a/xmake/includes/check_cincludes.lua +++ b/xmake/includes/check_cincludes.lua @@ -43,6 +43,7 @@ end -- e.g. -- -- configvar_check_cincludes("HAS_STRING_H", "string.h") +-- configvar_check_cincludes("HAS_STRING_H", "string.h", {default = 0}) -- configvar_check_cincludes("HAS_STRING_AND_STDIO_H", {"string.h", "stdio.h"}) -- function configvar_check_cincludes(definition, includes, opt) diff --git a/xmake/includes/check_csnippets.lua b/xmake/includes/check_csnippets.lua index 3f7f853e5..492c80a56 100644 --- a/xmake/includes/check_csnippets.lua +++ b/xmake/includes/check_csnippets.lua @@ -76,6 +76,8 @@ end -- -- configvar_check_csnippets("HAS_STATIC_ASSERT", "_Static_assert(1, \"\");", {includes = "stdio.h"}) -- configvar_check_csnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true}) +-- configvar_check_csnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true, default = 0}) +-- configvar_check_csnippets("LONG_SIZE=8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true, quote = false}) -- configvar_check_csnippets("PTR_SIZE", 'printf("%d", sizeof(void*)); return 0;', {output = true, number = true}) -- function configvar_check_csnippets(definition, snippets, opt) diff --git a/xmake/includes/check_ctypes.lua b/xmake/includes/check_ctypes.lua index 934fc83b7..e0c3caa47 100644 --- a/xmake/includes/check_ctypes.lua +++ b/xmake/includes/check_ctypes.lua @@ -55,6 +55,8 @@ end -- e.g. -- -- configvar_check_ctypes("HAS_WCHAR", "wchar_t") +-- configvar_check_ctypes("HAS_WCHAR", "wchar_t", {default = 0}) +-- configvar_check_ctypes("CUSTOM_WCHAR=wchar_t", "wchar_t", {default = "", quote = false}) -- configvar_check_ctypes("HAS_WCHAR_AND_FLOAT", {"wchar_t", "float"}) -- function configvar_check_ctypes(definition, types, opt) diff --git a/xmake/includes/check_cxxflags.lua b/xmake/includes/check_cxxflags.lua index 36ca0ccd5..9a0880697 100644 --- a/xmake/includes/check_cxxflags.lua +++ b/xmake/includes/check_cxxflags.lua @@ -23,7 +23,7 @@ -- e.g. -- -- check_cxxflags("HAS_SSE2", "-msse2") --- check_cxxflags("HAS_SSE2", {"-msse2", "/arch:SSE2"}) +-- check_cxxflags("HAS_SSE2", {"-msse", "-msse2"}) -- function check_cxxflags(definition, flags, opt) opt = opt or {} @@ -45,8 +45,10 @@ end -- e.g. -- -- configvar_check_cxxflags("HAS_SSE2", "-msse2") --- configvar_check_cxxflags("HAS_SSE2", {"-msse2", "/arch:SSE2"}) --- configvar_check_cxxflags("SSE=2", "-msse2") +-- configvar_check_cxxflags("HAS_SSE2", {"-msse", "-msse2"}) +-- configvar_check_cxxflags("HAS_SSE2", "-msse2", {default = 0}) +-- configvar_check_cxxflags("SSE_STR=2", "-msse2") +-- configvar_check_cxxflags("SSE=2", "-msse2", {quote = false}) -- function configvar_check_cxxflags(definition, flags, opt) opt = opt or {} diff --git a/xmake/includes/check_cxxfuncs.lua b/xmake/includes/check_cxxfuncs.lua index 426f51edb..3a64075dc 100644 --- a/xmake/includes/check_cxxfuncs.lua +++ b/xmake/includes/check_cxxfuncs.lua @@ -68,6 +68,8 @@ end -- -- configvar_check_cxxfuncs("HAS_SETJMP", "setjmp", {includes = {"signal.h", "setjmp.h"}, links = {}}) -- configvar_check_cxxfuncs("HAS_SETJMP", {"setjmp", "sigsetjmp{sigsetjmp((void*)0, 0);}"}) +-- configvar_check_cxxfuncs("HAS_SETJMP", "setjmp", {includes = {"setjmp.h"}, default = 0}) +-- configvar_check_cxxfuncs("CUSTOM_SETJMP=setjmp", "setjmp", {includes = {"setjmp.h"}, default = "", quote = false}) -- function configvar_check_cxxfuncs(definition, funcs, opt) opt = opt or {} diff --git a/xmake/includes/check_cxxincludes.lua b/xmake/includes/check_cxxincludes.lua index ed9ecd6cd..a779ffd15 100644 --- a/xmake/includes/check_cxxincludes.lua +++ b/xmake/includes/check_cxxincludes.lua @@ -40,6 +40,7 @@ end -- e.g. -- -- configvar_check_cxxincludes("HAS_STRING_H", "string.h") +-- configvar_check_cxxincludes("HAS_STRING_H", "string.h", {default = 0}) -- configvar_check_cxxincludes("HAS_STRING_AND_STDIO_H", {"string.h", "stdio.h"}) -- function configvar_check_cxxincludes(definition, includes, opt) diff --git a/xmake/includes/check_cxxsnippets.lua b/xmake/includes/check_cxxsnippets.lua index 6da696c03..a65ed7355 100644 --- a/xmake/includes/check_cxxsnippets.lua +++ b/xmake/includes/check_cxxsnippets.lua @@ -76,6 +76,8 @@ end -- -- configvar_check_cxxsnippets("HAS_STATIC_ASSERT", "static_assert(1, \"\");") -- configvar_check_cxxsnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true}) +-- configvar_check_cxxsnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true, default = 0}) +-- configvar_check_cxxsnippets("LONG_SIZE=8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true, quote = false}) -- configvar_check_cxxsnippets("PTR_SIZE", 'printf("%d", sizeof(void*)); return 0;', {output = true, number = true}) -- function configvar_check_cxxsnippets(definition, snippets, opt) diff --git a/xmake/includes/check_cxxtypes.lua b/xmake/includes/check_cxxtypes.lua index 1428e1fba..e53caae6e 100644 --- a/xmake/includes/check_cxxtypes.lua +++ b/xmake/includes/check_cxxtypes.lua @@ -55,6 +55,8 @@ end -- e.g. -- -- configvar_check_cxxtypes("HAS_WCHAR", "wchar_t") +-- configvar_check_cxxtypes("HAS_WCHAR", "wchar_t", {default = 0}) +-- configvar_check_cxxtypes("CUSTOM_WCHAR=wchar_t", "wchar_t", {default = "", quote = false}) -- configvar_check_cxxtypes("HAS_WCHAR_AND_FLOAT", {"wchar_t", "float"}) -- function configvar_check_cxxtypes(definition, types, opt) diff --git a/xmake/includes/check_features.lua b/xmake/includes/check_features.lua index e837c485c..7c02be173 100644 --- a/xmake/includes/check_features.lua +++ b/xmake/includes/check_features.lua @@ -52,6 +52,7 @@ end -- e.g. -- -- configvar_check_features("HAS_CONSTEXPR", "cxx_constexpr") +-- configvar_check_features("HAS_CONSTEXPR", "cxx_constexpr", {default = 0}) -- configvar_check_features("HAS_CONSEXPR_AND_STATIC_ASSERT", {"cxx_constexpr", "c_static_assert"}, {languages = "c++11"}) -- function configvar_check_features(definition, features, opt) diff --git a/xmake/includes/check_links.lua b/xmake/includes/check_links.lua index 40adb0193..06b8cb38c 100644 --- a/xmake/includes/check_links.lua +++ b/xmake/includes/check_links.lua @@ -40,6 +40,7 @@ end -- e.g. -- -- configvar_check_links("HAS_PTHREAD", "pthread") +-- configvar_check_links("HAS_PTHREAD", "pthread", {default = 0}) -- configvar_check_links("HAS_PTHREAD", {"pthread", "m", "dl"}) -- function configvar_check_links(definition, links, opt) diff --git a/xmake/includes/check_syslinks.lua b/xmake/includes/check_syslinks.lua index f7ac4a8df..133e24dcd 100644 --- a/xmake/includes/check_syslinks.lua +++ b/xmake/includes/check_syslinks.lua @@ -40,6 +40,7 @@ end -- e.g. -- -- configvar_check_syslinks("HAS_PTHREAD", "pthread") +-- configvar_check_syslinks("HAS_PTHREAD", "pthread", {default = 0}) -- configvar_check_syslinks("HAS_PTHREAD", {"pthread", "m", "dl"}) -- function configvar_check_syslinks(definition, links, opt) -- cgit v1.3.1 From 5f353149251447da48617b597fc2020d24c6bc2f Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Fri, 24 Sep 2021 12:20:02 +0800 Subject: use opt.quote in place of opt.number --- xmake/includes/check_csnippets.lua | 4 +++- xmake/includes/check_cxxsnippets.lua | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/xmake/includes/check_csnippets.lua b/xmake/includes/check_csnippets.lua index 492c80a56..95aa0b2d5 100644 --- a/xmake/includes/check_csnippets.lua +++ b/xmake/includes/check_csnippets.lua @@ -60,6 +60,8 @@ function check_csnippets(definition, snippets, opt) if option:value() then if opt.number then option:add("defines", definition .. "=" .. tonumber(option:value())) + elseif opt.quote == false then + option:add("defines", definition .. "=" .. option:value()) else option:add("defines", definition .. "=\"" .. option:value() .. "\"") end @@ -113,7 +115,7 @@ function configvar_check_csnippets(definition, snippets, opt) if opt.output then after_check(function (option) if option:value() then - option:set("configvar", defname, opt.number and tonumber(option:value()) or option:value()) + option:set("configvar", defname, opt.number and tonumber(option:value()) or option:value(), {quote = opt.quote}) end end) end diff --git a/xmake/includes/check_cxxsnippets.lua b/xmake/includes/check_cxxsnippets.lua index a65ed7355..b46c650ff 100644 --- a/xmake/includes/check_cxxsnippets.lua +++ b/xmake/includes/check_cxxsnippets.lua @@ -60,6 +60,8 @@ function check_cxxsnippets(definition, snippets, opt) if option:value() then if opt.number then option:add("defines", definition .. "=" .. tonumber(option:value())) + elseif opt.quote == false then + option:add("defines", definition .. "=" .. option:value()) else option:add("defines", definition .. "=\"" .. option:value() .. "\"") end @@ -113,7 +115,7 @@ function configvar_check_cxxsnippets(definition, snippets, opt) if opt.output then after_check(function (option) if option:value() then - option:set("configvar", defname, opt.number and tonumber(option:value()) or option:value()) + option:set("configvar", defname, opt.number and tonumber(option:value()) or option:value(), {quote = opt.quote}) end end) end -- cgit v1.3.1 From c2f3f280bcfd82618590e9872ddce19b56940ab0 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Sep 2021 22:41:45 +0800 Subject: add swig.c and swig.cpp rules --- tests/projects/swig/python_c/src/example.c | 14 ++++++++ tests/projects/swig/python_c/src/example.i | 11 ++++++ tests/projects/swig/python_c/xmake.lua | 8 +++++ xmake/rules/swig/build_module_file.lua | 58 ++++++++++++++++++++++++++++++ xmake/rules/swig/xmake.lua | 27 ++++++++++++-- 5 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 tests/projects/swig/python_c/src/example.c create mode 100644 tests/projects/swig/python_c/src/example.i create mode 100644 tests/projects/swig/python_c/xmake.lua create mode 100644 xmake/rules/swig/build_module_file.lua diff --git a/tests/projects/swig/python_c/src/example.c b/tests/projects/swig/python_c/src/example.c new file mode 100644 index 000000000..31c659bfa --- /dev/null +++ b/tests/projects/swig/python_c/src/example.c @@ -0,0 +1,14 @@ +double My_variable = 3.0; + +/* Compute factorial of n */ +int fact(int n) { + if (n <= 1) + return 1; + else + return n*fact(n-1); +} + +/* Compute n mod m */ +int my_mod(int n, int m) { + return(n % m); +} diff --git a/tests/projects/swig/python_c/src/example.i b/tests/projects/swig/python_c/src/example.i new file mode 100644 index 000000000..34193edc7 --- /dev/null +++ b/tests/projects/swig/python_c/src/example.i @@ -0,0 +1,11 @@ +%module example +%{ +/* Put headers and other declarations here */ +extern double My_variable; +extern int fact(int); +extern int my_mod(int n, int m); +%} + +extern double My_variable; +extern int fact(int); +extern int my_mod(int n, int m); diff --git a/tests/projects/swig/python_c/xmake.lua b/tests/projects/swig/python_c/xmake.lua new file mode 100644 index 000000000..2b30079b6 --- /dev/null +++ b/tests/projects/swig/python_c/xmake.lua @@ -0,0 +1,8 @@ +add_rules("mode.release", "mode.debug") +add_requires("python 3.x") + +target("example") + add_rules("swig.c") + add_files("src/example.i", {moduletype = "python"}) + add_files("src/example.c") + add_packages("python") diff --git a/xmake/rules/swig/build_module_file.lua b/xmake/rules/swig/build_module_file.lua new file mode 100644 index 000000000..edcd6b04b --- /dev/null +++ b/xmake/rules/swig/build_module_file.lua @@ -0,0 +1,58 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file build_module_file.lua +-- + +-- imports +import("lib.detect.find_tool") + +function main(target, batchcmds, sourcefile, opt) + + -- get module type + opt = opt or {} + local moduletype + local fileconfig = target:fileconfig(sourcefile) + if fileconfig then + moduletype = fileconfig.moduletype + end + assert(moduletype, "%s: unknown swig module type, please use `add_files(\"foo.c\", {moduletype = \"python\"})` to set it!", sourcefile) + + -- get swig + local swig = assert(find_tool("swig"), "swig not found!") + local sourcefile_cx = path.join(target:autogendir(), "rules", "swig", path.basename(sourcefile) .. (opt.sourcekind == "cxx" and ".cpp" or ".c")) + + -- add objectfile + local objectfile = target:objectfile(sourcefile_cx) + table.insert(target:objectfiles(), objectfile) + + -- add commands + local argv = {"-" .. moduletype, "-o", sourcefile_cx} + if opt.sourcekind == "cxx" then + table.insert(argv, "-c++") + end + table.insert(argv, sourcefile) + batchcmds:show_progress(opt.progress, "${color.build.object}compiling.swig.%s %s", moduletype, sourcefile) + batchcmds:mkdir(path.directory(sourcefile_cx)) + batchcmds:vrunv(swig.program, argv) + batchcmds:compile(sourcefile_cx, objectfile) + + -- add deps + batchcmds:add_depfiles(sourcefile) + batchcmds:set_depmtime(os.mtime(objectfile)) + batchcmds:set_depcache(target:dependfile(objectfile)) +end diff --git a/xmake/rules/swig/xmake.lua b/xmake/rules/swig/xmake.lua index 4ac852e48..1756cf1c9 100644 --- a/xmake/rules/swig/xmake.lua +++ b/xmake/rules/swig/xmake.lua @@ -18,9 +18,32 @@ -- @file xmake.lua -- -rule("swig") - set_extensions(".i") +-- references: +-- +-- https://github.com/xmake-io/xmake/issues/1622 +-- http://www.swig.org/Doc4.0/SWIGDocumentation.html#Introduction_nn4 +-- + +rule("swig.base") on_load(function (target) + target:set("kind", "shared") + if target:is_plat("windows") then + target:set("extension", ".pyd") + end + end) + +rule("swig.c") + set_extensions(".i") + add_deps("swig.base") + on_buildcmd_file(function (target, batchcmds, sourcefile, opt) + import("build_module_file")(target, batchcmds, sourcefile, table.join({sourcekind = "cc"}, opt)) + end) + +rule("swig.cpp") + set_extensions(".i") + add_deps("swig.base") + on_buildcmd_file(function (target, batchcmds, sourcefile, opt) + import("build_module_file")(target, batchcmds, sourcefile, table.join({sourcekind = "cxx"}, opt)) end) -- cgit v1.3.1 From c3b4b1882e06d80e2a3d2a81e4be594803d56c39 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Sep 2021 22:45:56 +0800 Subject: install swig scripts --- tests/projects/swig/python_c/xmake.lua | 2 +- tests/projects/swig/python_cpp/src/example.cpp | 14 ++++++++++++++ tests/projects/swig/python_cpp/src/example.i | 11 +++++++++++ tests/projects/swig/python_cpp/xmake.lua | 8 ++++++++ xmake/rules/swig/xmake.lua | 24 ++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 tests/projects/swig/python_cpp/src/example.cpp create mode 100644 tests/projects/swig/python_cpp/src/example.i create mode 100644 tests/projects/swig/python_cpp/xmake.lua diff --git a/tests/projects/swig/python_c/xmake.lua b/tests/projects/swig/python_c/xmake.lua index 2b30079b6..89b13cbd4 100644 --- a/tests/projects/swig/python_c/xmake.lua +++ b/tests/projects/swig/python_c/xmake.lua @@ -3,6 +3,6 @@ add_requires("python 3.x") target("example") add_rules("swig.c") - add_files("src/example.i", {moduletype = "python"}) + add_files("src/example.i", {moduletype = "python", scriptdir = "share"}) add_files("src/example.c") add_packages("python") diff --git a/tests/projects/swig/python_cpp/src/example.cpp b/tests/projects/swig/python_cpp/src/example.cpp new file mode 100644 index 000000000..31c659bfa --- /dev/null +++ b/tests/projects/swig/python_cpp/src/example.cpp @@ -0,0 +1,14 @@ +double My_variable = 3.0; + +/* Compute factorial of n */ +int fact(int n) { + if (n <= 1) + return 1; + else + return n*fact(n-1); +} + +/* Compute n mod m */ +int my_mod(int n, int m) { + return(n % m); +} diff --git a/tests/projects/swig/python_cpp/src/example.i b/tests/projects/swig/python_cpp/src/example.i new file mode 100644 index 000000000..34193edc7 --- /dev/null +++ b/tests/projects/swig/python_cpp/src/example.i @@ -0,0 +1,11 @@ +%module example +%{ +/* Put headers and other declarations here */ +extern double My_variable; +extern int fact(int); +extern int my_mod(int n, int m); +%} + +extern double My_variable; +extern int fact(int); +extern int my_mod(int n, int m); diff --git a/tests/projects/swig/python_cpp/xmake.lua b/tests/projects/swig/python_cpp/xmake.lua new file mode 100644 index 000000000..f0c322310 --- /dev/null +++ b/tests/projects/swig/python_cpp/xmake.lua @@ -0,0 +1,8 @@ +add_rules("mode.release", "mode.debug") +add_requires("python 3.x") + +target("example") + add_rules("swig.cpp") + add_files("src/example.i", {moduletype = "python", scriptdir = "share"}) + add_files("src/example.cpp") + add_packages("python") diff --git a/xmake/rules/swig/xmake.lua b/xmake/rules/swig/xmake.lua index 1756cf1c9..c02ed1362 100644 --- a/xmake/rules/swig/xmake.lua +++ b/xmake/rules/swig/xmake.lua @@ -30,6 +30,30 @@ rule("swig.base") if target:is_plat("windows") then target:set("extension", ".pyd") end + local scriptfiles = {} + for _, sourcebatch in pairs(target:sourcebatches()) do + if sourcebatch.rulename:startswith("swig.") then + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local scriptdir + local moduletype + local fileconfig = target:fileconfig(sourcefile) + if fileconfig then + moduletype = fileconfig.moduletype + scriptdir = fileconfig.scriptdir + end + local scriptfile = path.join(target:autogendir(), "rules", "swig", path.basename(sourcefile)) + if moduletype == "python" then + scriptfile = scriptfile .. ".py" + end + table.insert(scriptfiles, scriptfile) + if scriptdir then + target:add("installfiles", scriptfile, {prefixdir = scriptdir}) + end + end + end + end + -- for custom on_install/after_install, user can use it to install them + target:set("data", "swig.scriptfiles", scriptfiles) end) rule("swig.c") -- cgit v1.3.1 From 4a8694d08d48ebc4101cc1b35e88b3fffe56de59 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Sep 2021 22:47:08 +0800 Subject: support swig --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8eaeea298..45b74bad2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * [#388](https://github.com/xmake-io/xmake/issues/388): Pascal Language Support * [#1682](https://github.com/xmake-io/xmake/issues/1682): Add optional lua5.3 backend instead of luajit to provide better compatibility +* [#1622](https://github.com/xmake-io/xmake/issues/1622): Support Swig ### Change @@ -1084,6 +1085,7 @@ * [#388](https://github.com/xmake-io/xmake/issues/388): Pascal 语言支持,可以使用 fpc 来编译 free pascal * [#1682](https://github.com/xmake-io/xmake/issues/1682): 添加可选的额lua5.3 运行时替代 luajit,提供更好的平台兼容性。 +* [#1622](https://github.com/xmake-io/xmake/issues/1622): 支持 Swig ### 改进 -- cgit v1.3.1 From 28efcb4f71051f9a5ede3ced4f03fad8f311e949 Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Fri, 24 Sep 2021 14:56:28 +0800 Subject: fix filter with numbers as key --- xmake/core/base/interpreter.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/core/base/interpreter.lua b/xmake/core/base/interpreter.lua index ecfcc7270..131a6d1c2 100644 --- a/xmake/core/base/interpreter.lua +++ b/xmake/core/base/interpreter.lua @@ -446,7 +446,7 @@ function interpreter:_filter(values, level) if table.is_dictionary(values) then local results = {} for key, value in pairs(values) do - key = filter:handle(key) + key = (type(key) == "string" and filter:handle(key) or key) if type(value) == "string" then results[key] = filter:handle(value) elseif type(value) == "table" and level < 1 then -- cgit v1.3.1 From 413dfb47ea08bb19b91a96cd7ce44249821e8c6a Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Sep 2021 16:00:47 +0800 Subject: update get.ps1 and remove appveyor --- scripts/get.ps1 | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/scripts/get.ps1 b/scripts/get.ps1 index 8cb27a888..a8834718d 100755 --- a/scripts/get.ps1 +++ b/scripts/get.ps1 @@ -11,6 +11,7 @@ param ( ) & { + $LastRelease = "v2.5.7" $ErrorActionPreference = 'Stop' function writeErrorTip($msg) { @@ -30,9 +31,9 @@ param ( } if ($IsLinux -or $IsMacOS) { - writeErrorTip 'Install on *nix is not supported, try ' + writeErrorTip 'Install on *nix is not supported, try ' writeErrorTip '(Use curl) "bash <(curl -fsSL https://raw.githubusercontent.com/xmake-io/xmake/master/scripts/get.sh)"' - writeErrorTip 'or' + writeErrorTip 'or' writeErrorTip '(Use wget) "bash <(wget https://raw.githubusercontent.com/xmake-io/xmake/master/scripts/get.sh -O -)"' throw 'Unsupported platform' } @@ -90,7 +91,7 @@ param ( $url = if ($v -is [version]) { "https://github.com/xmake-io/xmake/releases/download/v$v/xmake-v$v.$winarch.exe" } else { - "https://ci.appveyor.com/api/projects/waruqi/xmake/artifacts/xmake-installer.exe?branch=$v&pr=false&job=Image%3A+Visual+Studio+2017%3B+Platform%3A+$arch" + "https://github.com/xmake-io/xmake/releases/download/$LastRelease/xmake-$v.$winarch.exe" } Write-Host "Start downloading $url .." try { @@ -145,9 +146,9 @@ param ( writeErrorTip "Please try again as administrator" return } - + if ($content) { - $content = [System.Text.RegularExpressions.Regex]::Replace($content, "\n*(# PowerShell parameter completion shim for xmake)?\s*Register-ArgumentCompleter -Native -CommandName xmake -ScriptBlock\s*{.+?\n}\s*", "`n", [System.Text.RegularExpressions.RegexOptions]::Singleline) + $content = [System.Text.RegularExpressions.Regex]::Replace($content, "\n*(# PowerShell parameter completion shim for xmake)?\s*Register-ArgumentCompleter -Native -CommandName xmake -ScriptBlock\s*{.+?\n}\s*", "`n", [System.Text.RegularExpressions.RegexOptions]::Singleline) } try { $appendcontent = (Invoke-Webrequest 'https://xmake.io/assets/scripts/pscompletions.text' -UseBasicParsing).Content -- cgit v1.3.1 From 0b2b346e9784637f4093e566c2cfb32e5eb16d6e Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Sep 2021 16:02:06 +0800 Subject: Delete .appveyor.yml --- .appveyor.yml | 125 ---------------------------------------------------------- 1 file changed, 125 deletions(-) delete mode 100644 .appveyor.yml diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index 0316f0178..000000000 --- a/.appveyor.yml +++ /dev/null @@ -1,125 +0,0 @@ -#version: v2.1.8.{build} -image: - - Visual Studio 2015 - - Visual Studio 2017 - -platform: - - x86 - - x64 - -install: - # prepare tools - - ps: Push-Location C:/ - - ps: (New-Item ./winenv/bin -ItemType Directory).FullName - # nsis - - ps: Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/nsis-3.04.zip" -UseBasicParsing -OutFile ./nsis.zip - - ps: Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/nsis-3.04-strlen_8192.zip" -UseBasicParsing -OutFile ./nsis-longstr.zip - - ps: Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/UAC.zip" -UseBasicParsing -OutFile ./nsis-uac.zip - - ps: Expand-Archive ./nsis.zip -DestinationPath ./nsis - - ps: Move-Item ./nsis/*/* ./nsis - - ps: Expand-Archive ./nsis-longstr.zip -DestinationPath ./nsis -Force - - ps: Expand-Archive ./nsis-uac.zip -DestinationPath ./nsis -Force - - ps: Move-Item ./nsis/UAC.nsh ./nsis/Include/ - # 7zip - - ps: Invoke-WebRequest "https://github.com/xmake-mirror/7zip/releases/download/19.00/7z19.00-$($env:platform).zip" -UseBasicParsing -OutFile .\7zip.zip - - ps: Expand-Archive ./7zip.zip -DestinationPath ./7zip - - ps: Copy-Item ./7zip/7z.exe ./winenv/bin - - ps: Copy-Item ./7zip/7z.dll ./winenv/bin - # curl - - ps: Invoke-WebRequest "https://github.com/xmake-io/xmake-win$(if ($env:platform -eq 'x64') { '64' } else { '32' })env/raw/master/bin/curl.exe" -UseBasicParsing -OutFile .\curl.exe - - ps: Invoke-WebRequest "https://raw.githubusercontent.com/xmake-io/xmake-win$(if ($env:platform -eq 'x64') { '64' } else { '32' })env/master/bin/curl-ca-bundle.crt" -UseBasicParsing -OutFile .\curl-ca-bundle.crt - - ps: Copy-Item ./curl.exe ./winenv/bin - - ps: Copy-Item ./curl-ca-bundle.crt ./winenv/bin - # - - ps: Pop-Location - # install xmake - - ps: git submodule -q update --init --recursive - - ps: ./scripts/get.ps1 -branch master - -before_build: - - ps: (Get-Command xmake).FileVersionInfo.ProductVersion - -build_script: - # self build - - ps: Push-Location ./core - - ps: xmake config --arch=$env:platform - - ps: xmake build - - ps: Pop-Location - # use new xmake - - ps: Set-AppveyorBuildVariable -Name XMAKE_PROGRAM_DIR -Value $(Resolve-Path ./xmake) - - ps: Copy-Item -Force .\core\build\xmake.exe $(Get-Command xmake).Path - - ps: (Get-Command xmake).FileVersionInfo.ProductVersion - # use bitcodes - #- ps: xmake l -v private.utils.bcsave --rootname='@programdir' -x 'scripts/**|templates/**' xmake - #- ps: (Get-Command xmake).FileVersionInfo.ProductVersion - -after_build: - # publish exe - - ps: Push-AppveyorArtifact .\core\build\xmake.exe -FileName xmake.exe -DeploymentName "xmake-executable" - - ps: (Get-FileHash .\core\build\xmake.exe -Algorithm SHA256).Hash.ToLower() + " *xmake.exe`n" | Out-File ./shafile -Encoding ASCII -NoNewLine - # compose & publish installer - - ps: Copy-Item C:\winenv\ . -Recurse - - ps: $version = (Get-Command xmake).FileVersionInfo - - ps: C:\nsis\makensis.exe - /DMAJOR=$($version.ProductMajorPart) - /DMINOR=$($version.ProductMinorPart) - /DALTER=$($version.ProductBuildPart) - /DBUILD=$($($version.ProductVersion -split '\+')[1]) - /D$($env:platform) - .\scripts\installer.nsi - - ps: Push-AppveyorArtifact .\scripts\xmake.exe -FileName xmake-installer.exe -DeploymentName "xmake-installer" - - ps: (Get-FileHash .\scripts\xmake.exe -Algorithm SHA256).Hash.ToLower() + " *xmake-installer.exe`n" | Out-File ./shafile -Encoding ASCII -NoNewLine -Append - # publish zip archive - - ps: Copy-Item .\*.md .\xmake - - ps: Copy-Item C:\winenv\ .\xmake -Recurse - - ps: Copy-Item .\core\build\xmake.exe .\xmake - - ps: Copy-Item .\scripts\xrepo.bat .\xmake\xrepo.bat - - ps: Copy-Item .\scripts\xrepo.ps1 .\xmake\xrepo.ps1 - - ps: |- - Add-Type -AssemblyName System.Text.Encoding - Add-Type -AssemblyName System.IO.Compression.FileSystem - - class FixedEncoder : System.Text.UTF8Encoding { - FixedEncoder() : base($true) { } - - [byte[]] GetBytes([string] $s) - { - $s = $s.Replace("\", "/") - return ([System.Text.UTF8Encoding]$this).GetBytes($s) - } - } - Copy-Item .\xmake .\archive\xmake -Recurse - - [System.IO.Compression.ZipFile]::CreateFromDirectory("$PWD\archive", "$PWD\archive.zip", [System.IO.Compression.CompressionLevel]::Optimal, $false, [FixedEncoder]::new()) - - ps: Push-AppveyorArtifact .\archive.zip -FileName xmake.zip -DeploymentName "xmake-archive" - - ps: (Get-FileHash .\archive.zip -Algorithm SHA256).Hash.ToLower() + " *xmake.zip`n" | Out-File ./shafile -Encoding ASCII -NoNewLine -Append - # publish sha file - - ps: Push-AppveyorArtifact ./shafile -FileName xmake.sha256 -DeploymentName "xmake-shafile" - -test_script: - - ps: xmake --version - - ps: Push-Location ./tests - - ps: |- - $tests = Get-ChildItem test.lua -Recurse | ForEach-Object { - $testname = "$(Resolve-Path $_.Directory -Relative)" - $filename = "$(Resolve-Path $_ -Relative)" - $fullname = "$($_.FullName)" - Add-AppveyorTest -Name $testname -Framework "xmake-test" -FileName $filename -Outcome None - return @{ testname = $testname; filename = $filename; fullname = $fullname } - } - - ps: $all_success = $true - - ps: |- - $tests | ForEach-Object { - $testname = $_.testname - $filename = $_.filename - Update-AppveyorTest -Name $testname -Framework "xmake-test" -FileName $filename -Outcome Running - $time = Measure-Command { - xmake lua --verbose --diagnosis runner.lua $_.fullname >stdout_file 2>stderr_file - $outcome = if ($?) { "Passed" } else { $all_success = $false; "Failed" } - } - Get-Content stdout_file | Out-Host - Get-Content stderr_file | Out-Host - Update-AppveyorTest -Name $testname -Framework "xmake-test" -FileName $filename -Outcome $outcome -Duration $time.TotalMilliseconds -StdOut (Get-Content -Raw stdout_file) -StdErr (Get-Content -Raw stderr_file) - } - - ps: Pop-Location - - ps: if ($all_success) { Write-Host "All tests passed!" } else { Write-Error "Some tests failed!" } -- cgit v1.3.1 From 686ea5861ca004c22a19ecbc7be67c17fd7f9755 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Sep 2021 17:12:13 +0800 Subject: Update windows.yml --- .github/workflows/windows.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 9672fc47e..1516a5984 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -35,6 +35,17 @@ jobs: - uses: little-core-labs/get-git-tag@v3.0.2 id: tagName + # Force xmake to a specific folder (for cache) + - name: Set xmake package cache path + run: echo "XMAKE_PKG_CACHEDIR=$(pwd)/xmake-cache" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + + # Cache xmake dependencies + - name: Retrieve xmake cache for packages + uses: actions/cache@v2 + with: + path: xmake-cache + key: ${{ matrix.os }}-${{ matrix.arch }} + - name: Prepare run: | xmake show -- cgit v1.3.1 From 37d770af0cb8714309a9aad7188616079ad006eb Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Sep 2021 21:27:07 +0800 Subject: Update find_swig.lua --- xmake/modules/detect/tools/find_swig.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/detect/tools/find_swig.lua b/xmake/modules/detect/tools/find_swig.lua index 1442d712d..25220030e 100644 --- a/xmake/modules/detect/tools/find_swig.lua +++ b/xmake/modules/detect/tools/find_swig.lua @@ -39,7 +39,7 @@ function main(opt) -- init options opt = opt or {} - opt.check = opt.check or "-help" + opt.check = opt.check or "-version" -- find program local program = find_program(opt.program or "swig", opt) -- cgit v1.3.1 From 83a9195621935b1276f4a6d7d904081ab069cfb6 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 25 Sep 2021 00:48:56 +0800 Subject: improve swig binary name --- xmake/rules/swig/xmake.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xmake/rules/swig/xmake.lua b/xmake/rules/swig/xmake.lua index c02ed1362..f4f6bd4ed 100644 --- a/xmake/rules/swig/xmake.lua +++ b/xmake/rules/swig/xmake.lua @@ -29,6 +29,8 @@ rule("swig.base") target:set("kind", "shared") if target:is_plat("windows") then target:set("extension", ".pyd") + elseif target:is_plat("linux") then + target:set("prefixname", "_") end local scriptfiles = {} for _, sourcebatch in pairs(target:sourcebatches()) do -- cgit v1.3.1 From 8970563b1478bced1c9550506f96eac0b914696a Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 25 Sep 2021 00:49:34 +0800 Subject: improve swig binary name --- xmake/rules/swig/xmake.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/xmake/rules/swig/xmake.lua b/xmake/rules/swig/xmake.lua index f4f6bd4ed..28f8e0563 100644 --- a/xmake/rules/swig/xmake.lua +++ b/xmake/rules/swig/xmake.lua @@ -27,10 +27,9 @@ rule("swig.base") on_load(function (target) target:set("kind", "shared") + target:set("prefixname", "_") if target:is_plat("windows") then target:set("extension", ".pyd") - elseif target:is_plat("linux") then - target:set("prefixname", "_") end local scriptfiles = {} for _, sourcebatch in pairs(target:sourcebatches()) do -- cgit v1.3.1 From 50eeea59ecee08e93e2c69929d12fa6953b92855 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 25 Sep 2021 21:01:04 +0800 Subject: fix format for lua --- core/src/xmake/io/pipe_read.c | 2 +- core/src/xmake/io/pipe_write.c | 6 +++--- core/src/xmake/io/socket_recv.c | 2 +- core/src/xmake/io/socket_recvfrom.c | 2 +- core/src/xmake/io/socket_send.c | 6 +++--- core/src/xmake/io/socket_sendfile.c | 4 ++-- core/src/xmake/io/socket_sendto.c | 2 +- core/src/xmake/process/open.c | 4 ++-- core/src/xmake/process/openv.c | 6 +++--- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/core/src/xmake/io/pipe_read.c b/core/src/xmake/io/pipe_read.c index 73451995b..72a931f5c 100644 --- a/core/src/xmake/io/pipe_read.c +++ b/core/src/xmake/io/pipe_read.c @@ -69,7 +69,7 @@ tb_int_t xm_io_pipe_read(lua_State* lua) if (size <= 0) { lua_pushinteger(lua, -1); - lua_pushfstring(lua, "invalid size(%ld)!", size); + lua_pushfstring(lua, "invalid size(%d)!", (tb_int_t)size); return 2; } diff --git a/core/src/xmake/io/pipe_write.c b/core/src/xmake/io/pipe_write.c index 27d805ace..c44836783 100644 --- a/core/src/xmake/io/pipe_write.c +++ b/core/src/xmake/io/pipe_write.c @@ -78,7 +78,7 @@ tb_int_t xm_io_pipe_write(lua_State* lua) if (!data || !size) { lua_pushinteger(lua, -1); - lua_pushfstring(lua, "invalid data(%p) and size(%zu)!", data, size); + lua_pushfstring(lua, "invalid data(%p) and size(%d)!", data, (tb_int_t)size); return 2; } @@ -88,7 +88,7 @@ tb_int_t xm_io_pipe_write(lua_State* lua) if (start < 1 || start > size) { lua_pushinteger(lua, -1); - lua_pushfstring(lua, "invalid start position(%ld)!", start); + lua_pushfstring(lua, "invalid start position(%d)!", (tb_int_t)start); return 2; } @@ -98,7 +98,7 @@ tb_int_t xm_io_pipe_write(lua_State* lua) if (last < start - 1 || last > size + start - 1) { lua_pushinteger(lua, -1); - lua_pushfstring(lua, "invalid last position(%ld)!", last); + lua_pushfstring(lua, "invalid last position(%d)!", (tb_int_t)last); return 2; } diff --git a/core/src/xmake/io/socket_recv.c b/core/src/xmake/io/socket_recv.c index aefdfc485..e3bd2dfed 100644 --- a/core/src/xmake/io/socket_recv.c +++ b/core/src/xmake/io/socket_recv.c @@ -69,7 +69,7 @@ tb_int_t xm_io_socket_recv(lua_State* lua) if (size <= 0) { lua_pushinteger(lua, -1); - lua_pushfstring(lua, "invalid size(%ld)!", size); + lua_pushfstring(lua, "invalid size(%d)!", (tb_int_t)size); return 2; } diff --git a/core/src/xmake/io/socket_recvfrom.c b/core/src/xmake/io/socket_recvfrom.c index 243e6e08f..2a6ed7a16 100644 --- a/core/src/xmake/io/socket_recvfrom.c +++ b/core/src/xmake/io/socket_recvfrom.c @@ -69,7 +69,7 @@ tb_int_t xm_io_socket_recvfrom(lua_State* lua) if (size <= 0) { lua_pushinteger(lua, -1); - lua_pushfstring(lua, "invalid size(%ld)!", size); + lua_pushfstring(lua, "invalid size(%d)!", (tb_int_t)size); return 2; } diff --git a/core/src/xmake/io/socket_send.c b/core/src/xmake/io/socket_send.c index 71c057de8..5d697f3e4 100644 --- a/core/src/xmake/io/socket_send.c +++ b/core/src/xmake/io/socket_send.c @@ -78,7 +78,7 @@ tb_int_t xm_io_socket_send(lua_State* lua) if (!data || !size) { lua_pushinteger(lua, -1); - lua_pushfstring(lua, "invalid data(%p) and size(%zu)!", data, size); + lua_pushfstring(lua, "invalid data(%p) and size(%d)!", data, (tb_int_t)size); return 2; } @@ -88,7 +88,7 @@ tb_int_t xm_io_socket_send(lua_State* lua) if (start < 1 || start > size) { lua_pushinteger(lua, -1); - lua_pushfstring(lua, "invalid start position(%ld)!", start); + lua_pushfstring(lua, "invalid start position(%d)!", (tb_int_t)start); return 2; } @@ -98,7 +98,7 @@ tb_int_t xm_io_socket_send(lua_State* lua) if (last < start - 1 || last > size + start - 1) { lua_pushinteger(lua, -1); - lua_pushfstring(lua, "invalid last position(%ld)!", last); + lua_pushfstring(lua, "invalid last position(%d)!", (tb_int_t)last); return 2; } diff --git a/core/src/xmake/io/socket_sendfile.c b/core/src/xmake/io/socket_sendfile.c index fba10874b..456d23b49 100644 --- a/core/src/xmake/io/socket_sendfile.c +++ b/core/src/xmake/io/socket_sendfile.c @@ -96,7 +96,7 @@ tb_int_t xm_io_socket_sendfile(lua_State* lua) if (start < 1 || start > filesize) { lua_pushinteger(lua, -1); - lua_pushfstring(lua, "invalid start position(%ld)!", start); + lua_pushfstring(lua, "invalid start position(%d)!", (tb_int_t)start); return 2; } @@ -106,7 +106,7 @@ tb_int_t xm_io_socket_sendfile(lua_State* lua) if (last < start - 1 || last > filesize + start - 1) { lua_pushinteger(lua, -1); - lua_pushfstring(lua, "invalid last position(%ld)!", last); + lua_pushfstring(lua, "invalid last position(%d)!", (tb_int_t)last); return 2; } diff --git a/core/src/xmake/io/socket_sendto.c b/core/src/xmake/io/socket_sendto.c index 864b51936..f203df5b6 100644 --- a/core/src/xmake/io/socket_sendto.c +++ b/core/src/xmake/io/socket_sendto.c @@ -78,7 +78,7 @@ tb_int_t xm_io_socket_sendto(lua_State* lua) if (!data || !size) { lua_pushinteger(lua, -1); - lua_pushfstring(lua, "invalid data(%p) and size(%zu)!", data, size); + lua_pushfstring(lua, "invalid data(%p) and size(%d)!", data, (tb_int_t)size); return 2; } diff --git a/core/src/xmake/process/open.c b/core/src/xmake/process/open.c index c35d9e3bf..083a01070 100644 --- a/core/src/xmake/process/open.c +++ b/core/src/xmake/process/open.c @@ -178,14 +178,14 @@ tb_int_t xm_process_open(lua_State* lua) else { // error - lua_pushfstring(lua, "envs is too large(%lu > %d) for process.openv", envn, tb_arrayn(envs) - 1); + lua_pushfstring(lua, "envs is too large(%d > %d) for process.openv", (tb_int_t)envn, tb_arrayn(envs) - 1); lua_error(lua); } } else { // error - lua_pushfstring(lua, "invalid envs[%ld] type(%s) for process.openv", i, luaL_typename(lua, -1)); + lua_pushfstring(lua, "invalid envs[%d] type(%s) for process.openv", (tb_int_t)i, luaL_typename(lua, -1)); lua_error(lua); } diff --git a/core/src/xmake/process/openv.c b/core/src/xmake/process/openv.c index 3ec887f1e..46bec2cf5 100644 --- a/core/src/xmake/process/openv.c +++ b/core/src/xmake/process/openv.c @@ -85,7 +85,7 @@ tb_int_t xm_process_openv(lua_State* lua) else { // error - lua_pushfstring(lua, "invalid argv[%ld] type(%s) for process.openv", argi, luaL_typename(lua, -1)); + lua_pushfstring(lua, "invalid argv[%d] type(%s) for process.openv", (tb_int_t)argi, luaL_typename(lua, -1)); lua_error(lua); } @@ -220,14 +220,14 @@ tb_int_t xm_process_openv(lua_State* lua) else { // error - lua_pushfstring(lua, "envs is too large(%lu > %d) for process.openv", envn, tb_arrayn(envs) - 1); + lua_pushfstring(lua, "envs is too large(%d > %d) for process.openv", (tb_int_t)envn, tb_arrayn(envs) - 1); lua_error(lua); } } else { // error - lua_pushfstring(lua, "invalid envs[%ld] type(%s) for process.openv", i, luaL_typename(lua, -1)); + lua_pushfstring(lua, "invalid envs[%d] type(%s) for process.openv", (tb_int_t)i, luaL_typename(lua, -1)); lua_error(lua); } -- cgit v1.3.1 From 697d7cc20e1e2914e72e396cf3158d9893a04e66 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 25 Sep 2021 21:57:16 +0800 Subject: improve error tips for package --- xmake/core/package/package.lua | 16 ++++++++-------- xmake/modules/lib/detect/check_cxsnippets.lua | 8 ++++---- .../private/action/require/impl/actions/download.lua | 17 +++++++++++++---- .../private/action/require/impl/actions/install.lua | 11 ++++++++++- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 8b7e26806..4b3432246 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -1485,7 +1485,7 @@ end -- @param funcs the funcs -- @param opt the argument options, e.g. { includes = ""} -- --- @return true or false +-- @return true or false, errors -- function _instance:has_cfuncs(funcs, opt) opt = opt or {} @@ -1499,7 +1499,7 @@ end -- @param funcs the funcs -- @param opt the argument options, e.g. {includes = ""} -- --- @return true or false +-- @return true or false, errors -- function _instance:has_cxxfuncs(funcs, opt) opt = opt or {} @@ -1513,7 +1513,7 @@ end -- @param types the types -- @param opt the argument options, e.g. { defines = ""} -- --- @return true or false +-- @return true or false, errors -- function _instance:has_ctypes(types, opt) opt = opt or {} @@ -1527,7 +1527,7 @@ end -- @param types the types -- @param opt the argument options, e.g. { defines = ""} -- --- @return true or false +-- @return true or false, errors -- function _instance:has_cxxtypes(types, opt) opt = opt or {} @@ -1541,7 +1541,7 @@ end -- @param includes the includes -- @param opt the argument options, e.g. { defines = ""} -- --- @return true or false +-- @return true or false, errors -- function _instance:has_cincludes(includes, opt) opt = opt or {} @@ -1555,7 +1555,7 @@ end -- @param includes the includes -- @param opt the argument options, e.g. { defines = ""} -- --- @return true or false +-- @return true or false, errors -- function _instance:has_cxxincludes(includes, opt) opt = opt or {} @@ -1569,7 +1569,7 @@ end -- @param snippets the snippets -- @param opt the argument options, e.g. { includes = ""} -- --- @return true or false +-- @return true or false, errors -- function _instance:check_csnippets(snippets, opt) opt = opt or {} @@ -1583,7 +1583,7 @@ end -- @param snippets the snippets -- @param opt the argument options, e.g. { includes = ""} -- --- @return true or false +-- @return true or false, errors -- function _instance:check_cxxsnippets(snippets, opt) opt = opt or {} diff --git a/xmake/modules/lib/detect/check_cxsnippets.lua b/xmake/modules/lib/detect/check_cxsnippets.lua index 5352301b0..ea0e941d3 100644 --- a/xmake/modules/lib/detect/check_cxsnippets.lua +++ b/xmake/modules/lib/detect/check_cxsnippets.lua @@ -143,9 +143,9 @@ end -- @return true or false -- -- @code --- local ok = check_cxsnippets("void test() {}") --- local ok = check_cxsnippets({"void test(){}", "#define TEST 1"}, {types = "wchar_t", includes = "stdio.h"}) --- local ok = check_cxsnippets({snippet_name = "void test(){}", "#define TEST 1"}, {types = "wchar_t", includes = "stdio.h"}) +-- local ok, output_or_errors = check_cxsnippets("void test() {}") +-- local ok, output_or_errors = check_cxsnippets({"void test(){}", "#define TEST 1"}, {types = "wchar_t", includes = "stdio.h"}) +-- local ok, output_or_errors = check_cxsnippets({snippet_name = "void test(){}", "#define TEST 1"}, {types = "wchar_t", includes = "stdio.h"}) -- @endcode -- function main(snippets, opt) @@ -265,6 +265,6 @@ function main(snippets, opt) if errors and option.get("diagnosis") and #tostring(errors) > 0 then cprint("${color.warning}checkinfo:${clear dim} %s", errors) end - return ok, output + return ok, ok and output or errors end diff --git a/xmake/modules/private/action/require/impl/actions/download.lua b/xmake/modules/private/action/require/impl/actions/download.lua index ba918e7f4..63e4c0d80 100644 --- a/xmake/modules/private/action/require/impl/actions/download.lua +++ b/xmake/modules/private/action/require/impl/actions/download.lua @@ -159,7 +159,7 @@ function _download(package, url, sourcedir, url_alias, url_excludes) -- create an empty source directory if do not extract package file os.tryrm(sourcedir) os.mkdir(sourcedir) - raise("cannot extract %s", packagefile) + raise("cannot extract %s, maybe missing extractor or invalid package file!", packagefile) end -- save original file path @@ -230,6 +230,7 @@ function main(package) end -- download url + local allerrors = {} ok = try { function () @@ -248,8 +249,12 @@ function main(package) function (errors) -- show or save the last errors - if errors and (option.get("verbose") or option.get("diagnosis")) then - cprint("${dim color.error}error: ${clear}%s", errors) + if errors then + if (option.get("verbose") or option.get("diagnosis")) then + cprint("${dim color.error}error: ${clear}%s", errors) + else + table.insert(allerrors, errors) + end end -- trace @@ -275,7 +280,11 @@ function main(package) cprint(" ${bright}- %s", table.concat(searchnames:to_array(), ", ")) cprint("and we can run `xmake g --pkg_searchdirs=/xxx` to set the search directories.") end - raise("download failed!") + if #allerrors then + raise(table.concat(allerrors, "\n")) + else + raise("download failed!") + end end end } diff --git a/xmake/modules/private/action/require/impl/actions/install.lua b/xmake/modules/private/action/require/impl/actions/install.lua index 8e8d92d39..9dcbc537b 100644 --- a/xmake/modules/private/action/require/impl/actions/install.lua +++ b/xmake/modules/private/action/require/impl/actions/install.lua @@ -278,7 +278,16 @@ function main(package) -- failed if not package:requireinfo().optional then if os.isfile(errorfile) then - print("if you want to get verbose errors, please see:") + if errors then + print("") + for idx, line in ipairs(errors:split("\n")) do + print(line) + if idx > 16 then + break + end + end + end + cprint("if you want to get more verbose errors, please see:") cprint(" -> ${bright}%s", errorfile) end raise("install failed!") -- cgit v1.3.1 From 55b850aadb0e9bcf2d72aea8697ec3392f966c22 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 25 Sep 2021 22:14:06 +0800 Subject: improve gcc framework --- xmake/modules/core/tools/gcc.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index 8d404f2dc..952f89dff 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -276,7 +276,7 @@ end -- make the frameworkdir flag function nf_frameworkdir(self, frameworkdir) - return {"-F", path.translate(frameworkdir)} + return {"-F" .. path.translate(frameworkdir)} end -- make the c precompiled header flag -- cgit v1.3.1 From 32f89fbfcfb6367f09813750c8c791647e24b63d Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 25 Sep 2021 23:05:51 +0800 Subject: inherit rpathdirs for static target --- xmake/rules/utils/inherit_links/inherit_links.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/utils/inherit_links/inherit_links.lua b/xmake/rules/utils/inherit_links/inherit_links.lua index 97c585ded..d5567b605 100644 --- a/xmake/rules/utils/inherit_links/inherit_links.lua +++ b/xmake/rules/utils/inherit_links/inherit_links.lua @@ -79,7 +79,7 @@ function main(target) -- and we need pass `{public = true}` to add_packages/add_links/... to export it if want to export links for shared target -- if targetkind == "static" then - for _, name in ipairs({"frameworkdirs", "frameworks", "linkdirs", "links", "syslinks"}) do + for _, name in ipairs({"rpathdirs", "frameworkdirs", "frameworks", "linkdirs", "links", "syslinks"}) do local values = _get_values_from_target(target, name) if values and #values > 0 then target:add(name, values, {public = true}) -- cgit v1.3.1 From be70f45c99e92a8f72c52bca943601761e18215d Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 26 Sep 2021 11:24:49 +0800 Subject: improve android ndk support for r23 --- xmake/modules/detect/sdks/find_ndk.lua | 10 +++++++--- xmake/toolchains/ndk/check.lua | 1 + xmake/toolchains/ndk/load.lua | 6 ++++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/xmake/modules/detect/sdks/find_ndk.lua b/xmake/modules/detect/sdks/find_ndk.lua index bc07f6081..4e355e49b 100644 --- a/xmake/modules/detect/sdks/find_ndk.lua +++ b/xmake/modules/detect/sdks/find_ndk.lua @@ -188,8 +188,12 @@ function _find_ndk(sdkdir, arch, ndk_sdkver, ndk_toolchains_ver) local gcc_toolchain_subdir = gcc_toolchain_subdirs[arch] or "arm-linux-androideabi-*" -- find the binary directory - local bindir = find_directory("bin", path.join(sdkdir, "toolchains", "llvm", "prebuilt", "*")) -- larger than ndk r16 - if not bindir then + local llvm_toolchain + local prebuilt = (is_host("macosx") and "darwin" or os.host()) .. "-x86_64" + local bindir = find_directory("bin", path.join(sdkdir, "toolchains", "llvm", "prebuilt", prebuilt)) -- larger than ndk r16 + if bindir then + llvm_toolchain = path.directory(bindir) + else bindir = find_directory("bin", path.join(sdkdir, "toolchains", gcc_toolchain_subdir, "prebuilt", "*")) end if not bindir then @@ -231,6 +235,7 @@ function _find_ndk(sdkdir, arch, ndk_sdkver, ndk_toolchains_ver) bindir = bindir, cross = cross, sdkver = sdkver, + llvm_toolchain = llvm_toolchain, -- >= ndk r22 gcc_toolchain = gcc_toolchain, toolchains_ver = toolchains_ver, sysroot = sysroot} @@ -280,7 +285,6 @@ function main(sdkdir, opt) if opt.verbose or option.get("verbose") then cprint("checking for NDK directory ... ${color.success}%s", ndk.sdkdir) cprint("checking for SDK version of NDK ... ${color.success}%s", ndk.sdkver) - cprint("checking for toolchains version of NDK ... ${color.success}%s", ndk.toolchains_ver) end else diff --git a/xmake/toolchains/ndk/check.lua b/xmake/toolchains/ndk/check.lua index aaf1d609a..991e4e3d9 100644 --- a/xmake/toolchains/ndk/check.lua +++ b/xmake/toolchains/ndk/check.lua @@ -49,6 +49,7 @@ function _check_ndk(toolchain) toolchain:config_set("ndk", ndk.sdkdir) toolchain:config_set("bindir", ndk.bindir) toolchain:config_set("cross", ndk.cross) + toolchain:config_set("llvm_toolchain", ndk.llvm_toolchain) toolchain:config_set("gcc_toolchain", ndk.gcc_toolchain) toolchain:config_set("ndkver", ndk.ndkver) toolchain:config_set("ndk_sdkver", ndk.sdkver) diff --git a/xmake/toolchains/ndk/load.lua b/xmake/toolchains/ndk/load.lua index 29e88d7ad..059f6b417 100644 --- a/xmake/toolchains/ndk/load.lua +++ b/xmake/toolchains/ndk/load.lua @@ -167,8 +167,10 @@ function main(toolchain) local ndk_sysroot = toolchain:config("ndk_sysroot") if ndk_sysroot and os.isdir(ndk_sysroot) then local triple = _get_triple(arch) - toolchain:add("cxflags", "-D__ANDROID_API__=" .. ndk_sdkver) - toolchain:add("asflags", "-D__ANDROID_API__=" .. ndk_sdkver) + if ndkver and tonumber(ndkver) < 22 then + toolchain:add("cxflags", "-D__ANDROID_API__=" .. ndk_sdkver) + toolchain:add("asflags", "-D__ANDROID_API__=" .. ndk_sdkver) + end toolchain:add("cflags", "--sysroot=" .. ndk_sysroot) toolchain:add("cxxflags","--sysroot=" .. ndk_sysroot) toolchain:add("asflags", "--sysroot=" .. ndk_sysroot) -- cgit v1.3.1 From d18679202f372ac5528543827b8409fefd401cfd Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 26 Sep 2021 11:32:26 +0800 Subject: improve to find ndk --- xmake/modules/detect/sdks/find_ndk.lua | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/xmake/modules/detect/sdks/find_ndk.lua b/xmake/modules/detect/sdks/find_ndk.lua index 4e355e49b..ac412bce0 100644 --- a/xmake/modules/detect/sdks/find_ndk.lua +++ b/xmake/modules/detect/sdks/find_ndk.lua @@ -50,10 +50,16 @@ function _find_ndkdir(sdkdir) if not sdkdir then sdkdir = os.getenv("ANDROID_NDK_HOME") or os.getenv("ANDROID_NDK_ROOT") if not sdkdir and config.get("android_sdk") then - sdkdir = path.join(config.get("android_sdk"), "ndk-bundle") + local ndkbundle = path.join(config.get("android_sdk"), "ndk-bundle") + if os.isdir(ndkbundle) then + sdkdir = ndkbundle + end end if not sdkdir and is_host("macosx") then - sdkdir = "~/Library/Android/sdk/ndk-bundle" + sdkdir = find_directory("NDK", "/Applications/AndroidNDK*.app/Contents") + if not sdkdir then + sdkdir = "~/Library/Android/sdk/ndk-bundle" + end end end -- cgit v1.3.1 From 4f3589dcc26944b642fbb92965c254362a5dc162 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 26 Sep 2021 12:13:38 +0800 Subject: improve show list --- xmake/plugins/show/showlist.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/plugins/show/showlist.lua b/xmake/plugins/show/showlist.lua index 66090fc48..923228e42 100644 --- a/xmake/plugins/show/showlist.lua +++ b/xmake/plugins/show/showlist.lua @@ -28,7 +28,7 @@ function main(values) local row = {} for _, value in ipairs(values) do table.insert(row, value) - if #row > 5 then + if #row > 2 then table.insert(tbl, row) row = {} end -- cgit v1.3.1 From 38ad0e37b05036a5bce2731e921b86eac846cb1b Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 26 Sep 2021 12:21:55 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45b74bad2..afe228046 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ * Improve on_load/after_load to support to add target deps dynamically * [#1675](https://github.com/xmake-io/xmake/pull/1675): Rename dynamic and import library suffix for mingw * [#1694](https://github.com/xmake-io/xmake/issues/1694): Support to define a variable without quotes for configuration files +* Support Android NDK r23 ### Bugs fixed @@ -1096,6 +1097,7 @@ * 改进 on_load/after_load 去支持动态的添加 target deps * [#1675](https://github.com/xmake-io/xmake/pull/1675): 针对 mingw 平台,重命名动态库和导入库文件名后缀 * [#1694](https://github.com/xmake-io/xmake/issues/1694): 支持在 set_configvar 中定义一个不带引号的字符串变量 +* 改进对 Android NDK r23 的支持 ### Bugs 修复 -- cgit v1.3.1 From 57222b35a8c1ba36d5487345e4fb16b40d07fd0e Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 26 Sep 2021 22:50:17 +0800 Subject: add c++latest --- CHANGELOG.md | 2 ++ xmake/modules/core/tools/cl.lua | 16 ++++++++++------ xmake/modules/core/tools/gcc.lua | 8 ++++++-- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index afe228046..f93fde1a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ * [#1675](https://github.com/xmake-io/xmake/pull/1675): Rename dynamic and import library suffix for mingw * [#1694](https://github.com/xmake-io/xmake/issues/1694): Support to define a variable without quotes for configuration files * Support Android NDK r23 +* Add `c++latest` and `clatest` for `set_languages` ### Bugs fixed @@ -1098,6 +1099,7 @@ * [#1675](https://github.com/xmake-io/xmake/pull/1675): 针对 mingw 平台,重命名动态库和导入库文件名后缀 * [#1694](https://github.com/xmake-io/xmake/issues/1694): 支持在 set_configvar 中定义一个不带引号的字符串变量 * 改进对 Android NDK r23 的支持 +* 为 `set_languages` 新增 `c++latest` 和 `clatest` 配置值 ### Bugs 修复 diff --git a/xmake/modules/core/tools/cl.lua b/xmake/modules/core/tools/cl.lua index d95d58e5d..0cad0abd6 100644 --- a/xmake/modules/core/tools/cl.lua +++ b/xmake/modules/core/tools/cl.lua @@ -197,12 +197,14 @@ function nf_language(self, stdname) _g.cmaps = { -- stdc - c99 = "-TP" -- compile as c++ files because older msvc only support c89 - , gnu99 = "-TP" - , c11 = {"-std:c11", "-TP"} - , gnu11 = {"-std:c11", "-TP"} - , c17 = {"-std:c17", "-TP"} - , gnu17 = {"-std:c17", "-TP"} + c99 = "-TP" -- compile as c++ files because older msvc only support c89 + , gnu99 = "-TP" + , c11 = {"-std:c11", "-TP"} + , gnu11 = {"-std:c11", "-TP"} + , c17 = {"-std:c17", "-TP"} + , gnu17 = {"-std:c17", "-TP"} + , clatest = "-std:c17" + , gnulatest = "-std:c17" } end @@ -222,6 +224,8 @@ function nf_language(self, stdname) , gnuxx20 = {"-std:c++20", "-std:c++latest"} , cxx2a = {"-std:c++20", "-std:c++latest"} , gnuxx2a = {"-std:c++20", "-std:c++latest"} + , cxxlatest = "-std:c++latest" + , gnuxxlatest = "-std:c++latest" } local cxxmaps2 = {} for k, v in pairs(_g.cxxmaps) do diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index 952f89dff..bb0bef168 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -180,6 +180,8 @@ function nf_language(self, stdname) , gnu11 = "-std=gnu11" , c17 = "-std=c17" , gnu17 = "-std=gnu17" + , clatest = "-std=c17" + , gnulatest = "-std=gnu17" } end @@ -197,10 +199,12 @@ function nf_language(self, stdname) , gnuxx17 = "-std=gnu++17" , cxx1z = "-std=c++1z" , gnuxx1z = "-std=gnu++1z" - , cxx20 = "-std=c++2a" - , gnuxx20 = "-std=gnu++2a" + , cxx20 = "-std=c++20" + , gnuxx20 = "-std=gnu++20" , cxx2a = "-std=c++2a" , gnuxx2a = "-std=gnu++2a" + , cxxlatest = "-std=c++2a" + , gnuxxlatest = "-std=gnu++2a" } local cxxmaps2 = {} for k, v in pairs(_g.cxxmaps) do -- cgit v1.3.1 From d00138d98064b84db0c76dde99587b5ea425fdf4 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 26 Sep 2021 23:12:02 +0800 Subject: improve languages --- xmake/modules/core/tools/clang_cl.lua | 10 ++++++++-- xmake/modules/core/tools/nvcc.lua | 1 + xmake/modules/core/tools/sdcc.lua | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/xmake/modules/core/tools/clang_cl.lua b/xmake/modules/core/tools/clang_cl.lua index 4e0046fe8..9c4236343 100644 --- a/xmake/modules/core/tools/clang_cl.lua +++ b/xmake/modules/core/tools/clang_cl.lua @@ -117,6 +117,10 @@ function nf_language(self, stdname) , gnu99 = "-Xclang -std=gnu99" , c11 = "-Xclang -std=c11" , gnu11 = "-Xclang -std=gnu11" + , c17 = "-Xclang -std=c17" + , gnu17 = "-Xclang -std=gnu17" + , clatest = "-Xclang -std=c17" + , gnulatest = "-Xclang -std=gnu17" } end @@ -134,10 +138,12 @@ function nf_language(self, stdname) , gnuxx17 = "-Xclang -std=gnu++17" , cxx1z = "-Xclang -std=c++1z" , gnuxx1z = "-Xclang -std=gnu++1z" - , cxx20 = "-Xclang -std=c++2a" - , gnuxx20 = "-Xclang -std=gnu++2a" + , cxx20 = "-Xclang -std=c++20" + , gnuxx20 = "-Xclang -std=gnu++20" , cxx2a = "-Xclang -std=c++2a" , gnuxx2a = "-Xclang -std=gnu++2a" + , cxxlatest = "-Xclang -std=c++latest" + , gnuxxlatest = "-Xclang -std=gnu++latest" } local cxxmaps2 = {} for k, v in pairs(_g.cxxmaps) do diff --git a/xmake/modules/core/tools/nvcc.lua b/xmake/modules/core/tools/nvcc.lua index 41093c502..b5e41367f 100644 --- a/xmake/modules/core/tools/nvcc.lua +++ b/xmake/modules/core/tools/nvcc.lua @@ -179,6 +179,7 @@ function nf_language(self, stdname) , cxx11 = "--std c++11" , cxx14 = "--std c++14" , cxx17 = "--std c++17" + , cxxlatest = "--std c++17" } local cxxmaps2 = {} for k, v in pairs(_g.cxxmaps) do diff --git a/xmake/modules/core/tools/sdcc.lua b/xmake/modules/core/tools/sdcc.lua index 00e081384..d2aece2e1 100644 --- a/xmake/modules/core/tools/sdcc.lua +++ b/xmake/modules/core/tools/sdcc.lua @@ -116,6 +116,8 @@ function nf_language(self, stdname) , gnu11 = "--std-sdcc11" , c20 = "--std-c2x" , gnu20 = "--std-sdcc2x" + , clatest = "--std-c2x" + , gnulatest = "--std-sdcc2x" } end return _g.cmaps[stdname] -- cgit v1.3.1 From 9128fe7d5b84a27831ae2535a16547bb0b9b7d8e Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 27 Sep 2021 22:35:24 +0800 Subject: add lua_c swig test --- tests/projects/swig/lua_c/src/example.c | 25 +++++++++++++++++++++++++ tests/projects/swig/lua_c/src/example.i | 6 ++++++ tests/projects/swig/lua_c/xmake.lua | 8 ++++++++ tests/projects/swig/python_c/src/example.c | 10 +++++----- tests/projects/swig/python_cpp/src/example.cpp | 10 +++++----- 5 files changed, 49 insertions(+), 10 deletions(-) create mode 100644 tests/projects/swig/lua_c/src/example.c create mode 100644 tests/projects/swig/lua_c/src/example.i create mode 100644 tests/projects/swig/lua_c/xmake.lua diff --git a/tests/projects/swig/lua_c/src/example.c b/tests/projects/swig/lua_c/src/example.c new file mode 100644 index 000000000..c4afe9779 --- /dev/null +++ b/tests/projects/swig/lua_c/src/example.c @@ -0,0 +1,25 @@ +#include +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" + +extern int luaopen_example(lua_State* L); // declare the wrapped module + +int main(int argc,char* argv[]) +{ + lua_State *L; + if (argc<2) + { + printf("%s: \n",argv[0]); + return 0; + } + L=lua_open(); + luaopen_base(L); // load basic libs (eg. print) + luaopen_example(L); // load the wrappered module + if (luaL_loadfile(L,argv[1])==0) // load and run the file + lua_pcall(L,0,0,0); + else + printf("unable to load %s\n",argv[1]); + lua_close(L); + return 0; +} diff --git a/tests/projects/swig/lua_c/src/example.i b/tests/projects/swig/lua_c/src/example.i new file mode 100644 index 000000000..f17b34a82 --- /dev/null +++ b/tests/projects/swig/lua_c/src/example.i @@ -0,0 +1,6 @@ +%module example +%{ +#include "example.h" +%} +int gcd(int x, int y); +extern double Foo; diff --git a/tests/projects/swig/lua_c/xmake.lua b/tests/projects/swig/lua_c/xmake.lua new file mode 100644 index 000000000..fc6e3dd7b --- /dev/null +++ b/tests/projects/swig/lua_c/xmake.lua @@ -0,0 +1,8 @@ +add_rules("mode.release", "mode.debug") +add_requires("lua") + +target("example") + add_rules("swig.c") + add_files("src/example.i", {moduletype = "lua", scriptdir = "share"}) + add_files("src/example.c") + add_packages("lua") diff --git a/tests/projects/swig/python_c/src/example.c b/tests/projects/swig/python_c/src/example.c index 31c659bfa..b0ddc9c26 100644 --- a/tests/projects/swig/python_c/src/example.c +++ b/tests/projects/swig/python_c/src/example.c @@ -2,13 +2,13 @@ double My_variable = 3.0; /* Compute factorial of n */ int fact(int n) { - if (n <= 1) - return 1; - else - return n*fact(n-1); + if (n <= 1) + return 1; + else + return n*fact(n-1); } /* Compute n mod m */ int my_mod(int n, int m) { - return(n % m); + return(n % m); } diff --git a/tests/projects/swig/python_cpp/src/example.cpp b/tests/projects/swig/python_cpp/src/example.cpp index 31c659bfa..b0ddc9c26 100644 --- a/tests/projects/swig/python_cpp/src/example.cpp +++ b/tests/projects/swig/python_cpp/src/example.cpp @@ -2,13 +2,13 @@ double My_variable = 3.0; /* Compute factorial of n */ int fact(int n) { - if (n <= 1) - return 1; - else - return n*fact(n-1); + if (n <= 1) + return 1; + else + return n*fact(n-1); } /* Compute n mod m */ int my_mod(int n, int m) { - return(n % m); + return(n % m); } -- cgit v1.3.1 From c223db1bdd7e90d970b378e6d6755e977ceb4c6d Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 27 Sep 2021 22:40:17 +0800 Subject: improve swig --- tests/projects/swig/lua_c/src/example.c | 27 +++------------------------ tests/projects/swig/lua_c/src/example.i | 6 +----- tests/projects/swig/lua_c/xmake.lua | 4 ++-- tests/projects/swig/python_c/xmake.lua | 4 ++-- tests/projects/swig/python_cpp/xmake.lua | 4 ++-- xmake/rules/swig/build_module_file.lua | 11 ++--------- xmake/rules/swig/xmake.lua | 23 +++++++++++++++++------ 7 files changed, 29 insertions(+), 50 deletions(-) diff --git a/tests/projects/swig/lua_c/src/example.c b/tests/projects/swig/lua_c/src/example.c index c4afe9779..06f76c542 100644 --- a/tests/projects/swig/lua_c/src/example.c +++ b/tests/projects/swig/lua_c/src/example.c @@ -1,25 +1,4 @@ -#include -#include "lua.h" -#include "lualib.h" -#include "lauxlib.h" - -extern int luaopen_example(lua_State* L); // declare the wrapped module - -int main(int argc,char* argv[]) -{ - lua_State *L; - if (argc<2) - { - printf("%s: \n",argv[0]); - return 0; - } - L=lua_open(); - luaopen_base(L); // load basic libs (eg. print) - luaopen_example(L); // load the wrappered module - if (luaL_loadfile(L,argv[1])==0) // load and run the file - lua_pcall(L,0,0,0); - else - printf("unable to load %s\n",argv[1]); - lua_close(L); - return 0; +int fact(int n) { + return n; } + diff --git a/tests/projects/swig/lua_c/src/example.i b/tests/projects/swig/lua_c/src/example.i index f17b34a82..5724920da 100644 --- a/tests/projects/swig/lua_c/src/example.i +++ b/tests/projects/swig/lua_c/src/example.i @@ -1,6 +1,2 @@ %module example -%{ -#include "example.h" -%} -int gcd(int x, int y); -extern double Foo; +int fact(int n); diff --git a/tests/projects/swig/lua_c/xmake.lua b/tests/projects/swig/lua_c/xmake.lua index fc6e3dd7b..4ee0226ee 100644 --- a/tests/projects/swig/lua_c/xmake.lua +++ b/tests/projects/swig/lua_c/xmake.lua @@ -2,7 +2,7 @@ add_rules("mode.release", "mode.debug") add_requires("lua") target("example") - add_rules("swig.c") - add_files("src/example.i", {moduletype = "lua", scriptdir = "share"}) + add_rules("swig.c", {moduletype = "lua"}) + add_files("src/example.i") add_files("src/example.c") add_packages("lua") diff --git a/tests/projects/swig/python_c/xmake.lua b/tests/projects/swig/python_c/xmake.lua index 89b13cbd4..7cc23e42b 100644 --- a/tests/projects/swig/python_c/xmake.lua +++ b/tests/projects/swig/python_c/xmake.lua @@ -2,7 +2,7 @@ add_rules("mode.release", "mode.debug") add_requires("python 3.x") target("example") - add_rules("swig.c") - add_files("src/example.i", {moduletype = "python", scriptdir = "share"}) + add_rules("swig.c", {moduletype = "python"}) + add_files("src/example.i", {scriptdir = "share"}) add_files("src/example.c") add_packages("python") diff --git a/tests/projects/swig/python_cpp/xmake.lua b/tests/projects/swig/python_cpp/xmake.lua index f0c322310..1aa612211 100644 --- a/tests/projects/swig/python_cpp/xmake.lua +++ b/tests/projects/swig/python_cpp/xmake.lua @@ -2,7 +2,7 @@ add_rules("mode.release", "mode.debug") add_requires("python 3.x") target("example") - add_rules("swig.cpp") - add_files("src/example.i", {moduletype = "python", scriptdir = "share"}) + add_rules("swig.cpp", {moduletype = "python"}) + add_files("src/example.i", {scriptdir = "share"}) add_files("src/example.cpp") add_packages("python") diff --git a/xmake/rules/swig/build_module_file.lua b/xmake/rules/swig/build_module_file.lua index edcd6b04b..a38fb009e 100644 --- a/xmake/rules/swig/build_module_file.lua +++ b/xmake/rules/swig/build_module_file.lua @@ -23,16 +23,8 @@ import("lib.detect.find_tool") function main(target, batchcmds, sourcefile, opt) - -- get module type - opt = opt or {} - local moduletype - local fileconfig = target:fileconfig(sourcefile) - if fileconfig then - moduletype = fileconfig.moduletype - end - assert(moduletype, "%s: unknown swig module type, please use `add_files(\"foo.c\", {moduletype = \"python\"})` to set it!", sourcefile) - -- get swig + opt = opt or {} local swig = assert(find_tool("swig"), "swig not found!") local sourcefile_cx = path.join(target:autogendir(), "rules", "swig", path.basename(sourcefile) .. (opt.sourcekind == "cxx" and ".cpp" or ".c")) @@ -41,6 +33,7 @@ function main(target, batchcmds, sourcefile, opt) table.insert(target:objectfiles(), objectfile) -- add commands + local moduletype = assert(target:data("swig.moduletype"), "swig.moduletype not found!") local argv = {"-" .. moduletype, "-o", sourcefile_cx} if opt.sourcekind == "cxx" then table.insert(argv, "-c++") diff --git a/xmake/rules/swig/xmake.lua b/xmake/rules/swig/xmake.lua index 28f8e0563..738cc12fd 100644 --- a/xmake/rules/swig/xmake.lua +++ b/xmake/rules/swig/xmake.lua @@ -27,24 +27,34 @@ rule("swig.base") on_load(function (target) target:set("kind", "shared") - target:set("prefixname", "_") - if target:is_plat("windows") then - target:set("extension", ".pyd") + local moduletype = target:extraconf("rules", "swig.c", "moduletype") or target:extraconf("rules", "swig.cpp", "moduletype") + if moduletype == "python" then + target:set("prefixname", "_") + if target:is_plat("windows") then + target:set("extension", ".pyd") + end + elseif moduletype == "lua" then + target:set("prefixname", "") + if not target:is_plat("windows") then + target:set("extension", ".so") + end + else + raise("unknown swig module type, please use `add_rules(\"swig.c\", {moduletype = \"python\"})` to set it!") end local scriptfiles = {} for _, sourcebatch in pairs(target:sourcebatches()) do if sourcebatch.rulename:startswith("swig.") then for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local scriptdir - local moduletype local fileconfig = target:fileconfig(sourcefile) if fileconfig then - moduletype = fileconfig.moduletype scriptdir = fileconfig.scriptdir end local scriptfile = path.join(target:autogendir(), "rules", "swig", path.basename(sourcefile)) if moduletype == "python" then scriptfile = scriptfile .. ".py" + elseif moduletype == "lua" then + scriptfile = scriptfile .. ".lua" end table.insert(scriptfiles, scriptfile) if scriptdir then @@ -54,7 +64,8 @@ rule("swig.base") end end -- for custom on_install/after_install, user can use it to install them - target:set("data", "swig.scriptfiles", scriptfiles) + target:data_set("swig.scriptfiles", scriptfiles) + target:data_set("swig.moduletype", moduletype) end) rule("swig.c") -- cgit v1.3.1 From 383c52d93446a72497b132ff6f38d2ef96817eeb Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 27 Sep 2021 22:40:47 +0800 Subject: add swigflags --- tests/projects/swig/lua_c/xmake.lua | 2 +- xmake/rules/swig/build_module_file.lua | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/projects/swig/lua_c/xmake.lua b/tests/projects/swig/lua_c/xmake.lua index 4ee0226ee..06dfac12b 100644 --- a/tests/projects/swig/lua_c/xmake.lua +++ b/tests/projects/swig/lua_c/xmake.lua @@ -3,6 +3,6 @@ add_requires("lua") target("example") add_rules("swig.c", {moduletype = "lua"}) - add_files("src/example.i") + add_files("src/example.i", {swigflags = "-no-old-metatable-bindings"}) add_files("src/example.c") add_packages("lua") diff --git a/xmake/rules/swig/build_module_file.lua b/xmake/rules/swig/build_module_file.lua index a38fb009e..42c9d9238 100644 --- a/xmake/rules/swig/build_module_file.lua +++ b/xmake/rules/swig/build_module_file.lua @@ -38,6 +38,10 @@ function main(target, batchcmds, sourcefile, opt) if opt.sourcekind == "cxx" then table.insert(argv, "-c++") end + local fileconfig = target:fileconfig(sourcefile) + if fileconfig.swigflags then + table.join2(argv, fileconfig.swigflags) + end table.insert(argv, sourcefile) batchcmds:show_progress(opt.progress, "${color.build.object}compiling.swig.%s %s", moduletype, sourcefile) batchcmds:mkdir(path.directory(sourcefile_cx)) -- cgit v1.3.1 From 130d0f14a97915934eb2e82fda05b25ca7f7284f Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 27 Sep 2021 22:45:17 +0800 Subject: update readme --- README.md | 9 +++++++-- README_zh.md | 17 +++++++++++------ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 009758828..3d5b1334c 100644 --- a/README.md +++ b/README.md @@ -242,7 +242,7 @@ fpc Free Pascal Programming Language Compiler * Vala * Pascal -## Support Features +## Supported Features * Simple project configuration syntax * Direct build support, without relying on any third-party back-end make tools @@ -273,8 +273,13 @@ fpc Free Pascal Programming Language Compiler * WDK Driver (umdf/kmdf/wdm) * WinSDK Application * MFC Application -* iOS/MacOS Application +* iOS/MacOS Application (Support .metal) * Framework and Bundle Program (iOS/MacOS) +* SWIG Modules (Lua, python, ...) +* Luarocks Modules +* Protobuf Program +* Lex/yacc program +* C++20 Modules ## More Examples diff --git a/README_zh.md b/README_zh.md index 14ef4938d..fb0f9d19e 100644 --- a/README_zh.md +++ b/README_zh.md @@ -274,13 +274,18 @@ fpc Free Pascal Programming Language Compiler * 静态库程序 * 动态库类型 * 控制台程序 -* Cuda程序 -* Qt应用程序 -* WDK驱动程序 -* WinSDK应用程序 -* MFC应用程序 -* iOS/MacOS应用程序 +* Cuda 程序 +* Qt 应用程序 +* WDK 驱动程序 +* WinSDK 应用程序 +* MFC 应用程序 +* iOS/MacOS 应用程序(支持.metal) * Framework和Bundle程序(iOS/MacOS) +* SWIG 模块 (Lua, python, ...) +* Luarocks 模块 +* Protobuf 程序 +* Lex/yacc 程序 +* C++20 模块 ## 更多例子 -- cgit v1.3.1 From 19b2916a1e97e5c5fb2965cab9b6b4aecd1e03b4 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 27 Sep 2021 23:15:13 +0800 Subject: improve languages --- xmake/modules/core/tools/cl.lua | 17 ++++++++++------- xmake/modules/core/tools/gcc.lua | 22 +++++++++++++++------- xmake/modules/core/tools/nvcc.lua | 15 +++++++++++++-- xmake/modules/core/tools/sdcc.lua | 18 ++++++++++++++---- 4 files changed, 52 insertions(+), 20 deletions(-) diff --git a/xmake/modules/core/tools/cl.lua b/xmake/modules/core/tools/cl.lua index 0cad0abd6..54eafe227 100644 --- a/xmake/modules/core/tools/cl.lua +++ b/xmake/modules/core/tools/cl.lua @@ -203,8 +203,8 @@ function nf_language(self, stdname) , gnu11 = {"-std:c11", "-TP"} , c17 = {"-std:c17", "-TP"} , gnu17 = {"-std:c17", "-TP"} - , clatest = "-std:c17" - , gnulatest = "-std:c17" + , clatest = {"-std:c17", "-std:c11"} + , gnulatest = {"-std:c17", "-std:c11"} } end @@ -241,14 +241,17 @@ function nf_language(self, stdname) end -- map it - local flags = maps[stdname] - if flags then - for _, flag in ipairs(table.wrap(flags)) do - if self:has_flags(flag, "cxflags") then - return flag + local result = maps[stdname] + if type(result) == "table" then + for _, v in ipairs(result) do + if self:has_flags(v, "cxflags") then + result = v + maps[stdname] = result + break end end end + return result end -- make the define flag diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index bb0bef168..c6422d204 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -180,8 +180,8 @@ function nf_language(self, stdname) , gnu11 = "-std=gnu11" , c17 = "-std=c17" , gnu17 = "-std=gnu17" - , clatest = "-std=c17" - , gnulatest = "-std=gnu17" + , clatest = {"-std=c17", "-std=c11", "-std=c99", "-std=c89", "-ansi"} + , gnulatest = {"-std=gnu17", "-std=gnu11", "-std=gnu99", "-std=gnu89", "-ansi"} } end @@ -203,8 +203,8 @@ function nf_language(self, stdname) , gnuxx20 = "-std=gnu++20" , cxx2a = "-std=c++2a" , gnuxx2a = "-std=gnu++2a" - , cxxlatest = "-std=c++2a" - , gnuxxlatest = "-std=gnu++2a" + , cxxlatest = {"-std=c++20", "-std=c++2a", "-std=c++17", "-std=c++14", "-std=c++11", "-std=c++1z", "-std=c++98"} + , gnuxxlatest = {"-std=gnu++20", "-std=gnu++2a", "-std=gnu++17", "-std=gnu++14", "-std=gnu++11", "-std=c++1z", "-std=gnu++98"} } local cxxmaps2 = {} for k, v in pairs(_g.cxxmaps) do @@ -220,9 +220,17 @@ function nf_language(self, stdname) elseif self:kind() == "sc" then maps = {} end - - -- make it - return maps[stdname] + local result = maps[stdname] + if type(result) == "table" then + for _, v in ipairs(result) do + if self:has_flags(v, "cxflags") then + result = v + maps[stdname] = result + break + end + end + end + return result end -- make the define flag diff --git a/xmake/modules/core/tools/nvcc.lua b/xmake/modules/core/tools/nvcc.lua index b5e41367f..c28d8e271 100644 --- a/xmake/modules/core/tools/nvcc.lua +++ b/xmake/modules/core/tools/nvcc.lua @@ -179,7 +179,7 @@ function nf_language(self, stdname) , cxx11 = "--std c++11" , cxx14 = "--std c++14" , cxx17 = "--std c++17" - , cxxlatest = "--std c++17" + , cxxlatest = {"--std c++17", "--std c++14", "--std c++11", "--std c++03"} } local cxxmaps2 = {} for k, v in pairs(_g.cxxmaps) do @@ -187,7 +187,18 @@ function nf_language(self, stdname) end table.join2(_g.cxxmaps, cxxmaps2) end - return _g.cxxmaps[stdname] + local maps = _g.cxxmaps + local result = maps[stdname] + if type(result) == "table" then + for _, v in ipairs(result) do + if self:has_flags(v, "cxflags") then + result = v + maps[stdname] = result + break + end + end + end + return result end -- make the define flag diff --git a/xmake/modules/core/tools/sdcc.lua b/xmake/modules/core/tools/sdcc.lua index d2aece2e1..526254fe7 100644 --- a/xmake/modules/core/tools/sdcc.lua +++ b/xmake/modules/core/tools/sdcc.lua @@ -106,7 +106,6 @@ function nf_language(self, stdname) if _g.cmaps == nil then _g.cmaps = { - -- stdc ansi = "--std-c89" , c89 = "--std-c89" , gnu89 = "--std-sdcc89" @@ -116,11 +115,22 @@ function nf_language(self, stdname) , gnu11 = "--std-sdcc11" , c20 = "--std-c2x" , gnu20 = "--std-sdcc2x" - , clatest = "--std-c2x" - , gnulatest = "--std-sdcc2x" + , clatest = {"--std-c2x", "--std-c11", "--std-c99", "--std-c89"} + , gnulatest = {"--std-sdcc2x", "--std-sdcc11", "--std-sdcc99", "--std-sdcc89"} } end - return _g.cmaps[stdname] + local maps = _g.cmaps + local result = maps[stdname] + if type(result) == "table" then + for _, v in ipairs(result) do + if self:has_flags(v, "cxflags") then + result = v + maps[stdname] = result + break + end + end + end + return result end -- make the define flag -- cgit v1.3.1 From c828253601411a49e036ec4847155991b5e095e2 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 27 Sep 2021 23:56:27 +0800 Subject: fix lua swig test --- tests/projects/swig/lua_c/src/example.i | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/projects/swig/lua_c/src/example.i b/tests/projects/swig/lua_c/src/example.i index 5724920da..e952f6123 100644 --- a/tests/projects/swig/lua_c/src/example.i +++ b/tests/projects/swig/lua_c/src/example.i @@ -1,2 +1,5 @@ %module example -int fact(int n); +%{ +extern int fact(int n); +%} +extern int fact(int n); -- cgit v1.3.1 From 7828621e2165455f90a0b4eecadddec0b7e6cdb0 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 28 Sep 2021 00:44:58 +0800 Subject: improve target:sourcekinds --- xmake/core/project/target.lua | 9 +++++++++ xmake/rules/swig/xmake.lua | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 3e2d308f9..52126b78c 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -1605,6 +1605,15 @@ function _instance:sourcekinds() table.insert(sourcekinds, sourcekind) end end + -- if the source file is added dynamically, we may not be able to get the sourcekinds, + -- so we can only continue to get it from the rule + -- https://github.com/xmake-io/xmake/issues/1622#issuecomment-927726697 + for _, ruleinst in ipairs(self:orderules()) do + local rule_sourcekinds = ruleinst:get("sourcekinds") + if rule_sourcekinds then + table.insert(sourcekinds, rule_sourcekinds) + end + end sourcekinds = table.unique(sourcekinds) self._SOURCEKINDS = sourcekinds end diff --git a/xmake/rules/swig/xmake.lua b/xmake/rules/swig/xmake.lua index 738cc12fd..29b2673a2 100644 --- a/xmake/rules/swig/xmake.lua +++ b/xmake/rules/swig/xmake.lua @@ -70,14 +70,14 @@ rule("swig.base") rule("swig.c") set_extensions(".i") - add_deps("swig.base") + add_deps("swig.base", "c.build") on_buildcmd_file(function (target, batchcmds, sourcefile, opt) import("build_module_file")(target, batchcmds, sourcefile, table.join({sourcekind = "cc"}, opt)) end) rule("swig.cpp") set_extensions(".i") - add_deps("swig.base") + add_deps("swig.base", "c++.build") on_buildcmd_file(function (target, batchcmds, sourcefile, opt) import("build_module_file")(target, batchcmds, sourcefile, table.join({sourcekind = "cxx"}, opt)) end) -- cgit v1.3.1 From af03b0768205a1f9c7430f6e2a20e85811a13c4a Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 28 Sep 2021 00:46:15 +0800 Subject: improve debug flags for nvcc --- xmake/modules/core/tools/nvcc.lua | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/xmake/modules/core/tools/nvcc.lua b/xmake/modules/core/tools/nvcc.lua index c28d8e271..d03a10865 100644 --- a/xmake/modules/core/tools/nvcc.lua +++ b/xmake/modules/core/tools/nvcc.lua @@ -59,7 +59,7 @@ function nf_symbol(self, level, target) -- debug? generate *.pdb file local flags = nil if level == "debug" then - flags = "-g -lineinfo" + flags = {"-g", "-lineinfo"} if is_plat("windows") then local host_flags = nil local symbolfile = nil @@ -82,11 +82,10 @@ function nf_symbol(self, level, target) else host_flags = "-Zi" end - flags = flags .. ' -Xcompiler "' .. host_flags .. '"' + table.insert(flags, "-Xcompiler") + table.insert(flags, host_flags) end end - - -- none return flags end -- cgit v1.3.1 From 64b17a551574c998fd9fce3f902bf6718ae11954 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 28 Sep 2021 00:53:32 +0800 Subject: improve cmakelists generator --- xmake/plugins/project/cmake/cmakelists.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 02abd56d7..44ad8d3c2 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -73,6 +73,9 @@ function _add_project(cmakelists) ]], project.name() or "") cmakelists:print("# project") cmakelists:print("cmake_minimum_required(VERSION %s)", _get_cmake_minver()) + -- see https://github.com/xmake-io/xmake/issues/1661#issuecomment-927951660 + cmakelists:print("cmake_policy(SET CMP0091 NEW)") + cmakelists:print('set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded")') local project_name = project.name() if not project_name then for _, target in pairs(project.targets()) do -- cgit v1.3.1 From 9adbd3eaa529a66ef9f070d39f6896d45221f9b6 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 28 Sep 2021 00:56:13 +0800 Subject: improve cmakelists --- xmake/plugins/project/cmake/cmakelists.lua | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 44ad8d3c2..0c51d7817 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -67,15 +67,18 @@ end -- add project info function _add_project(cmakelists) + local cmake_version = _get_cmake_minver() cmakelists:print([[# this is the build file for project %s # it is autogenerated by the xmake build system. # do not edit by hand. ]], project.name() or "") cmakelists:print("# project") - cmakelists:print("cmake_minimum_required(VERSION %s)", _get_cmake_minver()) + cmakelists:print("cmake_minimum_required(VERSION %s)", cmake_version) -- see https://github.com/xmake-io/xmake/issues/1661#issuecomment-927951660 - cmakelists:print("cmake_policy(SET CMP0091 NEW)") - cmakelists:print('set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded")') + if cmake_version:ge("3.15") then + cmakelists:print("cmake_policy(SET CMP0091 NEW)") + cmakelists:print('set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded")') + end local project_name = project.name() if not project_name then for _, target in pairs(project.targets()) do -- cgit v1.3.1 From f27971ea0d01415aa9cc7e4c69114149bccc15c1 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Sep 2021 00:44:27 +0800 Subject: improve vs runtime for cmake generator --- xmake/plugins/project/cmake/cmakelists.lua | 34 +++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 0c51d7817..2d26a7888 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -74,10 +74,9 @@ function _add_project(cmakelists) ]], project.name() or "") cmakelists:print("# project") cmakelists:print("cmake_minimum_required(VERSION %s)", cmake_version) - -- see https://github.com/xmake-io/xmake/issues/1661#issuecomment-927951660 - if cmake_version:ge("3.15") then + if cmake_version:ge("3.15.0") then + -- for MSVC_RUNTIME_LIBRARY cmakelists:print("cmake_policy(SET CMP0091 NEW)") - cmakelists:print('set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded")') end local project_name = project.name() if not project_name then @@ -373,6 +372,32 @@ function _add_target_optimization(cmakelists, target) end end +-- add target vs runtime +-- +-- https://github.com/xmake-io/xmake/issues/1661#issuecomment-927979489 +-- https://cmake.org/cmake/help/latest/prop_tgt/MSVC_RUNTIME_LIBRARY.html +-- +function _add_target_vs_runtime(cmakelists, target) + local cmake_minver = _get_cmake_minver() + if true then--cmake_minver:ge("3.15.0") then + local vs_runtime = target:get("runtimes") + if vs_runtime then + cmakelists:print("if(MSVC)") + if vs_runtime == "MT" then + vs_runtime = "MultiThreaded" + elseif vs_runtime == "MTd" then + vs_runtime = "MultiThreadedDebug" + elseif vs_runtime == "MD" then + vs_runtime = "MultiThreadedDLL" + elseif vs_runtime == "MDd" then + vs_runtime = "MultiThreadedDebugDLL" + end + cmakelists:print(' set_property(TARGET %s PROPERTY MSVC_RUNTIME_LIBRARY "%s")', target:name(), vs_runtime) + cmakelists:print("endif()") + end + end +end + -- add target link libraries function _add_target_link_libraries(cmakelists, target) @@ -509,6 +534,9 @@ function _add_target(cmakelists, target) -- add target optimization _add_target_optimization(cmakelists, target) + -- add vs runtime for msvc + _add_target_vs_runtime(cmakelists, target) + -- add target link libraries _add_target_link_libraries(cmakelists, target) -- cgit v1.3.1 From 1123617bd848a2328493f39b53b97e3ce707e7b3 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Sep 2021 00:44:34 +0800 Subject: fix minver --- xmake/plugins/project/cmake/cmakelists.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 2d26a7888..7d8765055 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -379,7 +379,7 @@ end -- function _add_target_vs_runtime(cmakelists, target) local cmake_minver = _get_cmake_minver() - if true then--cmake_minver:ge("3.15.0") then + if cmake_minver:ge("3.15.0") then local vs_runtime = target:get("runtimes") if vs_runtime then cmakelists:print("if(MSVC)") -- cgit v1.3.1 From 169141eaa2158281f80aca5c30e17c9d1ace52d7 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Sep 2021 00:45:56 +0800 Subject: improve vs runtime for cmake generator again --- xmake/plugins/project/cmake/cmakelists.lua | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 7d8765055..ba1689cb1 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -383,16 +383,13 @@ function _add_target_vs_runtime(cmakelists, target) local vs_runtime = target:get("runtimes") if vs_runtime then cmakelists:print("if(MSVC)") - if vs_runtime == "MT" then - vs_runtime = "MultiThreaded" - elseif vs_runtime == "MTd" then - vs_runtime = "MultiThreadedDebug" - elseif vs_runtime == "MD" then - vs_runtime = "MultiThreadedDLL" - elseif vs_runtime == "MDd" then - vs_runtime = "MultiThreadedDebugDLL" + if vs_runtime:startswith("MT") then + vs_runtime = "MultiThreaded$<$:Debug>" + elseif vs_runtime:startswith("MD") then + vs_runtime = "MultiThreaded$<$:Debug>DLL" end - cmakelists:print(' set_property(TARGET %s PROPERTY MSVC_RUNTIME_LIBRARY "%s")', target:name(), vs_runtime) + cmakelists:print(' set_property(TARGET %s PROPERTY', target:name()) + cmakelists:print(' MSVC_RUNTIME_LIBRARY "%s")', vs_runtime) cmakelists:print("endif()") end end -- cgit v1.3.1 From 88eda991bfd54b709cda4eb72be1665ad6ce85ef Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Sep 2021 00:51:53 +0800 Subject: add with cmakelists --- .../projects/c/library_with_cmakelists/.gitignore | 8 +++++++ .../c/library_with_cmakelists/foo/CMakeLists.txt | 8 +++++++ .../c/library_with_cmakelists/foo/src/interface.c | 6 ++++++ .../c/library_with_cmakelists/foo/src/interface.h | 8 +++++++ .../projects/c/library_with_cmakelists/src/main.c | 8 +++++++ tests/projects/c/library_with_cmakelists/xmake.lua | 25 ++++++++++++++++++++++ xmake/core/package/package.lua | 6 ++++++ .../action/require/impl/actions/install.lua | 5 ++++- 8 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 tests/projects/c/library_with_cmakelists/.gitignore create mode 100644 tests/projects/c/library_with_cmakelists/foo/CMakeLists.txt create mode 100644 tests/projects/c/library_with_cmakelists/foo/src/interface.c create mode 100644 tests/projects/c/library_with_cmakelists/foo/src/interface.h create mode 100644 tests/projects/c/library_with_cmakelists/src/main.c create mode 100644 tests/projects/c/library_with_cmakelists/xmake.lua diff --git a/tests/projects/c/library_with_cmakelists/.gitignore b/tests/projects/c/library_with_cmakelists/.gitignore new file mode 100644 index 000000000..152105761 --- /dev/null +++ b/tests/projects/c/library_with_cmakelists/.gitignore @@ -0,0 +1,8 @@ +# Xmake cache +.xmake/ +build/ + +# MacOS Cache +.DS_Store + + diff --git a/tests/projects/c/library_with_cmakelists/foo/CMakeLists.txt b/tests/projects/c/library_with_cmakelists/foo/CMakeLists.txt new file mode 100644 index 000000000..2654a77a2 --- /dev/null +++ b/tests/projects/c/library_with_cmakelists/foo/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.13.0) +project(foo_demo LANGUAGES C CXX ASM) + +add_library(foo STATIC "") +target_sources(foo PRIVATE + src/interface.c +) + diff --git a/tests/projects/c/library_with_cmakelists/foo/src/interface.c b/tests/projects/c/library_with_cmakelists/foo/src/interface.c new file mode 100644 index 000000000..598d07560 --- /dev/null +++ b/tests/projects/c/library_with_cmakelists/foo/src/interface.c @@ -0,0 +1,6 @@ +#include "interface.h" + +int add(int a, int b) +{ + return a + b; +} diff --git a/tests/projects/c/library_with_cmakelists/foo/src/interface.h b/tests/projects/c/library_with_cmakelists/foo/src/interface.h new file mode 100644 index 000000000..6c2aa9c2a --- /dev/null +++ b/tests/projects/c/library_with_cmakelists/foo/src/interface.h @@ -0,0 +1,8 @@ +/*! calculate add(a, b) + * + * @param a the first argument + * @param b the second argument + * + * @return the result + */ +int add(int a, int b); diff --git a/tests/projects/c/library_with_cmakelists/src/main.c b/tests/projects/c/library_with_cmakelists/src/main.c new file mode 100644 index 000000000..9505a2f75 --- /dev/null +++ b/tests/projects/c/library_with_cmakelists/src/main.c @@ -0,0 +1,8 @@ +#include "interface.h" +#include + +int main(int argc, char** argv) +{ + printf("add(1, 2) = %d\n", add(1, 2)); + return 0; +} diff --git a/tests/projects/c/library_with_cmakelists/xmake.lua b/tests/projects/c/library_with_cmakelists/xmake.lua new file mode 100644 index 000000000..337527d0f --- /dev/null +++ b/tests/projects/c/library_with_cmakelists/xmake.lua @@ -0,0 +1,25 @@ +add_rules("mode.debug", "mode.release") + +package("foo") + add_deps("cmake") + set_sourcedir("foo") + on_install(function (package) + local configs = {} + table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release")) + table.insert(configs, "-DBUILD_SHARED_LIBS=" .. (package:config("shared") and "ON" or "OFF")) + import("package.tools.cmake").build(package, configs, {buildir = "build"}) + os.cp("src/*.h", package:installdir("include")) + os.cp("build/*.a", package:installdir("lib")) + end) + on_test(function (package) + assert(package:has_cincludes("interface.h")) + end) +package_end() + +add_requires("foo") + +target("demo") + set_kind("binary") + add_files("src/main.c") + add_packages("foo") + diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 4b3432246..a29c4fd1f 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -514,6 +514,11 @@ function _instance:unlock() end end +-- get the source directory +function _instance:sourcedir() + return self:get("sourcedir") +end + -- get the cached directory of this package function _instance:cachedir() local name = self:name():lower():gsub("::", "_") @@ -1715,6 +1720,7 @@ function package.apis() , "package.set_homepage" , "package.set_description" , "package.set_parallelize" + , "package.set_sourcedir" , "package.set_installdir" -- package.add_xxx , "package.add_deps" diff --git a/xmake/modules/private/action/require/impl/actions/install.lua b/xmake/modules/private/action/require/impl/actions/install.lua index 9dcbc537b..fac545f8e 100644 --- a/xmake/modules/private/action/require/impl/actions/install.lua +++ b/xmake/modules/private/action/require/impl/actions/install.lua @@ -137,7 +137,10 @@ function main(package) -- enter the working directory local oldir = nil - if #package:urls() > 0 then + local sourcedir = package:sourcedir() + if sourcedir then + oldir = os.cd(sourcedir) + elseif #package:urls() > 0 then -- only one root directory? skip it local filedirs = os.filedirs(path.join(workdir, "source", "*")) if #filedirs == 1 and os.isdir(filedirs[1]) then -- cgit v1.3.1 From 78a086ae1bb8347e281e8561114eab5013e41c47 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Sep 2021 00:52:11 +0800 Subject: rename file --- tests/projects/c/library_with_cmakelists/foo/CMakeLists.txt | 4 ++-- tests/projects/c/library_with_cmakelists/foo/src/foo.c | 6 ++++++ tests/projects/c/library_with_cmakelists/foo/src/foo.h | 8 ++++++++ tests/projects/c/library_with_cmakelists/foo/src/interface.c | 6 ------ tests/projects/c/library_with_cmakelists/foo/src/interface.h | 8 -------- tests/projects/c/library_with_cmakelists/src/main.c | 2 +- tests/projects/c/library_with_cmakelists/xmake.lua | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) create mode 100644 tests/projects/c/library_with_cmakelists/foo/src/foo.c create mode 100644 tests/projects/c/library_with_cmakelists/foo/src/foo.h delete mode 100644 tests/projects/c/library_with_cmakelists/foo/src/interface.c delete mode 100644 tests/projects/c/library_with_cmakelists/foo/src/interface.h diff --git a/tests/projects/c/library_with_cmakelists/foo/CMakeLists.txt b/tests/projects/c/library_with_cmakelists/foo/CMakeLists.txt index 2654a77a2..4eca38b21 100644 --- a/tests/projects/c/library_with_cmakelists/foo/CMakeLists.txt +++ b/tests/projects/c/library_with_cmakelists/foo/CMakeLists.txt @@ -1,8 +1,8 @@ cmake_minimum_required(VERSION 3.13.0) -project(foo_demo LANGUAGES C CXX ASM) +project(foo LANGUAGES C CXX ASM) add_library(foo STATIC "") target_sources(foo PRIVATE - src/interface.c + src/foo.c ) diff --git a/tests/projects/c/library_with_cmakelists/foo/src/foo.c b/tests/projects/c/library_with_cmakelists/foo/src/foo.c new file mode 100644 index 000000000..598d07560 --- /dev/null +++ b/tests/projects/c/library_with_cmakelists/foo/src/foo.c @@ -0,0 +1,6 @@ +#include "interface.h" + +int add(int a, int b) +{ + return a + b; +} diff --git a/tests/projects/c/library_with_cmakelists/foo/src/foo.h b/tests/projects/c/library_with_cmakelists/foo/src/foo.h new file mode 100644 index 000000000..6c2aa9c2a --- /dev/null +++ b/tests/projects/c/library_with_cmakelists/foo/src/foo.h @@ -0,0 +1,8 @@ +/*! calculate add(a, b) + * + * @param a the first argument + * @param b the second argument + * + * @return the result + */ +int add(int a, int b); diff --git a/tests/projects/c/library_with_cmakelists/foo/src/interface.c b/tests/projects/c/library_with_cmakelists/foo/src/interface.c deleted file mode 100644 index 598d07560..000000000 --- a/tests/projects/c/library_with_cmakelists/foo/src/interface.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "interface.h" - -int add(int a, int b) -{ - return a + b; -} diff --git a/tests/projects/c/library_with_cmakelists/foo/src/interface.h b/tests/projects/c/library_with_cmakelists/foo/src/interface.h deleted file mode 100644 index 6c2aa9c2a..000000000 --- a/tests/projects/c/library_with_cmakelists/foo/src/interface.h +++ /dev/null @@ -1,8 +0,0 @@ -/*! calculate add(a, b) - * - * @param a the first argument - * @param b the second argument - * - * @return the result - */ -int add(int a, int b); diff --git a/tests/projects/c/library_with_cmakelists/src/main.c b/tests/projects/c/library_with_cmakelists/src/main.c index 9505a2f75..1e52e7a81 100644 --- a/tests/projects/c/library_with_cmakelists/src/main.c +++ b/tests/projects/c/library_with_cmakelists/src/main.c @@ -1,4 +1,4 @@ -#include "interface.h" +#include "foo.h" #include int main(int argc, char** argv) diff --git a/tests/projects/c/library_with_cmakelists/xmake.lua b/tests/projects/c/library_with_cmakelists/xmake.lua index 337527d0f..bc3260373 100644 --- a/tests/projects/c/library_with_cmakelists/xmake.lua +++ b/tests/projects/c/library_with_cmakelists/xmake.lua @@ -12,7 +12,7 @@ package("foo") os.cp("build/*.a", package:installdir("lib")) end) on_test(function (package) - assert(package:has_cincludes("interface.h")) + assert(package:has_cincludes("foo.h")) end) package_end() -- cgit v1.3.1 From 89d9924b0f86e2d650bfc719d87e9484ba52efcf Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Sep 2021 00:54:57 +0800 Subject: improve cmakelists --- tests/projects/c/library_with_cmakelists/foo/CMakeLists.txt | 7 +++++++ tests/projects/c/library_with_cmakelists/xmake.lua | 4 +--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/projects/c/library_with_cmakelists/foo/CMakeLists.txt b/tests/projects/c/library_with_cmakelists/foo/CMakeLists.txt index 4eca38b21..0745681e0 100644 --- a/tests/projects/c/library_with_cmakelists/foo/CMakeLists.txt +++ b/tests/projects/c/library_with_cmakelists/foo/CMakeLists.txt @@ -5,4 +5,11 @@ add_library(foo STATIC "") target_sources(foo PRIVATE src/foo.c ) +set_target_properties(foo PROPERTIES PUBLIC_HEADER src/foo.h) +include(GNUInstallDirs) +install(TARGETS foo + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) diff --git a/tests/projects/c/library_with_cmakelists/xmake.lua b/tests/projects/c/library_with_cmakelists/xmake.lua index bc3260373..4bf632e08 100644 --- a/tests/projects/c/library_with_cmakelists/xmake.lua +++ b/tests/projects/c/library_with_cmakelists/xmake.lua @@ -7,9 +7,7 @@ package("foo") local configs = {} table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release")) table.insert(configs, "-DBUILD_SHARED_LIBS=" .. (package:config("shared") and "ON" or "OFF")) - import("package.tools.cmake").build(package, configs, {buildir = "build"}) - os.cp("src/*.h", package:installdir("include")) - os.cp("build/*.a", package:installdir("lib")) + import("package.tools.cmake").install(package, configs, {buildir = "build"}) end) on_test(function (package) assert(package:has_cincludes("foo.h")) -- cgit v1.3.1 From b3a43699b3d8b8533910388eb9c489a00755d402 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Sep 2021 00:55:32 +0800 Subject: fix demo --- tests/projects/c/library_with_cmakelists/foo/src/foo.c | 2 +- tests/projects/c/library_with_cmakelists/foo/src/foo.h | 9 +-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/tests/projects/c/library_with_cmakelists/foo/src/foo.c b/tests/projects/c/library_with_cmakelists/foo/src/foo.c index 598d07560..08054d059 100644 --- a/tests/projects/c/library_with_cmakelists/foo/src/foo.c +++ b/tests/projects/c/library_with_cmakelists/foo/src/foo.c @@ -1,4 +1,4 @@ -#include "interface.h" +#include "foo.h" int add(int a, int b) { diff --git a/tests/projects/c/library_with_cmakelists/foo/src/foo.h b/tests/projects/c/library_with_cmakelists/foo/src/foo.h index 6c2aa9c2a..6295ab95c 100644 --- a/tests/projects/c/library_with_cmakelists/foo/src/foo.h +++ b/tests/projects/c/library_with_cmakelists/foo/src/foo.h @@ -1,8 +1 @@ -/*! calculate add(a, b) - * - * @param a the first argument - * @param b the second argument - * - * @return the result - */ -int add(int a, int b); +int add(int a, int b); -- cgit v1.3.1 From e582b4601a0821bf9a94ac1b568aff55c842131e Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Sep 2021 00:57:51 +0800 Subject: improve package --- xmake/modules/private/action/require/impl/package.lua | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 876dabb9a..b048b7818 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -295,8 +295,8 @@ function _select_package_version(package, requireinfo, locked_requireinfo) return version, source end - -- exists urls? otherwise be phony package (only as package group) - if #package:urls() > 0 then + -- if not phony package (only as package group) + if not requireinfo.group then -- has git url? local has_giturl = false @@ -324,6 +324,11 @@ function _select_package_version(package, requireinfo, locked_requireinfo) if not version and has_giturl and not semver.is_valid(require_version) then -- select branch? version, source = require_version ~= "latest" and require_version or "master", "branch" end + -- local source package? we use a phony version + if not version and require_version == "latest" and #package:urls() == 0 then + version = "latest" + source = "version" + end if not version then raise("package(%s): version(%s) not found!", package:name(), require_version) end -- cgit v1.3.1 From 9b6ed10af9394ac3db541f848ab3405b7d0daf3d Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Sep 2021 22:38:25 +0800 Subject: improve find_package --- tests/projects/c/library_with_cmakelists/xmake.lua | 4 ++++ xmake/core/package/package.lua | 15 +++++++++++++-- .../sandbox/modules/import/lib/detect/find_program.lua | 4 +++- xmake/modules/package/manager/xmake/find_package.lua | 6 +++++- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/tests/projects/c/library_with_cmakelists/xmake.lua b/tests/projects/c/library_with_cmakelists/xmake.lua index 4bf632e08..e27fcbafa 100644 --- a/tests/projects/c/library_with_cmakelists/xmake.lua +++ b/tests/projects/c/library_with_cmakelists/xmake.lua @@ -1,8 +1,12 @@ add_rules("mode.debug", "mode.release") +local cachedir = path.join(os.scriptdir(), "build", "cache") +local packagesdir = path.join(os.scriptdir(), "build", "packages") package("foo") add_deps("cmake") set_sourcedir("foo") + set_cachedir(cachedir) + set_installdir(packagesdir) on_install(function (package) local configs = {} table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release")) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index a29c4fd1f..5c7a04d34 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -521,8 +521,16 @@ end -- get the cached directory of this package function _instance:cachedir() - local name = self:name():lower():gsub("::", "_") - return path.join(package.cachedir(), name:sub(1, 1):lower(), name, self:version_str()) + local cachedir = self._CACHEDIR + if not cachedir then + cachedir = self:get("cachedir") + if not cachedir then + local name = self:name():lower():gsub("::", "_") + cachedir = path.join(package.cachedir(), name:sub(1, 1):lower(), name, self:version_str()) + end + self._CACHEDIR = cachedir + end + return cachedir end -- get the installed directory of this package @@ -1213,6 +1221,7 @@ function _instance:find_tool(name, opt) opt = opt or {} self._find_tool = self._find_tool or sandbox_module.import("lib.detect.find_tool", {anonymous = true}) return self._find_tool(name, {cachekey = opt.cachekey or "fetch_package_system", + installdir = self:installdir(), require_version = opt.require_version, norun = opt.norun, force = opt.force}) @@ -1228,6 +1237,7 @@ function _instance:find_package(name, opt) end return self._find_package(name, { force = opt.force, + installdir = self:installdir(), require_version = opt.require_version, mode = self:mode(), plat = self:plat(), @@ -1721,6 +1731,7 @@ function package.apis() , "package.set_description" , "package.set_parallelize" , "package.set_sourcedir" + , "package.set_cachedir" , "package.set_installdir" -- package.add_xxx , "package.add_deps" diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_program.lua b/xmake/core/sandbox/modules/import/lib/detect/find_program.lua index 4e5eadc14..59a01f746 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/find_program.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/find_program.lua @@ -139,7 +139,9 @@ end function sandbox_lib_detect_find_program._find_from_packages(name, opt) -- get the manifest file of package, e.g. ~/.xmake/packages/g/git/1.1.12/ed41d5327fad3fc06fe376b4a94f62ef/manifest.txt - local manifest_file = path.join(package.installdir(), name:sub(1, 1), name, opt.require_version, opt.buildhash, "manifest.txt") + opt = opt or {} + local installdir = opt.installdir or path.join(package.installdir(), name:sub(1, 1), name, opt.require_version, opt.buildhash) + local manifest_file = path.join(installdir, "manifest.txt") if not os.isfile(manifest_file) then return end diff --git a/xmake/modules/package/manager/xmake/find_package.lua b/xmake/modules/package/manager/xmake/find_package.lua index c594c8135..503d1beda 100644 --- a/xmake/modules/package/manager/xmake/find_package.lua +++ b/xmake/modules/package/manager/xmake/find_package.lua @@ -38,7 +38,11 @@ function _find_package_from_repo(name, opt) -- find the manifest file of package, e.g. ~/.xmake/packages/z/zlib/1.1.12/ed41d5327fad3fc06fe376b4a94f62ef/manifest.txt local packagedirs = {} - table.insert(packagedirs, path.join(package.installdir(), name:lower():sub(1, 1), name:lower(), opt.require_version, opt.buildhash)) + if opt.installdir then + table.insert(packagedirs, opt.installdir) + else + table.insert(packagedirs, path.join(package.installdir(), name:lower():sub(1, 1), name:lower(), opt.require_version, opt.buildhash)) + end local manifest_file = find_file("manifest.txt", packagedirs) if not manifest_file then return -- cgit v1.3.1 From 9b11147b98d5b51bc5064757c7f3629e5ad37cbb Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Sep 2021 22:41:19 +0800 Subject: add local package dir --- tests/projects/c/library_with_cmakelists/xmake.lua | 4 ---- xmake/core/package/package.lua | 18 ++++++++++++++++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/projects/c/library_with_cmakelists/xmake.lua b/tests/projects/c/library_with_cmakelists/xmake.lua index e27fcbafa..4bf632e08 100644 --- a/tests/projects/c/library_with_cmakelists/xmake.lua +++ b/tests/projects/c/library_with_cmakelists/xmake.lua @@ -1,12 +1,8 @@ add_rules("mode.debug", "mode.release") -local cachedir = path.join(os.scriptdir(), "build", "cache") -local packagesdir = path.join(os.scriptdir(), "build", "packages") package("foo") add_deps("cmake") set_sourcedir("foo") - set_cachedir(cachedir) - set_installdir(packagesdir) on_install(function (package) local configs = {} table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release")) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 5c7a04d34..e6a8335ee 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -461,6 +461,18 @@ function _instance:is_parallelize() return self:get("parallelize") ~= false end +-- is local embed package? +-- we install directly from the local source code instead of downloading it remotely +function _instance:is_embed() + return self:get("sourcedir") and #self:urls() == 0 and self:script("install") +end + +-- is local package? +-- we will use local installdir and cachedir in current project +function _instance:is_local() + return self:is_embed() +end + -- is debug package? (deprecated) function _instance:debug() return self:is_debug() @@ -526,7 +538,8 @@ function _instance:cachedir() cachedir = self:get("cachedir") if not cachedir then local name = self:name():lower():gsub("::", "_") - cachedir = path.join(package.cachedir(), name:sub(1, 1):lower(), name, self:version_str()) + local rootdir = self:is_local() and path.join(config.directory(), "cache", "packages") or package.cachedir() + cachedir = path.join(rootdir, name:sub(1, 1):lower(), name, self:version_str()) end self._CACHEDIR = cachedir end @@ -540,7 +553,8 @@ function _instance:installdir(...) installdir = self:get("installdir") if not installdir then local name = self:name():lower():gsub("::", "_") - installdir = path.join(package.installdir(), name:sub(1, 1):lower(), name) + local rootdir = self:is_local() and path.join(config.directory(), "packages") or package.installdir() + installdir = path.join(rootdir, name:sub(1, 1):lower(), name) if self:version_str() then installdir = path.join(installdir, self:version_str()) end -- cgit v1.3.1 From 913fcb7fbe40b009eb6759dd00b37ece56ef72a8 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Sep 2021 22:47:38 +0800 Subject: support to build embed package with cmake --- tests/projects/c/library_with_cmakelists/test.lua | 6 +++++ tests/projects/c/library_with_cmakelists/xmake.lua | 6 ++--- xmake/core/package/package.lua | 30 +++++++++++++++++++--- xmake/core/project/config.lua | 8 ++++-- xmake/modules/package/tools/cmake.lua | 4 +-- 5 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 tests/projects/c/library_with_cmakelists/test.lua diff --git a/tests/projects/c/library_with_cmakelists/test.lua b/tests/projects/c/library_with_cmakelists/test.lua new file mode 100644 index 000000000..b76241be2 --- /dev/null +++ b/tests/projects/c/library_with_cmakelists/test.lua @@ -0,0 +1,6 @@ +-- main entry +function main(t) + + -- build project + t:build() +end diff --git a/tests/projects/c/library_with_cmakelists/xmake.lua b/tests/projects/c/library_with_cmakelists/xmake.lua index 4bf632e08..e5646c372 100644 --- a/tests/projects/c/library_with_cmakelists/xmake.lua +++ b/tests/projects/c/library_with_cmakelists/xmake.lua @@ -2,15 +2,15 @@ add_rules("mode.debug", "mode.release") package("foo") add_deps("cmake") - set_sourcedir("foo") + set_sourcedir(path.join(os.scriptdir(), "foo")) on_install(function (package) local configs = {} table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release")) table.insert(configs, "-DBUILD_SHARED_LIBS=" .. (package:config("shared") and "ON" or "OFF")) - import("package.tools.cmake").install(package, configs, {buildir = "build"}) + import("package.tools.cmake").install(package, configs) end) on_test(function (package) - assert(package:has_cincludes("foo.h")) + assert(package:has_cfuncs("add", {includes = "foo.h"})) end) package_end() diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index e6a8335ee..e636cfbf5 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -531,6 +531,22 @@ function _instance:sourcedir() return self:get("sourcedir") end +-- get the build directory +function _instance:buildir() + local buildir = self._BUILDIR + if not buildir then + if self:is_local() then + local name = self:name():lower():gsub("::", "_") + local rootdir = path.join(config.buildir({absolute = true}), ".packages", name:sub(1, 1):lower(), name, self:version_str()) + buildir = path.join(rootdir, "cache", "build_" .. self:buildhash():sub(1, 8)) + else + buildir = "build_" .. self:buildhash():sub(1, 8) + end + self._BUILDIR = buildir + end + return buildir +end + -- get the cached directory of this package function _instance:cachedir() local cachedir = self._CACHEDIR @@ -538,8 +554,11 @@ function _instance:cachedir() cachedir = self:get("cachedir") if not cachedir then local name = self:name():lower():gsub("::", "_") - local rootdir = self:is_local() and path.join(config.directory(), "cache", "packages") or package.cachedir() - cachedir = path.join(rootdir, name:sub(1, 1):lower(), name, self:version_str()) + if self:is_local() then + cachedir = path.join(config.buildir({absolute = true}), ".packages", name:sub(1, 1):lower(), name, self:version_str(), "cache") + else + cachedir = path.join(package.cachedir(), name:sub(1, 1):lower(), name, self:version_str()) + end end self._CACHEDIR = cachedir end @@ -553,8 +572,11 @@ function _instance:installdir(...) installdir = self:get("installdir") if not installdir then local name = self:name():lower():gsub("::", "_") - local rootdir = self:is_local() and path.join(config.directory(), "packages") or package.installdir() - installdir = path.join(rootdir, name:sub(1, 1):lower(), name) + if self:is_local() then + installdir = path.join(config.buildir({absolute = true}), ".packages", name:sub(1, 1):lower(), name) + else + installdir = path.join(package.installdir(), name:sub(1, 1):lower(), name) + end if self:version_str() then installdir = path.join(installdir, self:version_str()) end diff --git a/xmake/core/project/config.lua b/xmake/core/project/config.lua index 31e7d0cb5..16912ab68 100644 --- a/xmake/core/project/config.lua +++ b/xmake/core/project/config.lua @@ -90,9 +90,11 @@ function config.options() end -- get the buildir -function config.buildir() +-- we can use `{absolute = true}` to force to get absolute path +function config.buildir(opt) -- get the absolute path first + opt = opt or {} local buildir = config.get("buildir") or "build" if not path.is_absolute(buildir) then local rootdir @@ -106,7 +108,9 @@ function config.buildir() end -- adjust path for the current directory - buildir = path.relative(buildir, os.curdir()) + if not opt.absolute then + buildir = path.relative(buildir, os.curdir()) + end return buildir end diff --git a/xmake/modules/package/tools/cmake.lua b/xmake/modules/package/tools/cmake.lua index 048ff5909..1134339d0 100644 --- a/xmake/modules/package/tools/cmake.lua +++ b/xmake/modules/package/tools/cmake.lua @@ -665,7 +665,7 @@ function build(package, configs, opt) opt = opt or {} -- enter build directory - local buildir = opt.buildir or "build_" .. hash.uuid4():split('%-')[1] + local buildir = opt.buildir or package:buildir() os.mkdir(path.join(buildir, "install")) local oldir = os.cd(buildir) @@ -724,7 +724,7 @@ function install(package, configs, opt) opt = opt or {} -- enter build directory - local buildir = opt.buildir or "build_" .. hash.uuid4():split('%-')[1] + local buildir = opt.buildir or package:buildir() os.mkdir(path.join(buildir, "install")) local oldir = os.cd(buildir) -- cgit v1.3.1 From 4b9fec3f8052c2e1096bca31908c51f409ef8dd1 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Sep 2021 22:47:56 +0800 Subject: improve tools/meson --- xmake/modules/package/tools/meson.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xmake/modules/package/tools/meson.lua b/xmake/modules/package/tools/meson.lua index 6361f2a0e..a57497343 100644 --- a/xmake/modules/package/tools/meson.lua +++ b/xmake/modules/package/tools/meson.lua @@ -25,11 +25,11 @@ import("core.tool.toolchain") import("package.tools.ninja") -- get build directory -function _get_buildir(opt) +function _get_buildir(package, opt) if opt and opt.buildir then return opt.buildir else - _g.buildir = _g.buildir or ("build_" .. hash.uuid4():split('%-')[1]) + _g.buildir = _g.buildir or package:buildir() return _g.buildir end end @@ -56,7 +56,7 @@ function _get_configs(package, configs, opt) end -- add build directory - table.insert(configs, _get_buildir(opt)) + table.insert(configs, _get_buildir(package, opt)) return configs end @@ -160,7 +160,7 @@ function build(package, configs, opt) generate(package, configs, opt) -- do build - local buildir = _get_buildir(opt) + local buildir = _get_buildir(package, opt) ninja.build(package, {}, {buildir = buildir, envs = opt.envs or buildenvs(package, opt)}) end @@ -172,7 +172,7 @@ function install(package, configs, opt) generate(package, configs, opt) -- do build and install - local buildir = _get_buildir(opt) + local buildir = _get_buildir(package, opt) ninja.install(package, {}, {buildir = buildir, envs = opt.envs or buildenvs(package, opt)}) -- fix static libname on windows -- cgit v1.3.1 From 6d57ef5efcd62d566654c1ab189fd66e735b17d0 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Sep 2021 22:50:51 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f93fde1a4..6a191282a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * [#388](https://github.com/xmake-io/xmake/issues/388): Pascal Language Support * [#1682](https://github.com/xmake-io/xmake/issues/1682): Add optional lua5.3 backend instead of luajit to provide better compatibility * [#1622](https://github.com/xmake-io/xmake/issues/1622): Support Swig +* [#1714](https://github.com/xmake-io/xmake/issues/1714): Support build local embed cmake projects ### Change @@ -1088,6 +1089,7 @@ * [#388](https://github.com/xmake-io/xmake/issues/388): Pascal 语言支持,可以使用 fpc 来编译 free pascal * [#1682](https://github.com/xmake-io/xmake/issues/1682): 添加可选的额lua5.3 运行时替代 luajit,提供更好的平台兼容性。 * [#1622](https://github.com/xmake-io/xmake/issues/1622): 支持 Swig +* [#1714](https://github.com/xmake-io/xmake/issues/1714): 支持内置 cmake 等第三方项目的混合编译 ### 改进 -- cgit v1.3.1 From 2904ba8f0e7eb87eab4b47a6021c1ce9039a40ba Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Sep 2021 22:53:05 +0800 Subject: fix test --- tests/projects/c/library_with_cmakelists/test.lua | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/projects/c/library_with_cmakelists/test.lua b/tests/projects/c/library_with_cmakelists/test.lua index b76241be2..3c28e0c3e 100644 --- a/tests/projects/c/library_with_cmakelists/test.lua +++ b/tests/projects/c/library_with_cmakelists/test.lua @@ -1,6 +1,13 @@ -- main entry function main(t) - -- build project - t:build() + -- freebsd ci is slower + if is_host("bsd") then + return + end + + -- only for x86/x64, because it will take too long time on ci with arm/mips + if os.subarch():startswith("x") or os.subarch() == "i386" then + t:build() + end end -- cgit v1.3.1 From d4397494c7585d62364df8026c1626f1f682baa5 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Sep 2021 23:19:52 +0800 Subject: add cxx_std_ features --- tests/apis/check_xxx/config.h.in | 8 ++++++++ tests/apis/check_xxx/xmake.lua | 8 ++++++++ xmake/modules/detect/tools/cl/cfeatures.lua | 5 +++++ xmake/modules/detect/tools/cl/cxxfeatures.lua | 10 ++++++++++ xmake/modules/detect/tools/clang/cfeatures.lua | 5 +++++ xmake/modules/detect/tools/clang/cxxfeatures.lua | 11 +++++++++++ xmake/modules/detect/tools/gcc/cfeatures.lua | 5 +++++ xmake/modules/detect/tools/gcc/cxxfeatures.lua | 10 ++++++++++ xmake/modules/lib/detect/features.lua | 5 ----- 9 files changed, 62 insertions(+), 5 deletions(-) diff --git a/tests/apis/check_xxx/config.h.in b/tests/apis/check_xxx/config.h.in index a8baad68d..5fc62415e 100644 --- a/tests/apis/check_xxx/config.h.in +++ b/tests/apis/check_xxx/config.h.in @@ -8,6 +8,14 @@ ${define HAS_CONSTEXPR} ${define HAS_CONSEXPR_AND_STATIC_ASSERT} ${define HAS_SSE2} ${define HAS_LONG_8} +${define HAS_CXX_STD_98} +${define HAS_CXX_STD_11} +${define HAS_CXX_STD_14} +${define HAS_CXX_STD_17} +${define HAS_CXX_STD_20} +${define HAS_C_STD_89} +${define HAS_C_STD_99} +${define HAS_C_STD_11} ${define PTR_SIZE} ${define HAVE_VISIBILITY} ${define CUSTOM_ASSERT} diff --git a/tests/apis/check_xxx/xmake.lua b/tests/apis/check_xxx/xmake.lua index ffd9f9242..59a648c5c 100644 --- a/tests/apis/check_xxx/xmake.lua +++ b/tests/apis/check_xxx/xmake.lua @@ -23,6 +23,14 @@ target("test") configvar_check_cfuncs("HAS_SETJMP", "setjmp", {includes = {"signal.h", "setjmp.h"}}) configvar_check_features("HAS_CONSTEXPR", "cxx_constexpr", {languages = "c++11"}) configvar_check_features("HAS_CONSEXPR_AND_STATIC_ASSERT", {"cxx_constexpr", "c_static_assert"}, {languages = "c++11"}) + configvar_check_features("HAS_CXX_STD_98", "cxx_std_98") + configvar_check_features("HAS_CXX_STD_11", "cxx_std_11", {languages = "c++11"}) + configvar_check_features("HAS_CXX_STD_14", "cxx_std_14", {languages = "c++14"}) + configvar_check_features("HAS_CXX_STD_17", "cxx_std_17", {languages = "c++17"}) + configvar_check_features("HAS_CXX_STD_20", "cxx_std_20", {languages = "c++20"}) + configvar_check_features("HAS_C_STD_89", "c_std_89") + configvar_check_features("HAS_C_STD_99", "c_std_99") + configvar_check_features("HAS_C_STD_11", "c_std_11", {languages = "c11"}) configvar_check_cflags("HAS_SSE2", "-msse2") configvar_check_csnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true}) configvar_check_csnippets("PTR_SIZE", 'printf("%d", sizeof(void*)); return 0;', {output = true, number = true}) diff --git a/xmake/modules/detect/tools/cl/cfeatures.lua b/xmake/modules/detect/tools/cl/cfeatures.lua index 88c65559f..9b043f7e1 100644 --- a/xmake/modules/detect/tools/cl/cfeatures.lua +++ b/xmake/modules/detect/tools/cl/cfeatures.lua @@ -31,6 +31,11 @@ function main() local msvc_minver = "_MSC_VER >= 1200" local msvc_2005 = "_MSC_VER >= 1400" local msvc_2010 = "_MSC_VER >= 1600" + local msvc_2019 = "_MSC_VER >= 1920" + + -- set language standard supports + _set("c_std_89", msvc_2005) + _set("c_std_99", msvc_2019) -- set features _set("c_static_assert", msvc_2010) diff --git a/xmake/modules/detect/tools/cl/cxxfeatures.lua b/xmake/modules/detect/tools/cl/cxxfeatures.lua index 661af6640..c8b683e6f 100644 --- a/xmake/modules/detect/tools/cl/cxxfeatures.lua +++ b/xmake/modules/detect/tools/cl/cxxfeatures.lua @@ -32,6 +32,7 @@ end -- http://www.visualstudio.com/en-us/news/vs2015-preview-vs.aspx -- http://blogs.msdn.com/b/vcblog/archive/2015/04/29/c-11-14-17-features-in-vs-2015-rc.aspx -- http://blogs.msdn.com/b/vcblog/archive/2015/06/19/c-11-14-17-features-in-vs-2015-rtm.aspx +-- https://docs.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance?view=msvc-160 -- -- porting from Modules/Compiler/MSVC-CXX-FeatureTests.cmake -- @@ -49,6 +50,15 @@ function main() local msvc_2013 = "_MSC_VER >= 1800" local msvc_2015 = "_MSC_VER >= 1900" local msvc_2017 = "_MSC_VER >= 1910" + local msvc_2019 = "_MSC_VER >= 1920" + local msvc_2022 = "_MSC_VER >= 1930" + + -- set language standard supports + _set("cxx_std_98", msvc_2005) + _set("cxx_std_11", msvc_2015) + _set("cxx_std_14", msvc_2017) + _set("cxx_std_17", msvc_2019) + _set("cxx_std_20", msvc_2022) -- VS version 15 (not 2015) introduces support for aggregate initializers. _set("cxx_aggregate_default_initializers", "_MSC_FULL_VER >= 190024406") diff --git a/xmake/modules/detect/tools/clang/cfeatures.lua b/xmake/modules/detect/tools/clang/cfeatures.lua index 8cdfadfd0..8c462a16f 100644 --- a/xmake/modules/detect/tools/clang/cfeatures.lua +++ b/xmake/modules/detect/tools/clang/cfeatures.lua @@ -38,6 +38,11 @@ function main() local c99 = clang_minver .. " && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L" local c90 = clang_minver + -- set language standard supports + _set("c_std_89", c90) + _set("c_std_99", c99) + _set("c_std_11", c11) + -- set features _set("c_static_assert", c11) _set("c_restrict", c99) diff --git a/xmake/modules/detect/tools/clang/cxxfeatures.lua b/xmake/modules/detect/tools/clang/cxxfeatures.lua index bbf3da8b8..6a468db00 100644 --- a/xmake/modules/detect/tools/clang/cxxfeatures.lua +++ b/xmake/modules/detect/tools/clang/cxxfeatures.lua @@ -28,6 +28,8 @@ end -- get features -- +-- @see http://clang.llvm.org/cxx_status.html +-- -- porting from Modules/Compiler/Clang-CXX-FeatureTests.cmake -- function main() @@ -37,11 +39,20 @@ function main() -- init conditions local clang_minver = "((__clang_major__ * 100) + __clang_minor__) >= 301" + local clang80_cxx20 = "((__clang_major__ * 100) + __clang_minor__) >= 800 && __cplusplus > 201707L" + local clang50_cxx17 = "((__clang_major__ * 100) + __clang_minor__) >= 500 && __cplusplus > 201703L" local clang34_cxx14 = "((__clang_major__ * 100) + __clang_minor__) >= 304 && __cplusplus > 201103L" local clang31_cxx11 = clang_minver .. " && __cplusplus >= 201103L" local clang29_cxx11 = clang_minver .. " && __cplusplus >= 201103L" local clang_cxx98 = clang_minver .. " && __cplusplus >= 199711L" + -- set language standard supports + _set("cxx_std_98", clang_cxx98) + _set("cxx_std_11", clang29_cxx11) + _set("cxx_std_14", clang34_cxx14) + _set("cxx_std_17", clang50_cxx17) + _set("cxx_std_20", clang80_cxx20) + -- set features for __has_feature() local features_of_has_feature = { diff --git a/xmake/modules/detect/tools/gcc/cfeatures.lua b/xmake/modules/detect/tools/gcc/cfeatures.lua index 664892720..9f4ee275b 100644 --- a/xmake/modules/detect/tools/gcc/cfeatures.lua +++ b/xmake/modules/detect/tools/gcc/cfeatures.lua @@ -33,6 +33,11 @@ function main() local gcc34_c99 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L" local gcc_c90 = gcc_minver + -- set language standard supports + _set("c_std_89", gcc46_c90) + _set("c_std_99", gcc34_c99) + _set("c_std_11", gcc46_c11) + -- set features _set("c_static_assert", gcc46_c11) -- GNU 4.7 correctly sets __STDC_VERSION__ to 201112L, but GNU 4.6 sets it to 201000L _set("c_restrict", gcc34_c99) diff --git a/xmake/modules/detect/tools/gcc/cxxfeatures.lua b/xmake/modules/detect/tools/gcc/cxxfeatures.lua index 4edb33a27..e40eadf13 100644 --- a/xmake/modules/detect/tools/gcc/cxxfeatures.lua +++ b/xmake/modules/detect/tools/gcc/cxxfeatures.lua @@ -28,6 +28,7 @@ end -- -- http://gcc.gnu.org/projects/cxx0x.html -- http://gcc.gnu.org/projects/cxx1y.html +-- https://gcc.gnu.org/projects/cxx-status.html -- -- porting from Modules/Compiler/GNU-CXX-FeatureTests.cmake -- @@ -35,6 +36,8 @@ function main() -- init conditions local gcc_minver = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404" + local gcc90_cxx20 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 900 && __cplusplus >= 201709L" + local gcc70_cxx17 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 700 && __cplusplus >= 201703L" local gcc50_cxx14 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 500 && __cplusplus >= 201402L" local gcc49_cxx14 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L" local gcc481_cxx11 = "((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40801) && __cplusplus >= 201103L" @@ -46,6 +49,13 @@ function main() local gcc44_cxx11 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && " .. gcc_cxx0x_defined local gcc43_cxx11 = gcc_minver .. " && " .. gcc_cxx0x_defined + -- set language standard supports + _set("cxx_std_98", gcc_minver) + _set("cxx_std_11", gcc43_cxx11) + _set("cxx_std_14", gcc49_cxx14) + _set("cxx_std_17", gcc70_cxx17) + _set("cxx_std_20", gcc90_cxx20) + -- set features _set("cxx_variable_templates", gcc50_cxx14) _set("cxx_relaxed_constexpr", gcc50_cxx14) diff --git a/xmake/modules/lib/detect/features.lua b/xmake/modules/lib/detect/features.lua index 614d8c592..8b9bde45b 100644 --- a/xmake/modules/lib/detect/features.lua +++ b/xmake/modules/lib/detect/features.lua @@ -79,12 +79,7 @@ function main(name, opt) end _g._checking = nil - -- no features? result = result or {} - - -- save result to cache results[key] = result - - -- ok? return result end -- cgit v1.3.1 From db6fe6c5fafdac2e719fcfbfc9dbe305ed4cf606 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Sep 2021 23:36:08 +0800 Subject: improve to detect c++ features --- xmake/modules/detect/tools/clang/cxxfeatures.lua | 5 +++-- xmake/modules/detect/tools/gcc/cxxfeatures.lua | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/xmake/modules/detect/tools/clang/cxxfeatures.lua b/xmake/modules/detect/tools/clang/cxxfeatures.lua index 6a468db00..1fd57c8d6 100644 --- a/xmake/modules/detect/tools/clang/cxxfeatures.lua +++ b/xmake/modules/detect/tools/clang/cxxfeatures.lua @@ -38,9 +38,10 @@ function main() _g.features = cxxfeatures() -- init conditions + -- clang -x c++ -std=c++20 -dM -E - < /dev/null | grep __cplusplus local clang_minver = "((__clang_major__ * 100) + __clang_minor__) >= 301" - local clang80_cxx20 = "((__clang_major__ * 100) + __clang_minor__) >= 800 && __cplusplus > 201707L" - local clang50_cxx17 = "((__clang_major__ * 100) + __clang_minor__) >= 500 && __cplusplus > 201703L" + local clang80_cxx20 = "((__clang_major__ * 100) + __clang_minor__) >= 800 && __cplusplus >= 202002L" + local clang50_cxx17 = "((__clang_major__ * 100) + __clang_minor__) >= 500 && __cplusplus >= 201703L" local clang34_cxx14 = "((__clang_major__ * 100) + __clang_minor__) >= 304 && __cplusplus > 201103L" local clang31_cxx11 = clang_minver .. " && __cplusplus >= 201103L" local clang29_cxx11 = clang_minver .. " && __cplusplus >= 201103L" diff --git a/xmake/modules/detect/tools/gcc/cxxfeatures.lua b/xmake/modules/detect/tools/gcc/cxxfeatures.lua index e40eadf13..96eaecf66 100644 --- a/xmake/modules/detect/tools/gcc/cxxfeatures.lua +++ b/xmake/modules/detect/tools/gcc/cxxfeatures.lua @@ -35,8 +35,9 @@ end function main() -- init conditions + -- gcc -x c++ -std=c++20 -dM -E - < /dev/null | grep __cplusplus local gcc_minver = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404" - local gcc90_cxx20 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 900 && __cplusplus >= 201709L" + local gcc90_cxx20 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 900 && __cplusplus >= 202002L" local gcc70_cxx17 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 700 && __cplusplus >= 201703L" local gcc50_cxx14 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 500 && __cplusplus >= 201402L" local gcc49_cxx14 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L" -- cgit v1.3.1 From 2c906bc87c0140c20509ee2063b64188375225f2 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Sep 2021 23:37:41 +0800 Subject: improve detect c17 --- tests/apis/check_xxx/config.h.in | 1 + tests/apis/check_xxx/xmake.lua | 1 + xmake/modules/detect/tools/clang/cfeatures.lua | 3 +++ xmake/modules/detect/tools/gcc/cfeatures.lua | 2 ++ 4 files changed, 7 insertions(+) diff --git a/tests/apis/check_xxx/config.h.in b/tests/apis/check_xxx/config.h.in index 5fc62415e..e5c1bc6a1 100644 --- a/tests/apis/check_xxx/config.h.in +++ b/tests/apis/check_xxx/config.h.in @@ -16,6 +16,7 @@ ${define HAS_CXX_STD_20} ${define HAS_C_STD_89} ${define HAS_C_STD_99} ${define HAS_C_STD_11} +${define HAS_C_STD_17} ${define PTR_SIZE} ${define HAVE_VISIBILITY} ${define CUSTOM_ASSERT} diff --git a/tests/apis/check_xxx/xmake.lua b/tests/apis/check_xxx/xmake.lua index 59a648c5c..e67fdd27f 100644 --- a/tests/apis/check_xxx/xmake.lua +++ b/tests/apis/check_xxx/xmake.lua @@ -31,6 +31,7 @@ target("test") configvar_check_features("HAS_C_STD_89", "c_std_89") configvar_check_features("HAS_C_STD_99", "c_std_99") configvar_check_features("HAS_C_STD_11", "c_std_11", {languages = "c11"}) + configvar_check_features("HAS_C_STD_17", "c_std_17", {languages = "c17"}) configvar_check_cflags("HAS_SSE2", "-msse2") configvar_check_csnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true}) configvar_check_csnippets("PTR_SIZE", 'printf("%d", sizeof(void*)); return 0;', {output = true, number = true}) diff --git a/xmake/modules/detect/tools/clang/cfeatures.lua b/xmake/modules/detect/tools/clang/cfeatures.lua index 8c462a16f..e9a1687a6 100644 --- a/xmake/modules/detect/tools/clang/cfeatures.lua +++ b/xmake/modules/detect/tools/clang/cfeatures.lua @@ -33,7 +33,9 @@ function main() _g.features = cfeatures() -- init conditions + -- clang -std=c11 -dM -E - < /dev/null | grep __STDC_VERSION__ local clang_minver = "((__clang_major__ * 100) + __clang_minor__) >= 304" + local c17 = clang_minver .. " && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201710L" local c11 = clang_minver .. " && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L" local c99 = clang_minver .. " && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L" local c90 = clang_minver @@ -42,6 +44,7 @@ function main() _set("c_std_89", c90) _set("c_std_99", c99) _set("c_std_11", c11) + _set("c_std_17", c17) -- set features _set("c_static_assert", c11) diff --git a/xmake/modules/detect/tools/gcc/cfeatures.lua b/xmake/modules/detect/tools/gcc/cfeatures.lua index 9f4ee275b..b9ebaa036 100644 --- a/xmake/modules/detect/tools/gcc/cfeatures.lua +++ b/xmake/modules/detect/tools/gcc/cfeatures.lua @@ -29,6 +29,7 @@ function main() -- init conditions local gcc_minver = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304" + local gcc10_c17 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 1000 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201710L" local gcc46_c11 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201000L" local gcc34_c99 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L" local gcc_c90 = gcc_minver @@ -37,6 +38,7 @@ function main() _set("c_std_89", gcc46_c90) _set("c_std_99", gcc34_c99) _set("c_std_11", gcc46_c11) + _set("c_std_17", gcc46_c17) -- set features _set("c_static_assert", gcc46_c11) -- GNU 4.7 correctly sets __STDC_VERSION__ to 201112L, but GNU 4.6 sets it to 201000L -- cgit v1.3.1 From 5d51a5ea5a32bdc17a6830605fa8904279102629 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Sep 2021 23:40:12 +0800 Subject: update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a191282a..a90e5e95c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ * [#1682](https://github.com/xmake-io/xmake/issues/1682): Add optional lua5.3 backend instead of luajit to provide better compatibility * [#1622](https://github.com/xmake-io/xmake/issues/1622): Support Swig * [#1714](https://github.com/xmake-io/xmake/issues/1714): Support build local embed cmake projects +* [#1715](https://github.com/xmake-io/xmake/issues/1715): Support to detect compiler language standards as features + ### Change @@ -1090,6 +1092,7 @@ * [#1682](https://github.com/xmake-io/xmake/issues/1682): 添加可选的额lua5.3 运行时替代 luajit,提供更好的平台兼容性。 * [#1622](https://github.com/xmake-io/xmake/issues/1622): 支持 Swig * [#1714](https://github.com/xmake-io/xmake/issues/1714): 支持内置 cmake 等第三方项目的混合编译 +* [#1715](https://github.com/xmake-io/xmake/issues/1715): 支持探测编译器语言标准特性 ### 改进 -- cgit v1.3.1 From b489ff22c57c843e6894b5280fa8930231f86249 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 30 Sep 2021 00:25:24 +0800 Subject: add check_macros --- tests/apis/check_xxx/config.h.in | 3 + tests/apis/check_xxx/xmake.lua | 4 ++ xmake/includes/check_macros.lua | 128 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 xmake/includes/check_macros.lua diff --git a/tests/apis/check_xxx/config.h.in b/tests/apis/check_xxx/config.h.in index e5c1bc6a1..9dedbaf96 100644 --- a/tests/apis/check_xxx/config.h.in +++ b/tests/apis/check_xxx/config.h.in @@ -17,6 +17,9 @@ ${define HAS_C_STD_89} ${define HAS_C_STD_99} ${define HAS_C_STD_11} ${define HAS_C_STD_17} +${define HAS_GCC} +${define HAS_CXX20} +${define NO_GCC} ${define PTR_SIZE} ${define HAVE_VISIBILITY} ${define CUSTOM_ASSERT} diff --git a/tests/apis/check_xxx/xmake.lua b/tests/apis/check_xxx/xmake.lua index e67fdd27f..810a67612 100644 --- a/tests/apis/check_xxx/xmake.lua +++ b/tests/apis/check_xxx/xmake.lua @@ -2,6 +2,7 @@ includes("check_links.lua") includes("check_ctypes.lua") includes("check_cflags.lua") includes("check_cfuncs.lua") +includes("check_macros.lua") includes("check_features.lua") includes("check_csnippets.lua") includes("check_cincludes.lua") @@ -37,3 +38,6 @@ target("test") configvar_check_csnippets("PTR_SIZE", 'printf("%d", sizeof(void*)); return 0;', {output = true, number = true}) configvar_check_csnippets("HAVE_VISIBILITY", 'extern __attribute__((__visibility__("hidden"))) int hiddenvar;', {default = 0}) configvar_check_csnippets("CUSTOM_ASSERT=assert", 'assert(1);', {default = "", quote = false}) + configvar_check_macros("HAS_GCC", "__GNUC__") + configvar_check_macros("NO_GCC", "__GNUC__", {defined = false}) + configvar_check_macros("HAS_CXX20", "__cplusplus >= 202002L", {languages = "c++20"}) diff --git a/xmake/includes/check_macros.lua b/xmake/includes/check_macros.lua new file mode 100644 index 000000000..ec4beddce --- /dev/null +++ b/xmake/includes/check_macros.lua @@ -0,0 +1,128 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file check_macros.lua +-- + +-- check macros and add macro definition +-- +-- e.g. +-- +-- check_macros("HAS_GCC", "__GNUC__") +-- check_macros("NO_GCC", "__GNUC__", {defined = false}) +-- check_macros("HAS_CXX20", "__cplusplus >= 202002L", {languages = "c++20"}) +-- +function check_macros(definition, macros, opt) + opt = opt or {} + local optname = "__" .. (opt.name or definition) + local snippets = {} + option(optname) + for _, macro in ipairs(macros) do + if macro:find(' ', 1, true) then + table.insert(snippets, ([[ + #if %s + #else + # #error %s is not satisfied! + #endif + ]]):format(macro, macro)) + else + table.insert(snippets, ([[ + #if%s %s + #else + # #error %s is not defined! + #endif + ]]):format(opt.defined ~= false and "def" or "ndef", macro, macro)) + end + end + if opt.languages and opt.languages:startswith("c++") then + add_cxxsnippets(definition, table.concat(snippets, "\n")) + else + add_csnippets(definition, table.concat(snippets, "\n")) + end + add_defines(definition) + if opt.languages then + set_languages(opt.languages) + end + if opt.cflags then + add_cflags(opt.cflags) + end + if opt.cxflags then + add_cxflags(opt.cxflags) + end + if opt.cxxflags then + add_cxxflags(opt.cxxflags) + end + option_end() + add_options(optname) +end + +-- check macros and add macro definition to the configuration files +-- +-- e.g. +-- configvar_check_macros("HAS_GCC", "__GNUC__") +-- configvar_check_macros("NO_GCC", "__GNUC__", {defined = false}) +-- configvar_check_macros("HAS_CXX20", "__cplusplus >= 202002L", {languages = "c++20"}) +function configvar_check_macros(definition, macros, opt) + opt = opt or {} + local optname = "__" .. (opt.name or definition) + local defname, defval = unpack(definition:split('=')) + local snippets = {} + option(optname) + for _, macro in ipairs(macros) do + if macro:find(' ', 1, true) then + table.insert(snippets, ([[ + #if %s + #else + # #error %s is not satisfied! + #endif + ]]):format(macro, macro)) + else + table.insert(snippets, ([[ + #if%s %s + #else + # #error %s is not defined! + #endif + ]]):format(opt.defined ~= false and "def" or "ndef", macro, macro)) + end + end + if opt.languages and opt.languages:startswith("c++") then + add_cxxsnippets(definition, table.concat(snippets, "\n")) + else + add_csnippets(definition, table.concat(snippets, "\n")) + end + if opt.default == nil then + set_configvar(defname, defval or 1, {quote = opt.quote}) + end + if opt.languages then + set_languages(opt.languages) + end + if opt.cflags then + add_cflags(opt.cflags) + end + if opt.cxflags then + add_cxflags(opt.cxflags) + end + if opt.cxxflags then + add_cxxflags(opt.cxxflags) + end + option_end() + if opt.default == nil then + add_options(optname) + else + set_configvar(defname, has_config(optname) and (defval or 1) or opt.default, {quote = opt.quote}) + end +end -- cgit v1.3.1 From 5c940914eb8c2b1e7a4ebffe34994405d3dd68ed Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 30 Sep 2021 00:25:35 +0800 Subject: update changelog --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a90e5e95c..a00ea994b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ * [#1682](https://github.com/xmake-io/xmake/issues/1682): Add optional lua5.3 backend instead of luajit to provide better compatibility * [#1622](https://github.com/xmake-io/xmake/issues/1622): Support Swig * [#1714](https://github.com/xmake-io/xmake/issues/1714): Support build local embed cmake projects -* [#1715](https://github.com/xmake-io/xmake/issues/1715): Support to detect compiler language standards as features +* [#1715](https://github.com/xmake-io/xmake/issues/1715): Support to detect compiler language standards as features and add `check_macros` ### Change @@ -1092,7 +1092,7 @@ * [#1682](https://github.com/xmake-io/xmake/issues/1682): 添加可选的额lua5.3 运行时替代 luajit,提供更好的平台兼容性。 * [#1622](https://github.com/xmake-io/xmake/issues/1622): 支持 Swig * [#1714](https://github.com/xmake-io/xmake/issues/1714): 支持内置 cmake 等第三方项目的混合编译 -* [#1715](https://github.com/xmake-io/xmake/issues/1715): 支持探测编译器语言标准特性 +* [#1715](https://github.com/xmake-io/xmake/issues/1715): 支持探测编译器语言标准特性,并且新增 `check_macros` 检测接口 ### 改进 -- cgit v1.3.1 From ed6dd5f22cc4f8b8a85e3146082e5bd48797292a Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 1 Oct 2021 00:41:18 +0800 Subject: improve tools/xmake --- xmake/modules/package/tools/xmake.lua | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/xmake/modules/package/tools/xmake.lua b/xmake/modules/package/tools/xmake.lua index facbf2be6..e782eb834 100644 --- a/xmake/modules/package/tools/xmake.lua +++ b/xmake/modules/package/tools/xmake.lua @@ -66,10 +66,6 @@ function _get_configs(package, configs) if sdkdir then table.insert(configs, "--sdk=" .. sdkdir) end - local toolchain_name = get_config("toolchain") - if toolchain_name then - table.insert(configs, "--toolchain=" .. toolchain_name) - end else local names = {"ndk", "ndk_sdkver", "vs", "mingw", "ld", "sh", "ar", "cc", "cxx", "mm", "mxx"} for _, name in ipairs(names) do @@ -79,6 +75,13 @@ function _get_configs(package, configs) end end end + -- we can only modify toolchain for linux or cross-compilation + if package:is_plat("linux", "cross") then + local toolchain_name = get_config("toolchain") + if toolchain_name then + table.insert(configs, "--toolchain=" .. toolchain_name) + end + end if not package:is_plat("windows", "mingw") and package:config("pic") ~= false then table.insert(cxflags, "-fPIC") end -- cgit v1.3.1 From e040b7041551c06f140933442c31bd3a1ece3edd Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 1 Oct 2021 22:38:03 +0800 Subject: update tbox --- core/src/tbox/tbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/tbox/tbox b/core/src/tbox/tbox index cde8c8ad9..7ca5145d4 160000 --- a/core/src/tbox/tbox +++ b/core/src/tbox/tbox @@ -1 +1 @@ -Subproject commit cde8c8ad90aac79d277a1891967be3c1a58e0858 +Subproject commit 7ca5145d40aa906fdc48b0b0e75e80412241be7e -- cgit v1.3.1 From 8290bf21a9ba66cc4b253e39d716d715a7cfe466 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 2 Oct 2021 00:23:08 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a00ea994b..b58b3c813 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * [#1622](https://github.com/xmake-io/xmake/issues/1622): Support Swig * [#1714](https://github.com/xmake-io/xmake/issues/1714): Support build local embed cmake projects * [#1715](https://github.com/xmake-io/xmake/issues/1715): Support to detect compiler language standards as features and add `check_macros` +* Support Loongarch ### Change @@ -1093,6 +1094,7 @@ * [#1622](https://github.com/xmake-io/xmake/issues/1622): 支持 Swig * [#1714](https://github.com/xmake-io/xmake/issues/1714): 支持内置 cmake 等第三方项目的混合编译 * [#1715](https://github.com/xmake-io/xmake/issues/1715): 支持探测编译器语言标准特性,并且新增 `check_macros` 检测接口 +* xmake 支持在 Loongarch 架构上运行 ### 改进 -- cgit v1.3.1 From d4789ff5e968294bf2e9831209d0cf61b61c9d43 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 2 Oct 2021 21:51:33 +0800 Subject: improve compile_commands --- xmake/plugins/project/clang/compile_commands.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/xmake/plugins/project/clang/compile_commands.lua b/xmake/plugins/project/clang/compile_commands.lua index eb30a1ee4..085d230ae 100644 --- a/xmake/plugins/project/clang/compile_commands.lua +++ b/xmake/plugins/project/clang/compile_commands.lua @@ -35,7 +35,11 @@ end function _translate_arguments(arguments) local args = {} local is_msvc = path.basename(arguments[1]):lower() == "cl" - for _, arg in ipairs(arguments) do + for idx, arg in ipairs(arguments) do + -- see https://github.com/xmake-io/xmake/issues/1721 + if idx == 1 and is_host("windows") and path.extension(arg) == "" then + arg = arg .. ".exe" + end if arg:find("-isystem", 1, true) then arg = arg:replace("-isystem", "-I") elseif arg:find("[%-/]external:I") then -- cgit v1.3.1 From e80a41789b0de5f2249c15d57486fd3a4b40ff99 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 2 Oct 2021 23:29:03 +0800 Subject: save and restore scope --- tests/apis/check_xxx/foo.c | 6 ++ tests/apis/check_xxx/main.c | 2 - tests/apis/check_xxx/xmake.lua | 11 +++- xmake/core/base/interpreter.lua | 110 ++++++++++++++++++------------- xmake/includes/check_cflags.lua | 4 ++ xmake/includes/check_cfuncs.lua | 4 ++ xmake/includes/check_cincludes.lua | 4 ++ xmake/includes/check_csnippets.lua | 4 ++ xmake/includes/check_ctypes.lua | 4 ++ xmake/includes/check_cxxflags.lua | 4 ++ xmake/includes/check_cxxfuncs.lua | 4 ++ xmake/includes/check_cxxincludes.lua | 4 ++ xmake/includes/check_cxxsnippets.lua | 4 ++ xmake/includes/check_cxxtypes.lua | 4 ++ xmake/includes/check_features.lua | 4 ++ xmake/includes/check_links.lua | 4 ++ xmake/includes/check_macros.lua | 4 ++ xmake/includes/check_syslinks.lua | 4 ++ xmake/includes/find_and_add_packages.lua | 2 + xmake/languages/c++/load.lua | 8 +-- 20 files changed, 139 insertions(+), 56 deletions(-) create mode 100644 tests/apis/check_xxx/foo.c diff --git a/tests/apis/check_xxx/foo.c b/tests/apis/check_xxx/foo.c new file mode 100644 index 000000000..c055f5886 --- /dev/null +++ b/tests/apis/check_xxx/foo.c @@ -0,0 +1,6 @@ +#include "config.h" + +int foo() +{ + return 0; +} diff --git a/tests/apis/check_xxx/main.c b/tests/apis/check_xxx/main.c index 5e40e6691..e5a9ccbdf 100644 --- a/tests/apis/check_xxx/main.c +++ b/tests/apis/check_xxx/main.c @@ -1,5 +1,3 @@ -#include "config.h" - int main(int argc, char** argv) { return 0; diff --git a/tests/apis/check_xxx/xmake.lua b/tests/apis/check_xxx/xmake.lua index 810a67612..b412571c4 100644 --- a/tests/apis/check_xxx/xmake.lua +++ b/tests/apis/check_xxx/xmake.lua @@ -7,9 +7,9 @@ includes("check_features.lua") includes("check_csnippets.lua") includes("check_cincludes.lua") -target("test") - set_kind("binary") - add_files("*.c") +target("foo") + set_kind("static") + add_files("foo.c") add_includedirs("$(buildir)") add_configfiles("config.h.in") @@ -41,3 +41,8 @@ target("test") configvar_check_macros("HAS_GCC", "__GNUC__") configvar_check_macros("NO_GCC", "__GNUC__", {defined = false}) configvar_check_macros("HAS_CXX20", "__cplusplus >= 202002L", {languages = "c++20"}) + +target("test") + add_deps("foo") + set_kind("binary") + add_files("main.c") diff --git a/xmake/core/base/interpreter.lua b/xmake/core/base/interpreter.lua index 131a6d1c2..9a0416c52 100644 --- a/xmake/core/base/interpreter.lua +++ b/xmake/core/base/interpreter.lua @@ -694,6 +694,10 @@ function interpreter.new() instance:api_register(nil, "add_subdirs", interpreter.api_builtin_includes) instance:api_register(nil, "add_subfiles", interpreter.api_builtin_includes) instance:api_register(nil, "set_xmakever", interpreter.api_builtin_set_xmakever) + instance:api_register(nil, "save_scope", interpreter.api_builtin_save_scope) + instance:api_register(nil, "restore_scope",interpreter.api_builtin_restore_scope) + instance:api_register(nil, "get_scopekind",interpreter.api_builtin_get_scopekind) + instance:api_register(nil, "get_scopename",interpreter.api_builtin_get_scopename) -- register the builtin modules for module_name, module in pairs(interpreter._builtin_modules()) do @@ -1533,22 +1537,12 @@ end -- the builtin api: includes() function interpreter:api_builtin_includes(...) - - -- check assert(self and self._PRIVATE and self._PRIVATE._ROOTDIR and self._PRIVATE._MTIMES) - - -- the current file local curfile = self._PRIVATE._CURFILE - assert(curfile) - - -- the scopes local scopes = self._PRIVATE._SCOPES - assert(scopes) - - -- get all subpaths - local subpaths = table.join(...) -- find all files + local subpaths = table.join(...) local subpaths_matched = {} for _, subpath in ipairs(subpaths) do -- find the given files from the project directory @@ -1646,6 +1640,64 @@ function interpreter:api_builtin_includes(...) self._PRIVATE._CURFILE = curfile end +-- the builtin api: save_scope() +-- save the current scope +function interpreter:api_builtin_save_scope() + assert(self and self._PRIVATE) + + -- the scopes + local scopes = self._PRIVATE._SCOPES + assert(scopes) + + -- save the current scope + local scope = {} + scope._CURRENT = scopes._CURRENT + scope._CURRENT_KIND = scopes._CURRENT_KIND + self._PRIVATE._SCOPES_SAVED = self._PRIVATE._SCOPES_SAVED or {} + table.insert(self._PRIVATE._SCOPES_SAVED, scope) +end + +-- the builtin api: restore_scope() +-- restore the current scope +function interpreter:api_builtin_restore_scope() + assert(self and self._PRIVATE) + + -- the scopes + local scopes = self._PRIVATE._SCOPES + assert(scopes) + + -- restore it + local scopes_saved = self._PRIVATE._SCOPES_SAVED + if scopes_saved and #scopes_saved > 0 then + local scope = scopes_saved[#scopes_saved] + if scope then + scopes._CURRENT = scope._CURRENT + scopes._CURRENT_KIND = scope._CURRENT_KIND + table.remove(scopes_saved, #scopes_saved) + end + end +end + +-- the builtin api: get_scopekind() +function interpreter:api_builtin_get_scopekind() + local scopes = self._PRIVATE._SCOPES + return scopes._CURRENT_KIND +end + +-- the builtin api: get_scopename() +function interpreter:api_builtin_get_scopename() + local scopes = self._PRIVATE._SCOPES + local scope_kind = scopes._CURRENT_KIND + if scope_kind and scopes[scope_kind] then + local scope_current = scopes._CURRENT + for name, scope in pairs(scopes[scope_kind]) do + if scope_current == scope then + return name + end + end + end +end + -- get api function function interpreter:api_func(apiname) @@ -1672,40 +1724,6 @@ function interpreter:api_call(apiname, ...) return apifunc(...) end --- save the current scope -function interpreter:scope_save() - - -- check - assert(self and self._PRIVATE) - - -- the scopes - local scopes = self._PRIVATE._SCOPES - assert(scopes) - - -- the current scope - local scope = {} - scope._CURRENT = scopes._CURRENT - scope._CURRENT_KIND = scopes._CURRENT_KIND - - -- ok? - return scope -end - --- restore the current scope -function interpreter:scope_restore(scope) - - -- check - assert(self and self._PRIVATE and scope) - - -- the scopes - local scopes = self._PRIVATE._SCOPES - assert(scopes) - - -- restore it - scopes._CURRENT = scope._CURRENT - scopes._CURRENT_KIND = scope._CURRENT_KIND -end - -- get current instance in the interpreter modules function interpreter.instance(script) @@ -1753,8 +1771,6 @@ function interpreter.instance(script) -- next level = level + 1 end - - -- ok? return instance end diff --git a/xmake/includes/check_cflags.lua b/xmake/includes/check_cflags.lua index 85c9ef3c7..ef3f7866b 100644 --- a/xmake/includes/check_cflags.lua +++ b/xmake/includes/check_cflags.lua @@ -28,6 +28,7 @@ function check_cflags(definition, flags, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) + save_scope() option(optname) add_defines(definition) on_check(function (option) @@ -37,6 +38,7 @@ function check_cflags(definition, flags, opt) end end) option_end() + restore_scope() add_options(optname) end @@ -54,6 +56,7 @@ function configvar_check_cflags(definition, flags, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) + save_scope() option(optname) if opt.default == nil then set_configvar(defname, defval or 1, {quote = opt.quote}) @@ -65,6 +68,7 @@ function configvar_check_cflags(definition, flags, opt) end end) option_end() + restore_scope() if opt.default == nil then add_options(optname) else diff --git a/xmake/includes/check_cfuncs.lua b/xmake/includes/check_cfuncs.lua index 42d173a18..1a64cb250 100644 --- a/xmake/includes/check_cfuncs.lua +++ b/xmake/includes/check_cfuncs.lua @@ -34,6 +34,7 @@ function check_cfuncs(definition, funcs, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) + save_scope() option(optname) add_cfuncs(funcs) add_defines(definition) @@ -59,6 +60,7 @@ function check_cfuncs(definition, funcs, opt) set_warnings(opt.warnings) end option_end() + restore_scope() add_options(optname) end @@ -75,6 +77,7 @@ function configvar_check_cfuncs(definition, funcs, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) + save_scope() option(optname) add_cfuncs(funcs) if opt.default == nil then @@ -102,6 +105,7 @@ function configvar_check_cfuncs(definition, funcs, opt) set_warnings(opt.warnings) end option_end() + restore_scope() if opt.default == nil then add_options(optname) else diff --git a/xmake/includes/check_cincludes.lua b/xmake/includes/check_cincludes.lua index f9d69aad5..dc0308a65 100644 --- a/xmake/includes/check_cincludes.lua +++ b/xmake/includes/check_cincludes.lua @@ -28,6 +28,7 @@ function check_cincludes(definition, includes, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) + save_scope() option(optname) add_cincludes(includes) if opt.includedirs then @@ -35,6 +36,7 @@ function check_cincludes(definition, includes, opt) end add_defines(definition) option_end() + restore_scope() add_options(optname) end @@ -50,6 +52,7 @@ function configvar_check_cincludes(definition, includes, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) + save_scope() option(optname) add_cincludes(includes) if opt.includedirs then @@ -59,6 +62,7 @@ function configvar_check_cincludes(definition, includes, opt) set_configvar(defname, defval or 1, {quote = opt.quote}) end option_end() + restore_scope() if opt.default == nil then add_options(optname) else diff --git a/xmake/includes/check_csnippets.lua b/xmake/includes/check_csnippets.lua index 95aa0b2d5..9d2370ee0 100644 --- a/xmake/includes/check_csnippets.lua +++ b/xmake/includes/check_csnippets.lua @@ -29,6 +29,7 @@ function check_csnippets(definition, snippets, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) + save_scope() option(optname) add_csnippets(definition, snippets, {tryrun = opt.tryrun, output = opt.output}) if not opt.output then @@ -69,6 +70,7 @@ function check_csnippets(definition, snippets, opt) end) end option_end() + restore_scope() add_options(optname) end @@ -86,6 +88,7 @@ function configvar_check_csnippets(definition, snippets, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) + save_scope() option(optname) add_csnippets(definition, snippets, {tryrun = opt.tryrun, output = opt.output}) if opt.default == nil then @@ -120,6 +123,7 @@ function configvar_check_csnippets(definition, snippets, opt) end) end option_end() + restore_scope() if opt.default == nil then add_options(optname) else diff --git a/xmake/includes/check_ctypes.lua b/xmake/includes/check_ctypes.lua index e0c3caa47..b3f59b04e 100644 --- a/xmake/includes/check_ctypes.lua +++ b/xmake/includes/check_ctypes.lua @@ -28,6 +28,7 @@ function check_ctypes(definition, types, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) + save_scope() option(optname) add_ctypes(types) add_defines(definition) @@ -47,6 +48,7 @@ function check_ctypes(definition, types, opt) add_cincludes(opt.includes) end option_end() + restore_scope() add_options(optname) end @@ -63,6 +65,7 @@ function configvar_check_ctypes(definition, types, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) + save_scope() option(optname) add_ctypes(types) if opt.default == nil then @@ -84,6 +87,7 @@ function configvar_check_ctypes(definition, types, opt) add_cincludes(opt.includes) end option_end() + restore_scope() if opt.default == nil then add_options(optname) else diff --git a/xmake/includes/check_cxxflags.lua b/xmake/includes/check_cxxflags.lua index 9a0880697..38ea5172e 100644 --- a/xmake/includes/check_cxxflags.lua +++ b/xmake/includes/check_cxxflags.lua @@ -28,6 +28,7 @@ function check_cxxflags(definition, flags, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) + save_scope() option(optname) add_defines(definition) on_check(function (option) @@ -37,6 +38,7 @@ function check_cxxflags(definition, flags, opt) end end) option_end() + restore_scope() add_options(optname) end @@ -54,6 +56,7 @@ function configvar_check_cxxflags(definition, flags, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) + save_scope() option(optname) if opt.default == nil then set_configvar(defname, defval or 1, {quote = opt.quote}) @@ -65,6 +68,7 @@ function configvar_check_cxxflags(definition, flags, opt) end end) option_end() + restore_scope() if opt.default == nil then add_options(optname) else diff --git a/xmake/includes/check_cxxfuncs.lua b/xmake/includes/check_cxxfuncs.lua index 3a64075dc..1488f7312 100644 --- a/xmake/includes/check_cxxfuncs.lua +++ b/xmake/includes/check_cxxfuncs.lua @@ -34,6 +34,7 @@ function check_cxxfuncs(definition, funcs, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) + save_scope() option(optname) add_cxxfuncs(funcs) add_defines(definition) @@ -59,6 +60,7 @@ function check_cxxfuncs(definition, funcs, opt) set_warnings(opt.warnings) end option_end() + restore_scope() add_options(optname) end @@ -75,6 +77,7 @@ function configvar_check_cxxfuncs(definition, funcs, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) + save_scope() option(optname) add_cxxfuncs(funcs) if opt.default == nil then @@ -102,6 +105,7 @@ function configvar_check_cxxfuncs(definition, funcs, opt) set_warnings(opt.warnings) end option_end() + restore_scope() if opt.default == nil then add_options(optname) else diff --git a/xmake/includes/check_cxxincludes.lua b/xmake/includes/check_cxxincludes.lua index a779ffd15..45cb2d2c0 100644 --- a/xmake/includes/check_cxxincludes.lua +++ b/xmake/includes/check_cxxincludes.lua @@ -28,10 +28,12 @@ function check_cxxincludes(definition, includes, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) + save_scope() option(optname) add_cxxincludes(includes) add_defines(definition) option_end() + restore_scope() add_options(optname) end @@ -47,12 +49,14 @@ function configvar_check_cxxincludes(definition, includes, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) + save_scope() option(optname) add_cxxincludes(includes) if opt.default == nil then set_configvar(defname, defval or 1, {quote = opt.quote}) end option_end() + restore_scope() if opt.default == nil then add_options(optname) else diff --git a/xmake/includes/check_cxxsnippets.lua b/xmake/includes/check_cxxsnippets.lua index b46c650ff..daa71780c 100644 --- a/xmake/includes/check_cxxsnippets.lua +++ b/xmake/includes/check_cxxsnippets.lua @@ -29,6 +29,7 @@ function check_cxxsnippets(definition, snippets, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) + save_scope() option(optname) add_cxxsnippets(definition, snippets, {tryrun = opt.tryrun, output = opt.output}) if not opt.output then @@ -69,6 +70,7 @@ function check_cxxsnippets(definition, snippets, opt) end) end option_end() + restore_scope() add_options(optname) end @@ -86,6 +88,7 @@ function configvar_check_cxxsnippets(definition, snippets, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) + save_scope() option(optname) add_cxxsnippets(definition, snippets, {tryrun = opt.tryrun, output = opt.output}) if opt.default == nil then @@ -120,6 +123,7 @@ function configvar_check_cxxsnippets(definition, snippets, opt) end) end option_end() + restore_scope() if opt.default == nil then add_options(optname) else diff --git a/xmake/includes/check_cxxtypes.lua b/xmake/includes/check_cxxtypes.lua index e53caae6e..f5b8c677a 100644 --- a/xmake/includes/check_cxxtypes.lua +++ b/xmake/includes/check_cxxtypes.lua @@ -28,6 +28,7 @@ function check_cxxtypes(definition, types, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) + save_scope() option(optname) add_cxxtypes(types) add_defines(definition) @@ -47,6 +48,7 @@ function check_cxxtypes(definition, types, opt) add_cxxincludes(opt.includes) end option_end() + restore_scope() add_options(optname) end @@ -63,6 +65,7 @@ function configvar_check_cxxtypes(definition, types, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) + save_scope() option(optname) add_cxxtypes(types) if opt.default == nil then @@ -84,6 +87,7 @@ function configvar_check_cxxtypes(definition, types, opt) add_cxxincludes(opt.includes) end option_end() + restore_scope() if opt.default == nil then add_options(optname) else diff --git a/xmake/includes/check_features.lua b/xmake/includes/check_features.lua index 7c02be173..3e8fb47be 100644 --- a/xmake/includes/check_features.lua +++ b/xmake/includes/check_features.lua @@ -28,6 +28,7 @@ function check_features(definition, features, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) + save_scope() option(optname) add_features(features) add_defines(definition) @@ -44,6 +45,7 @@ function check_features(definition, features, opt) add_cxxflags(opt.cxxflags) end option_end() + restore_scope() add_options(optname) end @@ -59,6 +61,7 @@ function configvar_check_features(definition, features, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) + save_scope() option(optname) add_features(features) if opt.default == nil then @@ -77,6 +80,7 @@ function configvar_check_features(definition, features, opt) add_cxxflags(opt.cxxflags) end option_end() + restore_scope() if opt.default == nil then add_options(optname) else diff --git a/xmake/includes/check_links.lua b/xmake/includes/check_links.lua index 06b8cb38c..54891361e 100644 --- a/xmake/includes/check_links.lua +++ b/xmake/includes/check_links.lua @@ -28,10 +28,12 @@ function check_links(definition, links, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) + save_scope() option(optname) add_links(links) add_defines(definition) option_end() + restore_scope() add_options(optname) end @@ -47,12 +49,14 @@ function configvar_check_links(definition, links, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) + save_scope() option(optname) add_links(links) if opt.default == nil then set_configvar(defname, defval or 1, {quote = opt.quote}) end option_end() + restore_scope() if opt.default == nil then add_options(optname) else diff --git a/xmake/includes/check_macros.lua b/xmake/includes/check_macros.lua index ec4beddce..0ed879c95 100644 --- a/xmake/includes/check_macros.lua +++ b/xmake/includes/check_macros.lua @@ -30,6 +30,7 @@ function check_macros(definition, macros, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) local snippets = {} + save_scope() option(optname) for _, macro in ipairs(macros) do if macro:find(' ', 1, true) then @@ -67,6 +68,7 @@ function check_macros(definition, macros, opt) add_cxxflags(opt.cxxflags) end option_end() + restore_scope() add_options(optname) end @@ -81,6 +83,7 @@ function configvar_check_macros(definition, macros, opt) local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) local snippets = {} + save_scope() option(optname) for _, macro in ipairs(macros) do if macro:find(' ', 1, true) then @@ -120,6 +123,7 @@ function configvar_check_macros(definition, macros, opt) add_cxxflags(opt.cxxflags) end option_end() + restore_scope() if opt.default == nil then add_options(optname) else diff --git a/xmake/includes/check_syslinks.lua b/xmake/includes/check_syslinks.lua index 133e24dcd..8df32a1b8 100644 --- a/xmake/includes/check_syslinks.lua +++ b/xmake/includes/check_syslinks.lua @@ -28,10 +28,12 @@ function check_syslinks(definition, links, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) + save_scope() option(optname) add_syslinks(links) add_defines(definition) option_end() + restore_scope() add_options(optname) end @@ -47,12 +49,14 @@ function configvar_check_syslinks(definition, links, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) + save_scope() option(optname) add_syslinks(links) if opt.default == nil then set_configvar(defname, defval or 1, {quote = opt.quote}) end option_end() + restore_scope() if opt.default == nil then add_options(optname) else diff --git a/xmake/includes/find_and_add_packages.lua b/xmake/includes/find_and_add_packages.lua index 21aa2f783..4bcdd76f9 100644 --- a/xmake/includes/find_and_add_packages.lua +++ b/xmake/includes/find_and_add_packages.lua @@ -33,11 +33,13 @@ function find_and_add_packages(...) for _, name in ipairs({...}) do local optname = "__" .. name + save_scope() option(optname) before_check(function (option) option:add(find_packages(name)) end) option_end() + restore_scope() add_options(optname) end end diff --git a/xmake/languages/c++/load.lua b/xmake/languages/c++/load.lua index 12fb5283b..16380ab3c 100644 --- a/xmake/languages/c++/load.lua +++ b/xmake/languages/c++/load.lua @@ -68,7 +68,7 @@ function _api_add_cfunc(interp, module, alias, links, includes, func) end -- save the current scope - local scope = interp:scope_save() + interp:api_builtin_save_scope() -- check option interp:api_call("option", name) @@ -78,7 +78,7 @@ function _api_add_cfunc(interp, module, alias, links, includes, func) if includes then interp:api_call("add_cincludes", includes) end -- restore the current scope - interp:scope_restore(scope) + interp:api_builtin_restore_scope() -- add this option interp:api_call("add_options", name) @@ -120,7 +120,7 @@ function _api_add_cxxfunc(interp, module, alias, links, includes, func) end -- save the current scope - local scope = interp:scope_save() + interp:api_builtin_save_scope() -- check option interp:api_call("option", name) @@ -130,7 +130,7 @@ function _api_add_cxxfunc(interp, module, alias, links, includes, func) if includes then interp:api_call("add_cxxincludes", includes) end -- restore the current scope - interp:scope_restore(scope) + interp:api_builtin_restore_scope() -- add this option interp:api_call("add_options", name) -- cgit v1.3.1 From 828b2b5392a59bcc441b481cae4c48bf9682b3e1 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 2 Oct 2021 23:41:20 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b58b3c813..a21db49a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ * [#1694](https://github.com/xmake-io/xmake/issues/1694): Support to define a variable without quotes for configuration files * Support Android NDK r23 * Add `c++latest` and `clatest` for `set_languages` +* [#1720](https://github.com/xmake-io/xmake/issues/1720): Add `save_scope` and `restore_scope` to fix `check_xxx` apis ### Bugs fixed @@ -1107,6 +1108,7 @@ * [#1694](https://github.com/xmake-io/xmake/issues/1694): 支持在 set_configvar 中定义一个不带引号的字符串变量 * 改进对 Android NDK r23 的支持 * 为 `set_languages` 新增 `c++latest` 和 `clatest` 配置值 +* [#1720](https://github.com/xmake-io/xmake/issues/1720): 添加 `save_scope` 和 `restore_scope` 去修复 `check_xxx` 相关接口 ### Bugs 修复 -- cgit v1.3.1 From 2c8c745ba9caa35734a3b21fc91c694273a000bd Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 6 Oct 2021 00:46:56 +0800 Subject: improve install and uninstall --- xmake/modules/target/action/install/main.lua | 11 ++++------- xmake/modules/target/action/install/unix.lua | 5 +++++ xmake/modules/target/action/install/windows.lua | 5 +++++ xmake/modules/target/action/uninstall/unix.lua | 5 +++++ xmake/modules/target/action/uninstall/windows.lua | 5 +++++ 5 files changed, 24 insertions(+), 7 deletions(-) diff --git a/xmake/modules/target/action/install/main.lua b/xmake/modules/target/action/install/main.lua index 289d258f0..c115e836e 100644 --- a/xmake/modules/target/action/install/main.lua +++ b/xmake/modules/target/action/install/main.lua @@ -20,7 +20,6 @@ -- install files function _install_files(target) - local srcfiles, dstfiles = target:installfiles() if srcfiles and dstfiles then local i = 1 @@ -47,12 +46,10 @@ function main(target, opt) print("installing %s to %s ..", target:name(), installdir) -- call script - if not target:is_phony() then - local install_style = target:is_plat("windows", "mingw") and "windows" or "unix" - local script = import(install_style, {anonymous = true})["install_" .. target:kind()] - if script then - script(target, opt) - end + local install_style = target:is_plat("windows", "mingw") and "windows" or "unix" + local script = import(install_style, {anonymous = true})["install_" .. target:kind()] + if script then + script(target, opt) end -- install other files diff --git a/xmake/modules/target/action/install/unix.lua b/xmake/modules/target/action/install/unix.lua index 521ed40de..165d8650e 100644 --- a/xmake/modules/target/action/install/unix.lua +++ b/xmake/modules/target/action/install/unix.lua @@ -126,3 +126,8 @@ function install_static(target, opt) -- install headers _install_headers(target, opt) end + +-- install phony +function install_phony(target, opt) + _install_headers(target, opt) +end diff --git a/xmake/modules/target/action/install/windows.lua b/xmake/modules/target/action/install/windows.lua index 87a7413ca..448415fa6 100644 --- a/xmake/modules/target/action/install/windows.lua +++ b/xmake/modules/target/action/install/windows.lua @@ -134,3 +134,8 @@ function install_static(target, opt) -- install headers _install_headers(target, opt) end + +-- install phony +function install_phony(target, opt) + _install_headers(target, opt) +end diff --git a/xmake/modules/target/action/uninstall/unix.lua b/xmake/modules/target/action/uninstall/unix.lua index e13057fa1..614d59448 100644 --- a/xmake/modules/target/action/uninstall/unix.lua +++ b/xmake/modules/target/action/uninstall/unix.lua @@ -95,3 +95,8 @@ function uninstall_static(target, opt) -- remove headers from the include directory _uninstall_headers(target, opt) end + +-- uninstall phony +function uninstall_phony(target, opt) + _uninstall_headers(target, opt) +end diff --git a/xmake/modules/target/action/uninstall/windows.lua b/xmake/modules/target/action/uninstall/windows.lua index 2915966db..cb9dcf16e 100644 --- a/xmake/modules/target/action/uninstall/windows.lua +++ b/xmake/modules/target/action/uninstall/windows.lua @@ -100,3 +100,8 @@ function uninstall_static(target, opt) -- remove headers from the include directory _uninstall_headers(target, opt) end + +-- uninstall phony +function uninstall_phony(target, opt) + _uninstall_headers(target, opt) +end -- cgit v1.3.1 From d5fc35d2c3eb9ee451980e0cd1ba93cb78db6a91 Mon Sep 17 00:00:00 2001 From: 域外創音 Date: Wed, 6 Oct 2021 14:01:14 +0800 Subject: "vs_runtime=MD" -> "vs_runtime='MD'" --- xmake/modules/private/xrepo/action/env.lua | 2 +- xmake/modules/private/xrepo/action/export.lua | 2 +- xmake/modules/private/xrepo/action/fetch.lua | 2 +- xmake/modules/private/xrepo/action/import.lua | 2 +- xmake/modules/private/xrepo/action/info.lua | 2 +- xmake/modules/private/xrepo/action/install.lua | 2 +- xmake/modules/private/xrepo/action/remove.lua | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/xmake/modules/private/xrepo/action/env.lua b/xmake/modules/private/xrepo/action/env.lua index e092c6944..b29d01623 100644 --- a/xmake/modules/private/xrepo/action/env.lua +++ b/xmake/modules/private/xrepo/action/env.lua @@ -47,7 +47,7 @@ function menu_options() {nil, "show", "k", nil, "Only show environment information." }, {'f', "configs", "kv", nil, "Set the given extra package configs.", "e.g.", - " - xrepo env -f \"vs_runtime=MD\" zlib cmake ..", + " - xrepo env -f \"vs_runtime='MD'\" zlib cmake ..", " - xrepo env -f \"regex=true,thread=true\" \"zlib,boost\" cmake .."}, {'b', "packages", "kv", nil, "Set the packages to be bound", "e.g.", diff --git a/xmake/modules/private/xrepo/action/export.lua b/xmake/modules/private/xrepo/action/export.lua index 4c2e8c445..e6c4b3ffc 100644 --- a/xmake/modules/private/xrepo/action/export.lua +++ b/xmake/modules/private/xrepo/action/export.lua @@ -39,7 +39,7 @@ function menu_options() values = {"release", "debug"} }, {'f', "configs", "kv", nil, "Set the given extra package configs.", "e.g.", - " - xrepo export -f \"vs_runtime=MD\" zlib", + " - xrepo export -f \"vs_runtime='MD'\" zlib", " - xrepo export -f \"regex=true,thread=true\" boost"}, {}, {nil, "shallow", "k", nil, "Does not export dependent packages."}, diff --git a/xmake/modules/private/xrepo/action/fetch.lua b/xmake/modules/private/xrepo/action/fetch.lua index a577b7c14..57e56c71b 100644 --- a/xmake/modules/private/xrepo/action/fetch.lua +++ b/xmake/modules/private/xrepo/action/fetch.lua @@ -38,7 +38,7 @@ function menu_options() values = {"release", "debug"} }, {'f', "configs", "kv", nil, "Set the given extra package configs.", "e.g.", - " - xrepo fetch --configs=\"vs_runtime=MD\" zlib", + " - xrepo fetch --configs=\"vs_runtime='MD'\" zlib", " - xrepo fetch --configs=\"regex=true,thread=true\" boost"}, {}, {nil, "deps", "k", nil, "Fetch packages with dependencies." }, diff --git a/xmake/modules/private/xrepo/action/import.lua b/xmake/modules/private/xrepo/action/import.lua index e3805135d..fb7cb15ef 100644 --- a/xmake/modules/private/xrepo/action/import.lua +++ b/xmake/modules/private/xrepo/action/import.lua @@ -39,7 +39,7 @@ function menu_options() values = {"release", "debug"} }, {'f', "configs", "kv", nil, "Set the given extra package configs.", "e.g.", - " - xrepo import -f \"vs_runtime=MD\" zlib", + " - xrepo import -f \"vs_runtime='MD'\" zlib", " - xrepo import -f \"regex=true,thread=true\" boost"}, {}, {'i', "packagedir", "kv", "packages","Set the imported packages directory."}, diff --git a/xmake/modules/private/xrepo/action/info.lua b/xmake/modules/private/xrepo/action/info.lua index 3258397cf..4d570da19 100644 --- a/xmake/modules/private/xrepo/action/info.lua +++ b/xmake/modules/private/xrepo/action/info.lua @@ -38,7 +38,7 @@ function menu_options() values = {"release", "debug"} }, {'f', "configs", "kv", nil, "Set the given extra package configs.", "e.g.", - " - xrepo fetch --configs=\"vs_runtime=MD\" zlib", + " - xrepo fetch --configs=\"vs_runtime='MD'\" zlib", " - xrepo fetch --configs=\"regex=true,thread=true\" boost"}, {}, {nil, "packages", "vs", nil, "The packages list.", diff --git a/xmake/modules/private/xrepo/action/install.lua b/xmake/modules/private/xrepo/action/install.lua index f6f111185..e14d6701e 100644 --- a/xmake/modules/private/xrepo/action/install.lua +++ b/xmake/modules/private/xrepo/action/install.lua @@ -38,7 +38,7 @@ function menu_options() values = {"release", "debug"} }, {'f', "configs", "kv", nil, "Set the given extra package configs.", "e.g.", - " - xrepo install -f \"vs_runtime=MD\" zlib", + " - xrepo install -f \"vs_runtime='MD'\" zlib", " - xrepo install -f \"regex=true,thread=true\" boost"}, {'j', "jobs", "kv", tostring(os.default_njob()), "Set the number of parallel compilation jobs."}, diff --git a/xmake/modules/private/xrepo/action/remove.lua b/xmake/modules/private/xrepo/action/remove.lua index 7624fa9cf..c9fce0831 100644 --- a/xmake/modules/private/xrepo/action/remove.lua +++ b/xmake/modules/private/xrepo/action/remove.lua @@ -39,7 +39,7 @@ function menu_options() values = {"release", "debug"} }, {'f', "configs", "kv", nil, "Set the given extra package configs.", "e.g.", - " - xrepo remove -f \"vs_runtime=MD\" zlib", + " - xrepo remove -f \"vs_runtime='MD'\" zlib", " - xrepo remove -f \"regex=true,thread=true\" boost"}, {}, {nil, "all", "k", nil, "Remove all packages and ignore extra package configs.", -- cgit v1.3.1 From c360a739ba17f89f7f4d4f8ffbebc30576cd7dea Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 7 Oct 2021 00:47:50 +0800 Subject: improve make for tools/make/autoconf --- xmake/modules/detect/tools/find_make.lua | 53 ++++++++++++++++++++++++++++++++ xmake/modules/package/tools/autoconf.lua | 43 +++++++++++++++++++++----- xmake/modules/package/tools/make.lua | 39 ++++++++++++----------- 3 files changed, 109 insertions(+), 26 deletions(-) create mode 100644 xmake/modules/detect/tools/find_make.lua diff --git a/xmake/modules/detect/tools/find_make.lua b/xmake/modules/detect/tools/find_make.lua new file mode 100644 index 000000000..eb2957d63 --- /dev/null +++ b/xmake/modules/detect/tools/find_make.lua @@ -0,0 +1,53 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_make.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find make +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local make = find_make() +-- +-- @endcode +-- +function main(opt) + + -- find program + opt = opt or {} + local program = find_program(opt.program or (is_host("bsd") and "gmake" or "make"), opt) + if not program and not opt.program and is_subhost("msys", "cygwin") then + program = find_program("mingw32-make.exe", opt) + end + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, opt) + end + return program, version +end + diff --git a/xmake/modules/package/tools/autoconf.lua b/xmake/modules/package/tools/autoconf.lua index b0607ac0d..f06a18bb0 100644 --- a/xmake/modules/package/tools/autoconf.lua +++ b/xmake/modules/package/tools/autoconf.lua @@ -23,6 +23,7 @@ import("core.base.option") import("core.project.config") import("core.tool.linker") import("core.tool.compiler") +import("lib.detect.find_tool") -- translate path function _translate_path(package, p) @@ -296,8 +297,25 @@ function configure(package, configs, opt) os.vrunv("sh", argv, {envs = envs}) end --- install package -function install(package, configs, opt) +-- do make +function make(package, argv, opt) + opt = opt or {} + local program + if package:is_plat("mingw") and is_subhost("windows") then + local mingw = assert(package:build_getenv("mingw") or package:build_getenv("sdk"), "mingw not found!") + program = path.join(mingw, "bin", "mingw32-make.exe") + else + local tool = find_tool("make") + if tool then + program = tool.program + end + end + assert(program, "make not found!") + os.vrunv(program, argv) +end + +-- build package +function build(package, configs, opt) -- do configure configure(package, configs, opt) @@ -309,12 +327,21 @@ function install(package, configs, opt) if option.get("verbose") then table.insert(argv, "V=1") end - if is_host("bsd") then - os.vrunv("gmake", argv) - os.vrun("gmake install") - else - os.vrunv("make", argv) - os.vrun("make install") + make(package, argv, opt) +end + +-- install package +function install(package, configs, opt) + + -- do build + opt = opt or {} + build(package, configs, opt) + + -- do install + local argv = {"install"} + if option.get("verbose") then + table.insert(argv, "V=1") end + make(package, argv, opt) end diff --git a/xmake/modules/package/tools/make.lua b/xmake/modules/package/tools/make.lua index a40cd57c1..af5f977fa 100644 --- a/xmake/modules/package/tools/make.lua +++ b/xmake/modules/package/tools/make.lua @@ -21,6 +21,7 @@ -- imports import("core.base.option") import("core.project.config") +import("lib.detect.find_tool") -- get the build environments function buildenvs(package) @@ -84,6 +85,24 @@ function buildenvs(package) return envs end +-- do make +function make(package, argv, opt) + opt = opt or {} + local program + local runenvs = opt.envs or buildenvs(package) + if package:is_plat("mingw") and is_subhost("windows") then + local mingw = assert(package:build_getenv("mingw") or package:build_getenv("sdk"), "mingw not found!") + program = path.join(mingw, "bin", "mingw32-make.exe") + else + local tool = find_tool("make", {envs = runenvs}) + if tool then + program = tool.program + end + end + assert(program, "make not found!") + os.vrunv(program, argv, {envs = runenvs}) +end + -- build package function build(package, configs, opt) @@ -108,15 +127,7 @@ function build(package, configs, opt) end -- do build - if is_host("bsd") then - os.vrunv("gmake", argv, {envs = opt.envs or buildenvs(package)}) - elseif package:is_plat("mingw") and is_subhost("windows") then - local mingw = assert(package:build_getenv("mingw") or package:build_getenv("sdk"), "mingw not found!") - local make = path.join(mingw, "bin", "mingw32-make.exe") - os.vrunv(make, argv, {envs = opt.envs or buildenvs(package)}) - else - os.vrunv("make", argv, {envs = opt.envs or buildenvs(package)}) - end + make(package, argv, opt) end -- install package @@ -131,13 +142,5 @@ function install(package, configs, opt) if option.get("verbose") then table.insert(argv, "VERBOSE=1") end - if is_host("bsd") then - os.vrunv("gmake", argv, {envs = opt.envs or buildenvs(package)}) - elseif package:is_plat("mingw") and is_subhost("windows") then - local mingw = assert(package:build_getenv("mingw") or package:build_getenv("sdk"), "mingw not found!") - local make = path.join(mingw, "bin", "mingw32-make.exe") - os.vrunv(make, argv, {envs = opt.envs or buildenvs(package)}) - else - os.vrunv("make", argv, {envs = opt.envs or buildenvs(package)}) - end + make(package, argv, opt) end -- cgit v1.3.1 From bf5cbeff9d3b65ad60789ef2119acc0b017f5fb9 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 7 Oct 2021 00:52:53 +0800 Subject: improve compile_commands --- xmake/modules/core/tools/nvcc.lua | 4 ++-- xmake/plugins/project/clang/compile_commands.lua | 23 +++++++++++++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/xmake/modules/core/tools/nvcc.lua b/xmake/modules/core/tools/nvcc.lua index d03a10865..25a589124 100644 --- a/xmake/modules/core/tools/nvcc.lua +++ b/xmake/modules/core/tools/nvcc.lua @@ -212,7 +212,7 @@ end -- make the includedir flag function nf_includedir(self, dir) - return {"-I", dir} + return {"-I" .. path.translate(dir)} end -- make the sysincludedir flag @@ -232,7 +232,7 @@ end -- make the linkdir flag function nf_linkdir(self, dir) - return {"-L", dir} + return {"-L" .. path.translate(dir)} end -- make the rpathdir flag diff --git a/xmake/plugins/project/clang/compile_commands.lua b/xmake/plugins/project/clang/compile_commands.lua index 085d230ae..a3f893d90 100644 --- a/xmake/plugins/project/clang/compile_commands.lua +++ b/xmake/plugins/project/clang/compile_commands.lua @@ -34,7 +34,8 @@ end -- https://github.com/xmake-io/xmake/issues/1050 function _translate_arguments(arguments) local args = {} - local is_msvc = path.basename(arguments[1]):lower() == "cl" + local cc = path.basename(arguments[1]):lower() + local is_include = false for idx, arg in ipairs(arguments) do -- see https://github.com/xmake-io/xmake/issues/1721 if idx == 1 and is_host("windows") and path.extension(arg) == "" then @@ -53,8 +54,26 @@ function _translate_arguments(arguments) end -- @see use msvc-style flags for msvc to support language-server better -- https://github.com/xmake-io/xmake/issues/1284 - if is_msvc and arg and arg:startswith("-") then + if cc == "cl" and arg and arg:startswith("-") then arg = arg:gsub("^%-", "/") + elseif cc == "nvcc" and arg then + -- support -I path with spaces for nvcc + -- https://github.com/xmake-io/xmake/issues/1726 + if is_include then + if arg and arg:find(' ', 1, true) then + arg = "\"" .. arg .. "\"" + end + is_include = false + elseif arg:startswith("-I") then + local f = arg:sub(1, 2) + local v = arg:sub(3) + if v and v:find(' ', 1, true) then + arg = f .. "\"" .. v .. "\"" + end + end + end + if arg == "-I" then + is_include = true end if arg then table.insert(args, arg) -- cgit v1.3.1 From baddd3397896673c9bdadf7f2da57370ed92ca4a Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 7 Oct 2021 00:53:01 +0800 Subject: improve freebsd ci --- .github/workflows/freebsd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/freebsd.yml b/.github/workflows/freebsd.yml index 43de28c51..42871147f 100644 --- a/.github/workflows/freebsd.yml +++ b/.github/workflows/freebsd.yml @@ -20,7 +20,7 @@ jobs: submodules: true - name: Tests - uses: vmactions/freebsd-vm@v0.1.3 + uses: vmactions/freebsd-vm@v0.1.5 with: usesh: true mem: 4096 -- cgit v1.3.1 From e2847cef98032016e4d8d71ce79a7cab434478e8 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 7 Oct 2021 00:53:20 +0800 Subject: update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a21db49a0..61e2fe137 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,6 @@ * [#1715](https://github.com/xmake-io/xmake/issues/1715): Support to detect compiler language standards as features and add `check_macros` * Support Loongarch - ### Change * [#1618](https://github.com/xmake-io/xmake/issues/1618): Improve vala to support to generate libraries and bindings @@ -24,6 +23,7 @@ * Support Android NDK r23 * Add `c++latest` and `clatest` for `set_languages` * [#1720](https://github.com/xmake-io/xmake/issues/1720): Add `save_scope` and `restore_scope` to fix `check_xxx` apis +* [#1726](https://github.com/xmake-io/xmake/issues/1726): Improve compile_commands generator to support nvcc ### Bugs fixed @@ -1109,6 +1109,7 @@ * 改进对 Android NDK r23 的支持 * 为 `set_languages` 新增 `c++latest` 和 `clatest` 配置值 * [#1720](https://github.com/xmake-io/xmake/issues/1720): 添加 `save_scope` 和 `restore_scope` 去修复 `check_xxx` 相关接口 +* [#1726](https://github.com/xmake-io/xmake/issues/1726): 改进 compile_commands 生成器去支持 nvcc ### Bugs 修复 -- cgit v1.3.1 From 02b4fcdadedc04df481c13185b35252ca4d98165 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 7 Oct 2021 00:55:32 +0800 Subject: fix freebsd ci --- .github/workflows/freebsd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/freebsd.yml b/.github/workflows/freebsd.yml index 42871147f..38eb93e22 100644 --- a/.github/workflows/freebsd.yml +++ b/.github/workflows/freebsd.yml @@ -9,7 +9,7 @@ on: jobs: build: - runs-on: macos-latest + runs-on: macos-10.15 concurrency: group: ${{ github.head_ref }}-FreeBSD -- cgit v1.3.1 From 4d37ba57eeff1e86b0546e422ddd51492cf75dad Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 8 Oct 2021 22:38:13 +0800 Subject: switch to luajit in this version --- .github/workflows/windows_lua.yml | 122 +++++++++++++++++++++++++++++++++++ .github/workflows/windows_luajit.yml | 122 ----------------------------------- core/xmake.lua | 2 +- 3 files changed, 123 insertions(+), 123 deletions(-) create mode 100644 .github/workflows/windows_lua.yml delete mode 100644 .github/workflows/windows_luajit.yml diff --git a/.github/workflows/windows_lua.yml b/.github/workflows/windows_lua.yml new file mode 100644 index 000000000..3ad8ebf74 --- /dev/null +++ b/.github/workflows/windows_lua.yml @@ -0,0 +1,122 @@ +name: Windows (Luajit) + +on: + pull_request: + push: + release: + types: [published] + +jobs: + build: + strategy: + matrix: + os: [windows-latest, windows-2016] + arch: [x64, x86] + + runs-on: ${{ matrix.os }} + + concurrency: + group: ${{ github.head_ref }}-${{ matrix.os }}-${{ matrix.arch }}-Windows-Luajit + cancel-in-progress: true + steps: + - uses: actions/checkout@v2 + with: + # WyriHaximus/github-action-get-previous-tag@master need it + fetch-depth: 0 + submodules: true + - uses: xmake-io/github-action-setup-xmake@v1 + with: + # this is not supported, use dev branch instead + # xmake-version: local# + xmake-version: branch@dev + - uses: dlang-community/setup-dlang@v1 + with: + compiler: dmd-latest + - uses: little-core-labs/get-git-tag@v3.0.2 + id: tagName + + - name: Prepare + run: | + xmake show + Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/nsis-3.04.zip" -UseBasicParsing -OutFile ./nsis.zip + Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/nsis-3.04-strlen_8192.zip" -UseBasicParsing -OutFile ./nsis-longstr.zip + Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/UAC.zip" -UseBasicParsing -OutFile ./nsis-uac.zip + Expand-Archive ./nsis.zip -DestinationPath ./nsis + Move-Item ./nsis/*/* ./nsis + Expand-Archive ./nsis-longstr.zip -DestinationPath ./nsis -Force + Expand-Archive ./nsis-uac.zip -DestinationPath ./nsis -Force + Move-Item ./nsis/UAC.nsh ./nsis/Include/ + + - name: Build + run: | + xmake f -vD -P core -a ${{ matrix.arch }} --runtime=lua + xmake -vD -P core + + - name: Tests + run: | + Copy-Item ./core/build/xmake.exe ./xmake + Copy-Item ./scripts/xrepo.bat ./xmake + Copy-Item ./scripts/xrepo.ps1 ./xmake + $Env:XMAKE_PROGRAM_DIR = $(Resolve-Path ./xmake) + Set-Item -Path Env:Path -Value ($Env:XMAKE_PROGRAM_DIR + ";" + $Env:Path) + xrepo --version + xmake show + #xmake l -v private.utils.bcsave --rootname='@programdir' -x 'scripts/**|templates/**' xmake + xmake lua -v -D tests/run.lua + + - name: Set release arch name + run: | + if ("${{ matrix.arch }}" -eq "x64") { + Write-Output "RELEASE_NAME=win64" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf-8 -Append + } else { + Write-Output "RELEASE_NAME=win32" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf-8 -Append + } + - name: Artifact + run: | + # build installer + (New-Item ./winenv/bin -ItemType Directory).FullName + Invoke-WebRequest "https://github.com/xmake-mirror/7zip/releases/download/19.00/7z19.00-${{ matrix.arch }}.zip" -UseBasicParsing -OutFile .\7zip.zip + Expand-Archive ./7zip.zip -DestinationPath ./7zip + Copy-Item ./7zip/7z.exe ./winenv/bin + Copy-Item ./7zip/7z.dll ./winenv/bin + Invoke-WebRequest "https://curl.se/windows/dl-7.78.0_2/curl-7.78.0_2-win32-mingw.zip" -UseBasicParsing -OutFile .\curl.zip + Expand-Archive ./curl.zip -DestinationPath ./curl + Copy-Item ./curl/curl-7.78.0-win32-mingw/bin/curl.exe ./winenv/bin + Copy-Item ./curl/curl-7.78.0-win32-mingw/bin/curl-ca-bundle.crt ./winenv/bin + $version = (Get-Command xmake/xmake.exe).FileVersionInfo + ./nsis/makensis.exe /DMAJOR=$($version.ProductMajorPart) /DMINOR=$($version.ProductMinorPart) /DALTER=$($version.ProductBuildPart) /DBUILD=$($($version.ProductVersion -split '\+')[1]) /D${{ matrix.arch }} .\scripts\installer.nsi + (New-Item ./artifacts/${{env.RELEASE_NAME}} -ItemType Directory).FullName + Copy-Item scripts/xmake.exe ./artifacts/${{env.RELEASE_NAME}}/xmake.exe + # archive + Copy-Item ./*.md ./xmake + Copy-Item ./winenv ./xmake -Recurse + Add-Type -AssemblyName System.Text.Encoding + Add-Type -AssemblyName System.IO.Compression.FileSystem + class FixedEncoder : System.Text.UTF8Encoding { + FixedEncoder() : base($true) { } + [byte[]] GetBytes([string] $s) + { + $s = $s.Replace("\", "/") + return ([System.Text.UTF8Encoding]$this).GetBytes($s) + } + } + Copy-Item ./xmake ./archive/xmake -Recurse + [System.IO.Compression.ZipFile]::CreateFromDirectory("$PWD\archive", "$PWD\archive.zip", [System.IO.Compression.CompressionLevel]::Optimal, $false, [FixedEncoder]::new()) + (Get-FileHash .\archive.zip -Algorithm SHA256).Hash.ToLower() + " *xmake.zip`n" | Out-File ./shafile -Encoding ASCII -NoNewLine -Append + Copy-Item archive.zip ./artifacts/${{env.RELEASE_NAME}} + Copy-Item shafile ./artifacts/${{env.RELEASE_NAME}} + + # upload artifacts + - uses: actions/upload-artifact@v2 + with: + name: xmake-latest.${{env.RELEASE_NAME}}.exe + path: artifacts/${{env.RELEASE_NAME}}/xmake.exe + - uses: actions/upload-artifact@v2 + with: + name: xmake-latest.${{ env.RELEASE_NAME }}.zip + path: artifacts/${{env.RELEASE_NAME}}/archive.zip + - uses: actions/upload-artifact@v2 + with: + name: xmake-latest.${{ env.RELEASE_NAME }}.sha256 + path: artifacts/${{env.RELEASE_NAME}}/shafile + diff --git a/.github/workflows/windows_luajit.yml b/.github/workflows/windows_luajit.yml deleted file mode 100644 index 3b2115beb..000000000 --- a/.github/workflows/windows_luajit.yml +++ /dev/null @@ -1,122 +0,0 @@ -name: Windows (Luajit) - -on: - pull_request: - push: - release: - types: [published] - -jobs: - build: - strategy: - matrix: - os: [windows-latest, windows-2016] - arch: [x64, x86] - - runs-on: ${{ matrix.os }} - - concurrency: - group: ${{ github.head_ref }}-${{ matrix.os }}-${{ matrix.arch }}-Windows-Luajit - cancel-in-progress: true - steps: - - uses: actions/checkout@v2 - with: - # WyriHaximus/github-action-get-previous-tag@master need it - fetch-depth: 0 - submodules: true - - uses: xmake-io/github-action-setup-xmake@v1 - with: - # this is not supported, use dev branch instead - # xmake-version: local# - xmake-version: branch@dev - - uses: dlang-community/setup-dlang@v1 - with: - compiler: dmd-latest - - uses: little-core-labs/get-git-tag@v3.0.2 - id: tagName - - - name: Prepare - run: | - xmake show - Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/nsis-3.04.zip" -UseBasicParsing -OutFile ./nsis.zip - Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/nsis-3.04-strlen_8192.zip" -UseBasicParsing -OutFile ./nsis-longstr.zip - Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/UAC.zip" -UseBasicParsing -OutFile ./nsis-uac.zip - Expand-Archive ./nsis.zip -DestinationPath ./nsis - Move-Item ./nsis/*/* ./nsis - Expand-Archive ./nsis-longstr.zip -DestinationPath ./nsis -Force - Expand-Archive ./nsis-uac.zip -DestinationPath ./nsis -Force - Move-Item ./nsis/UAC.nsh ./nsis/Include/ - - - name: Build - run: | - xmake f -vD -P core -a ${{ matrix.arch }} --runtime=luajit - xmake -vD -P core - - - name: Tests - run: | - Copy-Item ./core/build/xmake.exe ./xmake - Copy-Item ./scripts/xrepo.bat ./xmake - Copy-Item ./scripts/xrepo.ps1 ./xmake - $Env:XMAKE_PROGRAM_DIR = $(Resolve-Path ./xmake) - Set-Item -Path Env:Path -Value ($Env:XMAKE_PROGRAM_DIR + ";" + $Env:Path) - xrepo --version - xmake show - #xmake l -v private.utils.bcsave --rootname='@programdir' -x 'scripts/**|templates/**' xmake - xmake lua -v -D tests/run.lua - - - name: Set release arch name - run: | - if ("${{ matrix.arch }}" -eq "x64") { - Write-Output "RELEASE_NAME=win64" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf-8 -Append - } else { - Write-Output "RELEASE_NAME=win32" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf-8 -Append - } - - name: Artifact - run: | - # build installer - (New-Item ./winenv/bin -ItemType Directory).FullName - Invoke-WebRequest "https://github.com/xmake-mirror/7zip/releases/download/19.00/7z19.00-${{ matrix.arch }}.zip" -UseBasicParsing -OutFile .\7zip.zip - Expand-Archive ./7zip.zip -DestinationPath ./7zip - Copy-Item ./7zip/7z.exe ./winenv/bin - Copy-Item ./7zip/7z.dll ./winenv/bin - Invoke-WebRequest "https://curl.se/windows/dl-7.78.0_2/curl-7.78.0_2-win32-mingw.zip" -UseBasicParsing -OutFile .\curl.zip - Expand-Archive ./curl.zip -DestinationPath ./curl - Copy-Item ./curl/curl-7.78.0-win32-mingw/bin/curl.exe ./winenv/bin - Copy-Item ./curl/curl-7.78.0-win32-mingw/bin/curl-ca-bundle.crt ./winenv/bin - $version = (Get-Command xmake/xmake.exe).FileVersionInfo - ./nsis/makensis.exe /DMAJOR=$($version.ProductMajorPart) /DMINOR=$($version.ProductMinorPart) /DALTER=$($version.ProductBuildPart) /DBUILD=$($($version.ProductVersion -split '\+')[1]) /D${{ matrix.arch }} .\scripts\installer.nsi - (New-Item ./artifacts/${{env.RELEASE_NAME}} -ItemType Directory).FullName - Copy-Item scripts/xmake.exe ./artifacts/${{env.RELEASE_NAME}}/xmake.exe - # archive - Copy-Item ./*.md ./xmake - Copy-Item ./winenv ./xmake -Recurse - Add-Type -AssemblyName System.Text.Encoding - Add-Type -AssemblyName System.IO.Compression.FileSystem - class FixedEncoder : System.Text.UTF8Encoding { - FixedEncoder() : base($true) { } - [byte[]] GetBytes([string] $s) - { - $s = $s.Replace("\", "/") - return ([System.Text.UTF8Encoding]$this).GetBytes($s) - } - } - Copy-Item ./xmake ./archive/xmake -Recurse - [System.IO.Compression.ZipFile]::CreateFromDirectory("$PWD\archive", "$PWD\archive.zip", [System.IO.Compression.CompressionLevel]::Optimal, $false, [FixedEncoder]::new()) - (Get-FileHash .\archive.zip -Algorithm SHA256).Hash.ToLower() + " *xmake.zip`n" | Out-File ./shafile -Encoding ASCII -NoNewLine -Append - Copy-Item archive.zip ./artifacts/${{env.RELEASE_NAME}} - Copy-Item shafile ./artifacts/${{env.RELEASE_NAME}} - - # upload artifacts - - uses: actions/upload-artifact@v2 - with: - name: xmake-latest.${{env.RELEASE_NAME}}.exe - path: artifacts/${{env.RELEASE_NAME}}/xmake.exe - - uses: actions/upload-artifact@v2 - with: - name: xmake-latest.${{ env.RELEASE_NAME }}.zip - path: artifacts/${{env.RELEASE_NAME}}/archive.zip - - uses: actions/upload-artifact@v2 - with: - name: xmake-latest.${{ env.RELEASE_NAME }}.sha256 - path: artifacts/${{env.RELEASE_NAME}}/shafile - diff --git a/core/xmake.lua b/core/xmake.lua index a9108c487..71253d8ae 100644 --- a/core/xmake.lua +++ b/core/xmake.lua @@ -43,7 +43,7 @@ end -- the runtime option option("runtime") set_showmenu(true) - set_default("lua") + set_default("luajit") set_description("Use luajit or lua runtime") set_values("luajit", "lua") option_end() -- cgit v1.3.1 From c8208e5fe715ae140aff4bfc91d8ea1dbcaf9fad Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 8 Oct 2021 22:38:59 +0800 Subject: update spec --- scripts/rpmbuild/SPECS/xmake.spec | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/scripts/rpmbuild/SPECS/xmake.spec b/scripts/rpmbuild/SPECS/xmake.spec index a20b91ee9..17939bad5 100644 --- a/scripts/rpmbuild/SPECS/xmake.spec +++ b/scripts/rpmbuild/SPECS/xmake.spec @@ -1,8 +1,9 @@ %define xmake_revision c022587f0c32859b74f6fa16c7a3e16094bbbd7c -%define tbox_revision 5ef932750ede0b90867fd4afdcf1deed2464c82b +%define tbox_revision 7ca5145d40aa906fdc48b0b0e75e80412241be7e %define sv_revision 9a3cf7c8e589de4f70378824329882c4a047fffc %define lua_cjson_revision 515bab6d6d80b164b94db73af69609ea02f3a798 %define luajit_revision e9af1abec542e6f9851ff2368e7f196b6382a44c +%define lua_revision 75ea9ccbea7c4886f30da147fb67b693b2624c26 %define _binaries_in_noarch_packages_terminate_build 0 %undefine _disable_source_fetch @@ -15,9 +16,10 @@ License: ASL 2.0 URL: https://xmake.io Source0: https://github.com/xmake-io/xmake/archive/%{xmake_revision}.tar.gz#/xmake-%{xmake_revision}.tar.gz Source1: https://github.com/tboox/tbox/archive/%{tbox_revision}.tar.gz#/tbox-%{tbox_revision}.tar.gz -Source2: https://github.com/xmake-io/xmake-core-luajit/archive/%{luajit_revision}.tar.gz#/xmake-core-luajit-%{luajit_revision}.tar.gz -Source3: https://github.com/xmake-io/xmake-core-sv/archive/%{sv_revision}.tar.gz#/xmake-core-sv-%{sv_revision}.tar.gz -Source4: https://github.com/xmake-io/xmake-core-lua-cjson/archive/%{lua_cjson_revision}.tar.gz#/xmake-core-lua-cjson-%{lua_cjson_revision}.tar.gz +Source2: https://github.com/xmake-io/xmake-core-lua/archive/%{lua_revision}.tar.gz#/xmake-core-lua-%{lua_revision}.tar.gz +Source3: https://github.com/xmake-io/xmake-core-luajit/archive/%{luajit_revision}.tar.gz#/xmake-core-luajit-%{luajit_revision}.tar.gz +Source4: https://github.com/xmake-io/xmake-core-sv/archive/%{sv_revision}.tar.gz#/xmake-core-sv-%{sv_revision}.tar.gz +Source5: https://github.com/xmake-io/xmake-core-lua-cjson/archive/%{lua_cjson_revision}.tar.gz#/xmake-core-lua-cjson-%{lua_cjson_revision}.tar.gz BuildRequires: gcc-c++ BuildRequires: ncurses-devel @@ -38,19 +40,23 @@ system to help users solve the integrated use of C/C++ dependent libraries. %prep %setup -q -T -b 1 -n tbox-%{tbox_revision} cd .. -%setup -q -T -b 2 -n xmake-core-luajit-%{luajit_revision} +%setup -q -T -b 2 -n xmake-core-lua-%{lua_revision} cd .. -%setup -q -T -b 3 -n xmake-core-sv-%{sv_revision} +%setup -q -T -b 3 -n xmake-core-luajit-%{luajit_revision} cd .. -%setup -q -T -b 4 -n xmake-core-lua-cjson-%{lua_cjson_revision} +%setup -q -T -b 4 -n xmake-core-sv-%{sv_revision} +cd .. +%setup -q -T -b 5 -n xmake-core-lua-cjson-%{lua_cjson_revision} cd .. %setup -q -T -b 0 -n xmake-%{xmake_revision} rm -rf core/src/sv/sv rm -rf core/src/tbox/tbox +rm -rf core/src/lua/lua rm -rf core/src/luajit/luajit rm -rf core/src/lua-cjson/lua-cjson ln -s `pwd`/../tbox-%{tbox_revision} core/src/tbox/tbox ln -s `pwd`/../xmake-core-sv-%{sv_revision} core/src/sv/sv +ln -s `pwd`/../xmake-core-lua-%{lua_revision} core/src/lua/lua ln -s `pwd`/../xmake-core-luajit-%{luajit_revision} core/src/luajit/luajit ln -s `pwd`/../xmake-core-lua-cjson-%{lua_cjson_revision} core/src/lua-cjson/lua-cjson -- cgit v1.3.1 From 703d5a016e2c1881990fc34e2e989b28e7673aa2 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 9 Oct 2021 00:48:03 +0800 Subject: update version --- core/project.mak | 2 +- core/xmake.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/project.mak b/core/project.mak index adf613ef2..02bdcd9d9 100644 --- a/core/project.mak +++ b/core/project.mak @@ -10,7 +10,7 @@ PRO_VERSION_MAJOR = 2 PRO_VERSION_MINOR = 5 # the project alter version -PRO_VERSION_ALTER = 7 +PRO_VERSION_ALTER = 8 # the project prefix PRO_PREFIX = XM_ diff --git a/core/xmake.lua b/core/xmake.lua index 71253d8ae..cb4b41daf 100644 --- a/core/xmake.lua +++ b/core/xmake.lua @@ -2,7 +2,7 @@ set_project("xmake") -- version -set_version("2.5.7", {build = "%Y%m%d%H%M"}) +set_version("2.5.8", {build = "%Y%m%d%H%M"}) -- set xmake min version set_xmakever("2.2.3") -- cgit v1.3.1 From f00a152d2cd5238a74699394e0f396654cbf421e Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 9 Oct 2021 00:48:10 +0800 Subject: update spec --- CHANGELOG.md | 4 ++++ scripts/rpmbuild/SPECS/xmake.spec | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61e2fe137..2d6b88ccd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## master (unreleased) +## v2.5.8 + ### New features * [#388](https://github.com/xmake-io/xmake/issues/388): Pascal Language Support @@ -1088,6 +1090,8 @@ ## master (开发中) +## v2.5.8 + ### 新特性 * [#388](https://github.com/xmake-io/xmake/issues/388): Pascal 语言支持,可以使用 fpc 来编译 free pascal diff --git a/scripts/rpmbuild/SPECS/xmake.spec b/scripts/rpmbuild/SPECS/xmake.spec index 17939bad5..cbc0e928a 100644 --- a/scripts/rpmbuild/SPECS/xmake.spec +++ b/scripts/rpmbuild/SPECS/xmake.spec @@ -1,4 +1,4 @@ -%define xmake_revision c022587f0c32859b74f6fa16c7a3e16094bbbd7c +%define xmake_revision 703d5a016e2c1881990fc34e2e989b28e7673aa2 %define tbox_revision 7ca5145d40aa906fdc48b0b0e75e80412241be7e %define sv_revision 9a3cf7c8e589de4f70378824329882c4a047fffc %define lua_cjson_revision 515bab6d6d80b164b94db73af69609ea02f3a798 -- cgit v1.3.1 From 59498b047190411a144f821a5cc40174faeaaa9a Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 9 Oct 2021 11:07:39 +0800 Subject: improve interpreter --- xmake/core/base/interpreter.lua | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/xmake/core/base/interpreter.lua b/xmake/core/base/interpreter.lua index 9a0416c52..32602c4c4 100644 --- a/xmake/core/base/interpreter.lua +++ b/xmake/core/base/interpreter.lua @@ -491,16 +491,19 @@ function interpreter:_handle(scope, remove_repeat, enable_filter) local results = {} for name, values in pairs(scope) do - -- remove repeat first for each slice with deleted item (__del_xxx) - if remove_repeat and not table.is_dictionary(values) then - values = table.unique(values, function (v) return type(v) == "string" and v:startswith("__del_") end) - end - -- filter values + -- + -- @note we need do filter before removing repeat values + -- https://github.com/xmake-io/xmake/issues/1732 if enable_filter then values = self:_filter(values) end + -- remove repeat first for each slice with deleted item (__del_xxx) + if remove_repeat and not table.is_dictionary(values) then + values = table.unique(values, function (v) return type(v) == "string" and v:startswith("__del_") end) + end + -- unwrap it if be only one values = table.unwrap(values) -- cgit v1.3.1 From a01e17a5049bdd02ddc2514bd47af74cf2ff802d Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 9 Oct 2021 11:58:10 +0800 Subject: move private.utils.progress to utils.progress --- tests/apis/rules/xmake.lua | 2 +- xmake/actions/build/build.lua | 2 +- xmake/actions/build/kinds/binary.lua | 2 +- xmake/actions/build/kinds/shared.lua | 2 +- xmake/actions/build/kinds/static.lua | 2 +- xmake/actions/build/main.lua | 2 +- xmake/modules/core/tools/ar.lua | 2 +- xmake/modules/core/tools/cl.lua | 2 +- xmake/modules/core/tools/gcc.lua | 2 +- xmake/modules/core/tools/nvcc.lua | 2 +- xmake/modules/core/tools/sdcc.lua | 2 +- xmake/modules/private/action/build/object.lua | 2 +- .../action/require/impl/install_packages.lua | 2 +- .../private/action/require/impl/package.lua | 2 +- xmake/modules/private/async/runjobs.lua | 4 +- xmake/modules/private/utils/batchcmds.lua | 2 +- xmake/modules/utils/progress.lua | 139 +++++++++++++++++++++ xmake/rules/cuda/devlink/xmake.lua | 2 +- xmake/rules/qt/deploy/android.lua | 2 +- xmake/rules/qt/deploy/macosx.lua | 2 +- xmake/rules/utils/merge_archive/merge_archive.lua | 2 +- xmake/rules/utils/merge_archive/xmake.lua | 2 +- xmake/rules/utils/merge_object/xmake.lua | 2 +- .../rules/utils/symbols/export_all/export_all.lua | 2 +- xmake/rules/utils/symbols/extract/xmake.lua | 2 +- xmake/rules/wdk/inf/xmake.lua | 2 +- xmake/rules/wdk/man/xmake.lua | 2 +- xmake/rules/wdk/mc/xmake.lua | 2 +- xmake/rules/wdk/mof/xmake.lua | 2 +- xmake/rules/wdk/sign/xmake.lua | 2 +- xmake/rules/wdk/tracewpp/xmake.lua | 2 +- xmake/rules/xcode/application/build.lua | 2 +- xmake/rules/xcode/bundle/xmake.lua | 2 +- xmake/rules/xcode/framework/xmake.lua | 2 +- xmake/rules/xcode/info_plist/xmake.lua | 2 +- xmake/rules/xcode/storyboard/xmake.lua | 2 +- xmake/rules/xcode/xcassets/xmake.lua | 2 +- 37 files changed, 176 insertions(+), 37 deletions(-) create mode 100644 xmake/modules/utils/progress.lua diff --git a/tests/apis/rules/xmake.lua b/tests/apis/rules/xmake.lua index 276b4c074..5a6e5d546 100644 --- a/tests/apis/rules/xmake.lua +++ b/tests/apis/rules/xmake.lua @@ -27,7 +27,7 @@ rule("c code") end) on_build_file(function (target, sourcefile, opt) import("core.theme.theme") - import("private.utils.progress") + import("utils.progress") progress.show(opt.progress, "compiling.$(mode) %s", sourcefile) local objectfile_o = os.tmpfile() .. ".o" local sourcefile_c = os.tmpfile() .. ".c" diff --git a/xmake/actions/build/build.lua b/xmake/actions/build/build.lua index 0fc15fd81..267a802d3 100644 --- a/xmake/actions/build/build.lua +++ b/xmake/actions/build/build.lua @@ -218,7 +218,7 @@ function main(targetname) if batchjobs and batchjobs:size() > 0 then local curdir = os.curdir() runjobs("build", batchjobs, {comax = option.get("jobs") or 1, on_exit = function (errors) - import("private.utils.progress") + import("utils.progress") if errors and progress.showing_without_scroll() then print("") end diff --git a/xmake/actions/build/kinds/binary.lua b/xmake/actions/build/kinds/binary.lua index b84b518de..26544c311 100644 --- a/xmake/actions/build/kinds/binary.lua +++ b/xmake/actions/build/kinds/binary.lua @@ -24,7 +24,7 @@ import("core.theme.theme") import("core.tool.linker") import("core.tool.compiler") import("core.project.depend") -import("private.utils.progress") +import("utils.progress") import("private.utils.batchcmds") import("object", {alias = "add_batchjobs_for_object"}) diff --git a/xmake/actions/build/kinds/shared.lua b/xmake/actions/build/kinds/shared.lua index 376d73af3..99a6d1db5 100644 --- a/xmake/actions/build/kinds/shared.lua +++ b/xmake/actions/build/kinds/shared.lua @@ -24,7 +24,7 @@ import("core.theme.theme") import("core.tool.linker") import("core.tool.compiler") import("core.project.depend") -import("private.utils.progress") +import("utils.progress") import("private.utils.batchcmds") import("object", {alias = "add_batchjobs_for_object"}) diff --git a/xmake/actions/build/kinds/static.lua b/xmake/actions/build/kinds/static.lua index b3ac57e73..56a900572 100644 --- a/xmake/actions/build/kinds/static.lua +++ b/xmake/actions/build/kinds/static.lua @@ -24,7 +24,7 @@ import("core.theme.theme") import("core.tool.linker") import("core.tool.compiler") import("core.project.depend") -import("private.utils.progress") +import("utils.progress") import("private.utils.batchcmds") import("object", {alias = "add_batchjobs_for_object"}) diff --git a/xmake/actions/build/main.lua b/xmake/actions/build/main.lua index 864f88185..70d15d75e 100644 --- a/xmake/actions/build/main.lua +++ b/xmake/actions/build/main.lua @@ -27,7 +27,7 @@ import("core.project.config") import("core.project.project") import("core.platform.platform") import("core.theme.theme") -import("private.utils.progress") +import("utils.progress") import("build") import("build_files") import("cleaner") diff --git a/xmake/modules/core/tools/ar.lua b/xmake/modules/core/tools/ar.lua index dc858a19e..abb1e9695 100644 --- a/xmake/modules/core/tools/ar.lua +++ b/xmake/modules/core/tools/ar.lua @@ -20,7 +20,7 @@ -- imports import("core.tool.compiler") -import("private.utils.progress") +import("utils.progress") -- init it function init(self) diff --git a/xmake/modules/core/tools/cl.lua b/xmake/modules/core/tools/cl.lua index 54eafe227..efea29a14 100644 --- a/xmake/modules/core/tools/cl.lua +++ b/xmake/modules/core/tools/cl.lua @@ -26,7 +26,7 @@ import("core.project.project") import("core.language.language") import("private.tools.vstool") import("private.tools.cl.parse_include") -import("private.utils.progress") +import("utils.progress") -- init it function init(self) diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index c6422d204..2cf31e2dc 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -27,7 +27,7 @@ import("core.project.config") import("core.project.project") import("core.language.language") import("private.tools.ccache") -import("private.utils.progress") +import("utils.progress") -- init it function init(self) diff --git a/xmake/modules/core/tools/nvcc.lua b/xmake/modules/core/tools/nvcc.lua index 25a589124..2aad54096 100644 --- a/xmake/modules/core/tools/nvcc.lua +++ b/xmake/modules/core/tools/nvcc.lua @@ -26,7 +26,7 @@ import("core.project.project") import("core.platform.platform") import("core.language.language") import("private.tools.ccache") -import("private.utils.progress") +import("utils.progress") -- init it function init(self) diff --git a/xmake/modules/core/tools/sdcc.lua b/xmake/modules/core/tools/sdcc.lua index 526254fe7..82d6cd78a 100644 --- a/xmake/modules/core/tools/sdcc.lua +++ b/xmake/modules/core/tools/sdcc.lua @@ -21,7 +21,7 @@ -- imports import("core.base.option") import("core.base.global") -import("private.utils.progress") +import("utils.progress") -- init it function init(self) diff --git a/xmake/modules/private/action/build/object.lua b/xmake/modules/private/action/build/object.lua index 50397cda4..7a99de91e 100644 --- a/xmake/modules/private/action/build/object.lua +++ b/xmake/modules/private/action/build/object.lua @@ -25,7 +25,7 @@ import("core.tool.compiler") import("core.project.depend") import("private.tools.ccache") import("private.async.runjobs") -import("private.utils.progress") +import("utils.progress") -- do build file function _do_build_file(target, sourcefile, opt) diff --git a/xmake/modules/private/action/require/impl/install_packages.lua b/xmake/modules/private/action/require/impl/install_packages.lua index c8bdefbb1..714b98461 100644 --- a/xmake/modules/private/action/require/impl/install_packages.lua +++ b/xmake/modules/private/action/require/impl/install_packages.lua @@ -25,7 +25,7 @@ import("core.base.scheduler") import("core.project.project") import("core.base.tty") import("private.async.runjobs") -import("private.utils.progress") +import("utils.progress") import("actions.install", {alias = "action_install"}) import("actions.download", {alias = "action_download"}) import("net.fasturl") diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index b048b7818..f00d796f6 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -23,7 +23,7 @@ import("core.base.semver") import("core.base.option") import("core.base.global") import("core.base.hashset") -import("private.utils.progress") +import("utils.progress") import("core.cache.memcache") import("core.project.project") import("core.project.config") diff --git a/xmake/modules/private/async/runjobs.lua b/xmake/modules/private/async/runjobs.lua index 0361399dc..a4ea2bc10 100644 --- a/xmake/modules/private/async/runjobs.lua +++ b/xmake/modules/private/async/runjobs.lua @@ -20,7 +20,7 @@ -- imports import("core.base.scheduler") -import("private.utils.progress") +import("utils.progress") -- print back characters function _print_backchars(backnum) @@ -37,7 +37,7 @@ end -- e.g. -- runjobs("test", function (index) print("hello") end, {total = 100, comax = 6, timeout = 1000, on_timer = function (running_jobs_indices) end}) -- runjobs("test", function () os.sleep(10000) end, { progress = true }) --- runjobs("test", function () os.sleep(10000) end, { progress = { chars = {'/','\'} } }) -- see module private.utils.progress +-- runjobs("test", function () os.sleep(10000) end, { progress = { chars = {'/','\'} } }) -- see module utils.progress -- -- local jobs = jobpool.new() -- local root = jobs:addjob("job/root", function (idx, total) diff --git a/xmake/modules/private/utils/batchcmds.lua b/xmake/modules/private/utils/batchcmds.lua index 946135a87..34dd5d583 100644 --- a/xmake/modules/private/utils/batchcmds.lua +++ b/xmake/modules/private/utils/batchcmds.lua @@ -28,7 +28,7 @@ import("core.theme.theme") import("core.tool.linker") import("core.tool.compiler") import("core.language.language") -import("private.utils.progress", {alias = "progress_utils"}) +import("utils.progress", {alias = "progress_utils"}) -- define module local batchcmds = batchcmds or object { _init = {"_TARGET", "_CMDS", "_DEPS", "_tip"}} diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua new file mode 100644 index 000000000..074046a69 --- /dev/null +++ b/xmake/modules/utils/progress.lua @@ -0,0 +1,139 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author OpportunityLiu +-- @file progress.lua +-- + +-- imports +import("core.base.option") +import("core.base.object") +import("core.base.colors") +import("core.base.tty") +import("core.theme.theme") + +-- define module +local process = process or object { _init = { "_RUNNING", "_INDEX", "_STREAM", "_OPT" } } + +-- stop the progress indicator, clear written frames +function process:stop() + if self._RUNNING ~= 0 then + self:clear() + self._RUNNING = 0 + self._INDEX = 0 + end +end + +function process:_clear() + if self._RUNNING == 1 then + tty.erase_line_to_end() + self._RUNNING = 2 + return true + end +end + +-- clear previous frame of the progress indicator +function process:clear() + if self:_clear() then + self._STREAM:flush() + end +end + +-- write next frame of the progress indicator +function process:write() + local chars = self._OPT.chars[self._INDEX % #self._OPT.chars + 1] + tty.cursor_and_attrs_save() + self._STREAM:write(chars) + self._STREAM:flush() + tty.cursor_and_attrs_restore() + self._INDEX = self._INDEX + 1 + self._RUNNING = 1 +end + +-- check if the progress indicator is running +function process:running() + return self._RUNNING and true or false +end + +-- showing progress line without scroll? +function showing_without_scroll() + return _g.showing_without_scroll +end + +-- show the message with process +function show(progress, format, ...) + progress = math.floor(progress) + local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " + if option.get("verbose") then + cprint(progress_prefix .. "${dim}" .. format, progress, ...) + else + local is_scroll = _g.is_scroll + if is_scroll == nil then + is_scroll = theme.get("text.build.progress_style") == "scroll" + _g.is_scroll = is_scroll + end + if is_scroll then + cprint(progress_prefix .. format, progress, ...) + else + tty.erase_line_to_start().cr() + local msg = vformat(progress_prefix .. format, progress, ...) + local msg_plain = colors.translate(msg, {plain = true}) + local maxwidth = os.getwinsize().width + if #msg_plain <= maxwidth then + cprintf(msg) + else + -- windows width is too small? strip the partial message in middle + local partlen = math.floor(maxwidth / 2) - 3 + local sep = msg_plain:sub(partlen + 1, #msg_plain - partlen - 1) + local split = msg:split(sep, {plain = true, strict = true}) + cprintf(table.concat(split, "...")) + end + if math.floor(progress) == 100 then + print("") + _g.showing_without_scroll = false + else + _g.showing_without_scroll = true + end + io.flush() + end + end +end + +-- get the message text with process +function text(progress, format, ...) + progress = math.floor(progress) + local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " + if option.get("verbose") then + return string.format(progress_prefix .. "${dim}" .. format, progress, ...) + else + return string.format(progress_prefix .. format, progress, ...) + end +end + +-- build a progress indicator +-- @params stream - stream to write to, will use io.stdout if not provided +-- @params opt - options +-- - chars - an array of chars for progress indicator +function new(stream, opt) + + -- set default values + stream = stream or io.stdout + opt = opt or {} + if opt.chars == nil or #opt.chars == 0 then + opt.chars = theme.get("text.spinner.chars") + end + return process {_OPT = opt, _STREAM = stream, _RUNNING = 0, _INDEX = 0} +end diff --git a/xmake/rules/cuda/devlink/xmake.lua b/xmake/rules/cuda/devlink/xmake.lua index e92a0b779..fb1f603b0 100644 --- a/xmake/rules/cuda/devlink/xmake.lua +++ b/xmake/rules/cuda/devlink/xmake.lua @@ -34,7 +34,7 @@ rule("cuda.build.devlink") import("core.project.depend") import("core.tool.linker") import("core.platform.platform") - import("private.utils.progress") + import("utils.progress") -- disable devlink? if target:values("cuda.build.devlink") == false then diff --git a/xmake/rules/qt/deploy/android.lua b/xmake/rules/qt/deploy/android.lua index 97f97ea7a..c1cad3b54 100644 --- a/xmake/rules/qt/deploy/android.lua +++ b/xmake/rules/qt/deploy/android.lua @@ -25,7 +25,7 @@ import("core.base.semver") import("core.project.config") import("core.project.depend") import("core.tool.toolchain") -import("private.utils.progress") +import("utils.progress") -- escape path function _escape_path(p) diff --git a/xmake/rules/qt/deploy/macosx.lua b/xmake/rules/qt/deploy/macosx.lua index 5f7b8390d..26df10b14 100644 --- a/xmake/rules/qt/deploy/macosx.lua +++ b/xmake/rules/qt/deploy/macosx.lua @@ -25,7 +25,7 @@ import("core.project.config") import("core.project.depend") import("core.tool.toolchain") import("lib.detect.find_path") -import("private.utils.progress") +import("utils.progress") -- save Info.plist function _save_info_plist(target, info_plist_file) diff --git a/xmake/rules/utils/merge_archive/merge_archive.lua b/xmake/rules/utils/merge_archive/merge_archive.lua index 96069befb..c98fc6b31 100644 --- a/xmake/rules/utils/merge_archive/merge_archive.lua +++ b/xmake/rules/utils/merge_archive/merge_archive.lua @@ -23,7 +23,7 @@ import("core.base.option") import("core.theme.theme") import("core.project.depend") import("core.project.target", {alias = "project_target"}) -import("private.utils.progress") +import("utils.progress") import("core.tool.toolchain") import("private.tools.vstool") diff --git a/xmake/rules/utils/merge_archive/xmake.lua b/xmake/rules/utils/merge_archive/xmake.lua index 62e3900ff..fd7805d8b 100644 --- a/xmake/rules/utils/merge_archive/xmake.lua +++ b/xmake/rules/utils/merge_archive/xmake.lua @@ -25,7 +25,7 @@ rule("utils.merge.archive") if target:policy("build.merge_archive") and target:is_static() then import("utils.archive.merge_staticlib") import("core.project.depend") - import("private.utils.progress") + import("utils.progress") local libraryfiles = {} for _, dep in ipairs(target:orderdeps()) do if dep:is_static() then diff --git a/xmake/rules/utils/merge_object/xmake.lua b/xmake/rules/utils/merge_object/xmake.lua index 167e9013e..8bebb5f5c 100644 --- a/xmake/rules/utils/merge_object/xmake.lua +++ b/xmake/rules/utils/merge_object/xmake.lua @@ -31,7 +31,7 @@ rule("utils.merge.object") import("core.base.option") import("core.theme.theme") import("core.project.depend") - import("private.utils.progress") + import("utils.progress") -- get object file local objectfile = target:objectfile(sourcefile_obj) diff --git a/xmake/rules/utils/symbols/export_all/export_all.lua b/xmake/rules/utils/symbols/export_all/export_all.lua index 1a40e9820..800157411 100644 --- a/xmake/rules/utils/symbols/export_all/export_all.lua +++ b/xmake/rules/utils/symbols/export_all/export_all.lua @@ -24,7 +24,7 @@ import("core.tool.toolchain") import("core.base.option") import("core.base.hashset") import("core.project.depend") -import("private.utils.progress") +import("utils.progress") -- export all symbols for dynamic library function main (target, opt) diff --git a/xmake/rules/utils/symbols/extract/xmake.lua b/xmake/rules/utils/symbols/extract/xmake.lua index f78cab808..dd1f3a1df 100644 --- a/xmake/rules/utils/symbols/extract/xmake.lua +++ b/xmake/rules/utils/symbols/extract/xmake.lua @@ -46,7 +46,7 @@ rule("utils.symbols.extract") import("core.theme.theme") import("core.project.depend") import("core.platform.platform") - import("private.utils.progress") + import("utils.progress") -- get strip local strip = target:tool("strip") diff --git a/xmake/rules/wdk/inf/xmake.lua b/xmake/rules/wdk/inf/xmake.lua index 6ad91e62d..354fbc5a7 100644 --- a/xmake/rules/wdk/inf/xmake.lua +++ b/xmake/rules/wdk/inf/xmake.lua @@ -54,7 +54,7 @@ rule("wdk.inf") import("core.base.option") import("core.theme.theme") import("core.project.depend") - import("private.utils.progress") + import("utils.progress") -- the target file local targetfile = path.join(target:targetdir(), path.basename(sourcefile) .. ".inf") diff --git a/xmake/rules/wdk/man/xmake.lua b/xmake/rules/wdk/man/xmake.lua index 7843542d7..c5219aa56 100644 --- a/xmake/rules/wdk/man/xmake.lua +++ b/xmake/rules/wdk/man/xmake.lua @@ -57,7 +57,7 @@ rule("wdk.man") import("core.base.option") import("core.theme.theme") import("core.project.depend") - import("private.utils.progress") + import("utils.progress") -- get ctrpp local ctrpp = target:data("wdk.ctrpp") diff --git a/xmake/rules/wdk/mc/xmake.lua b/xmake/rules/wdk/mc/xmake.lua index abc75fdf7..689c9786c 100644 --- a/xmake/rules/wdk/mc/xmake.lua +++ b/xmake/rules/wdk/mc/xmake.lua @@ -57,7 +57,7 @@ rule("wdk.mc") import("core.base.option") import("core.theme.theme") import("core.project.depend") - import("private.utils.progress") + import("utils.progress") -- get mc local mc = target:data("wdk.mc") diff --git a/xmake/rules/wdk/mof/xmake.lua b/xmake/rules/wdk/mof/xmake.lua index 8be25de20..a1a2a0366 100644 --- a/xmake/rules/wdk/mof/xmake.lua +++ b/xmake/rules/wdk/mof/xmake.lua @@ -73,7 +73,7 @@ rule("wdk.mof") import("core.base.option") import("core.theme.theme") import("core.project.depend") - import("private.utils.progress") + import("utils.progress") -- get mofcomp local mofcomp = target:data("wdk.mofcomp") diff --git a/xmake/rules/wdk/sign/xmake.lua b/xmake/rules/wdk/sign/xmake.lua index dd137c5ec..6be72e7b3 100644 --- a/xmake/rules/wdk/sign/xmake.lua +++ b/xmake/rules/wdk/sign/xmake.lua @@ -93,7 +93,7 @@ rule("wdk.sign") import("core.project.config") import("core.project.depend") import("lib.detect.find_file") - import("private.utils.progress") + import("utils.progress") -- need build this object? local tempfile = os.tmpfile(target:targetfile()) diff --git a/xmake/rules/wdk/tracewpp/xmake.lua b/xmake/rules/wdk/tracewpp/xmake.lua index 52d72827f..75f4f37ef 100644 --- a/xmake/rules/wdk/tracewpp/xmake.lua +++ b/xmake/rules/wdk/tracewpp/xmake.lua @@ -57,7 +57,7 @@ rule("wdk.tracewpp") import("core.base.option") import("core.theme.theme") import("core.project.depend") - import("private.utils.progress") + import("utils.progress") -- get tracewpp local tracewpp = target:data("wdk.tracewpp") diff --git a/xmake/rules/xcode/application/build.lua b/xmake/rules/xcode/application/build.lua index 786f5da89..a4862ae86 100644 --- a/xmake/rules/xcode/application/build.lua +++ b/xmake/rules/xcode/application/build.lua @@ -23,7 +23,7 @@ import("core.base.option") import("core.theme.theme") import("core.project.depend") import("private.tools.codesign") -import("private.utils.progress") +import("utils.progress") -- main entry function main (target, opt) diff --git a/xmake/rules/xcode/bundle/xmake.lua b/xmake/rules/xcode/bundle/xmake.lua index 1c1cecf99..322a42418 100644 --- a/xmake/rules/xcode/bundle/xmake.lua +++ b/xmake/rules/xcode/bundle/xmake.lua @@ -60,7 +60,7 @@ rule("xcode.bundle") import("core.theme.theme") import("core.project.depend") import("private.tools.codesign") - import("private.utils.progress") + import("utils.progress") -- get bundle and resources directory local bundledir = path.absolute(target:data("xcode.bundle.rootdir")) diff --git a/xmake/rules/xcode/framework/xmake.lua b/xmake/rules/xcode/framework/xmake.lua index 6b46b3c97..de7d7c93c 100644 --- a/xmake/rules/xcode/framework/xmake.lua +++ b/xmake/rules/xcode/framework/xmake.lua @@ -85,7 +85,7 @@ rule("xcode.framework") import("core.theme.theme") import("core.project.depend") import("private.tools.codesign") - import("private.utils.progress") + import("utils.progress") -- get framework directory local bundledir = path.absolute(target:data("xcode.bundle.rootdir")) diff --git a/xmake/rules/xcode/info_plist/xmake.lua b/xmake/rules/xcode/info_plist/xmake.lua index 57d3c9995..bd991b6e1 100644 --- a/xmake/rules/xcode/info_plist/xmake.lua +++ b/xmake/rules/xcode/info_plist/xmake.lua @@ -32,7 +32,7 @@ rule("xcode.info_plist") import("core.theme.theme") import("core.project.depend") import("core.tool.toolchain") - import("private.utils.progress") + import("utils.progress") -- check assert(path.filename(sourcefile) == "Info.plist", "we only support Info.plist file!") diff --git a/xmake/rules/xcode/storyboard/xmake.lua b/xmake/rules/xcode/storyboard/xmake.lua index 6ec23dd80..d96a1c002 100644 --- a/xmake/rules/xcode/storyboard/xmake.lua +++ b/xmake/rules/xcode/storyboard/xmake.lua @@ -32,7 +32,7 @@ rule("xcode.storyboard") import("core.theme.theme") import("core.project.depend") import("core.tool.toolchain") - import("private.utils.progress") + import("utils.progress") -- get xcode sdk directory local xcode_sdkdir = assert(get_config("xcode"), "xcode not found!") diff --git a/xmake/rules/xcode/xcassets/xmake.lua b/xmake/rules/xcode/xcassets/xmake.lua index 09185b226..9322d10c1 100644 --- a/xmake/rules/xcode/xcassets/xmake.lua +++ b/xmake/rules/xcode/xcassets/xmake.lua @@ -32,7 +32,7 @@ rule("xcode.xcassets") import("core.theme.theme") import("core.project.depend") import("core.tool.toolchain") - import("private.utils.progress") + import("utils.progress") -- get xcode sdk directory local xcode_sdkdir = assert(get_config("xcode"), "xcode not found!") -- cgit v1.3.1 From 094b8d16d88787219cf8840b867846a4159de055 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 9 Oct 2021 12:02:03 +0800 Subject: switch to lua runtime --- .github/workflows/linux_lua.yml | 36 ----------- .github/workflows/linux_luajit.yml | 36 +++++++++++ .github/workflows/windows_lua.yml | 122 ----------------------------------- .github/workflows/windows_luajit.yml | 121 ++++++++++++++++++++++++++++++++++ core/xmake.lua | 2 +- makefile | 2 +- 6 files changed, 159 insertions(+), 160 deletions(-) delete mode 100644 .github/workflows/linux_lua.yml create mode 100644 .github/workflows/linux_luajit.yml delete mode 100644 .github/workflows/windows_lua.yml create mode 100644 .github/workflows/windows_luajit.yml diff --git a/.github/workflows/linux_lua.yml b/.github/workflows/linux_lua.yml deleted file mode 100644 index 71a365a3f..000000000 --- a/.github/workflows/linux_lua.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Linux (Lua) - -on: - pull_request: - push: - release: - types: [published] - -jobs: - build: - runs-on: ubuntu-latest - concurrency: - group: ${{ github.head_ref }}-Linux-Lua - cancel-in-progress: true - steps: - - uses: actions/checkout@v2 - with: - submodules: true - - uses: dlang-community/setup-dlang@v1 - with: - compiler: dmd-latest - - uses: little-core-labs/get-git-tag@v3.0.2 - id: tagName - - - name: Installation - run: | - make BACKEND=lua - ./scripts/get.sh __local__ __install_only__ - source ~/.xmake/profile - xmake --version - - - name: Tests - run: | - xmake lua -v -D tests/run.lua - xrepo --version - diff --git a/.github/workflows/linux_luajit.yml b/.github/workflows/linux_luajit.yml new file mode 100644 index 000000000..919c11550 --- /dev/null +++ b/.github/workflows/linux_luajit.yml @@ -0,0 +1,36 @@ +name: Linux (Luajit) + +on: + pull_request: + push: + release: + types: [published] + +jobs: + build: + runs-on: ubuntu-latest + concurrency: + group: ${{ github.head_ref }}-Linux-Luajit + cancel-in-progress: true + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - uses: dlang-community/setup-dlang@v1 + with: + compiler: dmd-latest + - uses: little-core-labs/get-git-tag@v3.0.2 + id: tagName + + - name: Installation + run: | + make RUNTIME=luajit + ./scripts/get.sh __local__ __install_only__ + source ~/.xmake/profile + xmake --version + + - name: Tests + run: | + xmake lua -v -D tests/run.lua + xrepo --version + diff --git a/.github/workflows/windows_lua.yml b/.github/workflows/windows_lua.yml deleted file mode 100644 index 3ad8ebf74..000000000 --- a/.github/workflows/windows_lua.yml +++ /dev/null @@ -1,122 +0,0 @@ -name: Windows (Luajit) - -on: - pull_request: - push: - release: - types: [published] - -jobs: - build: - strategy: - matrix: - os: [windows-latest, windows-2016] - arch: [x64, x86] - - runs-on: ${{ matrix.os }} - - concurrency: - group: ${{ github.head_ref }}-${{ matrix.os }}-${{ matrix.arch }}-Windows-Luajit - cancel-in-progress: true - steps: - - uses: actions/checkout@v2 - with: - # WyriHaximus/github-action-get-previous-tag@master need it - fetch-depth: 0 - submodules: true - - uses: xmake-io/github-action-setup-xmake@v1 - with: - # this is not supported, use dev branch instead - # xmake-version: local# - xmake-version: branch@dev - - uses: dlang-community/setup-dlang@v1 - with: - compiler: dmd-latest - - uses: little-core-labs/get-git-tag@v3.0.2 - id: tagName - - - name: Prepare - run: | - xmake show - Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/nsis-3.04.zip" -UseBasicParsing -OutFile ./nsis.zip - Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/nsis-3.04-strlen_8192.zip" -UseBasicParsing -OutFile ./nsis-longstr.zip - Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/UAC.zip" -UseBasicParsing -OutFile ./nsis-uac.zip - Expand-Archive ./nsis.zip -DestinationPath ./nsis - Move-Item ./nsis/*/* ./nsis - Expand-Archive ./nsis-longstr.zip -DestinationPath ./nsis -Force - Expand-Archive ./nsis-uac.zip -DestinationPath ./nsis -Force - Move-Item ./nsis/UAC.nsh ./nsis/Include/ - - - name: Build - run: | - xmake f -vD -P core -a ${{ matrix.arch }} --runtime=lua - xmake -vD -P core - - - name: Tests - run: | - Copy-Item ./core/build/xmake.exe ./xmake - Copy-Item ./scripts/xrepo.bat ./xmake - Copy-Item ./scripts/xrepo.ps1 ./xmake - $Env:XMAKE_PROGRAM_DIR = $(Resolve-Path ./xmake) - Set-Item -Path Env:Path -Value ($Env:XMAKE_PROGRAM_DIR + ";" + $Env:Path) - xrepo --version - xmake show - #xmake l -v private.utils.bcsave --rootname='@programdir' -x 'scripts/**|templates/**' xmake - xmake lua -v -D tests/run.lua - - - name: Set release arch name - run: | - if ("${{ matrix.arch }}" -eq "x64") { - Write-Output "RELEASE_NAME=win64" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf-8 -Append - } else { - Write-Output "RELEASE_NAME=win32" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf-8 -Append - } - - name: Artifact - run: | - # build installer - (New-Item ./winenv/bin -ItemType Directory).FullName - Invoke-WebRequest "https://github.com/xmake-mirror/7zip/releases/download/19.00/7z19.00-${{ matrix.arch }}.zip" -UseBasicParsing -OutFile .\7zip.zip - Expand-Archive ./7zip.zip -DestinationPath ./7zip - Copy-Item ./7zip/7z.exe ./winenv/bin - Copy-Item ./7zip/7z.dll ./winenv/bin - Invoke-WebRequest "https://curl.se/windows/dl-7.78.0_2/curl-7.78.0_2-win32-mingw.zip" -UseBasicParsing -OutFile .\curl.zip - Expand-Archive ./curl.zip -DestinationPath ./curl - Copy-Item ./curl/curl-7.78.0-win32-mingw/bin/curl.exe ./winenv/bin - Copy-Item ./curl/curl-7.78.0-win32-mingw/bin/curl-ca-bundle.crt ./winenv/bin - $version = (Get-Command xmake/xmake.exe).FileVersionInfo - ./nsis/makensis.exe /DMAJOR=$($version.ProductMajorPart) /DMINOR=$($version.ProductMinorPart) /DALTER=$($version.ProductBuildPart) /DBUILD=$($($version.ProductVersion -split '\+')[1]) /D${{ matrix.arch }} .\scripts\installer.nsi - (New-Item ./artifacts/${{env.RELEASE_NAME}} -ItemType Directory).FullName - Copy-Item scripts/xmake.exe ./artifacts/${{env.RELEASE_NAME}}/xmake.exe - # archive - Copy-Item ./*.md ./xmake - Copy-Item ./winenv ./xmake -Recurse - Add-Type -AssemblyName System.Text.Encoding - Add-Type -AssemblyName System.IO.Compression.FileSystem - class FixedEncoder : System.Text.UTF8Encoding { - FixedEncoder() : base($true) { } - [byte[]] GetBytes([string] $s) - { - $s = $s.Replace("\", "/") - return ([System.Text.UTF8Encoding]$this).GetBytes($s) - } - } - Copy-Item ./xmake ./archive/xmake -Recurse - [System.IO.Compression.ZipFile]::CreateFromDirectory("$PWD\archive", "$PWD\archive.zip", [System.IO.Compression.CompressionLevel]::Optimal, $false, [FixedEncoder]::new()) - (Get-FileHash .\archive.zip -Algorithm SHA256).Hash.ToLower() + " *xmake.zip`n" | Out-File ./shafile -Encoding ASCII -NoNewLine -Append - Copy-Item archive.zip ./artifacts/${{env.RELEASE_NAME}} - Copy-Item shafile ./artifacts/${{env.RELEASE_NAME}} - - # upload artifacts - - uses: actions/upload-artifact@v2 - with: - name: xmake-latest.${{env.RELEASE_NAME}}.exe - path: artifacts/${{env.RELEASE_NAME}}/xmake.exe - - uses: actions/upload-artifact@v2 - with: - name: xmake-latest.${{ env.RELEASE_NAME }}.zip - path: artifacts/${{env.RELEASE_NAME}}/archive.zip - - uses: actions/upload-artifact@v2 - with: - name: xmake-latest.${{ env.RELEASE_NAME }}.sha256 - path: artifacts/${{env.RELEASE_NAME}}/shafile - diff --git a/.github/workflows/windows_luajit.yml b/.github/workflows/windows_luajit.yml new file mode 100644 index 000000000..8bc06dbf6 --- /dev/null +++ b/.github/workflows/windows_luajit.yml @@ -0,0 +1,121 @@ +name: Windows (Luajit) + +on: + pull_request: + push: + release: + types: [published] + +jobs: + build: + strategy: + matrix: + os: [windows-latest, windows-2016] + arch: [x64, x86] + + runs-on: ${{ matrix.os }} + + concurrency: + group: ${{ github.head_ref }}-${{ matrix.os }}-${{ matrix.arch }}-Windows-Luajit + cancel-in-progress: true + steps: + - uses: actions/checkout@v2 + with: + # WyriHaximus/github-action-get-previous-tag@master need it + fetch-depth: 0 + submodules: true + - uses: xmake-io/github-action-setup-xmake@v1 + with: + # this is not supported, use dev branch instead + # xmake-version: local# + xmake-version: branch@dev + - uses: dlang-community/setup-dlang@v1 + with: + compiler: dmd-latest + - uses: little-core-labs/get-git-tag@v3.0.2 + id: tagName + + - name: Prepare + run: | + xmake show + Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/nsis-3.04.zip" -UseBasicParsing -OutFile ./nsis.zip + Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/nsis-3.04-strlen_8192.zip" -UseBasicParsing -OutFile ./nsis-longstr.zip + Invoke-WebRequest "https://github.com/xmake-mirror/nsis/releases/download/v30b3/UAC.zip" -UseBasicParsing -OutFile ./nsis-uac.zip + Expand-Archive ./nsis.zip -DestinationPath ./nsis + Move-Item ./nsis/*/* ./nsis + Expand-Archive ./nsis-longstr.zip -DestinationPath ./nsis -Force + Expand-Archive ./nsis-uac.zip -DestinationPath ./nsis -Force + Move-Item ./nsis/UAC.nsh ./nsis/Include/ + + - name: Build + run: | + xmake f -vD -P core -a ${{ matrix.arch }} --runtime=luajit + xmake -vD -P core + + - name: Tests + run: | + Copy-Item ./core/build/xmake.exe ./xmake + Copy-Item ./scripts/xrepo.bat ./xmake + Copy-Item ./scripts/xrepo.ps1 ./xmake + $Env:XMAKE_PROGRAM_DIR = $(Resolve-Path ./xmake) + Set-Item -Path Env:Path -Value ($Env:XMAKE_PROGRAM_DIR + ";" + $Env:Path) + xrepo --version + xmake show + xmake lua -v -D tests/run.lua + + - name: Set release arch name + run: | + if ("${{ matrix.arch }}" -eq "x64") { + Write-Output "RELEASE_NAME=win64" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf-8 -Append + } else { + Write-Output "RELEASE_NAME=win32" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf-8 -Append + } + - name: Artifact + run: | + # build installer + (New-Item ./winenv/bin -ItemType Directory).FullName + Invoke-WebRequest "https://github.com/xmake-mirror/7zip/releases/download/19.00/7z19.00-${{ matrix.arch }}.zip" -UseBasicParsing -OutFile .\7zip.zip + Expand-Archive ./7zip.zip -DestinationPath ./7zip + Copy-Item ./7zip/7z.exe ./winenv/bin + Copy-Item ./7zip/7z.dll ./winenv/bin + Invoke-WebRequest "https://curl.se/windows/dl-7.78.0_2/curl-7.78.0_2-win32-mingw.zip" -UseBasicParsing -OutFile .\curl.zip + Expand-Archive ./curl.zip -DestinationPath ./curl + Copy-Item ./curl/curl-7.78.0-win32-mingw/bin/curl.exe ./winenv/bin + Copy-Item ./curl/curl-7.78.0-win32-mingw/bin/curl-ca-bundle.crt ./winenv/bin + $version = (Get-Command xmake/xmake.exe).FileVersionInfo + ./nsis/makensis.exe /DMAJOR=$($version.ProductMajorPart) /DMINOR=$($version.ProductMinorPart) /DALTER=$($version.ProductBuildPart) /DBUILD=$($($version.ProductVersion -split '\+')[1]) /D${{ matrix.arch }} .\scripts\installer.nsi + (New-Item ./artifacts/${{env.RELEASE_NAME}} -ItemType Directory).FullName + Copy-Item scripts/xmake.exe ./artifacts/${{env.RELEASE_NAME}}/xmake.exe + # archive + Copy-Item ./*.md ./xmake + Copy-Item ./winenv ./xmake -Recurse + Add-Type -AssemblyName System.Text.Encoding + Add-Type -AssemblyName System.IO.Compression.FileSystem + class FixedEncoder : System.Text.UTF8Encoding { + FixedEncoder() : base($true) { } + [byte[]] GetBytes([string] $s) + { + $s = $s.Replace("\", "/") + return ([System.Text.UTF8Encoding]$this).GetBytes($s) + } + } + Copy-Item ./xmake ./archive/xmake -Recurse + [System.IO.Compression.ZipFile]::CreateFromDirectory("$PWD\archive", "$PWD\archive.zip", [System.IO.Compression.CompressionLevel]::Optimal, $false, [FixedEncoder]::new()) + (Get-FileHash .\archive.zip -Algorithm SHA256).Hash.ToLower() + " *xmake.zip`n" | Out-File ./shafile -Encoding ASCII -NoNewLine -Append + Copy-Item archive.zip ./artifacts/${{env.RELEASE_NAME}} + Copy-Item shafile ./artifacts/${{env.RELEASE_NAME}} + + # upload artifacts + - uses: actions/upload-artifact@v2 + with: + name: xmake-latest.${{env.RELEASE_NAME}}.exe + path: artifacts/${{env.RELEASE_NAME}}/xmake.exe + - uses: actions/upload-artifact@v2 + with: + name: xmake-latest.${{ env.RELEASE_NAME }}.zip + path: artifacts/${{env.RELEASE_NAME}}/archive.zip + - uses: actions/upload-artifact@v2 + with: + name: xmake-latest.${{ env.RELEASE_NAME }}.sha256 + path: artifacts/${{env.RELEASE_NAME}}/shafile + diff --git a/core/xmake.lua b/core/xmake.lua index cb4b41daf..a176adf76 100644 --- a/core/xmake.lua +++ b/core/xmake.lua @@ -43,7 +43,7 @@ end -- the runtime option option("runtime") set_showmenu(true) - set_default("luajit") + set_default("lua") set_description("Use luajit or lua runtime") set_values("luajit", "lua") option_end() diff --git a/makefile b/makefile index bdb79d05b..e848a2eda 100644 --- a/makefile +++ b/makefile @@ -17,7 +17,7 @@ endif # use luajit or lua backend ifeq ($(RUNTIME),) -RUNTIME :=luajit +RUNTIME :=lua endif # the temporary directory -- cgit v1.3.1 From 2aa89e62fcd1c90846baaebb973ac002e65d17d0 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 9 Oct 2021 12:32:18 +0800 Subject: Update makefile --- core/src/lua/makefile | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/core/src/lua/makefile b/core/src/lua/makefile index 4137fd22c..84a95abcf 100644 --- a/core/src/lua/makefile +++ b/core/src/lua/makefile @@ -64,16 +64,19 @@ endif lua_CFLAGS := -std=c99 -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 ifdef iswin -lua_CFLAGS += -DLUA_USE_WINDOWS +lua_CFLAGS_PLAT := -DLUA_USE_WINDOWS endif ifeq ($(PLAT),macosx) -lua_CFLAGS += -DLUA_USE_MACOSX \ - -Wno-error=string-plus-int -else -lua_CFLAGS += -DLUA_USE_LINUX +lua_CFLAGS += -Wno-error=string-plus-int +lua_CFLAGS_PLAT := -DLUA_USE_WINDOWS endif +ifeq($(lua_CFLAGS_PLAT),) +lua_CFLAGS_PLAT := -DLUA_USE_LINUX +endif +lua_CFLAGS += $(lua_CFLAGS_PLAT) + # use given system library? lua_C_FILES := $(if $(findstring lua,$(base_LIBNAMES)),,$(lua_C_FILES)) lua_ASM_FILES := $(if $(findstring lua,$(base_LIBNAMES)),,$(lua_ASM_FILES)) -- cgit v1.3.1 From 1e77446b9d4b398af4d90cf5234f9d2201ac3987 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 9 Oct 2021 12:37:27 +0800 Subject: Delete progress.lua --- xmake/modules/private/utils/progress.lua | 139 ------------------------------- 1 file changed, 139 deletions(-) delete mode 100644 xmake/modules/private/utils/progress.lua diff --git a/xmake/modules/private/utils/progress.lua b/xmake/modules/private/utils/progress.lua deleted file mode 100644 index 074046a69..000000000 --- a/xmake/modules/private/utils/progress.lua +++ /dev/null @@ -1,139 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- 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 --- --- http://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. --- --- Copyright (C) 2015-present, TBOOX Open Source Group. --- --- @author OpportunityLiu --- @file progress.lua --- - --- imports -import("core.base.option") -import("core.base.object") -import("core.base.colors") -import("core.base.tty") -import("core.theme.theme") - --- define module -local process = process or object { _init = { "_RUNNING", "_INDEX", "_STREAM", "_OPT" } } - --- stop the progress indicator, clear written frames -function process:stop() - if self._RUNNING ~= 0 then - self:clear() - self._RUNNING = 0 - self._INDEX = 0 - end -end - -function process:_clear() - if self._RUNNING == 1 then - tty.erase_line_to_end() - self._RUNNING = 2 - return true - end -end - --- clear previous frame of the progress indicator -function process:clear() - if self:_clear() then - self._STREAM:flush() - end -end - --- write next frame of the progress indicator -function process:write() - local chars = self._OPT.chars[self._INDEX % #self._OPT.chars + 1] - tty.cursor_and_attrs_save() - self._STREAM:write(chars) - self._STREAM:flush() - tty.cursor_and_attrs_restore() - self._INDEX = self._INDEX + 1 - self._RUNNING = 1 -end - --- check if the progress indicator is running -function process:running() - return self._RUNNING and true or false -end - --- showing progress line without scroll? -function showing_without_scroll() - return _g.showing_without_scroll -end - --- show the message with process -function show(progress, format, ...) - progress = math.floor(progress) - local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " - if option.get("verbose") then - cprint(progress_prefix .. "${dim}" .. format, progress, ...) - else - local is_scroll = _g.is_scroll - if is_scroll == nil then - is_scroll = theme.get("text.build.progress_style") == "scroll" - _g.is_scroll = is_scroll - end - if is_scroll then - cprint(progress_prefix .. format, progress, ...) - else - tty.erase_line_to_start().cr() - local msg = vformat(progress_prefix .. format, progress, ...) - local msg_plain = colors.translate(msg, {plain = true}) - local maxwidth = os.getwinsize().width - if #msg_plain <= maxwidth then - cprintf(msg) - else - -- windows width is too small? strip the partial message in middle - local partlen = math.floor(maxwidth / 2) - 3 - local sep = msg_plain:sub(partlen + 1, #msg_plain - partlen - 1) - local split = msg:split(sep, {plain = true, strict = true}) - cprintf(table.concat(split, "...")) - end - if math.floor(progress) == 100 then - print("") - _g.showing_without_scroll = false - else - _g.showing_without_scroll = true - end - io.flush() - end - end -end - --- get the message text with process -function text(progress, format, ...) - progress = math.floor(progress) - local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " - if option.get("verbose") then - return string.format(progress_prefix .. "${dim}" .. format, progress, ...) - else - return string.format(progress_prefix .. format, progress, ...) - end -end - --- build a progress indicator --- @params stream - stream to write to, will use io.stdout if not provided --- @params opt - options --- - chars - an array of chars for progress indicator -function new(stream, opt) - - -- set default values - stream = stream or io.stdout - opt = opt or {} - if opt.chars == nil or #opt.chars == 0 then - opt.chars = theme.get("text.spinner.chars") - end - return process {_OPT = opt, _STREAM = stream, _RUNNING = 0, _INDEX = 0} -end -- cgit v1.3.1 From 8bedd250e10d821857adf671d2282ca3cdd6706d Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 9 Oct 2021 12:40:55 +0800 Subject: Update object.lua --- xmake/rules/go/build/object.lua | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/xmake/rules/go/build/object.lua b/xmake/rules/go/build/object.lua index cf6a1c9ff..e24620702 100644 --- a/xmake/rules/go/build/object.lua +++ b/xmake/rules/go/build/object.lua @@ -21,9 +21,9 @@ -- imports import("core.base.option") import("core.base.hashset") -import("core.theme.theme") import("core.tool.compiler") import("core.project.depend") +import("utils.progress") -- build the source files function main(target, sourcebatch, opt) @@ -31,9 +31,6 @@ function main(target, sourcebatch, opt) -- is verbose? local verbose = option.get("verbose") - -- get progress range - local progress = assert(opt.progress, "no progress!") - -- get source files and kind local sourcefiles = sourcebatch.sourcefiles local sourcekind = sourcebatch.sourcekind @@ -72,12 +69,7 @@ function main(target, sourcebatch, opt) -- trace progress info for index, sourcefile in ipairs(sourcefiles) do - local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " - if verbose then - cprint(progress_prefix .. "${dim color.build.object}compiling.$(mode) %s", progress, sourcefile) - else - cprint(progress_prefix .. "${color.build.object}compiling.$(mode) %s", progress, sourcefile) - end + progress.show(opt.progress, "${color.build.object}compiling.$(mode) %s", sourcefile) end -- trace verbose info -- cgit v1.3.1 From 62ce99d893b8eefcc30415b4154619ecf749e7a6 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 9 Oct 2021 13:04:29 +0800 Subject: Update makefile --- core/src/lua/makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/lua/makefile b/core/src/lua/makefile index 84a95abcf..8a9639947 100644 --- a/core/src/lua/makefile +++ b/core/src/lua/makefile @@ -69,10 +69,10 @@ endif ifeq ($(PLAT),macosx) lua_CFLAGS += -Wno-error=string-plus-int -lua_CFLAGS_PLAT := -DLUA_USE_WINDOWS +lua_CFLAGS_PLAT := -DLUA_USE_MACOSX endif -ifeq($(lua_CFLAGS_PLAT),) +ifeq ($(lua_CFLAGS_PLAT),) lua_CFLAGS_PLAT := -DLUA_USE_LINUX endif lua_CFLAGS += $(lua_CFLAGS_PLAT) -- cgit v1.3.1 From f9487fe520c7a3266cc5ce91576ec06c1520c93a Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 9 Oct 2021 13:23:13 +0800 Subject: Update target.lua --- xmake/rules/rust/build/target.lua | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/xmake/rules/rust/build/target.lua b/xmake/rules/rust/build/target.lua index 67917ad29..a1f34beff 100644 --- a/xmake/rules/rust/build/target.lua +++ b/xmake/rules/rust/build/target.lua @@ -21,19 +21,13 @@ -- imports import("core.base.option") import("core.base.hashset") -import("core.theme.theme") import("core.tool.compiler") import("core.project.depend") +import("utils.progress") -- build the source files function build_sourcefiles(target, sourcebatch, opt) - -- is verbose? - local verbose = option.get("verbose") - - -- get progress range - local progress = assert(opt.progress, "no progress!") - -- get the target file local targetfile = target:targetfile() @@ -60,17 +54,10 @@ function build_sourcefiles(target, sourcebatch, opt) end -- trace progress into - cprintf("${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} ", progress) - if verbose then - cprint("${dim color.build.target}linking.$(mode) %s", path.filename(targetfile)) - else - cprint("${color.build.target}linking.$(mode) %s", path.filename(targetfile)) - end + progress.show(opt.progress, "${color.build.target}linking.$(mode) %s", path.filename(targetfile)) -- trace verbose info - if verbose then - print(compinst:buildcmd(sourcefiles, targetfile, {target = target, compflags = compflags})) - end + vprint(compinst:buildcmd(sourcefiles, targetfile, {target = target, compflags = compflags})) -- flush io buffer to update progress info io.flush() -- cgit v1.3.1 From c8e4af0a7da8bfd80daf90d0fe3dad0163abf4b1 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 9 Oct 2021 13:23:51 +0800 Subject: Update object.lua --- xmake/rules/go/build/object.lua | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/xmake/rules/go/build/object.lua b/xmake/rules/go/build/object.lua index e24620702..21436be47 100644 --- a/xmake/rules/go/build/object.lua +++ b/xmake/rules/go/build/object.lua @@ -27,10 +27,7 @@ import("utils.progress") -- build the source files function main(target, sourcebatch, opt) - - -- is verbose? - local verbose = option.get("verbose") - + -- get source files and kind local sourcefiles = sourcebatch.sourcefiles local sourcekind = sourcebatch.sourcekind @@ -73,9 +70,7 @@ function main(target, sourcebatch, opt) end -- trace verbose info - if verbose then - print(compinst:compcmd(sourcefiles, objectfile, {compflags = compflags})) - end + vprint(compinst:compcmd(sourcefiles, objectfile, {compflags = compflags})) -- compile it dependinfo.files = {} -- cgit v1.3.1 From 53a95c333a58fed76fc24765075c8bd925429bc6 Mon Sep 17 00:00:00 2001 From: wsw0108 Date: Sat, 9 Oct 2021 22:16:13 +0800 Subject: toolchain wasi using wasi-sdk --- xmake/toolchains/wasi/xmake.lua | 63 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 xmake/toolchains/wasi/xmake.lua diff --git a/xmake/toolchains/wasi/xmake.lua b/xmake/toolchains/wasi/xmake.lua new file mode 100644 index 000000000..de2b7f37e --- /dev/null +++ b/xmake/toolchains/wasi/xmake.lua @@ -0,0 +1,63 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author wsw0108 +-- @file xmake.lua +-- + +-- define toolchain +toolchain("wasi") + + -- set homepage + set_homepage("https://github.com/WebAssembly/wasi-sdk") + set_description("WASI-enabled WebAssembly C/C++ toolchain.") + + -- mark as standalone toolchain + set_kind("standalone") + + -- set toolset + set_toolset("cc", "clang") + set_toolset("cxx", "clang", "clang++") + set_toolset("cpp", "clang -E") + set_toolset("as", "clang") + set_toolset("ld", "clang++", "clang") + set_toolset("sh", "clang++", "clang") + set_toolset("ar", "llvm-ar") + set_toolset("ex", "llvm-ar") + set_toolset("ranlib", "llvm-ranlib") + set_toolset("strip", "llvm-strip") + + -- check toolchain + on_check(function (toolchain) + return import("lib.detect.find_tool")("clang") + end) + + -- on load + on_load(function (toolchain) + + local sdkdir = toolchain:sdkdir() + local sysroot = path.join(sdkdir, "share", "wasi-sysroot") + toolchain:add("cxflags", "--sysroot=" .. sysroot) + toolchain:add("mxflags", "--sysroot=" .. sysroot) + toolchain:add("ldflags", "--sysroot=" .. sysroot) + toolchain:add("shflags", "--sysroot=" .. sysroot) + + -- add bin search library for loading some dependent .dll files windows + local bindir = toolchain:bindir() + if bindir and is_host("windows") then + toolchain:add("runenvs", "PATH", bindir) + end + end) -- cgit v1.3.1 From ba1c8c827e462ece4b1fe41a126b30afe4adbe03 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 9 Oct 2021 22:40:19 +0800 Subject: switch lua 5.4.3 --- core/src/lua/lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/lua/lua b/core/src/lua/lua index 75ea9ccbe..eadd8c717 160000 --- a/core/src/lua/lua +++ b/core/src/lua/lua @@ -1 +1 @@ -Subproject commit 75ea9ccbea7c4886f30da147fb67b693b2624c26 +Subproject commit eadd8c7178c79c814ecca9652973a9b9dd4cc71b -- cgit v1.3.1 From f35f6e15e13a4e5a360b94148534623b6a9c5feb Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 9 Oct 2021 22:58:17 +0800 Subject: fix makefile --- core/src/lcurses/makefile | 2 +- core/src/lua-cjson/makefile | 2 +- core/src/lua/makefile | 3 +-- core/src/lua/xmake.lua | 2 +- core/src/xmake/makefile | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/core/src/lcurses/makefile b/core/src/lcurses/makefile index e5d519499..6347b4c8e 100644 --- a/core/src/lcurses/makefile +++ b/core/src/lcurses/makefile @@ -23,7 +23,7 @@ lcurses_CXFLAGS += -DUSE_LUAJIT endif ifeq ($(RUNTIME),lua) lcurses_INC_DIRS += ../lua/lua -lcurses_CXFLAGS += -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 +lcurses_CXFLAGS += -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 -DLUA_COMPAT_5_3 endif # suffix diff --git a/core/src/lua-cjson/makefile b/core/src/lua-cjson/makefile index 021c3d015..4a2c4ffeb 100644 --- a/core/src/lua-cjson/makefile +++ b/core/src/lua-cjson/makefile @@ -28,7 +28,7 @@ lua-cjson_CXFLAGS += -DUSE_LUAJIT endif ifeq ($(RUNTIME),lua) lua-cjson_INC_DIRS += ../lua/lua -lua-cjson_CXFLAGS += -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 +lua-cjson_CXFLAGS += -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 -DLUA_COMPAT_5_3 endif # use given system library? diff --git a/core/src/lua/makefile b/core/src/lua/makefile index 8a9639947..9db0fa518 100644 --- a/core/src/lua/makefile +++ b/core/src/lua/makefile @@ -37,7 +37,6 @@ lua_C_FILES += \ lua/lcorolib \ lua/lcode \ lua/ltablib \ - lua/lbitlib \ lua/lapi \ lua/lbaselib \ lua/ldebug \ @@ -62,7 +61,7 @@ ifeq ($(PLAT),cygwin) iswin = yes endif -lua_CFLAGS := -std=c99 -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 +lua_CFLAGS := -std=c99 -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 -DLUA_COMPAT_5_3 ifdef iswin lua_CFLAGS_PLAT := -DLUA_USE_WINDOWS endif diff --git a/core/src/lua/xmake.lua b/core/src/lua/xmake.lua index 4f209b693..9a622a2e9 100644 --- a/core/src/lua/xmake.lua +++ b/core/src/lua/xmake.lua @@ -20,7 +20,7 @@ target("lua") add_files("lua/*.c|lua.c") -- add defines - add_defines("LUA_COMPAT_5_1", "LUA_COMPAT_5_2", {public = true}) + add_defines("LUA_COMPAT_5_1", "LUA_COMPAT_5_2", "LUA_COMPAT_5_3", {public = true}) if is_plat("windows") then add_defines("LUA_USE_WINDOWS") elseif is_plat("macosx", "iphoneos") then diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index b29e8cc20..48eb51974 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -164,7 +164,7 @@ xmake_CXFLAGS += -DUSE_LUAJIT endif ifeq ($(RUNTIME),lua) xmake_INC_DIRS += ../lua/lua -xmake_CXFLAGS += -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 +xmake_CXFLAGS += -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 -DLUA_COMPAT_5_3 endif -- cgit v1.3.1 From dd6dd5f7558ccdff0e886823c35f2397602a0fde Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 9 Oct 2021 23:00:45 +0800 Subject: update changelog and readme --- CHANGELOG.md | 8 ++++++++ README.md | 3 ++- README_zh.md | 3 ++- core/src/lua/lua | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d6b88ccd..0ac3302b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### New features + +* [#1736](https://github.com/xmake-io/xmake/issues/1736): Support wasi-sdk toolchain + ## v2.5.8 ### New features @@ -1090,6 +1094,10 @@ ## master (开发中) +### 新特性 + +* [#1736](https://github.com/xmake-io/xmake/issues/1736): 支持 wasi-sdk 工具链 + ## v2.5.8 ### 新特性 diff --git a/README.md b/README.md index 3d5b1334c..12ffb7438 100644 --- a/README.md +++ b/README.md @@ -222,8 +222,9 @@ tinycc Tiny C Compiler emcc A toolchain for compiling to asm.js and WebAssembly icc Intel C/C++ Compiler ifort Intel Fortran Compiler -muslcc The musl-based cross-compilation toolchains +muslcc The musl-based cross-compilation toolchain fpc Free Pascal Programming Language Compiler +wasi WASI-enabled WebAssembly C/C++ toolchain ``` ## Supported Languages diff --git a/README_zh.md b/README_zh.md index fb0f9d19e..d00577c2d 100644 --- a/README_zh.md +++ b/README_zh.md @@ -230,8 +230,9 @@ tinycc Tiny C Compiler emcc A toolchain for compiling to asm.js and WebAssembly icc Intel C/C++ Compiler ifort Intel Fortran Compiler -muslcc The musl-based cross-compilation toolchains +muslcc The musl-based cross-compilation toolchain fpc Free Pascal Programming Language Compiler +wasi WASI-enabled WebAssembly C/C++ toolchain ``` ## 支持语言 diff --git a/core/src/lua/lua b/core/src/lua/lua index 75ea9ccbe..eadd8c717 160000 --- a/core/src/lua/lua +++ b/core/src/lua/lua @@ -1 +1 @@ -Subproject commit 75ea9ccbea7c4886f30da147fb67b693b2624c26 +Subproject commit eadd8c7178c79c814ecca9652973a9b9dd4cc71b -- cgit v1.3.1 From 1af0820871a06217312fcee22b68e15954fc553a Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 9 Oct 2021 23:58:21 +0800 Subject: fix some errors for lua5.4 --- core/src/lcurses/lcurses.c | 14 +++++++++++-- core/src/xmake/engine.c | 24 +++++++++++------------ core/src/xmake/prefix.h | 16 +++++++++++++++ core/src/xmake/sandbox/interactive.c | 5 +++++ xmake/core/_xmake_main.lua | 4 ++-- xmake/core/base/bytes.lua | 3 ++- xmake/core/base/table.lua | 9 ++++++++- xmake/core/sandbox/modules/interpreter/print.lua | 5 +++-- xmake/core/sandbox/modules/interpreter/unpack.lua | 2 +- xmake/core/sandbox/modules/unpack.lua | 2 +- 10 files changed, 62 insertions(+), 22 deletions(-) diff --git a/core/src/lcurses/lcurses.c b/core/src/lcurses/lcurses.c index f3bdf7244..a55b86606 100644 --- a/core/src/lcurses/lcurses.c +++ b/core/src/lcurses/lcurses.c @@ -2431,8 +2431,11 @@ int xm_curses_register (lua_State *L) lua_pushliteral(L, "__index"); lua_pushvalue(L, -2); /* push metatable */ lua_rawset(L, -3); /* metatable.__index = metatable */ +#if 0 luaL_openlib(L, NULL, windowlib, 0); - +#else + luaL_setfuncs(L, windowlib, 0); +#endif lua_pop(L, 1); /* remove metatable from stack */ /* @@ -2442,8 +2445,11 @@ int xm_curses_register (lua_State *L) lua_pushliteral(L, "__index"); lua_pushvalue(L, -2); /* push metatable */ lua_rawset(L, -3); /* metatable.__index = metatable */ +#if 0 luaL_openlib(L, NULL, chstrlib, 0); - +#else + luaL_setfuncs(L, chstrlib, 0); +#endif lua_pop(L, 1); /* remove metatable from stack */ @@ -2451,7 +2457,11 @@ int xm_curses_register (lua_State *L) ** create global table with curses methods/variables/constants */ lua_newtable(L); +#if 0 luaL_register(L, NULL, curseslib); +#else + luaL_setfuncs(L, curseslib, 0); +#endif lua_pushstring(L, "init"); lua_pushvalue(L, -2); diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index dbea858c1..0793f426e 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -845,41 +845,41 @@ xm_engine_ref_t xm_engine_init(tb_char_t const* name, xm_engine_lni_initalizer_c luaL_openlibs(engine->lua); // bind os functions - luaL_register(engine->lua, "os", g_os_functions); + xm_lua_register(engine->lua, "os", g_os_functions); // bind io functions - luaL_register(engine->lua, "io", g_io_functions); + xm_lua_register(engine->lua, "io", g_io_functions); // bind path functions - luaL_register(engine->lua, "path", g_path_functions); + xm_lua_register(engine->lua, "path", g_path_functions); // bind hash functions - luaL_register(engine->lua, "hash", g_hash_functions); + xm_lua_register(engine->lua, "hash", g_hash_functions); // bind string functions - luaL_register(engine->lua, "string", g_string_functions); + xm_lua_register(engine->lua, "string", g_string_functions); // bind process functions - luaL_register(engine->lua, "process", g_process_functions); + xm_lua_register(engine->lua, "process", g_process_functions); // bind sandbox functions - luaL_register(engine->lua, "sandbox", g_sandbox_functions); + xm_lua_register(engine->lua, "sandbox", g_sandbox_functions); // bind windows functions #ifdef TB_CONFIG_OS_WINDOWS - luaL_register(engine->lua, "winos", g_winos_functions); + xm_lua_register(engine->lua, "winos", g_winos_functions); #endif #ifdef XM_CONFIG_API_HAVE_READLINE // bind readline functions - luaL_register(engine->lua, "readline", g_readline_functions); + xm_lua_register(engine->lua, "readline", g_readline_functions); #endif // bind semver functions - luaL_register(engine->lua, "semver", g_semver_functions); + xm_lua_register(engine->lua, "semver", g_semver_functions); // bind libc functions - luaL_register(engine->lua, "libc", g_libc_functions); + xm_lua_register(engine->lua, "libc", g_libc_functions); #ifdef XM_CONFIG_API_HAVE_CURSES // bind curses @@ -1059,7 +1059,7 @@ tb_void_t xm_engine_register(xm_engine_ref_t self, tb_char_t const* module, luaL // do register lua_pushstring(engine->lua, module); lua_newtable(engine->lua); - luaL_register(engine->lua, tb_null, funcs); + xm_lua_register(engine->lua, tb_null, funcs); lua_rawset(engine->lua, -3); } tb_int_t xm_engine_run(tb_char_t const* name, tb_int_t argc, tb_char_t** argv, tb_char_t** taskargv, xm_engine_lni_initalizer_cb_t lni_initalizer) diff --git a/core/src/xmake/prefix.h b/core/src/xmake/prefix.h index f78b61127..fabb775fb 100644 --- a/core/src/xmake/prefix.h +++ b/core/src/xmake/prefix.h @@ -114,6 +114,22 @@ static __tb_inline__ tb_pointer_t xm_lua_topointer(lua_State* lua, tb_int_t idx) } #endif +static __tb_inline__ tb_void_t xm_lua_register(lua_State *lua, tb_char_t const* libname, luaL_Reg const* l) +{ +#if LUA_VERSION_NUM >= 504 + lua_getglobal(lua, libname); + if (lua_isnil(lua, -1)) + { + lua_pop(lua, 1); + lua_newtable(lua); + } + luaL_setfuncs(lua, l, 0); + lua_setglobal(lua, libname); +#else + luaL_register(lua, libname, l); +#endif +} + #endif diff --git a/core/src/xmake/sandbox/interactive.c b/core/src/xmake/sandbox/interactive.c index a62f6f77c..3b6ef3ff4 100644 --- a/core/src/xmake/sandbox/interactive.c +++ b/core/src/xmake/sandbox/interactive.c @@ -51,6 +51,11 @@ // buffer size for prompt #define LUA_PROMPT_BUFSIZE 4096 +// for lua5.4 +#ifndef LUA_QL +# define LUA_QL(x) "'" x "'" +#endif + /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ diff --git a/xmake/core/_xmake_main.lua b/xmake/core/_xmake_main.lua index cf82a5a9c..b35768058 100644 --- a/xmake/core/_xmake_main.lua +++ b/xmake/core/_xmake_main.lua @@ -120,8 +120,8 @@ function loadfile(filepath, mode, opt) return script, errors end --- init package path -table.insert(package.loaders, 2, function(v) +-- init package path, package.searchers for lua5.4 +table.insert(package.loaders or package.searchers, 2, function(v) local filepath = xmake._PROGRAM_DIR .. "/core/" .. v .. ".lua" local script, serr = _loadfile_impl(filepath) if not script then diff --git a/xmake/core/base/bytes.lua b/xmake/core/base/bytes.lua index 9f7b6ca4f..bb65d0cfc 100644 --- a/xmake/core/base/bytes.lua +++ b/xmake/core/base/bytes.lua @@ -28,6 +28,7 @@ local os = require("base/os") local utils = require("base/utils") local todisplay = require("base/todisplay") local libc = require("base/libc") +local table = require("base/table") -- new a bytes instance -- @@ -42,7 +43,7 @@ local libc = require("base/libc") -- function _instance.new(...) local args = {...} - local arg1, arg2, arg3 = unpack(args) + local arg1, arg2, arg3 = table.unpack(args) local instance = table.inherit(_instance) if type(arg1) == "number" then local size = arg1 diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua index 1e93efd8d..372e5f975 100644 --- a/xmake/core/base/table.lua +++ b/xmake/core/base/table.lua @@ -53,6 +53,13 @@ if not table.getn then end end +-- get array max length for lua5.4 +if not table.maxn then + function table.maxn(t) + return #t + end +end + -- move values of table(a1) to table(a2) -- -- disable the builtin implementation for android termux/arm64, it will crash when calling `table.move({1, 1}, 1, 2, 1, {})` @@ -322,7 +329,7 @@ end -- unpack table values -- polyfill of lua 5.2, @see https://www.lua.org/manual/5.2/manual.html#pdf-table.unpack -table.unpack = unpack +table.unpack = table.unpack or unpack -- get keys of a table function table.keys(tab) diff --git a/xmake/core/sandbox/modules/interpreter/print.lua b/xmake/core/sandbox/modules/interpreter/print.lua index 0f906f5a4..dd42c8fe9 100644 --- a/xmake/core/sandbox/modules/interpreter/print.lua +++ b/xmake/core/sandbox/modules/interpreter/print.lua @@ -19,6 +19,7 @@ -- -- load modules +local table = require("base/table") local try = require("sandbox/modules/try") local catch = require("sandbox/modules/catch") @@ -33,13 +34,13 @@ function _print(format, ...) { function () -- attempt to print format string first - io.write(string.format(format, unpack(args)) .. "\n") + io.write(string.format(format, table.unpack(args)) .. "\n") end, catch { function () -- print multi-variables with raw lua action - print(format, unpack(args)) + print(format, table.unpack(args)) end } } diff --git a/xmake/core/sandbox/modules/interpreter/unpack.lua b/xmake/core/sandbox/modules/interpreter/unpack.lua index 766e49f98..d05c3ce3d 100644 --- a/xmake/core/sandbox/modules/interpreter/unpack.lua +++ b/xmake/core/sandbox/modules/interpreter/unpack.lua @@ -19,5 +19,5 @@ -- -- load module -return unpack +return require("base/table").unpack diff --git a/xmake/core/sandbox/modules/unpack.lua b/xmake/core/sandbox/modules/unpack.lua index 766e49f98..d05c3ce3d 100644 --- a/xmake/core/sandbox/modules/unpack.lua +++ b/xmake/core/sandbox/modules/unpack.lua @@ -19,5 +19,5 @@ -- -- load module -return unpack +return require("base/table").unpack -- cgit v1.3.1 From ff96f6c08fcf72b44226626e1d04be60e92ac37c Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 00:01:01 +0800 Subject: fix some unpack --- xmake/actions/run/main.lua | 4 ++-- xmake/core/base/os.lua | 2 +- xmake/core/base/pipe.lua | 2 +- xmake/core/base/scopeinfo.lua | 8 ++++---- xmake/core/base/socket.lua | 4 ++-- xmake/core/base/table.lua | 4 ++-- xmake/core/package/package.lua | 2 +- xmake/core/sandbox/modules/interpreter/unpack.lua | 2 +- xmake/core/sandbox/modules/unpack.lua | 2 +- xmake/core/sandbox/modules/utils.lua | 4 ++-- xmake/includes/check_cflags.lua | 2 +- xmake/includes/check_cfuncs.lua | 2 +- xmake/includes/check_cincludes.lua | 2 +- xmake/includes/check_csnippets.lua | 2 +- xmake/includes/check_ctypes.lua | 2 +- xmake/includes/check_cxxflags.lua | 2 +- xmake/includes/check_cxxfuncs.lua | 2 +- xmake/includes/check_cxxincludes.lua | 2 +- xmake/includes/check_cxxsnippets.lua | 2 +- xmake/includes/check_cxxtypes.lua | 2 +- xmake/includes/check_features.lua | 2 +- xmake/includes/check_links.lua | 2 +- xmake/includes/check_macros.lua | 2 +- xmake/includes/check_syslinks.lua | 2 +- xmake/includes/qt_add_static_plugins.lua | 4 ++-- xmake/modules/lib/detect/pkgconfig.lua | 4 ++-- xmake/modules/package/manager/find_package.lua | 4 ++-- xmake/modules/package/manager/install_package.lua | 4 ++-- xmake/modules/private/action/require/impl/packagenv.lua | 2 +- xmake/modules/private/action/require/impl/search_packages.lua | 2 +- xmake/modules/private/xrepo/action/env.lua | 4 ++-- xmake/rules/qt/load.lua | 4 ++-- xmake/rules/xcode/application/run.lua | 4 ++-- 33 files changed, 47 insertions(+), 47 deletions(-) diff --git a/xmake/actions/run/main.lua b/xmake/actions/run/main.lua index a74845f95..f79a5d6b2 100644 --- a/xmake/actions/run/main.lua +++ b/xmake/actions/run/main.lua @@ -48,10 +48,10 @@ function _do_run_target(target) -- add run environments local addrunenvs, setrunenvs = make_runenvs(target) for name, values in pairs(addrunenvs) do - os.addenv(name, unpack(table.wrap(values))) + os.addenv(name, table.unpack(table.wrap(values))) end for name, value in pairs(setrunenvs) do - os.setenv(name, unpack(table.wrap(value))) + os.setenv(name, table.unpack(table.wrap(value))) end -- debugging? diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index 312d5705d..a4fdb570e 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -377,7 +377,7 @@ end -- match directories -- --- @note only return {} without count to simplify code, e.g. unpack(os.dirs("")) +-- @note only return {} without count to simplify code, e.g. table.unpack(os.dirs("")) -- function os.dirs(pattern, callback) return (os.match(pattern, 'd', callback)) diff --git a/xmake/core/base/pipe.lua b/xmake/core/base/pipe.lua index 5f7c46c06..92ad42bc6 100644 --- a/xmake/core/base/pipe.lua +++ b/xmake/core/base/pipe.lua @@ -67,7 +67,7 @@ function _instance:write(data, opt) return -1, errors end - -- data is bytes? unpack the raw address + -- data is bytes? table.unpack the raw address local datasize = #data if type(data) == "table" and data.caddr then datasize = data:size() diff --git a/xmake/core/base/scopeinfo.lua b/xmake/core/base/scopeinfo.lua index 1f07e236f..6c0563da2 100644 --- a/xmake/core/base/scopeinfo.lua +++ b/xmake/core/base/scopeinfo.lua @@ -451,7 +451,7 @@ function _instance:apival_set(name, ...) local array = name for _, dict in ipairs(array) do for k, v in pairs(dict) do - self:apival_set(k, unpack(table.wrap(v))) + self:apival_set(k, table.unpack(table.wrap(v))) end end @@ -459,7 +459,7 @@ function _instance:apival_set(name, ...) elseif table.is_dictionary(name) then local dict = name for k, v in pairs(dict) do - self:apival_set(k, unpack(table.wrap(v))) + self:apival_set(k, table.unpack(table.wrap(v))) end elseif name ~= nil then os.raise("unknown type(%s) for %s:set(%s, ...)", type(name), self:kind(), name) @@ -487,7 +487,7 @@ function _instance:apival_add(name, ...) local array = name for _, dict in ipairs(array) do for k, v in pairs(dict) do - self:apival_add(k, unpack(table.wrap(v))) + self:apival_add(k, table.unpack(table.wrap(v))) end end @@ -495,7 +495,7 @@ function _instance:apival_add(name, ...) elseif table.is_dictionary(name) then local dict = name for k, v in pairs(dict) do - self:apival_add(k, unpack(table.wrap(v))) + self:apival_add(k, table.unpack(table.wrap(v))) end elseif name ~= nil then os.raise("unknown type(%s) for %s:add(%s, ...)", type(name), self:kind(), name) diff --git a/xmake/core/base/socket.lua b/xmake/core/base/socket.lua index 7269cb504..4e6435c09 100644 --- a/xmake/core/base/socket.lua +++ b/xmake/core/base/socket.lua @@ -244,7 +244,7 @@ function _instance:send(data, opt) return -1, errors end - -- data is bytes? unpack the raw address + -- data is bytes? table.unpack the raw address local datasize = #data if type(data) == "table" and data.caddr then datasize = data:size() @@ -442,7 +442,7 @@ function _instance:sendto(data, addr, port, opt) return -1, string.format("%s: sendto empty address!", self) end - -- data is bytes? unpack the raw address + -- data is bytes? table.unpack the raw address if type(data) == "table" and data.caddr then data = {data = data:caddr(), size = data:size()} end diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua index 372e5f975..72987c1b6 100644 --- a/xmake/core/base/table.lua +++ b/xmake/core/base/table.lua @@ -327,9 +327,9 @@ function table.pack(...) return { n = select("#", ...), ... } end --- unpack table values +-- table.unpack table values -- polyfill of lua 5.2, @see https://www.lua.org/manual/5.2/manual.html#pdf-table.unpack -table.unpack = table.unpack or unpack +table.unpack = table.unpack or table.unpack -- get keys of a table function table.keys(tab) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index e636cfbf5..80f7e9904 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -731,7 +731,7 @@ function _instance:envs_enter() end end else - os.addenv(name, unpack(table.wrap(values))) + os.addenv(name, table.unpack(table.wrap(values))) end end end diff --git a/xmake/core/sandbox/modules/interpreter/unpack.lua b/xmake/core/sandbox/modules/interpreter/unpack.lua index d05c3ce3d..5d3b9c811 100644 --- a/xmake/core/sandbox/modules/interpreter/unpack.lua +++ b/xmake/core/sandbox/modules/interpreter/unpack.lua @@ -15,7 +15,7 @@ -- Copyright (C) 2015-present, TBOOX Open Source Group. -- -- @author ruki --- @file unpack.lua +-- @file table.unpack.lua -- -- load module diff --git a/xmake/core/sandbox/modules/unpack.lua b/xmake/core/sandbox/modules/unpack.lua index d05c3ce3d..5d3b9c811 100644 --- a/xmake/core/sandbox/modules/unpack.lua +++ b/xmake/core/sandbox/modules/unpack.lua @@ -15,7 +15,7 @@ -- Copyright (C) 2015-present, TBOOX Open Source Group. -- -- @author ruki --- @file unpack.lua +-- @file table.unpack.lua -- -- load module diff --git a/xmake/core/sandbox/modules/utils.lua b/xmake/core/sandbox/modules/utils.lua index 528f59b9e..59b4cf628 100644 --- a/xmake/core/sandbox/modules/utils.lua +++ b/xmake/core/sandbox/modules/utils.lua @@ -75,7 +75,7 @@ function sandbox_utils.print(format, ...) { function () -- attempt to format message - local message = vformat(format, unpack(args)) + local message = vformat(format, table.unpack(args)) -- trace utils._print(message) @@ -87,7 +87,7 @@ function sandbox_utils.print(format, ...) { function (errors) -- print multi-variables with raw lua action - sandbox_utils._print(format, unpack(args)) + sandbox_utils._print(format, table.unpack(args)) end } } diff --git a/xmake/includes/check_cflags.lua b/xmake/includes/check_cflags.lua index ef3f7866b..63354dfac 100644 --- a/xmake/includes/check_cflags.lua +++ b/xmake/includes/check_cflags.lua @@ -55,7 +55,7 @@ end function configvar_check_cflags(definition, flags, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) - local defname, defval = unpack(definition:split('=')) + local defname, defval = table.unpack(definition:split('=')) save_scope() option(optname) if opt.default == nil then diff --git a/xmake/includes/check_cfuncs.lua b/xmake/includes/check_cfuncs.lua index 1a64cb250..51352e424 100644 --- a/xmake/includes/check_cfuncs.lua +++ b/xmake/includes/check_cfuncs.lua @@ -76,7 +76,7 @@ end function configvar_check_cfuncs(definition, funcs, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) - local defname, defval = unpack(definition:split('=')) + local defname, defval = table.unpack(definition:split('=')) save_scope() option(optname) add_cfuncs(funcs) diff --git a/xmake/includes/check_cincludes.lua b/xmake/includes/check_cincludes.lua index dc0308a65..c954b5260 100644 --- a/xmake/includes/check_cincludes.lua +++ b/xmake/includes/check_cincludes.lua @@ -51,7 +51,7 @@ end function configvar_check_cincludes(definition, includes, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) - local defname, defval = unpack(definition:split('=')) + local defname, defval = table.unpack(definition:split('=')) save_scope() option(optname) add_cincludes(includes) diff --git a/xmake/includes/check_csnippets.lua b/xmake/includes/check_csnippets.lua index 9d2370ee0..19e87ab9e 100644 --- a/xmake/includes/check_csnippets.lua +++ b/xmake/includes/check_csnippets.lua @@ -87,7 +87,7 @@ end function configvar_check_csnippets(definition, snippets, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) - local defname, defval = unpack(definition:split('=')) + local defname, defval = table.unpack(definition:split('=')) save_scope() option(optname) add_csnippets(definition, snippets, {tryrun = opt.tryrun, output = opt.output}) diff --git a/xmake/includes/check_ctypes.lua b/xmake/includes/check_ctypes.lua index b3f59b04e..d14c64aa7 100644 --- a/xmake/includes/check_ctypes.lua +++ b/xmake/includes/check_ctypes.lua @@ -64,7 +64,7 @@ end function configvar_check_ctypes(definition, types, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) - local defname, defval = unpack(definition:split('=')) + local defname, defval = table.unpack(definition:split('=')) save_scope() option(optname) add_ctypes(types) diff --git a/xmake/includes/check_cxxflags.lua b/xmake/includes/check_cxxflags.lua index 38ea5172e..c93745134 100644 --- a/xmake/includes/check_cxxflags.lua +++ b/xmake/includes/check_cxxflags.lua @@ -55,7 +55,7 @@ end function configvar_check_cxxflags(definition, flags, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) - local defname, defval = unpack(definition:split('=')) + local defname, defval = table.unpack(definition:split('=')) save_scope() option(optname) if opt.default == nil then diff --git a/xmake/includes/check_cxxfuncs.lua b/xmake/includes/check_cxxfuncs.lua index 1488f7312..241effd19 100644 --- a/xmake/includes/check_cxxfuncs.lua +++ b/xmake/includes/check_cxxfuncs.lua @@ -76,7 +76,7 @@ end function configvar_check_cxxfuncs(definition, funcs, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) - local defname, defval = unpack(definition:split('=')) + local defname, defval = table.unpack(definition:split('=')) save_scope() option(optname) add_cxxfuncs(funcs) diff --git a/xmake/includes/check_cxxincludes.lua b/xmake/includes/check_cxxincludes.lua index 45cb2d2c0..15f4fa1df 100644 --- a/xmake/includes/check_cxxincludes.lua +++ b/xmake/includes/check_cxxincludes.lua @@ -48,7 +48,7 @@ end function configvar_check_cxxincludes(definition, includes, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) - local defname, defval = unpack(definition:split('=')) + local defname, defval = table.unpack(definition:split('=')) save_scope() option(optname) add_cxxincludes(includes) diff --git a/xmake/includes/check_cxxsnippets.lua b/xmake/includes/check_cxxsnippets.lua index daa71780c..9405b5707 100644 --- a/xmake/includes/check_cxxsnippets.lua +++ b/xmake/includes/check_cxxsnippets.lua @@ -87,7 +87,7 @@ end function configvar_check_cxxsnippets(definition, snippets, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) - local defname, defval = unpack(definition:split('=')) + local defname, defval = table.unpack(definition:split('=')) save_scope() option(optname) add_cxxsnippets(definition, snippets, {tryrun = opt.tryrun, output = opt.output}) diff --git a/xmake/includes/check_cxxtypes.lua b/xmake/includes/check_cxxtypes.lua index f5b8c677a..928ecbad5 100644 --- a/xmake/includes/check_cxxtypes.lua +++ b/xmake/includes/check_cxxtypes.lua @@ -64,7 +64,7 @@ end function configvar_check_cxxtypes(definition, types, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) - local defname, defval = unpack(definition:split('=')) + local defname, defval = table.unpack(definition:split('=')) save_scope() option(optname) add_cxxtypes(types) diff --git a/xmake/includes/check_features.lua b/xmake/includes/check_features.lua index 3e8fb47be..481d9b6fe 100644 --- a/xmake/includes/check_features.lua +++ b/xmake/includes/check_features.lua @@ -60,7 +60,7 @@ end function configvar_check_features(definition, features, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) - local defname, defval = unpack(definition:split('=')) + local defname, defval = table.unpack(definition:split('=')) save_scope() option(optname) add_features(features) diff --git a/xmake/includes/check_links.lua b/xmake/includes/check_links.lua index 54891361e..25ddaa619 100644 --- a/xmake/includes/check_links.lua +++ b/xmake/includes/check_links.lua @@ -48,7 +48,7 @@ end function configvar_check_links(definition, links, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) - local defname, defval = unpack(definition:split('=')) + local defname, defval = table.unpack(definition:split('=')) save_scope() option(optname) add_links(links) diff --git a/xmake/includes/check_macros.lua b/xmake/includes/check_macros.lua index 0ed879c95..352a2382f 100644 --- a/xmake/includes/check_macros.lua +++ b/xmake/includes/check_macros.lua @@ -81,7 +81,7 @@ end function configvar_check_macros(definition, macros, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) - local defname, defval = unpack(definition:split('=')) + local defname, defval = table.unpack(definition:split('=')) local snippets = {} save_scope() option(optname) diff --git a/xmake/includes/check_syslinks.lua b/xmake/includes/check_syslinks.lua index 8df32a1b8..379bb005a 100644 --- a/xmake/includes/check_syslinks.lua +++ b/xmake/includes/check_syslinks.lua @@ -48,7 +48,7 @@ end function configvar_check_syslinks(definition, links, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) - local defname, defval = unpack(definition:split('=')) + local defname, defval = table.unpack(definition:split('=')) save_scope() option(optname) add_syslinks(links) diff --git a/xmake/includes/qt_add_static_plugins.lua b/xmake/includes/qt_add_static_plugins.lua index 8ecb06056..e65965972 100644 --- a/xmake/includes/qt_add_static_plugins.lua +++ b/xmake/includes/qt_add_static_plugins.lua @@ -34,10 +34,10 @@ function qt_add_static_plugins(plugin, opt) opt = opt or {} add_values("qt.plugins", plugin) if opt.links then - add_values("qt.links", unpack(table.wrap(opt.links))) + add_values("qt.links", table.unpack(table.wrap(opt.links))) end if opt.linkdirs then - add_values("qt.linkdirs", unpack(table.wrap(opt.linkdirs))) + add_values("qt.linkdirs", table.unpack(table.wrap(opt.linkdirs))) end end diff --git a/xmake/modules/lib/detect/pkgconfig.lua b/xmake/modules/lib/detect/pkgconfig.lua index 9cd07a1e7..57726bae0 100644 --- a/xmake/modules/lib/detect/pkgconfig.lua +++ b/xmake/modules/lib/detect/pkgconfig.lua @@ -46,7 +46,7 @@ function version(name, opt) local configdirs_old = os.getenv("PKG_CONFIG_PATH") local configdirs = table.wrap(opt.configdirs) if #configdirs > 0 then - os.setenv("PKG_CONFIG_PATH", unpack(configdirs)) + os.setenv("PKG_CONFIG_PATH", table.unpack(configdirs)) end -- get version @@ -85,7 +85,7 @@ function variables(name, variables, opt) local configdirs_old = os.getenv("PKG_CONFIG_PATH") local configdirs = table.wrap(opt.configdirs) if #configdirs > 0 then - os.setenv("PKG_CONFIG_PATH", unpack(configdirs)) + os.setenv("PKG_CONFIG_PATH", table.unpack(configdirs)) end -- get variable value diff --git a/xmake/modules/package/manager/find_package.lua b/xmake/modules/package/manager/find_package.lua index 41c110796..7d82043b2 100644 --- a/xmake/modules/package/manager/find_package.lua +++ b/xmake/modules/package/manager/find_package.lua @@ -174,7 +174,7 @@ function main(name, opt) opt.mode = opt.mode or config.mode() or "release" -- get package manager name - local manager_name, package_name = unpack(name:split("::", {plain = true, strict = true})) + local manager_name, package_name = table.unpack(name:split("::", {plain = true, strict = true})) if package_name == nil then package_name = manager_name manager_name = nil @@ -184,7 +184,7 @@ function main(name, opt) -- get package name and require version local require_version = nil - package_name, require_version = unpack(package_name:trim():split("%s")) + package_name, require_version = table.unpack(package_name:trim():split("%s")) opt.require_version = require_version or opt.require_version -- find package diff --git a/xmake/modules/package/manager/install_package.lua b/xmake/modules/package/manager/install_package.lua index 1c5d5ab07..05e13ed27 100644 --- a/xmake/modules/package/manager/install_package.lua +++ b/xmake/modules/package/manager/install_package.lua @@ -93,7 +93,7 @@ function main(name, opt) opt.mode = opt.mode or config.mode() or "release" -- get package manager name - local manager_name, package_name = unpack(name:split("::", {plain = true, strict = true})) + local manager_name, package_name = table.unpack(name:split("::", {plain = true, strict = true})) if package_name == nil then package_name = manager_name manager_name = nil @@ -103,7 +103,7 @@ function main(name, opt) -- get package name and require version local require_version = nil - package_name, require_version = unpack(package_name:trim():split("%s")) + package_name, require_version = table.unpack(package_name:trim():split("%s")) opt.require_version = require_version or opt.require_version -- do install package diff --git a/xmake/modules/private/action/require/impl/packagenv.lua b/xmake/modules/private/action/require/impl/packagenv.lua index 12a98d36f..06a70df91 100644 --- a/xmake/modules/private/action/require/impl/packagenv.lua +++ b/xmake/modules/private/action/require/impl/packagenv.lua @@ -33,7 +33,7 @@ function _enter_package(package_name, envs, installdir) end end else - os.addenv(name, unpack(table.wrap(values))) + os.addenv(name, table.unpack(table.wrap(values))) end end end diff --git a/xmake/modules/private/action/require/impl/search_packages.lua b/xmake/modules/private/action/require/impl/search_packages.lua index 00cf1ffbf..276747db4 100644 --- a/xmake/modules/private/action/require/impl/search_packages.lua +++ b/xmake/modules/private/action/require/impl/search_packages.lua @@ -22,7 +22,7 @@ function _search_packages(name) -- get package manager name - local manager_name, package_name = unpack(name:split("::", {plain = true, strict = true})) + local manager_name, package_name = table.unpack(name:split("::", {plain = true, strict = true})) if package_name == nil then package_name = manager_name manager_name = "xmake" diff --git a/xmake/modules/private/xrepo/action/env.lua b/xmake/modules/private/xrepo/action/env.lua index b29d01623..742d30d12 100644 --- a/xmake/modules/private/xrepo/action/env.lua +++ b/xmake/modules/private/xrepo/action/env.lua @@ -208,7 +208,7 @@ function _package_addenvs(envs, instance) end end else - _addenvs(envs, name, unpack(table.wrap(values))) + _addenvs(envs, name, table.unpack(table.wrap(values))) end end @@ -237,7 +237,7 @@ function _toolchain_addenvs(envs) local toolchain_inst = toolchain.load(name, toolchain_opt) if toolchain_inst then for k, v in pairs(toolchain_inst:runenvs()) do - _addenvs(envs, k, unpack(path.splitenv(v))) + _addenvs(envs, k, table.unpack(path.splitenv(v))) end end end diff --git a/xmake/rules/qt/load.lua b/xmake/rules/qt/load.lua index 1c4627f11..c5bec10af 100644 --- a/xmake/rules/qt/load.lua +++ b/xmake/rules/qt/load.lua @@ -81,10 +81,10 @@ function _add_plugins(target, plugins) for name, plugin in pairs(plugins) do target:values_add("qt.plugins", name) if plugin.links then - target:values_add("qt.links", unpack(table.wrap(plugin.links))) + target:values_add("qt.links", table.unpack(table.wrap(plugin.links))) end if plugin.linkdirs then - target:values_add("qt.linkdirs", unpack(table.wrap(plugin.linkdirs))) + target:values_add("qt.linkdirs", table.unpack(table.wrap(plugin.linkdirs))) end end end diff --git a/xmake/rules/xcode/application/run.lua b/xmake/rules/xcode/application/run.lua index e92397a29..0e0663207 100644 --- a/xmake/rules/xcode/application/run.lua +++ b/xmake/rules/xcode/application/run.lua @@ -40,10 +40,10 @@ function _run_on_macosx(target, opt) -- add run environments local addrunenvs, setrunenvs = make_runenvs(target) for name, values in pairs(addrunenvs) do - os.addenv(name, unpack(table.wrap(values))) + os.addenv(name, table.unpack(table.wrap(values))) end for name, value in pairs(setrunenvs) do - os.setenv(name, unpack(table.wrap(value))) + os.setenv(name, table.unpack(table.wrap(value))) end -- debugging? -- cgit v1.3.1 From 37efd34d9f539e1b98404ad1134aa83b9baee0e4 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 00:02:03 +0800 Subject: fix more unpack --- xmake/core/base/interpreter.lua | 4 ++-- xmake/core/base/scopeinfo.lua | 8 ++++---- xmake/core/sandbox/modules/utils.lua | 4 ++-- xmake/modules/detect/tools/clang_cl/has_flags.lua | 2 +- xmake/modules/detect/tools/dmd/has_flags.lua | 2 +- xmake/modules/detect/tools/fpc/has_flags.lua | 2 +- xmake/modules/detect/tools/go/has_flags.lua | 2 +- xmake/modules/detect/tools/rustc/has_flags.lua | 2 +- xmake/modules/detect/tools/sdcc/has_flags.lua | 2 +- xmake/modules/detect/tools/swiftc/has_flags.lua | 2 +- xmake/modules/detect/tools/zig/has_flags.lua | 2 +- xmake/plugins/lua/main.lua | 2 +- xmake/rules/cuda/gencodes/xmake.lua | 2 +- 13 files changed, 18 insertions(+), 18 deletions(-) diff --git a/xmake/core/base/interpreter.lua b/xmake/core/base/interpreter.lua index 32602c4c4..13225ccd5 100644 --- a/xmake/core/base/interpreter.lua +++ b/xmake/core/base/interpreter.lua @@ -1306,7 +1306,7 @@ function interpreter:api_register_set_paths(scope_kind, ...) end -- translate paths - values = table.join(unpack(values)) + values = table.join(table.unpack(values)) local paths = self:_api_translate_paths(values, "set_" .. name) -- save values @@ -1378,7 +1378,7 @@ function interpreter:api_register_add_paths(scope_kind, ...) end -- translate paths - values = table.join(unpack(values)) + values = table.join(table.unpack(values)) local paths = self:_api_translate_paths(values, "add_" .. name) -- save values diff --git a/xmake/core/base/scopeinfo.lua b/xmake/core/base/scopeinfo.lua index 6c0563da2..9d4888f1c 100644 --- a/xmake/core/base/scopeinfo.lua +++ b/xmake/core/base/scopeinfo.lua @@ -109,7 +109,7 @@ function _instance:_api_set_values(name, ...) end -- expand values - values = table.join(unpack(values)) + values = table.join(table.unpack(values)) -- handle values local handled_values = self:_api_handle(values) @@ -148,7 +148,7 @@ function _instance:_api_add_values(name, ...) end -- expand values - values = table.join(unpack(values)) + values = table.join(table.unpack(values)) -- save values scope[name] = self:_api_handle(table.join2(table.wrap(scope[name]), values)) @@ -311,7 +311,7 @@ function _instance:_api_set_paths(name, ...) end -- expand values - values = table.join(unpack(values)) + values = table.join(table.unpack(values)) -- translate paths local paths = interp:_api_translate_paths(values, "set_" .. name, 5) @@ -351,7 +351,7 @@ function _instance:_api_add_paths(name, ...) end -- expand values - values = table.join(unpack(values)) + values = table.join(table.unpack(values)) -- translate paths local paths = interp:_api_translate_paths(values, "add_" .. name, 5) diff --git a/xmake/core/sandbox/modules/utils.lua b/xmake/core/sandbox/modules/utils.lua index 59b4cf628..b2f9a682a 100644 --- a/xmake/core/sandbox/modules/utils.lua +++ b/xmake/core/sandbox/modules/utils.lua @@ -55,10 +55,10 @@ function sandbox_utils._print(...) end -- print multi-variables with raw lua action - utils._print(unpack(args)) + utils._print(table.unpack(args)) -- write to the log file - log:printv(unpack(args)) + log:printv(table.unpack(args)) end -- print format string with newline diff --git a/xmake/modules/detect/tools/clang_cl/has_flags.lua b/xmake/modules/detect/tools/clang_cl/has_flags.lua index 27728697f..4917fb665 100644 --- a/xmake/modules/detect/tools/clang_cl/has_flags.lua +++ b/xmake/modules/detect/tools/clang_cl/has_flags.lua @@ -61,7 +61,7 @@ function _try_running(...) local argv = {...} local errors = nil - return try { function () os.runv(unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors + return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors end -- try running to check flags diff --git a/xmake/modules/detect/tools/dmd/has_flags.lua b/xmake/modules/detect/tools/dmd/has_flags.lua index 459db9228..235e99d4c 100644 --- a/xmake/modules/detect/tools/dmd/has_flags.lua +++ b/xmake/modules/detect/tools/dmd/has_flags.lua @@ -40,7 +40,7 @@ function _try_running(...) local argv = {...} local errors = nil - return try { function () os.runv(unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors + return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors end -- attempt to check it from the argument list diff --git a/xmake/modules/detect/tools/fpc/has_flags.lua b/xmake/modules/detect/tools/fpc/has_flags.lua index 9f66939cc..109e1014b 100644 --- a/xmake/modules/detect/tools/fpc/has_flags.lua +++ b/xmake/modules/detect/tools/fpc/has_flags.lua @@ -26,7 +26,7 @@ function _try_running(...) local argv = {...} local errors = nil - return try { function () os.runv(unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors + return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors end -- attempt to check it from the argument list diff --git a/xmake/modules/detect/tools/go/has_flags.lua b/xmake/modules/detect/tools/go/has_flags.lua index 267d4de8a..e1acf3769 100644 --- a/xmake/modules/detect/tools/go/has_flags.lua +++ b/xmake/modules/detect/tools/go/has_flags.lua @@ -35,7 +35,7 @@ function _try_running(...) local argv = {...} local errors = nil - return try { function () os.runv(unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors + return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors end -- attempt to check it from the argument list diff --git a/xmake/modules/detect/tools/rustc/has_flags.lua b/xmake/modules/detect/tools/rustc/has_flags.lua index e7c55a180..904a3c85a 100644 --- a/xmake/modules/detect/tools/rustc/has_flags.lua +++ b/xmake/modules/detect/tools/rustc/has_flags.lua @@ -26,7 +26,7 @@ function _try_running(...) local argv = {...} local errors = nil - return try { function () os.runv(unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors + return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors end -- attempt to check it from the argument list diff --git a/xmake/modules/detect/tools/sdcc/has_flags.lua b/xmake/modules/detect/tools/sdcc/has_flags.lua index 1198b6f44..c7c440a8a 100644 --- a/xmake/modules/detect/tools/sdcc/has_flags.lua +++ b/xmake/modules/detect/tools/sdcc/has_flags.lua @@ -41,7 +41,7 @@ function _try_running(...) local argv = {...} local errors = nil - return try { function () os.runv(unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors + return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors end -- attempt to check it from the argument list diff --git a/xmake/modules/detect/tools/swiftc/has_flags.lua b/xmake/modules/detect/tools/swiftc/has_flags.lua index 541b897a9..fc4ff6540 100644 --- a/xmake/modules/detect/tools/swiftc/has_flags.lua +++ b/xmake/modules/detect/tools/swiftc/has_flags.lua @@ -26,7 +26,7 @@ function _try_running(...) local argv = {...} local errors = nil - return try { function () os.runv(unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors + return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors end -- attempt to check it from the argument list diff --git a/xmake/modules/detect/tools/zig/has_flags.lua b/xmake/modules/detect/tools/zig/has_flags.lua index b12f3defb..1dea91cfe 100644 --- a/xmake/modules/detect/tools/zig/has_flags.lua +++ b/xmake/modules/detect/tools/zig/has_flags.lua @@ -34,7 +34,7 @@ function _try_running(...) local argv = {...} local errors = nil - return try { function () os.runv(unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors + return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors end -- attempt to check it from the argument list diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 40b16249e..cf0ed80a1 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -122,7 +122,7 @@ function _run_script(script, args) if _is_callable(func) then local result = table.pack(func(table.unpack(args, 1, args.n))) if printresult and result and result.n ~= 0 then - utils.dump(unpack(result, 1, result.n)) + utils.dump(table.unpack(result, 1, result.n)) end else -- dump variables directly diff --git a/xmake/rules/cuda/gencodes/xmake.lua b/xmake/rules/cuda/gencodes/xmake.lua index b5ebc22d1..e208c1f4f 100644 --- a/xmake/rules/cuda/gencodes/xmake.lua +++ b/xmake/rules/cuda/gencodes/xmake.lua @@ -112,7 +112,7 @@ rule("cuda.gencodes") if v_arch then table.insert(r_archs, v_arch) else - v_arch = math.min(unpack(r_archs)) + v_arch = math.min(table.unpack(r_archs)) end r_archs = table.unique(r_archs) -- cgit v1.3.1 From fc545b0e7bfd7441ea03f30c52fa373124186f4b Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 00:05:36 +0800 Subject: fix table.unpack --- xmake/core/base/table.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua index 72987c1b6..f571a4553 100644 --- a/xmake/core/base/table.lua +++ b/xmake/core/base/table.lua @@ -328,8 +328,8 @@ function table.pack(...) end -- table.unpack table values --- polyfill of lua 5.2, @see https://www.lua.org/manual/5.2/manual.html#pdf-table.unpack -table.unpack = table.unpack or table.unpack +-- polyfill of lua 5.2, @see https://www.lua.org/manual/5.2/manual.html#pdf-unpack +table.unpack = table.unpack or unpack -- get keys of a table function table.keys(tab) -- cgit v1.3.1 From f706a145a7d3da0ca1d8267a1016b15dcf1e5a58 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 09:17:11 +0800 Subject: fix table.maxn for lua54 --- xmake/core/base/table.lua | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua index f571a4553..5f2c4585a 100644 --- a/xmake/core/base/table.lua +++ b/xmake/core/base/table.lua @@ -53,10 +53,16 @@ if not table.getn then end end --- get array max length for lua5.4 +-- get array max integer key for lua5.4 if not table.maxn then function table.maxn(t) - return #t + local max = 0 + for k, _ in pairs(t) do + if type(k) == "number" and k > max then + max = k + end + end + return max end end -- cgit v1.3.1 From 998fe56110752f9ae8e4c298aec0aef174077a2b Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 09:28:20 +0800 Subject: fix loadstring missing --- xmake/core/base/serialize.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/core/base/serialize.lua b/xmake/core/base/serialize.lua index a49122308..2f8030338 100644 --- a/xmake/core/base/serialize.lua +++ b/xmake/core/base/serialize.lua @@ -323,7 +323,7 @@ function serialize.save(obj, opt) end -- binary mode - local func, lerr = loadstring("return " .. result, "=") + local func, lerr = load("return " .. result, "=") if lerr ~= nil then return nil, lerr end -- cgit v1.3.1 From fbcae436aa6cb62ce0fbd317d5ff95ddc744328b Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 09:38:01 +0800 Subject: fix compile error --- core/src/xmake/os/args.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/xmake/os/args.c b/core/src/xmake/os/args.c index 4f1c89f7f..c6de9e6c6 100644 --- a/core/src/xmake/os/args.c +++ b/core/src/xmake/os/args.c @@ -108,7 +108,7 @@ tb_int_t xm_os_args(lua_State* lua) if (lua_istable(lua, 1)) { tb_size_t i = 0; - tb_size_t n = lua_objlen(lua, 1); + tb_size_t n = (tb_size_t)lua_objlen(lua, 1); for (i = 1; i <= n; i++) { // add space -- cgit v1.3.1 From 18154145324b1ae0c9dabee8299149df8ef4ecbd Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 09:46:50 +0800 Subject: fix xmake.lua --- core/src/lua/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/lua/xmake.lua b/core/src/lua/xmake.lua index 9a622a2e9..62326e748 100644 --- a/core/src/lua/xmake.lua +++ b/core/src/lua/xmake.lua @@ -17,7 +17,7 @@ target("lua") add_includedirs("lua", {public = true}) -- add the common source files - add_files("lua/*.c|lua.c") + add_files("lua/*.c|lua.c|onelua.c") -- add defines add_defines("LUA_COMPAT_5_1", "LUA_COMPAT_5_2", "LUA_COMPAT_5_3", {public = true}) -- cgit v1.3.1 From a418cf89392b8df002b4f9e4670ea9cf9a672f6e Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 09:53:48 +0800 Subject: fix error --- core/src/xmake/process/openv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/xmake/process/openv.c b/core/src/xmake/process/openv.c index 46bec2cf5..493ba02ec 100644 --- a/core/src/xmake/process/openv.c +++ b/core/src/xmake/process/openv.c @@ -60,7 +60,7 @@ tb_int_t xm_process_openv(lua_State* lua) tb_check_return_val(shellname, 0); // get the arguments count - tb_long_t argn = lua_objlen(lua, 2); + tb_long_t argn = (tb_long_t)lua_objlen(lua, 2); tb_check_return_val(argn >= 0, 0); // get arguments -- cgit v1.3.1 From 2e17942f7e29307c64a6404e1b1e9cf753b973b9 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 09:59:31 +0800 Subject: fix error --- core/src/xmake/sandbox/interactive.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/xmake/sandbox/interactive.c b/core/src/xmake/sandbox/interactive.c index 3b6ef3ff4..fc0acad12 100644 --- a/core/src/xmake/sandbox/interactive.c +++ b/core/src/xmake/sandbox/interactive.c @@ -258,7 +258,7 @@ static tb_int_t xm_sandbox_loadline(lua_State* lua, tb_int_t top) * stack: arg1(sandbox_scope) scriptbuffer(top) -> ... * after: arg1(sandbox_scope) scriptbuffer scriptfunc(top) -> ... */ - status = luaL_loadbuffer(lua, lua_tostring(lua, -1), lua_strlen(lua, -1), "=stdin"); + status = luaL_loadbuffer(lua, lua_tostring(lua, -1), (size_t)lua_strlen(lua, -1), "=stdin"); // complete? if (!xm_sandbox_incomplete(lua, status)) break; -- cgit v1.3.1 From eb8ceef85ae8181d86e4e977ab060a477510a079 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 10:21:59 +0800 Subject: remove some table.maxn --- xmake/core/base/interpreter.lua | 5 ++--- xmake/core/sandbox/modules/irpairs.lua | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/xmake/core/base/interpreter.lua b/xmake/core/base/interpreter.lua index 13225ccd5..90e0a57e5 100644 --- a/xmake/core/base/interpreter.lua +++ b/xmake/core/base/interpreter.lua @@ -459,13 +459,12 @@ function interpreter:_filter(values, level) else -- filter value or arrays values = table.wrap(values) - for idx = 1, table.maxn(values) do - + for idx = 1, #values do local value = values[idx] if type(value) == "string" then value = filter:handle(value) elseif table.is_array(value) then - for i = 1, table.maxn(value) do + for i = 1, #value do local v = value[i] if type(v) == "string" then v = filter:handle(v) diff --git a/xmake/core/sandbox/modules/irpairs.lua b/xmake/core/sandbox/modules/irpairs.lua index 7cb175173..d59574481 100644 --- a/xmake/core/sandbox/modules/irpairs.lua +++ b/xmake/core/sandbox/modules/irpairs.lua @@ -60,7 +60,7 @@ function sandbox_irpairs(t, filter, ...) -- return iterator and initialized state t = table.wrap(t) - return iter, t, table.maxn(t) + 1 + return iter, t, table.getn(t) + 1 end -- load module -- cgit v1.3.1 From b09c9d8f16682eb201382f1b9be871d18f397fc7 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 13:08:01 +0800 Subject: Update get.ps1 --- scripts/get.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/get.ps1 b/scripts/get.ps1 index a8834718d..f03d80fa4 100755 --- a/scripts/get.ps1 +++ b/scripts/get.ps1 @@ -11,7 +11,7 @@ param ( ) & { - $LastRelease = "v2.5.7" + $LastRelease = "v2.5.8" $ErrorActionPreference = 'Stop' function writeErrorTip($msg) { -- cgit v1.3.1 From 3f673bdf28f6351e6f8ca83d4b84f598079a8e1f Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 20:41:23 +0800 Subject: update readme --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ac3302b0..3206c7485 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### New features * [#1736](https://github.com/xmake-io/xmake/issues/1736): Support wasi-sdk toolchain +* Support Lua 5.4 runtime ## v2.5.8 @@ -1097,6 +1098,7 @@ ### 新特性 * [#1736](https://github.com/xmake-io/xmake/issues/1736): 支持 wasi-sdk 工具链 +* 支持 Lua 5.4 运行时 ## v2.5.8 -- cgit v1.3.1 From a722feae41c2cdc6635a4997f2ebfa4bfbde3e19 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 20:44:27 +0800 Subject: update spec --- scripts/rpmbuild/SPECS/xmake.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/rpmbuild/SPECS/xmake.spec b/scripts/rpmbuild/SPECS/xmake.spec index cbc0e928a..6d2455c2c 100644 --- a/scripts/rpmbuild/SPECS/xmake.spec +++ b/scripts/rpmbuild/SPECS/xmake.spec @@ -1,9 +1,9 @@ -%define xmake_revision 703d5a016e2c1881990fc34e2e989b28e7673aa2 +%define xmake_revision 3f673bdf28f6351e6f8ca83d4b84f598079a8e1f %define tbox_revision 7ca5145d40aa906fdc48b0b0e75e80412241be7e %define sv_revision 9a3cf7c8e589de4f70378824329882c4a047fffc %define lua_cjson_revision 515bab6d6d80b164b94db73af69609ea02f3a798 %define luajit_revision e9af1abec542e6f9851ff2368e7f196b6382a44c -%define lua_revision 75ea9ccbea7c4886f30da147fb67b693b2624c26 +%define lua_revision eadd8c7178c79c814ecca9652973a9b9dd4cc71b %define _binaries_in_noarch_packages_terminate_build 0 %undefine _disable_source_fetch -- cgit v1.3.1 From b2da3200b61621acfb29ab88d1c8f5888f8f9713 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 20:46:17 +0800 Subject: update spec --- scripts/rpmbuild/SPECS/xmake.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/rpmbuild/SPECS/xmake.spec b/scripts/rpmbuild/SPECS/xmake.spec index 6d2455c2c..17d30d457 100644 --- a/scripts/rpmbuild/SPECS/xmake.spec +++ b/scripts/rpmbuild/SPECS/xmake.spec @@ -8,7 +8,7 @@ %undefine _disable_source_fetch Name: xmake -Version: 2.5.7 +Version: 2.5.8 Release: 1%{?dist} Summary: A cross-platform build utility based on Lua BuildArch: noarch -- cgit v1.3.1 From 0fe9bb8a7018b7b183873c3dcd8856bf7ea6b6c9 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 21:07:03 +0800 Subject: improve languages --- xmake/modules/core/tools/gcc.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index 2cf31e2dc..99938e59a 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -199,8 +199,8 @@ function nf_language(self, stdname) , gnuxx17 = "-std=gnu++17" , cxx1z = "-std=c++1z" , gnuxx1z = "-std=gnu++1z" - , cxx20 = "-std=c++20" - , gnuxx20 = "-std=gnu++20" + , cxx20 = {"-std=c++20", "-std=c++2a"} + , gnuxx20 = {"-std=gnu++20", "-std=c++2a"} , cxx2a = "-std=c++2a" , gnuxx2a = "-std=gnu++2a" , cxxlatest = {"-std=c++20", "-std=c++2a", "-std=c++17", "-std=c++14", "-std=c++11", "-std=c++1z", "-std=c++98"} -- cgit v1.3.1 From 0594b7cddec091cc9b91e06cf2ee61e4e671b595 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 21:33:03 +0800 Subject: fix languages --- xmake/modules/core/tools/cl.lua | 3 ++- xmake/modules/core/tools/gcc.lua | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/xmake/modules/core/tools/cl.lua b/xmake/modules/core/tools/cl.lua index efea29a14..6181af7d9 100644 --- a/xmake/modules/core/tools/cl.lua +++ b/xmake/modules/core/tools/cl.lua @@ -250,8 +250,9 @@ function nf_language(self, stdname) break end end + else + return result end - return result end -- make the define flag diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index 99938e59a..b9447a151 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -229,8 +229,9 @@ function nf_language(self, stdname) break end end + else + return result end - return result end -- make the define flag -- cgit v1.3.1 From c99b30e2dbcc62969c81ab83cf656f7e3b0edd43 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 22:25:22 +0800 Subject: add gcc-xx --- xmake/toolchains/gcc-10/xmake.lua | 3 +++ xmake/toolchains/gcc-11/xmake.lua | 3 +++ xmake/toolchains/gcc-8/xmake.lua | 3 +++ xmake/toolchains/gcc-9/xmake.lua | 3 +++ xmake/toolchains/gcc/xmake.lua | 27 ++++++++++++++++----------- 5 files changed, 28 insertions(+), 11 deletions(-) create mode 100644 xmake/toolchains/gcc-10/xmake.lua create mode 100644 xmake/toolchains/gcc-11/xmake.lua create mode 100644 xmake/toolchains/gcc-8/xmake.lua create mode 100644 xmake/toolchains/gcc-9/xmake.lua diff --git a/xmake/toolchains/gcc-10/xmake.lua b/xmake/toolchains/gcc-10/xmake.lua new file mode 100644 index 000000000..b1e2c8883 --- /dev/null +++ b/xmake/toolchains/gcc-10/xmake.lua @@ -0,0 +1,3 @@ +includes(path.join(os.scriptdir(), "../gcc/xmake.lua")) + +toolchain_gcc("10") diff --git a/xmake/toolchains/gcc-11/xmake.lua b/xmake/toolchains/gcc-11/xmake.lua new file mode 100644 index 000000000..2714c7718 --- /dev/null +++ b/xmake/toolchains/gcc-11/xmake.lua @@ -0,0 +1,3 @@ +includes(path.join(os.scriptdir(), "../gcc/xmake.lua")) + +toolchain_gcc("11") diff --git a/xmake/toolchains/gcc-8/xmake.lua b/xmake/toolchains/gcc-8/xmake.lua new file mode 100644 index 000000000..716477e01 --- /dev/null +++ b/xmake/toolchains/gcc-8/xmake.lua @@ -0,0 +1,3 @@ +includes(path.join(os.scriptdir(), "../gcc/xmake.lua")) + +toolchain_gcc("8") diff --git a/xmake/toolchains/gcc-9/xmake.lua b/xmake/toolchains/gcc-9/xmake.lua new file mode 100644 index 000000000..d33f396f6 --- /dev/null +++ b/xmake/toolchains/gcc-9/xmake.lua @@ -0,0 +1,3 @@ +includes(path.join(os.scriptdir(), "../gcc/xmake.lua")) + +toolchain_gcc("9") diff --git a/xmake/toolchains/gcc/xmake.lua b/xmake/toolchains/gcc/xmake.lua index 54816a98e..06be7cef9 100644 --- a/xmake/toolchains/gcc/xmake.lua +++ b/xmake/toolchains/gcc/xmake.lua @@ -19,7 +19,12 @@ -- -- define toolchain -toolchain("gcc") +function toolchain_gcc(version) +local suffix = "" +if version then + suffix = suffix .. "-" .. version +end +toolchain("gcc" .. suffix) -- set homepage set_homepage("https://gcc.gnu.org/") @@ -29,23 +34,21 @@ toolchain("gcc") set_kind("standalone") -- set toolset - set_toolset("cc", "gcc") - set_toolset("cxx", "gcc", "g++") - set_toolset("ld", "g++", "gcc") - set_toolset("sh", "g++", "gcc") + set_toolset("cc", "gcc" .. suffix) + set_toolset("cxx", "gcc" .. suffix, "g++" .. suffix) + set_toolset("ld", "g++" .. suffix, "gcc" .. suffix) + set_toolset("sh", "g++" .. suffix, "gcc" .. suffix) set_toolset("ar", "ar") set_toolset("ex", "ar") set_toolset("strip", "strip") - set_toolset("mm", "gcc") - set_toolset("mxx", "gcc", "g++") - set_toolset("as", "gcc") + set_toolset("mm", "gcc" .. suffix) + set_toolset("mxx", "gcc" .. suffix, "g++" .. suffix) + set_toolset("as", "gcc" .. suffix) - -- check toolchain on_check(function (toolchain) - return import("lib.detect.find_tool")("gcc") + return import("lib.detect.find_tool")("gcc" .. suffix) end) - -- on load on_load(function (toolchain) -- add march flags @@ -63,3 +66,5 @@ toolchain("gcc") toolchain:add("shflags", march) end end) +end +toolchain_gcc() -- cgit v1.3.1 From 1044a14cd543d0a42c57fb09ae38fd9488fea4f4 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 22:27:08 +0800 Subject: improve gcc-xxx description --- xmake/toolchains/gcc/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/toolchains/gcc/xmake.lua b/xmake/toolchains/gcc/xmake.lua index 06be7cef9..28e58c4a2 100644 --- a/xmake/toolchains/gcc/xmake.lua +++ b/xmake/toolchains/gcc/xmake.lua @@ -28,7 +28,7 @@ toolchain("gcc" .. suffix) -- set homepage set_homepage("https://gcc.gnu.org/") - set_description("GNU Compiler Collection") + set_description("GNU Compiler Collection" .. (version and (" (" .. version .. ")") or "")) -- mark as standalone toolchain set_kind("standalone") -- cgit v1.3.1 From b14cd48bebe5e86e676c94ff74776100f08f2823 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 22:29:50 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3206c7485..3e0c0bcef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * [#1736](https://github.com/xmake-io/xmake/issues/1736): Support wasi-sdk toolchain * Support Lua 5.4 runtime +* Add gcc-8, gcc-9, gcc-10, gcc-11 toolchains ## v2.5.8 @@ -1099,6 +1100,7 @@ * [#1736](https://github.com/xmake-io/xmake/issues/1736): 支持 wasi-sdk 工具链 * 支持 Lua 5.4 运行时 +* 添加 gcc-8, gcc-9, gcc-10, gcc-11 工具链 ## v2.5.8 -- cgit v1.3.1 From f7d079c1a5eef8d875b25e383132e6c114b7e48a Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 22:39:04 +0800 Subject: fix languages --- xmake/modules/core/tools/cl.lua | 2 +- xmake/modules/core/tools/gcc.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/modules/core/tools/cl.lua b/xmake/modules/core/tools/cl.lua index 6181af7d9..9e9f38ab8 100644 --- a/xmake/modules/core/tools/cl.lua +++ b/xmake/modules/core/tools/cl.lua @@ -247,7 +247,7 @@ function nf_language(self, stdname) if self:has_flags(v, "cxflags") then result = v maps[stdname] = result - break + return result end end else diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index b9447a151..49998fec6 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -226,7 +226,7 @@ function nf_language(self, stdname) if self:has_flags(v, "cxflags") then result = v maps[stdname] = result - break + return result end end else -- cgit v1.3.1 From 2a231e4654c2569c347e27351a28ea6c4e95cf0c Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 10 Oct 2021 23:03:20 +0800 Subject: fix module tests --- tests/projects/c++/modules/class/src/hello.mpp | 3 +-- tests/projects/c++/modules/class/src/hello_impl.cpp | 7 +++---- tests/projects/c++/modules/dependence/src/hello_impl.cpp | 6 +++--- tests/projects/c++/modules/hello/src/hello.mpp | 7 +++---- tests/projects/c++/modules/impl_unit/src/hello_impl.cpp | 6 +++--- tests/projects/c++/modules/inline_and_template/src/hello.mpp | 6 +++--- tests/projects/c++/modules/inline_and_template/src/say.mpp | 6 +++--- 7 files changed, 19 insertions(+), 22 deletions(-) diff --git a/tests/projects/c++/modules/class/src/hello.mpp b/tests/projects/c++/modules/class/src/hello.mpp index 9e4ecd960..268964aa3 100644 --- a/tests/projects/c++/modules/class/src/hello.mpp +++ b/tests/projects/c++/modules/class/src/hello.mpp @@ -5,8 +5,7 @@ export namespace hello { public: say(int data); void hello(); - private: int data_; }; -} \ No newline at end of file +} diff --git a/tests/projects/c++/modules/class/src/hello_impl.cpp b/tests/projects/c++/modules/class/src/hello_impl.cpp index 6d0008fbb..b8b572f27 100644 --- a/tests/projects/c++/modules/class/src/hello_impl.cpp +++ b/tests/projects/c++/modules/class/src/hello_impl.cpp @@ -1,14 +1,13 @@ -module hello; - +module; #include - using namespace std; +module hello; + namespace hello { say::say(int data) : data_(data) { } - void say::hello() { cout << "hello, say class: " << data_ << endl; } diff --git a/tests/projects/c++/modules/dependence/src/hello_impl.cpp b/tests/projects/c++/modules/dependence/src/hello_impl.cpp index 5dbc009f4..064afebad 100644 --- a/tests/projects/c++/modules/dependence/src/hello_impl.cpp +++ b/tests/projects/c++/modules/dependence/src/hello_impl.cpp @@ -1,6 +1,7 @@ -module hello; - +module; #include + +module hello; import mod; void inner() { @@ -13,7 +14,6 @@ namespace hello { void say_hello() { ::inner(); } say::say(int data) : data_{data} { - } void say::hello() { diff --git a/tests/projects/c++/modules/hello/src/hello.mpp b/tests/projects/c++/modules/hello/src/hello.mpp index 9bbd036f0..124bd72bc 100644 --- a/tests/projects/c++/modules/hello/src/hello.mpp +++ b/tests/projects/c++/modules/hello/src/hello.mpp @@ -1,11 +1,10 @@ -export module hello; - +module; #include -using namespace std; +export module hello; export namespace hello { void say(const char* str) { printf("%s\n", str); } -} \ No newline at end of file +} diff --git a/tests/projects/c++/modules/impl_unit/src/hello_impl.cpp b/tests/projects/c++/modules/impl_unit/src/hello_impl.cpp index 9cee17cfd..425c7aba4 100644 --- a/tests/projects/c++/modules/impl_unit/src/hello_impl.cpp +++ b/tests/projects/c++/modules/impl_unit/src/hello_impl.cpp @@ -1,9 +1,9 @@ -module hello; - +module; #include - using namespace std; +module hello; + namespace hello { void say_hi() { cout << "hello hi!" << endl; diff --git a/tests/projects/c++/modules/inline_and_template/src/hello.mpp b/tests/projects/c++/modules/inline_and_template/src/hello.mpp index c36d54783..94d40ddaa 100644 --- a/tests/projects/c++/modules/inline_and_template/src/hello.mpp +++ b/tests/projects/c++/modules/inline_and_template/src/hello.mpp @@ -1,9 +1,9 @@ -export module hello; - +module; #include +export module hello; export namespace hello { inline void say_hello() { std::printf("hello world!\n"); } -} \ No newline at end of file +} diff --git a/tests/projects/c++/modules/inline_and_template/src/say.mpp b/tests/projects/c++/modules/inline_and_template/src/say.mpp index b4d05a5f4..ab3290cf9 100644 --- a/tests/projects/c++/modules/inline_and_template/src/say.mpp +++ b/tests/projects/c++/modules/inline_and_template/src/say.mpp @@ -1,11 +1,11 @@ -export module say; - +module; #include +export module say; export class say { public: template void hello() { std::printf("hello, say class: %d\n", N); } -}; \ No newline at end of file +}; -- cgit v1.3.1 From 36124a072680bed917179154383def923154d90f Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 11 Oct 2021 22:57:57 +0800 Subject: add find_package for cmake --- xmake/core/project/target.lua | 4 + .../modules/package/manager/cmake/find_package.lua | 116 +++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 xmake/modules/package/manager/cmake/find_package.lua diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 52126b78c..53d17dadc 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -2088,6 +2088,10 @@ function target.linkname(filename, opt) if filename:startswith("lib") and filename:endswith(".dll.a") then return filename:sub(4, #filename - 6) end + -- for macOS, libxxx.tbd + if filename:startswith("lib") and filename:endswith(".tbd") then + return filename:sub(4, #filename - 4) + end local linkname, count = filename:gsub(target.filename("__pattern__", "static", {plat = opt.plat}):gsub("%.", "%%."):gsub("__pattern__", "(.+)") .. "$", "%1") if count == 0 then linkname, count = filename:gsub(target.filename("__pattern__", "shared", {plat = opt.plat}):gsub("%.", "%%."):gsub("__pattern__", "(.+)") .. "$", "%1") diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua new file mode 100644 index 000000000..ac944462c --- /dev/null +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -0,0 +1,116 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_package.lua +-- + +-- imports +import("core.base.option") +import("core.project.target") +import("lib.detect.find_tool") + +-- find package +function _find_package(cmake, name, opt) + + -- get work directory + local workdir = os.tmpfile() .. ".dir" + os.tryrm(workdir) + os.mkdir(workdir) + + -- generate CMakeLists.txt + local cmakefile = io.open(path.join(workdir, "CMakeLists.txt"), "w") + if cmake.version then + cmakefile:print("cmake_minimum_required(VERSION %s)", cmake.version) + end + cmakefile:print("project(find_package)") + cmakefile:print("find_package(%s REQUIRED)", name) + cmakefile:print("if(%s_FOUND)", name) + cmakefile:print(" message(STATUS \"%s_INCLUDE_DIR=\" ${%s_INCLUDE_DIR})", name:upper(), name:upper()) + cmakefile:print(" message(STATUS \"%s_LIBRARY=\" ${%s_LIBRARY})", name:upper(), name:upper()) + cmakefile:print("endif(%s_FOUND)", name) + cmakefile:close() + + -- run cmake to get output + local links + local linkdirs + local includedirs + local output, errors = try {function() return os.iorunv(cmake.program, {workdir}, {curdir = workdir}) end} + if output then + for _, line in ipairs(output:split("\n", {plain = true})) do + print(line) + local includedir_key = name:upper() .. "_INCLUDE_DIR=" + if line:find(includedir_key, 1, true) then + local splitinfo = line:split(includedir_key) + local includedir = splitinfo[2] + if includedir then + includedirs = includedirs or {} + table.insert(includedirs, includedir) + end + end + + local library_key = name:upper() .. "_LIBRARY=" + if line:find(library_key, 1, true) then + local splitinfo = line:split(library_key) + local library = splitinfo[2] + if library then + local linkdir = path.directory(library) + local link = target.linkname(path.filename(library)) + links = links or {} + linkdirs = linkdirs or {} + table.insert(links, link) + table.insert(linkdirs, linkdir) + end + end + end + end + + -- trace diagnosis info + if option.get("verbose") then + if output then + print(output) + end + if option.get("diagnosis") and errors and errors:trim() ~= "" then + cprint("${color.warning}checkinfo: ${clear dim}" .. errors) + end + end + + -- remove work directory + os.tryrm(workdir) + + -- get results + if links or includedirs then + local results = {} + results.links = links + results.linkdirs = linkdirs + results.includedirs = includedirs + return results + end +end + +-- find package using the cmake package manager +-- +-- @param name the package name +-- @param opt the options, e.g. {verbose = true) +-- +function main(name, opt) + opt = opt or {} + local cmake = find_tool("cmake", {version = true}) + if not cmake then + return + end + return _find_package(cmake, name, opt) +end -- cgit v1.3.1 From 6685d980a2527efc09b9fe6a0fcad41729b911e9 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 11 Oct 2021 22:59:34 +0800 Subject: improve cmake/find_package --- xmake/modules/package/manager/cmake/find_package.lua | 9 +++++++-- xmake/modules/package/manager/conan/find_package.lua | 2 +- xmake/modules/package/manager/conda/find_package.lua | 2 +- xmake/modules/package/manager/vcpkg/find_package.lua | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua index ac944462c..ffc81429f 100644 --- a/xmake/modules/package/manager/cmake/find_package.lua +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -36,8 +36,13 @@ function _find_package(cmake, name, opt) if cmake.version then cmakefile:print("cmake_minimum_required(VERSION %s)", cmake.version) end + -- e.g. OpenCV 4.1.1, Boost COMPONENTS regex system + local requirestr = name + if opt.required_version then + requirestr = requirestr .. " " .. opt.required_version + end cmakefile:print("project(find_package)") - cmakefile:print("find_package(%s REQUIRED)", name) + cmakefile:print("find_package(%s REQUIRED)", requirestr) cmakefile:print("if(%s_FOUND)", name) cmakefile:print(" message(STATUS \"%s_INCLUDE_DIR=\" ${%s_INCLUDE_DIR})", name:upper(), name:upper()) cmakefile:print(" message(STATUS \"%s_LIBRARY=\" ${%s_LIBRARY})", name:upper(), name:upper()) @@ -104,7 +109,7 @@ end -- find package using the cmake package manager -- -- @param name the package name --- @param opt the options, e.g. {verbose = true) +-- @param opt the options, e.g. {verbose = true, required_version = "1.0") -- function main(name, opt) opt = opt or {} diff --git a/xmake/modules/package/manager/conan/find_package.lua b/xmake/modules/package/manager/conan/find_package.lua index d372e2a75..fca3d3891 100644 --- a/xmake/modules/package/manager/conan/find_package.lua +++ b/xmake/modules/package/manager/conan/find_package.lua @@ -59,7 +59,7 @@ end -- find package using the conan package manager -- -- @param name the package name --- @param opt the options, e.g. {verbose = true, version = "1.12.x") +-- @param opt the options, e.g. {verbose = true) -- function main(name, opt) diff --git a/xmake/modules/package/manager/conda/find_package.lua b/xmake/modules/package/manager/conda/find_package.lua index 747e1bc9b..1e09072d4 100644 --- a/xmake/modules/package/manager/conda/find_package.lua +++ b/xmake/modules/package/manager/conda/find_package.lua @@ -52,7 +52,7 @@ end -- find package using the conda package manager -- -- @param name the package name --- @param opt the options, e.g. {verbose = true, version = "1.12.0") +-- @param opt the options, e.g. {verbose = true, require_version = "1.12.0") -- function main(name, opt) diff --git a/xmake/modules/package/manager/vcpkg/find_package.lua b/xmake/modules/package/manager/vcpkg/find_package.lua index 8bb4de8e8..36df275ba 100644 --- a/xmake/modules/package/manager/vcpkg/find_package.lua +++ b/xmake/modules/package/manager/vcpkg/find_package.lua @@ -29,7 +29,7 @@ import("detect.sdks.find_vcpkgdir") -- find package from the vcpkg package manager -- -- @param name the package name, e.g. zlib, pcre --- @param opt the options, e.g. {verbose = true, version = "1.12.x") +-- @param opt the options, e.g. {verbose = true) -- function main(name, opt) -- cgit v1.3.1 From 3fba00d7fcb0a084351498bc36d312a04191bdc4 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 11 Oct 2021 23:06:51 +0800 Subject: improve cmake/find_package to support multi paths --- .../modules/package/manager/cmake/find_package.lua | 77 ++++++++++++++-------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua index ffc81429f..b781997c6 100644 --- a/xmake/modules/package/manager/cmake/find_package.lua +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -44,8 +44,12 @@ function _find_package(cmake, name, opt) cmakefile:print("project(find_package)") cmakefile:print("find_package(%s REQUIRED)", requirestr) cmakefile:print("if(%s_FOUND)", name) - cmakefile:print(" message(STATUS \"%s_INCLUDE_DIR=\" ${%s_INCLUDE_DIR})", name:upper(), name:upper()) - cmakefile:print(" message(STATUS \"%s_LIBRARY=\" ${%s_LIBRARY})", name:upper(), name:upper()) + for _, macroname in ipairs({name, name:upper()}) do + cmakefile:print(" message(STATUS \"%s_INCLUDE_DIR=\" \"${%s_INCLUDE_DIR}\")", macroname, macroname) + cmakefile:print(" message(STATUS \"%s_INCLUDE_DIRS=\" \"${%s_INCLUDE_DIRS}\")", macroname, macroname) + cmakefile:print(" message(STATUS \"%s_LIBRARY=\" \"${%s_LIBRARY}\")", macroname, macroname) + cmakefile:print(" message(STATUS \"%s_LIBS=\" \"${%s_LIBS}\")", macroname, macroname) + end cmakefile:print("endif(%s_FOUND)", name) cmakefile:close() @@ -56,28 +60,49 @@ function _find_package(cmake, name, opt) local output, errors = try {function() return os.iorunv(cmake.program, {workdir}, {curdir = workdir}) end} if output then for _, line in ipairs(output:split("\n", {plain = true})) do - print(line) - local includedir_key = name:upper() .. "_INCLUDE_DIR=" - if line:find(includedir_key, 1, true) then - local splitinfo = line:split(includedir_key) - local includedir = splitinfo[2] - if includedir then - includedirs = includedirs or {} - table.insert(includedirs, includedir) + for _, macroname in ipairs({name, name:upper()}) do + -- parse includedirs + for _, includedir_key in ipairs({macroname .. "_INCLUDE_DIR=", macroname .. "_INCLUDE_DIRS="}) do + if line:find(includedir_key, 1, true) then + local splitinfo = line:split(includedir_key) + local values = splitinfo[2] + if values then + values = values:split(';', {plain = true}) + end + if values then + includedirs = includedirs or {} + table.join2(includedirs, values) + end + end end - end - local library_key = name:upper() .. "_LIBRARY=" - if line:find(library_key, 1, true) then - local splitinfo = line:split(library_key) - local library = splitinfo[2] - if library then - local linkdir = path.directory(library) - local link = target.linkname(path.filename(library)) - links = links or {} - linkdirs = linkdirs or {} - table.insert(links, link) - table.insert(linkdirs, linkdir) + -- parse links and linkdirs + for _, library_key in ipairs({macroname .. "_LIBRARY=", macroname .. "_LIBS="}) do + if line:find(library_key, 1, true) then + local splitinfo = line:split(library_key) + local values = splitinfo[2] + if values then + values = values:split(';', {plain = true}) + end + for _, library in ipairs(values) do + local linkdir = path.directory(library) + if linkdir ~= "." then + linkdirs = linkdirs or {} + table.insert(linkdirs, linkdir) + end + local link = target.linkname(path.filename(library)) + if not link then + -- has been link name? + if path.filename(library) == path.basename(library) and linkdir == "." then + link = library + end + end + if link then + links = links or {} + table.insert(links, link) + end + end + end end end end @@ -97,11 +122,11 @@ function _find_package(cmake, name, opt) os.tryrm(workdir) -- get results - if links or includedirs then + if true then --links or includedirs then local results = {} - results.links = links - results.linkdirs = linkdirs - results.includedirs = includedirs + results.links = table.reverse_unique(links) + results.linkdirs = table.unique(linkdirs) + results.includedirs = table.unique(includedirs) return results end end -- cgit v1.3.1 From 6b567e2681d35ed1614160edc1e9c50bbc2dd635 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 11 Oct 2021 23:27:36 +0800 Subject: add components --- .../modules/package/manager/cmake/find_package.lua | 56 ++++++++++++++++++---- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua index b781997c6..a42b28693 100644 --- a/xmake/modules/package/manager/cmake/find_package.lua +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -41,14 +41,28 @@ function _find_package(cmake, name, opt) if opt.required_version then requirestr = requirestr .. " " .. opt.required_version end + if opt.components then + requirestr = requirestr .. " COMPONENTS" + for _, component in ipairs(opt.components) do + requirestr = requirestr .. " " .. component + end + end cmakefile:print("project(find_package)") cmakefile:print("find_package(%s REQUIRED)", requirestr) cmakefile:print("if(%s_FOUND)", name) - for _, macroname in ipairs({name, name:upper()}) do - cmakefile:print(" message(STATUS \"%s_INCLUDE_DIR=\" \"${%s_INCLUDE_DIR}\")", macroname, macroname) - cmakefile:print(" message(STATUS \"%s_INCLUDE_DIRS=\" \"${%s_INCLUDE_DIRS}\")", macroname, macroname) - cmakefile:print(" message(STATUS \"%s_LIBRARY=\" \"${%s_LIBRARY}\")", macroname, macroname) - cmakefile:print(" message(STATUS \"%s_LIBS=\" \"${%s_LIBS}\")", macroname, macroname) + for _, macro_name in ipairs({name, name:upper()}) do + cmakefile:print(" message(STATUS \"%s_INCLUDE_DIR=\" \"${%s_INCLUDE_DIR}\")", macro_name, macro_name) + cmakefile:print(" message(STATUS \"%s_INCLUDE_DIRS=\" \"${%s_INCLUDE_DIRS}\")", macro_name, macro_name) + cmakefile:print(" message(STATUS \"%s_LIBRARY_DIR=\" \"${%s_LIBRARY_DIR}\")", macro_name, macro_name) + cmakefile:print(" message(STATUS \"%s_LIBRARY_DIRS=\" \"${%s_LIBRARY_DIRS}\")", macro_name, macro_name) + cmakefile:print(" message(STATUS \"%s_LIBRARY=\" \"${%s_LIBRARY}\")", macro_name, macro_name) + cmakefile:print(" message(STATUS \"%s_LIBRARIES=\" \"${%s_LIBRARIES}\")", macro_name, macro_name) + cmakefile:print(" message(STATUS \"%s_LIBS=\" \"${%s_LIBS}\")", macro_name, macro_name) + for _, component in ipairs(opt.components) do + local component_name = component:upper() + cmakefile:print(" message(STATUS \"%s_%s_LIBRARY_RELEASE=\" \"${%s_%s_LIBRARY_RELEASE}\")", + macro_name, component_name, macro_name, component_name) + end end cmakefile:print("endif(%s_FOUND)", name) cmakefile:close() @@ -60,9 +74,9 @@ function _find_package(cmake, name, opt) local output, errors = try {function() return os.iorunv(cmake.program, {workdir}, {curdir = workdir}) end} if output then for _, line in ipairs(output:split("\n", {plain = true})) do - for _, macroname in ipairs({name, name:upper()}) do + for _, macro_name in ipairs({name, name:upper()}) do -- parse includedirs - for _, includedir_key in ipairs({macroname .. "_INCLUDE_DIR=", macroname .. "_INCLUDE_DIRS="}) do + for _, includedir_key in ipairs({macro_name .. "_INCLUDE_DIR=", macro_name .. "_INCLUDE_DIRS="}) do if line:find(includedir_key, 1, true) then local splitinfo = line:split(includedir_key) local values = splitinfo[2] @@ -76,8 +90,23 @@ function _find_package(cmake, name, opt) end end + -- parse linkdirs + for _, linkdir_key in ipairs({macro_name .. "_LIBRARY_DIR=", macro_name .. "_LIBRARY_DIRS="}) do + if line:find(linkdir_key, 1, true) then + local splitinfo = line:split(linkdir_key) + local values = splitinfo[2] + if values then + values = values:split(';', {plain = true}) + end + if values then + linkdirs = linkdirs or {} + table.join2(linkdirs, values) + end + end + end + -- parse links and linkdirs - for _, library_key in ipairs({macroname .. "_LIBRARY=", macroname .. "_LIBS="}) do + for _, library_key in ipairs({macro_name .. "_LIBRARY=", macro_name .. "_LIBS=", macro_name .. "_LIBRARIES="}) do if line:find(library_key, 1, true) then local splitinfo = line:split(library_key) local values = splitinfo[2] @@ -98,6 +127,7 @@ function _find_package(cmake, name, opt) end end if link then + assert(not link:find("::", 1, true), "link(%s) is not supported yet!", link) links = links or {} table.insert(links, link) end @@ -122,7 +152,7 @@ function _find_package(cmake, name, opt) os.tryrm(workdir) -- get results - if true then --links or includedirs then + if links or includedirs then local results = {} results.links = table.reverse_unique(links) results.linkdirs = table.unique(linkdirs) @@ -133,8 +163,14 @@ end -- find package using the cmake package manager -- +-- e.g. +-- +-- find_package("cmake::ZLIB") +-- find_package("cmake::OpenCV", {required_version = "4.1.1"}) +-- find_package("cmake::Boost", {components = {"regex", "system"}}) +-- -- @param name the package name --- @param opt the options, e.g. {verbose = true, required_version = "1.0") +-- @param opt the options, e.g. {verbose = true, required_version = "1.0", components = {"regex", "system"}) -- function main(name, opt) opt = opt or {} -- cgit v1.3.1 From fd92a215ce0dc4ced07737696c857649a190cd5e Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 11 Oct 2021 23:30:12 +0800 Subject: add moduledirs for cmake --- xmake/modules/package/manager/cmake/find_package.lua | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua index a42b28693..7d75c4b21 100644 --- a/xmake/modules/package/manager/cmake/find_package.lua +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -36,6 +36,8 @@ function _find_package(cmake, name, opt) if cmake.version then cmakefile:print("cmake_minimum_required(VERSION %s)", cmake.version) end + cmakefile:print("project(find_package)") + -- e.g. OpenCV 4.1.1, Boost COMPONENTS regex system local requirestr = name if opt.required_version then @@ -47,7 +49,11 @@ function _find_package(cmake, name, opt) requirestr = requirestr .. " " .. component end end - cmakefile:print("project(find_package)") + if opt.moduledirs then + for _, moduledir in ipairs(opt.moduledirs) do + cmakefile:print("add_cmake_modules(%s)", moduledir) + end + end cmakefile:print("find_package(%s REQUIRED)", requirestr) cmakefile:print("if(%s_FOUND)", name) for _, macro_name in ipairs({name, name:upper()}) do @@ -58,11 +64,12 @@ function _find_package(cmake, name, opt) cmakefile:print(" message(STATUS \"%s_LIBRARY=\" \"${%s_LIBRARY}\")", macro_name, macro_name) cmakefile:print(" message(STATUS \"%s_LIBRARIES=\" \"${%s_LIBRARIES}\")", macro_name, macro_name) cmakefile:print(" message(STATUS \"%s_LIBS=\" \"${%s_LIBS}\")", macro_name, macro_name) + --[[ for _, component in ipairs(opt.components) do local component_name = component:upper() cmakefile:print(" message(STATUS \"%s_%s_LIBRARY_RELEASE=\" \"${%s_%s_LIBRARY_RELEASE}\")", macro_name, component_name, macro_name, component_name) - end + end]] end cmakefile:print("endif(%s_FOUND)", name) cmakefile:close() @@ -168,9 +175,12 @@ end -- find_package("cmake::ZLIB") -- find_package("cmake::OpenCV", {required_version = "4.1.1"}) -- find_package("cmake::Boost", {components = {"regex", "system"}}) +-- find_package("cmake::Foo", {moduledirs = "xxx"}) -- -- @param name the package name --- @param opt the options, e.g. {verbose = true, required_version = "1.0", components = {"regex", "system"}) +-- @param opt the options, e.g. {verbose = true, required_version = "1.0", +-- components = {"regex", "system"}, +-- moduledirs = "xxx") -- function main(name, opt) opt = opt or {} -- cgit v1.3.1 From beba6cdb749ddafdd9232f6fed30ee4e174b0652 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 11 Oct 2021 23:34:38 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e0c0bcef..bf3ed6849 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * [#1736](https://github.com/xmake-io/xmake/issues/1736): Support wasi-sdk toolchain * Support Lua 5.4 runtime * Add gcc-8, gcc-9, gcc-10, gcc-11 toolchains +* [#1623](https://github.com/xmake-io/xmake/issues/1632): Support find_package from cmake ## v2.5.8 @@ -1101,6 +1102,7 @@ * [#1736](https://github.com/xmake-io/xmake/issues/1736): 支持 wasi-sdk 工具链 * 支持 Lua 5.4 运行时 * 添加 gcc-8, gcc-9, gcc-10, gcc-11 工具链 +* [#1623](https://github.com/xmake-io/xmake/issues/1632): 支持 find_package 从 cmake 查找包 ## v2.5.8 -- cgit v1.3.1 From fbebeff0b41df6856ba8882a1ba1bc9a8d405fd2 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 11 Oct 2021 23:39:09 +0800 Subject: add c++17/20 features --- tests/apis/check_xxx/xmake.lua | 50 ++++++++++++++++++++++++ xmake/modules/detect/tools/gcc/cxxfeatures.lua | 54 ++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) diff --git a/tests/apis/check_xxx/xmake.lua b/tests/apis/check_xxx/xmake.lua index b412571c4..d5ed6e2fb 100644 --- a/tests/apis/check_xxx/xmake.lua +++ b/tests/apis/check_xxx/xmake.lua @@ -42,6 +42,56 @@ target("foo") configvar_check_macros("NO_GCC", "__GNUC__", {defined = false}) configvar_check_macros("HAS_CXX20", "__cplusplus >= 202002L", {languages = "c++20"}) + local features_cxx17 = { + "cxx_aggregate_bases", + "cxx_aligned_new", + "cxx_capture_star_this", + "cxx_constexpr", + "cxx_deduction_guides", + "cxx_enumerator_attributes", + "cxx_fold_expressions", + "cxx_guaranteed_copy_elision", + "cxx_hex_float", + "cxx_if_constexpr", + "cxx_inheriting_constructors", + "cxx_inline_variables", + "cxx_namespace_attributes", + "cxx_noexcept_function_type", + "cxx_nontype_template_args", + "cxx_nontype_template_parameter_auto", + "cxx_range_based_for", + "cxx_static_assert", + "cxx_structured_bindings", + "cxx_template_template_args", + "cxx_variadic_using"} + for _, feature in ipairs(features_cxx17) do + check_features("HAS_17_" .. feature:upper(), feature, {languages = "c++17"}) + end + + local features_cxx20 = { + "cxx_aggregate_paren_init", + "cxx_char8_t", + "cxx_concepts", + "cxx_conditional_explicit", + "cxx_consteval", + "cxx_constexpr", + "cxx_constexpr_dynamic_alloc", + "cxx_constexpr_in_decltype", + "cxx_constinit", + "cxx_deduction_guides", + "cxx_designated_initializers", + "cxx_generic_lambdas", + "cxx_impl_coroutine", + "cxx_impl_destroying_delete", + "cxx_impl_three_way_comparison", + "cxx_init_captures", + "cxx_modules", + "cxx_nontype_template_args", + "cxx_using_enum"} + for _, feature in ipairs(features_cxx20) do + check_features("HAS_20_" .. feature:upper(), feature, {languages = "c++20"}) + end + target("test") add_deps("foo") set_kind("binary") diff --git a/xmake/modules/detect/tools/gcc/cxxfeatures.lua b/xmake/modules/detect/tools/gcc/cxxfeatures.lua index 96eaecf66..9d628522c 100644 --- a/xmake/modules/detect/tools/gcc/cxxfeatures.lua +++ b/xmake/modules/detect/tools/gcc/cxxfeatures.lua @@ -162,6 +162,60 @@ function main() _set("cxx_variadic_macros", gcc_minver .. " && " .. gcc_cxx0x_defined) _set("cxx_template_template_parameters", gcc_minver .. " && __cplusplus") + -- c++17 language features with predefined macros + -- https://en.cppreference.com/w/cpp/feature_test + local features_cxx17 = { + "__cpp_aggregate_bases", + "__cpp_aligned_new", + "__cpp_capture_star_this", + "__cpp_constexpr", + "__cpp_deduction_guides", + "__cpp_enumerator_attributes", + "__cpp_fold_expressions", + "__cpp_guaranteed_copy_elision", + "__cpp_hex_float", + "__cpp_if_constexpr", + "__cpp_inheriting_constructors", + "__cpp_inline_variables", + "__cpp_namespace_attributes", + "__cpp_noexcept_function_type", + "__cpp_nontype_template_args", + "__cpp_nontype_template_parameter_auto", + "__cpp_range_based_for", + "__cpp_static_assert", + "__cpp_structured_bindings", + "__cpp_template_template_args", + "__cpp_variadic_using"} + for _, feature in ipairs(features_cxx17) do + _set((feature:gsub("__cpp", "cxx")), "__cplusplus && defined(" .. feature .. ")") + end + + -- c++20 language features with predefined macros + -- https://en.cppreference.com/w/cpp/feature_test + local features_cxx20 = { + "__cpp_aggregate_paren_init", + "__cpp_char8_t", + "__cpp_concepts", + "__cpp_conditional_explicit", + "__cpp_consteval", + "__cpp_constexpr", + "__cpp_constexpr_dynamic_alloc", + "__cpp_constexpr_in_decltype", + "__cpp_constinit", + "__cpp_deduction_guides", + "__cpp_designated_initializers", + "__cpp_generic_lambdas", + "__cpp_impl_coroutine", + "__cpp_impl_destroying_delete", + "__cpp_impl_three_way_comparison", + "__cpp_init_captures", + "__cpp_modules", + "__cpp_nontype_template_args", + "__cpp_using_enum"} + for _, feature in ipairs(features_cxx20) do + _set((feature:gsub("__cpp", "cxx")), "__cplusplus && defined(" .. feature .. ")") + end + -- get features return _g.features end -- cgit v1.3.1 From de3e0ce9c27b0d20384335e829dc9920f9b101a2 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 11 Oct 2021 23:39:26 +0800 Subject: update changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf3ed6849..c3ea6812a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ * Add gcc-8, gcc-9, gcc-10, gcc-11 toolchains * [#1623](https://github.com/xmake-io/xmake/issues/1632): Support find_package from cmake +### Changes + +* [#1528](https://github.com/xmake-io/xmake/issues/1528): Check c++17/20 features + ## v2.5.8 ### New features @@ -1104,6 +1108,10 @@ * 添加 gcc-8, gcc-9, gcc-10, gcc-11 工具链 * [#1623](https://github.com/xmake-io/xmake/issues/1632): 支持 find_package 从 cmake 查找包 +### 改进 + +* [#1528](https://github.com/xmake-io/xmake/issues/1528): 检测 c++17/20 特性 + ## v2.5.8 ### 新特性 -- cgit v1.3.1 From 9ae2f2130c571d4d7a3a2981de58112b03331b68 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 12 Oct 2021 00:20:11 +0800 Subject: add preset for cmake/find_package --- xmake/modules/package/manager/cmake/find_package.lua | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua index 7d75c4b21..7e9fe1f2b 100644 --- a/xmake/modules/package/manager/cmake/find_package.lua +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -54,6 +54,13 @@ function _find_package(cmake, name, opt) cmakefile:print("add_cmake_modules(%s)", moduledir) end end + if opt.presets then + for k, v in ipairs(opt.presets) do + if type(v) == "boolean" then + cmakefile:print("set(%s_%s %s)", name, k, v and "ON" or "OFF") + end + end + end cmakefile:print("find_package(%s REQUIRED)", requirestr) cmakefile:print("if(%s_FOUND)", name) for _, macro_name in ipairs({name, name:upper()}) do @@ -64,12 +71,6 @@ function _find_package(cmake, name, opt) cmakefile:print(" message(STATUS \"%s_LIBRARY=\" \"${%s_LIBRARY}\")", macro_name, macro_name) cmakefile:print(" message(STATUS \"%s_LIBRARIES=\" \"${%s_LIBRARIES}\")", macro_name, macro_name) cmakefile:print(" message(STATUS \"%s_LIBS=\" \"${%s_LIBS}\")", macro_name, macro_name) - --[[ - for _, component in ipairs(opt.components) do - local component_name = component:upper() - cmakefile:print(" message(STATUS \"%s_%s_LIBRARY_RELEASE=\" \"${%s_%s_LIBRARY_RELEASE}\")", - macro_name, component_name, macro_name, component_name) - end]] end cmakefile:print("endif(%s_FOUND)", name) cmakefile:close() @@ -174,13 +175,14 @@ end -- -- find_package("cmake::ZLIB") -- find_package("cmake::OpenCV", {required_version = "4.1.1"}) --- find_package("cmake::Boost", {components = {"regex", "system"}}) +-- find_package("cmake::Boost", {components = {"regex", "system"}, presets = {USE_STATIC_LIB = true}}) -- find_package("cmake::Foo", {moduledirs = "xxx"}) -- -- @param name the package name -- @param opt the options, e.g. {verbose = true, required_version = "1.0", -- components = {"regex", "system"}, --- moduledirs = "xxx") +-- moduledirs = "xxx", +-- presets = {USE_STATIC_LIB = true}) -- function main(name, opt) opt = opt or {} -- cgit v1.3.1 From b994f9c2c9d883414728b09a5990e10fb47f24c0 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 12 Oct 2021 00:20:24 +0800 Subject: improve preset for cmake/find_package --- xmake/modules/package/manager/cmake/find_package.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua index 7e9fe1f2b..7c4cc3df0 100644 --- a/xmake/modules/package/manager/cmake/find_package.lua +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -54,10 +54,13 @@ function _find_package(cmake, name, opt) cmakefile:print("add_cmake_modules(%s)", moduledir) end end + -- e.g. set(Boost_USE_STATIC_LIB ON) if opt.presets then for k, v in ipairs(opt.presets) do if type(v) == "boolean" then cmakefile:print("set(%s_%s %s)", name, k, v and "ON" or "OFF") + else + cmakefile:print("set(%s_%s %s)", name, k, tostring(v)) end end end -- cgit v1.3.1 From 732ac08c207edf9baca28424a428e26d24f0032f Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 12 Oct 2021 00:31:46 +0800 Subject: improve cmake/find_package --- .../modules/package/manager/cmake/find_package.lua | 157 +++++++++++---------- 1 file changed, 79 insertions(+), 78 deletions(-) diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua index 7c4cc3df0..653f69f16 100644 --- a/xmake/modules/package/manager/cmake/find_package.lua +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -30,6 +30,7 @@ function _find_package(cmake, name, opt) local workdir = os.tmpfile() .. ".dir" os.tryrm(workdir) os.mkdir(workdir) + io.writefile(path.join(workdir, "test.cpp"), "") -- generate CMakeLists.txt local cmakefile = io.open(path.join(workdir, "CMakeLists.txt"), "w") @@ -58,107 +59,106 @@ function _find_package(cmake, name, opt) if opt.presets then for k, v in ipairs(opt.presets) do if type(v) == "boolean" then - cmakefile:print("set(%s_%s %s)", name, k, v and "ON" or "OFF") + cmakefile:print("set(%s %s)", k, v and "ON" or "OFF") else - cmakefile:print("set(%s_%s %s)", name, k, tostring(v)) + cmakefile:print("set(%s %s)", k, tostring(v)) end end end cmakefile:print("find_package(%s REQUIRED)", requirestr) cmakefile:print("if(%s_FOUND)", name) - for _, macro_name in ipairs({name, name:upper()}) do - cmakefile:print(" message(STATUS \"%s_INCLUDE_DIR=\" \"${%s_INCLUDE_DIR}\")", macro_name, macro_name) - cmakefile:print(" message(STATUS \"%s_INCLUDE_DIRS=\" \"${%s_INCLUDE_DIRS}\")", macro_name, macro_name) - cmakefile:print(" message(STATUS \"%s_LIBRARY_DIR=\" \"${%s_LIBRARY_DIR}\")", macro_name, macro_name) - cmakefile:print(" message(STATUS \"%s_LIBRARY_DIRS=\" \"${%s_LIBRARY_DIRS}\")", macro_name, macro_name) - cmakefile:print(" message(STATUS \"%s_LIBRARY=\" \"${%s_LIBRARY}\")", macro_name, macro_name) - cmakefile:print(" message(STATUS \"%s_LIBRARIES=\" \"${%s_LIBRARIES}\")", macro_name, macro_name) - cmakefile:print(" message(STATUS \"%s_LIBS=\" \"${%s_LIBS}\")", macro_name, macro_name) - end + cmakefile:print(" add_executable(%s test.cpp)", name) + cmakefile:print(" target_include_directories(%s PRIVATE ${%s_INCLUDE_DIR} ${%s_INCLUDE_DIRS})", + name, name, name) + cmakefile:print(" target_include_directories(%s PRIVATE ${%s_INCLUDE_DIR} ${%s_INCLUDE_DIRS})", + name, name:upper(), name:upper()) + cmakefile:print(" target_link_libraries(%s ${%s_LIBRARY} ${%s_LIBRARIES} ${%s_LIBS})", + name, name, name, name) + cmakefile:print(" target_link_libraries(%s ${%s_LIBRARY} ${%s_LIBRARIES} ${%s_LIBS})", + name, name:upper(), name:upper(), name:upper()) cmakefile:print("endif(%s_FOUND)", name) cmakefile:close() - -- run cmake to get output + -- run cmake + try {function() return os.vrunv(cmake.program, {workdir}, {curdir = workdir}) end} + + -- pares includedirs local links local linkdirs + local libfiles local includedirs - local output, errors = try {function() return os.iorunv(cmake.program, {workdir}, {curdir = workdir}) end} - if output then - for _, line in ipairs(output:split("\n", {plain = true})) do - for _, macro_name in ipairs({name, name:upper()}) do - -- parse includedirs - for _, includedir_key in ipairs({macro_name .. "_INCLUDE_DIR=", macro_name .. "_INCLUDE_DIRS="}) do - if line:find(includedir_key, 1, true) then - local splitinfo = line:split(includedir_key) - local values = splitinfo[2] - if values then - values = values:split(';', {plain = true}) - end - if values then - includedirs = includedirs or {} - table.join2(includedirs, values) + local flagsfile = path.join(workdir, "CMakeFiles", name .. ".dir", "flags.make") + if os.isfile(flagsfile) then + local flagsdata = io.readfile(flagsfile) + if flagsdata then + if option.get("diagnosis") then + vprint(flagsdata) + end + for _, line in ipairs(flagsdata:split("\n", {plain = true})) do + if line:find("CXX_INCLUDES =", 1, true) then + local has_include = false + local flags = os.argv(line:split("=", {plain = true})[2]:trim()) + for _, flag in ipairs(flags) do + if has_include or (flag:startswith("-I") and #flag > 2) then + local includedir = has_include and flag or flag:sub(3) + if includedir and os.isdir(includedir) then + includedirs = includedirs or {} + table.insert(includedirs, includedir) + end + has_include = false + elseif flag == "-isystem" or flag == "-I" then + has_include = true end end end + end + end + end - -- parse linkdirs - for _, linkdir_key in ipairs({macro_name .. "_LIBRARY_DIR=", macro_name .. "_LIBRARY_DIRS="}) do - if line:find(linkdir_key, 1, true) then - local splitinfo = line:split(linkdir_key) - local values = splitinfo[2] - if values then - values = values:split(';', {plain = true}) - end - if values then - linkdirs = linkdirs or {} - table.join2(linkdirs, values) - end + -- parse links and linkdirs + local linkfile = path.join(workdir, "CMakeFiles", name .. ".dir", "link.txt") + if os.isfile(linkfile) then + local linkdata = io.readfile(linkfile) + if linkdata then + if option.get("diagnosis") then + vprint(linkdata) + end + for _, line in ipairs(os.argv(linkdata)) do + local is_library = false + for _, suffix in ipairs({".so", ".dylib", ".dylib", ".tbd", ".lib"}) do + if line:find(suffix, 1, true) then + is_library = true + break end end + if is_library then + -- strip library version suffix, e.g. libxxx.so.1.1 -> libxxx.so + if line:find(".so", 1, true) then + line = line:gsub("lib(.-)%.so%..+$", "lib%1.so") + end - -- parse links and linkdirs - for _, library_key in ipairs({macro_name .. "_LIBRARY=", macro_name .. "_LIBS=", macro_name .. "_LIBRARIES="}) do - if line:find(library_key, 1, true) then - local splitinfo = line:split(library_key) - local values = splitinfo[2] - if values then - values = values:split(';', {plain = true}) - end - for _, library in ipairs(values) do - local linkdir = path.directory(library) - if linkdir ~= "." then - linkdirs = linkdirs or {} - table.insert(linkdirs, linkdir) - end - local link = target.linkname(path.filename(library)) - if not link then - -- has been link name? - if path.filename(library) == path.basename(library) and linkdir == "." then - link = library - end - end - if link then - assert(not link:find("::", 1, true), "link(%s) is not supported yet!", link) - links = links or {} - table.insert(links, link) - end - end + -- get libfiles + if os.isfile(line) then + libfiles = libfiles or {} + table.insert(libfiles, line) + end + + -- get links and linkdirs + local linkdir = path.directory(line) + if linkdir ~= "." then + linkdirs = linkdirs or {} + table.insert(linkdirs, linkdir) + end + local link = target.linkname(path.filename(line)) + if link then + links = links or {} + table.insert(links, link) end end end end end - -- trace diagnosis info - if option.get("verbose") then - if output then - print(output) - end - if option.get("diagnosis") and errors and errors:trim() ~= "" then - cprint("${color.warning}checkinfo: ${clear dim}" .. errors) - end - end - -- remove work directory os.tryrm(workdir) @@ -167,6 +167,7 @@ function _find_package(cmake, name, opt) local results = {} results.links = table.reverse_unique(links) results.linkdirs = table.unique(linkdirs) + results.libfiles = table.unique(libfiles) results.includedirs = table.unique(includedirs) return results end @@ -178,14 +179,14 @@ end -- -- find_package("cmake::ZLIB") -- find_package("cmake::OpenCV", {required_version = "4.1.1"}) --- find_package("cmake::Boost", {components = {"regex", "system"}, presets = {USE_STATIC_LIB = true}}) +-- find_package("cmake::Boost", {components = {"regex", "system"}, presets = {Boost_USE_STATIC_LIB = true}}) -- find_package("cmake::Foo", {moduledirs = "xxx"}) -- -- @param name the package name -- @param opt the options, e.g. {verbose = true, required_version = "1.0", -- components = {"regex", "system"}, -- moduledirs = "xxx", --- presets = {USE_STATIC_LIB = true}) +-- presets = {Boost_USE_STATIC_LIB = true}) -- function main(name, opt) opt = opt or {} -- cgit v1.3.1 From b76924dfdc305e865244e6fa7460767b5cbbc794 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 12 Oct 2021 00:32:11 +0800 Subject: add defines to cmake/find_package --- .../modules/package/manager/cmake/find_package.lua | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua index 653f69f16..a8eb067b3 100644 --- a/xmake/modules/package/manager/cmake/find_package.lua +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -82,10 +82,11 @@ function _find_package(cmake, name, opt) -- run cmake try {function() return os.vrunv(cmake.program, {workdir}, {curdir = workdir}) end} - -- pares includedirs + -- pares defines and includedirs local links local linkdirs local libfiles + local defines local includedirs local flagsfile = path.join(workdir, "CMakeFiles", name .. ".dir", "flags.make") if os.isfile(flagsfile) then @@ -110,6 +111,17 @@ function _find_package(cmake, name, opt) has_include = true end end + elseif line:find("CXX_DEFINES =", 1, true) then + local flags = os.argv(line:split("=", {plain = true})[2]:trim()) + for _, flag in ipairs(flags) do + if flag:startswith("-D") and #flag > 2 then + local define = flag:sub(3) + if define then + defines = defines or {} + table.insert(defines, define) + end + end + end end end end @@ -165,9 +177,10 @@ function _find_package(cmake, name, opt) -- get results if links or includedirs then local results = {} - results.links = table.reverse_unique(links) - results.linkdirs = table.unique(linkdirs) - results.libfiles = table.unique(libfiles) + results.links = table.reverse_unique(links) + results.linkdirs = table.unique(linkdirs) + results.defines = table.unique(defines) + results.libfiles = table.unique(libfiles) results.includedirs = table.unique(includedirs) return results end -- cgit v1.3.1 From b143a5713590a3f6a64351eee31dd15ee1177228 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 12 Oct 2021 00:41:07 +0800 Subject: add envs to cmake/find_package --- xmake/modules/package/manager/cmake/find_package.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua index a8eb067b3..051486df5 100644 --- a/xmake/modules/package/manager/cmake/find_package.lua +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -80,7 +80,7 @@ function _find_package(cmake, name, opt) cmakefile:close() -- run cmake - try {function() return os.vrunv(cmake.program, {workdir}, {curdir = workdir}) end} + try {function() return os.vrunv(cmake.program, {workdir}, {curdir = workdir, envs = opt.envs}) end} -- pares defines and includedirs local links @@ -199,7 +199,8 @@ end -- @param opt the options, e.g. {verbose = true, required_version = "1.0", -- components = {"regex", "system"}, -- moduledirs = "xxx", --- presets = {Boost_USE_STATIC_LIB = true}) +-- presets = {Boost_USE_STATIC_LIB = true}, +-- envs = {CMAKE_PREFIX_PATH = "xxx"}) -- function main(name, opt) opt = opt or {} -- cgit v1.3.1 From 1cb2cb91f9ae2c251b2f1ba1870874570e11516f Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 12 Oct 2021 00:50:59 +0800 Subject: add module cache for clang --- xmake/rules/c++/modules/build_modulefiles.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/xmake/rules/c++/modules/build_modulefiles.lua b/xmake/rules/c++/modules/build_modulefiles.lua index 4e26f1eca..aa61fc696 100644 --- a/xmake/rules/c++/modules/build_modulefiles.lua +++ b/xmake/rules/c++/modules/build_modulefiles.lua @@ -24,6 +24,9 @@ import("core.tool.compiler") -- build module files using clang function _build_modulefiles_clang(target, sourcebatch, opt) + -- the module cache directory + local cachedir = path.join(target:autogendir(), "rules", "modules", "cache") + -- attempt to compile the module files as cxx sourcebatch.sourcekind = "cxx" sourcebatch.objectfiles = sourcebatch.objectfiles or {} @@ -35,7 +38,8 @@ function _build_modulefiles_clang(target, sourcebatch, opt) end -- compile module files to *.pcm - opt = table.join(opt, {configs = {force = {cxxflags = {opt.modulesflag, "--precompile", "-x c++-module"}}}}) + opt = table.join(opt, {configs = {force = {cxxflags = {opt.modulesflag, + "--precompile", "-x c++-module", "-fmodules-cache-path=" .. cachedir}}}}) import("private.action.build.object").build(target, sourcebatch, opt) -- compile *.pcm to object files @@ -53,7 +57,7 @@ function _build_modulefiles_clang(target, sourcebatch, opt) import("private.action.build.object").build(target, sourcebatch, opt) -- add module files - target:add("cxxflags", opt.modulesflag) + target:add("cxxflags", opt.modulesflag, "-fmodules-cache-path=" .. cachedir) for _, modulefile in ipairs(modulefiles) do target:add("cxxflags", "-fmodule-file=" .. modulefile) end -- cgit v1.3.1 From 09367e816155b80499ee5965ef686b55df54a590 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 12 Oct 2021 00:51:20 +0800 Subject: add module cache for clang --- xmake/rules/c++/modules/build_modulefiles.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/build_modulefiles.lua b/xmake/rules/c++/modules/build_modulefiles.lua index aa61fc696..430c4397f 100644 --- a/xmake/rules/c++/modules/build_modulefiles.lua +++ b/xmake/rules/c++/modules/build_modulefiles.lua @@ -52,7 +52,7 @@ function _build_modulefiles_clang(target, sourcebatch, opt) sourcebatch.dependfiles[idx] = target:dependfile(objectfile) table.insert(modulefiles, modulefile) end - opt.configs = {cxxflags = {opt.modulesflag}} + opt.configs = {cxxflags = {opt.modulesflag, "-fmodules-cache-path=" .. cachedir}} opt.quiet = true import("private.action.build.object").build(target, sourcebatch, opt) -- cgit v1.3.1 From b24465b8af066aabd8ef0d56bd725f743381e72a Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 12 Oct 2021 10:20:42 +0800 Subject: Update find_package.lua --- .../modules/package/manager/cmake/find_package.lua | 44 ++++++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua index 051486df5..c954f024d 100644 --- a/xmake/modules/package/manager/cmake/find_package.lua +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -57,7 +57,7 @@ function _find_package(cmake, name, opt) end -- e.g. set(Boost_USE_STATIC_LIB ON) if opt.presets then - for k, v in ipairs(opt.presets) do + for k, v in pairs(opt.presets) do if type(v) == "boolean" then cmakefile:print("set(%s %s)", k, v and "ON" or "OFF") else @@ -82,7 +82,7 @@ function _find_package(cmake, name, opt) -- run cmake try {function() return os.vrunv(cmake.program, {workdir}, {curdir = workdir, envs = opt.envs}) end} - -- pares defines and includedirs + -- pares defines and includedirs for macosx/linux local links local linkdirs local libfiles @@ -127,7 +127,7 @@ function _find_package(cmake, name, opt) end end - -- parse links and linkdirs + -- parse links and linkdirs for macosx/linux local linkfile = path.join(workdir, "CMakeFiles", name .. ".dir", "link.txt") if os.isfile(linkfile) then local linkdata = io.readfile(linkfile) @@ -171,6 +171,44 @@ function _find_package(cmake, name, opt) end end + -- pares includedirs and links/linkdirs for windows + local vcprojfile = path.join(workdir, name .. ".vcxproj") + if os.isfile(vcprojfile) then + local vcprojdata = io.readfile(vcprojfile) + if vcprojdata then + for _, line in ipairs(vcprojdata:split("\n", {plain = true})) do + local values = line:match("(.+);%%%(AdditionalIncludeDirectories%)") + if values then + includedirs = includedirs or {} + table.join2(includedirs, path.splitenv(values)) + end + + values = line:match("(.+)") + if values then + for _, library in ipairs(path.splitenv(values)) do + -- get libfiles + if os.isfile(library) then + libfiles = libfiles or {} + table.insert(libfiles, library) + end + + -- get links and linkdirs + local linkdir = path.directory(library) + if linkdir ~= "." then + linkdirs = linkdirs or {} + table.insert(linkdirs, linkdir) + local link = target.linkname(path.filename(library)) + if link then + links = links or {} + table.insert(links, link) + end + end + end + end + end + end + end + -- remove work directory os.tryrm(workdir) -- cgit v1.3.1 From 72fabb25dd367d87faa7a9461a6e79faa7196c48 Mon Sep 17 00:00:00 2001 From: Hoildkv <42310255+xq114@users.noreply.github.com> Date: Tue, 12 Oct 2021 14:01:16 +0800 Subject: make symbols outsides the library not exposed --- xmake/rules/utils/symbols/export_all/export_all.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xmake/rules/utils/symbols/export_all/export_all.lua b/xmake/rules/utils/symbols/export_all/export_all.lua index 800157411..f8247a878 100644 --- a/xmake/rules/utils/symbols/export_all/export_all.lua +++ b/xmake/rules/utils/symbols/export_all/export_all.lua @@ -56,8 +56,9 @@ function main (target, opt) local objectsymbols = try { function () return os.iorunv(dumpbin.program, {"/symbols", "/nologo", objectfile}) end } if objectsymbols then for _, line in ipairs(objectsymbols:split('\n', {plain = true})) do + -- https://docs.microsoft.com/en-us/cpp/build/reference/symbols -- 008 00000000 SECT3 notype () External | add - if line:find("External") then + if line:find("External") and not line:find("UNDEF") then local symbol = line:match(".*External%s+| (.*)") if symbol then symbol = symbol:split('%s')[1] -- cgit v1.3.1 From 417887dbd608961de809e7955be66fa9a9859176 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 12 Oct 2021 15:26:35 +0800 Subject: Update build_modulefiles.lua --- xmake/rules/c++/modules/build_modulefiles.lua | 85 ++++++++++++++++++--------- 1 file changed, 56 insertions(+), 29 deletions(-) diff --git a/xmake/rules/c++/modules/build_modulefiles.lua b/xmake/rules/c++/modules/build_modulefiles.lua index 430c4397f..7ad566f5c 100644 --- a/xmake/rules/c++/modules/build_modulefiles.lua +++ b/xmake/rules/c++/modules/build_modulefiles.lua @@ -24,6 +24,16 @@ import("core.tool.compiler") -- build module files using clang function _build_modulefiles_clang(target, sourcebatch, opt) + -- get modules flag + local modulesflag + local compinst = compiler.load("cxx", {target = target}) + if compinst:has_flags("-fmodules") then + modulesflag = "-fmodules" + elseif compinst:has_flags("-fmodules-ts") then + modulesflag = "-fmodules-ts" + end + assert(modulesflag, "compiler(clang): does not support c++ module!") + -- the module cache directory local cachedir = path.join(target:autogendir(), "rules", "modules", "cache") @@ -38,7 +48,7 @@ function _build_modulefiles_clang(target, sourcebatch, opt) end -- compile module files to *.pcm - opt = table.join(opt, {configs = {force = {cxxflags = {opt.modulesflag, + opt = table.join(opt, {configs = {force = {cxxflags = {modulesflag, "--precompile", "-x c++-module", "-fmodules-cache-path=" .. cachedir}}}}) import("private.action.build.object").build(target, sourcebatch, opt) @@ -52,7 +62,7 @@ function _build_modulefiles_clang(target, sourcebatch, opt) sourcebatch.dependfiles[idx] = target:dependfile(objectfile) table.insert(modulefiles, modulefile) end - opt.configs = {cxxflags = {opt.modulesflag, "-fmodules-cache-path=" .. cachedir}} + opt.configs = {cxxflags = {modulesflag, "-fmodules-cache-path=" .. cachedir}} opt.quiet = true import("private.action.build.object").build(target, sourcebatch, opt) @@ -98,6 +108,41 @@ end -- build module files using msvc function _build_modulefiles_msvc(target, sourcebatch, opt) + -- get modules flag + local modulesflag + local compinst = compiler.load("cxx", {target = target}) + if compinst:has_flags("/experimental:module") then + modulesflag = "/experimental:module" + end + assert(modulesflag, "compiler(msvc): does not support c++ module!") + + -- get output flag + local outputflag + if compinst:has_flags("/ifcOutput") then + outputflag = "/ifcOutput" + elseif compinst:has_flags("/module:output") then + outputflag = "/module:output" + end + assert(outputflag, "compiler(msvc): does not support c++ module!") + + -- get interface flag + local interfaceflag + if compinst:has_flags("/interface") then + interfaceflag = "/interface" + elseif compinst:has_flags("/module:interface") then + interfaceflag = "/module:interface" + end + assert(interfaceflag, "compiler(msvc): does not support c++ module!") + + -- get reference flag + local referenceflag + if compinst:has_flags("/reference") then + referenceflag = "/reference" + elseif compinst:has_flags("/module:interface") then + referenceflag = "/module:reference" + end + assert(referenceflag, "compiler(msvc): does not support c++ module!") + -- attempt to compile the module files as cxx local modulefiles = {} opt = table.join(opt, {configs = {}}) @@ -111,7 +156,7 @@ function _build_modulefiles_msvc(target, sourcebatch, opt) -- compile module file to *.pcm local singlebatch = {sourcekind = "cxx", sourcefiles = {sourcefile}, objectfiles = {objectfile}, dependfiles = {dependfile}} - opt.configs.cxxflags = {"/experimental:module /module:interface /module:output " .. os.args(modulefile), "/TP"} + opt.configs.cxxflags = {modulesflag, interfaceflag, outputflag .. " " .. os.args(modulefile), "/TP"} import("private.action.build.object").build(target, singlebatch, opt) table.insert(modulefiles, modulefile) table.insert(sourcebatch.objectfiles, objectfile) @@ -120,38 +165,20 @@ function _build_modulefiles_msvc(target, sourcebatch, opt) -- add module files for _, modulefile in ipairs(modulefiles) do - target:add("cxxflags", "/experimental:module /module:reference " .. os.args(modulefile)) + target:add("cxxflags", modulesflag, referenceflag .. " " .. os.args(modulefile)) end end -- build module files function main(target, sourcebatch, opt) - - -- do compile - local modulesflag = nil local _, toolname = target:tool("cxx") - local compinst = compiler.load("cxx") - if toolname:find("clang", 1, true) or toolname:find("gcc", 1, true) then - if compinst:has_flags("-fmodules") then - modulesflag = "-fmodules" - elseif compinst:has_flags("-fmodules-ts") then - modulesflag = "-fmodules-ts" - end + if toolname:find("clang", 1, true) then + _build_modulefiles_clang(target, sourcebatch, opt) + elseif toolname:find("gcc", 1, true) then + _build_modulefiles_gcc(target, sourcebatch, opt) elseif toolname == "cl" then - if compinst:has_flags("/experimental:module") then - modulesflag = "/experimental:module" - end - end - if modulesflag then - opt.modulesflag = modulesflag - if toolname:find("clang", 1, true) then - _build_modulefiles_clang(target, sourcebatch, opt) - elseif toolname:find("gcc", 1, true) then - _build_modulefiles_gcc(target, sourcebatch, opt) - elseif toolname == "cl" then - _build_modulefiles_msvc(target, sourcebatch, opt) - else - raise("compiler(%s): does not support c++ module!", toolname) - end + _build_modulefiles_msvc(target, sourcebatch, opt) + else + raise("compiler(%s): does not support c++ module!", toolname) end end -- cgit v1.3.1 From 71ea9007f37d54c0224c43c1a3a1f2f3854c07c0 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 12 Oct 2021 15:27:04 +0800 Subject: Update hello.mpp --- tests/projects/c++/modules/dependence/src/hello.mpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/tests/projects/c++/modules/dependence/src/hello.mpp b/tests/projects/c++/modules/dependence/src/hello.mpp index 3f803afaf..abac9fcb0 100644 --- a/tests/projects/c++/modules/dependence/src/hello.mpp +++ b/tests/projects/c++/modules/dependence/src/hello.mpp @@ -1,27 +1,14 @@ export module hello; export namespace hello { -#ifdef _MSC_VER - int data__; -#else extern int data__; -#endif void say_hello(); class say { public: say(int data); void hello(); - private: int data_; }; } -/* -#ifndef _MSC_VER -export namespace { - void anonymous() { - } -} -#endif -*/ \ No newline at end of file -- cgit v1.3.1 From 3cafed12222db81c39361adc4e2425fb33b5b170 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 12 Oct 2021 21:57:46 +0800 Subject: Update build_modulefiles.lua --- xmake/rules/c++/modules/build_modulefiles.lua | 31 ++++++++++++--------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/xmake/rules/c++/modules/build_modulefiles.lua b/xmake/rules/c++/modules/build_modulefiles.lua index 7ad566f5c..a41ab2f39 100644 --- a/xmake/rules/c++/modules/build_modulefiles.lua +++ b/xmake/rules/c++/modules/build_modulefiles.lua @@ -73,36 +73,33 @@ function _build_modulefiles_clang(target, sourcebatch, opt) end end --- TODO -- build module files using gcc function _build_modulefiles_gcc(target, sourcebatch, opt) - --[[ + -- get modules flag + local modulesflag + local compinst = compiler.load("cxx", {target = target}) + if compinst:has_flags("-fmodules-ts") then + modulesflag = "-fmodules-ts" + end + assert(modulesflag, "compiler(gcc): does not support c++ module!") + -- attempt to compile the module files as cxx - local modulefiles = {} - opt = table.join(opt, {configs = {}}) sourcebatch.sourcekind = "cxx" sourcebatch.objectfiles = sourcebatch.objectfiles or {} sourcebatch.dependfiles = sourcebatch.dependfiles or {} for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local objectfile = target:objectfile(sourcefile) - local dependfile = target:dependfile(objectfile) - local modulefile = objectfile .. ".pcm" - - -- compile module file to *.pcm - local singlebatch = {sourcekind = "cxx", sourcefiles = {sourcefile}, objectfiles = {objectfile}, dependfiles = {dependfile}} - opt.configs.cxxflags = {"-fmodules", "-fmodule-output=" .. modulefile, "-x c++"} - import("private.action.build.object").build(target, singlebatch, opt) - table.insert(modulefiles, modulefile) table.insert(sourcebatch.objectfiles, objectfile) - table.insert(sourcebatch.dependfiles, dependfile) + table.insert(sourcebatch.dependfiles, target:dependfile(objectfile)) end + -- compile module files to object files + opt = table.join(opt, {configs = {force = {cxxflags = {modulesflag, "-x c++"}}}}) + import("private.action.build.object").build(target, sourcebatch, opt) + -- add module files - for _, modulefile in ipairs(modulefiles) do - target:add("cxxflags", "-fmodules", "-fmodule-file=" .. modulefile) - end]] - raise("compiler(gcc): not implemented for c++ module!") + target:add("cxxflags", modulesflag) end -- build module files using msvc -- cgit v1.3.1 From 6d94f1182d93b04f854f90599e3878fd5826939e Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 13 Oct 2021 00:40:31 +0800 Subject: fix modules test --- tests/projects/c++/modules/class/src/hello_impl.cpp | 2 +- tests/projects/c++/modules/impl_unit/src/hello_impl.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/projects/c++/modules/class/src/hello_impl.cpp b/tests/projects/c++/modules/class/src/hello_impl.cpp index b8b572f27..5dd555a7a 100644 --- a/tests/projects/c++/modules/class/src/hello_impl.cpp +++ b/tests/projects/c++/modules/class/src/hello_impl.cpp @@ -1,9 +1,9 @@ module; #include -using namespace std; module hello; +using namespace std; namespace hello { say::say(int data) : data_(data) { diff --git a/tests/projects/c++/modules/impl_unit/src/hello_impl.cpp b/tests/projects/c++/modules/impl_unit/src/hello_impl.cpp index 425c7aba4..eccfed5d3 100644 --- a/tests/projects/c++/modules/impl_unit/src/hello_impl.cpp +++ b/tests/projects/c++/modules/impl_unit/src/hello_impl.cpp @@ -1,8 +1,8 @@ module; #include -using namespace std; module hello; +using namespace std; namespace hello { void say_hi() { -- cgit v1.3.1 From cbfbb1636bd892aa42054214e327eb6813654202 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 13 Oct 2021 12:31:04 +0800 Subject: Update build_modulefiles.lua --- xmake/rules/c++/modules/build_modulefiles.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/build_modulefiles.lua b/xmake/rules/c++/modules/build_modulefiles.lua index a41ab2f39..a8f0052a8 100644 --- a/xmake/rules/c++/modules/build_modulefiles.lua +++ b/xmake/rules/c++/modules/build_modulefiles.lua @@ -149,7 +149,7 @@ function _build_modulefiles_msvc(target, sourcebatch, opt) for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local objectfile = target:objectfile(sourcefile) local dependfile = target:dependfile(objectfile) - local modulefile = objectfile .. ".pcm" + local modulefile = objectfile .. ".ifc" -- compile module file to *.pcm local singlebatch = {sourcekind = "cxx", sourcefiles = {sourcefile}, objectfiles = {objectfile}, dependfiles = {dependfile}} -- cgit v1.3.1 From 55b632b420a23550991083471c90bbd042a974f7 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 13 Oct 2021 23:18:34 +0800 Subject: add c++ submodules and partitions --- tests/projects/c++/modules/partitions/src/main.cpp | 10 ++++++++++ tests/projects/c++/modules/partitions/src/math.mpp | 4 ++++ tests/projects/c++/modules/partitions/src/math1.mpp | 5 +++++ tests/projects/c++/modules/partitions/src/math2.mpp | 7 +++++++ tests/projects/c++/modules/partitions/xmake.lua | 7 +++++++ tests/projects/c++/modules/submodules/src/main.cpp | 10 ++++++++++ tests/projects/c++/modules/submodules/src/math.mpp | 4 ++++ tests/projects/c++/modules/submodules/src/math1.mpp | 5 +++++ tests/projects/c++/modules/submodules/src/math2.mpp | 7 +++++++ tests/projects/c++/modules/submodules/xmake.lua | 7 +++++++ 10 files changed, 66 insertions(+) create mode 100644 tests/projects/c++/modules/partitions/src/main.cpp create mode 100644 tests/projects/c++/modules/partitions/src/math.mpp create mode 100644 tests/projects/c++/modules/partitions/src/math1.mpp create mode 100644 tests/projects/c++/modules/partitions/src/math2.mpp create mode 100644 tests/projects/c++/modules/partitions/xmake.lua create mode 100644 tests/projects/c++/modules/submodules/src/main.cpp create mode 100644 tests/projects/c++/modules/submodules/src/math.mpp create mode 100644 tests/projects/c++/modules/submodules/src/math1.mpp create mode 100644 tests/projects/c++/modules/submodules/src/math2.mpp create mode 100644 tests/projects/c++/modules/submodules/xmake.lua diff --git a/tests/projects/c++/modules/partitions/src/main.cpp b/tests/projects/c++/modules/partitions/src/main.cpp new file mode 100644 index 000000000..eaaec9565 --- /dev/null +++ b/tests/projects/c++/modules/partitions/src/main.cpp @@ -0,0 +1,10 @@ +import std.core; +import math; + +int main() { + + std::cout << std::endl; + + std::cout << "add(3, 4): " << add(3, 4) << std::endl; + std::cout << "mul(3, 4): " << mul(3, 4) << std::endl; +} diff --git a/tests/projects/c++/modules/partitions/src/math.mpp b/tests/projects/c++/modules/partitions/src/math.mpp new file mode 100644 index 000000000..11402ade6 --- /dev/null +++ b/tests/projects/c++/modules/partitions/src/math.mpp @@ -0,0 +1,4 @@ +export module math; + +export import :math1; +export import :math2; diff --git a/tests/projects/c++/modules/partitions/src/math1.mpp b/tests/projects/c++/modules/partitions/src/math1.mpp new file mode 100644 index 000000000..8537d161a --- /dev/null +++ b/tests/projects/c++/modules/partitions/src/math1.mpp @@ -0,0 +1,5 @@ +export module math:math1; + +export int add(int fir, int sec) { + return fir + sec; +} diff --git a/tests/projects/c++/modules/partitions/src/math2.mpp b/tests/projects/c++/modules/partitions/src/math2.mpp new file mode 100644 index 000000000..78e14ed6f --- /dev/null +++ b/tests/projects/c++/modules/partitions/src/math2.mpp @@ -0,0 +1,7 @@ +export module math:math2; + +export { + int mul(int fir, int sec) { + return fir * sec; + } +} diff --git a/tests/projects/c++/modules/partitions/xmake.lua b/tests/projects/c++/modules/partitions/xmake.lua new file mode 100644 index 000000000..36697f3e8 --- /dev/null +++ b/tests/projects/c++/modules/partitions/xmake.lua @@ -0,0 +1,7 @@ +set_languages("c++20") +target("math") + set_kind("binary") + add_files("src/*.cpp") + add_files("src/math1.mpp") + add_files("src/math2.mpp") + add_files("src/math.mpp") diff --git a/tests/projects/c++/modules/submodules/src/main.cpp b/tests/projects/c++/modules/submodules/src/main.cpp new file mode 100644 index 000000000..eaaec9565 --- /dev/null +++ b/tests/projects/c++/modules/submodules/src/main.cpp @@ -0,0 +1,10 @@ +import std.core; +import math; + +int main() { + + std::cout << std::endl; + + std::cout << "add(3, 4): " << add(3, 4) << std::endl; + std::cout << "mul(3, 4): " << mul(3, 4) << std::endl; +} diff --git a/tests/projects/c++/modules/submodules/src/math.mpp b/tests/projects/c++/modules/submodules/src/math.mpp new file mode 100644 index 000000000..0b38b9c08 --- /dev/null +++ b/tests/projects/c++/modules/submodules/src/math.mpp @@ -0,0 +1,4 @@ +export module math; + +export import math.math1; +export import math.math2; diff --git a/tests/projects/c++/modules/submodules/src/math1.mpp b/tests/projects/c++/modules/submodules/src/math1.mpp new file mode 100644 index 000000000..3e06bf426 --- /dev/null +++ b/tests/projects/c++/modules/submodules/src/math1.mpp @@ -0,0 +1,5 @@ +export module math.math1; + +export int add(int fir, int sec) { + return fir + sec; +} diff --git a/tests/projects/c++/modules/submodules/src/math2.mpp b/tests/projects/c++/modules/submodules/src/math2.mpp new file mode 100644 index 000000000..f6c5381c3 --- /dev/null +++ b/tests/projects/c++/modules/submodules/src/math2.mpp @@ -0,0 +1,7 @@ +export module math.math2; + +export { + int mul(int fir, int sec) { + return fir * sec; + } +} diff --git a/tests/projects/c++/modules/submodules/xmake.lua b/tests/projects/c++/modules/submodules/xmake.lua new file mode 100644 index 000000000..36697f3e8 --- /dev/null +++ b/tests/projects/c++/modules/submodules/xmake.lua @@ -0,0 +1,7 @@ +set_languages("c++20") +target("math") + set_kind("binary") + add_files("src/*.cpp") + add_files("src/math1.mpp") + add_files("src/math2.mpp") + add_files("src/math.mpp") -- cgit v1.3.1 From 8c0bb24c70e94888ff4e731630cb47ca1cfafc86 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 13 Oct 2021 23:54:20 +0800 Subject: add more module examples --- tests/projects/c++/modules/partitions/src/main.cpp | 3 ++- tests/projects/c++/modules/partitions/xmake.lua | 5 +---- tests/projects/c++/modules/submodules/src/main.cpp | 2 +- tests/projects/c++/modules/submodules/xmake.lua | 5 +---- xmake/rules/c++/modules/build_modulefiles.lua | 2 +- 5 files changed, 6 insertions(+), 11 deletions(-) diff --git a/tests/projects/c++/modules/partitions/src/main.cpp b/tests/projects/c++/modules/partitions/src/main.cpp index eaaec9565..058dfd522 100644 --- a/tests/projects/c++/modules/partitions/src/main.cpp +++ b/tests/projects/c++/modules/partitions/src/main.cpp @@ -1,4 +1,5 @@ -import std.core; +#include + import math; int main() { diff --git a/tests/projects/c++/modules/partitions/xmake.lua b/tests/projects/c++/modules/partitions/xmake.lua index 36697f3e8..672034947 100644 --- a/tests/projects/c++/modules/partitions/xmake.lua +++ b/tests/projects/c++/modules/partitions/xmake.lua @@ -1,7 +1,4 @@ set_languages("c++20") target("math") set_kind("binary") - add_files("src/*.cpp") - add_files("src/math1.mpp") - add_files("src/math2.mpp") - add_files("src/math.mpp") + add_files("src/*.cpp", "src/*.mpp") diff --git a/tests/projects/c++/modules/submodules/src/main.cpp b/tests/projects/c++/modules/submodules/src/main.cpp index eaaec9565..5ff18701f 100644 --- a/tests/projects/c++/modules/submodules/src/main.cpp +++ b/tests/projects/c++/modules/submodules/src/main.cpp @@ -1,4 +1,4 @@ -import std.core; +#include import math; int main() { diff --git a/tests/projects/c++/modules/submodules/xmake.lua b/tests/projects/c++/modules/submodules/xmake.lua index 36697f3e8..672034947 100644 --- a/tests/projects/c++/modules/submodules/xmake.lua +++ b/tests/projects/c++/modules/submodules/xmake.lua @@ -1,7 +1,4 @@ set_languages("c++20") target("math") set_kind("binary") - add_files("src/*.cpp") - add_files("src/math1.mpp") - add_files("src/math2.mpp") - add_files("src/math.mpp") + add_files("src/*.cpp", "src/*.mpp") diff --git a/xmake/rules/c++/modules/build_modulefiles.lua b/xmake/rules/c++/modules/build_modulefiles.lua index a8f0052a8..efc1c3a38 100644 --- a/xmake/rules/c++/modules/build_modulefiles.lua +++ b/xmake/rules/c++/modules/build_modulefiles.lua @@ -67,7 +67,7 @@ function _build_modulefiles_clang(target, sourcebatch, opt) import("private.action.build.object").build(target, sourcebatch, opt) -- add module files - target:add("cxxflags", opt.modulesflag, "-fmodules-cache-path=" .. cachedir) + target:add("cxxflags", modulesflag, "-fmodules-cache-path=" .. cachedir) for _, modulefile in ipairs(modulefiles) do target:add("cxxflags", "-fmodule-file=" .. modulefile) end -- cgit v1.3.1 From 767f57b2e281a62f87d4e254cd93a41af00b55a8 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 14 Oct 2021 22:45:34 +0800 Subject: improve c++ modules test --- .gitignore | 3 +++ tests/projects/c++/modules/partitions/src/math.math1.mpp | 5 +++++ tests/projects/c++/modules/partitions/src/math.math2.mpp | 7 +++++++ tests/projects/c++/modules/partitions/src/math1.mpp | 5 ----- tests/projects/c++/modules/partitions/src/math2.mpp | 7 ------- tests/projects/c++/modules/submodules/src/math.math1.mpp | 5 +++++ tests/projects/c++/modules/submodules/src/math.math2.mpp | 7 +++++++ tests/projects/c++/modules/submodules/src/math1.mpp | 5 ----- tests/projects/c++/modules/submodules/src/math2.mpp | 7 ------- xmake/rules/c++/modules/build_modulefiles.lua | 6 ++++-- 10 files changed, 31 insertions(+), 26 deletions(-) create mode 100644 tests/projects/c++/modules/partitions/src/math.math1.mpp create mode 100644 tests/projects/c++/modules/partitions/src/math.math2.mpp delete mode 100644 tests/projects/c++/modules/partitions/src/math1.mpp delete mode 100644 tests/projects/c++/modules/partitions/src/math2.mpp create mode 100644 tests/projects/c++/modules/submodules/src/math.math1.mpp create mode 100644 tests/projects/c++/modules/submodules/src/math.math2.mpp delete mode 100644 tests/projects/c++/modules/submodules/src/math1.mpp delete mode 100644 tests/projects/c++/modules/submodules/src/math2.mpp diff --git a/.gitignore b/.gitignore index 1631dd04d..7107445a1 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,9 @@ .xmake/ build/ +# gcc cache +gcm.cache + # for VS Code .vscode/ diff --git a/tests/projects/c++/modules/partitions/src/math.math1.mpp b/tests/projects/c++/modules/partitions/src/math.math1.mpp new file mode 100644 index 000000000..8537d161a --- /dev/null +++ b/tests/projects/c++/modules/partitions/src/math.math1.mpp @@ -0,0 +1,5 @@ +export module math:math1; + +export int add(int fir, int sec) { + return fir + sec; +} diff --git a/tests/projects/c++/modules/partitions/src/math.math2.mpp b/tests/projects/c++/modules/partitions/src/math.math2.mpp new file mode 100644 index 000000000..78e14ed6f --- /dev/null +++ b/tests/projects/c++/modules/partitions/src/math.math2.mpp @@ -0,0 +1,7 @@ +export module math:math2; + +export { + int mul(int fir, int sec) { + return fir * sec; + } +} diff --git a/tests/projects/c++/modules/partitions/src/math1.mpp b/tests/projects/c++/modules/partitions/src/math1.mpp deleted file mode 100644 index 8537d161a..000000000 --- a/tests/projects/c++/modules/partitions/src/math1.mpp +++ /dev/null @@ -1,5 +0,0 @@ -export module math:math1; - -export int add(int fir, int sec) { - return fir + sec; -} diff --git a/tests/projects/c++/modules/partitions/src/math2.mpp b/tests/projects/c++/modules/partitions/src/math2.mpp deleted file mode 100644 index 78e14ed6f..000000000 --- a/tests/projects/c++/modules/partitions/src/math2.mpp +++ /dev/null @@ -1,7 +0,0 @@ -export module math:math2; - -export { - int mul(int fir, int sec) { - return fir * sec; - } -} diff --git a/tests/projects/c++/modules/submodules/src/math.math1.mpp b/tests/projects/c++/modules/submodules/src/math.math1.mpp new file mode 100644 index 000000000..3e06bf426 --- /dev/null +++ b/tests/projects/c++/modules/submodules/src/math.math1.mpp @@ -0,0 +1,5 @@ +export module math.math1; + +export int add(int fir, int sec) { + return fir + sec; +} diff --git a/tests/projects/c++/modules/submodules/src/math.math2.mpp b/tests/projects/c++/modules/submodules/src/math.math2.mpp new file mode 100644 index 000000000..f6c5381c3 --- /dev/null +++ b/tests/projects/c++/modules/submodules/src/math.math2.mpp @@ -0,0 +1,7 @@ +export module math.math2; + +export { + int mul(int fir, int sec) { + return fir * sec; + } +} diff --git a/tests/projects/c++/modules/submodules/src/math1.mpp b/tests/projects/c++/modules/submodules/src/math1.mpp deleted file mode 100644 index 3e06bf426..000000000 --- a/tests/projects/c++/modules/submodules/src/math1.mpp +++ /dev/null @@ -1,5 +0,0 @@ -export module math.math1; - -export int add(int fir, int sec) { - return fir + sec; -} diff --git a/tests/projects/c++/modules/submodules/src/math2.mpp b/tests/projects/c++/modules/submodules/src/math2.mpp deleted file mode 100644 index f6c5381c3..000000000 --- a/tests/projects/c++/modules/submodules/src/math2.mpp +++ /dev/null @@ -1,7 +0,0 @@ -export module math.math2; - -export { - int mul(int fir, int sec) { - return fir * sec; - } -} diff --git a/xmake/rules/c++/modules/build_modulefiles.lua b/xmake/rules/c++/modules/build_modulefiles.lua index efc1c3a38..c0a5ae381 100644 --- a/xmake/rules/c++/modules/build_modulefiles.lua +++ b/xmake/rules/c++/modules/build_modulefiles.lua @@ -42,13 +42,15 @@ function _build_modulefiles_clang(target, sourcebatch, opt) sourcebatch.objectfiles = sourcebatch.objectfiles or {} sourcebatch.dependfiles = sourcebatch.dependfiles or {} for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local objectfile = target:objectfile(sourcefile) .. ".pcm" + --local objectfile = target:objectfile(sourcefile) .. ".pcm" + local objectfile = path.join(cachedir, path.basename(sourcefile) .. ".pcm") table.insert(sourcebatch.objectfiles, objectfile) table.insert(sourcebatch.dependfiles, target:dependfile(objectfile)) end -- compile module files to *.pcm opt = table.join(opt, {configs = {force = {cxxflags = {modulesflag, + "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir, "--precompile", "-x c++-module", "-fmodules-cache-path=" .. cachedir}}}}) import("private.action.build.object").build(target, sourcebatch, opt) @@ -62,7 +64,7 @@ function _build_modulefiles_clang(target, sourcebatch, opt) sourcebatch.dependfiles[idx] = target:dependfile(objectfile) table.insert(modulefiles, modulefile) end - opt.configs = {cxxflags = {modulesflag, "-fmodules-cache-path=" .. cachedir}} + opt.configs = {cxxflags = {modulesflag, "-fmodules-cache-path=" .. cachedir, "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir}} opt.quiet = true import("private.action.build.object").build(target, sourcebatch, opt) -- cgit v1.3.1 From 0a3c4a6489810afdacfc1c362d0e223bf6f6bfbf Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 14 Oct 2021 22:48:47 +0800 Subject: support ifc search for msvc --- xmake/rules/c++/modules/build_modulefiles.lua | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/xmake/rules/c++/modules/build_modulefiles.lua b/xmake/rules/c++/modules/build_modulefiles.lua index c0a5ae381..873a8dfdd 100644 --- a/xmake/rules/c++/modules/build_modulefiles.lua +++ b/xmake/rules/c++/modules/build_modulefiles.lua @@ -116,9 +116,14 @@ function _build_modulefiles_msvc(target, sourcebatch, opt) assert(modulesflag, "compiler(msvc): does not support c++ module!") -- get output flag + local cachedir local outputflag if compinst:has_flags("/ifcOutput") then outputflag = "/ifcOutput" + cachedir = path.join(target:autogendir(), "rules", "modules", "cache") + if not os.isdir(cachedir) then + os.mkdir(cachedir) + end elseif compinst:has_flags("/module:output") then outputflag = "/module:output" end @@ -151,11 +156,14 @@ function _build_modulefiles_msvc(target, sourcebatch, opt) for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local objectfile = target:objectfile(sourcefile) local dependfile = target:dependfile(objectfile) - local modulefile = objectfile .. ".ifc" + local modulefile = (cachedir and path.join(cachedir, path.basename(sourcefile)) or objectfile) .. ".ifc" -- compile module file to *.pcm local singlebatch = {sourcekind = "cxx", sourcefiles = {sourcefile}, objectfiles = {objectfile}, dependfiles = {dependfile}} opt.configs.cxxflags = {modulesflag, interfaceflag, outputflag .. " " .. os.args(modulefile), "/TP"} + if cachedir then + table.insert(opt.configs.cxxflags, "/ifcSearchDir " .. os.args(cachedir)) + end import("private.action.build.object").build(target, singlebatch, opt) table.insert(modulefiles, modulefile) table.insert(sourcebatch.objectfiles, objectfile) @@ -164,7 +172,12 @@ function _build_modulefiles_msvc(target, sourcebatch, opt) -- add module files for _, modulefile in ipairs(modulefiles) do - target:add("cxxflags", modulesflag, referenceflag .. " " .. os.args(modulefile)) + target:add("cxxflags", modulesflag) + if cachedir then + target:add("cxxflags", "/ifcSearchDir " .. os.args(cachedir)) + else + target:add("cxxflags", referenceflag .. " " .. os.args(modulefile)) + end end end -- cgit v1.3.1 From d6d138881b996f0db385feb27cefb8bc6a495494 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 14 Oct 2021 22:52:30 +0800 Subject: improve build modules --- xmake/rules/c++/modules/build_modulefiles.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/build_modulefiles.lua b/xmake/rules/c++/modules/build_modulefiles.lua index 873a8dfdd..97c3d4a50 100644 --- a/xmake/rules/c++/modules/build_modulefiles.lua +++ b/xmake/rules/c++/modules/build_modulefiles.lua @@ -64,12 +64,15 @@ function _build_modulefiles_clang(target, sourcebatch, opt) sourcebatch.dependfiles[idx] = target:dependfile(objectfile) table.insert(modulefiles, modulefile) end - opt.configs = {cxxflags = {modulesflag, "-fmodules-cache-path=" .. cachedir, "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir}} + opt.configs = {cxxflags = {modulesflag, "-fmodules-cache-path=" .. cachedir, + "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir}} opt.quiet = true import("private.action.build.object").build(target, sourcebatch, opt) -- add module files target:add("cxxflags", modulesflag, "-fmodules-cache-path=" .. cachedir) + -- FIXME It is invalid for the module implementation unit +-- target:add("cxxflags", "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir) for _, modulefile in ipairs(modulefiles) do target:add("cxxflags", "-fmodule-file=" .. modulefile) end -- cgit v1.3.1 From 02a1dc5ba36b45b7a7ac917bb85f3851c87cb282 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 14 Oct 2021 23:56:40 +0800 Subject: remove unused line --- xmake/rules/c++/modules/build_modulefiles.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/xmake/rules/c++/modules/build_modulefiles.lua b/xmake/rules/c++/modules/build_modulefiles.lua index 97c3d4a50..624667661 100644 --- a/xmake/rules/c++/modules/build_modulefiles.lua +++ b/xmake/rules/c++/modules/build_modulefiles.lua @@ -42,7 +42,6 @@ function _build_modulefiles_clang(target, sourcebatch, opt) sourcebatch.objectfiles = sourcebatch.objectfiles or {} sourcebatch.dependfiles = sourcebatch.dependfiles or {} for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - --local objectfile = target:objectfile(sourcefile) .. ".pcm" local objectfile = path.join(cachedir, path.basename(sourcefile) .. ".pcm") table.insert(sourcebatch.objectfiles, objectfile) table.insert(sourcebatch.dependfiles, target:dependfile(objectfile)) -- cgit v1.3.1 From 3404b2307d5c191f27a140f51b78908de5e579de Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 15 Oct 2021 00:40:07 +0800 Subject: add batchjobs for c++ modules --- xmake/rules/c++/modules/build_modulefiles.lua | 198 -------------------------- xmake/rules/c++/modules/clang.lua | 86 +++++++++++ xmake/rules/c++/modules/gcc.lua | 59 ++++++++ xmake/rules/c++/modules/msvc.lua | 107 ++++++++++++++ xmake/rules/c++/modules/xmake.lua | 17 ++- 5 files changed, 268 insertions(+), 199 deletions(-) delete mode 100644 xmake/rules/c++/modules/build_modulefiles.lua create mode 100644 xmake/rules/c++/modules/clang.lua create mode 100644 xmake/rules/c++/modules/gcc.lua create mode 100644 xmake/rules/c++/modules/msvc.lua diff --git a/xmake/rules/c++/modules/build_modulefiles.lua b/xmake/rules/c++/modules/build_modulefiles.lua deleted file mode 100644 index 624667661..000000000 --- a/xmake/rules/c++/modules/build_modulefiles.lua +++ /dev/null @@ -1,198 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- 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 --- --- http://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. --- --- Copyright (C) 2015-present, TBOOX Open Source Group. --- --- @author ruki --- @file build_modulefiles.lua --- - --- imports -import("core.tool.compiler") - --- build module files using clang -function _build_modulefiles_clang(target, sourcebatch, opt) - - -- get modules flag - local modulesflag - local compinst = compiler.load("cxx", {target = target}) - if compinst:has_flags("-fmodules") then - modulesflag = "-fmodules" - elseif compinst:has_flags("-fmodules-ts") then - modulesflag = "-fmodules-ts" - end - assert(modulesflag, "compiler(clang): does not support c++ module!") - - -- the module cache directory - local cachedir = path.join(target:autogendir(), "rules", "modules", "cache") - - -- attempt to compile the module files as cxx - sourcebatch.sourcekind = "cxx" - sourcebatch.objectfiles = sourcebatch.objectfiles or {} - sourcebatch.dependfiles = sourcebatch.dependfiles or {} - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local objectfile = path.join(cachedir, path.basename(sourcefile) .. ".pcm") - table.insert(sourcebatch.objectfiles, objectfile) - table.insert(sourcebatch.dependfiles, target:dependfile(objectfile)) - end - - -- compile module files to *.pcm - opt = table.join(opt, {configs = {force = {cxxflags = {modulesflag, - "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir, - "--precompile", "-x c++-module", "-fmodules-cache-path=" .. cachedir}}}}) - import("private.action.build.object").build(target, sourcebatch, opt) - - -- compile *.pcm to object files - local modulefiles = {} - for idx, sourcefile in ipairs(sourcebatch.sourcefiles) do - local modulefile = sourcebatch.objectfiles[idx] - local objectfile = target:objectfile(sourcefile) - sourcebatch.sourcefiles[idx] = modulefile - sourcebatch.objectfiles[idx] = objectfile - sourcebatch.dependfiles[idx] = target:dependfile(objectfile) - table.insert(modulefiles, modulefile) - end - opt.configs = {cxxflags = {modulesflag, "-fmodules-cache-path=" .. cachedir, - "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir}} - opt.quiet = true - import("private.action.build.object").build(target, sourcebatch, opt) - - -- add module files - target:add("cxxflags", modulesflag, "-fmodules-cache-path=" .. cachedir) - -- FIXME It is invalid for the module implementation unit --- target:add("cxxflags", "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir) - for _, modulefile in ipairs(modulefiles) do - target:add("cxxflags", "-fmodule-file=" .. modulefile) - end -end - --- build module files using gcc -function _build_modulefiles_gcc(target, sourcebatch, opt) - - -- get modules flag - local modulesflag - local compinst = compiler.load("cxx", {target = target}) - if compinst:has_flags("-fmodules-ts") then - modulesflag = "-fmodules-ts" - end - assert(modulesflag, "compiler(gcc): does not support c++ module!") - - -- attempt to compile the module files as cxx - sourcebatch.sourcekind = "cxx" - sourcebatch.objectfiles = sourcebatch.objectfiles or {} - sourcebatch.dependfiles = sourcebatch.dependfiles or {} - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local objectfile = target:objectfile(sourcefile) - table.insert(sourcebatch.objectfiles, objectfile) - table.insert(sourcebatch.dependfiles, target:dependfile(objectfile)) - end - - -- compile module files to object files - opt = table.join(opt, {configs = {force = {cxxflags = {modulesflag, "-x c++"}}}}) - import("private.action.build.object").build(target, sourcebatch, opt) - - -- add module files - target:add("cxxflags", modulesflag) -end - --- build module files using msvc -function _build_modulefiles_msvc(target, sourcebatch, opt) - - -- get modules flag - local modulesflag - local compinst = compiler.load("cxx", {target = target}) - if compinst:has_flags("/experimental:module") then - modulesflag = "/experimental:module" - end - assert(modulesflag, "compiler(msvc): does not support c++ module!") - - -- get output flag - local cachedir - local outputflag - if compinst:has_flags("/ifcOutput") then - outputflag = "/ifcOutput" - cachedir = path.join(target:autogendir(), "rules", "modules", "cache") - if not os.isdir(cachedir) then - os.mkdir(cachedir) - end - elseif compinst:has_flags("/module:output") then - outputflag = "/module:output" - end - assert(outputflag, "compiler(msvc): does not support c++ module!") - - -- get interface flag - local interfaceflag - if compinst:has_flags("/interface") then - interfaceflag = "/interface" - elseif compinst:has_flags("/module:interface") then - interfaceflag = "/module:interface" - end - assert(interfaceflag, "compiler(msvc): does not support c++ module!") - - -- get reference flag - local referenceflag - if compinst:has_flags("/reference") then - referenceflag = "/reference" - elseif compinst:has_flags("/module:interface") then - referenceflag = "/module:reference" - end - assert(referenceflag, "compiler(msvc): does not support c++ module!") - - -- attempt to compile the module files as cxx - local modulefiles = {} - opt = table.join(opt, {configs = {}}) - sourcebatch.sourcekind = "cxx" - sourcebatch.objectfiles = sourcebatch.objectfiles or {} - sourcebatch.dependfiles = sourcebatch.dependfiles or {} - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local objectfile = target:objectfile(sourcefile) - local dependfile = target:dependfile(objectfile) - local modulefile = (cachedir and path.join(cachedir, path.basename(sourcefile)) or objectfile) .. ".ifc" - - -- compile module file to *.pcm - local singlebatch = {sourcekind = "cxx", sourcefiles = {sourcefile}, objectfiles = {objectfile}, dependfiles = {dependfile}} - opt.configs.cxxflags = {modulesflag, interfaceflag, outputflag .. " " .. os.args(modulefile), "/TP"} - if cachedir then - table.insert(opt.configs.cxxflags, "/ifcSearchDir " .. os.args(cachedir)) - end - import("private.action.build.object").build(target, singlebatch, opt) - table.insert(modulefiles, modulefile) - table.insert(sourcebatch.objectfiles, objectfile) - table.insert(sourcebatch.dependfiles, dependfile) - end - - -- add module files - for _, modulefile in ipairs(modulefiles) do - target:add("cxxflags", modulesflag) - if cachedir then - target:add("cxxflags", "/ifcSearchDir " .. os.args(cachedir)) - else - target:add("cxxflags", referenceflag .. " " .. os.args(modulefile)) - end - end -end - --- build module files -function main(target, sourcebatch, opt) - local _, toolname = target:tool("cxx") - if toolname:find("clang", 1, true) then - _build_modulefiles_clang(target, sourcebatch, opt) - elseif toolname:find("gcc", 1, true) then - _build_modulefiles_gcc(target, sourcebatch, opt) - elseif toolname == "cl" then - _build_modulefiles_msvc(target, sourcebatch, opt) - else - raise("compiler(%s): does not support c++ module!", toolname) - end -end diff --git a/xmake/rules/c++/modules/clang.lua b/xmake/rules/c++/modules/clang.lua new file mode 100644 index 000000000..c71915ea6 --- /dev/null +++ b/xmake/rules/c++/modules/clang.lua @@ -0,0 +1,86 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file clang.lua +-- + +-- imports +import("core.tool.compiler") + +-- build module files +function _build_modulefiles(target, sourcebatch, opt) + + -- get modules flag + local modulesflag + local compinst = compiler.load("cxx", {target = target}) + if compinst:has_flags("-fmodules") then + modulesflag = "-fmodules" + elseif compinst:has_flags("-fmodules-ts") then + modulesflag = "-fmodules-ts" + end + assert(modulesflag, "compiler(clang): does not support c++ module!") + + -- the module cache directory + local cachedir = path.join(target:autogendir(), "rules", "modules", "cache") + + -- attempt to compile the module files as cxx + sourcebatch.sourcekind = "cxx" + sourcebatch.objectfiles = sourcebatch.objectfiles or {} + sourcebatch.dependfiles = sourcebatch.dependfiles or {} + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local objectfile = path.join(cachedir, path.basename(sourcefile) .. ".pcm") + table.insert(sourcebatch.objectfiles, objectfile) + table.insert(sourcebatch.dependfiles, target:dependfile(objectfile)) + end + + -- compile module files to *.pcm + opt = table.join(opt, {configs = {force = {cxxflags = {modulesflag, + "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir, + "--precompile", "-x c++-module", "-fmodules-cache-path=" .. cachedir}}}}) + import("private.action.build.object").build(target, sourcebatch, opt) + + -- compile *.pcm to object files + local modulefiles = {} + for idx, sourcefile in ipairs(sourcebatch.sourcefiles) do + local modulefile = sourcebatch.objectfiles[idx] + local objectfile = target:objectfile(sourcefile) + sourcebatch.sourcefiles[idx] = modulefile + sourcebatch.objectfiles[idx] = objectfile + sourcebatch.dependfiles[idx] = target:dependfile(objectfile) + table.insert(modulefiles, modulefile) + end + opt.configs = {cxxflags = {modulesflag, "-fmodules-cache-path=" .. cachedir, + "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir}} + opt.quiet = true + import("private.action.build.object").build(target, sourcebatch, opt) + + -- add module files + target:add("cxxflags", modulesflag, "-fmodules-cache-path=" .. cachedir) + -- FIXME It is invalid for the module implementation unit +-- target:add("cxxflags", "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir) + for _, modulefile in ipairs(modulefiles) do + target:add("cxxflags", "-fmodule-file=" .. modulefile) + end +end + +function build_with_batchjobs(target, batchjobs, sourcebatch, opt) + local rootjob = opt.rootjob + batchjobs:addjob("rule/c++.build.modules/clang", function (index, total) + opt.progress = (index * 100) / total + _build_modulefiles(target, sourcebatch, opt) + end, {rootjob = rootjob}) +end diff --git a/xmake/rules/c++/modules/gcc.lua b/xmake/rules/c++/modules/gcc.lua new file mode 100644 index 000000000..98d266c26 --- /dev/null +++ b/xmake/rules/c++/modules/gcc.lua @@ -0,0 +1,59 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file gcc.lua +-- + +-- imports +import("core.tool.compiler") + +-- build module files +function _build_modulefiles(target, sourcebatch, opt) + + -- get modules flag + local modulesflag + local compinst = compiler.load("cxx", {target = target}) + if compinst:has_flags("-fmodules-ts") then + modulesflag = "-fmodules-ts" + end + assert(modulesflag, "compiler(gcc): does not support c++ module!") + + -- attempt to compile the module files as cxx + sourcebatch.sourcekind = "cxx" + sourcebatch.objectfiles = sourcebatch.objectfiles or {} + sourcebatch.dependfiles = sourcebatch.dependfiles or {} + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local objectfile = target:objectfile(sourcefile) + table.insert(sourcebatch.objectfiles, objectfile) + table.insert(sourcebatch.dependfiles, target:dependfile(objectfile)) + end + + -- compile module files to object files + opt = table.join(opt, {configs = {force = {cxxflags = {modulesflag, "-x c++"}}}}) + import("private.action.build.object").build(target, sourcebatch, opt) + + -- add module files + target:add("cxxflags", modulesflag) +end + +function build_with_batchjobs(target, batchjobs, sourcebatch, opt) + local rootjob = opt.rootjob + batchjobs:addjob("rule/c++.build.modules/gcc", function (index, total) + opt.progress = (index * 100) / total + _build_modulefiles(target, sourcebatch, opt) + end, {rootjob = rootjob}) +end diff --git a/xmake/rules/c++/modules/msvc.lua b/xmake/rules/c++/modules/msvc.lua new file mode 100644 index 000000000..43b000c9b --- /dev/null +++ b/xmake/rules/c++/modules/msvc.lua @@ -0,0 +1,107 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file msvc.lua +-- + +-- imports +import("core.tool.compiler") + +-- build module files +function _build_modulefiles(target, sourcebatch, opt) + + -- get modules flag + local modulesflag + local compinst = compiler.load("cxx", {target = target}) + if compinst:has_flags("/experimental:module") then + modulesflag = "/experimental:module" + end + assert(modulesflag, "compiler(msvc): does not support c++ module!") + + -- get output flag + local cachedir + local outputflag + if compinst:has_flags("/ifcOutput") then + outputflag = "/ifcOutput" + cachedir = path.join(target:autogendir(), "rules", "modules", "cache") + if not os.isdir(cachedir) then + os.mkdir(cachedir) + end + elseif compinst:has_flags("/module:output") then + outputflag = "/module:output" + end + assert(outputflag, "compiler(msvc): does not support c++ module!") + + -- get interface flag + local interfaceflag + if compinst:has_flags("/interface") then + interfaceflag = "/interface" + elseif compinst:has_flags("/module:interface") then + interfaceflag = "/module:interface" + end + assert(interfaceflag, "compiler(msvc): does not support c++ module!") + + -- get reference flag + local referenceflag + if compinst:has_flags("/reference") then + referenceflag = "/reference" + elseif compinst:has_flags("/module:interface") then + referenceflag = "/module:reference" + end + assert(referenceflag, "compiler(msvc): does not support c++ module!") + + -- attempt to compile the module files as cxx + local modulefiles = {} + opt = table.join(opt, {configs = {}}) + sourcebatch.sourcekind = "cxx" + sourcebatch.objectfiles = sourcebatch.objectfiles or {} + sourcebatch.dependfiles = sourcebatch.dependfiles or {} + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local objectfile = target:objectfile(sourcefile) + local dependfile = target:dependfile(objectfile) + local modulefile = (cachedir and path.join(cachedir, path.basename(sourcefile)) or objectfile) .. ".ifc" + + -- compile module file to *.pcm + local singlebatch = {sourcekind = "cxx", sourcefiles = {sourcefile}, objectfiles = {objectfile}, dependfiles = {dependfile}} + opt.configs.cxxflags = {modulesflag, interfaceflag, outputflag .. " " .. os.args(modulefile), "/TP"} + if cachedir then + table.insert(opt.configs.cxxflags, "/ifcSearchDir " .. os.args(cachedir)) + end + import("private.action.build.object").build(target, singlebatch, opt) + table.insert(modulefiles, modulefile) + table.insert(sourcebatch.objectfiles, objectfile) + table.insert(sourcebatch.dependfiles, dependfile) + end + + -- add module files + for _, modulefile in ipairs(modulefiles) do + target:add("cxxflags", modulesflag) + if cachedir then + target:add("cxxflags", "/ifcSearchDir " .. os.args(cachedir)) + else + target:add("cxxflags", referenceflag .. " " .. os.args(modulefile)) + end + end +end + +function build_with_batchjobs(target, batchjobs, sourcebatch, opt) + local rootjob = opt.rootjob + batchjobs:addjob("rule/c++.build.modules/msvc", function (index, total) + opt.progress = (index * 100) / total + _build_modulefiles(target, sourcebatch, opt) + end, {rootjob = rootjob}) +end diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index dfaf04897..1b99473c0 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -21,5 +21,20 @@ -- define rule: c++.build.modules rule("c++.build.modules") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") - before_build_files("build_modulefiles") + on_load(function (target) + -- we disable to build across targets in parallel, because the source files may depend on other target modules + target:set("policy", "build.across_targets_in_parallel", false) + end) + before_build_files(function (target, batchjobs, sourcebatch, opt) + local _, toolname = target:tool("cxx") + if toolname:find("clang", 1, true) then + import("clang").build_with_batchjobs(target, batchjobs, sourcebatch, opt) + elseif toolname:find("gcc", 1, true) then + import("gcc").build_with_batchjobs(target, batchjobs, sourcebatch, opt) + elseif toolname == "cl" then + import("msvc").build_with_batchjobs(target, batchjobs, sourcebatch, opt) + else + raise("compiler(%s): does not support c++ module!", toolname) + end + end, {batch = true}) -- cgit v1.3.1 From 6cd055242dad6d0697f340f0cdc6b8f56e63df12 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 15 Oct 2021 00:46:08 +0800 Subject: improve gcc modules --- xmake/modules/private/action/build/object.lua | 6 +++--- xmake/rules/c++/modules/gcc.lua | 26 +++++++++++++++----------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/xmake/modules/private/action/build/object.lua b/xmake/modules/private/action/build/object.lua index 7a99de91e..e07ab76b7 100644 --- a/xmake/modules/private/action/build/object.lua +++ b/xmake/modules/private/action/build/object.lua @@ -85,7 +85,7 @@ function _do_build_file(target, sourcefile, opt) end -- build object -function _build_object(target, sourcefile, opt) +function build_object(target, sourcefile, opt) local script = target:script("build_file", _do_build_file) if script then script(target, sourcefile, opt) @@ -99,7 +99,7 @@ function build(target, sourcebatch, opt) opt.objectfile = sourcebatch.objectfiles[i] opt.dependfile = sourcebatch.dependfiles[i] opt.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile) - _build_object(target, sourcefile, opt) + build_object(target, sourcefile, opt) end end @@ -113,7 +113,7 @@ function main(target, batchjobs, sourcebatch, opt) local sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile) batchjobs:addjob(sourcefile, function (index, total) local build_opt = table.join({objectfile = objectfile, dependfile = dependfile, sourcekind = sourcekind, progress = (index * 100) / total}, opt) - _build_object(target, sourcefile, build_opt) + build_object(target, sourcefile, build_opt) end, {rootjob = rootjob}) end end diff --git a/xmake/rules/c++/modules/gcc.lua b/xmake/rules/c++/modules/gcc.lua index 98d266c26..cd1dac970 100644 --- a/xmake/rules/c++/modules/gcc.lua +++ b/xmake/rules/c++/modules/gcc.lua @@ -20,9 +20,10 @@ -- imports import("core.tool.compiler") +import("private.action.build.object", {alias = "objectbuilder"}) -- build module files -function _build_modulefiles(target, sourcebatch, opt) +function build_with_batchjobs(target, batchjobs, sourcebatch, opt) -- get modules flag local modulesflag @@ -32,7 +33,7 @@ function _build_modulefiles(target, sourcebatch, opt) end assert(modulesflag, "compiler(gcc): does not support c++ module!") - -- attempt to compile the module files as cxx + -- we need patch objectfiles to sourcebatch for linking module objects sourcebatch.sourcekind = "cxx" sourcebatch.objectfiles = sourcebatch.objectfiles or {} sourcebatch.dependfiles = sourcebatch.dependfiles or {} @@ -43,17 +44,20 @@ function _build_modulefiles(target, sourcebatch, opt) end -- compile module files to object files - opt = table.join(opt, {configs = {force = {cxxflags = {modulesflag, "-x c++"}}}}) - import("private.action.build.object").build(target, sourcebatch, opt) + local rootjob = opt.rootjob + for i = 1, #sourcebatch.sourcefiles do + local sourcefile = sourcebatch.sourcefiles[i] + batchjobs:addjob(sourcefile, function (index, total) + opt = table.join(opt, {configs = {force = {cxxflags = {modulesflag, "-x c++"}}}}) + opt.progress = (index * 100) / total + opt.objectfile = sourcebatch.objectfiles[i] + opt.dependfile = sourcebatch.dependfiles[i] + opt.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile) + objectbuilder.build_object(target, sourcefile, opt) + end, {rootjob = rootjob}) + end -- add module files target:add("cxxflags", modulesflag) end -function build_with_batchjobs(target, batchjobs, sourcebatch, opt) - local rootjob = opt.rootjob - batchjobs:addjob("rule/c++.build.modules/gcc", function (index, total) - opt.progress = (index * 100) / total - _build_modulefiles(target, sourcebatch, opt) - end, {rootjob = rootjob}) -end -- cgit v1.3.1 From fcc6bfb7b12634df1783ade4ecbcbb0a88ad1f80 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 15 Oct 2021 22:37:38 +0800 Subject: improve c++ modules for clang --- xmake/rules/c++/modules/clang.lua | 79 ++++++++++++++++++++++----------------- xmake/rules/c++/modules/gcc.lua | 14 +++---- 2 files changed, 51 insertions(+), 42 deletions(-) diff --git a/xmake/rules/c++/modules/clang.lua b/xmake/rules/c++/modules/clang.lua index c71915ea6..7037c0767 100644 --- a/xmake/rules/c++/modules/clang.lua +++ b/xmake/rules/c++/modules/clang.lua @@ -20,9 +20,10 @@ -- imports import("core.tool.compiler") +import("private.action.build.object", {alias = "objectbuilder"}) -- build module files -function _build_modulefiles(target, sourcebatch, opt) +function build_with_batchjobs(target, batchjobs, sourcebatch, opt) -- get modules flag local modulesflag @@ -37,50 +38,58 @@ function _build_modulefiles(target, sourcebatch, opt) -- the module cache directory local cachedir = path.join(target:autogendir(), "rules", "modules", "cache") - -- attempt to compile the module files as cxx + -- we need patch objectfiles to sourcebatch for linking module objects + local modulefiles = {} sourcebatch.sourcekind = "cxx" sourcebatch.objectfiles = sourcebatch.objectfiles or {} sourcebatch.dependfiles = sourcebatch.dependfiles or {} for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local objectfile = path.join(cachedir, path.basename(sourcefile) .. ".pcm") + local modulefile = path.join(cachedir, path.basename(sourcefile) .. ".pcm") + local objectfile = target:objectfile(sourcefile) table.insert(sourcebatch.objectfiles, objectfile) table.insert(sourcebatch.dependfiles, target:dependfile(objectfile)) + table.insert(modulefiles, modulefile) end - -- compile module files to *.pcm - opt = table.join(opt, {configs = {force = {cxxflags = {modulesflag, - "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir, - "--precompile", "-x c++-module", "-fmodules-cache-path=" .. cachedir}}}}) - import("private.action.build.object").build(target, sourcebatch, opt) + -- compile module files to object files + local rootjob = opt.rootjob + local count = 0 + local sourcefiles_total = #sourcebatch.sourcefiles + for i = 1, sourcefiles_total do + local sourcefile = sourcebatch.sourcefiles[i] + batchjobs:addjob(sourcefile, function (index, total) - -- compile *.pcm to object files - local modulefiles = {} - for idx, sourcefile in ipairs(sourcebatch.sourcefiles) do - local modulefile = sourcebatch.objectfiles[idx] - local objectfile = target:objectfile(sourcefile) - sourcebatch.sourcefiles[idx] = modulefile - sourcebatch.objectfiles[idx] = objectfile - sourcebatch.dependfiles[idx] = target:dependfile(objectfile) - table.insert(modulefiles, modulefile) - end - opt.configs = {cxxflags = {modulesflag, "-fmodules-cache-path=" .. cachedir, - "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir}} - opt.quiet = true - import("private.action.build.object").build(target, sourcebatch, opt) + -- compile module files to *.pcm + local opt2 = table.join(opt, {configs = {force = {cxxflags = {modulesflag, + "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir, + "--precompile", "-x c++-module", "-fmodules-cache-path=" .. cachedir}}}}) + opt2.progress = (index * 100) / total + opt2.objectfile = modulefiles[i] + opt2.dependfile = target:dependfile(opt2.objectfile) + opt2.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile) + objectbuilder.build_object(target, sourcefile, opt2) + + -- compile *.pcm to object files + opt2.configs = {force = {cxxflags = {modulesflag, "-fmodules-cache-path=" .. cachedir, + "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir}}} + opt2.quiet = true + opt2.objectfile = sourcebatch.objectfiles[i] + opt2.dependfile = sourcebatch.dependfiles[i] + objectbuilder.build_object(target, modulefiles[i], opt2) - -- add module files - target:add("cxxflags", modulesflag, "-fmodules-cache-path=" .. cachedir) - -- FIXME It is invalid for the module implementation unit --- target:add("cxxflags", "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir) - for _, modulefile in ipairs(modulefiles) do - target:add("cxxflags", "-fmodule-file=" .. modulefile) + -- add module flags to other c++ files after building all modules + count = count + 1 + if count == sourcefiles_total then + target:add("cxxflags", modulesflag, "-fmodules-cache-path=" .. cachedir, {force = true}) + -- FIXME It is invalid for the module implementation unit + --target:add("cxxflags", "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir, {force = true}) + for _, modulefile in ipairs(modulefiles) do + target:add("cxxflags", "-fmodule-file=" .. modulefile, {force = true}) + end + end + + end, {rootjob = rootjob}) end -end -function build_with_batchjobs(target, batchjobs, sourcebatch, opt) - local rootjob = opt.rootjob - batchjobs:addjob("rule/c++.build.modules/clang", function (index, total) - opt.progress = (index * 100) / total - _build_modulefiles(target, sourcebatch, opt) - end, {rootjob = rootjob}) end + diff --git a/xmake/rules/c++/modules/gcc.lua b/xmake/rules/c++/modules/gcc.lua index cd1dac970..d5ffbc57b 100644 --- a/xmake/rules/c++/modules/gcc.lua +++ b/xmake/rules/c++/modules/gcc.lua @@ -48,16 +48,16 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) for i = 1, #sourcebatch.sourcefiles do local sourcefile = sourcebatch.sourcefiles[i] batchjobs:addjob(sourcefile, function (index, total) - opt = table.join(opt, {configs = {force = {cxxflags = {modulesflag, "-x c++"}}}}) - opt.progress = (index * 100) / total - opt.objectfile = sourcebatch.objectfiles[i] - opt.dependfile = sourcebatch.dependfiles[i] - opt.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile) - objectbuilder.build_object(target, sourcefile, opt) + local opt2 = table.join(opt, {configs = {force = {cxxflags = {"-x c++"}}}}) + opt2.progress = (index * 100) / total + opt2.objectfile = sourcebatch.objectfiles[i] + opt2.dependfile = sourcebatch.dependfiles[i] + opt2.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile) + objectbuilder.build_object(target, sourcefile, opt2) end, {rootjob = rootjob}) end - -- add module files + -- add module flags target:add("cxxflags", modulesflag) end -- cgit v1.3.1 From 68653074d80808f265b354902dce70e0b3d2dcfe Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 15 Oct 2021 22:40:50 +0800 Subject: improve c++ modules for msvc --- xmake/rules/c++/modules/msvc.lua | 58 ++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/xmake/rules/c++/modules/msvc.lua b/xmake/rules/c++/modules/msvc.lua index 43b000c9b..6d100b96f 100644 --- a/xmake/rules/c++/modules/msvc.lua +++ b/xmake/rules/c++/modules/msvc.lua @@ -20,9 +20,10 @@ -- imports import("core.tool.compiler") +import("private.action.build.object", {alias = "objectbuilder"}) -- build module files -function _build_modulefiles(target, sourcebatch, opt) +function build_with_batchjobs(target, batchjobs, sourcebatch, opt) -- get modules flag local modulesflag @@ -64,9 +65,8 @@ function _build_modulefiles(target, sourcebatch, opt) end assert(referenceflag, "compiler(msvc): does not support c++ module!") - -- attempt to compile the module files as cxx + -- we need patch objectfiles to sourcebatch for linking module objects local modulefiles = {} - opt = table.join(opt, {configs = {}}) sourcebatch.sourcekind = "cxx" sourcebatch.objectfiles = sourcebatch.objectfiles or {} sourcebatch.dependfiles = sourcebatch.dependfiles or {} @@ -74,34 +74,40 @@ function _build_modulefiles(target, sourcebatch, opt) local objectfile = target:objectfile(sourcefile) local dependfile = target:dependfile(objectfile) local modulefile = (cachedir and path.join(cachedir, path.basename(sourcefile)) or objectfile) .. ".ifc" - - -- compile module file to *.pcm - local singlebatch = {sourcekind = "cxx", sourcefiles = {sourcefile}, objectfiles = {objectfile}, dependfiles = {dependfile}} - opt.configs.cxxflags = {modulesflag, interfaceflag, outputflag .. " " .. os.args(modulefile), "/TP"} - if cachedir then - table.insert(opt.configs.cxxflags, "/ifcSearchDir " .. os.args(cachedir)) - end - import("private.action.build.object").build(target, singlebatch, opt) table.insert(modulefiles, modulefile) table.insert(sourcebatch.objectfiles, objectfile) table.insert(sourcebatch.dependfiles, dependfile) end - -- add module files - for _, modulefile in ipairs(modulefiles) do - target:add("cxxflags", modulesflag) - if cachedir then - target:add("cxxflags", "/ifcSearchDir " .. os.args(cachedir)) - else - target:add("cxxflags", referenceflag .. " " .. os.args(modulefile)) - end + -- compile module files to object files + local rootjob = opt.rootjob + local count = 0 + local sourcefiles_total = #sourcebatch.sourcefiles + for i = 1, sourcefiles_total do + local sourcefile = sourcebatch.sourcefiles[i] + batchjobs:addjob(sourcefile, function (index, total) + local opt2 = table.join(opt, {configs = {force = {cxxflags = {interfaceflag, + outputflag .. " " .. os.args(modulefiles[i]), "/TP"}}}}) + opt2.progress = (index * 100) / total + opt2.objectfile = sourcebatch.objectfiles[i] + opt2.dependfile = sourcebatch.dependfiles[i] + opt2.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile) + objectbuilder.build_object(target, sourcefile, opt2) + + -- add module flags to other c++ files after building all modules + count = count + 1 + if count == sourcefiles_total and not cachedir then + for _, modulefile in ipairs(modulefiles) do + target:add("cxxflags", referenceflag .. " " .. os.args(modulefile)) + end + end + end, {rootjob = rootjob}) end -end -function build_with_batchjobs(target, batchjobs, sourcebatch, opt) - local rootjob = opt.rootjob - batchjobs:addjob("rule/c++.build.modules/msvc", function (index, total) - opt.progress = (index * 100) / total - _build_modulefiles(target, sourcebatch, opt) - end, {rootjob = rootjob}) + -- add module flags + target:add("cxxflags", modulesflag) + if cachedir then + target:add("cxxflags", "/ifcSearchDir " .. os.args(cachedir)) + end end + -- cgit v1.3.1 From 4526e745d6283106f46160c629984299e3297ab1 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 15 Oct 2021 22:44:16 +0800 Subject: add more c++ module tests --- tests/projects/c++/modules/dependence2/src/bar.mpp | 8 ++++++++ tests/projects/c++/modules/dependence2/src/cat.mpp | 8 ++++++++ tests/projects/c++/modules/dependence2/src/foo.mpp | 13 +++++++++++++ tests/projects/c++/modules/dependence2/src/main.cpp | 10 ++++++++++ tests/projects/c++/modules/dependence2/src/zoo.mpp | 8 ++++++++ tests/projects/c++/modules/dependence2/xmake.lua | 4 ++++ 6 files changed, 51 insertions(+) create mode 100644 tests/projects/c++/modules/dependence2/src/bar.mpp create mode 100644 tests/projects/c++/modules/dependence2/src/cat.mpp create mode 100644 tests/projects/c++/modules/dependence2/src/foo.mpp create mode 100644 tests/projects/c++/modules/dependence2/src/main.cpp create mode 100644 tests/projects/c++/modules/dependence2/src/zoo.mpp create mode 100644 tests/projects/c++/modules/dependence2/xmake.lua diff --git a/tests/projects/c++/modules/dependence2/src/bar.mpp b/tests/projects/c++/modules/dependence2/src/bar.mpp new file mode 100644 index 000000000..140924a85 --- /dev/null +++ b/tests/projects/c++/modules/dependence2/src/bar.mpp @@ -0,0 +1,8 @@ +export module bar; +import zoo; + +export namespace bar { + int add(int a, int b) { + return zoo::add(a, b); + } +} diff --git a/tests/projects/c++/modules/dependence2/src/cat.mpp b/tests/projects/c++/modules/dependence2/src/cat.mpp new file mode 100644 index 000000000..652940c08 --- /dev/null +++ b/tests/projects/c++/modules/dependence2/src/cat.mpp @@ -0,0 +1,8 @@ +export module cat; + +export namespace cat { + int sub(int a, int b) { + return a - b; + } +} + diff --git a/tests/projects/c++/modules/dependence2/src/foo.mpp b/tests/projects/c++/modules/dependence2/src/foo.mpp new file mode 100644 index 000000000..5aac74086 --- /dev/null +++ b/tests/projects/c++/modules/dependence2/src/foo.mpp @@ -0,0 +1,13 @@ +export module foo; +import bar; +import cat; + +export namespace foo { + int add(int a, int b) { + return bar::add(a, b); + } + int sub(int a, int b) { + return cat::sub(a, b); + } +} + diff --git a/tests/projects/c++/modules/dependence2/src/main.cpp b/tests/projects/c++/modules/dependence2/src/main.cpp new file mode 100644 index 000000000..b5c04f1b2 --- /dev/null +++ b/tests/projects/c++/modules/dependence2/src/main.cpp @@ -0,0 +1,10 @@ +#include + +import foo; + +int main() { + printf("add(1, 2): %d\n", foo::add(1, 2)); + printf("sub(1, 2): %d\n", foo::sub(1, 2)); + return 0; +} + diff --git a/tests/projects/c++/modules/dependence2/src/zoo.mpp b/tests/projects/c++/modules/dependence2/src/zoo.mpp new file mode 100644 index 000000000..60c86ddf6 --- /dev/null +++ b/tests/projects/c++/modules/dependence2/src/zoo.mpp @@ -0,0 +1,8 @@ +export module zoo; + +export namespace zoo { + int add(int a, int b) { + return a + b; + } +} + diff --git a/tests/projects/c++/modules/dependence2/xmake.lua b/tests/projects/c++/modules/dependence2/xmake.lua new file mode 100644 index 000000000..6d64b49b1 --- /dev/null +++ b/tests/projects/c++/modules/dependence2/xmake.lua @@ -0,0 +1,4 @@ +set_languages("c++20") +target("dependence") + set_kind("binary") + add_files("src/*.cpp", "src/*.mpp") -- cgit v1.3.1 From 4db6d4b4eab1d11a93cd48778c9dc19699d605ce Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 15 Oct 2021 22:45:02 +0800 Subject: fix policy --- xmake/rules/c++/modules/xmake.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 1b99473c0..53a7899d0 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -21,11 +21,12 @@ -- define rule: c++.build.modules rule("c++.build.modules") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") - on_load(function (target) + before_build_files(function (target, batchjobs, sourcebatch, opt) -- we disable to build across targets in parallel, because the source files may depend on other target modules + -- @note we cannot set it in on_load, because it will affect all c++ projects target:set("policy", "build.across_targets_in_parallel", false) - end) - before_build_files(function (target, batchjobs, sourcebatch, opt) + + -- build module files with batchjobs local _, toolname = target:tool("cxx") if toolname:find("clang", 1, true) then import("clang").build_with_batchjobs(target, batchjobs, sourcebatch, opt) -- cgit v1.3.1 From 031626f8266e7bcced4d0f1f8f7a7cc5c45ba00a Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 15 Oct 2021 22:56:04 +0800 Subject: add generate moduledeps stub --- xmake/rules/c++/modules/moduledeps.lua | 24 ++++++++++++++++++++++++ xmake/rules/c++/modules/xmake.lua | 9 +++++++++ 2 files changed, 33 insertions(+) create mode 100644 xmake/rules/c++/modules/moduledeps.lua diff --git a/xmake/rules/c++/modules/moduledeps.lua b/xmake/rules/c++/modules/moduledeps.lua new file mode 100644 index 000000000..25842c9f7 --- /dev/null +++ b/xmake/rules/c++/modules/moduledeps.lua @@ -0,0 +1,24 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file moduledeps.lua +-- + +-- generate module deps +function generate(target, sourcebatch, opt) +end + diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 53a7899d0..0e1e99d5d 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -21,6 +21,15 @@ -- define rule: c++.build.modules rule("c++.build.modules") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") + before_build(function (target, opt) + local sourcebatches = target:sourcebatches() + if sourcebatches then + local sourcebatch = sourcebatches["c++.build.modules"] + if sourcebatch then + import("moduledeps").generate(target, sourcebatch, opt) + end + end + end) before_build_files(function (target, batchjobs, sourcebatch, opt) -- we disable to build across targets in parallel, because the source files may depend on other target modules -- @note we cannot set it in on_load, because it will affect all c++ projects -- cgit v1.3.1 From 8ca0e848506b052bcf107c0b65d2f9d04247de26 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 15 Oct 2021 23:09:05 +0800 Subject: generate module deps --- xmake/rules/c++/modules/moduledeps.lua | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/xmake/rules/c++/modules/moduledeps.lua b/xmake/rules/c++/modules/moduledeps.lua index 25842c9f7..9ae2b3cab 100644 --- a/xmake/rules/c++/modules/moduledeps.lua +++ b/xmake/rules/c++/modules/moduledeps.lua @@ -18,7 +18,47 @@ -- @file moduledeps.lua -- +-- imports +import("core.project.depend") +import("utils.progress") + +-- generate module deps for the given file +function _generate_moduledeps(target, sourcefile, opt) + local dependfile = target:dependfile(sourcefile) + depend.on_changed(function () + + -- trace progress + progress.show(opt.progress, "${color.build.target}generating.deps %s", sourcefile) + + -- generating deps + local module_name + local module_deps + local sourcecode = io.readfile(sourcefile) + sourcecode = sourcecode:gsub("//.-\n", "\n") + sourcecode = sourcecode:gsub("/%*.-%*/", "") + for _, line in ipairs(sourcecode:split("\n", {plain = true})) do + if not module_name then + module_name = line:match("export%s+module%s+(.+)%s*;") + end + local module_depname = line:match("import%s+(.+)%s*;") + if module_depname then + module_deps = module_deps or {} + table.insert(module_deps, module_depname) + end + end + + -- save depend data + if module_name then + io.save(dependfile, {name = module_name, deps = module_deps, file = sourcefile}) + end + + end, {dependfile = dependfile, files = {sourcefile}}) +end + -- generate module deps function generate(target, sourcebatch, opt) + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + _generate_moduledeps(target, sourcefile, opt) + end end -- cgit v1.3.1 From 091e754eb4d5328385fed59d5c4f92e09355ff51 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 15 Oct 2021 23:18:52 +0800 Subject: load module deps --- xmake/rules/c++/modules/build_modules/clang.lua | 95 +++++++++++++++++ xmake/rules/c++/modules/build_modules/gcc.lua | 63 +++++++++++ .../c++/modules/build_modules/module_parser.lua | 92 ++++++++++++++++ xmake/rules/c++/modules/build_modules/msvc.lua | 118 +++++++++++++++++++++ xmake/rules/c++/modules/clang.lua | 95 ----------------- xmake/rules/c++/modules/gcc.lua | 63 ----------- xmake/rules/c++/modules/moduledeps.lua | 64 ----------- xmake/rules/c++/modules/msvc.lua | 113 -------------------- xmake/rules/c++/modules/xmake.lua | 8 +- 9 files changed, 372 insertions(+), 339 deletions(-) create mode 100644 xmake/rules/c++/modules/build_modules/clang.lua create mode 100644 xmake/rules/c++/modules/build_modules/gcc.lua create mode 100644 xmake/rules/c++/modules/build_modules/module_parser.lua create mode 100644 xmake/rules/c++/modules/build_modules/msvc.lua delete mode 100644 xmake/rules/c++/modules/clang.lua delete mode 100644 xmake/rules/c++/modules/gcc.lua delete mode 100644 xmake/rules/c++/modules/moduledeps.lua delete mode 100644 xmake/rules/c++/modules/msvc.lua diff --git a/xmake/rules/c++/modules/build_modules/clang.lua b/xmake/rules/c++/modules/build_modules/clang.lua new file mode 100644 index 000000000..7037c0767 --- /dev/null +++ b/xmake/rules/c++/modules/build_modules/clang.lua @@ -0,0 +1,95 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file clang.lua +-- + +-- imports +import("core.tool.compiler") +import("private.action.build.object", {alias = "objectbuilder"}) + +-- build module files +function build_with_batchjobs(target, batchjobs, sourcebatch, opt) + + -- get modules flag + local modulesflag + local compinst = compiler.load("cxx", {target = target}) + if compinst:has_flags("-fmodules") then + modulesflag = "-fmodules" + elseif compinst:has_flags("-fmodules-ts") then + modulesflag = "-fmodules-ts" + end + assert(modulesflag, "compiler(clang): does not support c++ module!") + + -- the module cache directory + local cachedir = path.join(target:autogendir(), "rules", "modules", "cache") + + -- we need patch objectfiles to sourcebatch for linking module objects + local modulefiles = {} + sourcebatch.sourcekind = "cxx" + sourcebatch.objectfiles = sourcebatch.objectfiles or {} + sourcebatch.dependfiles = sourcebatch.dependfiles or {} + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local modulefile = path.join(cachedir, path.basename(sourcefile) .. ".pcm") + local objectfile = target:objectfile(sourcefile) + table.insert(sourcebatch.objectfiles, objectfile) + table.insert(sourcebatch.dependfiles, target:dependfile(objectfile)) + table.insert(modulefiles, modulefile) + end + + -- compile module files to object files + local rootjob = opt.rootjob + local count = 0 + local sourcefiles_total = #sourcebatch.sourcefiles + for i = 1, sourcefiles_total do + local sourcefile = sourcebatch.sourcefiles[i] + batchjobs:addjob(sourcefile, function (index, total) + + -- compile module files to *.pcm + local opt2 = table.join(opt, {configs = {force = {cxxflags = {modulesflag, + "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir, + "--precompile", "-x c++-module", "-fmodules-cache-path=" .. cachedir}}}}) + opt2.progress = (index * 100) / total + opt2.objectfile = modulefiles[i] + opt2.dependfile = target:dependfile(opt2.objectfile) + opt2.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile) + objectbuilder.build_object(target, sourcefile, opt2) + + -- compile *.pcm to object files + opt2.configs = {force = {cxxflags = {modulesflag, "-fmodules-cache-path=" .. cachedir, + "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir}}} + opt2.quiet = true + opt2.objectfile = sourcebatch.objectfiles[i] + opt2.dependfile = sourcebatch.dependfiles[i] + objectbuilder.build_object(target, modulefiles[i], opt2) + + -- add module flags to other c++ files after building all modules + count = count + 1 + if count == sourcefiles_total then + target:add("cxxflags", modulesflag, "-fmodules-cache-path=" .. cachedir, {force = true}) + -- FIXME It is invalid for the module implementation unit + --target:add("cxxflags", "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir, {force = true}) + for _, modulefile in ipairs(modulefiles) do + target:add("cxxflags", "-fmodule-file=" .. modulefile, {force = true}) + end + end + + end, {rootjob = rootjob}) + end + +end + diff --git a/xmake/rules/c++/modules/build_modules/gcc.lua b/xmake/rules/c++/modules/build_modules/gcc.lua new file mode 100644 index 000000000..d5ffbc57b --- /dev/null +++ b/xmake/rules/c++/modules/build_modules/gcc.lua @@ -0,0 +1,63 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file gcc.lua +-- + +-- imports +import("core.tool.compiler") +import("private.action.build.object", {alias = "objectbuilder"}) + +-- build module files +function build_with_batchjobs(target, batchjobs, sourcebatch, opt) + + -- get modules flag + local modulesflag + local compinst = compiler.load("cxx", {target = target}) + if compinst:has_flags("-fmodules-ts") then + modulesflag = "-fmodules-ts" + end + assert(modulesflag, "compiler(gcc): does not support c++ module!") + + -- we need patch objectfiles to sourcebatch for linking module objects + sourcebatch.sourcekind = "cxx" + sourcebatch.objectfiles = sourcebatch.objectfiles or {} + sourcebatch.dependfiles = sourcebatch.dependfiles or {} + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local objectfile = target:objectfile(sourcefile) + table.insert(sourcebatch.objectfiles, objectfile) + table.insert(sourcebatch.dependfiles, target:dependfile(objectfile)) + end + + -- compile module files to object files + local rootjob = opt.rootjob + for i = 1, #sourcebatch.sourcefiles do + local sourcefile = sourcebatch.sourcefiles[i] + batchjobs:addjob(sourcefile, function (index, total) + local opt2 = table.join(opt, {configs = {force = {cxxflags = {"-x c++"}}}}) + opt2.progress = (index * 100) / total + opt2.objectfile = sourcebatch.objectfiles[i] + opt2.dependfile = sourcebatch.dependfiles[i] + opt2.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile) + objectbuilder.build_object(target, sourcefile, opt2) + end, {rootjob = rootjob}) + end + + -- add module flags + target:add("cxxflags", modulesflag) +end + diff --git a/xmake/rules/c++/modules/build_modules/module_parser.lua b/xmake/rules/c++/modules/build_modules/module_parser.lua new file mode 100644 index 000000000..a3991a5e1 --- /dev/null +++ b/xmake/rules/c++/modules/build_modules/module_parser.lua @@ -0,0 +1,92 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file module_parser.lua +-- + +-- imports +import("core.project.depend") +import("utils.progress") + +-- get depend file of module source file +function _get_dependfile_of_modulesource(target, sourcefile) + return target:dependfile(sourcefile) +end + +-- get depend file of module object file +function _get_dependfile_of_moduleobject(target, sourcefile) + local objectfile = target:objectfile(sourcefile) + return target:dependfile(objectfile) +end + +-- generate module deps for the given file +function _generate_moduledeps(target, sourcefile, opt) + local dependfile = _get_dependfile_of_modulesource(target, sourcefile) + depend.on_changed(function () + + -- trace progress + progress.show(opt.progress, "${color.build.target}generating.deps %s", sourcefile) + + -- generating deps + local module_name + local module_deps + local sourcecode = io.readfile(sourcefile) + sourcecode = sourcecode:gsub("//.-\n", "\n") + sourcecode = sourcecode:gsub("/%*.-%*/", "") + for _, line in ipairs(sourcecode:split("\n", {plain = true})) do + if not module_name then + module_name = line:match("export%s+module%s+(.+)%s*;") + end + local module_depname = line:match("import%s+(.+)%s*;") + if module_depname then + module_deps = module_deps or {} + table.insert(module_deps, module_depname) + end + end + + -- save depend data + if module_name then + local dependinfo = {moduleinfo = {name = module_name, deps = module_deps, file = sourcefile}} + return dependinfo + end + + end, {dependfile = dependfile, files = {sourcefile}}) +end + +-- generate module deps +function generate(target, sourcebatch, opt) + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + _generate_moduledeps(target, sourcefile, opt) + end +end + +-- load module deps +function load(target, sourcebatch, opt) + local moduledeps + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local dependfile = _get_dependfile_of_modulesource(target, sourcefile) + if os.isfile(dependfile) then + local data = io.load(dependfile) + if data then + local moduleinfo = data.moduleinfo + moduledeps = moduledeps or {} + moduledeps[moduleinfo.name] = moduleinfo + end + end + end + return moduledeps +end diff --git a/xmake/rules/c++/modules/build_modules/msvc.lua b/xmake/rules/c++/modules/build_modules/msvc.lua new file mode 100644 index 000000000..15be07a41 --- /dev/null +++ b/xmake/rules/c++/modules/build_modules/msvc.lua @@ -0,0 +1,118 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file msvc.lua +-- + +-- imports +import("core.tool.compiler") +import("private.action.build.object", {alias = "objectbuilder"}) +import("module_parser") + +-- build module files +function build_with_batchjobs(target, batchjobs, sourcebatch, opt) + + -- get modules flag + local modulesflag + local compinst = compiler.load("cxx", {target = target}) + if compinst:has_flags("/experimental:module") then + modulesflag = "/experimental:module" + end + assert(modulesflag, "compiler(msvc): does not support c++ module!") + + -- get output flag + local cachedir + local outputflag + if compinst:has_flags("/ifcOutput") then + outputflag = "/ifcOutput" + cachedir = path.join(target:autogendir(), "rules", "modules", "cache") + if not os.isdir(cachedir) then + os.mkdir(cachedir) + end + elseif compinst:has_flags("/module:output") then + outputflag = "/module:output" + end + assert(outputflag, "compiler(msvc): does not support c++ module!") + + -- get interface flag + local interfaceflag + if compinst:has_flags("/interface") then + interfaceflag = "/interface" + elseif compinst:has_flags("/module:interface") then + interfaceflag = "/module:interface" + end + assert(interfaceflag, "compiler(msvc): does not support c++ module!") + + -- get reference flag + local referenceflag + if compinst:has_flags("/reference") then + referenceflag = "/reference" + elseif compinst:has_flags("/module:interface") then + referenceflag = "/module:reference" + end + assert(referenceflag, "compiler(msvc): does not support c++ module!") + + -- we need patch objectfiles to sourcebatch for linking module objects + local modulefiles = {} + sourcebatch.sourcekind = "cxx" + sourcebatch.objectfiles = sourcebatch.objectfiles or {} + sourcebatch.dependfiles = sourcebatch.dependfiles or {} + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local objectfile = target:objectfile(sourcefile) + local dependfile = target:dependfile(objectfile) + local modulefile = (cachedir and path.join(cachedir, path.basename(sourcefile)) or objectfile) .. ".ifc" + table.insert(modulefiles, modulefile) + table.insert(sourcebatch.objectfiles, objectfile) + table.insert(sourcebatch.dependfiles, dependfile) + end + + -- load moduledeps + local moduledeps = module_parser.load(target, sourcebatch, opt) + print(moduledeps) + + -- compile module files to object files + local rootjob = opt.rootjob + local count = 0 + local sourcefiles_total = #sourcebatch.sourcefiles + for i = 1, sourcefiles_total do + local sourcefile = sourcebatch.sourcefiles[i] + batchjobs:addjob(sourcefile, function (index, total) + local opt2 = table.join(opt, {configs = {force = {cxxflags = {interfaceflag, + outputflag .. " " .. os.args(modulefiles[i]), "/TP"}}}}) + opt2.progress = (index * 100) / total + opt2.objectfile = sourcebatch.objectfiles[i] + opt2.dependfile = sourcebatch.dependfiles[i] + opt2.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile) + objectbuilder.build_object(target, sourcefile, opt2) + + -- add module flags to other c++ files after building all modules + count = count + 1 + if count == sourcefiles_total and not cachedir then + for _, modulefile in ipairs(modulefiles) do + target:add("cxxflags", referenceflag .. " " .. os.args(modulefile)) + end + end + end, {rootjob = rootjob}) + end + + -- add module flags + target:add("cxxflags", modulesflag) + if cachedir then + target:add("cxxflags", "/ifcSearchDir " .. os.args(cachedir)) + end +end + diff --git a/xmake/rules/c++/modules/clang.lua b/xmake/rules/c++/modules/clang.lua deleted file mode 100644 index 7037c0767..000000000 --- a/xmake/rules/c++/modules/clang.lua +++ /dev/null @@ -1,95 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- 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 --- --- http://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. --- --- Copyright (C) 2015-present, TBOOX Open Source Group. --- --- @author ruki --- @file clang.lua --- - --- imports -import("core.tool.compiler") -import("private.action.build.object", {alias = "objectbuilder"}) - --- build module files -function build_with_batchjobs(target, batchjobs, sourcebatch, opt) - - -- get modules flag - local modulesflag - local compinst = compiler.load("cxx", {target = target}) - if compinst:has_flags("-fmodules") then - modulesflag = "-fmodules" - elseif compinst:has_flags("-fmodules-ts") then - modulesflag = "-fmodules-ts" - end - assert(modulesflag, "compiler(clang): does not support c++ module!") - - -- the module cache directory - local cachedir = path.join(target:autogendir(), "rules", "modules", "cache") - - -- we need patch objectfiles to sourcebatch for linking module objects - local modulefiles = {} - sourcebatch.sourcekind = "cxx" - sourcebatch.objectfiles = sourcebatch.objectfiles or {} - sourcebatch.dependfiles = sourcebatch.dependfiles or {} - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local modulefile = path.join(cachedir, path.basename(sourcefile) .. ".pcm") - local objectfile = target:objectfile(sourcefile) - table.insert(sourcebatch.objectfiles, objectfile) - table.insert(sourcebatch.dependfiles, target:dependfile(objectfile)) - table.insert(modulefiles, modulefile) - end - - -- compile module files to object files - local rootjob = opt.rootjob - local count = 0 - local sourcefiles_total = #sourcebatch.sourcefiles - for i = 1, sourcefiles_total do - local sourcefile = sourcebatch.sourcefiles[i] - batchjobs:addjob(sourcefile, function (index, total) - - -- compile module files to *.pcm - local opt2 = table.join(opt, {configs = {force = {cxxflags = {modulesflag, - "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir, - "--precompile", "-x c++-module", "-fmodules-cache-path=" .. cachedir}}}}) - opt2.progress = (index * 100) / total - opt2.objectfile = modulefiles[i] - opt2.dependfile = target:dependfile(opt2.objectfile) - opt2.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile) - objectbuilder.build_object(target, sourcefile, opt2) - - -- compile *.pcm to object files - opt2.configs = {force = {cxxflags = {modulesflag, "-fmodules-cache-path=" .. cachedir, - "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir}}} - opt2.quiet = true - opt2.objectfile = sourcebatch.objectfiles[i] - opt2.dependfile = sourcebatch.dependfiles[i] - objectbuilder.build_object(target, modulefiles[i], opt2) - - -- add module flags to other c++ files after building all modules - count = count + 1 - if count == sourcefiles_total then - target:add("cxxflags", modulesflag, "-fmodules-cache-path=" .. cachedir, {force = true}) - -- FIXME It is invalid for the module implementation unit - --target:add("cxxflags", "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir, {force = true}) - for _, modulefile in ipairs(modulefiles) do - target:add("cxxflags", "-fmodule-file=" .. modulefile, {force = true}) - end - end - - end, {rootjob = rootjob}) - end - -end - diff --git a/xmake/rules/c++/modules/gcc.lua b/xmake/rules/c++/modules/gcc.lua deleted file mode 100644 index d5ffbc57b..000000000 --- a/xmake/rules/c++/modules/gcc.lua +++ /dev/null @@ -1,63 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- 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 --- --- http://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. --- --- Copyright (C) 2015-present, TBOOX Open Source Group. --- --- @author ruki --- @file gcc.lua --- - --- imports -import("core.tool.compiler") -import("private.action.build.object", {alias = "objectbuilder"}) - --- build module files -function build_with_batchjobs(target, batchjobs, sourcebatch, opt) - - -- get modules flag - local modulesflag - local compinst = compiler.load("cxx", {target = target}) - if compinst:has_flags("-fmodules-ts") then - modulesflag = "-fmodules-ts" - end - assert(modulesflag, "compiler(gcc): does not support c++ module!") - - -- we need patch objectfiles to sourcebatch for linking module objects - sourcebatch.sourcekind = "cxx" - sourcebatch.objectfiles = sourcebatch.objectfiles or {} - sourcebatch.dependfiles = sourcebatch.dependfiles or {} - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local objectfile = target:objectfile(sourcefile) - table.insert(sourcebatch.objectfiles, objectfile) - table.insert(sourcebatch.dependfiles, target:dependfile(objectfile)) - end - - -- compile module files to object files - local rootjob = opt.rootjob - for i = 1, #sourcebatch.sourcefiles do - local sourcefile = sourcebatch.sourcefiles[i] - batchjobs:addjob(sourcefile, function (index, total) - local opt2 = table.join(opt, {configs = {force = {cxxflags = {"-x c++"}}}}) - opt2.progress = (index * 100) / total - opt2.objectfile = sourcebatch.objectfiles[i] - opt2.dependfile = sourcebatch.dependfiles[i] - opt2.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile) - objectbuilder.build_object(target, sourcefile, opt2) - end, {rootjob = rootjob}) - end - - -- add module flags - target:add("cxxflags", modulesflag) -end - diff --git a/xmake/rules/c++/modules/moduledeps.lua b/xmake/rules/c++/modules/moduledeps.lua deleted file mode 100644 index 9ae2b3cab..000000000 --- a/xmake/rules/c++/modules/moduledeps.lua +++ /dev/null @@ -1,64 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- 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 --- --- http://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. --- --- Copyright (C) 2015-present, TBOOX Open Source Group. --- --- @author ruki --- @file moduledeps.lua --- - --- imports -import("core.project.depend") -import("utils.progress") - --- generate module deps for the given file -function _generate_moduledeps(target, sourcefile, opt) - local dependfile = target:dependfile(sourcefile) - depend.on_changed(function () - - -- trace progress - progress.show(opt.progress, "${color.build.target}generating.deps %s", sourcefile) - - -- generating deps - local module_name - local module_deps - local sourcecode = io.readfile(sourcefile) - sourcecode = sourcecode:gsub("//.-\n", "\n") - sourcecode = sourcecode:gsub("/%*.-%*/", "") - for _, line in ipairs(sourcecode:split("\n", {plain = true})) do - if not module_name then - module_name = line:match("export%s+module%s+(.+)%s*;") - end - local module_depname = line:match("import%s+(.+)%s*;") - if module_depname then - module_deps = module_deps or {} - table.insert(module_deps, module_depname) - end - end - - -- save depend data - if module_name then - io.save(dependfile, {name = module_name, deps = module_deps, file = sourcefile}) - end - - end, {dependfile = dependfile, files = {sourcefile}}) -end - --- generate module deps -function generate(target, sourcebatch, opt) - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - _generate_moduledeps(target, sourcefile, opt) - end -end - diff --git a/xmake/rules/c++/modules/msvc.lua b/xmake/rules/c++/modules/msvc.lua deleted file mode 100644 index 6d100b96f..000000000 --- a/xmake/rules/c++/modules/msvc.lua +++ /dev/null @@ -1,113 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- 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 --- --- http://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. --- --- Copyright (C) 2015-present, TBOOX Open Source Group. --- --- @author ruki --- @file msvc.lua --- - --- imports -import("core.tool.compiler") -import("private.action.build.object", {alias = "objectbuilder"}) - --- build module files -function build_with_batchjobs(target, batchjobs, sourcebatch, opt) - - -- get modules flag - local modulesflag - local compinst = compiler.load("cxx", {target = target}) - if compinst:has_flags("/experimental:module") then - modulesflag = "/experimental:module" - end - assert(modulesflag, "compiler(msvc): does not support c++ module!") - - -- get output flag - local cachedir - local outputflag - if compinst:has_flags("/ifcOutput") then - outputflag = "/ifcOutput" - cachedir = path.join(target:autogendir(), "rules", "modules", "cache") - if not os.isdir(cachedir) then - os.mkdir(cachedir) - end - elseif compinst:has_flags("/module:output") then - outputflag = "/module:output" - end - assert(outputflag, "compiler(msvc): does not support c++ module!") - - -- get interface flag - local interfaceflag - if compinst:has_flags("/interface") then - interfaceflag = "/interface" - elseif compinst:has_flags("/module:interface") then - interfaceflag = "/module:interface" - end - assert(interfaceflag, "compiler(msvc): does not support c++ module!") - - -- get reference flag - local referenceflag - if compinst:has_flags("/reference") then - referenceflag = "/reference" - elseif compinst:has_flags("/module:interface") then - referenceflag = "/module:reference" - end - assert(referenceflag, "compiler(msvc): does not support c++ module!") - - -- we need patch objectfiles to sourcebatch for linking module objects - local modulefiles = {} - sourcebatch.sourcekind = "cxx" - sourcebatch.objectfiles = sourcebatch.objectfiles or {} - sourcebatch.dependfiles = sourcebatch.dependfiles or {} - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local objectfile = target:objectfile(sourcefile) - local dependfile = target:dependfile(objectfile) - local modulefile = (cachedir and path.join(cachedir, path.basename(sourcefile)) or objectfile) .. ".ifc" - table.insert(modulefiles, modulefile) - table.insert(sourcebatch.objectfiles, objectfile) - table.insert(sourcebatch.dependfiles, dependfile) - end - - -- compile module files to object files - local rootjob = opt.rootjob - local count = 0 - local sourcefiles_total = #sourcebatch.sourcefiles - for i = 1, sourcefiles_total do - local sourcefile = sourcebatch.sourcefiles[i] - batchjobs:addjob(sourcefile, function (index, total) - local opt2 = table.join(opt, {configs = {force = {cxxflags = {interfaceflag, - outputflag .. " " .. os.args(modulefiles[i]), "/TP"}}}}) - opt2.progress = (index * 100) / total - opt2.objectfile = sourcebatch.objectfiles[i] - opt2.dependfile = sourcebatch.dependfiles[i] - opt2.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile) - objectbuilder.build_object(target, sourcefile, opt2) - - -- add module flags to other c++ files after building all modules - count = count + 1 - if count == sourcefiles_total and not cachedir then - for _, modulefile in ipairs(modulefiles) do - target:add("cxxflags", referenceflag .. " " .. os.args(modulefile)) - end - end - end, {rootjob = rootjob}) - end - - -- add module flags - target:add("cxxflags", modulesflag) - if cachedir then - target:add("cxxflags", "/ifcSearchDir " .. os.args(cachedir)) - end -end - diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 0e1e99d5d..ad36226eb 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -26,7 +26,7 @@ rule("c++.build.modules") if sourcebatches then local sourcebatch = sourcebatches["c++.build.modules"] if sourcebatch then - import("moduledeps").generate(target, sourcebatch, opt) + import("build_modules.module_parser").generate(target, sourcebatch, opt) end end end) @@ -38,11 +38,11 @@ rule("c++.build.modules") -- build module files with batchjobs local _, toolname = target:tool("cxx") if toolname:find("clang", 1, true) then - import("clang").build_with_batchjobs(target, batchjobs, sourcebatch, opt) + import("build_modules.clang").build_with_batchjobs(target, batchjobs, sourcebatch, opt) elseif toolname:find("gcc", 1, true) then - import("gcc").build_with_batchjobs(target, batchjobs, sourcebatch, opt) + import("build_modules.gcc").build_with_batchjobs(target, batchjobs, sourcebatch, opt) elseif toolname == "cl" then - import("msvc").build_with_batchjobs(target, batchjobs, sourcebatch, opt) + import("build_modules.msvc").build_with_batchjobs(target, batchjobs, sourcebatch, opt) else raise("compiler(%s): does not support c++ module!", toolname) end -- cgit v1.3.1 From d71f50b60d8872c1ab5fc92b21d9f41fe93983b3 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 15 Oct 2021 23:57:07 +0800 Subject: improve to load moduledeps --- xmake/rules/c++/modules/build_modules/module_parser.lua | 12 ++++++++---- xmake/rules/c++/modules/build_modules/msvc.lua | 2 +- xmake/rules/c++/modules/xmake.lua | 9 --------- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/xmake/rules/c++/modules/build_modules/module_parser.lua b/xmake/rules/c++/modules/build_modules/module_parser.lua index a3991a5e1..5ac4e42e9 100644 --- a/xmake/rules/c++/modules/build_modules/module_parser.lua +++ b/xmake/rules/c++/modules/build_modules/module_parser.lua @@ -20,14 +20,13 @@ -- imports import("core.project.depend") -import("utils.progress") -- get depend file of module source file function _get_dependfile_of_modulesource(target, sourcefile) return target:dependfile(sourcefile) end --- get depend file of module object file +-- get depend file of module object file, compiler will rewrite it function _get_dependfile_of_moduleobject(target, sourcefile) local objectfile = target:objectfile(sourcefile) return target:dependfile(objectfile) @@ -38,8 +37,8 @@ function _generate_moduledeps(target, sourcefile, opt) local dependfile = _get_dependfile_of_modulesource(target, sourcefile) depend.on_changed(function () - -- trace progress - progress.show(opt.progress, "${color.build.target}generating.deps %s", sourcefile) + -- trace + vprint("generating.moduledeps %s", sourcefile) -- generating deps local module_name @@ -76,6 +75,11 @@ end -- load module deps function load(target, sourcebatch, opt) + + -- do generate first + generate(target, sourcebatch, opt) + + -- load deps local moduledeps for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = _get_dependfile_of_modulesource(target, sourcefile) diff --git a/xmake/rules/c++/modules/build_modules/msvc.lua b/xmake/rules/c++/modules/build_modules/msvc.lua index 15be07a41..a463f036a 100644 --- a/xmake/rules/c++/modules/build_modules/msvc.lua +++ b/xmake/rules/c++/modules/build_modules/msvc.lua @@ -82,7 +82,7 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) -- load moduledeps local moduledeps = module_parser.load(target, sourcebatch, opt) - print(moduledeps) + --print(moduledeps) -- compile module files to object files local rootjob = opt.rootjob diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index ad36226eb..9018f5e2d 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -21,15 +21,6 @@ -- define rule: c++.build.modules rule("c++.build.modules") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") - before_build(function (target, opt) - local sourcebatches = target:sourcebatches() - if sourcebatches then - local sourcebatch = sourcebatches["c++.build.modules"] - if sourcebatch then - import("build_modules.module_parser").generate(target, sourcebatch, opt) - end - end - end) before_build_files(function (target, batchjobs, sourcebatch, opt) -- we disable to build across targets in parallel, because the source files may depend on other target modules -- @note we cannot set it in on_load, because it will affect all c++ projects -- cgit v1.3.1 From 386f926b5c2651db23afdd59ecb8591382b3598f Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 15 Oct 2021 23:59:14 +0800 Subject: load moduledeps for gcc --- xmake/rules/c++/modules/build_modules/gcc.lua | 5 +++++ xmake/rules/c++/modules/build_modules/msvc.lua | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/xmake/rules/c++/modules/build_modules/gcc.lua b/xmake/rules/c++/modules/build_modules/gcc.lua index d5ffbc57b..1fb6b5a10 100644 --- a/xmake/rules/c++/modules/build_modules/gcc.lua +++ b/xmake/rules/c++/modules/build_modules/gcc.lua @@ -21,6 +21,7 @@ -- imports import("core.tool.compiler") import("private.action.build.object", {alias = "objectbuilder"}) +import("module_parser") -- build module files function build_with_batchjobs(target, batchjobs, sourcebatch, opt) @@ -43,6 +44,10 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) table.insert(sourcebatch.dependfiles, target:dependfile(objectfile)) end + -- TODO load moduledeps + --local moduledeps = module_parser.load(target, sourcebatch, opt) + --print(moduledeps) + -- compile module files to object files local rootjob = opt.rootjob for i = 1, #sourcebatch.sourcefiles do diff --git a/xmake/rules/c++/modules/build_modules/msvc.lua b/xmake/rules/c++/modules/build_modules/msvc.lua index a463f036a..e40975557 100644 --- a/xmake/rules/c++/modules/build_modules/msvc.lua +++ b/xmake/rules/c++/modules/build_modules/msvc.lua @@ -80,8 +80,8 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) table.insert(sourcebatch.dependfiles, dependfile) end - -- load moduledeps - local moduledeps = module_parser.load(target, sourcebatch, opt) + -- TODO load moduledeps + --local moduledeps = module_parser.load(target, sourcebatch, opt) --print(moduledeps) -- compile module files to object files -- cgit v1.3.1 From 934befffcc389d3bd9497e5de1d19407466a28c5 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 16 Oct 2021 00:57:59 +0800 Subject: build module batch jobs --- xmake/modules/private/async/jobpool.lua | 15 +++++++++++++ xmake/rules/c++/modules/build_modules/clang.lua | 24 +++++++++++++++++--- xmake/rules/c++/modules/build_modules/gcc.lua | 26 +++++++++++++++++----- .../c++/modules/build_modules/module_parser.lua | 18 +++++++++++++++ xmake/rules/c++/modules/build_modules/msvc.lua | 26 +++++++++++++++++----- 5 files changed, 94 insertions(+), 15 deletions(-) diff --git a/xmake/modules/private/async/jobpool.lua b/xmake/modules/private/async/jobpool.lua index 299700534..f7eef0c1b 100644 --- a/xmake/modules/private/async/jobpool.lua +++ b/xmake/modules/private/async/jobpool.lua @@ -35,8 +35,23 @@ function jobpool:rootjob() return self._rootjob end +-- new run job +-- +-- e.g. +-- local job = jobpool:newjob("xxx", function (index, total) end) +-- jobpool:add(job, rootjob1) +-- jobpool:add(job, rootjob2) +-- jobpool:add(job, rootjob3) +-- +function jobpool:newjob(name, run) + return {name = name, run = run} +end + -- add run job to the given job node -- +-- e.g. +-- local job = jobpool:addjob("xxx", function (index, total) end, {rootjob = rootjob}) +-- -- @param name the job name -- @param run the run command/script -- @param opt the options (rootjob) diff --git a/xmake/rules/c++/modules/build_modules/clang.lua b/xmake/rules/c++/modules/build_modules/clang.lua index 7037c0767..06b5aa1db 100644 --- a/xmake/rules/c++/modules/build_modules/clang.lua +++ b/xmake/rules/c++/modules/build_modules/clang.lua @@ -21,6 +21,7 @@ -- imports import("core.tool.compiler") import("private.action.build.object", {alias = "objectbuilder"}) +import("module_parser") -- build module files function build_with_batchjobs(target, batchjobs, sourcebatch, opt) @@ -51,13 +52,19 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) table.insert(modulefiles, modulefile) end + -- load moduledeps + local moduledeps = module_parser.load(target, sourcebatch, opt) + + -- build moduledeps + local moduledeps_files = module_parser.build(moduledeps) + -- compile module files to object files - local rootjob = opt.rootjob local count = 0 local sourcefiles_total = #sourcebatch.sourcefiles for i = 1, sourcefiles_total do local sourcefile = sourcebatch.sourcefiles[i] - batchjobs:addjob(sourcefile, function (index, total) + local moduledep = assert(moduledeps_files[sourcefile], "moduledep(%s) not found!", sourcefile) + moduledep.job = batchjobs:newjob(sourcefile, function (index, total) -- compile module files to *.pcm local opt2 = table.join(opt, {configs = {force = {cxxflags = {modulesflag, @@ -88,8 +95,19 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) end end - end, {rootjob = rootjob}) + end) end + -- build batchjobs + local rootjob = opt.rootjob + for _, moduledep in pairs(moduledeps) do + if moduledep.parents then + for _, parent in ipairs(moduledep.parents) do + batchjobs:add(moduledep.job, parent.job) + end + else + batchjobs:add(moduledep.job, rootjob) + end + end end diff --git a/xmake/rules/c++/modules/build_modules/gcc.lua b/xmake/rules/c++/modules/build_modules/gcc.lua index 1fb6b5a10..1264f29c2 100644 --- a/xmake/rules/c++/modules/build_modules/gcc.lua +++ b/xmake/rules/c++/modules/build_modules/gcc.lua @@ -44,25 +44,39 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) table.insert(sourcebatch.dependfiles, target:dependfile(objectfile)) end - -- TODO load moduledeps - --local moduledeps = module_parser.load(target, sourcebatch, opt) - --print(moduledeps) + -- load moduledeps + local moduledeps = module_parser.load(target, sourcebatch, opt) + + -- build moduledeps + local moduledeps_files = module_parser.build(moduledeps) -- compile module files to object files - local rootjob = opt.rootjob for i = 1, #sourcebatch.sourcefiles do local sourcefile = sourcebatch.sourcefiles[i] - batchjobs:addjob(sourcefile, function (index, total) + local moduledep = assert(moduledeps_files[sourcefile], "moduledep(%s) not found!", sourcefile) + moduledep.job = batchjobs:newjob(sourcefile, function (index, total) local opt2 = table.join(opt, {configs = {force = {cxxflags = {"-x c++"}}}}) opt2.progress = (index * 100) / total opt2.objectfile = sourcebatch.objectfiles[i] opt2.dependfile = sourcebatch.dependfiles[i] opt2.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile) objectbuilder.build_object(target, sourcefile, opt2) - end, {rootjob = rootjob}) + end) end -- add module flags target:add("cxxflags", modulesflag) + + -- build batchjobs + local rootjob = opt.rootjob + for _, moduledep in pairs(moduledeps) do + if moduledep.parents then + for _, parent in ipairs(moduledep.parents) do + batchjobs:add(moduledep.job, parent.job) + end + else + batchjobs:add(moduledep.job, rootjob) + end + end end diff --git a/xmake/rules/c++/modules/build_modules/module_parser.lua b/xmake/rules/c++/modules/build_modules/module_parser.lua index 5ac4e42e9..17e0f4d24 100644 --- a/xmake/rules/c++/modules/build_modules/module_parser.lua +++ b/xmake/rules/c++/modules/build_modules/module_parser.lua @@ -94,3 +94,21 @@ function load(target, sourcebatch, opt) end return moduledeps end + +-- build module deps +function build(moduledeps) + local moduledeps_files = {} + for _, moduledep in pairs(moduledeps) do + if moduledep.deps then + for _, depname in ipairs(moduledep.deps) do + local dep = moduledeps[depname] + if dep then + dep.parents = dep.parents or {} + table.insert(dep.parents, moduledep) + end + end + end + moduledeps_files[moduledep.file] = moduledep + end + return moduledeps_files +end diff --git a/xmake/rules/c++/modules/build_modules/msvc.lua b/xmake/rules/c++/modules/build_modules/msvc.lua index e40975557..831b5cd88 100644 --- a/xmake/rules/c++/modules/build_modules/msvc.lua +++ b/xmake/rules/c++/modules/build_modules/msvc.lua @@ -80,17 +80,19 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) table.insert(sourcebatch.dependfiles, dependfile) end - -- TODO load moduledeps - --local moduledeps = module_parser.load(target, sourcebatch, opt) - --print(moduledeps) + -- load moduledeps + local moduledeps = module_parser.load(target, sourcebatch, opt) + + -- build moduledeps + local moduledeps_files = module_parser.build(moduledeps) -- compile module files to object files - local rootjob = opt.rootjob local count = 0 local sourcefiles_total = #sourcebatch.sourcefiles for i = 1, sourcefiles_total do local sourcefile = sourcebatch.sourcefiles[i] - batchjobs:addjob(sourcefile, function (index, total) + local moduledep = assert(moduledeps_files[sourcefile], "moduledep(%s) not found!", sourcefile) + moduledep.job = batchjobs:newjob(sourcefile, function (index, total) local opt2 = table.join(opt, {configs = {force = {cxxflags = {interfaceflag, outputflag .. " " .. os.args(modulefiles[i]), "/TP"}}}}) opt2.progress = (index * 100) / total @@ -106,7 +108,7 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) target:add("cxxflags", referenceflag .. " " .. os.args(modulefile)) end end - end, {rootjob = rootjob}) + end) end -- add module flags @@ -114,5 +116,17 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) if cachedir then target:add("cxxflags", "/ifcSearchDir " .. os.args(cachedir)) end + + -- build batchjobs + local rootjob = opt.rootjob + for _, moduledep in pairs(moduledeps) do + if moduledep.parents then + for _, parent in ipairs(moduledep.parents) do + batchjobs:add(moduledep.job, parent.job) + end + else + batchjobs:add(moduledep.job, rootjob) + end + end end -- cgit v1.3.1 From 9d707e01104fe21569b9354ff1a8191f27d5b43a Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 16 Oct 2021 00:59:31 +0800 Subject: fix module partition --- xmake/rules/c++/modules/build_modules/module_parser.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xmake/rules/c++/modules/build_modules/module_parser.lua b/xmake/rules/c++/modules/build_modules/module_parser.lua index 17e0f4d24..b97b7e1d0 100644 --- a/xmake/rules/c++/modules/build_modules/module_parser.lua +++ b/xmake/rules/c++/modules/build_modules/module_parser.lua @@ -52,6 +52,10 @@ function _generate_moduledeps(target, sourcefile, opt) end local module_depname = line:match("import%s+(.+)%s*;") if module_depname then + -- partition? import :xxx; + if module_depname:startswith(":") then + module_depname = module_name .. module_depname + end module_deps = module_deps or {} table.insert(module_deps, module_depname) end -- cgit v1.3.1 From fceae198e53036fce3dd179cadabafe991c6ea0b Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 16 Oct 2021 00:22:16 +0800 Subject: improve gcc/parse_deps --- xmake/modules/private/tools/gcc/parse_deps.lua | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/xmake/modules/private/tools/gcc/parse_deps.lua b/xmake/modules/private/tools/gcc/parse_deps.lua index cb06d091c..606e6c840 100644 --- a/xmake/modules/private/tools/gcc/parse_deps.lua +++ b/xmake/modules/private/tools/gcc/parse_deps.lua @@ -54,9 +54,18 @@ end -- src/tbox/libc/string/../../prefix/../config.h \ -- build/iphoneos/x86_64/release/tbox.config.h \ -- +-- with c++ modules: +-- build/.objs/dependence/linux/x86_64/release/src/foo.mpp.o: src/foo.mpp\ +-- build/.objs/dependence/linux/x86_64/release/src/foo.mpp.o gcm.cache/foo.gcm: bar.c++m cat.c++m\ +-- foo.c++m: gcm.cache/foo.gcm\ +-- .PHONY: foo.c++m\ +-- gcm.cache/foo.gcm:| build/.objs/dependence/linux/x86_64/release/src/foo.mpp.o\ +-- CXX_IMPORTS += bar.c++m cat.c++m\ +-- function main(depsdata) -- we assume there is only one valid line + local block = 0 local results = hashset.new() local projectdir = os.projectdir() local line = depsdata:rtrim() -- maybe there will be an empty newline at the end. so we trim it first @@ -68,8 +77,15 @@ function main(depsdata) if is_host("windows") and includefile:match("^%w\\:") then includefile = includefile:replace("\\:", ":", plain) end - if not includefile:endswith(":") then -- ignore "xxx.o:" prefix + if includefile:endswith(":") then -- ignore "xxx.o:" prefix + block = block + 1 + if block > 1 then + -- skip other `xxx.o:` block + break + end + else includefile = includefile:replace(space_placeholder, ' ', plain) + includefile = includefile:split("\n")[1] if #includefile > 0 then includefile = _normailize_dep(includefile, projectdir) if includefile then -- cgit v1.3.1 From bbe1a5c2f7418d085304d1dcd0462cf4b2193497 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 16 Oct 2021 00:30:11 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ xmake/modules/private/tools/gcc/parse_deps.lua | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3ea6812a..07a55c723 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ ### Changes * [#1528](https://github.com/xmake-io/xmake/issues/1528): Check c++17/20 features +* [#1729](https://github.com/xmake-io/xmake/issues/1729): Improve C++20 modules for clang/gcc/msvc ## v2.5.8 @@ -1111,6 +1112,7 @@ ### 改进 * [#1528](https://github.com/xmake-io/xmake/issues/1528): 检测 c++17/20 特性 +* [#1729](https://github.com/xmake-io/xmake/issues/1729): 改进 C++20 modules 对 clang/gcc/msvc 的支持 ## v2.5.8 diff --git a/xmake/modules/private/tools/gcc/parse_deps.lua b/xmake/modules/private/tools/gcc/parse_deps.lua index 606e6c840..3b682753c 100644 --- a/xmake/modules/private/tools/gcc/parse_deps.lua +++ b/xmake/modules/private/tools/gcc/parse_deps.lua @@ -85,7 +85,7 @@ function main(depsdata) end else includefile = includefile:replace(space_placeholder, ' ', plain) - includefile = includefile:split("\n")[1] + includefile = includefile:split("\n", {plain = true})[1] if #includefile > 0 then includefile = _normailize_dep(includefile, projectdir) if includefile then -- cgit v1.3.1 From 194e8abb709553c79d5ee34d9bd4a714aa3004d7 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 16 Oct 2021 23:18:53 +0800 Subject: add headeronly kind for target --- tests/projects/c/headeronly/src/foo.h | 9 +++ tests/projects/c/headeronly/test.lua | 6 ++ tests/projects/c/headeronly/xmake.lua | 9 +++ xmake/actions/build/build.lua | 5 +- xmake/actions/install/main.lua | 2 +- xmake/actions/package/local/main.lua | 68 +++++++++++++++++++++- xmake/actions/package/oldpkg/main.lua | 25 ++++---- xmake/actions/package/remote/main.lua | 9 ++- xmake/actions/run/main.lua | 2 +- xmake/core/project/target.lua | 18 ++++-- .../target/action/install/cmake_importfiles.lua | 8 ++- .../action/install/pkgconfig_importfiles.lua | 10 +++- xmake/modules/target/action/install/unix.lua | 4 +- xmake/modules/target/action/install/windows.lua | 4 +- xmake/modules/target/action/uninstall/unix.lua | 4 +- xmake/modules/target/action/uninstall/windows.lua | 4 +- .../cmake_importfiles/xxxTargets-headeronly.cmake | 9 +++ 17 files changed, 157 insertions(+), 39 deletions(-) create mode 100644 tests/projects/c/headeronly/src/foo.h create mode 100644 tests/projects/c/headeronly/test.lua create mode 100644 tests/projects/c/headeronly/xmake.lua create mode 100644 xmake/scripts/cmake_importfiles/xxxTargets-headeronly.cmake diff --git a/tests/projects/c/headeronly/src/foo.h b/tests/projects/c/headeronly/src/foo.h new file mode 100644 index 000000000..915f44b87 --- /dev/null +++ b/tests/projects/c/headeronly/src/foo.h @@ -0,0 +1,9 @@ +/*! calculate add(a, b) + * + * @param a the first argument + * @param b the second argument + * + * @return the result + */ +int add(int a, int b); + diff --git a/tests/projects/c/headeronly/test.lua b/tests/projects/c/headeronly/test.lua new file mode 100644 index 000000000..b76241be2 --- /dev/null +++ b/tests/projects/c/headeronly/test.lua @@ -0,0 +1,6 @@ +-- main entry +function main(t) + + -- build project + t:build() +end diff --git a/tests/projects/c/headeronly/xmake.lua b/tests/projects/c/headeronly/xmake.lua new file mode 100644 index 000000000..d43bdceda --- /dev/null +++ b/tests/projects/c/headeronly/xmake.lua @@ -0,0 +1,9 @@ +add_rules("mode.release", "mode.debug") + +target("foo") + set_kind("headeronly") + add_headerfiles("src/foo.h") + add_rules("utils.install.cmake_importfiles") + add_rules("utils.install.pkgconfig_importfiles") + + diff --git a/xmake/actions/build/build.lua b/xmake/actions/build/build.lua index 267a802d3..c3817fb0a 100644 --- a/xmake/actions/build/build.lua +++ b/xmake/actions/build/build.lua @@ -28,8 +28,7 @@ import("core.base.hashset") -- clean target for rebuilding function _clean_target(target) - local targetkind = target:kind() - if targetkind ~= "phony" and targetkind ~= "object" then + if target:targetfile() then os.tryrm(target:symbolfile()) os.tryrm(target:targetfile()) end @@ -54,7 +53,7 @@ function _add_batchjobs_builtin(batchjobs, rootjob, target) end -- uses the builtin target script - if not job and not target:is_phony() then + if not job and (target:is_static() or target:is_binary() or target:is_shared() or target:is_object()) then job, job_leaf = import("kinds." .. target:kind(), {anonymous = true})(batchjobs, rootjob, target) end job = job or rootjob diff --git a/xmake/actions/install/main.lua b/xmake/actions/install/main.lua index febae713b..82534ffe0 100644 --- a/xmake/actions/install/main.lua +++ b/xmake/actions/install/main.lua @@ -46,7 +46,7 @@ function _check_targets(targetname) -- filter and check targets with builtin-install script local targetnames = {} for _, target in ipairs(targets) do - if not target:is_phony() and target:is_enabled() and not target:script("install") then + if target:targetfile() and target:is_enabled() and not target:script("install") then local targetfile = target:targetfile() if targetfile and not os.isfile(targetfile) then table.insert(targetnames, target:name()) diff --git a/xmake/actions/package/local/main.lua b/xmake/actions/package/local/main.lua index 72cfac3ac..dd7be7de0 100644 --- a/xmake/actions/package/local/main.lua +++ b/xmake/actions/package/local/main.lua @@ -174,14 +174,76 @@ function _package_library(target) print("package(%s): %s generated", packagename, packagedir) end +-- package headeronly library +function _package_headeronly(target) + + -- get the output directory + local outputdir = option.get("outputdir") or config.buildir() + local packagename = target:name():lower() + if #packagename > 1 and bit.band(packagename:byte(2), 0xc0) == 0x80 then + wprint("package(%s): cannot generate package, becauese it contains unicode characters!", packagename) + return + end + local packagedir = path.join(outputdir, "packages", packagename:sub(1, 1), packagename) + local headerdir = path.join(packagedir, target:plat(), target:arch(), config.mode(), "include") + + -- copy headers + local srcheaders, dstheaders = target:headerfiles(headerdir) + if srcheaders and dstheaders then + local i = 1 + for _, srcheader in ipairs(srcheaders) do + local dstheader = dstheaders[i] + if dstheader then + os.vcp(srcheader, dstheader) + end + i = i + 1 + end + end + + -- generate xmake.lua + local file = io.open(path.join(packagedir, "xmake.lua"), "w") + if file then + local deps = _get_linkdeps(target) + file:print("package(\"%s\")", packagename) + local homepage = option.get("homepage") + if homepage then + file:print(" set_homepage(\"%s\")", homepage) + end + local description = option.get("description") or ("The " .. packagename .. " package") + file:print(" set_description(\"%s\")", description) + if target:license() then + file:print(" set_license(\"%s\")", target:license()) + end + if #deps > 0 then + file:print(" add_deps(\"%s\")", table.concat(deps, "\", \"")) + end + file:print("") + file:print([[ + on_load(function (package) + package:set("installdir", path.join(os.scriptdir(), package:plat(), package:arch(), package:mode())) + end) + + on_fetch(function (package) + local result = {} + result.includedirs = package:installdir("include") + return result + end)]]) + file:close() + end + + -- show tips + print("package(%s): %s generated", packagename, packagedir) +end + -- do package target function _do_package_target(target) if not target:is_phony() then local scripts = { - binary = _package_binary - , static = _package_library - , shared = _package_library + binary = _package_binary + , static = _package_library + , shared = _package_library + , headeronly = _package_headeronly } local kind = target:kind() assert(scripts[kind], "this target(%s) with kind(%s) can not be packaged!", target:name(), kind) diff --git a/xmake/actions/package/oldpkg/main.lua b/xmake/actions/package/oldpkg/main.lua index d47d8d474..4dea87c4b 100644 --- a/xmake/actions/package/oldpkg/main.lua +++ b/xmake/actions/package/oldpkg/main.lua @@ -35,12 +35,14 @@ function _package_library(target) local targetname = target:name() -- copy the library file to the output directory - os.vcp(target:targetfile(), format("%s/%s.pkg/$(plat)/$(arch)/lib/$(mode)/%s", outputdir, targetname, path.filename(target:targetfile()))) + if not target:is_headeronly() then + os.vcp(target:targetfile(), format("%s/%s.pkg/$(plat)/$(arch)/lib/$(mode)/%s", outputdir, targetname, path.filename(target:targetfile()))) - -- copy the symbol file to the output directory - local symbolfile = target:symbolfile() - if os.isfile(symbolfile) then - os.vcp(symbolfile, format("%s/%s.pkg/$(plat)/$(arch)/lib/$(mode)/%s", outputdir, targetname, path.filename(symbolfile))) + -- copy the symbol file to the output directory + local symbolfile = target:symbolfile() + if os.isfile(symbolfile) then + os.vcp(symbolfile, format("%s/%s.pkg/$(plat)/$(arch)/lib/$(mode)/%s", outputdir, targetname, path.filename(symbolfile))) + end end -- copy *.lib for shared/windows (*.dll) target @@ -78,8 +80,10 @@ function _package_library(target) file:print("option(\"%s\")", targetname) file:print(" set_showmenu(true)") file:print(" set_category(\"package\")") - file:print(" add_links(\"%s\")", target:basename()) - file:write(" add_linkdirs(\"$(plat)/$(arch)/lib/$(mode)\")\n") + if not target:is_headeronly() then + file:print(" add_links(\"%s\")", target:basename()) + file:write(" add_linkdirs(\"$(plat)/$(arch)/lib/$(mode)\")\n") + end file:write(" add_includedirs(\"$(plat)/$(arch)/include\")\n") local languages = target:get("languages") if languages then @@ -94,9 +98,10 @@ function _do_package_target(target) if not target:is_phony() then local scripts = { - binary = function (target) end - , static = _package_library - , shared = _package_library + binary = function (target) end + , static = _package_library + , shared = _package_library + , headeronly = _package_library } local kind = target:kind() assert(scripts[kind], "this target(%s) with kind(%s) can not be packaged!", target:name(), kind) diff --git a/xmake/actions/package/remote/main.lua b/xmake/actions/package/remote/main.lua index f1aacf057..9db86e8d5 100644 --- a/xmake/actions/package/remote/main.lua +++ b/xmake/actions/package/remote/main.lua @@ -57,6 +57,8 @@ function _package_remote(target) file:print("package(\"%s\")", packagename) if target:is_binary() then file:print(" set_kind(\"binary\")") + elseif target:is_headeronly() then + file:print(" set_kind(\"library\", {headeronly = true})") end local homepage = option.get("homepage") if homepage then @@ -102,9 +104,10 @@ function _package_target(target) if not target:is_phony() then local scripts = { - binary = _package_remote - , static = _package_remote - , shared = _package_remote + binary = _package_remote + , static = _package_remote + , shared = _package_remote + , headeronly = _package_remote } local kind = target:kind() assert(scripts[kind], "this target(%s) with kind(%s) can not be packaged!", target:name(), kind) diff --git a/xmake/actions/run/main.lua b/xmake/actions/run/main.lua index f79a5d6b2..3b51c3c81 100644 --- a/xmake/actions/run/main.lua +++ b/xmake/actions/run/main.lua @@ -162,7 +162,7 @@ function _check_targets(targetname) -- filter and check targets with builtin-run script local targetnames = {} for _, target in ipairs(targets) do - if not target:is_phony() and target:is_enabled() and not target:script("run") then + if target:targetfile() and target:is_enabled() and not target:script("run") then local targetfile = target:targetfile() if targetfile and not os.isfile(targetfile) then table.insert(targetnames, target:name()) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 53d17dadc..d6bba579a 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -676,9 +676,19 @@ function _instance:is_static() return self:kind() == "static" end +-- is object files target? +function _instance:is_object() + return self:kind() == "object" +end + +-- is headeronly target? +function _instance:is_headeronly() + return self:kind() == "headeronly" +end + -- is library target? function _instance:is_library() - return self:is_static() or self:is_shared() + return self:is_static() or self:is_shared() or self:is_headeronly() end -- is default target? @@ -1011,13 +1021,13 @@ end -- get the target file name function _instance:filename() - -- only compile objects? no target file - local targetkind = self:kind() - if targetkind == "object" then + -- no target file? + if self:is_object() or self:is_phony() or self:is_headeronly() then return end -- make the target file name and attempt to use the format of linker first + local targetkind = self:targetkind() local filename = self:get("filename") if not filename then local prefixname = self:get("prefixname") diff --git a/xmake/modules/target/action/install/cmake_importfiles.lua b/xmake/modules/target/action/install/cmake_importfiles.lua index e4e5d118e..ea53ab519 100644 --- a/xmake/modules/target/action/install/cmake_importfiles.lua +++ b/xmake/modules/target/action/install/cmake_importfiles.lua @@ -40,7 +40,7 @@ end function _get_builtinvars(target, installdir) return {TARGETNAME = target:name(), PROJECTNAME = project.name() or target:name(), - TARGETFILENAME = _get_libfile(target, installdir), + TARGETFILENAME = target:targetfile() and _get_libfile(target, installdir), TARGETKIND = target:is_shared() and "SHARED" or "STATIC", PACKAGE_VERSION = target:get("version") or "1.0.0", TARGET_PTRBYTES = target:is_arch("x86", "i386") and "4" or "8"} @@ -85,7 +85,7 @@ function _append_cmake_configfile(target, installdir, filename, opt) local builtinvars = _get_builtinvars(target, installdir) -- generate the file if not exist / file is outdated - if not os.isfile(importfile_dst) or os.mtime(importfile_dst) < os.mtime(target:targetfile()) then + if target:is_headeronly() or not os.isfile(importfile_dst) or os.mtime(importfile_dst) < os.mtime(target:targetfile()) then _install_cmake_configfile(target, installdir, filename, opt) end @@ -151,7 +151,9 @@ function main(target, opt) _append_cmake_configfile(target, installdir, "xxxConfig.cmake", opt) _install_cmake_configfile(target, installdir, "xxxConfigVersion.cmake", opt) _install_cmake_targetfile(target, installdir, "xxxTargets.cmake", opt) - if is_mode("debug") then + if target:is_headeronly() then + _install_cmake_targetfile(target, installdir, "xxxTargets-headeronly.cmake", opt) + elseif is_mode("debug") then _install_cmake_targetfile(target, installdir, "xxxTargets-debug.cmake", opt) else _install_cmake_targetfile(target, installdir, "xxxTargets-release.cmake", opt) diff --git a/xmake/modules/target/action/install/pkgconfig_importfiles.lua b/xmake/modules/target/action/install/pkgconfig_importfiles.lua index 1187bb5e6..0cad0d267 100644 --- a/xmake/modules/target/action/install/pkgconfig_importfiles.lua +++ b/xmake/modules/target/action/install/pkgconfig_importfiles.lua @@ -66,7 +66,9 @@ function main(target, opt) if file then file:print("prefix=%s", installdir) file:print("exec_prefix=${prefix}") - file:print("libdir=${exec_prefix}/lib") + if not target:is_headeronly() then + file:print("libdir=${exec_prefix}/lib") + end file:print("includedir=${prefix}/include") file:print("") file:print("Name: %s", target:name()) @@ -75,8 +77,10 @@ function main(target, opt) if version then file:print("Version: %s", version) end - file:print("Libs: %s", libs) - file:print("Libs.private: ") + if not target:is_headeronly() then + file:print("Libs: %s", libs) + file:print("Libs.private: ") + end file:print("Cflags: %s", cflags) file:close() end diff --git a/xmake/modules/target/action/install/unix.lua b/xmake/modules/target/action/install/unix.lua index 165d8650e..af641e5bc 100644 --- a/xmake/modules/target/action/install/unix.lua +++ b/xmake/modules/target/action/install/unix.lua @@ -127,7 +127,7 @@ function install_static(target, opt) _install_headers(target, opt) end --- install phony -function install_phony(target, opt) +-- install headeronly library +function install_headeronly(target, opt) _install_headers(target, opt) end diff --git a/xmake/modules/target/action/install/windows.lua b/xmake/modules/target/action/install/windows.lua index 448415fa6..0ea1e22b6 100644 --- a/xmake/modules/target/action/install/windows.lua +++ b/xmake/modules/target/action/install/windows.lua @@ -135,7 +135,7 @@ function install_static(target, opt) _install_headers(target, opt) end --- install phony -function install_phony(target, opt) +-- install headeronly +function install_headeronly(target, opt) _install_headers(target, opt) end diff --git a/xmake/modules/target/action/uninstall/unix.lua b/xmake/modules/target/action/uninstall/unix.lua index 614d59448..e11446dd4 100644 --- a/xmake/modules/target/action/uninstall/unix.lua +++ b/xmake/modules/target/action/uninstall/unix.lua @@ -96,7 +96,7 @@ function uninstall_static(target, opt) _uninstall_headers(target, opt) end --- uninstall phony -function uninstall_phony(target, opt) +-- uninstall headeronly library +function uninstall_headeronly(target, opt) _uninstall_headers(target, opt) end diff --git a/xmake/modules/target/action/uninstall/windows.lua b/xmake/modules/target/action/uninstall/windows.lua index cb9dcf16e..73c43cc0a 100644 --- a/xmake/modules/target/action/uninstall/windows.lua +++ b/xmake/modules/target/action/uninstall/windows.lua @@ -101,7 +101,7 @@ function uninstall_static(target, opt) _uninstall_headers(target, opt) end --- uninstall phony -function uninstall_phony(target, opt) +-- uninstall headeronly library +function uninstall_headeronly(target, opt) _uninstall_headers(target, opt) end diff --git a/xmake/scripts/cmake_importfiles/xxxTargets-headeronly.cmake b/xmake/scripts/cmake_importfiles/xxxTargets-headeronly.cmake new file mode 100644 index 000000000..c35a310a4 --- /dev/null +++ b/xmake/scripts/cmake_importfiles/xxxTargets-headeronly.cmake @@ -0,0 +1,9 @@ +#---------------------------------------------------------------- +# Generated CMake target import file for configuration "Headeronly". +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) -- cgit v1.3.1 From 6c0849152c205f92a3b5073a89e9aa6bbcbba707 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 16 Oct 2021 23:25:29 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07a55c723..73520a7cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * Support Lua 5.4 runtime * Add gcc-8, gcc-9, gcc-10, gcc-11 toolchains * [#1623](https://github.com/xmake-io/xmake/issues/1632): Support find_package from cmake +* [#1747](https://github.com/xmake-io/xmake/issues/1747): Add `set_kind("headeronly")` for target to install files for headeronly library ### Changes @@ -1108,6 +1109,7 @@ * 支持 Lua 5.4 运行时 * 添加 gcc-8, gcc-9, gcc-10, gcc-11 工具链 * [#1623](https://github.com/xmake-io/xmake/issues/1632): 支持 find_package 从 cmake 查找包 +* [#1747](https://github.com/xmake-io/xmake/issues/1747): 添加 `set_kind("headeronly")` 更好的处理 headeronly 库的安装 ### 改进 -- cgit v1.3.1 From 2c018854833aa388bb16580f7d61646e90ce4bda Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 16 Oct 2021 23:26:25 +0800 Subject: update changelog --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73520a7cc..09b60b8ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ ### Changes * [#1528](https://github.com/xmake-io/xmake/issues/1528): Check c++17/20 features -* [#1729](https://github.com/xmake-io/xmake/issues/1729): Improve C++20 modules for clang/gcc/msvc +* [#1729](https://github.com/xmake-io/xmake/issues/1729): Improve C++20 modules for clang/gcc/msvc, support inter-module dependency compilation and parallel optimization ## v2.5.8 @@ -1114,7 +1114,7 @@ ### 改进 * [#1528](https://github.com/xmake-io/xmake/issues/1528): 检测 c++17/20 特性 -* [#1729](https://github.com/xmake-io/xmake/issues/1729): 改进 C++20 modules 对 clang/gcc/msvc 的支持 +* [#1729](https://github.com/xmake-io/xmake/issues/1729): 改进 C++20 modules 对 clang/gcc/msvc 的支持,支持模块间依赖编译和并行优化 ## v2.5.8 -- cgit v1.3.1 From f91fc985a24094fd90a825f68c9ca63f7aa83ce0 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 17 Oct 2021 22:20:28 +0800 Subject: add unit_unit tests --- tests/projects/c/unit_build/src/bar/test4.c | 8 ++++++++ tests/projects/c/unit_build/src/bar/test5.c | 8 ++++++++ tests/projects/c/unit_build/src/foo/test1.c | 8 ++++++++ tests/projects/c/unit_build/src/foo/test2.c | 8 ++++++++ tests/projects/c/unit_build/src/header.h | 10 ++++++++++ tests/projects/c/unit_build/src/main.c | 7 +++++++ tests/projects/c/unit_build/src/test.cpp | 4 ++++ tests/projects/c/unit_build/src/test2.c | 8 ++++++++ tests/projects/c/unit_build/src/test6.c | 8 ++++++++ tests/projects/c/unit_build/src/test7.c | 8 ++++++++ tests/projects/c/unit_build/src/test8.c | 8 ++++++++ tests/projects/c/unit_build/test.lua | 6 ++++++ tests/projects/c/unit_build/xmake.lua | 8 ++++++++ xmake/rules/c++/unit_build/xmake.lua | 21 +++++++++++++++++++++ 14 files changed, 120 insertions(+) create mode 100644 tests/projects/c/unit_build/src/bar/test4.c create mode 100644 tests/projects/c/unit_build/src/bar/test5.c create mode 100644 tests/projects/c/unit_build/src/foo/test1.c create mode 100644 tests/projects/c/unit_build/src/foo/test2.c create mode 100644 tests/projects/c/unit_build/src/header.h create mode 100644 tests/projects/c/unit_build/src/main.c create mode 100644 tests/projects/c/unit_build/src/test.cpp create mode 100644 tests/projects/c/unit_build/src/test2.c create mode 100644 tests/projects/c/unit_build/src/test6.c create mode 100644 tests/projects/c/unit_build/src/test7.c create mode 100644 tests/projects/c/unit_build/src/test8.c create mode 100644 tests/projects/c/unit_build/test.lua create mode 100644 tests/projects/c/unit_build/xmake.lua create mode 100644 xmake/rules/c++/unit_build/xmake.lua diff --git a/tests/projects/c/unit_build/src/bar/test4.c b/tests/projects/c/unit_build/src/bar/test4.c new file mode 100644 index 000000000..a92803eb7 --- /dev/null +++ b/tests/projects/c/unit_build/src/bar/test4.c @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test4() +{ + return 0; +} diff --git a/tests/projects/c/unit_build/src/bar/test5.c b/tests/projects/c/unit_build/src/bar/test5.c new file mode 100644 index 000000000..2a3e7066c --- /dev/null +++ b/tests/projects/c/unit_build/src/bar/test5.c @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test5() +{ + return 0; +} diff --git a/tests/projects/c/unit_build/src/foo/test1.c b/tests/projects/c/unit_build/src/foo/test1.c new file mode 100644 index 000000000..e9d6c83d9 --- /dev/null +++ b/tests/projects/c/unit_build/src/foo/test1.c @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test() +{ + return 0; +} diff --git a/tests/projects/c/unit_build/src/foo/test2.c b/tests/projects/c/unit_build/src/foo/test2.c new file mode 100644 index 000000000..b4ce69b0f --- /dev/null +++ b/tests/projects/c/unit_build/src/foo/test2.c @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test3() +{ + return 0; +} diff --git a/tests/projects/c/unit_build/src/header.h b/tests/projects/c/unit_build/src/header.h new file mode 100644 index 000000000..29bfc5870 --- /dev/null +++ b/tests/projects/c/unit_build/src/header.h @@ -0,0 +1,10 @@ +// header.h +#ifndef HEADER_H +#define HEADER_H + +#include +#include +#include + +#endif + diff --git a/tests/projects/c/unit_build/src/main.c b/tests/projects/c/unit_build/src/main.c new file mode 100644 index 000000000..f0408cdf8 --- /dev/null +++ b/tests/projects/c/unit_build/src/main.c @@ -0,0 +1,7 @@ +#include "header.h" + +int main(int argc, char** argv) +{ + printf("hello xmake!\n"); + return 0; +} diff --git a/tests/projects/c/unit_build/src/test.cpp b/tests/projects/c/unit_build/src/test.cpp new file mode 100644 index 000000000..1cedddad9 --- /dev/null +++ b/tests/projects/c/unit_build/src/test.cpp @@ -0,0 +1,4 @@ +int test_cpp() +{ + return 0; +} diff --git a/tests/projects/c/unit_build/src/test2.c b/tests/projects/c/unit_build/src/test2.c new file mode 100644 index 000000000..596359cd2 --- /dev/null +++ b/tests/projects/c/unit_build/src/test2.c @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test2() +{ + return 0; +} diff --git a/tests/projects/c/unit_build/src/test6.c b/tests/projects/c/unit_build/src/test6.c new file mode 100644 index 000000000..efbd7c6c1 --- /dev/null +++ b/tests/projects/c/unit_build/src/test6.c @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test6() +{ + return 0; +} diff --git a/tests/projects/c/unit_build/src/test7.c b/tests/projects/c/unit_build/src/test7.c new file mode 100644 index 000000000..24aeff619 --- /dev/null +++ b/tests/projects/c/unit_build/src/test7.c @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test7() +{ + return 0; +} diff --git a/tests/projects/c/unit_build/src/test8.c b/tests/projects/c/unit_build/src/test8.c new file mode 100644 index 000000000..6ad5680a6 --- /dev/null +++ b/tests/projects/c/unit_build/src/test8.c @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test8() +{ + return 0; +} diff --git a/tests/projects/c/unit_build/test.lua b/tests/projects/c/unit_build/test.lua new file mode 100644 index 000000000..b76241be2 --- /dev/null +++ b/tests/projects/c/unit_build/test.lua @@ -0,0 +1,6 @@ +-- main entry +function main(t) + + -- build project + t:build() +end diff --git a/tests/projects/c/unit_build/xmake.lua b/tests/projects/c/unit_build/xmake.lua new file mode 100644 index 000000000..1df67c0ec --- /dev/null +++ b/tests/projects/c/unit_build/xmake.lua @@ -0,0 +1,8 @@ +target("test") + set_kind("binary") + add_includedirs("src") + add_rules("c++.unit_build", {batchsize = 2}) + add_files("src/*.c", "src/*.cpp") + add_files("src/foo/*.c", {unit_group = "foo"}) + add_files("src/bar/*.c", {unit_group = "bar"}) + diff --git a/xmake/rules/c++/unit_build/xmake.lua b/xmake/rules/c++/unit_build/xmake.lua new file mode 100644 index 000000000..c6d0ea0bd --- /dev/null +++ b/xmake/rules/c++/unit_build/xmake.lua @@ -0,0 +1,21 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +rule("c++.unit_build") -- cgit v1.3.1 From 9dbe8c62ebbfb7fe0fb3335790af184b2b7860a1 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 17 Oct 2021 23:56:16 +0800 Subject: add unit_build rule --- xmake/core/project/target.lua | 4 -- xmake/rules/c++/unit_build/unit_build.lua | 108 ++++++++++++++++++++++++++++++ xmake/rules/c++/unit_build/xmake.lua | 24 +++++++ 3 files changed, 132 insertions(+), 4 deletions(-) create mode 100644 xmake/rules/c++/unit_build/unit_build.lua diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index d6bba579a..08ab720c0 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -1688,11 +1688,7 @@ function _instance:sourcebatches() end end end - - -- cache it self._SOURCEBATCHES = sourcebatches - - -- ok? return sourcebatches, modified end diff --git a/xmake/rules/c++/unit_build/unit_build.lua b/xmake/rules/c++/unit_build/unit_build.lua new file mode 100644 index 000000000..030639f1a --- /dev/null +++ b/xmake/rules/c++/unit_build/unit_build.lua @@ -0,0 +1,108 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file unit_build.lua +-- + +-- imports +import("core.project.depend") + +function _merge_unitfile(target, sourcefile_unit, sourcefiles, opt) + local dependfile = target:dependfile(sourcefile_unit) + depend.on_changed(function () + + -- trace + vprint("generating.unitfile %s", sourcefile_unit) + + -- do merge + local unitfile = io.open(sourcefile_unit, "w") + for _, sourcefile in ipairs(sourcefiles) do + sourcefile = path.absolute(sourcefile) + sourcefile_unit = path.absolute(sourcefile_unit) + sourcefile = path.relative(sourcefile, path.directory(sourcefile_unit)) + unitfile:print("#include \"%s\"", sourcefile) + end + unitfile:close() + + end, {dependfile = dependfile, files = sourcefiles}) +end + +function generate_unitfiles(target, sourcebatch, opt) + local unitbatch = target:data("unit_build.unitbatch." .. sourcebatch.rulename) + if unitbatch then + for _, sourcefile_unit in ipairs(sourcebatch.sourcefiles) do + local sourceinfo = unitbatch[sourcefile_unit] + if sourceinfo then + local sourcefiles = sourceinfo.sourcefiles + if sourcefiles then + _merge_unitfile(target, sourcefile_unit, sourcefiles, opt) + end + end + end + end +end + +function main(target, sourcebatch) + + -- get unit batch sources + local extraconf = target:extraconf("rules", "c++.unit_build") + local batchsize = extraconf.batchsize + local id = 1 + local count = 0 + local unitbatch = {} + local sourcedir = path.join(target:autogendir({root = true}), "unit_build") + for idx, sourcefile in pairs(sourcebatch.sourcefiles) do + local sourcefile_unit + local objectfile = sourcebatch.objectfiles[idx] + local dependfile = sourcebatch.dependfiles[idx] + local fileconfig = target:fileconfig(sourcefile) + if fileconfig and fileconfig.unit_group then + sourcefile_unit = path.join(sourcedir, "unit_" .. fileconfig.unit_group .. path.extension(sourcefile)) + else + if batchsize and count > batchsize then + id = id + 1 + end + sourcefile_unit = path.join(sourcedir, "unit_" .. hash.uuid(tostring(id)):split("-", {plain = true})[1] .. path.extension(sourcefile)) + count = count + 1 + end + local sourceinfo = unitbatch[sourcefile_unit] + if not sourceinfo then + sourceinfo = {} + sourceinfo.objectfile = target:objectfile(sourcefile_unit) + sourceinfo.dependfile = target:dependfile(sourceinfo.objectfile) + unitbatch[sourcefile_unit] = sourceinfo + end + sourceinfo.sourcefiles = sourceinfo.sourcefiles or {} + table.insert(sourceinfo.sourcefiles, sourcefile) + end + + -- use unit batch + local sourcefiles = {} + local objectfiles = {} + local dependfiles = {} + for sourcefile_unit, sourceinfo in pairs(unitbatch) do + table.insert(sourcefiles, sourcefile_unit) + table.insert(objectfiles, sourceinfo.objectfile) + table.insert(dependfiles, sourceinfo.dependfile) + end + sourcebatch.sourcefiles = sourcefiles + sourcebatch.objectfiles = objectfiles + sourcebatch.dependfiles = dependfiles + + -- save unit batch + target:data_set("unit_build.unitbatch." .. sourcebatch.rulename, unitbatch) +end diff --git a/xmake/rules/c++/unit_build/xmake.lua b/xmake/rules/c++/unit_build/xmake.lua index c6d0ea0bd..b0eb7b39a 100644 --- a/xmake/rules/c++/unit_build/xmake.lua +++ b/xmake/rules/c++/unit_build/xmake.lua @@ -19,3 +19,27 @@ -- rule("c++.unit_build") + after_load(function (target) + import("unit_build") + local sourcebatches = target:sourcebatches() + if sourcebatches then + for _, rulename in ipairs({"c.build", "c++.build"}) do + local sourcebatch = sourcebatches[rulename] + if sourcebatch then + unit_build(target, sourcebatch) + end + end + end + end) + before_build(function (target, opt) + import("unit_build") + local sourcebatches = target:sourcebatches() + if sourcebatches then + for _, rulename in ipairs({"c.build", "c++.build"}) do + local sourcebatch = sourcebatches[rulename] + if sourcebatch then + unit_build.generate_unitfiles(target, sourcebatch, opt) + end + end + end + end) -- cgit v1.3.1 From d31f3b2ef667e8c0b22cebbe9ab6f7579905d3ff Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 18 Oct 2021 21:01:29 +0800 Subject: improve unit_build --- xmake/rules/c++/unit_build/unit_build.lua | 39 +++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/xmake/rules/c++/unit_build/unit_build.lua b/xmake/rules/c++/unit_build/unit_build.lua index 030639f1a..7fd50b596 100644 --- a/xmake/rules/c++/unit_build/unit_build.lua +++ b/xmake/rules/c++/unit_build/unit_build.lua @@ -56,14 +56,25 @@ function generate_unitfiles(target, sourcebatch, opt) end end +-- use unit build +-- +-- e.g. +-- add_rules("c++.unit_build", {batchsize = 2}) +-- add_files("src/*.c", "src/*.cpp", {unit_ignored = true}) +-- add_files("src/foo/*.c", {unit_group = "foo"}) +-- add_files("src/bar/*.c", {unit_group = "bar"}) +-- function main(target, sourcebatch) -- get unit batch sources local extraconf = target:extraconf("rules", "c++.unit_build") - local batchsize = extraconf.batchsize + local batchsize = extraconf and extraconf.batchsize local id = 1 local count = 0 local unitbatch = {} + local sourcefiles = {} + local objectfiles = {} + local dependfiles = {} local sourcedir = path.join(target:autogendir({root = true}), "unit_build") for idx, sourcefile in pairs(sourcebatch.sourcefiles) do local sourcefile_unit @@ -72,6 +83,11 @@ function main(target, sourcebatch) local fileconfig = target:fileconfig(sourcefile) if fileconfig and fileconfig.unit_group then sourcefile_unit = path.join(sourcedir, "unit_" .. fileconfig.unit_group .. path.extension(sourcefile)) + elseif fileconfig and fileconfig.unit_ignored then + -- we do not add these files to unit file + table.insert(sourcefiles, sourcefile) + table.insert(objectfiles, objectfile) + table.insert(dependfiles, dependfile) else if batchsize and count > batchsize then id = id + 1 @@ -79,21 +95,20 @@ function main(target, sourcebatch) sourcefile_unit = path.join(sourcedir, "unit_" .. hash.uuid(tostring(id)):split("-", {plain = true})[1] .. path.extension(sourcefile)) count = count + 1 end - local sourceinfo = unitbatch[sourcefile_unit] - if not sourceinfo then - sourceinfo = {} - sourceinfo.objectfile = target:objectfile(sourcefile_unit) - sourceinfo.dependfile = target:dependfile(sourceinfo.objectfile) - unitbatch[sourcefile_unit] = sourceinfo + if sourcefile_unit then + local sourceinfo = unitbatch[sourcefile_unit] + if not sourceinfo then + sourceinfo = {} + sourceinfo.objectfile = target:objectfile(sourcefile_unit) + sourceinfo.dependfile = target:dependfile(sourceinfo.objectfile) + unitbatch[sourcefile_unit] = sourceinfo + end + sourceinfo.sourcefiles = sourceinfo.sourcefiles or {} + table.insert(sourceinfo.sourcefiles, sourcefile) end - sourceinfo.sourcefiles = sourceinfo.sourcefiles or {} - table.insert(sourceinfo.sourcefiles, sourcefile) end -- use unit batch - local sourcefiles = {} - local objectfiles = {} - local dependfiles = {} for sourcefile_unit, sourceinfo in pairs(unitbatch) do table.insert(sourcefiles, sourcefile_unit) table.insert(objectfiles, sourceinfo.objectfile) -- cgit v1.3.1 From 69ddff2a27199172659c9c823dabde8c4b004ae3 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 18 Oct 2021 21:01:43 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09b60b8ae..89d1a64aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * Add gcc-8, gcc-9, gcc-10, gcc-11 toolchains * [#1623](https://github.com/xmake-io/xmake/issues/1632): Support find_package from cmake * [#1747](https://github.com/xmake-io/xmake/issues/1747): Add `set_kind("headeronly")` for target to install files for headeronly library +* [#1019](https://github.com/xmake-io/xmake/issues/1019): Support Unity build ### Changes @@ -1110,6 +1111,7 @@ * 添加 gcc-8, gcc-9, gcc-10, gcc-11 工具链 * [#1623](https://github.com/xmake-io/xmake/issues/1632): 支持 find_package 从 cmake 查找包 * [#1747](https://github.com/xmake-io/xmake/issues/1747): 添加 `set_kind("headeronly")` 更好的处理 headeronly 库的安装 +* [#1019](https://github.com/xmake-io/xmake/issues/1019): 支持 Unity build ### 改进 -- cgit v1.3.1 From 4e3967d123432b2352b450ed892fcb1b8f3b37d2 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 18 Oct 2021 21:02:26 +0800 Subject: rename to unity build --- tests/projects/c/unit_build/src/bar/test4.c | 8 -- tests/projects/c/unit_build/src/bar/test5.c | 8 -- tests/projects/c/unit_build/src/foo/test1.c | 8 -- tests/projects/c/unit_build/src/foo/test2.c | 8 -- tests/projects/c/unit_build/src/header.h | 10 --- tests/projects/c/unit_build/src/main.c | 7 -- tests/projects/c/unit_build/src/test.cpp | 4 - tests/projects/c/unit_build/src/test2.c | 8 -- tests/projects/c/unit_build/src/test6.c | 8 -- tests/projects/c/unit_build/src/test7.c | 8 -- tests/projects/c/unit_build/src/test8.c | 8 -- tests/projects/c/unit_build/test.lua | 6 -- tests/projects/c/unit_build/xmake.lua | 8 -- tests/projects/c/unity_build/src/bar/test4.c | 8 ++ tests/projects/c/unity_build/src/bar/test5.c | 8 ++ tests/projects/c/unity_build/src/foo/test1.c | 8 ++ tests/projects/c/unity_build/src/foo/test2.c | 8 ++ tests/projects/c/unity_build/src/header.h | 10 +++ tests/projects/c/unity_build/src/main.c | 7 ++ tests/projects/c/unity_build/src/test.cpp | 4 + tests/projects/c/unity_build/src/test2.c | 8 ++ tests/projects/c/unity_build/src/test6.c | 8 ++ tests/projects/c/unity_build/src/test7.c | 8 ++ tests/projects/c/unity_build/src/test8.c | 8 ++ tests/projects/c/unity_build/test.lua | 6 ++ tests/projects/c/unity_build/xmake.lua | 8 ++ xmake/rules/c++/unit_build/unit_build.lua | 123 --------------------------- xmake/rules/c++/unit_build/xmake.lua | 45 ---------- xmake/rules/c++/unity_build/unity_build.lua | 123 +++++++++++++++++++++++++++ xmake/rules/c++/unity_build/xmake.lua | 45 ++++++++++ 30 files changed, 267 insertions(+), 267 deletions(-) delete mode 100644 tests/projects/c/unit_build/src/bar/test4.c delete mode 100644 tests/projects/c/unit_build/src/bar/test5.c delete mode 100644 tests/projects/c/unit_build/src/foo/test1.c delete mode 100644 tests/projects/c/unit_build/src/foo/test2.c delete mode 100644 tests/projects/c/unit_build/src/header.h delete mode 100644 tests/projects/c/unit_build/src/main.c delete mode 100644 tests/projects/c/unit_build/src/test.cpp delete mode 100644 tests/projects/c/unit_build/src/test2.c delete mode 100644 tests/projects/c/unit_build/src/test6.c delete mode 100644 tests/projects/c/unit_build/src/test7.c delete mode 100644 tests/projects/c/unit_build/src/test8.c delete mode 100644 tests/projects/c/unit_build/test.lua delete mode 100644 tests/projects/c/unit_build/xmake.lua create mode 100644 tests/projects/c/unity_build/src/bar/test4.c create mode 100644 tests/projects/c/unity_build/src/bar/test5.c create mode 100644 tests/projects/c/unity_build/src/foo/test1.c create mode 100644 tests/projects/c/unity_build/src/foo/test2.c create mode 100644 tests/projects/c/unity_build/src/header.h create mode 100644 tests/projects/c/unity_build/src/main.c create mode 100644 tests/projects/c/unity_build/src/test.cpp create mode 100644 tests/projects/c/unity_build/src/test2.c create mode 100644 tests/projects/c/unity_build/src/test6.c create mode 100644 tests/projects/c/unity_build/src/test7.c create mode 100644 tests/projects/c/unity_build/src/test8.c create mode 100644 tests/projects/c/unity_build/test.lua create mode 100644 tests/projects/c/unity_build/xmake.lua delete mode 100644 xmake/rules/c++/unit_build/unit_build.lua delete mode 100644 xmake/rules/c++/unit_build/xmake.lua create mode 100644 xmake/rules/c++/unity_build/unity_build.lua create mode 100644 xmake/rules/c++/unity_build/xmake.lua diff --git a/tests/projects/c/unit_build/src/bar/test4.c b/tests/projects/c/unit_build/src/bar/test4.c deleted file mode 100644 index a92803eb7..000000000 --- a/tests/projects/c/unit_build/src/bar/test4.c +++ /dev/null @@ -1,8 +0,0 @@ - -// main.cpp -#include "header.h" - -int test4() -{ - return 0; -} diff --git a/tests/projects/c/unit_build/src/bar/test5.c b/tests/projects/c/unit_build/src/bar/test5.c deleted file mode 100644 index 2a3e7066c..000000000 --- a/tests/projects/c/unit_build/src/bar/test5.c +++ /dev/null @@ -1,8 +0,0 @@ - -// main.cpp -#include "header.h" - -int test5() -{ - return 0; -} diff --git a/tests/projects/c/unit_build/src/foo/test1.c b/tests/projects/c/unit_build/src/foo/test1.c deleted file mode 100644 index e9d6c83d9..000000000 --- a/tests/projects/c/unit_build/src/foo/test1.c +++ /dev/null @@ -1,8 +0,0 @@ - -// main.cpp -#include "header.h" - -int test() -{ - return 0; -} diff --git a/tests/projects/c/unit_build/src/foo/test2.c b/tests/projects/c/unit_build/src/foo/test2.c deleted file mode 100644 index b4ce69b0f..000000000 --- a/tests/projects/c/unit_build/src/foo/test2.c +++ /dev/null @@ -1,8 +0,0 @@ - -// main.cpp -#include "header.h" - -int test3() -{ - return 0; -} diff --git a/tests/projects/c/unit_build/src/header.h b/tests/projects/c/unit_build/src/header.h deleted file mode 100644 index 29bfc5870..000000000 --- a/tests/projects/c/unit_build/src/header.h +++ /dev/null @@ -1,10 +0,0 @@ -// header.h -#ifndef HEADER_H -#define HEADER_H - -#include -#include -#include - -#endif - diff --git a/tests/projects/c/unit_build/src/main.c b/tests/projects/c/unit_build/src/main.c deleted file mode 100644 index f0408cdf8..000000000 --- a/tests/projects/c/unit_build/src/main.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "header.h" - -int main(int argc, char** argv) -{ - printf("hello xmake!\n"); - return 0; -} diff --git a/tests/projects/c/unit_build/src/test.cpp b/tests/projects/c/unit_build/src/test.cpp deleted file mode 100644 index 1cedddad9..000000000 --- a/tests/projects/c/unit_build/src/test.cpp +++ /dev/null @@ -1,4 +0,0 @@ -int test_cpp() -{ - return 0; -} diff --git a/tests/projects/c/unit_build/src/test2.c b/tests/projects/c/unit_build/src/test2.c deleted file mode 100644 index 596359cd2..000000000 --- a/tests/projects/c/unit_build/src/test2.c +++ /dev/null @@ -1,8 +0,0 @@ - -// main.cpp -#include "header.h" - -int test2() -{ - return 0; -} diff --git a/tests/projects/c/unit_build/src/test6.c b/tests/projects/c/unit_build/src/test6.c deleted file mode 100644 index efbd7c6c1..000000000 --- a/tests/projects/c/unit_build/src/test6.c +++ /dev/null @@ -1,8 +0,0 @@ - -// main.cpp -#include "header.h" - -int test6() -{ - return 0; -} diff --git a/tests/projects/c/unit_build/src/test7.c b/tests/projects/c/unit_build/src/test7.c deleted file mode 100644 index 24aeff619..000000000 --- a/tests/projects/c/unit_build/src/test7.c +++ /dev/null @@ -1,8 +0,0 @@ - -// main.cpp -#include "header.h" - -int test7() -{ - return 0; -} diff --git a/tests/projects/c/unit_build/src/test8.c b/tests/projects/c/unit_build/src/test8.c deleted file mode 100644 index 6ad5680a6..000000000 --- a/tests/projects/c/unit_build/src/test8.c +++ /dev/null @@ -1,8 +0,0 @@ - -// main.cpp -#include "header.h" - -int test8() -{ - return 0; -} diff --git a/tests/projects/c/unit_build/test.lua b/tests/projects/c/unit_build/test.lua deleted file mode 100644 index b76241be2..000000000 --- a/tests/projects/c/unit_build/test.lua +++ /dev/null @@ -1,6 +0,0 @@ --- main entry -function main(t) - - -- build project - t:build() -end diff --git a/tests/projects/c/unit_build/xmake.lua b/tests/projects/c/unit_build/xmake.lua deleted file mode 100644 index 1df67c0ec..000000000 --- a/tests/projects/c/unit_build/xmake.lua +++ /dev/null @@ -1,8 +0,0 @@ -target("test") - set_kind("binary") - add_includedirs("src") - add_rules("c++.unit_build", {batchsize = 2}) - add_files("src/*.c", "src/*.cpp") - add_files("src/foo/*.c", {unit_group = "foo"}) - add_files("src/bar/*.c", {unit_group = "bar"}) - diff --git a/tests/projects/c/unity_build/src/bar/test4.c b/tests/projects/c/unity_build/src/bar/test4.c new file mode 100644 index 000000000..a92803eb7 --- /dev/null +++ b/tests/projects/c/unity_build/src/bar/test4.c @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test4() +{ + return 0; +} diff --git a/tests/projects/c/unity_build/src/bar/test5.c b/tests/projects/c/unity_build/src/bar/test5.c new file mode 100644 index 000000000..2a3e7066c --- /dev/null +++ b/tests/projects/c/unity_build/src/bar/test5.c @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test5() +{ + return 0; +} diff --git a/tests/projects/c/unity_build/src/foo/test1.c b/tests/projects/c/unity_build/src/foo/test1.c new file mode 100644 index 000000000..e9d6c83d9 --- /dev/null +++ b/tests/projects/c/unity_build/src/foo/test1.c @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test() +{ + return 0; +} diff --git a/tests/projects/c/unity_build/src/foo/test2.c b/tests/projects/c/unity_build/src/foo/test2.c new file mode 100644 index 000000000..b4ce69b0f --- /dev/null +++ b/tests/projects/c/unity_build/src/foo/test2.c @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test3() +{ + return 0; +} diff --git a/tests/projects/c/unity_build/src/header.h b/tests/projects/c/unity_build/src/header.h new file mode 100644 index 000000000..29bfc5870 --- /dev/null +++ b/tests/projects/c/unity_build/src/header.h @@ -0,0 +1,10 @@ +// header.h +#ifndef HEADER_H +#define HEADER_H + +#include +#include +#include + +#endif + diff --git a/tests/projects/c/unity_build/src/main.c b/tests/projects/c/unity_build/src/main.c new file mode 100644 index 000000000..f0408cdf8 --- /dev/null +++ b/tests/projects/c/unity_build/src/main.c @@ -0,0 +1,7 @@ +#include "header.h" + +int main(int argc, char** argv) +{ + printf("hello xmake!\n"); + return 0; +} diff --git a/tests/projects/c/unity_build/src/test.cpp b/tests/projects/c/unity_build/src/test.cpp new file mode 100644 index 000000000..1cedddad9 --- /dev/null +++ b/tests/projects/c/unity_build/src/test.cpp @@ -0,0 +1,4 @@ +int test_cpp() +{ + return 0; +} diff --git a/tests/projects/c/unity_build/src/test2.c b/tests/projects/c/unity_build/src/test2.c new file mode 100644 index 000000000..596359cd2 --- /dev/null +++ b/tests/projects/c/unity_build/src/test2.c @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test2() +{ + return 0; +} diff --git a/tests/projects/c/unity_build/src/test6.c b/tests/projects/c/unity_build/src/test6.c new file mode 100644 index 000000000..efbd7c6c1 --- /dev/null +++ b/tests/projects/c/unity_build/src/test6.c @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test6() +{ + return 0; +} diff --git a/tests/projects/c/unity_build/src/test7.c b/tests/projects/c/unity_build/src/test7.c new file mode 100644 index 000000000..24aeff619 --- /dev/null +++ b/tests/projects/c/unity_build/src/test7.c @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test7() +{ + return 0; +} diff --git a/tests/projects/c/unity_build/src/test8.c b/tests/projects/c/unity_build/src/test8.c new file mode 100644 index 000000000..6ad5680a6 --- /dev/null +++ b/tests/projects/c/unity_build/src/test8.c @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test8() +{ + return 0; +} diff --git a/tests/projects/c/unity_build/test.lua b/tests/projects/c/unity_build/test.lua new file mode 100644 index 000000000..b76241be2 --- /dev/null +++ b/tests/projects/c/unity_build/test.lua @@ -0,0 +1,6 @@ +-- main entry +function main(t) + + -- build project + t:build() +end diff --git a/tests/projects/c/unity_build/xmake.lua b/tests/projects/c/unity_build/xmake.lua new file mode 100644 index 000000000..447960db5 --- /dev/null +++ b/tests/projects/c/unity_build/xmake.lua @@ -0,0 +1,8 @@ +target("test") + set_kind("binary") + add_includedirs("src") + add_rules("c++.unity_build", {batchsize = 2}) + add_files("src/*.c", "src/*.cpp") + add_files("src/foo/*.c", {unity_group = "foo"}) + add_files("src/bar/*.c", {unity_group = "bar"}) + diff --git a/xmake/rules/c++/unit_build/unit_build.lua b/xmake/rules/c++/unit_build/unit_build.lua deleted file mode 100644 index 7fd50b596..000000000 --- a/xmake/rules/c++/unit_build/unit_build.lua +++ /dev/null @@ -1,123 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- 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 --- --- http://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. --- --- Copyright (C) 2015-present, TBOOX Open Source Group. --- --- @author ruki --- @file unit_build.lua --- - --- imports -import("core.project.depend") - -function _merge_unitfile(target, sourcefile_unit, sourcefiles, opt) - local dependfile = target:dependfile(sourcefile_unit) - depend.on_changed(function () - - -- trace - vprint("generating.unitfile %s", sourcefile_unit) - - -- do merge - local unitfile = io.open(sourcefile_unit, "w") - for _, sourcefile in ipairs(sourcefiles) do - sourcefile = path.absolute(sourcefile) - sourcefile_unit = path.absolute(sourcefile_unit) - sourcefile = path.relative(sourcefile, path.directory(sourcefile_unit)) - unitfile:print("#include \"%s\"", sourcefile) - end - unitfile:close() - - end, {dependfile = dependfile, files = sourcefiles}) -end - -function generate_unitfiles(target, sourcebatch, opt) - local unitbatch = target:data("unit_build.unitbatch." .. sourcebatch.rulename) - if unitbatch then - for _, sourcefile_unit in ipairs(sourcebatch.sourcefiles) do - local sourceinfo = unitbatch[sourcefile_unit] - if sourceinfo then - local sourcefiles = sourceinfo.sourcefiles - if sourcefiles then - _merge_unitfile(target, sourcefile_unit, sourcefiles, opt) - end - end - end - end -end - --- use unit build --- --- e.g. --- add_rules("c++.unit_build", {batchsize = 2}) --- add_files("src/*.c", "src/*.cpp", {unit_ignored = true}) --- add_files("src/foo/*.c", {unit_group = "foo"}) --- add_files("src/bar/*.c", {unit_group = "bar"}) --- -function main(target, sourcebatch) - - -- get unit batch sources - local extraconf = target:extraconf("rules", "c++.unit_build") - local batchsize = extraconf and extraconf.batchsize - local id = 1 - local count = 0 - local unitbatch = {} - local sourcefiles = {} - local objectfiles = {} - local dependfiles = {} - local sourcedir = path.join(target:autogendir({root = true}), "unit_build") - for idx, sourcefile in pairs(sourcebatch.sourcefiles) do - local sourcefile_unit - local objectfile = sourcebatch.objectfiles[idx] - local dependfile = sourcebatch.dependfiles[idx] - local fileconfig = target:fileconfig(sourcefile) - if fileconfig and fileconfig.unit_group then - sourcefile_unit = path.join(sourcedir, "unit_" .. fileconfig.unit_group .. path.extension(sourcefile)) - elseif fileconfig and fileconfig.unit_ignored then - -- we do not add these files to unit file - table.insert(sourcefiles, sourcefile) - table.insert(objectfiles, objectfile) - table.insert(dependfiles, dependfile) - else - if batchsize and count > batchsize then - id = id + 1 - end - sourcefile_unit = path.join(sourcedir, "unit_" .. hash.uuid(tostring(id)):split("-", {plain = true})[1] .. path.extension(sourcefile)) - count = count + 1 - end - if sourcefile_unit then - local sourceinfo = unitbatch[sourcefile_unit] - if not sourceinfo then - sourceinfo = {} - sourceinfo.objectfile = target:objectfile(sourcefile_unit) - sourceinfo.dependfile = target:dependfile(sourceinfo.objectfile) - unitbatch[sourcefile_unit] = sourceinfo - end - sourceinfo.sourcefiles = sourceinfo.sourcefiles or {} - table.insert(sourceinfo.sourcefiles, sourcefile) - end - end - - -- use unit batch - for sourcefile_unit, sourceinfo in pairs(unitbatch) do - table.insert(sourcefiles, sourcefile_unit) - table.insert(objectfiles, sourceinfo.objectfile) - table.insert(dependfiles, sourceinfo.dependfile) - end - sourcebatch.sourcefiles = sourcefiles - sourcebatch.objectfiles = objectfiles - sourcebatch.dependfiles = dependfiles - - -- save unit batch - target:data_set("unit_build.unitbatch." .. sourcebatch.rulename, unitbatch) -end diff --git a/xmake/rules/c++/unit_build/xmake.lua b/xmake/rules/c++/unit_build/xmake.lua deleted file mode 100644 index b0eb7b39a..000000000 --- a/xmake/rules/c++/unit_build/xmake.lua +++ /dev/null @@ -1,45 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- 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 --- --- http://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. --- --- Copyright (C) 2015-present, TBOOX Open Source Group. --- --- @author ruki --- @file xmake.lua --- - -rule("c++.unit_build") - after_load(function (target) - import("unit_build") - local sourcebatches = target:sourcebatches() - if sourcebatches then - for _, rulename in ipairs({"c.build", "c++.build"}) do - local sourcebatch = sourcebatches[rulename] - if sourcebatch then - unit_build(target, sourcebatch) - end - end - end - end) - before_build(function (target, opt) - import("unit_build") - local sourcebatches = target:sourcebatches() - if sourcebatches then - for _, rulename in ipairs({"c.build", "c++.build"}) do - local sourcebatch = sourcebatches[rulename] - if sourcebatch then - unit_build.generate_unitfiles(target, sourcebatch, opt) - end - end - end - end) diff --git a/xmake/rules/c++/unity_build/unity_build.lua b/xmake/rules/c++/unity_build/unity_build.lua new file mode 100644 index 000000000..57bff99a0 --- /dev/null +++ b/xmake/rules/c++/unity_build/unity_build.lua @@ -0,0 +1,123 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file unity_build.lua +-- + +-- imports +import("core.project.depend") + +function _merge_unityfile(target, sourcefile_unity, sourcefiles, opt) + local dependfile = target:dependfile(sourcefile_unity) + depend.on_changed(function () + + -- trace + vprint("generating.unityfile %s", sourcefile_unity) + + -- do merge + local unityfile = io.open(sourcefile_unity, "w") + for _, sourcefile in ipairs(sourcefiles) do + sourcefile = path.absolute(sourcefile) + sourcefile_unity = path.absolute(sourcefile_unity) + sourcefile = path.relative(sourcefile, path.directory(sourcefile_unity)) + unityfile:print("#include \"%s\"", sourcefile) + end + unityfile:close() + + end, {dependfile = dependfile, files = sourcefiles}) +end + +function generate_unityfiles(target, sourcebatch, opt) + local unity_batch = target:data("unity_build.unity_batch." .. sourcebatch.rulename) + if unity_batch then + for _, sourcefile_unity in ipairs(sourcebatch.sourcefiles) do + local sourceinfo = unity_batch[sourcefile_unity] + if sourceinfo then + local sourcefiles = sourceinfo.sourcefiles + if sourcefiles then + _merge_unityfile(target, sourcefile_unity, sourcefiles, opt) + end + end + end + end +end + +-- use unity build +-- +-- e.g. +-- add_rules("c++.unity_build", {batchsize = 2}) +-- add_files("src/*.c", "src/*.cpp", {unity_ignored = true}) +-- add_files("src/foo/*.c", {unity_group = "foo"}) +-- add_files("src/bar/*.c", {unity_group = "bar"}) +-- +function main(target, sourcebatch) + + -- get unit batch sources + local extraconf = target:extraconf("rules", "c++.unity_build") + local batchsize = extraconf and extraconf.batchsize + local id = 1 + local count = 0 + local unity_batch = {} + local sourcefiles = {} + local objectfiles = {} + local dependfiles = {} + local sourcedir = path.join(target:autogendir({root = true}), "unity_build") + for idx, sourcefile in pairs(sourcebatch.sourcefiles) do + local sourcefile_unity + local objectfile = sourcebatch.objectfiles[idx] + local dependfile = sourcebatch.dependfiles[idx] + local fileconfig = target:fileconfig(sourcefile) + if fileconfig and fileconfig.unity_group then + sourcefile_unity = path.join(sourcedir, "unity_" .. fileconfig.unity_group .. path.extension(sourcefile)) + elseif fileconfig and fileconfig.unity_ignored then + -- we do not add these files to unit file + table.insert(sourcefiles, sourcefile) + table.insert(objectfiles, objectfile) + table.insert(dependfiles, dependfile) + else + if batchsize and count > batchsize then + id = id + 1 + end + sourcefile_unity = path.join(sourcedir, "unity_" .. hash.uuid(tostring(id)):split("-", {plain = true})[1] .. path.extension(sourcefile)) + count = count + 1 + end + if sourcefile_unity then + local sourceinfo = unity_batch[sourcefile_unity] + if not sourceinfo then + sourceinfo = {} + sourceinfo.objectfile = target:objectfile(sourcefile_unity) + sourceinfo.dependfile = target:dependfile(sourceinfo.objectfile) + unity_batch[sourcefile_unity] = sourceinfo + end + sourceinfo.sourcefiles = sourceinfo.sourcefiles or {} + table.insert(sourceinfo.sourcefiles, sourcefile) + end + end + + -- use unit batch + for sourcefile_unity, sourceinfo in pairs(unity_batch) do + table.insert(sourcefiles, sourcefile_unity) + table.insert(objectfiles, sourceinfo.objectfile) + table.insert(dependfiles, sourceinfo.dependfile) + end + sourcebatch.sourcefiles = sourcefiles + sourcebatch.objectfiles = objectfiles + sourcebatch.dependfiles = dependfiles + + -- save unit batch + target:data_set("unity_build.unity_batch." .. sourcebatch.rulename, unity_batch) +end diff --git a/xmake/rules/c++/unity_build/xmake.lua b/xmake/rules/c++/unity_build/xmake.lua new file mode 100644 index 000000000..838f8a097 --- /dev/null +++ b/xmake/rules/c++/unity_build/xmake.lua @@ -0,0 +1,45 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +rule("c++.unity_build") + after_load(function (target) + import("unity_build") + local sourcebatches = target:sourcebatches() + if sourcebatches then + for _, rulename in ipairs({"c.build", "c++.build"}) do + local sourcebatch = sourcebatches[rulename] + if sourcebatch then + unity_build(target, sourcebatch) + end + end + end + end) + before_build(function (target, opt) + import("unity_build") + local sourcebatches = target:sourcebatches() + if sourcebatches then + for _, rulename in ipairs({"c.build", "c++.build"}) do + local sourcebatch = sourcebatches[rulename] + if sourcebatch then + unity_build.generate_unitfiles(target, sourcebatch, opt) + end + end + end + end) -- cgit v1.3.1 From 26de32e94fea1b849395ccf035aeb111b71084f3 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 18 Oct 2021 21:02:32 +0800 Subject: rename to unity build --- xmake/rules/c++/unity_build/unity_build.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/c++/unity_build/unity_build.lua b/xmake/rules/c++/unity_build/unity_build.lua index 57bff99a0..82338f506 100644 --- a/xmake/rules/c++/unity_build/unity_build.lua +++ b/xmake/rules/c++/unity_build/unity_build.lua @@ -84,7 +84,7 @@ function main(target, sourcebatch) if fileconfig and fileconfig.unity_group then sourcefile_unity = path.join(sourcedir, "unity_" .. fileconfig.unity_group .. path.extension(sourcefile)) elseif fileconfig and fileconfig.unity_ignored then - -- we do not add these files to unit file + -- we do not add these files to unity file table.insert(sourcefiles, sourcefile) table.insert(objectfiles, objectfile) table.insert(dependfiles, dependfile) -- cgit v1.3.1 From afcfa7fcd5dd767ecd683cdd5bacea120cfc6270 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 18 Oct 2021 21:04:08 +0800 Subject: improve unity build --- xmake/rules/c++/unity_build/unity_build.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/c++/unity_build/unity_build.lua b/xmake/rules/c++/unity_build/unity_build.lua index 82338f506..e28e5aff3 100644 --- a/xmake/rules/c++/unity_build/unity_build.lua +++ b/xmake/rules/c++/unity_build/unity_build.lua @@ -83,7 +83,7 @@ function main(target, sourcebatch) local fileconfig = target:fileconfig(sourcefile) if fileconfig and fileconfig.unity_group then sourcefile_unity = path.join(sourcedir, "unity_" .. fileconfig.unity_group .. path.extension(sourcefile)) - elseif fileconfig and fileconfig.unity_ignored then + elseif (fileconfig and fileconfig.unity_ignored) or (batchsize == 0) then -- we do not add these files to unity file table.insert(sourcefiles, sourcefile) table.insert(objectfiles, objectfile) -- cgit v1.3.1 From 2f8bf766dfeb9103e5ab9a1ccc7936a5bc04aa9c Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 18 Oct 2021 21:05:07 +0800 Subject: fix errors --- xmake/rules/c++/unity_build/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/c++/unity_build/xmake.lua b/xmake/rules/c++/unity_build/xmake.lua index 838f8a097..b03a383ae 100644 --- a/xmake/rules/c++/unity_build/xmake.lua +++ b/xmake/rules/c++/unity_build/xmake.lua @@ -38,7 +38,7 @@ rule("c++.unity_build") for _, rulename in ipairs({"c.build", "c++.build"}) do local sourcebatch = sourcebatches[rulename] if sourcebatch then - unity_build.generate_unitfiles(target, sourcebatch, opt) + unity_build.generate_unityfiles(target, sourcebatch, opt) end end end -- cgit v1.3.1 From 105117735be22a14c32d136681b5f08916625fb4 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 18 Oct 2021 22:17:25 +0800 Subject: add c.unity_build --- tests/projects/c/unity_build/xmake.lua | 2 +- xmake/rules/c++/unity_build/unity_build.lua | 2 +- xmake/rules/c++/unity_build/xmake.lua | 38 +++++++++++++++++++++-------- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/tests/projects/c/unity_build/xmake.lua b/tests/projects/c/unity_build/xmake.lua index 447960db5..89166a312 100644 --- a/tests/projects/c/unity_build/xmake.lua +++ b/tests/projects/c/unity_build/xmake.lua @@ -1,7 +1,7 @@ target("test") set_kind("binary") add_includedirs("src") - add_rules("c++.unity_build", {batchsize = 2}) + add_rules("c.unity_build", {batchsize = 2}) add_files("src/*.c", "src/*.cpp") add_files("src/foo/*.c", {unity_group = "foo"}) add_files("src/bar/*.c", {unity_group = "bar"}) diff --git a/xmake/rules/c++/unity_build/unity_build.lua b/xmake/rules/c++/unity_build/unity_build.lua index e28e5aff3..96b53001e 100644 --- a/xmake/rules/c++/unity_build/unity_build.lua +++ b/xmake/rules/c++/unity_build/unity_build.lua @@ -67,7 +67,7 @@ end function main(target, sourcebatch) -- get unit batch sources - local extraconf = target:extraconf("rules", "c++.unity_build") + local extraconf = target:extraconf("rules", sourcebatch.sourcekind == "cxx" and "c++.unity_build" or "c.unity_build") local batchsize = extraconf and extraconf.batchsize local id = 1 local count = 0 diff --git a/xmake/rules/c++/unity_build/xmake.lua b/xmake/rules/c++/unity_build/xmake.lua index b03a383ae..e0dfa9660 100644 --- a/xmake/rules/c++/unity_build/xmake.lua +++ b/xmake/rules/c++/unity_build/xmake.lua @@ -18,16 +18,36 @@ -- @file xmake.lua -- +rule("c.unity_build") + after_load(function (target) + import("unity_build") + local sourcebatches = target:sourcebatches() + if sourcebatches then + local sourcebatch = sourcebatches["c.build"] + if sourcebatch then + unity_build(target, sourcebatch) + end + end + end) + before_build(function (target, opt) + import("unity_build") + local sourcebatches = target:sourcebatches() + if sourcebatches then + local sourcebatch = sourcebatches["c.build"] + if sourcebatch then + unity_build.generate_unityfiles(target, sourcebatch, opt) + end + end + end) + rule("c++.unity_build") after_load(function (target) import("unity_build") local sourcebatches = target:sourcebatches() if sourcebatches then - for _, rulename in ipairs({"c.build", "c++.build"}) do - local sourcebatch = sourcebatches[rulename] - if sourcebatch then - unity_build(target, sourcebatch) - end + local sourcebatch = sourcebatches["c++.build"] + if sourcebatch then + unity_build(target, sourcebatch) end end end) @@ -35,11 +55,9 @@ rule("c++.unity_build") import("unity_build") local sourcebatches = target:sourcebatches() if sourcebatches then - for _, rulename in ipairs({"c.build", "c++.build"}) do - local sourcebatch = sourcebatches[rulename] - if sourcebatch then - unity_build.generate_unityfiles(target, sourcebatch, opt) - end + local sourcebatch = sourcebatches["c++.build"] + if sourcebatch then + unity_build.generate_unityfiles(target, sourcebatch, opt) end end end) -- cgit v1.3.1 From 7214daac014811ca73103d0e8d22bdc2b1b54470 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 18 Oct 2021 22:18:01 +0800 Subject: add c++ unity build test --- tests/projects/c++/unity_build/src/bar/test4.cpp | 8 +++++++ tests/projects/c++/unity_build/src/bar/test5.cpp | 8 +++++++ tests/projects/c++/unity_build/src/bar/test6.cpp | 8 +++++++ tests/projects/c++/unity_build/src/foo/test.cpp | 8 +++++++ tests/projects/c++/unity_build/src/foo/test2.cpp | 8 +++++++ tests/projects/c++/unity_build/src/header.h | 27 ++++++++++++++++++++++++ tests/projects/c++/unity_build/src/header2.h | 0 tests/projects/c++/unity_build/src/main.cpp | 8 +++++++ tests/projects/c++/unity_build/src/test.c | 4 ++++ tests/projects/c++/unity_build/src/test7.cpp | 8 +++++++ tests/projects/c++/unity_build/src/test8.cpp | 8 +++++++ tests/projects/c++/unity_build/test.lua | 6 ++++++ tests/projects/c++/unity_build/xmake.lua | 9 ++++++++ 13 files changed, 110 insertions(+) create mode 100644 tests/projects/c++/unity_build/src/bar/test4.cpp create mode 100644 tests/projects/c++/unity_build/src/bar/test5.cpp create mode 100644 tests/projects/c++/unity_build/src/bar/test6.cpp create mode 100644 tests/projects/c++/unity_build/src/foo/test.cpp create mode 100644 tests/projects/c++/unity_build/src/foo/test2.cpp create mode 100644 tests/projects/c++/unity_build/src/header.h create mode 100644 tests/projects/c++/unity_build/src/header2.h create mode 100644 tests/projects/c++/unity_build/src/main.cpp create mode 100644 tests/projects/c++/unity_build/src/test.c create mode 100644 tests/projects/c++/unity_build/src/test7.cpp create mode 100644 tests/projects/c++/unity_build/src/test8.cpp create mode 100644 tests/projects/c++/unity_build/test.lua create mode 100644 tests/projects/c++/unity_build/xmake.lua diff --git a/tests/projects/c++/unity_build/src/bar/test4.cpp b/tests/projects/c++/unity_build/src/bar/test4.cpp new file mode 100644 index 000000000..a92803eb7 --- /dev/null +++ b/tests/projects/c++/unity_build/src/bar/test4.cpp @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test4() +{ + return 0; +} diff --git a/tests/projects/c++/unity_build/src/bar/test5.cpp b/tests/projects/c++/unity_build/src/bar/test5.cpp new file mode 100644 index 000000000..2a3e7066c --- /dev/null +++ b/tests/projects/c++/unity_build/src/bar/test5.cpp @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test5() +{ + return 0; +} diff --git a/tests/projects/c++/unity_build/src/bar/test6.cpp b/tests/projects/c++/unity_build/src/bar/test6.cpp new file mode 100644 index 000000000..efbd7c6c1 --- /dev/null +++ b/tests/projects/c++/unity_build/src/bar/test6.cpp @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test6() +{ + return 0; +} diff --git a/tests/projects/c++/unity_build/src/foo/test.cpp b/tests/projects/c++/unity_build/src/foo/test.cpp new file mode 100644 index 000000000..e9d6c83d9 --- /dev/null +++ b/tests/projects/c++/unity_build/src/foo/test.cpp @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test() +{ + return 0; +} diff --git a/tests/projects/c++/unity_build/src/foo/test2.cpp b/tests/projects/c++/unity_build/src/foo/test2.cpp new file mode 100644 index 000000000..596359cd2 --- /dev/null +++ b/tests/projects/c++/unity_build/src/foo/test2.cpp @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test2() +{ + return 0; +} diff --git a/tests/projects/c++/unity_build/src/header.h b/tests/projects/c++/unity_build/src/header.h new file mode 100644 index 000000000..affda55ca --- /dev/null +++ b/tests/projects/c++/unity_build/src/header.h @@ -0,0 +1,27 @@ +// header.h +#ifndef HEADER_H +#define HEADER_H + +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif + diff --git a/tests/projects/c++/unity_build/src/header2.h b/tests/projects/c++/unity_build/src/header2.h new file mode 100644 index 000000000..e69de29bb diff --git a/tests/projects/c++/unity_build/src/main.cpp b/tests/projects/c++/unity_build/src/main.cpp new file mode 100644 index 000000000..27d41ee50 --- /dev/null +++ b/tests/projects/c++/unity_build/src/main.cpp @@ -0,0 +1,8 @@ +#include "header.h" + +int main(int argc, char** argv) +{ + std::string s("xmake"); + printf("hello %s!\n", s.c_str()); + return 0; +} diff --git a/tests/projects/c++/unity_build/src/test.c b/tests/projects/c++/unity_build/src/test.c new file mode 100644 index 000000000..7f0aa2bf4 --- /dev/null +++ b/tests/projects/c++/unity_build/src/test.c @@ -0,0 +1,4 @@ + +void test_c(void) +{ +} diff --git a/tests/projects/c++/unity_build/src/test7.cpp b/tests/projects/c++/unity_build/src/test7.cpp new file mode 100644 index 000000000..24aeff619 --- /dev/null +++ b/tests/projects/c++/unity_build/src/test7.cpp @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test7() +{ + return 0; +} diff --git a/tests/projects/c++/unity_build/src/test8.cpp b/tests/projects/c++/unity_build/src/test8.cpp new file mode 100644 index 000000000..6ad5680a6 --- /dev/null +++ b/tests/projects/c++/unity_build/src/test8.cpp @@ -0,0 +1,8 @@ + +// main.cpp +#include "header.h" + +int test8() +{ + return 0; +} diff --git a/tests/projects/c++/unity_build/test.lua b/tests/projects/c++/unity_build/test.lua new file mode 100644 index 000000000..b76241be2 --- /dev/null +++ b/tests/projects/c++/unity_build/test.lua @@ -0,0 +1,6 @@ +-- main entry +function main(t) + + -- build project + t:build() +end diff --git a/tests/projects/c++/unity_build/xmake.lua b/tests/projects/c++/unity_build/xmake.lua new file mode 100644 index 000000000..ce38ae9ec --- /dev/null +++ b/tests/projects/c++/unity_build/xmake.lua @@ -0,0 +1,9 @@ +target("test") + set_kind("binary") + add_includedirs("src") + add_rules("c++.unity_build", {batchsize = 2}) + add_files("src/*.c", "src/*.cpp") + add_files("src/foo/*.cpp", {unity_group = "foo"}) + add_files("src/bar/*.cpp", {unity_group = "bar"}) + + -- cgit v1.3.1 From bc6e13ac0a28839ed45aec376fcd10acdc6488a6 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 18 Oct 2021 22:18:56 +0800 Subject: fix links --- xmake/rules/c++/unity_build/unity_build.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xmake/rules/c++/unity_build/unity_build.lua b/xmake/rules/c++/unity_build/unity_build.lua index 96b53001e..4574011f2 100644 --- a/xmake/rules/c++/unity_build/unity_build.lua +++ b/xmake/rules/c++/unity_build/unity_build.lua @@ -109,7 +109,8 @@ function main(target, sourcebatch) end -- use unit batch - for sourcefile_unity, sourceinfo in pairs(unity_batch) do + for _, sourcefile_unity in ipairs(table.orderkeys(unity_batch)) do + local sourceinfo = unity_batch[sourcefile_unity] table.insert(sourcefiles, sourcefile_unity) table.insert(objectfiles, sourceinfo.objectfile) table.insert(dependfiles, sourceinfo.dependfile) -- cgit v1.3.1 From 7f5c18288cf287abe44e57046a80ef7db0c0b0da Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 18 Oct 2021 22:59:43 +0800 Subject: improve single batch --- xmake/rules/c++/unity_build/unity_build.lua | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/xmake/rules/c++/unity_build/unity_build.lua b/xmake/rules/c++/unity_build/unity_build.lua index 4574011f2..d73a3adf4 100644 --- a/xmake/rules/c++/unity_build/unity_build.lua +++ b/xmake/rules/c++/unity_build/unity_build.lua @@ -83,7 +83,7 @@ function main(target, sourcebatch) local fileconfig = target:fileconfig(sourcefile) if fileconfig and fileconfig.unity_group then sourcefile_unity = path.join(sourcedir, "unity_" .. fileconfig.unity_group .. path.extension(sourcefile)) - elseif (fileconfig and fileconfig.unity_ignored) or (batchsize == 0) then + elseif (fileconfig and fileconfig.unity_ignored) or (batchsize and batchsize <= 1) then -- we do not add these files to unity file table.insert(sourcefiles, sourcefile) table.insert(objectfiles, objectfile) @@ -111,9 +111,15 @@ function main(target, sourcebatch) -- use unit batch for _, sourcefile_unity in ipairs(table.orderkeys(unity_batch)) do local sourceinfo = unity_batch[sourcefile_unity] - table.insert(sourcefiles, sourcefile_unity) - table.insert(objectfiles, sourceinfo.objectfile) - table.insert(dependfiles, sourceinfo.dependfile) + if #sourceinfo.sourcefiles > 1 then + table.insert(sourcefiles, sourcefile_unity) + table.insert(objectfiles, sourceinfo.objectfile) + table.insert(dependfiles, sourceinfo.dependfile) + else + table.insert(sourcefiles, sourceinfo.sourcefiles[1]) + table.insert(objectfiles, sourceinfo.objectfile) + table.insert(dependfiles, sourceinfo.dependfile) + end end sourcebatch.sourcefiles = sourcefiles sourcebatch.objectfiles = objectfiles -- cgit v1.3.1 From 1ec16d7882188dd817ccb23be43359aa4d045d24 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 19 Oct 2021 00:06:00 +0800 Subject: add uniqueid --- tests/projects/c++/unity_build/src/bar/test4.cpp | 6 +++++- tests/projects/c++/unity_build/src/bar/test5.cpp | 7 ++++++- tests/projects/c++/unity_build/xmake.lua | 2 +- xmake/rules/c++/unity_build/unity_build.lua | 11 +++++++++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/tests/projects/c++/unity_build/src/bar/test4.cpp b/tests/projects/c++/unity_build/src/bar/test4.cpp index a92803eb7..8fe732964 100644 --- a/tests/projects/c++/unity_build/src/bar/test4.cpp +++ b/tests/projects/c++/unity_build/src/bar/test4.cpp @@ -2,7 +2,11 @@ // main.cpp #include "header.h" +namespace MY_UNITY_ID { + int i = 42; +} + int test4() { - return 0; + return MY_UNITY_ID::i; } diff --git a/tests/projects/c++/unity_build/src/bar/test5.cpp b/tests/projects/c++/unity_build/src/bar/test5.cpp index 2a3e7066c..afff0b46c 100644 --- a/tests/projects/c++/unity_build/src/bar/test5.cpp +++ b/tests/projects/c++/unity_build/src/bar/test5.cpp @@ -2,7 +2,12 @@ // main.cpp #include "header.h" +namespace MY_UNITY_ID { + int i = 42; +} + int test5() { - return 0; + return MY_UNITY_ID::i; } + diff --git a/tests/projects/c++/unity_build/xmake.lua b/tests/projects/c++/unity_build/xmake.lua index ce38ae9ec..a881c5c36 100644 --- a/tests/projects/c++/unity_build/xmake.lua +++ b/tests/projects/c++/unity_build/xmake.lua @@ -1,7 +1,7 @@ target("test") set_kind("binary") add_includedirs("src") - add_rules("c++.unity_build", {batchsize = 2}) + add_rules("c++.unity_build", {batchsize = 2, uniqueid = "MY_UNITY_ID"}) add_files("src/*.c", "src/*.cpp") add_files("src/foo/*.cpp", {unity_group = "foo"}) add_files("src/bar/*.cpp", {unity_group = "bar"}) diff --git a/xmake/rules/c++/unity_build/unity_build.lua b/xmake/rules/c++/unity_build/unity_build.lua index d73a3adf4..2d8e69d5d 100644 --- a/xmake/rules/c++/unity_build/unity_build.lua +++ b/xmake/rules/c++/unity_build/unity_build.lua @@ -29,12 +29,21 @@ function _merge_unityfile(target, sourcefile_unity, sourcefiles, opt) vprint("generating.unityfile %s", sourcefile_unity) -- do merge + local uniqueid = target:data("unity_build.uniqueid") local unityfile = io.open(sourcefile_unity, "w") for _, sourcefile in ipairs(sourcefiles) do sourcefile = path.absolute(sourcefile) sourcefile_unity = path.absolute(sourcefile_unity) sourcefile = path.relative(sourcefile, path.directory(sourcefile_unity)) + if uniqueid then + unityfile:print("#ifndef %s", uniqueid) + unityfile:print("#define %s %s", uniqueid, "unity_" .. hash.uuid():split("-", {plain = true})[1]) + unityfile:print("#endif") + end unityfile:print("#include \"%s\"", sourcefile) + if uniqueid then + unityfile:print("#undef %s", uniqueid) + end end unityfile:close() @@ -69,6 +78,7 @@ function main(target, sourcebatch) -- get unit batch sources local extraconf = target:extraconf("rules", sourcebatch.sourcekind == "cxx" and "c++.unity_build" or "c.unity_build") local batchsize = extraconf and extraconf.batchsize + local uniqueid = extraconf and extraconf.uniqueid local id = 1 local count = 0 local unity_batch = {} @@ -126,5 +136,6 @@ function main(target, sourcebatch) sourcebatch.dependfiles = dependfiles -- save unit batch + target:data_set("unity_build.uniqueid", uniqueid) target:data_set("unity_build.unity_batch." .. sourcebatch.rulename, unity_batch) end -- cgit v1.3.1 From 7e6fba5fe7662b4e58ce150aeab17c70b6b12254 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 18 Oct 2021 19:07:39 +0800 Subject: Update unity_build.lua --- xmake/rules/c++/unity_build/unity_build.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/xmake/rules/c++/unity_build/unity_build.lua b/xmake/rules/c++/unity_build/unity_build.lua index 2d8e69d5d..608f79fed 100644 --- a/xmake/rules/c++/unity_build/unity_build.lua +++ b/xmake/rules/c++/unity_build/unity_build.lua @@ -36,9 +36,7 @@ function _merge_unityfile(target, sourcefile_unity, sourcefiles, opt) sourcefile_unity = path.absolute(sourcefile_unity) sourcefile = path.relative(sourcefile, path.directory(sourcefile_unity)) if uniqueid then - unityfile:print("#ifndef %s", uniqueid) unityfile:print("#define %s %s", uniqueid, "unity_" .. hash.uuid():split("-", {plain = true})[1]) - unityfile:print("#endif") end unityfile:print("#include \"%s\"", sourcefile) if uniqueid then -- cgit v1.3.1 From 87e3ab369eb97e7402aed596d2ec90c2741a605b Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 19 Oct 2021 00:52:04 +0800 Subject: add utils.amalgamate --- xmake/modules/utils/amalgamate.lua | 44 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 xmake/modules/utils/amalgamate.lua diff --git a/xmake/modules/utils/amalgamate.lua b/xmake/modules/utils/amalgamate.lua new file mode 100644 index 000000000..9d2f38209 --- /dev/null +++ b/xmake/modules/utils/amalgamate.lua @@ -0,0 +1,44 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file amalgamate.lua +-- + +-- imports +import("core.base.option") +import("core.project.config") +import("core.project.project") + +-- the options +local options = +{ + {'o', "outputdir", "kv", nil, "Set the output directory."}, + {nil, "target", "v", nil, "The target name." } +} + +-- generate amalgamate code +-- +-- https://github.com/xmake-io/xmake/issues/1438 +-- +function main(...) + + -- parse arguments + local argv = table.pack(...) + local args = option.parse(argv, options, "Generate amalgamate code." + , "" + , "Usage: xmake l utils.amalgamate [options]") +end -- cgit v1.3.1 From 632b064c26ed87080d891d193cf959ab68f09651 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 19 Oct 2021 00:57:06 +0800 Subject: impl cli.amalgamate --- xmake/modules/cli/amalgamate.lua | 103 +++++++++++++++++++++++++++++++++++++ xmake/modules/utils/amalgamate.lua | 44 ---------------- 2 files changed, 103 insertions(+), 44 deletions(-) create mode 100644 xmake/modules/cli/amalgamate.lua delete mode 100644 xmake/modules/utils/amalgamate.lua diff --git a/xmake/modules/cli/amalgamate.lua b/xmake/modules/cli/amalgamate.lua new file mode 100644 index 000000000..1657fbadf --- /dev/null +++ b/xmake/modules/cli/amalgamate.lua @@ -0,0 +1,103 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file amalgamate.lua +-- + +-- imports +import("core.base.option") +import("core.project.config") +import("core.project.task") +import("core.project.project") + +-- the options +local options = +{ + {'u', "uniqueid", "kv", nil, "Set the unique id." }, + {'o', "outputdir", "kv", nil, "Set the output directory."}, + {nil, "target", "v", nil, "The target name." } +} + +-- generate code +function _generate_amalgamate_code(target, opt) + + -- generate source code + local outputdir = opt.outputdir + local uniqueid = opt.uniqueid + for _, sourcebatch in pairs(target:sourcebatches()) do + local sourcekind = sourcebatch.sourcekind + if sourcekind == "cc" or sourcekind == "cxx" then + local outputpath = path.join(outputdir, target:name() .. (sourcekind == "cxx" and ".cpp" or ".c")) + local outputfile = io.open(outputpath, "w") + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + if uniqueid then + outputfile:print("#define %s %s", uniqueid, "unity_" .. hash.uuid():split("-", {plain = true})[1]) + end + outputfile:write(io.readfile(sourcefile)) + if uniqueid then + outputfile:print("#undef %s", uniqueid) + end + end + outputfile:close() + cprint("${bright}%s generated!", outputpath) + end + end + + -- generate header file + local srcheaders = target:headerfiles(includedir) + if srcheaders then + local outputpath = path.join(outputdir, target:name() .. ".h") + local outputfile = io.open(outputpath, "w") + for _, srcheader in ipairs(srcheaders) do + if uniqueid then + outputfile:print("#define %s %s", uniqueid, "unity_" .. hash.uuid():split("-", {plain = true})[1]) + end + outputfile:write(io.readfile(srcheader)) + if uniqueid then + outputfile:print("#undef %s", uniqueid) + end + end + outputfile:close() + cprint("${bright}%s generated!", outputpath) + end +end + +-- generate amalgamate code +-- +-- https://github.com/xmake-io/xmake/issues/1438 +-- +function main(...) + + -- parse arguments + local argv = table.pack(...) + local args = option.parse(argv, options, "Generate amalgamate code.", + "", + "Usage: xmake l cli.amalgamate [options]") + + -- config first + task.run("config") + + -- generate amalgamate code + args.outputdir = args.outputdir or config.buildir() + if args.target then + _generate_amalgamate_code(args.target, args) + else + for _, target in ipairs(project.ordertargets()) do + _generate_amalgamate_code(target, args) + end + end +end diff --git a/xmake/modules/utils/amalgamate.lua b/xmake/modules/utils/amalgamate.lua deleted file mode 100644 index 9d2f38209..000000000 --- a/xmake/modules/utils/amalgamate.lua +++ /dev/null @@ -1,44 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- 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 --- --- http://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. --- --- Copyright (C) 2015-present, TBOOX Open Source Group. --- --- @author ruki --- @file amalgamate.lua --- - --- imports -import("core.base.option") -import("core.project.config") -import("core.project.project") - --- the options -local options = -{ - {'o', "outputdir", "kv", nil, "Set the output directory."}, - {nil, "target", "v", nil, "The target name." } -} - --- generate amalgamate code --- --- https://github.com/xmake-io/xmake/issues/1438 --- -function main(...) - - -- parse arguments - local argv = table.pack(...) - local args = option.parse(argv, options, "Generate amalgamate code." - , "" - , "Usage: xmake l utils.amalgamate [options]") -end -- cgit v1.3.1 From 63a7afefde2caf98b3b4a9114b6050f9d4baecd4 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 19 Oct 2021 22:34:39 +0800 Subject: improve amalgamate --- xmake/modules/cli/amalgamate.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/xmake/modules/cli/amalgamate.lua b/xmake/modules/cli/amalgamate.lua index 1657fbadf..e495ae70b 100644 --- a/xmake/modules/cli/amalgamate.lua +++ b/xmake/modules/cli/amalgamate.lua @@ -35,6 +35,11 @@ local options = -- generate code function _generate_amalgamate_code(target, opt) + -- only for library + if not target:is_library() then + return + end + -- generate source code local outputdir = opt.outputdir local uniqueid = opt.uniqueid @@ -59,7 +64,7 @@ function _generate_amalgamate_code(target, opt) -- generate header file local srcheaders = target:headerfiles(includedir) - if srcheaders then + if srcheaders and #srcheaders > 0 then local outputpath = path.join(outputdir, target:name() .. ".h") local outputfile = io.open(outputpath, "w") for _, srcheader in ipairs(srcheaders) do -- cgit v1.3.1 From 1c92df260a519c84b647a07da5f7a85b4d792ff1 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 19 Oct 2021 22:41:01 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89d1a64aa..e2da4954c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * [#1623](https://github.com/xmake-io/xmake/issues/1632): Support find_package from cmake * [#1747](https://github.com/xmake-io/xmake/issues/1747): Add `set_kind("headeronly")` for target to install files for headeronly library * [#1019](https://github.com/xmake-io/xmake/issues/1019): Support Unity build +* [#1438](https://github.com/xmake-io/xmake/issues/1438): Support code amalgamation, `xmake l cli.amalgamate` ### Changes @@ -1112,6 +1113,7 @@ * [#1623](https://github.com/xmake-io/xmake/issues/1632): 支持 find_package 从 cmake 查找包 * [#1747](https://github.com/xmake-io/xmake/issues/1747): 添加 `set_kind("headeronly")` 更好的处理 headeronly 库的安装 * [#1019](https://github.com/xmake-io/xmake/issues/1019): 支持 Unity build +* [#1438](https://github.com/xmake-io/xmake/issues/1438): 增加 `xmake l cli.amalgamate` 命令支持代码合并 ### 改进 -- cgit v1.3.1 From 6cc23f1211ea6f635393e9d6a02ef93857bca9ab Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 20 Oct 2021 00:43:14 +0800 Subject: fix cmake importfiles for headeronly --- xmake/modules/cli/amalgamate.lua | 4 ++-- xmake/modules/target/action/install/cmake_importfiles.lua | 14 +++++++------- .../scripts/cmake_importfiles/xxxTargets-headeronly.cmake | 9 --------- 3 files changed, 9 insertions(+), 18 deletions(-) delete mode 100644 xmake/scripts/cmake_importfiles/xxxTargets-headeronly.cmake diff --git a/xmake/modules/cli/amalgamate.lua b/xmake/modules/cli/amalgamate.lua index e495ae70b..a9835eda6 100644 --- a/xmake/modules/cli/amalgamate.lua +++ b/xmake/modules/cli/amalgamate.lua @@ -35,8 +35,8 @@ local options = -- generate code function _generate_amalgamate_code(target, opt) - -- only for library - if not target:is_library() then + -- only for library/binary + if not target:is_library() and not target:is_binary() then return end diff --git a/xmake/modules/target/action/install/cmake_importfiles.lua b/xmake/modules/target/action/install/cmake_importfiles.lua index ea53ab519..c566b4471 100644 --- a/xmake/modules/target/action/install/cmake_importfiles.lua +++ b/xmake/modules/target/action/install/cmake_importfiles.lua @@ -41,7 +41,7 @@ function _get_builtinvars(target, installdir) return {TARGETNAME = target:name(), PROJECTNAME = project.name() or target:name(), TARGETFILENAME = target:targetfile() and _get_libfile(target, installdir), - TARGETKIND = target:is_shared() and "SHARED" or "STATIC", + TARGETKIND = target:is_headeronly() and "interface" or (target:is_shared() and "SHARED" or "STATIC"), PACKAGE_VERSION = target:get("version") or "1.0.0", TARGET_PTRBYTES = target:is_arch("x86", "i386") and "4" or "8"} end @@ -151,12 +151,12 @@ function main(target, opt) _append_cmake_configfile(target, installdir, "xxxConfig.cmake", opt) _install_cmake_configfile(target, installdir, "xxxConfigVersion.cmake", opt) _install_cmake_targetfile(target, installdir, "xxxTargets.cmake", opt) - if target:is_headeronly() then - _install_cmake_targetfile(target, installdir, "xxxTargets-headeronly.cmake", opt) - elseif is_mode("debug") then - _install_cmake_targetfile(target, installdir, "xxxTargets-debug.cmake", opt) - else - _install_cmake_targetfile(target, installdir, "xxxTargets-release.cmake", opt) + if not target:is_headeronly() then + if is_mode("debug") then + _install_cmake_targetfile(target, installdir, "xxxTargets-debug.cmake", opt) + else + _install_cmake_targetfile(target, installdir, "xxxTargets-release.cmake", opt) + end end end diff --git a/xmake/scripts/cmake_importfiles/xxxTargets-headeronly.cmake b/xmake/scripts/cmake_importfiles/xxxTargets-headeronly.cmake deleted file mode 100644 index c35a310a4..000000000 --- a/xmake/scripts/cmake_importfiles/xxxTargets-headeronly.cmake +++ /dev/null @@ -1,9 +0,0 @@ -#---------------------------------------------------------------- -# Generated CMake target import file for configuration "Headeronly". -#---------------------------------------------------------------- - -# Commands may need to know the format version. -set(CMAKE_IMPORT_FILE_VERSION 1) - -# Commands beyond this point should not need to know the version. -set(CMAKE_IMPORT_FILE_VERSION) -- cgit v1.3.1 From 971dbe92eb973a1b0ff4f720d455050eabe058e3 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 20 Oct 2021 00:44:30 +0800 Subject: improve pkgconfig importfiles --- .../target/action/install/pkgconfig_importfiles.lua | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/xmake/modules/target/action/install/pkgconfig_importfiles.lua b/xmake/modules/target/action/install/pkgconfig_importfiles.lua index 0cad0d267..942c496c7 100644 --- a/xmake/modules/target/action/install/pkgconfig_importfiles.lua +++ b/xmake/modules/target/action/install/pkgconfig_importfiles.lua @@ -35,11 +35,11 @@ function main(target, opt) local pcfile = path.join(installdir, opt and opt.libdir or "lib", "pkgconfig", opt.filename or (target:basename() .. ".pc")) -- get includedirs - local includedirs = opt.includedirs or {path.join(installdir, "include")} + local includedirs = opt.includedirs -- get links and linkdirs local links = opt.links or target:basename() - local linkdirs = opt.linkdirs or {path.join(installdir, "lib")} + local linkdirs = opt.linkdirs -- get libs local libs = "" @@ -47,8 +47,10 @@ function main(target, opt) libs = libs .. "-L" .. linkdir end libs = libs .. " -L${libdir}" - for _, link in ipairs(links) do - libs = libs .. " -l" .. link + if not target:is_headeronly() then + for _, link in ipairs(links) do + libs = libs .. " -l" .. link + end end -- get cflags @@ -66,9 +68,7 @@ function main(target, opt) if file then file:print("prefix=%s", installdir) file:print("exec_prefix=${prefix}") - if not target:is_headeronly() then - file:print("libdir=${exec_prefix}/lib") - end + file:print("libdir=${exec_prefix}/lib") file:print("includedir=${prefix}/include") file:print("") file:print("Name: %s", target:name()) @@ -77,10 +77,8 @@ function main(target, opt) if version then file:print("Version: %s", version) end - if not target:is_headeronly() then - file:print("Libs: %s", libs) - file:print("Libs.private: ") - end + file:print("Libs: %s", libs) + file:print("Libs.private: ") file:print("Cflags: %s", cflags) file:close() end -- cgit v1.3.1 From c6698421b4c1b93a21deb47fae9fb4b92e1b26c0 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 20 Oct 2021 22:33:15 +0800 Subject: make targetkind as upper --- xmake/modules/target/action/install/cmake_importfiles.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/target/action/install/cmake_importfiles.lua b/xmake/modules/target/action/install/cmake_importfiles.lua index c566b4471..1249c9c8b 100644 --- a/xmake/modules/target/action/install/cmake_importfiles.lua +++ b/xmake/modules/target/action/install/cmake_importfiles.lua @@ -41,7 +41,7 @@ function _get_builtinvars(target, installdir) return {TARGETNAME = target:name(), PROJECTNAME = project.name() or target:name(), TARGETFILENAME = target:targetfile() and _get_libfile(target, installdir), - TARGETKIND = target:is_headeronly() and "interface" or (target:is_shared() and "SHARED" or "STATIC"), + TARGETKIND = target:is_headeronly() and "INTERFACE" or (target:is_shared() and "SHARED" or "STATIC"), PACKAGE_VERSION = target:get("version") or "1.0.0", TARGET_PTRBYTES = target:is_arch("x86", "i386") and "4" or "8"} end -- cgit v1.3.1 From 96a18c9c00393addb18e584cc6be441d0f0d8731 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 20 Oct 2021 16:18:22 +0800 Subject: Update pkgconfig_importfiles.lua --- xmake/modules/target/action/install/pkgconfig_importfiles.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/xmake/modules/target/action/install/pkgconfig_importfiles.lua b/xmake/modules/target/action/install/pkgconfig_importfiles.lua index 942c496c7..820d7ef54 100644 --- a/xmake/modules/target/action/install/pkgconfig_importfiles.lua +++ b/xmake/modules/target/action/install/pkgconfig_importfiles.lua @@ -78,7 +78,6 @@ function main(target, opt) file:print("Version: %s", version) end file:print("Libs: %s", libs) - file:print("Libs.private: ") file:print("Cflags: %s", cflags) file:close() end -- cgit v1.3.1 From 1c861cdfb827f8a5f2fe4db414bbe200dea82009 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 21 Oct 2021 00:28:23 +0800 Subject: fix submodule --- xmake/modules/devel/git/submodule/update.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/devel/git/submodule/update.lua b/xmake/modules/devel/git/submodule/update.lua index 881663706..511684c1c 100644 --- a/xmake/modules/devel/git/submodule/update.lua +++ b/xmake/modules/devel/git/submodule/update.lua @@ -77,7 +77,7 @@ function main(opt) if longpaths_old and longpaths_old:find("false") then os.vrunv(git.program, {"config", "--global", "core.longpaths", "false"}, {curdir = opt.repodir}) else - os.vrunv(git.program, {"config", "--global", "--unset", "core.longpaths", {curdir = opt.repodir}}) + os.vrunv(git.program, {"config", "--global", "--unset", "core.longpaths"}, {curdir = opt.repodir}) end end end -- cgit v1.3.1 From bceaaa3f9f350fb5e53fc7f6c81ad1f74ef72059 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 21 Oct 2021 00:28:37 +0800 Subject: fix archlinux ci --- .github/workflows/archlinux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/archlinux.yml b/.github/workflows/archlinux.yml index 2c13dd367..c9fb04cb4 100644 --- a/.github/workflows/archlinux.yml +++ b/.github/workflows/archlinux.yml @@ -9,7 +9,7 @@ on: jobs: build: - container: archlinux:latest + container: archlinux:base-devel runs-on: ubuntu-latest concurrency: -- cgit v1.3.1 From 0614e6649733e35033f85e2e33f4bbc283382d40 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 21 Oct 2021 00:50:00 +0800 Subject: check require options --- xmake/modules/private/action/require/impl/package.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index f00d796f6..b017328db 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -161,6 +161,16 @@ function _load_require(require_str, requires_extra, parentinfo) end end + -- check require options + local extra_options = hashset.of("plat", "arch", "kind", "targetos", + "alias", "group", "system", "option", "default", "optional", "debug", + "verify", "external", "private", "build", "configs", "version") + for name, value in pairs(require_extra) do + if not extra_options:has(name) then + wprint("add_requires(\"%s\") has unknown option: {%s=%s}!", require_str, name, tostring(value)) + end + end + -- init required item local required = {} parentinfo = parentinfo or {} -- cgit v1.3.1 From 94529263aba197863bfc37c66ffba12f93b93cd6 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 21 Oct 2021 07:44:55 +0800 Subject: Update package.lua --- xmake/modules/private/action/require/impl/package.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index b017328db..5a43de562 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -162,7 +162,7 @@ function _load_require(require_str, requires_extra, parentinfo) end -- check require options - local extra_options = hashset.of("plat", "arch", "kind", "targetos", + local extra_options = hashset.of("plat", "arch", "kind", "host", "targetos", "alias", "group", "system", "option", "default", "optional", "debug", "verify", "external", "private", "build", "configs", "version") for name, value in pairs(require_extra) do -- cgit v1.3.1 From 7251eee6ab7ec54f5a052860ac28f46a02371eb9 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 21 Oct 2021 22:33:09 +0800 Subject: add find_nim --- xmake/modules/detect/tools/find_nim.lua | 52 +++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 xmake/modules/detect/tools/find_nim.lua diff --git a/xmake/modules/detect/tools/find_nim.lua b/xmake/modules/detect/tools/find_nim.lua new file mode 100644 index 000000000..ae524ddbc --- /dev/null +++ b/xmake/modules/detect/tools/find_nim.lua @@ -0,0 +1,52 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_nim.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find nim +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local nim = find_nim() +-- local nim, version = find_nim({program = "nim", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "nim", opt) + + -- find program version + local version = nil + if program and opt.version then + version = find_programver(program, opt) + end + return program, version +end -- cgit v1.3.1 From c03c36da556816137e18916dcca4517a8a10c6b7 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 21 Oct 2021 22:42:59 +0800 Subject: add nim lang --- tests/projects/nim/console/src/main | Bin 0 -> 92184 bytes tests/projects/nim/console/src/main.nim | 1 + tests/projects/nim/console/xmake.lua | 5 ++ xmake/core/tool/toolchain.lua | 4 ++ xmake/languages/nim/load.lua | 56 +++++++++++++++ xmake/languages/nim/xmake.lua | 78 +++++++++++++++++++++ xmake/modules/core/tools/nim.lua | 89 ++++++++++++++++++++++++ xmake/modules/detect/tools/nim/has_flags.lua | 98 +++++++++++++++++++++++++++ xmake/platforms/linux/xmake.lua | 2 +- xmake/platforms/macosx/xmake.lua | 2 +- xmake/platforms/windows/xmake.lua | 2 +- xmake/rules/nim/xmake.lua | 37 ++++++++++ xmake/rules/rust/build/target.lua | 7 +- xmake/toolchains/nim/xmake.lua | 38 +++++++++++ 14 files changed, 413 insertions(+), 6 deletions(-) create mode 100755 tests/projects/nim/console/src/main create mode 100644 tests/projects/nim/console/src/main.nim create mode 100644 tests/projects/nim/console/xmake.lua create mode 100644 xmake/languages/nim/load.lua create mode 100644 xmake/languages/nim/xmake.lua create mode 100644 xmake/modules/core/tools/nim.lua create mode 100644 xmake/modules/detect/tools/nim/has_flags.lua create mode 100644 xmake/rules/nim/xmake.lua create mode 100644 xmake/toolchains/nim/xmake.lua diff --git a/tests/projects/nim/console/src/main b/tests/projects/nim/console/src/main new file mode 100755 index 000000000..84f0819ac Binary files /dev/null and b/tests/projects/nim/console/src/main differ diff --git a/tests/projects/nim/console/src/main.nim b/tests/projects/nim/console/src/main.nim new file mode 100644 index 000000000..17179284f --- /dev/null +++ b/tests/projects/nim/console/src/main.nim @@ -0,0 +1 @@ +echo "hello xmake!" diff --git a/tests/projects/nim/console/xmake.lua b/tests/projects/nim/console/xmake.lua new file mode 100644 index 000000000..35bcd3792 --- /dev/null +++ b/tests/projects/nim/console/xmake.lua @@ -0,0 +1,5 @@ +add_rules("mode.debug", "mode.release") + +target("test") + set_kind("binary") + add_files("src/*.nim") diff --git a/xmake/core/tool/toolchain.lua b/xmake/core/tool/toolchain.lua index 868d05746..59e171d58 100644 --- a/xmake/core/tool/toolchain.lua +++ b/xmake/core/tool/toolchain.lua @@ -369,6 +369,10 @@ function _instance:_description(toolkind) cu = "the cuda compiler", culd = "the cuda linker", cuccbin = "the cuda host c++ compiler", + nc = "the nim compiler", + ncld = "the nim linker", + ncsh = "the nim shared library linker", + ncar = "the nim static library archiver" } self._DESCRIPTIONS = descriptions end diff --git a/xmake/languages/nim/load.lua b/xmake/languages/nim/load.lua new file mode 100644 index 000000000..1e96d7c39 --- /dev/null +++ b/xmake/languages/nim/load.lua @@ -0,0 +1,56 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file load.lua +-- + +function _get_apis() + local apis = {} + apis.values = { + -- target.add_xxx + "target.add_ncflags" + , "target.add_ldflags" + , "target.add_arflags" + , "target.add_shflags" + , "target.add_rpathdirs" -- @note do not translate path, it's usually an absolute path or contains $ORIGIN/@loader_path + -- option.add_xxx + , "option.add_ncflags" + , "option.add_ldflags" + , "option.add_arflags" + , "option.add_shflags" + , "option.add_rpathdirs" + -- toolchain.add_xxx + , "toolchain.add_ncflags" + , "toolchain.add_ldflags" + , "toolchain.add_arflags" + , "toolchain.add_shflags" + , "toolchain.add_rpathdirs" + } + apis.paths = { + -- target.add_xxx + "target.add_linkdirs" + -- option.add_xxx + , "option.add_linkdirs" + } + return apis +end + +function main() + return {apis = _get_apis()} +end + + diff --git a/xmake/languages/nim/xmake.lua b/xmake/languages/nim/xmake.lua new file mode 100644 index 000000000..a7ffab4f9 --- /dev/null +++ b/xmake/languages/nim/xmake.lua @@ -0,0 +1,78 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +language("nim") + add_rules("nim") + set_sourcekinds {nc = ".nim"} + set_sourceflags {nc = "ncflags"} + set_targetkinds {binary = "ncld", static = "ncar", shared = "ncsh"} + set_targetflags {binary = "ldflags", static = "arflags", shared = "shflags"} + set_langkinds {nim = "nc"} + set_mixingkinds("nc") + + on_load("load") + + set_nameflags { + object = { + "target.symbols" + , "target.warnings" + , "target.defines" + , "target.undefines" + , "target.optimize:check" + , "target.vectorexts:check" + } + , binary = { + "config.linkdirs" + , "target.linkdirs" + , "target.rpathdirs" + , "target.strip" + , "target.symbols" + , "toolchain.linkdirs" + , "toolchain.rpathdirs" + } + , shared = { + "config.linkdirs" + , "target.linkdirs" + , "target.strip" + , "target.symbols" + , "toolchain.linkdirs" + } + , static = { + "target.strip" + , "target.symbols" + } + } + + set_menu { + config = + { + {category = "Cross Complation Configuration/Compiler Configuration" } + , {nil, "nc", "kv", nil, "The Nim Compiler" } + + , {category = "Cross Complation Configuration/Linker Configuration" } + , {nil, "ncld", "kv", nil, "The Nim Linker" } + , {nil, "ncar", "kv", nil, "The Nim Static Library Archiver" } + , {nil, "ncsh", "kv", nil, "The Nim Shared Library Linker" } + + , {category = "Cross Complation Configuration/Builtin Flags Configuration" } + , {nil, "linkdirs", "kv", nil, "The Link Search Directories" } + } + } + diff --git a/xmake/modules/core/tools/nim.lua b/xmake/modules/core/tools/nim.lua new file mode 100644 index 000000000..4cee95c95 --- /dev/null +++ b/xmake/modules/core/tools/nim.lua @@ -0,0 +1,89 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file nim.lua +-- + +-- imports +import("core.base.option") +import("core.project.config") +import("core.project.project") + +-- init it +function init(self) + + -- init arflags + self:set("ncarflags", "--app:staticlib") + + -- init shflags + self:set("ncshflags", "--app:lib") +end + +-- make the define flag +function nf_define(self, macro) + return "--define:" .. macro +end + +-- make the undefine flag +function nf_undefine(self, macro) + return "--undef:" .. macro +end + +-- make the optimize flag +function nf_optimize(self, level) + local maps = + { + none = "--opt:none" + , fast = "--opt:speed" + , faster = "--opt:speed" + , fastest = "--opt:speed" + , smallest = "--opt:size" + , aggressive = "--opt:speed" + } + return maps[level] +end + +-- make the symbol flag +function nf_symbol(self, level) + local maps = + { + debug = "--stackTrace:on" + } + return maps[level] +end + +-- make the link flag +function nf_link(self, lib) + return "--passL:" .. lib +end + +-- make the linkdir flag +function nf_linkdir(self, dir) + return {"-L" .. dir} +end + +-- make the build arguments list +function buildargv(self, sourcefiles, targetkind, targetfile, flags) + return self:program(), table.join(flags, "c", "-o:" .. targetfile, sourcefiles) +end + +-- build the target file +function build(self, sourcefiles, targetkind, targetfile, flags) + os.mkdir(path.directory(targetfile)) + os.runv(buildargv(self, sourcefiles, targetkind, targetfile, flags)) +end + diff --git a/xmake/modules/detect/tools/nim/has_flags.lua b/xmake/modules/detect/tools/nim/has_flags.lua new file mode 100644 index 000000000..2fe415241 --- /dev/null +++ b/xmake/modules/detect/tools/nim/has_flags.lua @@ -0,0 +1,98 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file has_flags.lua +-- + +-- imports +import("core.cache.detectcache") + +-- try running +function _try_running(...) + + local argv = {...} + local errors = nil + return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors +end + +-- attempt to check it from the argument list +function _check_from_arglist(flags, opt) + + -- only one flag? + if #flags > 1 then + return + end + + -- make cache key + local key = "detect.tools.nim.has_flags" + + -- make allflags key + local flagskey = opt.program .. "_" .. (opt.programver or "") + + -- get all allflags from argument list + local allflags = detectcache:get2(key, flagskey) + if not allflags then + + -- get argument list + allflags = {} + local arglist = os.iorunv(opt.program, {"--help"}) + if arglist then + for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do + allflags[arg] = true + end + end + + -- save cache + detectcache:set2(key, flagskey, allflags) + detectcache:save() + end + return allflags[flags[1]] +end + +-- try running to check flags +function _check_try_running(flags, opt) + + -- make an stub source file + local sourcefile = path.join(os.tmpdir(), "detect", "nim_has_flags.nim") + if not os.isfile(sourcefile) then + io.writefile(sourcefile, "echo \"hello\"") + end + + -- check it + local binaryfile = os.tmpfile() + local ok, errors = _try_running(opt.program, table.join("c", flags, "-o:" .. binaryfile, sourcefile)) + os.tryrm(binaryfile) + return ok, errors +end + +-- has_flags(flags)? +-- +-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|rc|dc|mm|mxx]"} +-- +-- @return true or false +-- +function main(flags, opt) + + -- attempt to check it from the argument list + if _check_from_arglist(flags, opt) then + return true + end + + -- try running to check it + return _check_try_running(flags, opt) +end + diff --git a/xmake/platforms/linux/xmake.lua b/xmake/platforms/linux/xmake.lua index f855903f3..ab7c71f75 100644 --- a/xmake/platforms/linux/xmake.lua +++ b/xmake/platforms/linux/xmake.lua @@ -40,7 +40,7 @@ platform("linux") set_installdir("/usr/local") -- set toolchains - set_toolchains("envs", "cross", "gcc", "clang", "yasm", "nasm", "fasm", "cuda", "dlang", "go", "rust", "gfortran", "zig", "fpc") + set_toolchains("envs", "cross", "gcc", "clang", "yasm", "nasm", "fasm", "cuda", "dlang", "go", "rust", "gfortran", "zig", "fpc", "nim") -- set menu set_menu { diff --git a/xmake/platforms/macosx/xmake.lua b/xmake/platforms/macosx/xmake.lua index 792a5cad3..8571a13c4 100644 --- a/xmake/platforms/macosx/xmake.lua +++ b/xmake/platforms/macosx/xmake.lua @@ -40,7 +40,7 @@ platform("macosx") set_installdir("/usr/local") -- set toolchains - set_toolchains("envs", "xcode", "clang", "gcc", "yasm", "nasm", "cuda", "dlang", "rust", "go", "gfortran", "zig", "fpc") + set_toolchains("envs", "xcode", "clang", "gcc", "yasm", "nasm", "cuda", "dlang", "rust", "go", "gfortran", "zig", "fpc", "nim") -- set menu set_menu { diff --git a/xmake/platforms/windows/xmake.lua b/xmake/platforms/windows/xmake.lua index caf707d50..f7687f44b 100644 --- a/xmake/platforms/windows/xmake.lua +++ b/xmake/platforms/windows/xmake.lua @@ -38,7 +38,7 @@ platform("windows") set_formats("symbol", "$(name).pdb") -- set toolchains - set_toolchains("msvc", "clang", "yasm", "nasm", "cuda", "dlang", "rust", "go", "gfortran", "zig", "fpc") + set_toolchains("msvc", "clang", "yasm", "nasm", "cuda", "dlang", "rust", "go", "gfortran", "zig", "fpc", "nim") -- set menu set_menu { diff --git a/xmake/rules/nim/xmake.lua b/xmake/rules/nim/xmake.lua new file mode 100644 index 000000000..7d65c9c12 --- /dev/null +++ b/xmake/rules/nim/xmake.lua @@ -0,0 +1,37 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +-- define rule: nim.build +rule("nim.build") + set_sourcekinds("nc") + on_load(function (target) + local cachedir = path.join(target:autogendir(), "nimcache") + target:add("ncflags", "--nimcache:" .. cachedir, {force = true}) + end) + on_build("build.target") + +-- define rule: nim +rule("nim") + + -- add build rules + add_deps("nim.build") + + -- inherit links and linkdirs of all dependent targets by default + add_deps("utils.inherit.links") diff --git a/xmake/rules/rust/build/target.lua b/xmake/rules/rust/build/target.lua index a1f34beff..5f0167693 100644 --- a/xmake/rules/rust/build/target.lua +++ b/xmake/rules/rust/build/target.lua @@ -76,10 +76,11 @@ end function main(target, opt) -- @note only support one source kind! - for _, sourcebatch in pairs(target:sourcebatches()) do - if sourcebatch.sourcekind == "rc" then + local sourcebatches = target:sourcebatches() + if sourcebatches then + local sourcebatch = sourcebatches["rust.build"] + if sourcebatch then build_sourcefiles(target, sourcebatch, opt) - break end end end diff --git a/xmake/toolchains/nim/xmake.lua b/xmake/toolchains/nim/xmake.lua new file mode 100644 index 000000000..660f63f56 --- /dev/null +++ b/xmake/toolchains/nim/xmake.lua @@ -0,0 +1,38 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +-- define toolchain +toolchain("nim") + + -- set homepage + set_homepage("https://nim-lang.org/") + set_description("Nim Programming Language Compiler") + + -- set toolset + set_toolset("nc", "$(env NC)", "nim") + set_toolset("ncld", "$(env NC)", "nim") + set_toolset("ncsh", "$(env NC)", "nim") + set_toolset("ncar", "$(env NC)", "nim") + + -- on load + on_load(function (toolchain) + toolchain:set("ncshflags", "") + toolchain:set("ncldflags", "") + end) -- cgit v1.3.1 From f0d5c879cadf8809566aa7e607c55252f6e471d5 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 21 Oct 2021 22:57:16 +0800 Subject: support static and shared library for nim --- tests/projects/nim/shared_library/src/foo.nim | 5 +++ tests/projects/nim/shared_library/src/main.nim | 4 +++ tests/projects/nim/shared_library/xmake.lua | 12 +++++++ tests/projects/nim/static_library/src/bar.nim | 5 +++ tests/projects/nim/static_library/src/foo.nim | 8 +++++ tests/projects/nim/static_library/src/main.nim | 5 +++ tests/projects/nim/static_library/xmake.lua | 12 +++++++ xmake/languages/nim/xmake.lua | 11 ++++++- xmake/modules/core/tools/nim.lua | 45 +++++++++++++++++++++++--- 9 files changed, 101 insertions(+), 6 deletions(-) create mode 100644 tests/projects/nim/shared_library/src/foo.nim create mode 100644 tests/projects/nim/shared_library/src/main.nim create mode 100644 tests/projects/nim/shared_library/xmake.lua create mode 100644 tests/projects/nim/static_library/src/bar.nim create mode 100644 tests/projects/nim/static_library/src/foo.nim create mode 100644 tests/projects/nim/static_library/src/main.nim create mode 100644 tests/projects/nim/static_library/xmake.lua diff --git a/tests/projects/nim/shared_library/src/foo.nim b/tests/projects/nim/shared_library/src/foo.nim new file mode 100644 index 000000000..4a3e920ff --- /dev/null +++ b/tests/projects/nim/shared_library/src/foo.nim @@ -0,0 +1,5 @@ +proc fibonacci(n: int): int {.cdecl, exportc, dynlib.} = + if n < 2: + result = n + else: + result = fibonacci(n - 1) + (n - 2).fibonacci diff --git a/tests/projects/nim/shared_library/src/main.nim b/tests/projects/nim/shared_library/src/main.nim new file mode 100644 index 000000000..c473c5401 --- /dev/null +++ b/tests/projects/nim/shared_library/src/main.nim @@ -0,0 +1,4 @@ +proc fibonacci(n: int): int {.cdecl, importc} + +echo fibonacci(2) + diff --git a/tests/projects/nim/shared_library/xmake.lua b/tests/projects/nim/shared_library/xmake.lua new file mode 100644 index 000000000..b560961d6 --- /dev/null +++ b/tests/projects/nim/shared_library/xmake.lua @@ -0,0 +1,12 @@ +add_rules("mode.debug", "mode.release") + +target("foo") + set_kind("shared") + add_files("src/foo.nim") + +target("test") + set_kind("binary") + add_deps("foo") + add_files("src/main.nim") + + diff --git a/tests/projects/nim/static_library/src/bar.nim b/tests/projects/nim/static_library/src/bar.nim new file mode 100644 index 000000000..911a3cc85 --- /dev/null +++ b/tests/projects/nim/static_library/src/bar.nim @@ -0,0 +1,5 @@ +proc bar(n: int): int {.cdecl, exportc} = + if n < 2: + result = n + else: + result = bar(n - 1) + (n - 2).bar diff --git a/tests/projects/nim/static_library/src/foo.nim b/tests/projects/nim/static_library/src/foo.nim new file mode 100644 index 000000000..ba0fcad5b --- /dev/null +++ b/tests/projects/nim/static_library/src/foo.nim @@ -0,0 +1,8 @@ +import bar + +proc foo(n: int): int {.cdecl, exportc} = + if n < 2: + result = n + else: + result = foo(n - 1) + (n - 2).foo + diff --git a/tests/projects/nim/static_library/src/main.nim b/tests/projects/nim/static_library/src/main.nim new file mode 100644 index 000000000..a91ba0614 --- /dev/null +++ b/tests/projects/nim/static_library/src/main.nim @@ -0,0 +1,5 @@ +proc foo(n: int): int {.cdecl, importc} +proc bar(n: int): int {.cdecl, importc} + +echo foo(2) +echo bar(2) diff --git a/tests/projects/nim/static_library/xmake.lua b/tests/projects/nim/static_library/xmake.lua new file mode 100644 index 000000000..7ef38314a --- /dev/null +++ b/tests/projects/nim/static_library/xmake.lua @@ -0,0 +1,12 @@ +add_rules("mode.debug", "mode.release") + +target("foo") + set_kind("static") + add_files("src/foo.nim") + +target("test") + set_kind("binary") + add_deps("foo") + add_files("src/main.nim") + + diff --git a/xmake/languages/nim/xmake.lua b/xmake/languages/nim/xmake.lua index a7ffab4f9..44deef165 100644 --- a/xmake/languages/nim/xmake.lua +++ b/xmake/languages/nim/xmake.lua @@ -31,12 +31,15 @@ language("nim") set_nameflags { object = { - "target.symbols" + "config.includedirs" + , "target.symbols" , "target.warnings" , "target.defines" , "target.undefines" , "target.optimize:check" , "target.vectorexts:check" + , "target.includedirs" + , "toolchain.includedirs" } , binary = { "config.linkdirs" @@ -46,6 +49,9 @@ language("nim") , "target.symbols" , "toolchain.linkdirs" , "toolchain.rpathdirs" + , "config.links" + , "target.links" + , "toolchain.links" } , shared = { "config.linkdirs" @@ -53,6 +59,9 @@ language("nim") , "target.strip" , "target.symbols" , "toolchain.linkdirs" + , "config.links" + , "target.links" + , "toolchain.links" } , static = { "target.strip" diff --git a/xmake/modules/core/tools/nim.lua b/xmake/modules/core/tools/nim.lua index 4cee95c95..20ec40353 100644 --- a/xmake/modules/core/tools/nim.lua +++ b/xmake/modules/core/tools/nim.lua @@ -24,13 +24,30 @@ import("core.project.config") import("core.project.project") -- init it +-- +-- @see https://nim-lang.org/docs/nimc.html function init(self) -- init arflags - self:set("ncarflags", "--app:staticlib") + self:set("ncarflags", "--app:staticlib", "--noMain") -- init shflags - self:set("ncshflags", "--app:lib") + self:set("ncshflags", "--app:lib", "--noMain") +end + +-- make the warning flag +function nf_warning(self, level) + local maps = + { + none = "--warning:X:off" + , less = "--warning:X:on" + , more = "--warning:X:on" + , all = "--warning:X:on" + , allextra = "--warning:X:on" + , everything = "--warning:X:on" + , error = "--warningAsError:X:on" + } + return maps[level] end -- make the define flag @@ -66,19 +83,37 @@ function nf_symbol(self, level) return maps[level] end +-- make the includedir flag +function nf_includedir(self, dir) + return {"--passC:-I" .. path.translate(dir)} +end + -- make the link flag function nf_link(self, lib) - return "--passL:" .. lib + return "--passL:-l" .. lib end -- make the linkdir flag function nf_linkdir(self, dir) - return {"-L" .. dir} + return {"--passL:-L" .. path.translate(dir)} end -- make the build arguments list function buildargv(self, sourcefiles, targetkind, targetfile, flags) - return self:program(), table.join(flags, "c", "-o:" .. targetfile, sourcefiles) + local flags_extra = {} + if targetkind == "static" then + -- fix multiple definition of `NimMain', it is only workaround solution + -- we need to wait for this problem to be resolved + -- + -- @see https://github.com/nim-lang/Nim/issues/15955 + local uniquekey = hash.uuid(targetfile):split("-", {plain = true})[1] + table.insert(flags_extra, "--passC:-DNimMain=NimMain_" .. uniquekey) + table.insert(flags_extra, "--passC:-DNimMainInner=NimMainInner_" .. uniquekey) + table.insert(flags_extra, "--passC:-DNimMainModule=NimMainModule_" .. uniquekey) + table.insert(flags_extra, "--passC:-DPreMain=PreMain_" .. uniquekey) + table.insert(flags_extra, "--passC:-DPreMainInner=PreMainInner_" .. uniquekey) + end + return self:program(), table.join("c", flags, flags_extra, "-o:" .. targetfile, sourcefiles) end -- build the target file -- cgit v1.3.1 From 6af62c9f179ad500ae8a0a6c1f3607f77839dc92 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 21 Oct 2021 22:57:37 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ README.md | 2 ++ README_zh.md | 2 ++ 3 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2da4954c..ba059a5c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * [#1747](https://github.com/xmake-io/xmake/issues/1747): Add `set_kind("headeronly")` for target to install files for headeronly library * [#1019](https://github.com/xmake-io/xmake/issues/1019): Support Unity build * [#1438](https://github.com/xmake-io/xmake/issues/1438): Support code amalgamation, `xmake l cli.amalgamate` +* [#1765](https://github.com/xmake-io/xmake/issues/1756): Support nim language ### Changes @@ -1114,6 +1115,7 @@ * [#1747](https://github.com/xmake-io/xmake/issues/1747): 添加 `set_kind("headeronly")` 更好的处理 headeronly 库的安装 * [#1019](https://github.com/xmake-io/xmake/issues/1019): 支持 Unity build * [#1438](https://github.com/xmake-io/xmake/issues/1438): 增加 `xmake l cli.amalgamate` 命令支持代码合并 +* [#1765](https://github.com/xmake-io/xmake/issues/1756): 支持 nim 语言 ### 改进 diff --git a/README.md b/README.md index 12ffb7438..741e90823 100644 --- a/README.md +++ b/README.md @@ -225,6 +225,7 @@ ifort Intel Fortran Compiler muslcc The musl-based cross-compilation toolchain fpc Free Pascal Programming Language Compiler wasi WASI-enabled WebAssembly C/C++ toolchain +nim Nim Programming Language Compiler ``` ## Supported Languages @@ -242,6 +243,7 @@ wasi WASI-enabled WebAssembly C/C++ toolchain * Zig * Vala * Pascal +* Nim ## Supported Features diff --git a/README_zh.md b/README_zh.md index d00577c2d..8b40da549 100644 --- a/README_zh.md +++ b/README_zh.md @@ -233,6 +233,7 @@ ifort Intel Fortran Compiler muslcc The musl-based cross-compilation toolchain fpc Free Pascal Programming Language Compiler wasi WASI-enabled WebAssembly C/C++ toolchain +nim Nim Programming Language Compiler ``` ## 支持语言 @@ -249,6 +250,7 @@ wasi WASI-enabled WebAssembly C/C++ toolchain * Zig * Vala * Pascal +* Nim ## 支持特性 -- cgit v1.3.1 From efa63d26a7d3c5a76344141150771fe76137ef3a Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 21 Oct 2021 22:58:58 +0800 Subject: add nim templates --- tests/projects/nim/shared_library/src/foo.nim | 4 ++-- tests/projects/nim/shared_library/src/main.nim | 4 ++-- xmake/templates/nim/console/project/src/main | Bin 0 -> 92184 bytes xmake/templates/nim/console/project/src/main.nim | 1 + xmake/templates/nim/console/project/xmake.lua | 7 +++++++ xmake/templates/nim/console/template.lua | 2 ++ xmake/templates/nim/shared/project/src/foo.nim | 6 ++++++ xmake/templates/nim/shared/project/src/main.nim | 3 +++ xmake/templates/nim/shared/project/xmake.lua | 14 ++++++++++++++ xmake/templates/nim/shared/template.lua | 2 ++ xmake/templates/nim/static/project/src/foo.nim | 6 ++++++ xmake/templates/nim/static/project/src/main.nim | 3 +++ xmake/templates/nim/static/project/xmake.lua | 14 ++++++++++++++ xmake/templates/nim/static/template.lua | 2 ++ xmake/templates/rust/console/project/xmake.lua | 6 ------ 15 files changed, 64 insertions(+), 10 deletions(-) create mode 100755 xmake/templates/nim/console/project/src/main create mode 100644 xmake/templates/nim/console/project/src/main.nim create mode 100644 xmake/templates/nim/console/project/xmake.lua create mode 100644 xmake/templates/nim/console/template.lua create mode 100644 xmake/templates/nim/shared/project/src/foo.nim create mode 100644 xmake/templates/nim/shared/project/src/main.nim create mode 100644 xmake/templates/nim/shared/project/xmake.lua create mode 100644 xmake/templates/nim/shared/template.lua create mode 100644 xmake/templates/nim/static/project/src/foo.nim create mode 100644 xmake/templates/nim/static/project/src/main.nim create mode 100644 xmake/templates/nim/static/project/xmake.lua create mode 100644 xmake/templates/nim/static/template.lua diff --git a/tests/projects/nim/shared_library/src/foo.nim b/tests/projects/nim/shared_library/src/foo.nim index 4a3e920ff..db968d723 100644 --- a/tests/projects/nim/shared_library/src/foo.nim +++ b/tests/projects/nim/shared_library/src/foo.nim @@ -1,5 +1,5 @@ -proc fibonacci(n: int): int {.cdecl, exportc, dynlib.} = +proc foo(n: int): int {.cdecl, exportc, dynlib.} = if n < 2: result = n else: - result = fibonacci(n - 1) + (n - 2).fibonacci + result = foo(n - 1) + (n - 2).foo diff --git a/tests/projects/nim/shared_library/src/main.nim b/tests/projects/nim/shared_library/src/main.nim index c473c5401..81a64bda0 100644 --- a/tests/projects/nim/shared_library/src/main.nim +++ b/tests/projects/nim/shared_library/src/main.nim @@ -1,4 +1,4 @@ -proc fibonacci(n: int): int {.cdecl, importc} +proc foo(n: int): int {.cdecl, importc} -echo fibonacci(2) +echo foo(2) diff --git a/xmake/templates/nim/console/project/src/main b/xmake/templates/nim/console/project/src/main new file mode 100755 index 000000000..84f0819ac Binary files /dev/null and b/xmake/templates/nim/console/project/src/main differ diff --git a/xmake/templates/nim/console/project/src/main.nim b/xmake/templates/nim/console/project/src/main.nim new file mode 100644 index 000000000..17179284f --- /dev/null +++ b/xmake/templates/nim/console/project/src/main.nim @@ -0,0 +1 @@ +echo "hello xmake!" diff --git a/xmake/templates/nim/console/project/xmake.lua b/xmake/templates/nim/console/project/xmake.lua new file mode 100644 index 000000000..1aa5639db --- /dev/null +++ b/xmake/templates/nim/console/project/xmake.lua @@ -0,0 +1,7 @@ +add_rules("mode.debug", "mode.release") + +target("${TARGETNAME}") + set_kind("binary") + add_files("src/*.nim") + +${FAQ} diff --git a/xmake/templates/nim/console/template.lua b/xmake/templates/nim/console/template.lua new file mode 100644 index 000000000..ed2e13b57 --- /dev/null +++ b/xmake/templates/nim/console/template.lua @@ -0,0 +1,2 @@ +template("console") + add_configfiles("xmake.lua") diff --git a/xmake/templates/nim/shared/project/src/foo.nim b/xmake/templates/nim/shared/project/src/foo.nim new file mode 100644 index 000000000..cde4de7ca --- /dev/null +++ b/xmake/templates/nim/shared/project/src/foo.nim @@ -0,0 +1,6 @@ +proc foo(n: int): int {.cdecl, exportc, dynlib.} = + if n < 2: + result = n + else: + result = foo(n - 1) + (n - 2).foo + diff --git a/xmake/templates/nim/shared/project/src/main.nim b/xmake/templates/nim/shared/project/src/main.nim new file mode 100644 index 000000000..1be3abe69 --- /dev/null +++ b/xmake/templates/nim/shared/project/src/main.nim @@ -0,0 +1,3 @@ +proc foo(n: int): int {.cdecl, importc} + +echo foo(2) diff --git a/xmake/templates/nim/shared/project/xmake.lua b/xmake/templates/nim/shared/project/xmake.lua new file mode 100644 index 000000000..e2d380ac6 --- /dev/null +++ b/xmake/templates/nim/shared/project/xmake.lua @@ -0,0 +1,14 @@ +add_rules("mode.debug", "mode.release") + +target("${TARGETNAME}") + set_kind("shared") + add_files("src/foo.nim") + +target("${TARGETNAME}_demo") + set_kind("binary") + add_deps("${TARGETNAME}") + add_files("src/main.nim") + +${FAQ} + + diff --git a/xmake/templates/nim/shared/template.lua b/xmake/templates/nim/shared/template.lua new file mode 100644 index 000000000..d7ec5bae4 --- /dev/null +++ b/xmake/templates/nim/shared/template.lua @@ -0,0 +1,2 @@ +template("shared") + add_configfiles("xmake.lua") diff --git a/xmake/templates/nim/static/project/src/foo.nim b/xmake/templates/nim/static/project/src/foo.nim new file mode 100644 index 000000000..be0904262 --- /dev/null +++ b/xmake/templates/nim/static/project/src/foo.nim @@ -0,0 +1,6 @@ +proc foo(n: int): int {.cdecl, exportc} = + if n < 2: + result = n + else: + result = foo(n - 1) + (n - 2).foo + diff --git a/xmake/templates/nim/static/project/src/main.nim b/xmake/templates/nim/static/project/src/main.nim new file mode 100644 index 000000000..1be3abe69 --- /dev/null +++ b/xmake/templates/nim/static/project/src/main.nim @@ -0,0 +1,3 @@ +proc foo(n: int): int {.cdecl, importc} + +echo foo(2) diff --git a/xmake/templates/nim/static/project/xmake.lua b/xmake/templates/nim/static/project/xmake.lua new file mode 100644 index 000000000..cf70acb9e --- /dev/null +++ b/xmake/templates/nim/static/project/xmake.lua @@ -0,0 +1,14 @@ +add_rules("mode.debug", "mode.release") + +target("${TARGETNAME}") + set_kind("static") + add_files("src/foo.nim") + +target("${TARGETNAME}_demo") + set_kind("binary") + add_deps("${TARGETNAME}") + add_files("src/main.nim") + +${FAQ} + + diff --git a/xmake/templates/nim/static/template.lua b/xmake/templates/nim/static/template.lua new file mode 100644 index 000000000..abfe91a4b --- /dev/null +++ b/xmake/templates/nim/static/template.lua @@ -0,0 +1,2 @@ +template("static") + add_configfiles("xmake.lua") diff --git a/xmake/templates/rust/console/project/xmake.lua b/xmake/templates/rust/console/project/xmake.lua index 7a363c461..5c3f06804 100644 --- a/xmake/templates/rust/console/project/xmake.lua +++ b/xmake/templates/rust/console/project/xmake.lua @@ -1,13 +1,7 @@ --- add modes: debug and release add_rules("mode.debug", "mode.release") --- add target target("${TARGETNAME}") - - -- set kind set_kind("binary") - - -- add files add_files("src/*.rs") ${FAQ} -- cgit v1.3.1 From cc00b3574b5892f191cef90f81acd3c27b548ff8 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 21 Oct 2021 23:05:45 +0800 Subject: improve tests --- tests/projects/nim/console/xmake.lua | 2 +- tests/projects/nim/console_with_c/src/foo.c | 3 +++ tests/projects/nim/console_with_c/src/main | Bin 0 -> 92184 bytes tests/projects/nim/console_with_c/src/main.nim | 3 +++ tests/projects/nim/console_with_c/xmake.lua | 10 ++++++++++ xmake/templates/nim/console/project/xmake.lua | 4 ++-- 6 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 tests/projects/nim/console_with_c/src/foo.c create mode 100755 tests/projects/nim/console_with_c/src/main create mode 100644 tests/projects/nim/console_with_c/src/main.nim create mode 100644 tests/projects/nim/console_with_c/xmake.lua diff --git a/tests/projects/nim/console/xmake.lua b/tests/projects/nim/console/xmake.lua index 35bcd3792..40459a274 100644 --- a/tests/projects/nim/console/xmake.lua +++ b/tests/projects/nim/console/xmake.lua @@ -2,4 +2,4 @@ add_rules("mode.debug", "mode.release") target("test") set_kind("binary") - add_files("src/*.nim") + add_files("src/main.nim") diff --git a/tests/projects/nim/console_with_c/src/foo.c b/tests/projects/nim/console_with_c/src/foo.c new file mode 100644 index 000000000..7e3f727d6 --- /dev/null +++ b/tests/projects/nim/console_with_c/src/foo.c @@ -0,0 +1,3 @@ +int foo(int n) { + return n; +} diff --git a/tests/projects/nim/console_with_c/src/main b/tests/projects/nim/console_with_c/src/main new file mode 100755 index 000000000..84f0819ac Binary files /dev/null and b/tests/projects/nim/console_with_c/src/main differ diff --git a/tests/projects/nim/console_with_c/src/main.nim b/tests/projects/nim/console_with_c/src/main.nim new file mode 100644 index 000000000..1be3abe69 --- /dev/null +++ b/tests/projects/nim/console_with_c/src/main.nim @@ -0,0 +1,3 @@ +proc foo(n: int): int {.cdecl, importc} + +echo foo(2) diff --git a/tests/projects/nim/console_with_c/xmake.lua b/tests/projects/nim/console_with_c/xmake.lua new file mode 100644 index 000000000..c2d067cd6 --- /dev/null +++ b/tests/projects/nim/console_with_c/xmake.lua @@ -0,0 +1,10 @@ +add_rules("mode.debug", "mode.release") + +target("foo") + set_kind("static") + add_files("src/*.c") + +target("test") + set_kind("binary") + add_deps("foo") + add_files("src/main.nim") diff --git a/xmake/templates/nim/console/project/xmake.lua b/xmake/templates/nim/console/project/xmake.lua index 1aa5639db..f41148c2f 100644 --- a/xmake/templates/nim/console/project/xmake.lua +++ b/xmake/templates/nim/console/project/xmake.lua @@ -2,6 +2,6 @@ add_rules("mode.debug", "mode.release") target("${TARGETNAME}") set_kind("binary") - add_files("src/*.nim") - + add_files("src/main.nim") + ${FAQ} -- cgit v1.3.1 From 3c5a1cc28b28bab2f714dd4ec163a6f2b1f61cae Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 21 Oct 2021 23:06:50 +0800 Subject: add more nim tests --- tests/projects/nim/console_with_c/src/main | Bin 92184 -> 0 bytes tests/projects/nim/console_with_packages/src/main.nim | 3 +++ tests/projects/nim/console_with_packages/xmake.lua | 8 ++++++++ 3 files changed, 11 insertions(+) delete mode 100755 tests/projects/nim/console_with_c/src/main create mode 100644 tests/projects/nim/console_with_packages/src/main.nim create mode 100644 tests/projects/nim/console_with_packages/xmake.lua diff --git a/tests/projects/nim/console_with_c/src/main b/tests/projects/nim/console_with_c/src/main deleted file mode 100755 index 84f0819ac..000000000 Binary files a/tests/projects/nim/console_with_c/src/main and /dev/null differ diff --git a/tests/projects/nim/console_with_packages/src/main.nim b/tests/projects/nim/console_with_packages/src/main.nim new file mode 100644 index 000000000..a3368303a --- /dev/null +++ b/tests/projects/nim/console_with_packages/src/main.nim @@ -0,0 +1,3 @@ +proc zlibVersion(): cstring {.cdecl, importc} + +echo zlibVersion() diff --git a/tests/projects/nim/console_with_packages/xmake.lua b/tests/projects/nim/console_with_packages/xmake.lua new file mode 100644 index 000000000..924ee9632 --- /dev/null +++ b/tests/projects/nim/console_with_packages/xmake.lua @@ -0,0 +1,8 @@ +add_rules("mode.debug", "mode.release") + +add_requires("zlib") + +target("test") + set_kind("binary") + add_files("src/main.nim") + add_packages("zlib") -- cgit v1.3.1 From a8fd397c2d1543140b285011fbebf5a9041efeb5 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 21 Oct 2021 17:06:15 +0800 Subject: Update nim.lua --- xmake/modules/core/tools/nim.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xmake/modules/core/tools/nim.lua b/xmake/modules/core/tools/nim.lua index 20ec40353..bab8b458a 100644 --- a/xmake/modules/core/tools/nim.lua +++ b/xmake/modules/core/tools/nim.lua @@ -65,11 +65,11 @@ function nf_optimize(self, level) local maps = { none = "--opt:none" - , fast = "--opt:speed" - , faster = "--opt:speed" - , fastest = "--opt:speed" - , smallest = "--opt:size" - , aggressive = "--opt:speed" + , fast = "-d:release" + , faster = "-d:release" + , fastest = "-d:release" + , smallest = {"-d:release", "--opt:size"} + , aggressive = "-d:danger" } return maps[level] end -- cgit v1.3.1 From a48901eab4c530e440b9fcbd339ad0c83ec9ed1f Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 21 Oct 2021 23:55:45 +0800 Subject: add missing build files --- xmake/rules/nim/build/target.lua | 86 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 xmake/rules/nim/build/target.lua diff --git a/xmake/rules/nim/build/target.lua b/xmake/rules/nim/build/target.lua new file mode 100644 index 000000000..79e271063 --- /dev/null +++ b/xmake/rules/nim/build/target.lua @@ -0,0 +1,86 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file target.lua +-- + +-- imports +import("core.base.option") +import("core.base.hashset") +import("core.tool.compiler") +import("core.project.depend") +import("utils.progress") + +-- build the source files +function build_sourcefiles(target, sourcebatch, opt) + + -- get the target file + local targetfile = target:targetfile() + + -- get source files and kind + local sourcefiles = sourcebatch.sourcefiles + local sourcekind = sourcebatch.sourcekind + + -- get depend file + local dependfile = target:dependfile(targetfile) + + -- load compiler + local compinst = compiler.load(sourcekind, {target = target}) + + -- get compile flags + local compflags = compinst:compflags({target = target}) + + -- load dependent info + local dependinfo = option.get("rebuild") and {} or (depend.load(dependfile) or {}) + + -- need build this object? + local depvalues = {compinst:program(), compflags} + if not depend.is_changed(dependinfo, {lastmtime = os.mtime(targetfile), values = depvalues}) then + return + end + + -- trace progress into + progress.show(opt.progress, "${color.build.target}linking.$(mode) %s", path.filename(targetfile)) + + -- trace verbose info + vprint(compinst:buildcmd(sourcefiles, targetfile, {target = target, compflags = compflags})) + + -- flush io buffer to update progress info + io.flush() + + -- compile it + dependinfo.files = {} + assert(compinst:build(sourcefiles, targetfile, {target = target, dependinfo = dependinfo, compflags = compflags})) + + -- update files and values to the dependent file + dependinfo.values = depvalues + table.join2(dependinfo.files, sourcefiles) + depend.save(dependinfo, dependfile) +end + +-- build target +function main(target, opt) + + -- @note only support one source kind! + local sourcebatches = target:sourcebatches() + if sourcebatches then + local sourcebatch = sourcebatches["nim.build"] + if sourcebatch then + build_sourcefiles(target, sourcebatch, opt) + end + end +end -- cgit v1.3.1 From 57891fca57a7be845cd02a947e73567b9d437cc4 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 21 Oct 2021 23:56:42 +0800 Subject: add debug symbol for nim --- xmake/modules/core/tools/nim.lua | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/xmake/modules/core/tools/nim.lua b/xmake/modules/core/tools/nim.lua index bab8b458a..b76fcb4ea 100644 --- a/xmake/modules/core/tools/nim.lua +++ b/xmake/modules/core/tools/nim.lua @@ -78,11 +78,20 @@ end function nf_symbol(self, level) local maps = { - debug = "--stackTrace:on" + debug = "--debugger:native" } return maps[level] end +-- make the strip flag +function nf_strip(self, level) + if is_plat("linux", "macosx", "bsd") then + if level == "debug" or level == "all" then + return "--passL:-s" + end + end +end + -- make the includedir flag function nf_includedir(self, dir) return {"--passC:-I" .. path.translate(dir)} -- cgit v1.3.1 From 72f482c4d675e4e82b6d37c10428de47f25d9b45 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 22 Oct 2021 00:33:40 +0800 Subject: use vcc for nim/windows --- xmake/languages/nim/xmake.lua | 6 +++--- xmake/toolchains/nim/xmake.lua | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/xmake/languages/nim/xmake.lua b/xmake/languages/nim/xmake.lua index 44deef165..d68bec867 100644 --- a/xmake/languages/nim/xmake.lua +++ b/xmake/languages/nim/xmake.lua @@ -73,15 +73,15 @@ language("nim") config = { {category = "Cross Complation Configuration/Compiler Configuration" } - , {nil, "nc", "kv", nil, "The Nim Compiler" } + , {nil, "nc", "kv", nil, "The Nim Compiler" } , {category = "Cross Complation Configuration/Linker Configuration" } , {nil, "ncld", "kv", nil, "The Nim Linker" } , {nil, "ncar", "kv", nil, "The Nim Static Library Archiver" } , {nil, "ncsh", "kv", nil, "The Nim Shared Library Linker" } - , {category = "Cross Complation Configuration/Builtin Flags Configuration" } - , {nil, "linkdirs", "kv", nil, "The Link Search Directories" } + , {category = "Cross Complation Configuration/Builtin Flags Configuration" } + , {nil, "linkdirs", "kv", nil, "The Link Search Directories" } } } diff --git a/xmake/toolchains/nim/xmake.lua b/xmake/toolchains/nim/xmake.lua index 660f63f56..598073abd 100644 --- a/xmake/toolchains/nim/xmake.lua +++ b/xmake/toolchains/nim/xmake.lua @@ -33,6 +33,9 @@ toolchain("nim") -- on load on_load(function (toolchain) + if toolchain:is_plat("windows") then + toolchain:set("ncflags", "--cc:vcc") + end toolchain:set("ncshflags", "") toolchain:set("ncldflags", "") end) -- cgit v1.3.1 From 07a58ccc42a8a752cecb895254238baae9abdd50 Mon Sep 17 00:00:00 2001 From: goiabae Date: Fri, 22 Oct 2021 00:26:59 -0300 Subject: added xbps as pm option --- scripts/get.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/get.sh b/scripts/get.sh index f64ff8041..f7ef65acf 100755 --- a/scripts/get.sh +++ b/scripts/get.sh @@ -156,9 +156,11 @@ install_tools() { emerge -V >/dev/null 2>&1 && $sudoprefix emerge -atv dev-vcs/git ccache; } || { pkg list-installed >/dev/null 2>&1 && $sudoprefix pkg install -y git getconf build-essential readline ccache; } || # termux { pkg help >/dev/null 2>&1 && $sudoprefix pkg install -y git readline ccache ncurses; } || # freebsd - { apk --version >/dev/null 2>&1 && $sudoprefix apk add git gcc g++ make readline-dev ncurses-dev libc-dev linux-headers; } + { apk --version >/dev/null 2>&1 && $sudoprefix apk add git gcc g++ make readline-dev ncurses-dev libc-dev linux-headers; } || + { xbps-install --version >/dev/null 2>&1 && $sudoprefix xbps-install -Sy git base-devel ccache; } #void + } -test_tools || { install_tools && test_tools; } || my_exit "$(echo -e 'Dependencies Installation Fail\nThe getter currently only support these package managers\n\t* apt\n\t* yum\n\t* zypper\n\t* pacman\n\t* portage\nPlease install following dependencies manually:\n\t* git\n\t* build essential like `make`, `gcc`, etc\n\t* libreadline-dev (readline-devel)\n\t* ccache (optional)')" 1 +test_tools || { install_tools && test_tools; } || my_exit "$(echo -e 'Dependencies Installation Fail\nThe getter currently only support these package managers\n\t* apt\n\t* yum\n\t* zypper\n\t* pacman\n\t* portage\n\t* xbps\n Please install following dependencies manually:\n\t* git\n\t* build essential like `make`, `gcc`, etc\n\t* libreadline-dev (readline-devel)\n\t* ccache (optional)')" 1 projectdir=$tmpdir if [ 'x__local__' = "x$branch" ]; then if [ -d '.git' ]; then -- cgit v1.3.1 From 5d3b5637a39d3f89dbe7891d0eacf3e028578818 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 22 Oct 2021 22:39:26 +0800 Subject: pass msvc envs to nim --- tests/projects/nim/static_library/src/bar.nim | 5 ----- tests/projects/nim/static_library/src/foo.nim | 2 -- tests/projects/nim/static_library/src/main.nim | 2 -- xmake/modules/core/tools/nim.lua | 15 ++++++++++----- xmake/modules/detect/tools/nim/has_flags.lua | 6 +++--- xmake/toolchains/nim/xmake.lua | 6 ++++++ 6 files changed, 19 insertions(+), 17 deletions(-) delete mode 100644 tests/projects/nim/static_library/src/bar.nim diff --git a/tests/projects/nim/static_library/src/bar.nim b/tests/projects/nim/static_library/src/bar.nim deleted file mode 100644 index 911a3cc85..000000000 --- a/tests/projects/nim/static_library/src/bar.nim +++ /dev/null @@ -1,5 +0,0 @@ -proc bar(n: int): int {.cdecl, exportc} = - if n < 2: - result = n - else: - result = bar(n - 1) + (n - 2).bar diff --git a/tests/projects/nim/static_library/src/foo.nim b/tests/projects/nim/static_library/src/foo.nim index ba0fcad5b..be0904262 100644 --- a/tests/projects/nim/static_library/src/foo.nim +++ b/tests/projects/nim/static_library/src/foo.nim @@ -1,5 +1,3 @@ -import bar - proc foo(n: int): int {.cdecl, exportc} = if n < 2: result = n diff --git a/tests/projects/nim/static_library/src/main.nim b/tests/projects/nim/static_library/src/main.nim index a91ba0614..1be3abe69 100644 --- a/tests/projects/nim/static_library/src/main.nim +++ b/tests/projects/nim/static_library/src/main.nim @@ -1,5 +1,3 @@ proc foo(n: int): int {.cdecl, importc} -proc bar(n: int): int {.cdecl, importc} echo foo(2) -echo bar(2) diff --git a/xmake/modules/core/tools/nim.lua b/xmake/modules/core/tools/nim.lua index b76fcb4ea..d142e3f0e 100644 --- a/xmake/modules/core/tools/nim.lua +++ b/xmake/modules/core/tools/nim.lua @@ -84,8 +84,8 @@ function nf_symbol(self, level) end -- make the strip flag -function nf_strip(self, level) - if is_plat("linux", "macosx", "bsd") then +function nf_strip(self, level, target) + if target:is_plat("linux", "macosx", "bsd") then if level == "debug" or level == "all" then return "--passL:-s" end @@ -103,8 +103,12 @@ function nf_link(self, lib) end -- make the linkdir flag -function nf_linkdir(self, dir) - return {"--passL:-L" .. path.translate(dir)} +function nf_linkdir(self, dir, target) + if target:is_plat("windows") then + return {"--passL:-libpath:" .. path.translate(dir)} + else + return {"--passL:-L" .. path.translate(dir)} + end end -- make the build arguments list @@ -128,6 +132,7 @@ end -- build the target file function build(self, sourcefiles, targetkind, targetfile, flags) os.mkdir(path.directory(targetfile)) - os.runv(buildargv(self, sourcefiles, targetkind, targetfile, flags)) + local program, argv = buildargv(self, sourcefiles, targetkind, targetfile, flags) + os.runv(program, argv, {envs = self:runenvs()}) end diff --git a/xmake/modules/detect/tools/nim/has_flags.lua b/xmake/modules/detect/tools/nim/has_flags.lua index 2fe415241..5538257fb 100644 --- a/xmake/modules/detect/tools/nim/has_flags.lua +++ b/xmake/modules/detect/tools/nim/has_flags.lua @@ -73,9 +73,9 @@ function _check_try_running(flags, opt) end -- check it - local binaryfile = os.tmpfile() - local ok, errors = _try_running(opt.program, table.join("c", flags, "-o:" .. binaryfile, sourcefile)) - os.tryrm(binaryfile) + local cachedir = os.tmpfile() .. ".dir" + local ok, errors = _try_running(opt.program, table.join("c", "-c", flags, "--nimcache:" .. cachedir, sourcefile)) + os.tryrm(cachedir) return ok, errors end diff --git a/xmake/toolchains/nim/xmake.lua b/xmake/toolchains/nim/xmake.lua index 598073abd..39565822d 100644 --- a/xmake/toolchains/nim/xmake.lua +++ b/xmake/toolchains/nim/xmake.lua @@ -35,6 +35,12 @@ toolchain("nim") on_load(function (toolchain) if toolchain:is_plat("windows") then toolchain:set("ncflags", "--cc:vcc") + local msvc = import("core.tool.toolchain", {anonymous = true}).load("msvc", {plat = toolchain:plat(), arch = toolchain:arch()}) + if msvc:check() then + for name, value in pairs(msvc:get("runenvs")) do + toolchain:add("runenvs", name, value) + end + end end toolchain:set("ncshflags", "") toolchain:set("ncldflags", "") -- cgit v1.3.1 From 62d3e0c681f25cb48560d07461a92738b55a0b6d Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 22 Oct 2021 12:47:15 +0800 Subject: Update xmake.lua --- xmake/rules/nim/xmake.lua | 153 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 138 insertions(+), 15 deletions(-) diff --git a/xmake/rules/nim/xmake.lua b/xmake/rules/nim/xmake.lua index 7d65c9c12..4ecb12fc7 100644 --- a/xmake/rules/nim/xmake.lua +++ b/xmake/rules/nim/xmake.lua @@ -15,23 +15,146 @@ -- Copyright (C) 2015-present, TBOOX Open Source Group. -- -- @author ruki --- @file xmake.lua +-- @file nim.lua -- --- define rule: nim.build -rule("nim.build") - set_sourcekinds("nc") - on_load(function (target) - local cachedir = path.join(target:autogendir(), "nimcache") - target:add("ncflags", "--nimcache:" .. cachedir, {force = true}) - end) - on_build("build.target") +-- imports +import("core.base.option") +import("core.project.config") +import("core.project.project") --- define rule: nim -rule("nim") +-- init it +-- +-- @see https://nim-lang.org/docs/nimc.html +function init(self) + + -- init arflags + self:set("ncarflags", "--app:staticlib", "--noMain") + + -- init shflags + self:set("ncshflags", "--app:lib", "--noMain") +end + +-- make the warning flag +function nf_warning(self, level) + local maps = + { + none = "--warning:X:off" + , less = "--warning:X:on" + , more = "--warning:X:on" + , all = "--warning:X:on" + , allextra = "--warning:X:on" + , everything = "--warning:X:on" + , error = "--warningAsError:X:on" + } + return maps[level] +end + +-- make the define flag +function nf_define(self, macro) + return "--define:" .. macro +end + +-- make the undefine flag +function nf_undefine(self, macro) + return "--undef:" .. macro +end + +-- make the optimize flag +function nf_optimize(self, level) + local maps = + { + none = "--opt:none" + , fast = "-d:release" + , faster = "-d:release" + , fastest = "-d:release" + , smallest = {"-d:release", "--opt:size"} + , aggressive = "-d:danger" + } + return maps[level] +end + +-- make the symbol flag +function nf_symbol(self, level) + local maps = + { + debug = "--debugger:native" + } + return maps[level] +end + +-- make the strip flag +function nf_strip(self, level, target) + if target:is_plat("linux", "macosx", "bsd") then + if level == "debug" or level == "all" then + return "--passL:-s" + end + end +end + +-- make the includedir flag +function nf_includedir(self, dir) + return {"--passC:-I" .. path.translate(dir)} +end + +-- make the link flag +function nf_link(self, lib, target) + if target:is_plat("windows") then + return "--passL:" .. lib .. ".lib" + else + return "--passL:-l" .. lib + end +end + +-- make the linkdir flag +function nf_linkdir(self, dir, target) + if target:is_plat("windows") then + return {"--passL:-libpath:" .. path.translate(dir)} + else + return {"--passL:-L" .. path.translate(dir)} + end +end + +-- make the build arguments list +function buildargv(self, sourcefiles, targetkind, targetfile, flags) + local flags_extra = {} + if targetkind == "static" then + -- fix multiple definition of `NimMain', it is only workaround solution + -- we need to wait for this problem to be resolved + -- + -- @see https://github.com/nim-lang/Nim/issues/15955 + local uniquekey = hash.uuid(targetfile):split("-", {plain = true})[1] + table.insert(flags_extra, "--passC:-DNimMain=NimMain_" .. uniquekey) + table.insert(flags_extra, "--passC:-DNimMainInner=NimMainInner_" .. uniquekey) + table.insert(flags_extra, "--passC:-DNimMainModule=NimMainModule_" .. uniquekey) + table.insert(flags_extra, "--passC:-DPreMain=PreMain_" .. uniquekey) + table.insert(flags_extra, "--passC:-DPreMainInner=PreMainInner_" .. uniquekey) + end + if targetkind ~= "static" and is_plat("windows") then + -- fix link flags for windows + -- @see https://github.com/nim-lang/Nim/issues/19033 + local flags_new = {} + local flags_link = {} + for _, flag in ipairs(flags) do + if flag:find("passL:", 1, true) then + table.insert(flags_link, flag) + else + table.insert(flags_new, flag) + end + end + if #flags_link > 0 then + table.insert(flags_new, "--passL:-link") + table.join2(flags_new, flags_link) + end + flags = flags_new + end + return self:program(), table.join("c", flags, flags_extra, "-o:" .. targetfile, sourcefiles) +end - -- add build rules - add_deps("nim.build") +-- build the target file +function build(self, sourcefiles, targetkind, targetfile, flags) + os.mkdir(path.directory(targetfile)) + local program, argv = buildargv(self, sourcefiles, targetkind, targetfile, flags) + os.runv(program, argv, {envs = self:runenvs()}) +end - -- inherit links and linkdirs of all dependent targets by default - add_deps("utils.inherit.links") -- cgit v1.3.1 From 55eaa73edf4b3bace71ec1a71b957c34374442b2 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 23 Oct 2021 00:34:32 +0800 Subject: fix nim --- xmake/modules/core/tools/nim.lua | 27 ++++++- xmake/rules/nim/xmake.lua | 153 ++++----------------------------------- 2 files changed, 40 insertions(+), 140 deletions(-) diff --git a/xmake/modules/core/tools/nim.lua b/xmake/modules/core/tools/nim.lua index d142e3f0e..0eece46cf 100644 --- a/xmake/modules/core/tools/nim.lua +++ b/xmake/modules/core/tools/nim.lua @@ -98,8 +98,12 @@ function nf_includedir(self, dir) end -- make the link flag -function nf_link(self, lib) - return "--passL:-l" .. lib +function nf_link(self, lib, target) + if target:is_plat("windows") then + return "--passL:" .. lib .. ".lib" + else + return "--passL:-l" .. lib + end end -- make the linkdir flag @@ -126,6 +130,24 @@ function buildargv(self, sourcefiles, targetkind, targetfile, flags) table.insert(flags_extra, "--passC:-DPreMain=PreMain_" .. uniquekey) table.insert(flags_extra, "--passC:-DPreMainInner=PreMainInner_" .. uniquekey) end + if targetkind ~= "static" and is_plat("windows") then + -- fix link flags for windows + -- @see https://github.com/nim-lang/Nim/issues/19033 + local flags_new = {} + local flags_link = {} + for _, flag in ipairs(flags) do + if flag:find("passL:", 1, true) then + table.insert(flags_link, flag) + else + table.insert(flags_new, flag) + end + end + if #flags_link > 0 then + table.insert(flags_new, "--passL:-link") + table.join2(flags_new, flags_link) + end + flags = flags_new + end return self:program(), table.join("c", flags, flags_extra, "-o:" .. targetfile, sourcefiles) end @@ -136,3 +158,4 @@ function build(self, sourcefiles, targetkind, targetfile, flags) os.runv(program, argv, {envs = self:runenvs()}) end + diff --git a/xmake/rules/nim/xmake.lua b/xmake/rules/nim/xmake.lua index 4ecb12fc7..7d65c9c12 100644 --- a/xmake/rules/nim/xmake.lua +++ b/xmake/rules/nim/xmake.lua @@ -15,146 +15,23 @@ -- Copyright (C) 2015-present, TBOOX Open Source Group. -- -- @author ruki --- @file nim.lua +-- @file xmake.lua -- --- imports -import("core.base.option") -import("core.project.config") -import("core.project.project") +-- define rule: nim.build +rule("nim.build") + set_sourcekinds("nc") + on_load(function (target) + local cachedir = path.join(target:autogendir(), "nimcache") + target:add("ncflags", "--nimcache:" .. cachedir, {force = true}) + end) + on_build("build.target") --- init it --- --- @see https://nim-lang.org/docs/nimc.html -function init(self) - - -- init arflags - self:set("ncarflags", "--app:staticlib", "--noMain") - - -- init shflags - self:set("ncshflags", "--app:lib", "--noMain") -end - --- make the warning flag -function nf_warning(self, level) - local maps = - { - none = "--warning:X:off" - , less = "--warning:X:on" - , more = "--warning:X:on" - , all = "--warning:X:on" - , allextra = "--warning:X:on" - , everything = "--warning:X:on" - , error = "--warningAsError:X:on" - } - return maps[level] -end - --- make the define flag -function nf_define(self, macro) - return "--define:" .. macro -end - --- make the undefine flag -function nf_undefine(self, macro) - return "--undef:" .. macro -end - --- make the optimize flag -function nf_optimize(self, level) - local maps = - { - none = "--opt:none" - , fast = "-d:release" - , faster = "-d:release" - , fastest = "-d:release" - , smallest = {"-d:release", "--opt:size"} - , aggressive = "-d:danger" - } - return maps[level] -end - --- make the symbol flag -function nf_symbol(self, level) - local maps = - { - debug = "--debugger:native" - } - return maps[level] -end - --- make the strip flag -function nf_strip(self, level, target) - if target:is_plat("linux", "macosx", "bsd") then - if level == "debug" or level == "all" then - return "--passL:-s" - end - end -end - --- make the includedir flag -function nf_includedir(self, dir) - return {"--passC:-I" .. path.translate(dir)} -end - --- make the link flag -function nf_link(self, lib, target) - if target:is_plat("windows") then - return "--passL:" .. lib .. ".lib" - else - return "--passL:-l" .. lib - end -end - --- make the linkdir flag -function nf_linkdir(self, dir, target) - if target:is_plat("windows") then - return {"--passL:-libpath:" .. path.translate(dir)} - else - return {"--passL:-L" .. path.translate(dir)} - end -end - --- make the build arguments list -function buildargv(self, sourcefiles, targetkind, targetfile, flags) - local flags_extra = {} - if targetkind == "static" then - -- fix multiple definition of `NimMain', it is only workaround solution - -- we need to wait for this problem to be resolved - -- - -- @see https://github.com/nim-lang/Nim/issues/15955 - local uniquekey = hash.uuid(targetfile):split("-", {plain = true})[1] - table.insert(flags_extra, "--passC:-DNimMain=NimMain_" .. uniquekey) - table.insert(flags_extra, "--passC:-DNimMainInner=NimMainInner_" .. uniquekey) - table.insert(flags_extra, "--passC:-DNimMainModule=NimMainModule_" .. uniquekey) - table.insert(flags_extra, "--passC:-DPreMain=PreMain_" .. uniquekey) - table.insert(flags_extra, "--passC:-DPreMainInner=PreMainInner_" .. uniquekey) - end - if targetkind ~= "static" and is_plat("windows") then - -- fix link flags for windows - -- @see https://github.com/nim-lang/Nim/issues/19033 - local flags_new = {} - local flags_link = {} - for _, flag in ipairs(flags) do - if flag:find("passL:", 1, true) then - table.insert(flags_link, flag) - else - table.insert(flags_new, flag) - end - end - if #flags_link > 0 then - table.insert(flags_new, "--passL:-link") - table.join2(flags_new, flags_link) - end - flags = flags_new - end - return self:program(), table.join("c", flags, flags_extra, "-o:" .. targetfile, sourcefiles) -end +-- define rule: nim +rule("nim") --- build the target file -function build(self, sourcefiles, targetkind, targetfile, flags) - os.mkdir(path.directory(targetfile)) - local program, argv = buildargv(self, sourcefiles, targetkind, targetfile, flags) - os.runv(program, argv, {envs = self:runenvs()}) -end + -- add build rules + add_deps("nim.build") + -- inherit links and linkdirs of all dependent targets by default + add_deps("utils.inherit.links") -- cgit v1.3.1 From de06bfc4e74ee23c6d7d599cd3bf4e7e1072f0b1 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 23 Oct 2021 00:45:55 +0800 Subject: add include and lib envs for xrepo env --- xmake/modules/private/xrepo/action/env.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/xmake/modules/private/xrepo/action/env.lua b/xmake/modules/private/xrepo/action/env.lua index 742d30d12..0a6ccb7ed 100644 --- a/xmake/modules/private/xrepo/action/env.lua +++ b/xmake/modules/private/xrepo/action/env.lua @@ -227,6 +227,13 @@ function _package_addenvs(envs, instance) _addenvs(envs, "ACLOCAL_PATH", aclocal) end _addenvs(envs, "CMAKE_PREFIX_PATH", installdir) + if instance:is_plat("windows") then + _addenvs(envs, "INCLUDE", path.join(installdir, "include")) + _addenvs(envs, "LIBPATH", path.join(installdir, "lib")) + else + _addenvs(envs, "CPATH", path.join(installdir, "include")) + _addenvs(envs, "LIBRARY_PATH", path.join(installdir, "lib")) + end end end -- cgit v1.3.1 From 2a4674d25e471b19b9befcd581440661e2c36e49 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 23 Oct 2021 00:17:10 +0800 Subject: improve xrepo env --- xmake/core/project/project.lua | 3 + .../modules/import/core/project/project.lua | 8 ++ xmake/modules/private/xrepo/action/env.lua | 112 ++++++++++++++++----- 3 files changed, 100 insertions(+), 23 deletions(-) diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index f832305ca..57a8c5c58 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -1086,6 +1086,9 @@ function project.mtimes() local mtimes = project._MTIMES if not mtimes then mtimes = project.interpreter():mtimes() + for _, rcfile in ipairs(project.rcfiles()) do + mtimes[rcfile] = os.mtime(rcfile) + end project._MTIMES = mtimes end return mtimes diff --git a/xmake/core/sandbox/modules/import/core/project/project.lua b/xmake/core/sandbox/modules/import/core/project/project.lua index 2330dccd0..12b133b37 100644 --- a/xmake/core/sandbox/modules/import/core/project/project.lua +++ b/xmake/core/sandbox/modules/import/core/project/project.lua @@ -159,5 +159,13 @@ function sandbox_core_project.unlock() end end +-- change project file and directory (xmake.lua) +function sandbox_core_project.changefile(projectfile) + xmake._PROJECT_FILE = projectfile + xmake._PROJECT_DIR = path.directory(projectfile) + xmake._WORKING_DIR = xmake._PROJECT_DIR + config._DIRECTORY = nil +end + -- return module return sandbox_core_project diff --git a/xmake/modules/private/xrepo/action/env.lua b/xmake/modules/private/xrepo/action/env.lua index 0a6ccb7ed..7db7e7459 100644 --- a/xmake/modules/private/xrepo/action/env.lua +++ b/xmake/modules/private/xrepo/action/env.lua @@ -22,6 +22,7 @@ import("core.base.option") import("core.base.task") import("core.base.hashset") +import("core.base.global") import("core.project.config") import("core.project.project") import("core.tool.toolchain") @@ -49,14 +50,27 @@ function menu_options() "e.g.", " - xrepo env -f \"vs_runtime='MD'\" zlib cmake ..", " - xrepo env -f \"regex=true,thread=true\" \"zlib,boost\" cmake .."}, - {'b', "packages", "kv", nil, "Set the packages to be bound", + {nil, "add", "k", nil, "Add global environment config.", "e.g.", + " - xrepo env --add base.lua", + " - xrepo env --add myenv.lua"}, + {nil, "remove", "k", nil, "Remove global environment config.", + "e.g.", + " - xrepo env --remove base", + " - xrepo env --remove myenv"}, + {"l", "list", "k", nil, "List all global environment configs.", + "e.g.", + " - xrepo env --list"}, + {'b', "bind", "kv", nil, "Bind the specified environment or package.", + "e.g.", + " - xrepo env -b base", + " - xrepo env -b myenv", " - xrepo env -b \"python 3.x\" python", " - xrepo env -b \"llvm 11.x\" bash", " $ clang --version", " - xrepo env -p android -b \"zlib,luajit 2.x\" luajit xx.lua"}, {}, - {nil, "program", "v", nil, "Set the program name to be run", + {nil, "program", "v", nil, "Set the program name to be run.", "e.g.", " - xrepo env", " - xrepo env bash", @@ -112,9 +126,10 @@ function _get_requires(packages) end -- enter project -function _enter_project() +function _enter_project(opt) -- enter working project directory + opt = opt or {} local workdir = path.join(os.tmpdir(), "xrepo", "working") if not os.isdir(workdir) then os.mkdir(workdir) @@ -123,6 +138,10 @@ function _enter_project() else os.cd(workdir) end + if opt.enteronly then + project.changefile(path.join(workdir, "xmake.lua")) + return + end -- do configure first local config_argv = {"f", "-c"} @@ -174,6 +193,23 @@ function _remove_repeat_pathenv(value) return value end +-- get environment directory +function _get_envsdir() + return path.join(global.directory(), "envs") +end + +-- get bound environment or packages +function _get_boundenv() + local bind = option.get("bind") + if bind then + local envfile = path.join(_get_envsdir(), bind .. ".lua") + if envfile and os.isfile(envfile) then + return envfile + end + end + return bind +end + -- add values to environment variable function _addenvs(envs, name, ...) local values = {...} @@ -253,22 +289,33 @@ end -- get package environments function _package_getenvs() local envs = os.getenvs() - if os.isfile(os.projectfile()) and not option.get("packages") then + local boundenv = _get_boundenv() + local has_envfile = false + local packages = nil + if boundenv and os.isfile(boundenv) then + has_envfile = true + else + packages = boundenv or option.get("program") + end + if os.isfile(os.projectfile()) or has_envfile then + if not os.isfile(os.projectfile()) then + _enter_project({enteronly = true}) + end + if has_envfile then + table.insert(project.rcfiles(), boundenv) + end task.run("config", {target = "all"}, {disable_dump = true}) _toolchain_addenvs(envs) local requires, requires_extra = get_requires() for _, instance in ipairs(package.load_packages(requires, {requires_extra = requires_extra})) do _package_addenvs(envs, instance) end - else - local packages = option.get("packages") or option.get("program") - if packages then - _enter_project() - packages = packages:split(',', {plain = true}) - local requires, requires_extra = _get_requires(packages) - for _, instance in ipairs(package.load_packages(requires, {requires_extra = requires_extra})) do - _package_addenvs(envs, instance) - end + elseif packages then + _enter_project() + packages = packages:split(',', {plain = true}) + local requires, requires_extra = _get_requires(packages) + for _, instance in ipairs(package.load_packages(requires, {requires_extra = requires_extra})) do + _package_addenvs(envs, instance) end end local results = {} @@ -371,18 +418,37 @@ end -- main entry function main() - local envs = _package_getenvs() - local program = option.get("program") - if program and not option.get("show") then - if envs and envs.PATH then - os.setenv("PATH", envs.PATH) + if option.get("list") then + print("%s:", _get_envsdir()) + local count = 0 + for _, envfile in ipairs(os.files(path.join(_get_envsdir(), "*.lua"))) do + local envname = path.basename(envfile) + print(" - %s", envname) + count = count + 1 end - if program == "shell" then - _run_shell(envs) - else - os.execv(program, option.get("arguments"), {envs = envs}) + print("envs(%d) found!", count) + elseif option.get("add") then + local envfile = assert(option.get("program"), "please set environment config file!") + if os.isfile(envfile) then + os.vcp(envfile, path.join(_get_envsdir(), path.filename(envfile))) end + elseif option.get("remove") then + local envname = assert(option.get("program"), "please set environment config name!") + os.rm(path.join(_get_envsdir(), envname .. ".lua")) else - print(envs) + local envs = _package_getenvs() + local program = option.get("program") + if program and not option.get("show") then + if envs and envs.PATH then + os.setenv("PATH", envs.PATH) + end + if program == "shell" then + _run_shell(envs) + else + os.execv(program, option.get("arguments"), {envs = envs}) + end + else + print(envs) + end end end -- cgit v1.3.1 From 63301ceb02b675594799d2c36cd71d7bb3cc110b Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 23 Oct 2021 00:21:55 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba059a5c4..d6a272961 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * [#1019](https://github.com/xmake-io/xmake/issues/1019): Support Unity build * [#1438](https://github.com/xmake-io/xmake/issues/1438): Support code amalgamation, `xmake l cli.amalgamate` * [#1765](https://github.com/xmake-io/xmake/issues/1756): Support nim language +* [#1762](https://github.com/xmake-io/xmake/issues/1762): Manage and switch the given package envs for `xrepo env` ### Changes @@ -1116,6 +1117,7 @@ * [#1019](https://github.com/xmake-io/xmake/issues/1019): 支持 Unity build * [#1438](https://github.com/xmake-io/xmake/issues/1438): 增加 `xmake l cli.amalgamate` 命令支持代码合并 * [#1765](https://github.com/xmake-io/xmake/issues/1756): 支持 nim 语言 +* [#1762](https://github.com/xmake-io/xmake/issues/1762): 为 `xrepo env` 管理和切换指定的环境配置 ### 改进 -- cgit v1.3.1 From 6bac1ec396557471cf0651a3d8dadbb76234299c Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 23 Oct 2021 00:29:36 +0800 Subject: improve project.chdir --- xmake/core/sandbox/modules/import/core/project/project.lua | 5 ++++- xmake/modules/private/xrepo/action/env.lua | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/xmake/core/sandbox/modules/import/core/project/project.lua b/xmake/core/sandbox/modules/import/core/project/project.lua index 12b133b37..f515b3e74 100644 --- a/xmake/core/sandbox/modules/import/core/project/project.lua +++ b/xmake/core/sandbox/modules/import/core/project/project.lua @@ -160,7 +160,10 @@ function sandbox_core_project.unlock() end -- change project file and directory (xmake.lua) -function sandbox_core_project.changefile(projectfile) +function sandbox_core_project.chdir(projectdir, projectfile) + if not projectfile then + projectfile = path.join(projectdir, "xmake.lua") + end xmake._PROJECT_FILE = projectfile xmake._PROJECT_DIR = path.directory(projectfile) xmake._WORKING_DIR = xmake._PROJECT_DIR diff --git a/xmake/modules/private/xrepo/action/env.lua b/xmake/modules/private/xrepo/action/env.lua index 7db7e7459..8590fcab9 100644 --- a/xmake/modules/private/xrepo/action/env.lua +++ b/xmake/modules/private/xrepo/action/env.lua @@ -139,7 +139,7 @@ function _enter_project(opt) os.cd(workdir) end if opt.enteronly then - project.changefile(path.join(workdir, "xmake.lua")) + project.chdir(workdir) return end -- cgit v1.3.1 From 8492e2a5133e27794e8fac48212e8540bef9ffd7 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 24 Oct 2021 22:12:36 +0800 Subject: improve tools/xmake --- xmake/modules/package/tools/xmake.lua | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/xmake/modules/package/tools/xmake.lua b/xmake/modules/package/tools/xmake.lua index e782eb834..abcd7fc1e 100644 --- a/xmake/modules/package/tools/xmake.lua +++ b/xmake/modules/package/tools/xmake.lua @@ -66,6 +66,14 @@ function _get_configs(package, configs) if sdkdir then table.insert(configs, "--sdk=" .. sdkdir) end + -- we can only modify toolchain for cross-compilation + -- + -- e.g. xrepo install -p cross --toolchain=muslcc meson, + -- we cannot pass muslcc toolchain to it's deps(zlib, ..), because meson is always host binary and zlib is host library. + local toolchain_name = get_config("toolchain") + if toolchain_name then + table.insert(configs, "--toolchain=" .. toolchain_name) + end else local names = {"ndk", "ndk_sdkver", "vs", "mingw", "ld", "sh", "ar", "cc", "cxx", "mm", "mxx"} for _, name in ipairs(names) do @@ -75,13 +83,6 @@ function _get_configs(package, configs) end end end - -- we can only modify toolchain for linux or cross-compilation - if package:is_plat("linux", "cross") then - local toolchain_name = get_config("toolchain") - if toolchain_name then - table.insert(configs, "--toolchain=" .. toolchain_name) - end - end if not package:is_plat("windows", "mingw") and package:config("pic") ~= false then table.insert(cxflags, "-fPIC") end -- cgit v1.3.1 From df89676a5a905ced4cae2be987742c1d4d91c563 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 25 Oct 2021 16:34:07 +0800 Subject: Fix install for mac M1 --- makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index e848a2eda..63d019542 100644 --- a/makefile +++ b/makefile @@ -117,7 +117,8 @@ install: @if [ ! -d $(destdir)/bin ]; then mkdir -p $(destdir)/bin; fi @# install the xmake directory @cp -r xmake/* $(xmake_dir_install) - @# install the xmake core file + @# install the xmake core file, @note we need remove old binary first on mac M1, otherwise it will be killed + @if [ -f $(xmake_core_install) ]; then rm $(xmake_core_install); fi @cp -p $(xmake_core) $(xmake_core_install) @chmod 755 $(xmake_core_install) @# install the xrepo bin file -- cgit v1.3.1 From e678a046088bf328c0a6ce9b919b5e6a00bbad0c Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 25 Oct 2021 22:45:24 +0800 Subject: support circle compiler --- CHANGELOG.md | 2 + README.md | 1 + README_zh.md | 1 + xmake/modules/core/tools/circle.lua | 34 ++++++++++++++++ xmake/modules/detect/tools/circle/has_flags.lua | 23 +++++++++++ xmake/modules/detect/tools/find_circle.lua | 52 +++++++++++++++++++++++++ xmake/toolchains/circle/xmake.lua | 52 +++++++++++++++++++++++++ 7 files changed, 165 insertions(+) create mode 100644 xmake/modules/core/tools/circle.lua create mode 100644 xmake/modules/detect/tools/circle/has_flags.lua create mode 100644 xmake/modules/detect/tools/find_circle.lua create mode 100644 xmake/toolchains/circle/xmake.lua diff --git a/CHANGELOG.md b/CHANGELOG.md index d6a272961..35c5e38ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * [#1438](https://github.com/xmake-io/xmake/issues/1438): Support code amalgamation, `xmake l cli.amalgamate` * [#1765](https://github.com/xmake-io/xmake/issues/1756): Support nim language * [#1762](https://github.com/xmake-io/xmake/issues/1762): Manage and switch the given package envs for `xrepo env` +* [#1767](https://github.com/xmake-io/xmake/issues/1767): Support Circle compiler ### Changes @@ -1118,6 +1119,7 @@ * [#1438](https://github.com/xmake-io/xmake/issues/1438): 增加 `xmake l cli.amalgamate` 命令支持代码合并 * [#1765](https://github.com/xmake-io/xmake/issues/1756): 支持 nim 语言 * [#1762](https://github.com/xmake-io/xmake/issues/1762): 为 `xrepo env` 管理和切换指定的环境配置 +* [#1767](https://github.com/xmake-io/xmake/issues/1767): 支持 Circle 编译器 ### 改进 diff --git a/README.md b/README.md index 741e90823..bd9fa28de 100644 --- a/README.md +++ b/README.md @@ -226,6 +226,7 @@ muslcc The musl-based cross-compilation toolchain fpc Free Pascal Programming Language Compiler wasi WASI-enabled WebAssembly C/C++ toolchain nim Nim Programming Language Compiler +circle A new C++20 compiler ``` ## Supported Languages diff --git a/README_zh.md b/README_zh.md index 8b40da549..ac7941603 100644 --- a/README_zh.md +++ b/README_zh.md @@ -234,6 +234,7 @@ muslcc The musl-based cross-compilation toolchain fpc Free Pascal Programming Language Compiler wasi WASI-enabled WebAssembly C/C++ toolchain nim Nim Programming Language Compiler +circle A new C++20 compiler ``` ## 支持语言 diff --git a/xmake/modules/core/tools/circle.lua b/xmake/modules/core/tools/circle.lua new file mode 100644 index 000000000..fcf567549 --- /dev/null +++ b/xmake/modules/core/tools/circle.lua @@ -0,0 +1,34 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file circle.lua +-- + +inherit("gcc") + +function init(self) + _super.init(self) +end + +function nf_strip(self, level) + local maps = + { + debug = "-Wl,-S" + , all = "-Wl,-s" + } + return maps[level] +end diff --git a/xmake/modules/detect/tools/circle/has_flags.lua b/xmake/modules/detect/tools/circle/has_flags.lua new file mode 100644 index 000000000..6464e10b6 --- /dev/null +++ b/xmake/modules/detect/tools/circle/has_flags.lua @@ -0,0 +1,23 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file has_flags.lua +-- + +-- imports +inherit("detect.tools.gcc.has_flags") + diff --git a/xmake/modules/detect/tools/find_circle.lua b/xmake/modules/detect/tools/find_circle.lua new file mode 100644 index 000000000..ba2f805c2 --- /dev/null +++ b/xmake/modules/detect/tools/find_circle.lua @@ -0,0 +1,52 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_circle.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find circle +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local circle = find_circle() +-- local circle, version = find_circle({program = "circle", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "circle", opt) + + -- find program version + local version = nil + if program and opt.version then + version = find_programver(program, opt) + end + return program, version +end diff --git a/xmake/toolchains/circle/xmake.lua b/xmake/toolchains/circle/xmake.lua new file mode 100644 index 000000000..2e5d84757 --- /dev/null +++ b/xmake/toolchains/circle/xmake.lua @@ -0,0 +1,52 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +toolchain("circle") + + set_homepage("https://www.circle-lang.org/") + set_description("A new C++20 compiler. It's written from scratch and designed for easy extension.") + + set_kind("standalone") + + set_toolset("cc", "circle") + set_toolset("cxx", "circle") + set_toolset("ld", "circle") + set_toolset("sh", "circle") + set_toolset("ar", "ar") + set_toolset("ex", "ar") + set_toolset("strip", "strip") + + on_check(function (toolchain) + return import("lib.detect.find_tool")("circle") + end) + + on_load(function (toolchain) + local march + if toolchain:is_arch("x86_64", "x64") then + march = "-m64" + elseif toolchain:is_arch("i386", "x86") then + march = "-m32" + end + if march then + toolchain:add("cxflags", march) + toolchain:add("ldflags", march) + toolchain:add("shflags", march) + end + end) -- cgit v1.3.1 From f08ac4c4eff8fbb3574e5e2ca66cea414c3bbb80 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 26 Oct 2021 22:39:37 +0800 Subject: add find_mdk --- xmake/modules/detect/sdks/find_mdk.lua | 123 +++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 xmake/modules/detect/sdks/find_mdk.lua diff --git a/xmake/modules/detect/sdks/find_mdk.lua b/xmake/modules/detect/sdks/find_mdk.lua new file mode 100644 index 000000000..a2af360f1 --- /dev/null +++ b/xmake/modules/detect/sdks/find_mdk.lua @@ -0,0 +1,123 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_mdk.lua +-- + +-- imports +import("lib.detect.find_path") +import("core.base.option") +import("core.base.semver") +import("core.project.config") +import("core.cache.detectcache") + +-- find MDK directory +function _find_sdkdir(sdkdir) + local paths = { + "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Keil\\Products\\MDK;Path)" + } + if sdkdir then + table.insert(paths, 1, sdkdir) + end + local result = find_path("armcc", paths) or find_path("armclang", paths) + if not result then + -- find it from some logical drives paths + paths = {} + for _, logical_drive in ipairs(winos.logical_drives()) do + table.insert(paths, path.join(logical_drive, "Keil_v5", "ARM")) + end + result = find_path("armcc", paths) or find_path("armclang", paths) + end + return result +end + +-- find MDK toolchains +function _find_mdk(sdkdir) + + -- find mdk directory + sdkdir = _find_sdkdir(sdkdir) + if not sdkdir or not os.isdir(sdkdir) then + return nil + end + local result = {sdkdir = sdkdir} + + -- get sdk version + local sdkver = winos.registry_query("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Keil\\Products\\MDK;Version") + if sdkver then + sdkver = semver.match(sdkver, 1, "V%d+%.%d+") + if sdkver then + result.sdkver = sdkver:rawstr() + end + end + + -- armcc sdk directory + local sdkdir_armcc = path.join(sdkdir, "armcc") + if os.isdir(sdkdir_armcc) and os.isfile(path.join(sdkdir_armcc, "bin", "armcc.exe")) then + result.sdkdir_armcc = sdkdir_armcc + end + + -- armclang sdk directory + local sdkdir_armclang = path.join(sdkdir, "armclang") + if os.isdir(sdkdir_armclang) and os.isfile(path.join(sdkdir_armclang, "bin", "armclang.exe")) then + result.sdkdir_armclang = sdkdir_armclang + end + return result +end + +-- find MDK toolchains +-- +-- @param sdkdir the MDK directory +-- @param opt the argument options, e.g. {verbose = true, force = false} +-- +-- @return the MDK toolchains. e.g. {sdkver = ..., sdkdir, sdkdir_armcc, sdkdir_armclang} +-- +-- @code +-- +-- local toolchains = find_mdk("~/mdk") +-- +-- @endcode +-- +function main(sdkdir, opt) + + -- init arguments + opt = opt or {} + + -- attempt to load cache first + local key = "detect.sdks.find_mdk" + local cacheinfo = detectcache:get(key) or {} + if not opt.force and cacheinfo.mdk and cacheinfo.mdk.sdkdir and os.isdir(cacheinfo.mdk.sdkdir) then + return cacheinfo.mdk + end + + -- find mdk + local mdk = _find_mdk(sdkdir or config.get("sdk")) + if mdk then + if opt.verbose or option.get("verbose") then + cprint("checking for MDK directory ... ${color.success}%s", mdk.sdkdir) + end + else + if opt.verbose or option.get("verbose") then + cprint("checking for MDK directory ... ${color.nothing}${text.nothing}") + end + end + + -- save to cache + cacheinfo.mdk = mdk or false + detectcache:set(key, cacheinfo) + detectcache:save() + return mdk +end -- cgit v1.3.1 From d1e61a632767c25fa0db5bde323a2765ed273f8f Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 26 Oct 2021 22:40:55 +0800 Subject: find armcc and armclang --- xmake/modules/detect/tools/find_armcc.lua | 60 ++++++++++++++++++++++++++++ xmake/modules/detect/tools/find_armclang.lua | 59 +++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 xmake/modules/detect/tools/find_armcc.lua create mode 100644 xmake/modules/detect/tools/find_armclang.lua diff --git a/xmake/modules/detect/tools/find_armcc.lua b/xmake/modules/detect/tools/find_armcc.lua new file mode 100644 index 000000000..584e9b3a9 --- /dev/null +++ b/xmake/modules/detect/tools/find_armcc.lua @@ -0,0 +1,60 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_armcc.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") +import("detect.sdks.find_mdk") + +-- find armcc +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local armcc = find_armcc() +-- local armcc, version = find_armcc({program = "armcc", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + opt.check = "-h" + + -- find program + local program = find_program(opt.program or "armcc.exe", opt) + if not program then + local mdk = find_mdk() + if mdk and mdk.sdkdir_armcc then + program = find_program(path.join(mdk.sdkdir_armcc, "bin", "armcc.exe"), opt) + end + end + + -- find program version + local version = nil + if program and opt.version then + version = find_programver(program, opt) + end + return program, version +end diff --git a/xmake/modules/detect/tools/find_armclang.lua b/xmake/modules/detect/tools/find_armclang.lua new file mode 100644 index 000000000..ed6b0bbfe --- /dev/null +++ b/xmake/modules/detect/tools/find_armclang.lua @@ -0,0 +1,59 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_armclang.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") +import("detect.sdks.find_mdk") + +-- find armclang +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local armclang = find_armclang() +-- local armclang, version = find_armclang({program = "armclang", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "armclang.exe", opt) + if not program then + local mdk = find_mdk() + if mdk and mdk.sdkdir_armclang then + program = find_program(path.join(mdk.sdkdir_armclang, "bin", "armclang.exe"), opt) + end + end + + -- find program version + local version = nil + if program and opt.version then + version = find_programver(program, opt) + end + return program, version +end -- cgit v1.3.1 From f039264c1bb4fc8247b23800c1331c0baa45cb88 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 26 Oct 2021 22:52:14 +0800 Subject: add find armlink, armar, armasm --- xmake/modules/core/tools/armcc.lua | 25 +++++++++++ xmake/modules/core/tools/armclang.lua | 25 +++++++++++ xmake/modules/detect/tools/find_armar.lua | 65 +++++++++++++++++++++++++++++ xmake/modules/detect/tools/find_armasm.lua | 65 +++++++++++++++++++++++++++++ xmake/modules/detect/tools/find_armlink.lua | 65 +++++++++++++++++++++++++++++ xmake/toolchains/armcc/xmake.lua | 41 ++++++++++++++++++ xmake/toolchains/armclang/xmake.lua | 41 ++++++++++++++++++ xmake/toolchains/clang/xmake.lua | 8 ---- 8 files changed, 327 insertions(+), 8 deletions(-) create mode 100644 xmake/modules/core/tools/armcc.lua create mode 100644 xmake/modules/core/tools/armclang.lua create mode 100644 xmake/modules/detect/tools/find_armar.lua create mode 100644 xmake/modules/detect/tools/find_armasm.lua create mode 100644 xmake/modules/detect/tools/find_armlink.lua create mode 100644 xmake/toolchains/armcc/xmake.lua create mode 100644 xmake/toolchains/armclang/xmake.lua diff --git a/xmake/modules/core/tools/armcc.lua b/xmake/modules/core/tools/armcc.lua new file mode 100644 index 000000000..40854eb7a --- /dev/null +++ b/xmake/modules/core/tools/armcc.lua @@ -0,0 +1,25 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file armcc.lua +-- + +inherit("gcc") + +function init(self) + _super.init(self) +end diff --git a/xmake/modules/core/tools/armclang.lua b/xmake/modules/core/tools/armclang.lua new file mode 100644 index 000000000..42bec8fd5 --- /dev/null +++ b/xmake/modules/core/tools/armclang.lua @@ -0,0 +1,25 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file armclang.lua +-- + +inherit("gcc") + +function init(self) + _super.init(self) +end diff --git a/xmake/modules/detect/tools/find_armar.lua b/xmake/modules/detect/tools/find_armar.lua new file mode 100644 index 000000000..725d6a988 --- /dev/null +++ b/xmake/modules/detect/tools/find_armar.lua @@ -0,0 +1,65 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_armar.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") +import("detect.sdks.find_mdk") + +-- find armar +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local armar = find_armar() +-- local armar, version = find_armar({program = "armar", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + opt.check = "-h" + + -- find program + local program = find_program(opt.program or "armar.exe", opt) + if not program then + local mdk = find_mdk() + if mdk then + if mdk.sdkdir_armcc then + program = find_program(path.join(mdk.sdkdir_armcc, "bin", "armar.exe"), opt) + end + if not program and mdk.sdkdir_armclang then + program = find_program(path.join(mdk.sdkdir_armclang, "bin", "armar.exe"), opt) + end + end + end + + -- find program version + local version = nil + if program and opt.version then + version = find_programver(program, opt) + end + return program, version +end diff --git a/xmake/modules/detect/tools/find_armasm.lua b/xmake/modules/detect/tools/find_armasm.lua new file mode 100644 index 000000000..280333195 --- /dev/null +++ b/xmake/modules/detect/tools/find_armasm.lua @@ -0,0 +1,65 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_armasm.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") +import("detect.sdks.find_mdk") + +-- find armasm +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local armasm = find_armasm() +-- local armasm, version = find_armasm({program = "armasm", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + opt.check = "-h" + + -- find program + local program = find_program(opt.program or "armasm.exe", opt) + if not program then + local mdk = find_mdk() + if mdk then + if mdk.sdkdir_armcc then + program = find_program(path.join(mdk.sdkdir_armcc, "bin", "armasm.exe"), opt) + end + if not program and mdk.sdkdir_armclang then + program = find_program(path.join(mdk.sdkdir_armclang, "bin", "armasm.exe"), opt) + end + end + end + + -- find program version + local version = nil + if program and opt.version then + version = find_programver(program, opt) + end + return program, version +end diff --git a/xmake/modules/detect/tools/find_armlink.lua b/xmake/modules/detect/tools/find_armlink.lua new file mode 100644 index 000000000..3ab383c86 --- /dev/null +++ b/xmake/modules/detect/tools/find_armlink.lua @@ -0,0 +1,65 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_armlink.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") +import("detect.sdks.find_mdk") + +-- find armlink +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local armlink = find_armlink() +-- local armlink, version = find_armlink({program = "armlink", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + opt.check = "-h" + + -- find program + local program = find_program(opt.program or "armlink.exe", opt) + if not program then + local mdk = find_mdk() + if mdk then + if mdk.sdkdir_armcc then + program = find_program(path.join(mdk.sdkdir_armcc, "bin", "armlink.exe"), opt) + end + if not program and mdk.sdkdir_armclang then + program = find_program(path.join(mdk.sdkdir_armclang, "bin", "armlink.exe"), opt) + end + end + end + + -- find program version + local version = nil + if program and opt.version then + version = find_programver(program, opt) + end + return program, version +end diff --git a/xmake/toolchains/armcc/xmake.lua b/xmake/toolchains/armcc/xmake.lua new file mode 100644 index 000000000..1ba3a15eb --- /dev/null +++ b/xmake/toolchains/armcc/xmake.lua @@ -0,0 +1,41 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +toolchain("armcc") + + set_homepage("https://www2.keil.com/mdk5/compiler/5") + set_description("ARM Compiler Version 5 of Keil MDK") + + set_kind("standalone") + + set_toolset("cc", "armcc") + set_toolset("cxx", "armcc") + set_toolset("ld", "armlink") + set_toolset("sh", "armlink") + set_toolset("ar", "armar") + set_toolset("ex", "armar") + set_toolset("as", "armasm") + + on_check(function (toolchain) + return import("lib.detect.find_tool")("armcc") + end) + + on_load(function (toolchain) + end) diff --git a/xmake/toolchains/armclang/xmake.lua b/xmake/toolchains/armclang/xmake.lua new file mode 100644 index 000000000..5461d2f3d --- /dev/null +++ b/xmake/toolchains/armclang/xmake.lua @@ -0,0 +1,41 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +toolchain("armclang") + + set_homepage("https://www2.keil.com/mdk5/compiler/6") + set_description("ARM Compiler Version 6 of Keil MDK") + + set_kind("standalone") + + set_toolset("cc", "armclang") + set_toolset("cxx", "armclang") + set_toolset("ld", "armlink") + set_toolset("sh", "armlink") + set_toolset("ar", "armar") + set_toolset("ex", "armar") + set_toolset("as", "armasm") + + on_check(function (toolchain) + return import("lib.detect.find_tool")("armclang") + end) + + on_load(function (toolchain) + end) diff --git a/xmake/toolchains/clang/xmake.lua b/xmake/toolchains/clang/xmake.lua index cf184baf6..ea4a45e30 100644 --- a/xmake/toolchains/clang/xmake.lua +++ b/xmake/toolchains/clang/xmake.lua @@ -18,17 +18,13 @@ -- @file xmake.lua -- --- define toolchain toolchain("clang") - -- set homepage set_homepage("https://clang.llvm.org/") set_description("A C language family frontend for LLVM") - -- mark as standalone toolchain set_kind("standalone") - -- set toolset set_toolset("cc", "clang") set_toolset("cxx", "clang", "clang++") set_toolset("ld", "clang++", "clang") @@ -40,15 +36,11 @@ toolchain("clang") set_toolset("mxx", "clang", "clang++") set_toolset("as", "clang") - -- check toolchain on_check(function (toolchain) return import("lib.detect.find_tool")("clang") end) - -- on load on_load(function (toolchain) - - -- add march flags local march if toolchain:is_arch("x86_64", "x64") then march = "-m64" -- cgit v1.3.1 From cefbbead0df98e924e79384765eccabd8850c5d1 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 26 Oct 2021 22:52:49 +0800 Subject: add arm tools --- xmake/modules/core/tools/armar.lua | 26 ++++++++++++++++++++++++++ xmake/modules/core/tools/armasm.lua | 25 +++++++++++++++++++++++++ xmake/modules/core/tools/armlink.lua | 25 +++++++++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 xmake/modules/core/tools/armar.lua create mode 100644 xmake/modules/core/tools/armasm.lua create mode 100644 xmake/modules/core/tools/armlink.lua diff --git a/xmake/modules/core/tools/armar.lua b/xmake/modules/core/tools/armar.lua new file mode 100644 index 000000000..66740c11a --- /dev/null +++ b/xmake/modules/core/tools/armar.lua @@ -0,0 +1,26 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file armar.lua +-- + +inherit("ar") + +function init(self) + _super.init(self) +end + diff --git a/xmake/modules/core/tools/armasm.lua b/xmake/modules/core/tools/armasm.lua new file mode 100644 index 000000000..7820eea69 --- /dev/null +++ b/xmake/modules/core/tools/armasm.lua @@ -0,0 +1,25 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file armasm.lua +-- + +inherit("gcc") + +function init(self) + _super.init(self) +end diff --git a/xmake/modules/core/tools/armlink.lua b/xmake/modules/core/tools/armlink.lua new file mode 100644 index 000000000..34895be6c --- /dev/null +++ b/xmake/modules/core/tools/armlink.lua @@ -0,0 +1,25 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file armlink.lua +-- + +inherit("gcc") + +function init(self) + _super.init(self) +end -- cgit v1.3.1 From 59a6225f09410e8e4cdadd224e31f92d575537e3 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 26 Oct 2021 22:59:59 +0800 Subject: improve armclang --- .../mdk/hello/src/RTE/Device/ARMCM3/ARMCM3_ac5.sct | 76 +++++++++ .../hello/src/RTE/Device/ARMCM3/startup_ARMCM3.c | 150 ++++++++++++++++++ .../hello/src/RTE/Device/ARMCM3/startup_ARMCM3.s | 172 +++++++++++++++++++++ .../hello/src/RTE/Device/ARMCM3/system_ARMCM3.c | 65 ++++++++ tests/projects/mdk/hello/src/hello.c | 4 + tests/projects/mdk/hello/xmake.lua | 6 + xmake/modules/detect/tools/armclang/has_flags.lua | 23 +++ xmake/toolchains/armcc/xmake.lua | 1 - xmake/toolchains/armclang/xmake.lua | 4 +- 9 files changed, 499 insertions(+), 2 deletions(-) create mode 100644 tests/projects/mdk/hello/src/RTE/Device/ARMCM3/ARMCM3_ac5.sct create mode 100644 tests/projects/mdk/hello/src/RTE/Device/ARMCM3/startup_ARMCM3.c create mode 100644 tests/projects/mdk/hello/src/RTE/Device/ARMCM3/startup_ARMCM3.s create mode 100644 tests/projects/mdk/hello/src/RTE/Device/ARMCM3/system_ARMCM3.c create mode 100644 tests/projects/mdk/hello/src/hello.c create mode 100644 tests/projects/mdk/hello/xmake.lua create mode 100644 xmake/modules/detect/tools/armclang/has_flags.lua diff --git a/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/ARMCM3_ac5.sct b/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/ARMCM3_ac5.sct new file mode 100644 index 000000000..91666461d --- /dev/null +++ b/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/ARMCM3_ac5.sct @@ -0,0 +1,76 @@ +#! armcc -E +; command above MUST be in first line (no comment above!) + +/* +;-------- <<< Use Configuration Wizard in Context Menu >>> ------------------- +*/ + +/*--------------------- Flash Configuration ---------------------------------- +; Flash Configuration +; Flash Base Address <0x0-0xFFFFFFFF:8> +; Flash Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + *----------------------------------------------------------------------------*/ +#define __ROM_BASE 0x00000000 +#define __ROM_SIZE 0x00080000 + +/*--------------------- Embedded RAM Configuration --------------------------- +; RAM Configuration +; RAM Base Address <0x0-0xFFFFFFFF:8> +; RAM Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + *----------------------------------------------------------------------------*/ +#define __RAM_BASE 0x20000000 +#define __RAM_SIZE 0x00040000 + +/*--------------------- Stack / Heap Configuration --------------------------- +; Stack / Heap Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + *----------------------------------------------------------------------------*/ +#define __STACK_SIZE 0x00000200 +#define __HEAP_SIZE 0x00000C00 + +/* +;------------- <<< end of configuration section >>> --------------------------- +*/ + + +/*---------------------------------------------------------------------------- + User Stack & Heap boundary definition + *----------------------------------------------------------------------------*/ +#define __STACK_TOP (__RAM_BASE + __RAM_SIZE) /* starts at end of RAM */ +#define __HEAP_BASE (AlignExpr(+0, 8)) /* starts after RW_RAM section, 8 byte aligned */ + + +/*---------------------------------------------------------------------------- + Scatter File Definitions definition + *----------------------------------------------------------------------------*/ +#define __RO_BASE __ROM_BASE +#define __RO_SIZE __ROM_SIZE + +#define __RW_BASE __RAM_BASE +#define __RW_SIZE (__RAM_SIZE - __STACK_SIZE - __HEAP_SIZE) + + +LR_ROM __RO_BASE __RO_SIZE { ; load region size_region + ER_ROM __RO_BASE __RO_SIZE { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + .ANY (+XO) + } + + RW_RAM __RW_BASE __RW_SIZE { ; RW data + .ANY (+RW +ZI) + } + +#if __HEAP_SIZE > 0 + ARM_LIB_HEAP __HEAP_BASE EMPTY __HEAP_SIZE { ; Reserve empty region for heap + } +#endif + + ARM_LIB_STACK __STACK_TOP EMPTY -__STACK_SIZE { ; Reserve empty region for stack + } +} diff --git a/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/startup_ARMCM3.c b/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/startup_ARMCM3.c new file mode 100644 index 000000000..da67c87c9 --- /dev/null +++ b/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/startup_ARMCM3.c @@ -0,0 +1,150 @@ +/****************************************************************************** + * @file startup_ARMCM3.c + * @brief CMSIS-Core(M) Device Startup File for a Cortex-M3 Device + * @version V2.0.3 + * @date 31. March 2020 + ******************************************************************************/ +/* + * Copyright (c) 2009-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 (ARMCM3) + #include "ARMCM3.h" +#else + #error device not specified! +#endif + +/*---------------------------------------------------------------------------- + External References + *----------------------------------------------------------------------------*/ +extern uint32_t __INITIAL_SP; + +extern __NO_RETURN void __PROGRAM_START(void); + +/*---------------------------------------------------------------------------- + Internal References + *----------------------------------------------------------------------------*/ +__NO_RETURN void Reset_Handler (void); + void Default_Handler(void); + +/*---------------------------------------------------------------------------- + Exception / Interrupt Handler + *----------------------------------------------------------------------------*/ +/* Exceptions */ +void NMI_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); +void HardFault_Handler (void) __attribute__ ((weak)); +void MemManage_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); +void BusFault_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); +void UsageFault_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); +void SVC_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); +void DebugMon_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); +void PendSV_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); +void SysTick_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); + +void Interrupt0_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); +void Interrupt1_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); +void Interrupt2_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); +void Interrupt3_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); +void Interrupt4_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); +void Interrupt5_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); +void Interrupt6_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); +void Interrupt7_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); +void Interrupt8_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); +void Interrupt9_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); + + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + +extern const VECTOR_TABLE_Type __VECTOR_TABLE[240]; + const VECTOR_TABLE_Type __VECTOR_TABLE[240] __VECTOR_TABLE_ATTRIBUTE = { + (VECTOR_TABLE_Type)(&__INITIAL_SP), /* Initial Stack Pointer */ + Reset_Handler, /* Reset Handler */ + NMI_Handler, /* -14 NMI Handler */ + HardFault_Handler, /* -13 Hard Fault Handler */ + MemManage_Handler, /* -12 MPU Fault Handler */ + BusFault_Handler, /* -11 Bus Fault Handler */ + UsageFault_Handler, /* -10 Usage Fault Handler */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + SVC_Handler, /* -5 SVCall Handler */ + DebugMon_Handler, /* -4 Debug Monitor Handler */ + 0, /* Reserved */ + PendSV_Handler, /* -2 PendSV Handler */ + SysTick_Handler, /* -1 SysTick Handler */ + + /* Interrupts */ + Interrupt0_Handler, /* 0 Interrupt 0 */ + Interrupt1_Handler, /* 1 Interrupt 1 */ + Interrupt2_Handler, /* 2 Interrupt 2 */ + Interrupt3_Handler, /* 3 Interrupt 3 */ + Interrupt4_Handler, /* 4 Interrupt 4 */ + Interrupt5_Handler, /* 5 Interrupt 5 */ + Interrupt6_Handler, /* 6 Interrupt 6 */ + Interrupt7_Handler, /* 7 Interrupt 7 */ + Interrupt8_Handler, /* 8 Interrupt 8 */ + Interrupt9_Handler /* 9 Interrupt 9 */ + /* Interrupts 10 .. 223 are left out */ +}; + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +/*---------------------------------------------------------------------------- + Reset Handler called on controller reset + *----------------------------------------------------------------------------*/ +__NO_RETURN void Reset_Handler(void) +{ + SystemInit(); /* CMSIS System Initialization */ + __PROGRAM_START(); /* Enter PreMain (C library entry point) */ +} + + +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wmissing-noreturn" +#endif + +/*---------------------------------------------------------------------------- + Hard Fault Handler + *----------------------------------------------------------------------------*/ +void HardFault_Handler(void) +{ + while(1); +} + +/*---------------------------------------------------------------------------- + Default Handler for Exceptions / Interrupts + *----------------------------------------------------------------------------*/ +void Default_Handler(void) +{ + while(1); +} + +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang diagnostic pop +#endif + diff --git a/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/startup_ARMCM3.s b/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/startup_ARMCM3.s new file mode 100644 index 000000000..efe40c1e3 --- /dev/null +++ b/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/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/mdk/hello/src/RTE/Device/ARMCM3/system_ARMCM3.c b/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/system_ARMCM3.c new file mode 100644 index 000000000..19484537f --- /dev/null +++ b/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/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/mdk/hello/src/hello.c b/tests/projects/mdk/hello/src/hello.c new file mode 100644 index 000000000..a6e46accc --- /dev/null +++ b/tests/projects/mdk/hello/src/hello.c @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} diff --git a/tests/projects/mdk/hello/xmake.lua b/tests/projects/mdk/hello/xmake.lua new file mode 100644 index 000000000..faa68cf5f --- /dev/null +++ b/tests/projects/mdk/hello/xmake.lua @@ -0,0 +1,6 @@ +add_rules("mode.debug", "mode.release") +target("hello") + set_kind("binary") + set_extension(".axf") + add_files("src/**.c", "src/**.s") + diff --git a/xmake/modules/detect/tools/armclang/has_flags.lua b/xmake/modules/detect/tools/armclang/has_flags.lua new file mode 100644 index 000000000..6464e10b6 --- /dev/null +++ b/xmake/modules/detect/tools/armclang/has_flags.lua @@ -0,0 +1,23 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file has_flags.lua +-- + +-- imports +inherit("detect.tools.gcc.has_flags") + diff --git a/xmake/toolchains/armcc/xmake.lua b/xmake/toolchains/armcc/xmake.lua index 1ba3a15eb..95f1d0528 100644 --- a/xmake/toolchains/armcc/xmake.lua +++ b/xmake/toolchains/armcc/xmake.lua @@ -28,7 +28,6 @@ toolchain("armcc") set_toolset("cc", "armcc") set_toolset("cxx", "armcc") set_toolset("ld", "armlink") - set_toolset("sh", "armlink") set_toolset("ar", "armar") set_toolset("ex", "armar") set_toolset("as", "armasm") diff --git a/xmake/toolchains/armclang/xmake.lua b/xmake/toolchains/armclang/xmake.lua index 5461d2f3d..20ee896fc 100644 --- a/xmake/toolchains/armclang/xmake.lua +++ b/xmake/toolchains/armclang/xmake.lua @@ -28,7 +28,6 @@ toolchain("armclang") set_toolset("cc", "armclang") set_toolset("cxx", "armclang") set_toolset("ld", "armlink") - set_toolset("sh", "armlink") set_toolset("ar", "armar") set_toolset("ex", "armar") set_toolset("as", "armasm") @@ -38,4 +37,7 @@ toolchain("armclang") end) on_load(function (toolchain) + toolchain:add("cxflags", "--target=aarch64-arm-none-eabi") + toolchain:add("asflags", "--target=aarch64-arm-none-eabi") + toolchain:add("ldflags", "--target=aarch64-arm-none-eabi") end) -- cgit v1.3.1 From f818c0d180bd0e19070dbe03e0cbc1405712b2ed Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 26 Oct 2021 23:06:48 +0800 Subject: impl armcc and armasm --- .../hello/src/RTE/Device/ARMCM3/startup_ARMCM3.c | 150 -------------------- tests/projects/mdk/hello/xmake.lua | 2 +- xmake/modules/core/tools/armasm.lua | 146 ++++++++++++++++++- xmake/modules/core/tools/armcc.lua | 155 ++++++++++++++++++++- xmake/modules/core/tools/sdcc.lua | 5 +- xmake/modules/detect/tools/armcc/has_flags.lua | 23 +++ xmake/toolchains/armcc/xmake.lua | 3 + 7 files changed, 327 insertions(+), 157 deletions(-) delete mode 100644 tests/projects/mdk/hello/src/RTE/Device/ARMCM3/startup_ARMCM3.c create mode 100644 xmake/modules/detect/tools/armcc/has_flags.lua diff --git a/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/startup_ARMCM3.c b/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/startup_ARMCM3.c deleted file mode 100644 index da67c87c9..000000000 --- a/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/startup_ARMCM3.c +++ /dev/null @@ -1,150 +0,0 @@ -/****************************************************************************** - * @file startup_ARMCM3.c - * @brief CMSIS-Core(M) Device Startup File for a Cortex-M3 Device - * @version V2.0.3 - * @date 31. March 2020 - ******************************************************************************/ -/* - * Copyright (c) 2009-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 (ARMCM3) - #include "ARMCM3.h" -#else - #error device not specified! -#endif - -/*---------------------------------------------------------------------------- - External References - *----------------------------------------------------------------------------*/ -extern uint32_t __INITIAL_SP; - -extern __NO_RETURN void __PROGRAM_START(void); - -/*---------------------------------------------------------------------------- - Internal References - *----------------------------------------------------------------------------*/ -__NO_RETURN void Reset_Handler (void); - void Default_Handler(void); - -/*---------------------------------------------------------------------------- - Exception / Interrupt Handler - *----------------------------------------------------------------------------*/ -/* Exceptions */ -void NMI_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); -void HardFault_Handler (void) __attribute__ ((weak)); -void MemManage_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); -void BusFault_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); -void UsageFault_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); -void SVC_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); -void DebugMon_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); -void PendSV_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); -void SysTick_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); - -void Interrupt0_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); -void Interrupt1_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); -void Interrupt2_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); -void Interrupt3_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); -void Interrupt4_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); -void Interrupt5_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); -void Interrupt6_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); -void Interrupt7_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); -void Interrupt8_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); -void Interrupt9_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); - - -/*---------------------------------------------------------------------------- - Exception / Interrupt Vector table - *----------------------------------------------------------------------------*/ - -#if defined ( __GNUC__ ) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#endif - -extern const VECTOR_TABLE_Type __VECTOR_TABLE[240]; - const VECTOR_TABLE_Type __VECTOR_TABLE[240] __VECTOR_TABLE_ATTRIBUTE = { - (VECTOR_TABLE_Type)(&__INITIAL_SP), /* Initial Stack Pointer */ - Reset_Handler, /* Reset Handler */ - NMI_Handler, /* -14 NMI Handler */ - HardFault_Handler, /* -13 Hard Fault Handler */ - MemManage_Handler, /* -12 MPU Fault Handler */ - BusFault_Handler, /* -11 Bus Fault Handler */ - UsageFault_Handler, /* -10 Usage Fault Handler */ - 0, /* Reserved */ - 0, /* Reserved */ - 0, /* Reserved */ - 0, /* Reserved */ - SVC_Handler, /* -5 SVCall Handler */ - DebugMon_Handler, /* -4 Debug Monitor Handler */ - 0, /* Reserved */ - PendSV_Handler, /* -2 PendSV Handler */ - SysTick_Handler, /* -1 SysTick Handler */ - - /* Interrupts */ - Interrupt0_Handler, /* 0 Interrupt 0 */ - Interrupt1_Handler, /* 1 Interrupt 1 */ - Interrupt2_Handler, /* 2 Interrupt 2 */ - Interrupt3_Handler, /* 3 Interrupt 3 */ - Interrupt4_Handler, /* 4 Interrupt 4 */ - Interrupt5_Handler, /* 5 Interrupt 5 */ - Interrupt6_Handler, /* 6 Interrupt 6 */ - Interrupt7_Handler, /* 7 Interrupt 7 */ - Interrupt8_Handler, /* 8 Interrupt 8 */ - Interrupt9_Handler /* 9 Interrupt 9 */ - /* Interrupts 10 .. 223 are left out */ -}; - -#if defined ( __GNUC__ ) -#pragma GCC diagnostic pop -#endif - -/*---------------------------------------------------------------------------- - Reset Handler called on controller reset - *----------------------------------------------------------------------------*/ -__NO_RETURN void Reset_Handler(void) -{ - SystemInit(); /* CMSIS System Initialization */ - __PROGRAM_START(); /* Enter PreMain (C library entry point) */ -} - - -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wmissing-noreturn" -#endif - -/*---------------------------------------------------------------------------- - Hard Fault Handler - *----------------------------------------------------------------------------*/ -void HardFault_Handler(void) -{ - while(1); -} - -/*---------------------------------------------------------------------------- - Default Handler for Exceptions / Interrupts - *----------------------------------------------------------------------------*/ -void Default_Handler(void) -{ - while(1); -} - -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #pragma clang diagnostic pop -#endif - diff --git a/tests/projects/mdk/hello/xmake.lua b/tests/projects/mdk/hello/xmake.lua index faa68cf5f..af9f2acde 100644 --- a/tests/projects/mdk/hello/xmake.lua +++ b/tests/projects/mdk/hello/xmake.lua @@ -3,4 +3,4 @@ target("hello") set_kind("binary") set_extension(".axf") add_files("src/**.c", "src/**.s") - + add_defines("__EVAL", "__MICROLIB") diff --git a/xmake/modules/core/tools/armasm.lua b/xmake/modules/core/tools/armasm.lua index 7820eea69..98d2bea18 100644 --- a/xmake/modules/core/tools/armasm.lua +++ b/xmake/modules/core/tools/armasm.lua @@ -18,8 +18,150 @@ -- @file armasm.lua -- -inherit("gcc") +-- imports +import("core.base.option") +import("core.base.global") +import("core.language.language") +import("utils.progress") +-- init it function init(self) - _super.init(self) end + +-- make the symbol flag +function nf_symbol(self, level) + -- only for source kind + local kind = self:kind() + if language.sourcekinds()[kind] then + local maps = _g.symbol_maps + if not maps then + maps = + { + debug = "-g" + } + _g.symbol_maps = maps + end + return maps[level .. '_' .. kind] or maps[level] + end +end + +-- make the optimize flag +function nf_optimize(self, level) + local maps = + { + none = "-O0" + , fast = "-O1" + , faster = "-O2" + , fastest = "-O3" + , smallest = "-Os" + , aggressive = "-Ofast" + } + return maps[level] +end + +-- make the language flag +function nf_language(self, stdname) + + -- the stdc maps + if _g.cmaps == nil then + _g.cmaps = + { + ansi = "-c89" + , c89 = "-c89" + , gnu89 = "-c89" + , c99 = "-c99" + , gnu99 = "-c99" + , c11 = "-c11" + , gnu11 = "-c11" + , clatest = {"-c11", "-c99", "-c89"} + , gnulatest = {"-c11", "-c99", "-c89"} + } + end + local maps = _g.cmaps + local result = maps[stdname] + if type(result) == "table" then + for _, v in ipairs(result) do + if self:has_flags(v, "cxflags") then + result = v + maps[stdname] = result + return result + end + end + else + return result + end +end + +-- make the includedir flag +function nf_includedir(self, dir) + return {"-I" .. dir} +end + +-- make the sysincludedir flag +function nf_sysincludedir(self, dir) + return nf_includedir(self, dir) +end + +-- make the compile arguments list +function compargv(self, sourcefile, objectfile, flags) + return self:program(), table.join("-c", flags, "-o", objectfile, sourcefile) +end + +-- compile the source file +function compile(self, sourcefile, objectfile, dependinfo, flags) + + -- ensure the object directory + os.mkdir(path.directory(objectfile)) + + -- compile it + try + { + function () + local outdata, errdata = os.iorunv(compargv(self, sourcefile, objectfile, flags)) + return (outdata or "") .. (errdata or "") + end, + catch + { + function (errors) + + -- try removing the old object file for forcing to rebuild this source file + os.tryrm(objectfile) + + -- find the start line of error + local lines = tostring(errors):split("\n") + local start = 0 + for index, line in ipairs(lines) do + if line:find("error:", 1, true) or line:find("错误:", 1, true) then + start = index + break + end + end + + -- get 16 lines of errors + if start > 0 or not option.get("verbose") then + if start == 0 then start = 1 end + errors = table.concat(table.slice(lines, start, start + ((#lines - start > 16) and 16 or (#lines - start))), "\n") + end + + -- raise compiling errors + raise(errors) + end + }, + finally + { + function (ok, warnings) + + -- print some warnings + if warnings and #warnings > 0 and (option.get("verbose") or option.get("warning") or global.get("build_warning")) then + if progress.showing_without_scroll() then + print("") + end + cprint("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) + end + end + } + } +end + + + diff --git a/xmake/modules/core/tools/armcc.lua b/xmake/modules/core/tools/armcc.lua index 40854eb7a..6215242ec 100644 --- a/xmake/modules/core/tools/armcc.lua +++ b/xmake/modules/core/tools/armcc.lua @@ -18,8 +18,159 @@ -- @file armcc.lua -- -inherit("gcc") +-- imports +import("core.base.option") +import("core.base.global") +import("core.language.language") +import("utils.progress") +-- init it function init(self) - _super.init(self) end + +-- make the symbol flag +function nf_symbol(self, level) + -- only for source kind + local kind = self:kind() + if language.sourcekinds()[kind] then + local maps = _g.symbol_maps + if not maps then + maps = + { + debug = "-g" + } + _g.symbol_maps = maps + end + return maps[level .. '_' .. kind] or maps[level] + end +end + +-- make the optimize flag +function nf_optimize(self, level) + local maps = + { + none = "-O0" + , fast = "-O1" + , faster = "-O2" + , fastest = "-O3" + , smallest = "-Os" + , aggressive = "-Ofast" + } + return maps[level] +end + +-- make the language flag +function nf_language(self, stdname) + + -- the stdc maps + if _g.cmaps == nil then + _g.cmaps = + { + ansi = "-c89" + , c89 = "-c89" + , gnu89 = "-c89" + , c99 = "-c99" + , gnu99 = "-c99" + , c11 = "-c11" + , gnu11 = "-c11" + , clatest = {"-c11", "-c99", "-c89"} + , gnulatest = {"-c11", "-c99", "-c89"} + } + end + local maps = _g.cmaps + local result = maps[stdname] + if type(result) == "table" then + for _, v in ipairs(result) do + if self:has_flags(v, "cxflags") then + result = v + maps[stdname] = result + return result + end + end + else + return result + end +end + +-- make the define flag +function nf_define(self, macro) + return "-D" .. macro +end + +-- make the undefine flag +function nf_undefine(self, macro) + return "-U" .. macro +end + +-- make the includedir flag +function nf_includedir(self, dir) + return {"-I" .. dir} +end + +-- make the sysincludedir flag +function nf_sysincludedir(self, dir) + return nf_includedir(self, dir) +end + +-- make the compile arguments list +function compargv(self, sourcefile, objectfile, flags) + return self:program(), table.join("-c", flags, "-o", objectfile, sourcefile) +end + +-- compile the source file +function compile(self, sourcefile, objectfile, dependinfo, flags) + + -- ensure the object directory + os.mkdir(path.directory(objectfile)) + + -- compile it + try + { + function () + local outdata, errdata = os.iorunv(compargv(self, sourcefile, objectfile, flags)) + return (outdata or "") .. (errdata or "") + end, + catch + { + function (errors) + + -- try removing the old object file for forcing to rebuild this source file + os.tryrm(objectfile) + + -- find the start line of error + local lines = tostring(errors):split("\n") + local start = 0 + for index, line in ipairs(lines) do + if line:find("error:", 1, true) or line:find("错误:", 1, true) then + start = index + break + end + end + + -- get 16 lines of errors + if start > 0 or not option.get("verbose") then + if start == 0 then start = 1 end + errors = table.concat(table.slice(lines, start, start + ((#lines - start > 16) and 16 or (#lines - start))), "\n") + end + + -- raise compiling errors + raise(errors) + end + }, + finally + { + function (ok, warnings) + + -- print some warnings + if warnings and #warnings > 0 and (option.get("verbose") or option.get("warning") or global.get("build_warning")) then + if progress.showing_without_scroll() then + print("") + end + cprint("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) + end + end + } + } +end + + diff --git a/xmake/modules/core/tools/sdcc.lua b/xmake/modules/core/tools/sdcc.lua index 82d6cd78a..0153ed652 100644 --- a/xmake/modules/core/tools/sdcc.lua +++ b/xmake/modules/core/tools/sdcc.lua @@ -126,11 +126,12 @@ function nf_language(self, stdname) if self:has_flags(v, "cxflags") then result = v maps[stdname] = result - break + return result end end + else + return result end - return result end -- make the define flag diff --git a/xmake/modules/detect/tools/armcc/has_flags.lua b/xmake/modules/detect/tools/armcc/has_flags.lua new file mode 100644 index 000000000..6464e10b6 --- /dev/null +++ b/xmake/modules/detect/tools/armcc/has_flags.lua @@ -0,0 +1,23 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file has_flags.lua +-- + +-- imports +inherit("detect.tools.gcc.has_flags") + diff --git a/xmake/toolchains/armcc/xmake.lua b/xmake/toolchains/armcc/xmake.lua index 95f1d0528..d280d0344 100644 --- a/xmake/toolchains/armcc/xmake.lua +++ b/xmake/toolchains/armcc/xmake.lua @@ -37,4 +37,7 @@ toolchain("armcc") end) on_load(function (toolchain) + toolchain:add("cxflags", "--cpu Cortex-M3", {force = true}) + toolchain:add("asflags", "--cpu Cortex-M3", {force = true}) + toolchain:add("ldflags", "--cpu Cortex-M3", {force = true}) end) -- cgit v1.3.1 From ccfb92f406dbd1535db64cfdb0e4a80d031805e9 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 26 Oct 2021 23:11:01 +0800 Subject: improve mdk test --- tests/projects/mdk/hello/src/ARMCM3_ac5.sct | 76 + .../mdk/hello/src/RTE/Device/ARMCM3/ARMCM3_ac5.sct | 76 - .../hello/src/RTE/Device/ARMCM3/startup_ARMCM3.s | 172 -- .../hello/src/RTE/Device/ARMCM3/system_ARMCM3.c | 65 - tests/projects/mdk/hello/src/hello.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_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 | 4 + tests/projects/mdk/hello/src/startup_ARMCM3.s | 172 ++ tests/projects/mdk/hello/src/system_ARMCM3.c | 65 + tests/projects/mdk/hello/xmake.lua | 1 + xmake/modules/core/tools/armasm.lua | 2 +- 17 files changed, 3935 insertions(+), 318 deletions(-) create mode 100644 tests/projects/mdk/hello/src/ARMCM3_ac5.sct delete mode 100644 tests/projects/mdk/hello/src/RTE/Device/ARMCM3/ARMCM3_ac5.sct delete mode 100644 tests/projects/mdk/hello/src/RTE/Device/ARMCM3/startup_ARMCM3.s delete mode 100644 tests/projects/mdk/hello/src/RTE/Device/ARMCM3/system_ARMCM3.c delete mode 100644 tests/projects/mdk/hello/src/hello.c create mode 100644 tests/projects/mdk/hello/src/lib/cmsis/ARMCM3.h create mode 100644 tests/projects/mdk/hello/src/lib/cmsis/cmsis_armcc.h create mode 100644 tests/projects/mdk/hello/src/lib/cmsis/cmsis_compiler.h create mode 100644 tests/projects/mdk/hello/src/lib/cmsis/cmsis_version.h create mode 100644 tests/projects/mdk/hello/src/lib/cmsis/core_cm3.h create mode 100644 tests/projects/mdk/hello/src/lib/cmsis/mpu_armv7.h create mode 100644 tests/projects/mdk/hello/src/lib/cmsis/system_ARMCM3.h create mode 100644 tests/projects/mdk/hello/src/main.c create mode 100644 tests/projects/mdk/hello/src/startup_ARMCM3.s create mode 100644 tests/projects/mdk/hello/src/system_ARMCM3.c diff --git a/tests/projects/mdk/hello/src/ARMCM3_ac5.sct b/tests/projects/mdk/hello/src/ARMCM3_ac5.sct new file mode 100644 index 000000000..91666461d --- /dev/null +++ b/tests/projects/mdk/hello/src/ARMCM3_ac5.sct @@ -0,0 +1,76 @@ +#! armcc -E +; command above MUST be in first line (no comment above!) + +/* +;-------- <<< Use Configuration Wizard in Context Menu >>> ------------------- +*/ + +/*--------------------- Flash Configuration ---------------------------------- +; Flash Configuration +; Flash Base Address <0x0-0xFFFFFFFF:8> +; Flash Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + *----------------------------------------------------------------------------*/ +#define __ROM_BASE 0x00000000 +#define __ROM_SIZE 0x00080000 + +/*--------------------- Embedded RAM Configuration --------------------------- +; RAM Configuration +; RAM Base Address <0x0-0xFFFFFFFF:8> +; RAM Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + *----------------------------------------------------------------------------*/ +#define __RAM_BASE 0x20000000 +#define __RAM_SIZE 0x00040000 + +/*--------------------- Stack / Heap Configuration --------------------------- +; Stack / Heap Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + *----------------------------------------------------------------------------*/ +#define __STACK_SIZE 0x00000200 +#define __HEAP_SIZE 0x00000C00 + +/* +;------------- <<< end of configuration section >>> --------------------------- +*/ + + +/*---------------------------------------------------------------------------- + User Stack & Heap boundary definition + *----------------------------------------------------------------------------*/ +#define __STACK_TOP (__RAM_BASE + __RAM_SIZE) /* starts at end of RAM */ +#define __HEAP_BASE (AlignExpr(+0, 8)) /* starts after RW_RAM section, 8 byte aligned */ + + +/*---------------------------------------------------------------------------- + Scatter File Definitions definition + *----------------------------------------------------------------------------*/ +#define __RO_BASE __ROM_BASE +#define __RO_SIZE __ROM_SIZE + +#define __RW_BASE __RAM_BASE +#define __RW_SIZE (__RAM_SIZE - __STACK_SIZE - __HEAP_SIZE) + + +LR_ROM __RO_BASE __RO_SIZE { ; load region size_region + ER_ROM __RO_BASE __RO_SIZE { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + .ANY (+XO) + } + + RW_RAM __RW_BASE __RW_SIZE { ; RW data + .ANY (+RW +ZI) + } + +#if __HEAP_SIZE > 0 + ARM_LIB_HEAP __HEAP_BASE EMPTY __HEAP_SIZE { ; Reserve empty region for heap + } +#endif + + ARM_LIB_STACK __STACK_TOP EMPTY -__STACK_SIZE { ; Reserve empty region for stack + } +} diff --git a/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/ARMCM3_ac5.sct b/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/ARMCM3_ac5.sct deleted file mode 100644 index 91666461d..000000000 --- a/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/ARMCM3_ac5.sct +++ /dev/null @@ -1,76 +0,0 @@ -#! armcc -E -; command above MUST be in first line (no comment above!) - -/* -;-------- <<< Use Configuration Wizard in Context Menu >>> ------------------- -*/ - -/*--------------------- Flash Configuration ---------------------------------- -; Flash Configuration -; Flash Base Address <0x0-0xFFFFFFFF:8> -; Flash Size (in Bytes) <0x0-0xFFFFFFFF:8> -; - *----------------------------------------------------------------------------*/ -#define __ROM_BASE 0x00000000 -#define __ROM_SIZE 0x00080000 - -/*--------------------- Embedded RAM Configuration --------------------------- -; RAM Configuration -; RAM Base Address <0x0-0xFFFFFFFF:8> -; RAM Size (in Bytes) <0x0-0xFFFFFFFF:8> -; - *----------------------------------------------------------------------------*/ -#define __RAM_BASE 0x20000000 -#define __RAM_SIZE 0x00040000 - -/*--------------------- Stack / Heap Configuration --------------------------- -; Stack / Heap Configuration -; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> -; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> -; - *----------------------------------------------------------------------------*/ -#define __STACK_SIZE 0x00000200 -#define __HEAP_SIZE 0x00000C00 - -/* -;------------- <<< end of configuration section >>> --------------------------- -*/ - - -/*---------------------------------------------------------------------------- - User Stack & Heap boundary definition - *----------------------------------------------------------------------------*/ -#define __STACK_TOP (__RAM_BASE + __RAM_SIZE) /* starts at end of RAM */ -#define __HEAP_BASE (AlignExpr(+0, 8)) /* starts after RW_RAM section, 8 byte aligned */ - - -/*---------------------------------------------------------------------------- - Scatter File Definitions definition - *----------------------------------------------------------------------------*/ -#define __RO_BASE __ROM_BASE -#define __RO_SIZE __ROM_SIZE - -#define __RW_BASE __RAM_BASE -#define __RW_SIZE (__RAM_SIZE - __STACK_SIZE - __HEAP_SIZE) - - -LR_ROM __RO_BASE __RO_SIZE { ; load region size_region - ER_ROM __RO_BASE __RO_SIZE { ; load address = execution address - *.o (RESET, +First) - *(InRoot$$Sections) - .ANY (+RO) - .ANY (+XO) - } - - RW_RAM __RW_BASE __RW_SIZE { ; RW data - .ANY (+RW +ZI) - } - -#if __HEAP_SIZE > 0 - ARM_LIB_HEAP __HEAP_BASE EMPTY __HEAP_SIZE { ; Reserve empty region for heap - } -#endif - - ARM_LIB_STACK __STACK_TOP EMPTY -__STACK_SIZE { ; Reserve empty region for stack - } -} diff --git a/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/startup_ARMCM3.s b/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/startup_ARMCM3.s deleted file mode 100644 index efe40c1e3..000000000 --- a/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/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/RTE/Device/ARMCM3/system_ARMCM3.c b/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/system_ARMCM3.c deleted file mode 100644 index 19484537f..000000000 --- a/tests/projects/mdk/hello/src/RTE/Device/ARMCM3/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/src/hello.c b/tests/projects/mdk/hello/src/hello.c deleted file mode 100644 index a6e46accc..000000000 --- a/tests/projects/mdk/hello/src/hello.c +++ /dev/null @@ -1,4 +0,0 @@ -int main() -{ - return 0; -} diff --git a/tests/projects/mdk/hello/src/lib/cmsis/ARMCM3.h b/tests/projects/mdk/hello/src/lib/cmsis/ARMCM3.h new file mode 100644 index 000000000..44c0c23f4 --- /dev/null +++ b/tests/projects/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/mdk/hello/src/lib/cmsis/cmsis_armcc.h b/tests/projects/mdk/hello/src/lib/cmsis/cmsis_armcc.h new file mode 100644 index 000000000..a955d4713 --- /dev/null +++ b/tests/projects/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/mdk/hello/src/lib/cmsis/cmsis_compiler.h b/tests/projects/mdk/hello/src/lib/cmsis/cmsis_compiler.h new file mode 100644 index 000000000..adbf296f1 --- /dev/null +++ b/tests/projects/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/mdk/hello/src/lib/cmsis/cmsis_version.h b/tests/projects/mdk/hello/src/lib/cmsis/cmsis_version.h new file mode 100644 index 000000000..2f048e455 --- /dev/null +++ b/tests/projects/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/mdk/hello/src/lib/cmsis/core_cm3.h b/tests/projects/mdk/hello/src/lib/cmsis/core_cm3.h new file mode 100644 index 000000000..74fb87e5c --- /dev/null +++ b/tests/projects/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/mdk/hello/src/lib/cmsis/mpu_armv7.h b/tests/projects/mdk/hello/src/lib/cmsis/mpu_armv7.h new file mode 100644 index 000000000..d9eedf81a --- /dev/null +++ b/tests/projects/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/mdk/hello/src/lib/cmsis/system_ARMCM3.h b/tests/projects/mdk/hello/src/lib/cmsis/system_ARMCM3.h new file mode 100644 index 000000000..5d1237770 --- /dev/null +++ b/tests/projects/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/mdk/hello/src/main.c b/tests/projects/mdk/hello/src/main.c new file mode 100644 index 000000000..a6e46accc --- /dev/null +++ b/tests/projects/mdk/hello/src/main.c @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} diff --git a/tests/projects/mdk/hello/src/startup_ARMCM3.s b/tests/projects/mdk/hello/src/startup_ARMCM3.s new file mode 100644 index 000000000..efe40c1e3 --- /dev/null +++ b/tests/projects/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/mdk/hello/src/system_ARMCM3.c b/tests/projects/mdk/hello/src/system_ARMCM3.c new file mode 100644 index 000000000..19484537f --- /dev/null +++ b/tests/projects/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/mdk/hello/xmake.lua b/tests/projects/mdk/hello/xmake.lua index af9f2acde..d5a0429e4 100644 --- a/tests/projects/mdk/hello/xmake.lua +++ b/tests/projects/mdk/hello/xmake.lua @@ -4,3 +4,4 @@ target("hello") set_extension(".axf") add_files("src/**.c", "src/**.s") add_defines("__EVAL", "__MICROLIB") + add_includedirs("src/lib/cmsis") diff --git a/xmake/modules/core/tools/armasm.lua b/xmake/modules/core/tools/armasm.lua index 98d2bea18..181d8b7e8 100644 --- a/xmake/modules/core/tools/armasm.lua +++ b/xmake/modules/core/tools/armasm.lua @@ -104,7 +104,7 @@ end -- make the compile arguments list function compargv(self, sourcefile, objectfile, flags) - return self:program(), table.join("-c", flags, "-o", objectfile, sourcefile) + return self:program(), table.join(flags, "-o", objectfile, sourcefile) end -- compile the source file -- cgit v1.3.1 From 8654ee65203a6ed670bc671a73bf8f704510bf80 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 26 Oct 2021 23:13:56 +0800 Subject: add mdk.console --- tests/projects/mdk/hello/xmake.lua | 6 ++-- xmake/modules/detect/tools/armcc/has_flags.lua | 23 -------------- xmake/modules/detect/tools/armclang/has_flags.lua | 23 -------------- xmake/rules/mdk/xmake.lua | 38 +++++++++++++++++++++++ xmake/toolchains/armcc/xmake.lua | 5 --- 5 files changed, 41 insertions(+), 54 deletions(-) delete mode 100644 xmake/modules/detect/tools/armcc/has_flags.lua delete mode 100644 xmake/modules/detect/tools/armclang/has_flags.lua create mode 100644 xmake/rules/mdk/xmake.lua diff --git a/tests/projects/mdk/hello/xmake.lua b/tests/projects/mdk/hello/xmake.lua index d5a0429e4..2d375a05f 100644 --- a/tests/projects/mdk/hello/xmake.lua +++ b/tests/projects/mdk/hello/xmake.lua @@ -1,7 +1,7 @@ add_rules("mode.debug", "mode.release") target("hello") - set_kind("binary") - set_extension(".axf") - add_files("src/**.c", "src/**.s") + add_rules("mdk.console") + add_values("mdk.cpu", "Cortex-M3") + add_files("src/*.c", "src/*.s") add_defines("__EVAL", "__MICROLIB") add_includedirs("src/lib/cmsis") diff --git a/xmake/modules/detect/tools/armcc/has_flags.lua b/xmake/modules/detect/tools/armcc/has_flags.lua deleted file mode 100644 index 6464e10b6..000000000 --- a/xmake/modules/detect/tools/armcc/has_flags.lua +++ /dev/null @@ -1,23 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- 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 --- --- http://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. --- --- Copyright (C) 2015-present, TBOOX Open Source Group. --- --- @author ruki --- @file has_flags.lua --- - --- imports -inherit("detect.tools.gcc.has_flags") - diff --git a/xmake/modules/detect/tools/armclang/has_flags.lua b/xmake/modules/detect/tools/armclang/has_flags.lua deleted file mode 100644 index 6464e10b6..000000000 --- a/xmake/modules/detect/tools/armclang/has_flags.lua +++ /dev/null @@ -1,23 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- 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 --- --- http://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. --- --- Copyright (C) 2015-present, TBOOX Open Source Group. --- --- @author ruki --- @file has_flags.lua --- - --- imports -inherit("detect.tools.gcc.has_flags") - diff --git a/xmake/rules/mdk/xmake.lua b/xmake/rules/mdk/xmake.lua new file mode 100644 index 000000000..452d8a4d3 --- /dev/null +++ b/xmake/rules/mdk/xmake.lua @@ -0,0 +1,38 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +rule("mdk.console") + on_load(function (target) + -- we disable checking flags for cross toolchain automatically + target:set("policy", "check.auto_ignore_flags", false) + target:set("policy", "check.auto_map_flags", false) + + -- set default output binary + target:set("kind", "binary") + if not target:get("extension") then + target:set("extension", ".axf") + end + + -- set cpu + local cpu = assert(target:values("mdk.cpu"), "unknown cpu, please use `add_values(\"mdk.cpu\", \"\")` to set it!") + target:add("cxflags", "--cpu " .. cpu) + target:add("asflags", "--cpu " .. cpu) + target:add("ldflags", "--cpu " .. cpu) + end) diff --git a/xmake/toolchains/armcc/xmake.lua b/xmake/toolchains/armcc/xmake.lua index d280d0344..487b33604 100644 --- a/xmake/toolchains/armcc/xmake.lua +++ b/xmake/toolchains/armcc/xmake.lua @@ -36,8 +36,3 @@ toolchain("armcc") return import("lib.detect.find_tool")("armcc") end) - on_load(function (toolchain) - toolchain:add("cxflags", "--cpu Cortex-M3", {force = true}) - toolchain:add("asflags", "--cpu Cortex-M3", {force = true}) - toolchain:add("ldflags", "--cpu Cortex-M3", {force = true}) - end) -- cgit v1.3.1 From 38009bf0e115a8cd83299fe76cf0fdb86c8fbf67 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 26 Oct 2021 23:14:22 +0800 Subject: remove sct --- tests/projects/mdk/hello/src/ARMCM3_ac5.sct | 76 ----------------------------- 1 file changed, 76 deletions(-) delete mode 100644 tests/projects/mdk/hello/src/ARMCM3_ac5.sct diff --git a/tests/projects/mdk/hello/src/ARMCM3_ac5.sct b/tests/projects/mdk/hello/src/ARMCM3_ac5.sct deleted file mode 100644 index 91666461d..000000000 --- a/tests/projects/mdk/hello/src/ARMCM3_ac5.sct +++ /dev/null @@ -1,76 +0,0 @@ -#! armcc -E -; command above MUST be in first line (no comment above!) - -/* -;-------- <<< Use Configuration Wizard in Context Menu >>> ------------------- -*/ - -/*--------------------- Flash Configuration ---------------------------------- -; Flash Configuration -; Flash Base Address <0x0-0xFFFFFFFF:8> -; Flash Size (in Bytes) <0x0-0xFFFFFFFF:8> -; - *----------------------------------------------------------------------------*/ -#define __ROM_BASE 0x00000000 -#define __ROM_SIZE 0x00080000 - -/*--------------------- Embedded RAM Configuration --------------------------- -; RAM Configuration -; RAM Base Address <0x0-0xFFFFFFFF:8> -; RAM Size (in Bytes) <0x0-0xFFFFFFFF:8> -; - *----------------------------------------------------------------------------*/ -#define __RAM_BASE 0x20000000 -#define __RAM_SIZE 0x00040000 - -/*--------------------- Stack / Heap Configuration --------------------------- -; Stack / Heap Configuration -; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> -; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> -; - *----------------------------------------------------------------------------*/ -#define __STACK_SIZE 0x00000200 -#define __HEAP_SIZE 0x00000C00 - -/* -;------------- <<< end of configuration section >>> --------------------------- -*/ - - -/*---------------------------------------------------------------------------- - User Stack & Heap boundary definition - *----------------------------------------------------------------------------*/ -#define __STACK_TOP (__RAM_BASE + __RAM_SIZE) /* starts at end of RAM */ -#define __HEAP_BASE (AlignExpr(+0, 8)) /* starts after RW_RAM section, 8 byte aligned */ - - -/*---------------------------------------------------------------------------- - Scatter File Definitions definition - *----------------------------------------------------------------------------*/ -#define __RO_BASE __ROM_BASE -#define __RO_SIZE __ROM_SIZE - -#define __RW_BASE __RAM_BASE -#define __RW_SIZE (__RAM_SIZE - __STACK_SIZE - __HEAP_SIZE) - - -LR_ROM __RO_BASE __RO_SIZE { ; load region size_region - ER_ROM __RO_BASE __RO_SIZE { ; load address = execution address - *.o (RESET, +First) - *(InRoot$$Sections) - .ANY (+RO) - .ANY (+XO) - } - - RW_RAM __RW_BASE __RW_SIZE { ; RW data - .ANY (+RW +ZI) - } - -#if __HEAP_SIZE > 0 - ARM_LIB_HEAP __HEAP_BASE EMPTY __HEAP_SIZE { ; Reserve empty region for heap - } -#endif - - ARM_LIB_STACK __STACK_TOP EMPTY -__STACK_SIZE { ; Reserve empty region for stack - } -} -- cgit v1.3.1 From 80dd8e90c0eea596298463e521e64b27c4995a4d Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 26 Oct 2021 23:25:16 +0800 Subject: improve armcc and armclang --- .../mdk/hello/src/lib/cmsis/cmsis_armclang.h | 1503 ++++++++++++++++++++ tests/projects/mdk/hello/xmake.lua | 1 - xmake/rules/mdk/xmake.lua | 6 - xmake/toolchains/armcc/xmake.lua | 8 + xmake/toolchains/armclang/xmake.lua | 10 +- xmake/toolchains/sdcc/xmake.lua | 2 - 6 files changed, 1518 insertions(+), 12 deletions(-) create mode 100644 tests/projects/mdk/hello/src/lib/cmsis/cmsis_armclang.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 new file mode 100644 index 000000000..691141774 --- /dev/null +++ b/tests/projects/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/mdk/hello/xmake.lua b/tests/projects/mdk/hello/xmake.lua index 2d375a05f..710e29bcf 100644 --- a/tests/projects/mdk/hello/xmake.lua +++ b/tests/projects/mdk/hello/xmake.lua @@ -1,7 +1,6 @@ add_rules("mode.debug", "mode.release") target("hello") add_rules("mdk.console") - add_values("mdk.cpu", "Cortex-M3") add_files("src/*.c", "src/*.s") add_defines("__EVAL", "__MICROLIB") add_includedirs("src/lib/cmsis") diff --git a/xmake/rules/mdk/xmake.lua b/xmake/rules/mdk/xmake.lua index 452d8a4d3..640d40aee 100644 --- a/xmake/rules/mdk/xmake.lua +++ b/xmake/rules/mdk/xmake.lua @@ -29,10 +29,4 @@ rule("mdk.console") if not target:get("extension") then target:set("extension", ".axf") end - - -- set cpu - local cpu = assert(target:values("mdk.cpu"), "unknown cpu, please use `add_values(\"mdk.cpu\", \"\")` to set it!") - target:add("cxflags", "--cpu " .. cpu) - target:add("asflags", "--cpu " .. cpu) - target:add("ldflags", "--cpu " .. cpu) end) diff --git a/xmake/toolchains/armcc/xmake.lua b/xmake/toolchains/armcc/xmake.lua index 487b33604..a54269758 100644 --- a/xmake/toolchains/armcc/xmake.lua +++ b/xmake/toolchains/armcc/xmake.lua @@ -36,3 +36,11 @@ toolchain("armcc") return import("lib.detect.find_tool")("armcc") end) + on_load(function (toolchain) + local arch = toolchain:arch() + if arch then + toolchain:add("cxflags", "--cpu " .. arch) + toolchain:add("asflags", "--cpu " .. arch) + toolchain:add("ldflags", "--cpu " .. arch) + end + end) diff --git a/xmake/toolchains/armclang/xmake.lua b/xmake/toolchains/armclang/xmake.lua index 20ee896fc..c3fa6afd7 100644 --- a/xmake/toolchains/armclang/xmake.lua +++ b/xmake/toolchains/armclang/xmake.lua @@ -37,7 +37,11 @@ toolchain("armclang") end) on_load(function (toolchain) - toolchain:add("cxflags", "--target=aarch64-arm-none-eabi") - toolchain:add("asflags", "--target=aarch64-arm-none-eabi") - toolchain:add("ldflags", "--target=aarch64-arm-none-eabi") + local arch = toolchain:arch() + if arch then + toolchain:add("cxflags", "-target=arm-arm-none-eabi") + toolchain:add("cxflags", "-mcpu=" .. arch:lower()) + toolchain:add("asflags", "--cpu " .. arch) + toolchain:add("ldflags", "--cpu " .. arch) + end end) diff --git a/xmake/toolchains/sdcc/xmake.lua b/xmake/toolchains/sdcc/xmake.lua index 869135578..f196f916d 100644 --- a/xmake/toolchains/sdcc/xmake.lua +++ b/xmake/toolchains/sdcc/xmake.lua @@ -52,8 +52,6 @@ toolchain("sdcc") -- on load on_load(function (toolchain) - - -- add port flags for arch local arch = toolchain:arch() if arch then toolchain:add("cxflags", "-m" .. arch) -- cgit v1.3.1 From dea09f243e33b43c8c8be40d8a471b4580db1de7 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 26 Oct 2021 23:27:19 +0800 Subject: improve armlink --- tests/projects/mdk/hello/src/foo/foo.c | 4 ++++ tests/projects/mdk/hello/src/main.c | 4 +++- tests/projects/mdk/hello/xmake.lua | 6 ++++++ xmake/modules/core/tools/armlink.lua | 33 +++++++++++++++++++++++++++++++-- xmake/rules/mdk/xmake.lua | 10 ++++++++++ 5 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 tests/projects/mdk/hello/src/foo/foo.c diff --git a/tests/projects/mdk/hello/src/foo/foo.c b/tests/projects/mdk/hello/src/foo/foo.c new file mode 100644 index 000000000..e51afb553 --- /dev/null +++ b/tests/projects/mdk/hello/src/foo/foo.c @@ -0,0 +1,4 @@ +int foo(int x) +{ + return x; +} diff --git a/tests/projects/mdk/hello/src/main.c b/tests/projects/mdk/hello/src/main.c index a6e46accc..28d909a18 100644 --- a/tests/projects/mdk/hello/src/main.c +++ b/tests/projects/mdk/hello/src/main.c @@ -1,4 +1,6 @@ +int foo(int x); + int main() { - return 0; + return foo(1); } diff --git a/tests/projects/mdk/hello/xmake.lua b/tests/projects/mdk/hello/xmake.lua index 710e29bcf..97d640297 100644 --- a/tests/projects/mdk/hello/xmake.lua +++ b/tests/projects/mdk/hello/xmake.lua @@ -1,5 +1,11 @@ add_rules("mode.debug", "mode.release") + +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_defines("__EVAL", "__MICROLIB") diff --git a/xmake/modules/core/tools/armlink.lua b/xmake/modules/core/tools/armlink.lua index 34895be6c..02c2b4800 100644 --- a/xmake/modules/core/tools/armlink.lua +++ b/xmake/modules/core/tools/armlink.lua @@ -18,8 +18,37 @@ -- @file armlink.lua -- -inherit("gcc") +-- imports +import("core.base.option") +import("core.base.global") +import("utils.progress") function init(self) - _super.init(self) end + +-- make the link flag +function nf_link(self, lib) + return "lib" .. lib .. ".a" +end + +-- make the syslink flag +function nf_syslink(self, lib) + return nf_link(self, lib) +end + +-- make the linkdir flag +function nf_linkdir(self, dir) + return {"--userlibpath", dir} +end + +-- make the link arguments list +function linkargv(self, objectfiles, targetkind, targetfile, flags) + return self:program(), table.join("-o", targetfile, objectfiles, flags) +end + +-- link the target file +function link(self, objectfiles, targetkind, targetfile, flags) + os.mkdir(path.directory(targetfile)) + os.runv(linkargv(self, objectfiles, targetkind, targetfile, flags)) +end + diff --git a/xmake/rules/mdk/xmake.lua b/xmake/rules/mdk/xmake.lua index 640d40aee..f45e04c6e 100644 --- a/xmake/rules/mdk/xmake.lua +++ b/xmake/rules/mdk/xmake.lua @@ -30,3 +30,13 @@ rule("mdk.console") target:set("extension", ".axf") end end) + +rule("mdk.static") + on_load(function (target) + -- we disable checking flags for cross toolchain automatically + target:set("policy", "check.auto_ignore_flags", false) + target:set("policy", "check.auto_map_flags", false) + + -- set default output binary + target:set("kind", "static") + end) -- cgit v1.3.1 From ab85e9e49a2e5de91631726efaeb9b12fb6babce Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 26 Oct 2021 23:28:05 +0800 Subject: update changelog and readme --- CHANGELOG.md | 2 ++ README.md | 2 ++ README_zh.md | 2 ++ 3 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35c5e38ad..3243da493 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ * [#1765](https://github.com/xmake-io/xmake/issues/1756): Support nim language * [#1762](https://github.com/xmake-io/xmake/issues/1762): Manage and switch the given package envs for `xrepo env` * [#1767](https://github.com/xmake-io/xmake/issues/1767): Support Circle compiler +* [#1753](https://github.com/xmake-io/xmake/issues/1753): Support armcc/armclang toolchains for Keil/MDK ### Changes @@ -1120,6 +1121,7 @@ * [#1765](https://github.com/xmake-io/xmake/issues/1756): 支持 nim 语言 * [#1762](https://github.com/xmake-io/xmake/issues/1762): 为 `xrepo env` 管理和切换指定的环境配置 * [#1767](https://github.com/xmake-io/xmake/issues/1767): 支持 Circle 编译器 +* [#1753](https://github.com/xmake-io/xmake/issues/1753): 支持 Keil/MDK 的 armcc/armclang 工具链 ### 改进 diff --git a/README.md b/README.md index bd9fa28de..d73b31ff2 100644 --- a/README.md +++ b/README.md @@ -227,6 +227,8 @@ fpc Free Pascal Programming Language Compiler wasi WASI-enabled WebAssembly C/C++ toolchain nim Nim Programming Language Compiler circle A new C++20 compiler +armcc ARM Compiler Version 5 of Keil MDK +armclang ARM Compiler Version 6 of Keil MDK ``` ## Supported Languages diff --git a/README_zh.md b/README_zh.md index ac7941603..0783cf54c 100644 --- a/README_zh.md +++ b/README_zh.md @@ -235,6 +235,8 @@ fpc Free Pascal Programming Language Compiler wasi WASI-enabled WebAssembly C/C++ toolchain nim Nim Programming Language Compiler circle A new C++20 compiler +armcc ARM Compiler Version 5 of Keil MDK +armclang ARM Compiler Version 6 of Keil MDK ``` ## 支持语言 -- cgit v1.3.1 From 63c46927a81593033193b12bbf3a72db5c9726dd Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 27 Oct 2021 00:38:01 +0800 Subject: improve armcc and armclang toolchain --- xmake/core/tool/toolchain.lua | 2 +- xmake/toolchains/armcc/xmake.lua | 12 ++++++++++-- xmake/toolchains/armclang/xmake.lua | 11 +++++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/xmake/core/tool/toolchain.lua b/xmake/core/tool/toolchain.lua index 59e171d58..2ff1dbc65 100644 --- a/xmake/core/tool/toolchain.lua +++ b/xmake/core/tool/toolchain.lua @@ -210,7 +210,7 @@ end -- get the bin directory function _instance:bindir() local bindir = self:config("bindir") or config.get("bin") or self:info():get("bindir") - if not bindir and self:cross() and self:sdkdir() and os.isdir(path.join(self:sdkdir(), "bin")) then + if not bindir and self:is_cross() and self:sdkdir() and os.isdir(path.join(self:sdkdir(), "bin")) then bindir = path.join(self:sdkdir(), "bin") end return bindir diff --git a/xmake/toolchains/armcc/xmake.lua b/xmake/toolchains/armcc/xmake.lua index a54269758..1b819bc48 100644 --- a/xmake/toolchains/armcc/xmake.lua +++ b/xmake/toolchains/armcc/xmake.lua @@ -23,7 +23,7 @@ toolchain("armcc") set_homepage("https://www2.keil.com/mdk5/compiler/5") set_description("ARM Compiler Version 5 of Keil MDK") - set_kind("standalone") + set_kind("cross") set_toolset("cc", "armcc") set_toolset("cxx", "armcc") @@ -33,9 +33,17 @@ toolchain("armcc") set_toolset("as", "armasm") on_check(function (toolchain) - return import("lib.detect.find_tool")("armcc") + import("lib.detect.find_tool") + import("detect.sdks.find_mdk") + local mdk = find_mdk() + if mdk and mdk.sdkdir_armcc and find_tool("armcc") then + toolchain:config_set("sdkdir", mdk.sdkdir_armcc) + toolchain:configs_save() + return true + end end) + on_load(function (toolchain) local arch = toolchain:arch() if arch then diff --git a/xmake/toolchains/armclang/xmake.lua b/xmake/toolchains/armclang/xmake.lua index c3fa6afd7..bab9f582b 100644 --- a/xmake/toolchains/armclang/xmake.lua +++ b/xmake/toolchains/armclang/xmake.lua @@ -23,7 +23,7 @@ toolchain("armclang") set_homepage("https://www2.keil.com/mdk5/compiler/6") set_description("ARM Compiler Version 6 of Keil MDK") - set_kind("standalone") + set_kind("cross") set_toolset("cc", "armclang") set_toolset("cxx", "armclang") @@ -33,7 +33,14 @@ toolchain("armclang") set_toolset("as", "armasm") on_check(function (toolchain) - return import("lib.detect.find_tool")("armclang") + import("lib.detect.find_tool") + import("detect.sdks.find_mdk") + local mdk = find_mdk() + if mdk and mdk.sdkdir_armclang and find_tool("armclang") then + toolchain:config_set("sdkdir", mdk.sdkdir_armclang) + toolchain:configs_save() + return true + end end) on_load(function (toolchain) -- cgit v1.3.1 From 17b521d9059907d08390b462bcf09bd8075b84b3 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 27 Oct 2021 00:45:44 +0800 Subject: add table.contains --- xmake/core/base/table.lua | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua index 5f2c4585a..4f21ec358 100644 --- a/xmake/core/base/table.lua +++ b/xmake/core/base/table.lua @@ -227,6 +227,27 @@ function table.is_dictionary(dict) return type(dict) == "table" and dict[1] == nil end +-- does contain the given value in table? +function table.contains(t, value) + local found = false + if table.is_array(t) then + for _, v in ipairs(t) do + if v == value then + found = true + break + end + end + else + for _, v in pairs(t) do + if v == value then + found = true + break + end + end + end + return found +end + -- read data from iterator, push them to an array -- usage: table.to_array(ipairs("a", "b")) -> {{1,"a",n=2},{2,"b",n=2}},2 -- usage: table.to_array(io.lines("file")) -> {"line 1","line 2", ... , "line n"},n -- cgit v1.3.1 From da63bca85fe3d05368556056a90498d784c47bae Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 27 Oct 2021 22:32:39 +0800 Subject: remove ex kind --- tests/apis/set_toolchains/xmake.lua | 1 - xmake/core/tool/toolchain.lua | 1 - xmake/rules/utils/merge_archive/merge_archive.lua | 5 +++-- xmake/toolchains/armcc/xmake.lua | 1 - xmake/toolchains/armclang/xmake.lua | 1 - xmake/toolchains/circle/xmake.lua | 1 - xmake/toolchains/clang/xmake.lua | 1 - xmake/toolchains/cross/load.lua | 1 - xmake/toolchains/emcc/xmake.lua | 1 - xmake/toolchains/envs/xmake.lua | 1 - xmake/toolchains/gcc/xmake.lua | 1 - xmake/toolchains/icc/load.lua | 3 --- xmake/toolchains/ifort/load.lua | 1 - xmake/toolchains/llvm/xmake.lua | 1 - xmake/toolchains/mingw/xmake.lua | 2 -- xmake/toolchains/msvc/load.lua | 1 - xmake/toolchains/ndk/load.lua | 1 - xmake/toolchains/sdcc/xmake.lua | 1 - xmake/toolchains/wasi/xmake.lua | 1 - xmake/toolchains/xcode/xmake.lua | 1 - 20 files changed, 3 insertions(+), 24 deletions(-) diff --git a/tests/apis/set_toolchains/xmake.lua b/tests/apis/set_toolchains/xmake.lua index 83bdb4a5e..9db80f107 100644 --- a/tests/apis/set_toolchains/xmake.lua +++ b/tests/apis/set_toolchains/xmake.lua @@ -10,7 +10,6 @@ toolchain("myclang") set_toolset("ld", "clang++", "clang") set_toolset("sh", "clang++", "clang") set_toolset("ar", "ar") - set_toolset("ex", "ar") set_toolset("strip", "strip") set_toolset("mm", "clang") set_toolset("mxx", "clang", "clang++") diff --git a/xmake/core/tool/toolchain.lua b/xmake/core/tool/toolchain.lua index 2ff1dbc65..3779d9297 100644 --- a/xmake/core/tool/toolchain.lua +++ b/xmake/core/tool/toolchain.lua @@ -338,7 +338,6 @@ function _instance:_description(toolkind) ld = "the linker", sh = "the shared library linker", ar = "the static library archiver", - ex = "the static library extractor", mrc = "the windows resource compiler", strip = "the symbols stripper", dsymutil = "the symbols generator", diff --git a/xmake/rules/utils/merge_archive/merge_archive.lua b/xmake/rules/utils/merge_archive/merge_archive.lua index c98fc6b31..02d572afc 100644 --- a/xmake/rules/utils/merge_archive/merge_archive.lua +++ b/xmake/rules/utils/merge_archive/merge_archive.lua @@ -93,11 +93,12 @@ end -- do extract function _extract(target, libraryfile, objectdir) - local program, toolname = target:tool("ex") + local program, toolname = target:tool("ar") if program and toolname then if toolname:find("ar") then _extract_for_ar(program, libraryfile, objectdir) - elseif toolname == "lib" then + elseif toolname == "link" then + program = program:replace("link.exe", "lib.exe", {plain = true}) _extract_for_msvclib(program, libraryfile, objectdir) end else diff --git a/xmake/toolchains/armcc/xmake.lua b/xmake/toolchains/armcc/xmake.lua index 1b819bc48..f7c0fe837 100644 --- a/xmake/toolchains/armcc/xmake.lua +++ b/xmake/toolchains/armcc/xmake.lua @@ -29,7 +29,6 @@ toolchain("armcc") set_toolset("cxx", "armcc") set_toolset("ld", "armlink") set_toolset("ar", "armar") - set_toolset("ex", "armar") set_toolset("as", "armasm") on_check(function (toolchain) diff --git a/xmake/toolchains/armclang/xmake.lua b/xmake/toolchains/armclang/xmake.lua index bab9f582b..7faf06f0d 100644 --- a/xmake/toolchains/armclang/xmake.lua +++ b/xmake/toolchains/armclang/xmake.lua @@ -29,7 +29,6 @@ toolchain("armclang") set_toolset("cxx", "armclang") set_toolset("ld", "armlink") set_toolset("ar", "armar") - set_toolset("ex", "armar") set_toolset("as", "armasm") on_check(function (toolchain) diff --git a/xmake/toolchains/circle/xmake.lua b/xmake/toolchains/circle/xmake.lua index 2e5d84757..9f0416e83 100644 --- a/xmake/toolchains/circle/xmake.lua +++ b/xmake/toolchains/circle/xmake.lua @@ -30,7 +30,6 @@ toolchain("circle") set_toolset("ld", "circle") set_toolset("sh", "circle") set_toolset("ar", "ar") - set_toolset("ex", "ar") set_toolset("strip", "strip") on_check(function (toolchain) diff --git a/xmake/toolchains/clang/xmake.lua b/xmake/toolchains/clang/xmake.lua index ea4a45e30..96d22eac7 100644 --- a/xmake/toolchains/clang/xmake.lua +++ b/xmake/toolchains/clang/xmake.lua @@ -30,7 +30,6 @@ toolchain("clang") set_toolset("ld", "clang++", "clang") set_toolset("sh", "clang++", "clang") set_toolset("ar", "ar") - set_toolset("ex", "ar") set_toolset("strip", "strip") set_toolset("mm", "clang") set_toolset("mxx", "clang", "clang++") diff --git a/xmake/toolchains/cross/load.lua b/xmake/toolchains/cross/load.lua index 04d6f3044..dc0fd1b12 100644 --- a/xmake/toolchains/cross/load.lua +++ b/xmake/toolchains/cross/load.lua @@ -42,7 +42,6 @@ function main(toolchain) toolchain:add("toolset", "ld", cross .. "g++", cross .. "gcc", cross .. "clang++", cross .. "clang") toolchain:add("toolset", "sh", cross .. "g++", cross .. "gcc", cross .. "clang++", cross .. "clang") toolchain:add("toolset", "ar", cross .. "ar") - toolchain:add("toolset", "ex", cross .. "ar") toolchain:add("toolset", "ranlib", cross .. "ranlib") toolchain:add("toolset", "strip", cross .. "strip") diff --git a/xmake/toolchains/emcc/xmake.lua b/xmake/toolchains/emcc/xmake.lua index 2623fdf24..1379bd1c2 100644 --- a/xmake/toolchains/emcc/xmake.lua +++ b/xmake/toolchains/emcc/xmake.lua @@ -37,7 +37,6 @@ toolchain("emcc") set_toolset("ld", "em++" .. suffix, "emcc" .. suffix) set_toolset("sh", "em++" .. suffix, "emcc" .. suffix) set_toolset("ar", "emar" .. suffix) - set_toolset("ex", "emar" .. suffix) set_toolset("as", "emcc" .. suffix) -- check toolchain diff --git a/xmake/toolchains/envs/xmake.lua b/xmake/toolchains/envs/xmake.lua index 500eb38c6..b40cf6166 100644 --- a/xmake/toolchains/envs/xmake.lua +++ b/xmake/toolchains/envs/xmake.lua @@ -30,7 +30,6 @@ toolchain("envs") set_toolset("ld", "$(env LD)", "$(env CXX)") set_toolset("sh", "$(env SH)", "$(env LD)", "$(env CXX)") set_toolset("ar", "$(env AR)") - set_toolset("ex", "$(env EX)", "$(env AR)") set_toolset("strip", "$(env STRIP)") set_toolset("ranlib","$(env RANLIB)") set_toolset("mm", "$(env MM)") diff --git a/xmake/toolchains/gcc/xmake.lua b/xmake/toolchains/gcc/xmake.lua index 28e58c4a2..365341eda 100644 --- a/xmake/toolchains/gcc/xmake.lua +++ b/xmake/toolchains/gcc/xmake.lua @@ -39,7 +39,6 @@ toolchain("gcc" .. suffix) set_toolset("ld", "g++" .. suffix, "gcc" .. suffix) set_toolset("sh", "g++" .. suffix, "gcc" .. suffix) set_toolset("ar", "ar") - set_toolset("ex", "ar") set_toolset("strip", "strip") set_toolset("mm", "gcc" .. suffix) set_toolset("mxx", "gcc" .. suffix, "g++" .. suffix) diff --git a/xmake/toolchains/icc/load.lua b/xmake/toolchains/icc/load.lua index e4cee9959..5784fc5c8 100644 --- a/xmake/toolchains/icc/load.lua +++ b/xmake/toolchains/icc/load.lua @@ -58,14 +58,12 @@ function _load_intel_on_windows(toolchain) toolchain:set("toolset", "ld", "link.exe") toolchain:set("toolset", "sh", "link.exe") toolchain:set("toolset", "ar", "link.exe") - toolchain:set("toolset", "ex", "lib.exe") else toolchain:set("toolset", "cc", "icc") toolchain:set("toolset", "cxx", "icpc", "icc") toolchain:set("toolset", "ld", "icpc", "icc") toolchain:set("toolset", "sh", "icpc", "icc") toolchain:set("toolset", "ar", "ar") - toolchain:set("toolset", "ex", "ar") toolchain:set("toolset", "strip", "strip") toolchain:set("toolset", "as", "icc") end @@ -86,7 +84,6 @@ function _load_intel_on_linux(toolchain) toolchain:set("toolset", "ld", "icpc", "icc") toolchain:set("toolset", "sh", "icpc", "icc") toolchain:set("toolset", "ar", "ar") - toolchain:set("toolset", "ex", "ar") toolchain:set("toolset", "strip", "strip") toolchain:set("toolset", "as", "icc") diff --git a/xmake/toolchains/ifort/load.lua b/xmake/toolchains/ifort/load.lua index 8fa00c6ec..804f3a914 100644 --- a/xmake/toolchains/ifort/load.lua +++ b/xmake/toolchains/ifort/load.lua @@ -56,7 +56,6 @@ function _load_intel_on_windows(toolchain) toolchain:set("toolset", "fcld", "ifort.exe") toolchain:set("toolset", "fcsh", "ifort.exe") toolchain:set("toolset", "ar", "link.exe") - toolchain:set("toolset", "ex", "lib.exe") -- add ifort environments _add_ifortenv(toolchain, "PATH") diff --git a/xmake/toolchains/llvm/xmake.lua b/xmake/toolchains/llvm/xmake.lua index e08cb0e5d..40ec8fa92 100644 --- a/xmake/toolchains/llvm/xmake.lua +++ b/xmake/toolchains/llvm/xmake.lua @@ -36,7 +36,6 @@ toolchain("llvm") set_toolset("ld", "clang++", "clang") set_toolset("sh", "clang++", "clang") set_toolset("ar", "llvm-ar") - set_toolset("ex", "llvm-ar") set_toolset("ranlib", "llvm-ranlib") set_toolset("strip", "llvm-strip") diff --git a/xmake/toolchains/mingw/xmake.lua b/xmake/toolchains/mingw/xmake.lua index 3ddd5c103..188b5ae8a 100644 --- a/xmake/toolchains/mingw/xmake.lua +++ b/xmake/toolchains/mingw/xmake.lua @@ -61,7 +61,6 @@ toolchain("mingw") if is_host("windows") and bindir then -- @note we uses bin/ar.exe instead of bin/cross-gcc-ar.exe, @see https://github.com/xmake-io/xmake/issues/807#issuecomment-635779210 toolchain:add("toolset", "ar", path.join(bindir, "ar")) - toolchain:add("toolset", "ex", path.join(bindir, "ar")) toolchain:add("toolset", "strip", path.join(bindir, "strip")) toolchain:add("toolset", "ranlib", path.join(bindir, "ranlib")) end @@ -72,7 +71,6 @@ toolchain("mingw") toolchain:add("toolset", "ld", cross .. "g++", cross .. "gcc") toolchain:add("toolset", "sh", cross .. "g++", cross .. "gcc") toolchain:add("toolset", "ar", cross .. "ar") - toolchain:add("toolset", "ex", cross .. "ar") toolchain:add("toolset", "strip", cross .. "strip") toolchain:add("toolset", "ranlib", cross .. "ranlib") toolchain:add("toolset", "mrc", cross .. "windres") diff --git a/xmake/toolchains/msvc/load.lua b/xmake/toolchains/msvc/load.lua index 195815590..b6b9175f0 100644 --- a/xmake/toolchains/msvc/load.lua +++ b/xmake/toolchains/msvc/load.lua @@ -54,7 +54,6 @@ function main(toolchain) toolchain:set("toolset", "ld", "link.exe") toolchain:set("toolset", "sh", "link.exe") toolchain:set("toolset", "ar", "link.exe") - toolchain:set("toolset", "ex", "lib.exe") -- add vs environments _add_vsenv(toolchain, "PATH") diff --git a/xmake/toolchains/ndk/load.lua b/xmake/toolchains/ndk/load.lua index 059f6b417..494558673 100644 --- a/xmake/toolchains/ndk/load.lua +++ b/xmake/toolchains/ndk/load.lua @@ -89,7 +89,6 @@ function main(toolchain) toolchain:set("toolset", "ld", "clang++", "clang", cross .. "g++", cross .. "gcc") toolchain:set("toolset", "sh", "clang++", "clang", cross .. "g++", cross .. "gcc") toolchain:set("toolset", "ar", gcc_toolchain_bin and path.join(gcc_toolchain_bin, cross .. "ar") or (cross .. "ar"), "llvm-ar") - toolchain:set("toolset", "ex", gcc_toolchain_bin and path.join(gcc_toolchain_bin, cross .. "ar") or (cross .. "ar"), "llvm-ar") toolchain:set("toolset", "ranlib", gcc_toolchain_bin and path.join(gcc_toolchain_bin, cross .. "ranlib") or (cross .. "ranlib")) toolchain:set("toolset", "strip", gcc_toolchain_bin and path.join(gcc_toolchain_bin, cross .. "strip") or (cross .. "strip")) diff --git a/xmake/toolchains/sdcc/xmake.lua b/xmake/toolchains/sdcc/xmake.lua index f196f916d..18dc595ff 100644 --- a/xmake/toolchains/sdcc/xmake.lua +++ b/xmake/toolchains/sdcc/xmake.lua @@ -36,7 +36,6 @@ toolchain("sdcc") set_toolset("ld", "sdcc") set_toolset("sh", "sdcc") set_toolset("ar", "sdar") - set_toolset("ex", "sdar") -- set archs set_archs("stm8", "mcs51", "z80", "z180", "r2k", "r3ka", "s08", "hc08") diff --git a/xmake/toolchains/wasi/xmake.lua b/xmake/toolchains/wasi/xmake.lua index de2b7f37e..9d6ec360c 100644 --- a/xmake/toolchains/wasi/xmake.lua +++ b/xmake/toolchains/wasi/xmake.lua @@ -36,7 +36,6 @@ toolchain("wasi") set_toolset("ld", "clang++", "clang") set_toolset("sh", "clang++", "clang") set_toolset("ar", "llvm-ar") - set_toolset("ex", "llvm-ar") set_toolset("ranlib", "llvm-ranlib") set_toolset("strip", "llvm-strip") diff --git a/xmake/toolchains/xcode/xmake.lua b/xmake/toolchains/xcode/xmake.lua index b4d8c3d66..f2b2683ff 100644 --- a/xmake/toolchains/xcode/xmake.lua +++ b/xmake/toolchains/xcode/xmake.lua @@ -60,7 +60,6 @@ toolchain("xcode") toolchain:set("toolset", "ld", cross .. "clang++", cross .. "clang") toolchain:set("toolset", "sh", cross .. "clang++", cross .. "clang") toolchain:set("toolset", "ar", cross .. "ar") - toolchain:set("toolset", "ex", cross .. "ar") toolchain:set("toolset", "strip", cross .. "strip") toolchain:set("toolset", "dsymutil", cross .. "dsymutil", "dsymutil") toolchain:set("toolset", "mm", cross .. "clang") -- cgit v1.3.1 From d76dfd89f4c32c51a7dc898f0f86320294df7dfb Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 27 Oct 2021 22:34:37 +0800 Subject: improve ml/has_flags --- xmake/modules/detect/tools/ml/has_flags.lua | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/xmake/modules/detect/tools/ml/has_flags.lua b/xmake/modules/detect/tools/ml/has_flags.lua index 53576fa22..0dbda2134 100644 --- a/xmake/modules/detect/tools/ml/has_flags.lua +++ b/xmake/modules/detect/tools/ml/has_flags.lua @@ -61,12 +61,21 @@ function _check_try_running(flags, opt) -- make an stub source file local sourcefile = path.join(os.tmpdir(), "detect", "ml_has_flags.asm") if not os.isfile(sourcefile) then - io.writefile(sourcefile, ".code\nend") + io.writefile(sourcefile, [[ +ifndef X64 +.686p +.model flat, C +endif +.code +end]]) end -- check it local errors = nil return try { function () + if opt.program:find("ml64", 1, true) then + table.insert(flags, "-DX64") + end local _, errs = os.iorunv(opt.program, table.join("-c", "-nologo", flags, "-Fo" .. os.nuldev(), sourcefile), {envs = opt.envs}) if errs and #errs:trim() > 0 then return false, errs -- cgit v1.3.1 From 1f2e6861e8160fa1584c67d6783b11b2dbd6c85e Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 27 Oct 2021 22:35:15 +0800 Subject: add symbols for masm --- xmake/modules/core/tools/ml.lua | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/xmake/modules/core/tools/ml.lua b/xmake/modules/core/tools/ml.lua index 83da11fb6..e9154251d 100644 --- a/xmake/modules/core/tools/ml.lua +++ b/xmake/modules/core/tools/ml.lua @@ -20,6 +20,7 @@ -- imports import("private.tools.vstool") +import("core.base.hashset") -- init it -- @@ -57,6 +58,23 @@ function init(self) }) end +-- make the symbol flags +function nf_symbols(self, levels, target) + local flags = nil + local values = hashset.from(levels) + if values:has("debug") then + flags = {} + if values:has("edit") then + table.insert(flags, "-ZI") + elseif values:has("embed") then + table.insert(flags, "-Z7") + else + table.insert(flags, "-Zi") + end + end + return flags +end + -- make the warning flag function nf_warning(self, level) -- cgit v1.3.1 From 71217ef2ce95a70aad0fd1cad05eb462b4612a5b Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 27 Oct 2021 22:36:35 +0800 Subject: remove some comments --- xmake/modules/core/tools/dmd.lua | 8 -------- xmake/modules/core/tools/go.lua | 20 -------------------- xmake/modules/core/tools/ml.lua | 4 ---- xmake/modules/core/tools/rustc.lua | 16 ---------------- xmake/modules/core/tools/sdcc.lua | 14 -------------- xmake/modules/core/tools/zig.lua | 8 -------- 6 files changed, 70 deletions(-) diff --git a/xmake/modules/core/tools/dmd.lua b/xmake/modules/core/tools/dmd.lua index 2a9d860e1..3f29da28f 100644 --- a/xmake/modules/core/tools/dmd.lua +++ b/xmake/modules/core/tools/dmd.lua @@ -146,11 +146,7 @@ end -- link the target file function link(self, objectfiles, targetkind, targetfile, flags) - - -- ensure the target directory os.mkdir(path.directory(targetfile)) - - -- link it os.runv(linkargv(self, objectfiles, targetkind, targetfile, flags)) end @@ -161,11 +157,7 @@ end -- compile the source file function compile(self, sourcefile, objectfile, dependinfo, flags) - - -- ensure the object directory os.mkdir(path.directory(objectfile)) - - -- compile it os.runv(compargv(self, sourcefile, objectfile, flags)) end diff --git a/xmake/modules/core/tools/go.lua b/xmake/modules/core/tools/go.lua index fbd046cf0..34d096873 100644 --- a/xmake/modules/core/tools/go.lua +++ b/xmake/modules/core/tools/go.lua @@ -35,14 +35,10 @@ end -- make the optimize flag function nf_optimize(self, level) - - -- the maps local maps = { none = "-N" } - - -- make it return maps[level] end @@ -59,22 +55,16 @@ function nf_symbol(self, level, target, mapkind) { debug = "-E" } - - -- make it return maps[level] end -- make the strip flag function nf_strip(self, level) - - -- the maps local maps = { debug = "-s" , all = "-s" } - - -- make it return maps[level] end @@ -95,8 +85,6 @@ end -- make the link arguments list function linkargv(self, objectfiles, targetkind, targetfile, flags) - - -- make it if targetkind == "static" then return self:program(), table.join("tool", "pack", flags, targetfile, objectfiles) else @@ -106,11 +94,7 @@ end -- link the target file function link(self, objectfiles, targetkind, targetfile, flags) - - -- ensure the target directory os.mkdir(path.directory(targetfile)) - - -- link it local program, argv = linkargv(self, objectfiles, targetkind, targetfile, flags) os.runv(program, argv, {envs = self:runenvs()}) end @@ -122,11 +106,7 @@ end -- compile the source file function compile(self, sourcefiles, objectfile, dependinfo, flags) - - -- ensure the object directory os.mkdir(path.directory(objectfile)) - - -- compile it local program, argv = compargv(self, sourcefiles, objectfile, flags) os.runv(program, argv, {envs = self:runenvs()}) end diff --git a/xmake/modules/core/tools/ml.lua b/xmake/modules/core/tools/ml.lua index e9154251d..3550b1a32 100644 --- a/xmake/modules/core/tools/ml.lua +++ b/xmake/modules/core/tools/ml.lua @@ -77,8 +77,6 @@ end -- make the warning flag function nf_warning(self, level) - - -- the maps local maps = { none = "-w" @@ -88,8 +86,6 @@ function nf_warning(self, level) , everything = "-W3" , error = "-WX" } - - -- make it return maps[level] end diff --git a/xmake/modules/core/tools/rustc.lua b/xmake/modules/core/tools/rustc.lua index ade2daea4..a30a389af 100644 --- a/xmake/modules/core/tools/rustc.lua +++ b/xmake/modules/core/tools/rustc.lua @@ -41,8 +41,6 @@ end -- make the optimize flag function nf_optimize(self, level) - - -- the maps local maps = { none = "-C opt-level=0" @@ -52,21 +50,15 @@ function nf_optimize(self, level) , smallest = "-C opt-level=s" , aggressive = "-C opt-level=z" } - - -- make it return maps[level] end -- make the symbol flag function nf_symbol(self, level) - - -- the maps local maps = { debug = "-C debuginfo=2" } - - -- make it return maps[level] end @@ -82,11 +74,7 @@ end -- build the target file function build(self, sourcefiles, targetkind, targetfile, flags) - - -- ensure the target directory os.mkdir(path.directory(targetfile)) - - -- build it os.runv(buildargv(self, sourcefiles, targetkind, targetfile, flags)) end @@ -97,11 +85,7 @@ end -- compile the source file function compile(self, sourcefiles, objectfile, dependinfo, flags) - - -- ensure the object directory os.mkdir(path.directory(objectfile)) - - -- compile it os.runv(compargv(self, sourcefiles, objectfile, flags)) end diff --git a/xmake/modules/core/tools/sdcc.lua b/xmake/modules/core/tools/sdcc.lua index 0153ed652..4605f12f8 100644 --- a/xmake/modules/core/tools/sdcc.lua +++ b/xmake/modules/core/tools/sdcc.lua @@ -68,23 +68,17 @@ end -- make the warning flag function nf_warning(self, level) - - -- the maps local maps = { none = "--less-pedantic" , less = "--less-pedantic" , error = "-Werror" } - - -- make it return maps[level] end -- make the optimize flag function nf_optimize(self, level) - - -- the maps local maps = { none = "" @@ -94,15 +88,11 @@ function nf_optimize(self, level) , smallest = "--opt-code-size" , aggressive = "--opt-code-speed" } - - -- make it return maps[level] end -- make the language flag function nf_language(self, stdname) - - -- the stdc maps if _g.cmaps == nil then _g.cmaps = { @@ -176,11 +166,7 @@ end -- link the target file function link(self, objectfiles, targetkind, targetfile, flags) - - -- ensure the target directory os.mkdir(path.directory(targetfile)) - - -- link it os.runv(linkargv(self, objectfiles, targetkind, targetfile, flags)) end diff --git a/xmake/modules/core/tools/zig.lua b/xmake/modules/core/tools/zig.lua index 140e1ae0a..f0d6c5d98 100644 --- a/xmake/modules/core/tools/zig.lua +++ b/xmake/modules/core/tools/zig.lua @@ -116,11 +116,7 @@ end -- link the target file function link(self, objectfiles, targetkind, targetfile, flags) - - -- ensure the target directory os.mkdir(path.directory(targetfile)) - - -- link it os.runv(linkargv(self, objectfiles, targetkind, targetfile, flags)) end @@ -131,11 +127,7 @@ end -- compile the source file function compile(self, sourcefile, objectfile, dependinfo, flags) - - -- ensure the object directory os.mkdir(path.directory(objectfile)) - - -- compile it os.runv(compargv(self, sourcefile, objectfile, flags)) end -- cgit v1.3.1 From 019744ba3a592cb0b0a89d275f96ed665531253f Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 27 Oct 2021 22:40:18 +0800 Subject: add nimble test --- tests/projects/nim/console_with_packages/src/main.nim | 3 --- tests/projects/nim/console_with_packages/xmake.lua | 8 -------- tests/projects/nim/native_package/src/main.nim | 3 +++ tests/projects/nim/native_package/xmake.lua | 8 ++++++++ tests/projects/nim/nimble_package/src/main.nim | 3 +++ tests/projects/nim/nimble_package/xmake.lua | 8 ++++++++ 6 files changed, 22 insertions(+), 11 deletions(-) delete mode 100644 tests/projects/nim/console_with_packages/src/main.nim delete mode 100644 tests/projects/nim/console_with_packages/xmake.lua create mode 100644 tests/projects/nim/native_package/src/main.nim create mode 100644 tests/projects/nim/native_package/xmake.lua create mode 100644 tests/projects/nim/nimble_package/src/main.nim create mode 100644 tests/projects/nim/nimble_package/xmake.lua diff --git a/tests/projects/nim/console_with_packages/src/main.nim b/tests/projects/nim/console_with_packages/src/main.nim deleted file mode 100644 index a3368303a..000000000 --- a/tests/projects/nim/console_with_packages/src/main.nim +++ /dev/null @@ -1,3 +0,0 @@ -proc zlibVersion(): cstring {.cdecl, importc} - -echo zlibVersion() diff --git a/tests/projects/nim/console_with_packages/xmake.lua b/tests/projects/nim/console_with_packages/xmake.lua deleted file mode 100644 index 924ee9632..000000000 --- a/tests/projects/nim/console_with_packages/xmake.lua +++ /dev/null @@ -1,8 +0,0 @@ -add_rules("mode.debug", "mode.release") - -add_requires("zlib") - -target("test") - set_kind("binary") - add_files("src/main.nim") - add_packages("zlib") diff --git a/tests/projects/nim/native_package/src/main.nim b/tests/projects/nim/native_package/src/main.nim new file mode 100644 index 000000000..a3368303a --- /dev/null +++ b/tests/projects/nim/native_package/src/main.nim @@ -0,0 +1,3 @@ +proc zlibVersion(): cstring {.cdecl, importc} + +echo zlibVersion() diff --git a/tests/projects/nim/native_package/xmake.lua b/tests/projects/nim/native_package/xmake.lua new file mode 100644 index 000000000..924ee9632 --- /dev/null +++ b/tests/projects/nim/native_package/xmake.lua @@ -0,0 +1,8 @@ +add_rules("mode.debug", "mode.release") + +add_requires("zlib") + +target("test") + set_kind("binary") + add_files("src/main.nim") + add_packages("zlib") diff --git a/tests/projects/nim/nimble_package/src/main.nim b/tests/projects/nim/nimble_package/src/main.nim new file mode 100644 index 000000000..b78aa2495 --- /dev/null +++ b/tests/projects/nim/nimble_package/src/main.nim @@ -0,0 +1,3 @@ +import zip/zlib + +echo zlibVersion() diff --git a/tests/projects/nim/nimble_package/xmake.lua b/tests/projects/nim/nimble_package/xmake.lua new file mode 100644 index 000000000..af3e0f0f5 --- /dev/null +++ b/tests/projects/nim/nimble_package/xmake.lua @@ -0,0 +1,8 @@ +add_rules("mode.debug", "mode.release") + +add_requires("nimble::zip") + +target("test") + set_kind("binary") + add_files("src/main.nim") + add_packages("nimble::zip") -- cgit v1.3.1 From 65b92a8486ebb5e36e7d4fb7c133fb9fe2f9a798 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 27 Oct 2021 22:40:39 +0800 Subject: add find_nimble --- xmake/modules/detect/tools/find_nimble.lua | 52 ++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 xmake/modules/detect/tools/find_nimble.lua diff --git a/xmake/modules/detect/tools/find_nimble.lua b/xmake/modules/detect/tools/find_nimble.lua new file mode 100644 index 000000000..7d4364b64 --- /dev/null +++ b/xmake/modules/detect/tools/find_nimble.lua @@ -0,0 +1,52 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_nimble.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find nim +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local nim = find_nimble() +-- local nim, version = find_nimble({program = "nimble", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "nimble", opt) + + -- find program version + local version = nil + if program and opt.version then + version = find_programver(program, opt) + end + return program, version +end -- cgit v1.3.1 From c871e3f603c6022c16659cca61f8995f29b5275e Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 27 Oct 2021 22:41:07 +0800 Subject: add nimble stub --- .../package/manager/nimble/find_package.lua | 41 ++++++++++++++++++++++ .../package/manager/nimble/install_package.lua | 41 ++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 xmake/modules/package/manager/nimble/find_package.lua create mode 100644 xmake/modules/package/manager/nimble/install_package.lua diff --git a/xmake/modules/package/manager/nimble/find_package.lua b/xmake/modules/package/manager/nimble/find_package.lua new file mode 100644 index 000000000..cb9d3884a --- /dev/null +++ b/xmake/modules/package/manager/nimble/find_package.lua @@ -0,0 +1,41 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_package.lua +-- + +-- imports +import("core.base.option") +import("core.project.config") +import("core.project.target") +import("lib.detect.find_tool") +import("lib.detect.find_file") + +-- find package using the nimble package manager +-- +-- @param name the package name +-- @param opt the options, e.g. {verbose = true, version = "1.12.x") +-- +function main(name, opt) + + -- find nimble + local nimble = find_tool("nimble") + if not nimble then + raise("nimble not found!") + end + +end diff --git a/xmake/modules/package/manager/nimble/install_package.lua b/xmake/modules/package/manager/nimble/install_package.lua new file mode 100644 index 000000000..57addc15a --- /dev/null +++ b/xmake/modules/package/manager/nimble/install_package.lua @@ -0,0 +1,41 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file install_package.lua +-- + +-- imports +import("core.base.option") +import("core.project.config") +import("lib.detect.find_tool") + +-- install package +-- +-- @param name the package name, e.g. nimble::zip +-- @param opt the options, e.g. { verbose = true, mode = "release", plat = , arch = , require_version = "x.x.x", buildhash = "xxxxxx"} +-- +-- @return true or false +-- +function main(name, opt) + + -- find nimble + local nimble = find_tool("nimble") + if not nimble then + raise("nimble not found!") + end + +end -- cgit v1.3.1 From cc80af774a9426d7775be165adb4aa00d8569ed6 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 27 Oct 2021 22:45:11 +0800 Subject: impl nimble/install_package --- tests/projects/nim/nimble_package/xmake.lua | 2 +- xmake/modules/package/manager/nimble/install_package.lua | 12 ++++++++++++ xmake/modules/private/action/require/impl/package.lua | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/projects/nim/nimble_package/xmake.lua b/tests/projects/nim/nimble_package/xmake.lua index af3e0f0f5..45e6f3132 100644 --- a/tests/projects/nim/nimble_package/xmake.lua +++ b/tests/projects/nim/nimble_package/xmake.lua @@ -1,6 +1,6 @@ add_rules("mode.debug", "mode.release") -add_requires("nimble::zip") +add_requires("nimble::zip >0.3") target("test") set_kind("binary") diff --git a/xmake/modules/package/manager/nimble/install_package.lua b/xmake/modules/package/manager/nimble/install_package.lua index 57addc15a..b5ba21438 100644 --- a/xmake/modules/package/manager/nimble/install_package.lua +++ b/xmake/modules/package/manager/nimble/install_package.lua @@ -38,4 +38,16 @@ function main(name, opt) raise("nimble not found!") end + -- install the given package + local argv = {"install", "-y"} + if option.get("verbose") then + table.insert(argv, "--verbose") + end + local require_str = name + if opt.require_version and opt.require_version ~= "latest" and opt.require_version ~= "master" then + name = name .. "@" + name = name .. opt.require_version + end + table.insert(argv, name) + os.vrunv(nimble.program, argv) end diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 5a43de562..77c20648b 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -339,7 +339,7 @@ function _select_package_version(package, requireinfo, locked_requireinfo) version = "latest" source = "version" end - if not version then + if not version and not package:is_thirdparty() then raise("package(%s): version(%s) not found!", package:name(), require_version) end return version, source -- cgit v1.3.1 From 20d47ee82092c9d92f18284cf6873bde6e65c2f3 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 27 Oct 2021 22:45:27 +0800 Subject: improve comments --- xmake/modules/package/manager/dub/install_package.lua | 2 +- xmake/modules/package/manager/nimble/install_package.lua | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/xmake/modules/package/manager/dub/install_package.lua b/xmake/modules/package/manager/dub/install_package.lua index 84406af5f..d459bfd92 100644 --- a/xmake/modules/package/manager/dub/install_package.lua +++ b/xmake/modules/package/manager/dub/install_package.lua @@ -26,7 +26,7 @@ import("lib.detect.find_tool") -- install package -- -- @param name the package name, e.g. dub::log --- @param opt the options, e.g. { verbose = true, mode = "release", plat = , arch = , require_version = "x.x.x", buildhash = "xxxxxx"} +-- @param opt the options, e.g. { verbose = true, mode = "release", plat = , arch = , require_version = "x.x.x"} -- -- @return true or false -- diff --git a/xmake/modules/package/manager/nimble/install_package.lua b/xmake/modules/package/manager/nimble/install_package.lua index b5ba21438..326758e8c 100644 --- a/xmake/modules/package/manager/nimble/install_package.lua +++ b/xmake/modules/package/manager/nimble/install_package.lua @@ -25,8 +25,13 @@ import("lib.detect.find_tool") -- install package -- +-- e.g. +-- add_requires("nimble::zip") +-- add_requires("nimble::zip >0.3") +-- add_requires("nimble::zip 0.3.1") +-- -- @param name the package name, e.g. nimble::zip --- @param opt the options, e.g. { verbose = true, mode = "release", plat = , arch = , require_version = "x.x.x", buildhash = "xxxxxx"} +-- @param opt the options, e.g. { verbose = true, mode = "release", plat = , arch = , require_version = "x.x.x"} -- -- @return true or false -- -- cgit v1.3.1 From 3225b2b74981dc87130966b0b6a4011f5e0eff6c Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 27 Oct 2021 22:52:03 +0800 Subject: impl nimble find_package --- xmake/modules/package/manager/dub/find_package.lua | 2 +- .../package/manager/nimble/find_package.lua | 28 +++++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/xmake/modules/package/manager/dub/find_package.lua b/xmake/modules/package/manager/dub/find_package.lua index 8543a8bfb..5d49d695e 100644 --- a/xmake/modules/package/manager/dub/find_package.lua +++ b/xmake/modules/package/manager/dub/find_package.lua @@ -30,7 +30,7 @@ import("lib.detect.find_file") -- find package using the dub package manager -- -- @param name the package name --- @param opt the options, e.g. {verbose = true, version = "1.12.x") +-- @param opt the options, e.g. {verbose = true, require_version = "1.12.x") -- function main(name, opt) diff --git a/xmake/modules/package/manager/nimble/find_package.lua b/xmake/modules/package/manager/nimble/find_package.lua index cb9d3884a..c39d6ed34 100644 --- a/xmake/modules/package/manager/nimble/find_package.lua +++ b/xmake/modules/package/manager/nimble/find_package.lua @@ -20,6 +20,7 @@ -- imports import("core.base.option") +import("core.base.semver") import("core.project.config") import("core.project.target") import("lib.detect.find_tool") @@ -28,7 +29,7 @@ import("lib.detect.find_file") -- find package using the nimble package manager -- -- @param name the package name --- @param opt the options, e.g. {verbose = true, version = "1.12.x") +-- @param opt the options, e.g. {verbose = true, require_version = "1.12.x") -- function main(name, opt) @@ -38,4 +39,29 @@ function main(name, opt) raise("nimble not found!") end + -- find it from all installed package list + local result + local list = os.iorunv(nimble.program, {"list", "-i"}) + for _, line in ipairs(list:split("\n", {plain = true})) do + local splitinfo = line:split("%s+") + local package_name = splitinfo[1] + local package_version = splitinfo[2] + if package_name == name and package_version then + if package_version then + package_version = package_version:match("%[(.+)%]") + end + if opt.require_version then + if package_version and (opt.require_version == "latest" or semver.match(package_version, 1, opt.require_version)) then + result = {version = package_version} + break + end + else + result = {} + break + end + end + end + -- @note we need not return links and includedirs information, + -- because it's nim source code package and nim will find them automatically + return result end -- cgit v1.3.1 From 909fe3d6df145c81338c9f4277634b255548086f Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 27 Oct 2021 13:05:51 +0800 Subject: Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d73b31ff2..a651bc525 100644 --- a/README.md +++ b/README.md @@ -177,6 +177,7 @@ The test project: [xmake-core](https://github.com/xmake-io/xmake/tree/master/cor * Clib (clib::clibs/bytes@0.0.4) * Dub (dub::log 0.4.3) * Portage on Gentoo/Linux (portage::libhandy) +* Nimble for nimlang (nimble::zip >1.3) ## Supported platforms -- cgit v1.3.1 From e3ec4dcf0e78eb6c3f25db3cff8c017b9cad9528 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 27 Oct 2021 13:06:45 +0800 Subject: Update README_zh.md --- README_zh.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README_zh.md b/README_zh.md index 0783cf54c..d6389d3a8 100644 --- a/README_zh.md +++ b/README_zh.md @@ -185,6 +185,8 @@ $ xmake f --menu * Apt on ubuntu/debian (apt::zlib1g-dev) * Clib (clib::clibs/bytes@0.0.4) * Dub (dub::log 0.4.3) +* Portage on Gentoo/Linux (portage::libhandy) +* Nimble for nimlang (nimble::zip >1.3) ## 支持平台 -- cgit v1.3.1 From 0330837144456c27559b61e2819c566cfebdd16f Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 27 Oct 2021 20:06:56 +0800 Subject: Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index a651bc525..db603e4ed 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,10 @@ xmake is a lightweight cross-platform build utility based on Lua. It uses xmake. It can compile the project directly like Make/Ninja, or generate project files like CMake/Meson, and it also has a built-in package management system to help users solve the integrated use of C/C++ dependent libraries. +``` +Xmake = Build backend + Project Generator + Package Manager +``` + If you want to know more, please refer to: [Documents](https://xmake.io/#/getting_started), [Github](https://github.com/xmake-io/xmake) and [Gitee](https://gitee.com/tboox/xmake) and also welcome to join our [community](https://xmake.io/#/about/contact). ![](https://xmake.io/assets/img/index/xmake-basic-render.gif) -- cgit v1.3.1 From 811a0d8dccbf758acdb074cbca736dcafc4590d7 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 27 Oct 2021 20:07:47 +0800 Subject: Update README_zh.md --- README_zh.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README_zh.md b/README_zh.md index d6389d3a8..ff03a0637 100644 --- a/README_zh.md +++ b/README_zh.md @@ -64,7 +64,11 @@ xmake 是一个基于 Lua 的轻量级跨平台构建工具,使用 xmake.lua 虽然,简单易用是 xmake 的一大特色,但 xmake 的功能也是非常强大的,既能够像 Make/Ninja 那样可以直接编译项目,也可以像 CMake/Meson 那样生成工程文件,还有内置的包管理系统来帮助用户解决 C/C++依赖库的集成使用问题。 -目前,xmake主要用于C/C++项目的构建,但是同时也支持其他native语言的构建,可以实现跟C/C++进行混合编译,同时编译速度也是非常的快,可以跟Ninja持平。 +目前,xmake主要用于 C/C++ 项目的构建,但是同时也支持其他native语言的构建,可以实现跟C/C++进行混合编译,同时编译速度也是非常的快,可以跟Ninja持平。 + +``` +Xmake = Build backend + Project Generator + Package Manager +``` 如果你想要了解更多,请参考:[在线文档](https://xmake.io/#/zh-cn/getting_started), [Github](https://github.com/xmake-io/xmake)以及[Gitee](https://gitee.com/tboox/xmake),同时也欢迎加入我们的 [社区](https://xmake.io/#/zh-ch/about/contact). -- cgit v1.3.1 From d527a9213c3ac1651dc7f7bea7a2ea91139ed6ff Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 28 Oct 2021 00:30:49 +0800 Subject: fix compiler --- xmake/core/tool/compiler.lua | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/xmake/core/tool/compiler.lua b/xmake/core/tool/compiler.lua index 0e64de8c3..3aa2a8e6c 100644 --- a/xmake/core/tool/compiler.lua +++ b/xmake/core/tool/compiler.lua @@ -74,6 +74,22 @@ function compiler:_add_flags_from_compiler(flags, targetkind) end end +-- add flags from the sourcefile config +function compiler:_add_flags_from_fileconfig(flags, target, sourcefile, fileconfig) + + -- add flags from the current compiler + local add_sourceflags = self:_tool().add_sourceflags + if add_sourceflags then + local flag = add_sourceflags(self:_tool(), sourcefile, fileconfig, target, self:_targetkind()) + if flag and flag ~= "" then + table.join2(flags, flag) + end + end + + -- add flags from the common argument option + self:_add_flags_from_argument(flags, target, fileconfig) +end + -- load compiler tool function compiler._load_tool(sourcekind, target) @@ -262,22 +278,6 @@ function compiler:compcmd(sourcefiles, objectfile, opt) return os.args(table.join(self:compargv(sourcefiles, objectfile, opt))) end --- add flags from the sourcefile config -function builder:_add_flags_from_fileconfig(flags, target, sourcefile, fileconfig) - - -- add flags from the current compiler - local add_sourceflags = self:_tool().add_sourceflags - if add_sourceflags then - local flag = add_sourceflags(self:_tool(), sourcefile, fileconfig, target, self:_targetkind()) - if flag and flag ~= "" then - table.join2(flags, flag) - end - end - - -- add flags from the common argument option - self:_add_flags_from_argument(flags, target, fileconfig) -end - -- get the compling flags -- -- @param opt the argument options (contain all the compiler attributes of target), -- cgit v1.3.1 From 020ec323df6377390fe144e8af78dd7cc741ec0b Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 28 Oct 2021 00:37:30 +0800 Subject: improve ml --- xmake/core/base/table.lua | 46 ++++++++++++++++++++++++++++++---------- xmake/core/tool/compiler.lua | 2 +- xmake/modules/core/tools/gcc.lua | 1 - xmake/modules/core/tools/ml.lua | 21 +++++++++++++----- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua index 4f21ec358..21fa185a0 100644 --- a/xmake/core/base/table.lua +++ b/xmake/core/base/table.lua @@ -227,21 +227,45 @@ function table.is_dictionary(dict) return type(dict) == "table" and dict[1] == nil end --- does contain the given value in table? -function table.contains(t, value) +-- does contain the given values in table? +-- contains arg1 or arg2 ... +function table.contains(t, arg1, arg2, ...) local found = false - if table.is_array(t) then - for _, v in ipairs(t) do - if v == value then - found = true - break + if arg2 == nil then -- only one value + if table.is_array(t) then + for _, v in ipairs(t) do + if v == arg1 then + found = true + break + end + end + else + for _, v in pairs(t) do + if v == arg1 then + found = true + break + end end end else - for _, v in pairs(t) do - if v == value then - found = true - break + local values = {} + local args = table.pack(arg1, arg2, ...) + for _, arg in ipairs(args) do + values[arg] = true + end + if table.is_array(t) then + for _, v in ipairs(t) do + if values[v] then + found = true + break + end + end + else + for _, v in pairs(t) do + if values[v] then + found = true + break + end end end end diff --git a/xmake/core/tool/compiler.lua b/xmake/core/tool/compiler.lua index 3aa2a8e6c..bddfea057 100644 --- a/xmake/core/tool/compiler.lua +++ b/xmake/core/tool/compiler.lua @@ -284,7 +284,7 @@ end -- e.g. -- {target = ..., targetkind = "static", configs = {defines = "", cxflags = "", includedirs = ""}} -- --- @return flags string, flags list +-- @return flags list -- function compiler:compflags(opt) diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index 49998fec6..2e93ea2bb 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -421,7 +421,6 @@ end -- make the compile arguments list function compargv(self, sourcefile, objectfile, flags) - -- precompiled header? local extension = path.extension(sourcefile) if (extension:startswith(".h") or extension == ".inl") then diff --git a/xmake/modules/core/tools/ml.lua b/xmake/modules/core/tools/ml.lua index 3550b1a32..6678bec81 100644 --- a/xmake/modules/core/tools/ml.lua +++ b/xmake/modules/core/tools/ml.lua @@ -29,11 +29,7 @@ import("core.base.hashset") function init(self) -- init asflags - if self:program():find("64") then - self:set("asflags", "-nologo") - else - self:set("asflags", "-nologo", "-Gd") - end + self:set("asflags", "-nologo") -- init flags map self:set("mapflags", @@ -111,6 +107,21 @@ end -- make the compile arguments list function compargv(self, sourcefile, objectfile, flags) + -- we need to set the default -Gd option for the x86 architecture, + -- if the other calling convention flags are not set + -- + -- we can't directly remove -Gd. This is not only for backward compatibility, + -- but also to simplify mixed compilation with c programs. + -- + -- although this may affect some performance, + -- it only takes effect under x86 asm, so there will be no major performance issues. + -- + -- @see https://github.com/xmake-io/xmake/issues/1779 + -- + if not self:program():find("64", 1, true) and + not table.contains(flags, "-Gd", "/Gd", "-Gc", "/Gc", "-GZ", "/GZ") then + table.insert(flags, "-Gd") + end return self:program(), table.join("-c", flags, "-Fo" .. objectfile, sourcefile) end -- cgit v1.3.1 From eb08e0fe247e681f2c9dd1184ac96ac16ba71641 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 28 Oct 2021 00:37:45 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3243da493..c983d79be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ * [#1528](https://github.com/xmake-io/xmake/issues/1528): Check c++17/20 features * [#1729](https://github.com/xmake-io/xmake/issues/1729): Improve C++20 modules for clang/gcc/msvc, support inter-module dependency compilation and parallel optimization +* [#1779](https://github.com/xmake-io/xmake/issues/1779): Remove builtin `-Gd` for ml.exe/x86 ## v2.5.8 @@ -1127,6 +1128,7 @@ * [#1528](https://github.com/xmake-io/xmake/issues/1528): 检测 c++17/20 特性 * [#1729](https://github.com/xmake-io/xmake/issues/1729): 改进 C++20 modules 对 clang/gcc/msvc 的支持,支持模块间依赖编译和并行优化 +* [#1779](https://github.com/xmake-io/xmake/issues/1779): 改进 ml.exe/x86,移除内置的 `-Gd` 选项 ## v2.5.8 -- cgit v1.3.1 From 7b6391d71e863e8395bfd8b7e28337c84e7cac36 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 28 Oct 2021 00:38:50 +0800 Subject: improve ml --- xmake/modules/core/tools/ml.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/core/tools/ml.lua b/xmake/modules/core/tools/ml.lua index 6678bec81..59749974c 100644 --- a/xmake/modules/core/tools/ml.lua +++ b/xmake/modules/core/tools/ml.lua @@ -119,7 +119,7 @@ function compargv(self, sourcefile, objectfile, flags) -- @see https://github.com/xmake-io/xmake/issues/1779 -- if not self:program():find("64", 1, true) and - not table.contains(flags, "-Gd", "/Gd", "-Gc", "/Gc", "-GZ", "/GZ") then + not table.contains(flags, "-Gc", "/Gc", "-GZ", "/GZ") then table.insert(flags, "-Gd") end return self:program(), table.join("-c", flags, "-Fo" .. objectfile, sourcefile) -- cgit v1.3.1 From 7de003849e02ded862dd4be131fc34c30c2dfb9c Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 28 Oct 2021 00:40:46 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c983d79be..1f0821a32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ * [#1762](https://github.com/xmake-io/xmake/issues/1762): Manage and switch the given package envs for `xrepo env` * [#1767](https://github.com/xmake-io/xmake/issues/1767): Support Circle compiler * [#1753](https://github.com/xmake-io/xmake/issues/1753): Support armcc/armclang toolchains for Keil/MDK +* [#1774](https://github.com/xmake-io/xmake/issues/1774): Add table.contains api ### Changes @@ -1123,6 +1124,7 @@ * [#1762](https://github.com/xmake-io/xmake/issues/1762): 为 `xrepo env` 管理和切换指定的环境配置 * [#1767](https://github.com/xmake-io/xmake/issues/1767): 支持 Circle 编译器 * [#1753](https://github.com/xmake-io/xmake/issues/1753): 支持 Keil/MDK 的 armcc/armclang 工具链 +* [#1774](https://github.com/xmake-io/xmake/issues/1774): 添加 table.contains api ### 改进 -- cgit v1.3.1 From 07e83caa38bce6835f8e68673b106f6d56d6d607 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 28 Oct 2021 22:37:02 +0800 Subject: update readme --- README.md | 40 +++++++++++++++++++++++----------------- README_zh.md | 33 ++++++++++++++++++++------------- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index db603e4ed..e7e77eccc 100644 --- a/README.md +++ b/README.md @@ -183,6 +183,17 @@ The test project: [xmake-core](https://github.com/xmake-io/xmake/tree/master/cor * Portage on Gentoo/Linux (portage::libhandy) * Nimble for nimlang (nimble::zip >1.3) +### Package management features + +* The official repository provides nearly 500+ packages, one-click compilation on all platforms +* Full platform package support, support for cross-compiled dependent package integration +* Support package virtual environment, `xrepo env shell` +* Rrecompiled package acceleration for windows +* Support self-built package repositories, private repository deployment +* Third-party package repository support, such as: vcpkg, conan, conda, etc. +* Support to pull using remote toolchain automatically +* Support to lock package dependency + ## Supported platforms * Windows (x86, x64) @@ -255,24 +266,19 @@ armclang ARM Compiler Version 6 of Keil MDK ## Supported Features -* Simple project configuration syntax -* Direct build support, without relying on any third-party back-end make tools -* Support cross platform -* Support cross compilation -* Multi-task parallel compilation support -* C++20 Module-TS support -* Support cross-platform C/C++ dependency packages -* Support self-built distributed package repositories -* Support the installation of cloud pre-compiled packages -* Support third-party package repositories, such as: vcpkg, conan, conda, etc. -* Support multi-language mixed compilation -* Flexible lua scripts, rich extension modules -* Support for generating vsproj/cmake/makefile/compile_commands files +* The configuration grammar is simple and easy to use +* Quick installation, without any dependencies +* One-click compilation for all platforms +* Support cross compilation, intelligent analysis of cross tool chain information +* Extremely fast, multi-task parallel compilation support +* C++20 Module support +* Support cross-platform C/C++ dependency package quick integration, built-in package manager +* Multi-language mixed compilation support +* Rich plug-in support, providing various project generators, such as: vs/makefile/cmakelists/compile_commands to generate plugins * REPL interactive execution support -* Incremental compilation support, automatic analysis of header dependency files -* Fast switching toolchains -* Automatic pull toolchain and dependency package integration -* Support precompiled package and lock package requires +* Incremental compilation support, automatic analysis of header files +* Quick switching and customization support of tool chain +* A large number of expansion modules support ## Supported Projects diff --git a/README_zh.md b/README_zh.md index ff03a0637..006d413e1 100644 --- a/README_zh.md +++ b/README_zh.md @@ -192,6 +192,17 @@ $ xmake f --menu * Portage on Gentoo/Linux (portage::libhandy) * Nimble for nimlang (nimble::zip >1.3) +### 包管理特性 + +* 官方仓库提供近 500+ 常用包,真正做到全平台一键下载集成编译 +* 全平台包支持,支持交叉编译的依赖包集成 +* 支持包虚拟环境管理和加载,`xrepo env shell` +* Windows 云端预编译包加速 +* 支持自建包仓库,私有仓库部署 +* 第三方包仓库支持,提供更加丰富的包源,例如:vcpkg, conan, conda 等等 +* 支持自动拉取使用云端工具链 +* 支持包依赖锁定 + ## 支持平台 * Windows (x86, x64) @@ -263,23 +274,19 @@ armclang ARM Compiler Version 6 of Keil MDK ## 支持特性 -* 简洁的配置语法 -* 直接构建支持,不依赖任何第三方后端 make 工具 -* 跨平台支持,不同平台可方便快速地切换 -* 交叉编译支持,智能分析交叉工具链信息 -* 多任务并行编译支持 -* C++20 Module-TS 支持 -* 支持跨平台的 C/C++ 依赖包快速集成 -* 自建分布式包仓库,支持安装云端预编译包 -* 第三方包仓库支持,例如:vcpkg, conan, conda 等等 +* 语法简单易上手 +* 快速安装,无任何依赖 +* 全平台一键编译 +* 支持交叉编译,智能分析交叉工具链信息 +* 极速,多任务并行编译支持 +* C++20 Module 支持 +* 支持跨平台的 C/C++ 依赖包快速集成,内置包管理器 * 多语言混合编译支持 -* 灵活的 lua 脚本,丰富的扩展模块,可实现高度定制化 -* 丰富的插件支持,内置 vs/cmake/makefile/compile_commands 等生成插件 +* 丰富的插件支持,提供各种工程生成器,例如:vs/makefile/cmakelists/compile_commands 生成插件 * REPL 交互式执行支持 * 增量编译支持,头文件依赖自动分析 * 工具链的快速切换、定制化支持 -* 自动拉取工具链以及依赖包的快速整合 -* 支持预编译包以及包依赖锁定 +* 丰富的扩展模块支持 ## 工程类型 -- cgit v1.3.1 From 0b3057dce66dc41957de6c588d1fd2664c8de298 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 28 Oct 2021 22:37:37 +0800 Subject: fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e7e77eccc..3c1350bfb 100644 --- a/README.md +++ b/README.md @@ -188,7 +188,7 @@ The test project: [xmake-core](https://github.com/xmake-io/xmake/tree/master/cor * The official repository provides nearly 500+ packages, one-click compilation on all platforms * Full platform package support, support for cross-compiled dependent package integration * Support package virtual environment, `xrepo env shell` -* Rrecompiled package acceleration for windows +* Precompiled package acceleration for windows * Support self-built package repositories, private repository deployment * Third-party package repository support, such as: vcpkg, conan, conda, etc. * Support to pull using remote toolchain automatically -- cgit v1.3.1 From ee15c74a2d73fc8df4a11efdc2dd4848807ffe27 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 28 Oct 2021 22:54:58 +0800 Subject: add custom commands for cmake --- xmake/plugins/project/cmake/cmakelists.lua | 127 ++++++++++++++++++++++++++--- xmake/rules/utils/bin2c/xmake.lua | 8 +- 2 files changed, 123 insertions(+), 12 deletions(-) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index ba1689cb1..c43f7584f 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -22,7 +22,9 @@ import("core.project.project") import("core.tool.compiler") import("core.base.semver") +import("core.project.rule") import("lib.detect.find_tool") +import("private.utils.batchcmds") -- get minimal cmake version function _get_cmake_minver() @@ -146,8 +148,13 @@ end -- add target sources function _add_target_sources(cmakelists, target) cmakelists:print("target_sources(%s PRIVATE", target:name()) - for _, sourcefile in ipairs(target:sourcefiles()) do - cmakelists:print(" " .. _get_unix_path(sourcefile)) + for _, sourcebatch in pairs(target:sourcebatches()) do + local sourcekind = sourcebatch.sourcekind + if sourcekind == "cc" or sourcekind == "cxx" or sourcekind == "as" then + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + cmakelists:print(" " .. _get_unix_path(sourcefile)) + end + end end for _, headerfile in ipairs(target:headerfiles()) do cmakelists:print(" " .. _get_unix_path(headerfile)) @@ -448,24 +455,119 @@ end -- add target link options function _add_target_link_options(cmakelists, target) - local ldflags = _get_configs_from_target(target, "ldflags") - local shflags = _get_configs_from_target(target, "shflags") + local ldflags = _get_configs_from_target(target, "ldflags") + local shflags = _get_configs_from_target(target, "shflags") if #ldflags > 0 or #shflags > 0 then - local cmake_minver = _get_cmake_minver() - if cmake_minver:ge("3.13.0") then - cmakelists:print("target_link_options(%s PRIVATE", target:name()) - else - cmakelists:print("target_link_libraries(%s PRIVATE", target:name()) - end + local flags = {} for _, flag in ipairs(table.unique(table.join(ldflags, shflags))) do if target:linker():has_flags(flag) then + table.insert(flags, flag) + end + end + if #flags > 0 then + local cmake_minver = _get_cmake_minver() + if cmake_minver:ge("3.13.0") then + cmakelists:print("target_link_options(%s PRIVATE", target:name()) + else + cmakelists:print("target_link_libraries(%s PRIVATE", target:name()) + end + for _, flag in ipairs(flags) do cmakelists:print(" " .. flag) end + cmakelists:print(")") + end + end +end + +-- add custom command +function _add_target_custom_command(cmakelists, target, command, suffix) + cmakelists:print("add_custom_command(TARGET %s", target:name()) + if suffix == "prefix" then + cmakelists:print(" PRE_BUILD") + elseif suffix == "suffix" then + cmakelists:print(" POST_BUILD") + end + cmakelists:print(" COMMAND %s", os.args(command)) + cmakelists:print(" VERBATIM") + cmakelists:print(")") +end + +-- add target custom commands for target +function _add_target_custom_commands_for_target(cmakelists, target, suffix) + for _, ruleinst in ipairs(target:orderules()) do + local scriptname = "buildcmd" .. (suffix and ("_" .. suffix) or "") + local script = ruleinst:script(scriptname) + if script then + local batchcmds_ = batchcmds.new({target = target}) + script(target, batchcmds_, {}) + if not batchcmds_:empty() then + for _, cmd in ipairs(batchcmds_:cmds()) do + if cmd.program then + _add_target_custom_command(cmakelists, target, table.join(cmd.program, cmd.argv), suffix) + end + end + end end - cmakelists:print(")") end end +-- add target custom commands for object rules +function _add_target_custom_commands_for_objectrules(cmakelists, target, sourcebatch, suffix) + + -- get rule + local rulename = assert(sourcebatch.rulename, "unknown rule for sourcebatch!") + local ruleinst = assert(project.rule(rulename) or rule.rule(rulename), "unknown rule: %s", rulename) + + -- generate commands for xx_buildcmd_files + local scriptname = "buildcmd_files" .. (suffix and ("_" .. suffix) or "") + local script = ruleinst:script(scriptname) + if script then + local batchcmds_ = batchcmds.new({target = target}) + script(target, batchcmds_, sourcebatch, {}) + if not batchcmds_:empty() then + for _, cmd in ipairs(batchcmds_:cmds()) do + if cmd.program then + _add_target_custom_command(cmakelists, target, table.join(cmd.program, cmd.argv), suffix) + end + end + end + end + + -- generate commands for xx_buildcmd_file + if not script then + scriptname = "buildcmd_file" .. (suffix and ("_" .. suffix) or "") + script = ruleinst:script(scriptname) + if script then + local sourcekind = sourcebatch.sourcekind + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local batchcmds_ = batchcmds.new({target = target}) + script(target, batchcmds_, sourcefile, {}) + if not batchcmds_:empty() then + for _, cmd in ipairs(batchcmds_:cmds()) do + if cmd.program then + _add_target_custom_command(cmakelists, target, table.join(cmd.program, cmd.argv), suffix) + end + end + end + end + end + end +end + +-- add target custom commands +function _add_target_custom_commands(cmakelists, target) + _add_target_custom_commands_for_target(cmakelists, target, "before") + for _, sourcebatch in pairs(target:sourcebatches()) do + local sourcekind = sourcebatch.sourcekind + if sourcekind ~= "cc" and sourcekind ~= "cxx" and sourcekind ~= "as" then + _add_target_custom_commands_for_objectrules(cmakelists, target, sourcebatch, "before") + _add_target_custom_commands_for_objectrules(cmakelists, target, sourcebatch) + _add_target_custom_commands_for_objectrules(cmakelists, target, sourcebatch, "after") + end + end + _add_target_custom_commands_for_target(cmakelists, target, "after") +end + -- TODO export target headers (deprecated) function _export_target_headers(target) local srcheaders, dstheaders = target:headers() @@ -543,6 +645,9 @@ function _add_target(cmakelists, target) -- add target link options _add_target_link_options(cmakelists, target) + -- add target custom commands + _add_target_custom_commands(cmakelists, target) + -- add target sources _add_target_sources(cmakelists, target) diff --git a/xmake/rules/utils/bin2c/xmake.lua b/xmake/rules/utils/bin2c/xmake.lua index 5110ea2fd..81e042c41 100644 --- a/xmake/rules/utils/bin2c/xmake.lua +++ b/xmake/rules/utils/bin2c/xmake.lua @@ -20,12 +20,18 @@ rule("utils.bin2c") set_extensions(".bin") + on_load(function (target) + local headerdir = path.join(target:autogendir(), "rules", "c++", "bin2c") + if not os.isdir(headerdir) then + os.mkdir(headerdir) + end + target:add("includedirs", headerdir) + end) before_buildcmd_file(function (target, batchcmds, sourcefile_bin, opt) -- get header file local headerdir = path.join(target:autogendir(), "rules", "c++", "bin2c") local headerfile = path.join(headerdir, path.filename(sourcefile_bin) .. ".h") - target:add("includedirs", headerdir) -- add commands batchcmds:show_progress(opt.progress, "${color.build.object}generating.bin2c %s", sourcefile_bin) -- cgit v1.3.1 From 6f1d565decf6623cad7c56ff3d1badcc2f40e6d4 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 28 Oct 2021 23:31:06 +0800 Subject: improve pre-build for cmake custom command --- CHANGELOG.md | 2 ++ xmake/plugins/project/cmake/cmakelists.lua | 34 ++++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f0821a32..42a4452ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ * [#1767](https://github.com/xmake-io/xmake/issues/1767): Support Circle compiler * [#1753](https://github.com/xmake-io/xmake/issues/1753): Support armcc/armclang toolchains for Keil/MDK * [#1774](https://github.com/xmake-io/xmake/issues/1774): Add table.contains api +* [#1735](https://github.com/xmake-io/xmake/issues/1735): Add custom command in cmake generator ### Changes @@ -1125,6 +1126,7 @@ * [#1767](https://github.com/xmake-io/xmake/issues/1767): 支持 Circle 编译器 * [#1753](https://github.com/xmake-io/xmake/issues/1753): 支持 Keil/MDK 的 armcc/armclang 工具链 * [#1774](https://github.com/xmake-io/xmake/issues/1774): 添加 table.contains api +* [#1735](https://github.com/xmake-io/xmake/issues/1735): 添加自定义命令到 cmake 生成器 ### 改进 diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index c43f7584f..b4d9fe952 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -481,15 +481,31 @@ end -- add custom command function _add_target_custom_command(cmakelists, target, command, suffix) - cmakelists:print("add_custom_command(TARGET %s", target:name()) - if suffix == "prefix" then - cmakelists:print(" PRE_BUILD") - elseif suffix == "suffix" then - cmakelists:print(" POST_BUILD") - end - cmakelists:print(" COMMAND %s", os.args(command)) - cmakelists:print(" VERBATIM") - cmakelists:print(")") + local command_str = os.args(command) + if suffix == "before" then + -- ADD_CUSTOM_COMMAND and PRE_BUILD did not work as I expected, + -- so we need use add_dependencies and fake target to support it. + -- + -- @see https://gitlab.kitware.com/cmake/cmake/-/issues/17802 + -- + local key = hash.uuid(command_str):split("-", {plain = true})[1] + cmakelists:print("add_custom_command(OUTPUT output_%s", key) + cmakelists:print(" COMMAND %s", command_str) + cmakelists:print(" VERBATIM") + cmakelists:print(")") + cmakelists:print("add_custom_target(target_%s", key) + cmakelists:print(" DEPENDS output_%s", key) + cmakelists:print(")") + cmakelists:print("add_dependencies(%s target_%s)", target:name(), key) + else + cmakelists:print("add_custom_command(TARGET %s", target:name()) + if suffix == "after" then + cmakelists:print(" POST_BUILD") + end + cmakelists:print(" COMMAND %s", command_str) + cmakelists:print(" VERBATIM") + cmakelists:print(")") + end end -- add target custom commands for target -- cgit v1.3.1 From a1e47674d4ce9d61bbb52d084fdf9453eda0d6da Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 28 Oct 2021 23:37:23 +0800 Subject: add more command for cmake --- xmake/plugins/project/cmake/cmakelists.lua | 40 +++++++++++++++++++++++++----- xmake/plugins/project/make/makefile.lua | 6 ++--- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index b4d9fe952..0a417c997 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -479,18 +479,45 @@ function _add_target_link_options(cmakelists, target) end end +-- get command string +function _get_command_string(cmd) + local kind = cmd.kind + if cmd.program then + return os.args(table.join(cmd.program, cmd.argv)) + elseif kind == "cp" then + if is_subhost("windows") then + return string.format("copy /Y %s %s > NUL 2>&1", cmd.srcpath, cmd.dstpath) + else + return string.format("cp %s %s", cmd.srcpath, cmd.dstpath) + end + elseif kind == "rm" then + if is_subhost("windows") then + return string.format("del /F /Q %s > NUL 2>&1 || rmdir /S /Q %s > NUL 2>&1", cmd.filepath, cmd.filepath) + else + return string.format("rm -rf %s", cmd.filepath) + end + elseif kind == "mkdir" then + if is_subhost("windows") then + return string.format("mkdir %s > NUL 2>&1", cmd.dir) + else + return string.format("mkdir -p %s", cmd.dir) + end + elseif kind == "show" then + return string.format("echo %s", cmd.showtext) + end +end + -- add custom command function _add_target_custom_command(cmakelists, target, command, suffix) - local command_str = os.args(command) if suffix == "before" then -- ADD_CUSTOM_COMMAND and PRE_BUILD did not work as I expected, -- so we need use add_dependencies and fake target to support it. -- -- @see https://gitlab.kitware.com/cmake/cmake/-/issues/17802 -- - local key = hash.uuid(command_str):split("-", {plain = true})[1] + local key = hash.uuid(command):split("-", {plain = true})[1] cmakelists:print("add_custom_command(OUTPUT output_%s", key) - cmakelists:print(" COMMAND %s", command_str) + cmakelists:print(" COMMAND %s", command) cmakelists:print(" VERBATIM") cmakelists:print(")") cmakelists:print("add_custom_target(target_%s", key) @@ -502,7 +529,7 @@ function _add_target_custom_command(cmakelists, target, command, suffix) if suffix == "after" then cmakelists:print(" POST_BUILD") end - cmakelists:print(" COMMAND %s", command_str) + cmakelists:print(" COMMAND %s", command) cmakelists:print(" VERBATIM") cmakelists:print(")") end @@ -518,8 +545,9 @@ function _add_target_custom_commands_for_target(cmakelists, target, suffix) script(target, batchcmds_, {}) if not batchcmds_:empty() then for _, cmd in ipairs(batchcmds_:cmds()) do - if cmd.program then - _add_target_custom_command(cmakelists, target, table.join(cmd.program, cmd.argv), suffix) + local command = _get_command_string(cmd) + if command then + _add_target_custom_command(cmakelists, target, command, suffix) end end end diff --git a/xmake/plugins/project/make/makefile.lua b/xmake/plugins/project/make/makefile.lua index 6b94cf992..f9f0581c0 100644 --- a/xmake/plugins/project/make/makefile.lua +++ b/xmake/plugins/project/make/makefile.lua @@ -33,7 +33,7 @@ end -- mkdir directory function _mkdir(makefile, dir) - if is_plat("windows") then + if is_subhost("windows") then makefile:print("\t-@mkdir %s > NUL 2>&1", dir) else makefile:print("\t@mkdir -p %s", dir) @@ -42,7 +42,7 @@ end -- copy file function _cp(makefile, sourcefile, targetfile) - if is_plat("windows") then + if is_subhost("windows") then makefile:print("\t@copy /Y %s %s > NUL 2>&1", sourcefile, targetfile) else makefile:print("\t@cp %s %s", sourcefile, targetfile) @@ -51,7 +51,7 @@ end -- try to remove the given file or directory function _tryrm(makefile, filedir) - if is_plat("windows") then + if is_subhost("windows") then -- we attempt to delete it as file first, we remove it as directory if failed makefile:print("\t@del /F /Q %s > NUL 2>&1 || rmdir /S /Q %s > NUL 2>&1", filedir, filedir) else -- cgit v1.3.1 From d48ea6ae405def382ece2aa58cad9ab96d6fcd80 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 28 Oct 2021 23:38:39 +0800 Subject: improve custom command --- xmake/plugins/project/cmake/cmakelists.lua | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 0a417c997..a8b64fa95 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -515,7 +515,7 @@ function _add_target_custom_command(cmakelists, target, command, suffix) -- -- @see https://gitlab.kitware.com/cmake/cmake/-/issues/17802 -- - local key = hash.uuid(command):split("-", {plain = true})[1] + local key = target:name() .. "_" .. hash.uuid():split("-", {plain = true})[1] cmakelists:print("add_custom_command(OUTPUT output_%s", key) cmakelists:print(" COMMAND %s", command) cmakelists:print(" VERBATIM") @@ -570,8 +570,9 @@ function _add_target_custom_commands_for_objectrules(cmakelists, target, sourceb script(target, batchcmds_, sourcebatch, {}) if not batchcmds_:empty() then for _, cmd in ipairs(batchcmds_:cmds()) do - if cmd.program then - _add_target_custom_command(cmakelists, target, table.join(cmd.program, cmd.argv), suffix) + local command = _get_command_string(cmd) + if command then + _add_target_custom_command(cmakelists, target, command, suffix) end end end @@ -588,8 +589,9 @@ function _add_target_custom_commands_for_objectrules(cmakelists, target, sourceb script(target, batchcmds_, sourcefile, {}) if not batchcmds_:empty() then for _, cmd in ipairs(batchcmds_:cmds()) do - if cmd.program then - _add_target_custom_command(cmakelists, target, table.join(cmd.program, cmd.argv), suffix) + local command = _get_command_string(cmd) + if command then + _add_target_custom_command(cmakelists, target, command, suffix) end end end -- cgit v1.3.1 From 5dfb6ef01df389dbfa8d5cbb12128caf6a655d1f Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 28 Oct 2021 17:10:27 +0800 Subject: Update xmake.lua --- xmake/toolchains/nim/xmake.lua | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/xmake/toolchains/nim/xmake.lua b/xmake/toolchains/nim/xmake.lua index 39565822d..e85a80204 100644 --- a/xmake/toolchains/nim/xmake.lua +++ b/xmake/toolchains/nim/xmake.lua @@ -18,28 +18,22 @@ -- @file xmake.lua -- --- define toolchain toolchain("nim") - -- set homepage set_homepage("https://nim-lang.org/") set_description("Nim Programming Language Compiler") - -- set toolset set_toolset("nc", "$(env NC)", "nim") set_toolset("ncld", "$(env NC)", "nim") set_toolset("ncsh", "$(env NC)", "nim") set_toolset("ncar", "$(env NC)", "nim") - -- on load on_load(function (toolchain) if toolchain:is_plat("windows") then toolchain:set("ncflags", "--cc:vcc") local msvc = import("core.tool.toolchain", {anonymous = true}).load("msvc", {plat = toolchain:plat(), arch = toolchain:arch()}) - if msvc:check() then - for name, value in pairs(msvc:get("runenvs")) do - toolchain:add("runenvs", name, value) - end + for name, value in pairs(msvc:get("runenvs")) do + toolchain:add("runenvs", name, value) end end toolchain:set("ncshflags", "") -- cgit v1.3.1 From 3b0024764afaa0391b903059a0215c638cb03e85 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Thu, 28 Oct 2021 12:58:16 +0200 Subject: MSVC: Add flag conversion for Wswitch and Wswitch-enum --- xmake/modules/core/tools/cl.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xmake/modules/core/tools/cl.lua b/xmake/modules/core/tools/cl.lua index 9e9f38ab8..acf99529f 100644 --- a/xmake/modules/core/tools/cl.lua +++ b/xmake/modules/core/tools/cl.lua @@ -62,6 +62,8 @@ function init(self) , ["-W2"] = "-W2" , ["-W3"] = "-W3" , ["-Werror"] = "-WX" + , ["-Wswitch"] = "-we4062" + , ["-Wswitch-enum"] = "-we4061" , ["%-Wno%-error=.*"] = "" , ["%-fno%-.*"] = "" -- cgit v1.3.1 From 2505c46acf19f66d92765854f0853d251be30506 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 29 Oct 2021 00:36:05 +0800 Subject: improve cmakelists --- xmake/modules/private/utils/batchcmds.lua | 14 ++++++++++++++ xmake/plugins/project/cmake/cmakelists.lua | 29 +++++++++++++++-------------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/xmake/modules/private/utils/batchcmds.lua b/xmake/modules/private/utils/batchcmds.lua index 34dd5d583..bb5204072 100644 --- a/xmake/modules/private/utils/batchcmds.lua +++ b/xmake/modules/private/utils/batchcmds.lua @@ -117,6 +117,14 @@ function _runcmd_mkdir(cmd, opt) end end +-- run command: os.cd +function _runcmd_cd(cmd, opt) + local dir = cmd.dir + if not opt.dryrun then + os.cd(dir) + end +end + -- run command: os.rm function _runcmd_rm(cmd, opt) local filepath = cmd.filepath @@ -158,6 +166,7 @@ function _runcmd(cmd, opt) vrunv = _runcmd_vrunv, execv = _runcmd_execv, mkdir = _runcmd_mkdir, + cd = _runcmd_cd, rm = _runcmd_rm, cp = _runcmd_cp, mv = _runcmd_mv, @@ -268,6 +277,11 @@ function batchcmds:ln(srcpath, dstpath, opt) table.insert(self:cmds(), {kind = "ln", srcpath = srcpath, dstpath = dstpath, opt = opt}) end +-- add command: os.cd +function batchcmds:cd(dir, opt) + table.insert(self:cmds(), {kind = "cd", dir = dir, opt = opt}) +end + -- add command: show function batchcmds:show(format, ...) local showtext = string.format(format, ...) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index a8b64fa95..3223f1c9f 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -482,26 +482,27 @@ end -- get command string function _get_command_string(cmd) local kind = cmd.kind + local opt = cmd.opt if cmd.program then - return os.args(table.join(cmd.program, cmd.argv)) + local command = os.args(table.join(cmd.program, cmd.argv)) + if opt and opt.curdir then + command = "${CMAKE_COMMAND} -E chdir \"" .. opt.curdir .. "\" " .. command + end + return command elseif kind == "cp" then - if is_subhost("windows") then - return string.format("copy /Y %s %s > NUL 2>&1", cmd.srcpath, cmd.dstpath) + if os.isdir(cmd.srcpath) then + return string.format("${CMAKE_COMMAND} -E copy_directory %s %s", cmd.srcpath, cmd.dstpath) else - return string.format("cp %s %s", cmd.srcpath, cmd.dstpath) + return string.format("${CMAKE_COMMAND} -E copy %s %s", cmd.srcpath, cmd.dstpath) end elseif kind == "rm" then - if is_subhost("windows") then - return string.format("del /F /Q %s > NUL 2>&1 || rmdir /S /Q %s > NUL 2>&1", cmd.filepath, cmd.filepath) - else - return string.format("rm -rf %s", cmd.filepath) - end + return string.format("${CMAKE_COMMAND} -E rm -rf %s", cmd.filepath) + elseif kind == "mv" then + return string.format("${CMAKE_COMMAND} -E rename %s %s", cmd.srcpath, cmd.dstpath) + elseif kind == "cd" then + return string.format("cd %s", cmd.dir) elseif kind == "mkdir" then - if is_subhost("windows") then - return string.format("mkdir %s > NUL 2>&1", cmd.dir) - else - return string.format("mkdir -p %s", cmd.dir) - end + return string.format("${CMAKE_COMMAND} -E make_directory %s", cmd.dir) elseif kind == "show" then return string.format("echo %s", cmd.showtext) end -- cgit v1.3.1 From 557c4c790f5d932052f223127dca14860b03eabc Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 29 Oct 2021 00:40:23 +0800 Subject: add git branch and commit --- core/makefile | 14 ++++++++++++++ core/src/xmake/engine.c | 4 +++- core/src/xmake/makefile | 7 ++++++- core/src/xmake/xmake.config.h.in | 2 ++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/core/makefile b/core/makefile index 40811af32..51c7611fa 100644 --- a/core/makefile +++ b/core/makefile @@ -298,6 +298,14 @@ base_LIBNAMES += $(shell if { cat detect/readline.c | $(CC) -xc - -lreadline -o base_LIBNAMES += m dl pthread endif +# get branch and commit +ifeq ($(BRANCH),) +BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null) +endif +ifeq ($(COMMIT),) +COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null) +endif + # check jit compiler ifeq ($(PLAT),linux) luajit_JIT :=$(shell if [ -f "/etc/redhat-release" ]; then echo "nojit"; else echo "jit"; fi ) @@ -360,6 +368,8 @@ config : .null @$(ECHO) " small:\t\t"$(SMALL) @$(ECHO) " ccache:\t\t"$(CCACHE) @$(ECHO) " distcc:\t\t"$(DISTCC) + @$(ECHO) " branch:\t\t"$(BRANCH) + @$(ECHO) " commit:\t\t"$(COMMIT) @$(ECHO) " luajit:\t\t"$(luajit_JIT) @$(ECHO) "" @$(ECHO) "packages:" @@ -393,6 +403,10 @@ config : .null @$(ECHO) "# project" >> .config.mak @$(ECHO) "PRO_DIR ="$(PRO_DIR) >> .config.mak @$(ECHO) "export PRO_DIR" >> .config.mak + @$(ECHO) "BRANCH ="$(BRANCH) >> .config.mak + @$(ECHO) "export BRANCH" >> .config.mak + @$(ECHO) "COMMIT ="$(COMMIT) >> .config.mak + @$(ECHO) "export COMMIT" >> .config.mak @$(ECHO) "" >> .config.mak @$(ECHO) "# profile" >> .config.mak @$(ECHO) "PROF ="$(PROF) >> .config.mak diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index 0793f426e..f63e43ee1 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -906,7 +906,9 @@ xm_engine_ref_t xm_engine_init(tb_char_t const* name, xm_engine_lni_initalizer_c // init version string tb_char_t version_cstr[256] = {0}; - tb_snprintf(version_cstr, sizeof(version_cstr), "%u.%u.%u+%llu", version->major, version->minor, version->alter, version->build); + if (tb_strcmp(XM_CONFIG_VERSION_BRANCH, "") && tb_strcmp(XM_CONFIG_VERSION_COMMIT, "")) + tb_snprintf(version_cstr, sizeof(version_cstr), "%u.%u.%u+%s-%s", version->major, version->minor, version->alter, XM_CONFIG_VERSION_COMMIT, XM_CONFIG_VERSION_BRANCH); + else tb_snprintf(version_cstr, sizeof(version_cstr), "%u.%u.%u+%llu", version->major, version->minor, version->alter, version->build); lua_pushstring(engine->lua, version_cstr); lua_setglobal(engine->lua, "_VERSION"); diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index 48eb51974..88bce5d1f 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -166,7 +166,12 @@ ifeq ($(RUNTIME),lua) xmake_INC_DIRS += ../lua/lua xmake_CXFLAGS += -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 -DLUA_COMPAT_5_3 endif - +ifneq ($(BRANCH),) +xmake_CXFLAGS += -DXM_CONFIG_VERSION_BRANCH="\"$(BRANCH)\"" +endif +ifneq ($(COMMIT),) +xmake_CXFLAGS += -DXM_CONFIG_VERSION_COMMIT="\"$(COMMIT)\"" +endif # suffix include $(PRO_DIR)/suffix.mak diff --git a/core/src/xmake/xmake.config.h.in b/core/src/xmake/xmake.config.h.in index d4c1f675a..a896b1335 100644 --- a/core/src/xmake/xmake.config.h.in +++ b/core/src/xmake/xmake.config.h.in @@ -7,5 +7,7 @@ #define XM_CONFIG_VERSION_MINOR ${VERSION_MINOR} #define XM_CONFIG_VERSION_ALTER ${VERSION_ALTER} #define XM_CONFIG_VERSION_BUILD ${VERSION_BUILD} +#define XM_CONFIG_VERSION_BRANCH "${GIT_BRANCH}" +#define XM_CONFIG_VERSION_COMMIT "${GIT_COMMIT}" #endif -- cgit v1.3.1 From acf31495a316b7eda54a200d150912b267c6e583 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 29 Oct 2021 00:40:48 +0800 Subject: fix makefile --- core/src/xmake/makefile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index 88bce5d1f..f45d834e2 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -166,12 +166,8 @@ ifeq ($(RUNTIME),lua) xmake_INC_DIRS += ../lua/lua xmake_CXFLAGS += -DLUA_COMPAT_5_1 -DLUA_COMPAT_5_2 -DLUA_COMPAT_5_3 endif -ifneq ($(BRANCH),) xmake_CXFLAGS += -DXM_CONFIG_VERSION_BRANCH="\"$(BRANCH)\"" -endif -ifneq ($(COMMIT),) xmake_CXFLAGS += -DXM_CONFIG_VERSION_COMMIT="\"$(COMMIT)\"" -endif # suffix include $(PRO_DIR)/suffix.mak -- cgit v1.3.1 From d4cff6e11c4fb3c0bbe466af800bf9ab66e8f683 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 29 Oct 2021 00:41:47 +0800 Subject: improve version --- core/src/xmake/engine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index f63e43ee1..70dba69d7 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -907,7 +907,7 @@ xm_engine_ref_t xm_engine_init(tb_char_t const* name, xm_engine_lni_initalizer_c // init version string tb_char_t version_cstr[256] = {0}; if (tb_strcmp(XM_CONFIG_VERSION_BRANCH, "") && tb_strcmp(XM_CONFIG_VERSION_COMMIT, "")) - tb_snprintf(version_cstr, sizeof(version_cstr), "%u.%u.%u+%s-%s", version->major, version->minor, version->alter, XM_CONFIG_VERSION_COMMIT, XM_CONFIG_VERSION_BRANCH); + tb_snprintf(version_cstr, sizeof(version_cstr), "%u.%u.%u-%s+%s", version->major, version->minor, version->alter, XM_CONFIG_VERSION_BRANCH, XM_CONFIG_VERSION_COMMIT); else tb_snprintf(version_cstr, sizeof(version_cstr), "%u.%u.%u+%llu", version->major, version->minor, version->alter, version->build); lua_pushstring(engine->lua, version_cstr); lua_setglobal(engine->lua, "_VERSION"); -- cgit v1.3.1 From b8baa986376112e67221fa8b982d2b3197e1d919 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 29 Oct 2021 00:44:04 +0800 Subject: improve version build number --- core/src/xmake/engine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index 70dba69d7..34ed7a196 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -907,7 +907,7 @@ xm_engine_ref_t xm_engine_init(tb_char_t const* name, xm_engine_lni_initalizer_c // init version string tb_char_t version_cstr[256] = {0}; if (tb_strcmp(XM_CONFIG_VERSION_BRANCH, "") && tb_strcmp(XM_CONFIG_VERSION_COMMIT, "")) - tb_snprintf(version_cstr, sizeof(version_cstr), "%u.%u.%u-%s+%s", version->major, version->minor, version->alter, XM_CONFIG_VERSION_BRANCH, XM_CONFIG_VERSION_COMMIT); + tb_snprintf(version_cstr, sizeof(version_cstr), "%u.%u.%u+%s.%s", version->major, version->minor, version->alter, XM_CONFIG_VERSION_BRANCH, XM_CONFIG_VERSION_COMMIT); else tb_snprintf(version_cstr, sizeof(version_cstr), "%u.%u.%u+%llu", version->major, version->minor, version->alter, version->build); lua_pushstring(engine->lua, version_cstr); lua_setglobal(engine->lua, "_VERSION"); -- cgit v1.3.1 From 9eedba8ac9cd4832e20343a0eda720b9c1ceb5a9 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 29 Oct 2021 00:45:53 +0800 Subject: add xmake.branch --- xmake/core/base/xmake.lua | 7 ++++++- xmake/core/sandbox/modules/xmake.lua | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/xmake/core/base/xmake.lua b/xmake/core/base/xmake.lua index 239540a5a..837742af2 100644 --- a/xmake/core/base/xmake.lua +++ b/xmake/core/base/xmake.lua @@ -29,7 +29,7 @@ function xmake.name() return xmake._NAME or "xmake" end --- get xmake version +-- get xmake version, e.g. v2.5.8+dev.d4cff6e11 function xmake.version() if xmake._VERSION_CACHE == nil then xmake._VERSION_CACHE = semver.new(xmake._VERSION) or false @@ -37,6 +37,11 @@ function xmake.version() return xmake._VERSION_CACHE or nil end +-- get the git branch of xmake version, e.g. build: {"dev", "d4cff6e11"} +function xmake.branch() + return xmake.version():build()[1] +end + -- get the program directory function xmake.programdir() return xmake._PROGRAM_DIR diff --git a/xmake/core/sandbox/modules/xmake.lua b/xmake/core/sandbox/modules/xmake.lua index fcc6437e1..70e5f5e36 100644 --- a/xmake/core/sandbox/modules/xmake.lua +++ b/xmake/core/sandbox/modules/xmake.lua @@ -26,6 +26,7 @@ local sandbox_xmake = sandbox_xmake or {} -- inherit some builtin interfaces sandbox_xmake.version = xmake.version +sandbox_xmake.branch = xmake.branch sandbox_xmake.programdir = xmake.programdir sandbox_xmake.programfile = xmake.programfile sandbox_xmake.luajit = xmake.luajit -- cgit v1.3.1 From c8fc101fa5289a657dca1fdfe8a3b6195cfe3776 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 29 Oct 2021 22:54:08 +0800 Subject: improve get.sh --- scripts/get.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/get.sh b/scripts/get.sh index f7ef65acf..4aa988526 100755 --- a/scripts/get.sh +++ b/scripts/get.sh @@ -143,7 +143,8 @@ test_tools() echo -e "$prog" | clang -xc - -o /dev/null -lreadline || echo -e "$prog" | cc -xc - -o /dev/null -I/usr/local/include -L/usr/local/lib -lreadline || echo -e "$prog" | gcc -xc - -o /dev/null -I/usr/local/include -L/usr/local/lib -lreadline || - echo -e "$prog" | clang -xc - -o /dev/null -I/usr/local/include -L/usr/local/lib -lreadline + echo -e "$prog" | clang -xc - -o /dev/null -I/usr/local/include -L/usr/local/lib -lreadline || + echo -e "$prog" | cc -xc -c - -o /dev/null -I/usr/include -I/usr/local/include } } >/dev/null 2>&1 } @@ -156,6 +157,7 @@ install_tools() { emerge -V >/dev/null 2>&1 && $sudoprefix emerge -atv dev-vcs/git ccache; } || { pkg list-installed >/dev/null 2>&1 && $sudoprefix pkg install -y git getconf build-essential readline ccache; } || # termux { pkg help >/dev/null 2>&1 && $sudoprefix pkg install -y git readline ccache ncurses; } || # freebsd + { nix-env --version >/dev/null 2>&1 && nix-env -i git gcc readline ncurses; } || # nixos { apk --version >/dev/null 2>&1 && $sudoprefix apk add git gcc g++ make readline-dev ncurses-dev libc-dev linux-headers; } || { xbps-install --version >/dev/null 2>&1 && $sudoprefix xbps-install -Sy git base-devel ccache; } #void -- cgit v1.3.1 From 72e8db58ba933ab481929525a3c524a316ff4251 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 29 Oct 2021 22:56:09 +0800 Subject: fix get.sh for nixos --- scripts/get.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/get.sh b/scripts/get.sh index 4aa988526..834289767 100755 --- a/scripts/get.sh +++ b/scripts/get.sh @@ -40,7 +40,7 @@ remote_get_content() { if curl --version >/dev/null 2>&1 then curl -fSL "$1" - elif wget --version >/dev/null 2>&1 + elif wget --version >/dev/null 2>&1 || wget --help >/dev/null 2>&1 then wget "$1" -O - fi -- cgit v1.3.1 From 286ca7ad3ad325758c38546e5c8c2004c8719fe6 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 29 Oct 2021 22:56:43 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42a4452ad..aca5b9485 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ * [#1528](https://github.com/xmake-io/xmake/issues/1528): Check c++17/20 features * [#1729](https://github.com/xmake-io/xmake/issues/1729): Improve C++20 modules for clang/gcc/msvc, support inter-module dependency compilation and parallel optimization * [#1779](https://github.com/xmake-io/xmake/issues/1779): Remove builtin `-Gd` for ml.exe/x86 +* [#1781](https://github.com/xmake-io/xmake/issues/1781): Improve get.sh installation script to support nixos ## v2.5.8 @@ -1127,6 +1128,7 @@ * [#1753](https://github.com/xmake-io/xmake/issues/1753): 支持 Keil/MDK 的 armcc/armclang 工具链 * [#1774](https://github.com/xmake-io/xmake/issues/1774): 添加 table.contains api * [#1735](https://github.com/xmake-io/xmake/issues/1735): 添加自定义命令到 cmake 生成器 +* [#1781](https://github.com/xmake-io/xmake/issues/1781): 改进 get.sh 安装脚本支持 nixos ### 改进 -- cgit v1.3.1 From 9070ba7533f5d3081ef9b6f46bf15752c674067d Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 29 Oct 2021 22:58:19 +0800 Subject: improve get.sh --- scripts/get.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/get.sh b/scripts/get.sh index 834289767..8abf1e26e 100755 --- a/scripts/get.sh +++ b/scripts/get.sh @@ -144,7 +144,9 @@ test_tools() echo -e "$prog" | cc -xc - -o /dev/null -I/usr/local/include -L/usr/local/lib -lreadline || echo -e "$prog" | gcc -xc - -o /dev/null -I/usr/local/include -L/usr/local/lib -lreadline || echo -e "$prog" | clang -xc - -o /dev/null -I/usr/local/include -L/usr/local/lib -lreadline || - echo -e "$prog" | cc -xc -c - -o /dev/null -I/usr/include -I/usr/local/include + echo -e "$prog" | cc -xc -c - -o /dev/null -I/usr/include -I/usr/local/include || + echo -e "$prog" | gcc -xc -c - -o /dev/null -I/usr/include -I/usr/local/include || + echo -e "$prog" | clang -xc -c - -o /dev/null -I/usr/include -I/usr/local/include } } >/dev/null 2>&1 } -- cgit v1.3.1 From 5db0e363896320b0cde42dd857a61941176df6e6 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 29 Oct 2021 23:00:28 +0800 Subject: improve get.sh --- scripts/get.sh | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/scripts/get.sh b/scripts/get.sh index 8abf1e26e..01634a967 100755 --- a/scripts/get.sh +++ b/scripts/get.sh @@ -133,17 +133,14 @@ my_exit(){ } test_tools() { - prog='#include \n#include \nint main(){readline(0);return 0;}' + prog='#include \nint main(){return 0;}' { git --version && $make --version && { - echo -e "$prog" | cc -xc - -o /dev/null -lreadline || - echo -e "$prog" | gcc -xc - -o /dev/null -lreadline || - echo -e "$prog" | clang -xc - -o /dev/null -lreadline || - echo -e "$prog" | cc -xc - -o /dev/null -I/usr/local/include -L/usr/local/lib -lreadline || - echo -e "$prog" | gcc -xc - -o /dev/null -I/usr/local/include -L/usr/local/lib -lreadline || - echo -e "$prog" | clang -xc - -o /dev/null -I/usr/local/include -L/usr/local/lib -lreadline || + echo -e "$prog" | cc -xc - -o /dev/null || + echo -e "$prog" | gcc -xc - -o /dev/null || + echo -e "$prog" | clang -xc - -o /dev/null || echo -e "$prog" | cc -xc -c - -o /dev/null -I/usr/include -I/usr/local/include || echo -e "$prog" | gcc -xc -c - -o /dev/null -I/usr/include -I/usr/local/include || echo -e "$prog" | clang -xc -c - -o /dev/null -I/usr/include -I/usr/local/include -- cgit v1.3.1 From b876a04a87a87db33f427ff894ae74a2431d5299 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 29 Oct 2021 23:54:57 +0800 Subject: update readme --- README.md | 2 +- README_zh.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3c1350bfb..fe3fa6864 100644 --- a/README.md +++ b/README.md @@ -215,7 +215,7 @@ The test project: [xmake-core](https://github.com/xmake-io/xmake/tree/master/cor ```bash $ xmake show -l toolchains xcode Xcode IDE -vs VisualStudio IDE +msvc Microsoft Visual C/C++ Compiler yasm The Yasm Modular Assembler clang A C language family frontend for LLVM go Go Programming Language Compiler diff --git a/README_zh.md b/README_zh.md index 006d413e1..5fa08e133 100644 --- a/README_zh.md +++ b/README_zh.md @@ -224,7 +224,7 @@ $ xmake f --menu ```bash $ xmake show -l toolchains xcode Xcode IDE -vs VisualStudio IDE +msvc Microsoft Visual C/C++ Compiler yasm The Yasm Modular Assembler clang A C language family frontend for LLVM go Go Programming Language Compiler -- cgit v1.3.1 From c3384d3f1927eee53ebb8d94ed764e8de7ddc212 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 30 Oct 2021 22:20:42 +0800 Subject: Update gcc.lua --- xmake/modules/core/tools/gcc.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index 2e93ea2bb..5baa9069d 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -500,7 +500,10 @@ function compile(self, sourcefile, objectfile, dependinfo, flags) if ok and errdata and #errdata > 0 and (option.get("diagnosis") or option.get("warning") or global.get("build_warning")) then local lines = errdata:split('\n', {plain = true}) if #lines > 0 then - local warnings = table.concat(table.slice(lines, 1, (#lines > 8 and 8 or #lines)), "\n") + if option.get("diagnosis") then + lines = table.slice(lines, 1, (#lines > 16 and 16 or #lines)) + end + local warnings = table.concat(lines, "\n") if progress.showing_without_scroll() then print("") end -- cgit v1.3.1 From f9af5b38ecf35c9e5741542e7a0f02f9dd0409f8 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 30 Oct 2021 22:22:22 +0800 Subject: Update cl.lua --- xmake/modules/core/tools/cl.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xmake/modules/core/tools/cl.lua b/xmake/modules/core/tools/cl.lua index acf99529f..7bbb6ff8b 100644 --- a/xmake/modules/core/tools/cl.lua +++ b/xmake/modules/core/tools/cl.lua @@ -476,7 +476,10 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) end end if #lines > 0 then - local warnings = table.concat(table.slice(lines, 1, (#lines > 8 and 8 or #lines)), "\r\n") + if not option.get("diagnosis") then + lines = table.slice(lines, 1, (#lines > 16 and 16 or #lines)) + end + local warnings = table.concat(lines, "\r\n") if progress.showing_without_scroll() then print("") end -- cgit v1.3.1 From 1fdc20b61c6a5abd5bbec59f6274c035897bb3b4 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 30 Oct 2021 22:22:59 +0800 Subject: Update gcc.lua --- xmake/modules/core/tools/gcc.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index 5baa9069d..224dc6c2d 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -500,7 +500,7 @@ function compile(self, sourcefile, objectfile, dependinfo, flags) if ok and errdata and #errdata > 0 and (option.get("diagnosis") or option.get("warning") or global.get("build_warning")) then local lines = errdata:split('\n', {plain = true}) if #lines > 0 then - if option.get("diagnosis") then + if not option.get("diagnosis") then lines = table.slice(lines, 1, (#lines > 16 and 16 or #lines)) end local warnings = table.concat(lines, "\n") -- cgit v1.3.1 From ce2c9b5eff82bf96804514b837dc215b6a07c739 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 31 Oct 2021 16:05:05 +0800 Subject: improve apt::find_package --- xmake/modules/package/manager/apt/find_package.lua | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/xmake/modules/package/manager/apt/find_package.lua b/xmake/modules/package/manager/apt/find_package.lua index 3fee1034f..27a0ebbe1 100644 --- a/xmake/modules/package/manager/apt/find_package.lua +++ b/xmake/modules/package/manager/apt/find_package.lua @@ -51,14 +51,11 @@ function main(name, opt) line = line:trim() -- get includedirs - -- we need not add it, gcc/clang will use /usr/ as default sysroot - --[[ local pos = line:find("include/", 1, true) if pos then + -- we need not add includedirs, gcc/clang will use /usr/ as default sysroot result = result or {} - result.includedirs = result.includedirs or {} - table.insert(result.includedirs, line:sub(1, pos + 7)) - end]] + end -- get linkdirs and links if line:endswith(".a") or line:endswith(".so") then -- cgit v1.3.1 From b41c432c85d82d7e7c5503635b1d04820c6fb783 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 31 Oct 2021 20:28:25 +0800 Subject: update version --- core/project.mak | 2 +- core/xmake.lua | 4 ++-- makefile | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/project.mak b/core/project.mak index 02bdcd9d9..99e6ca226 100644 --- a/core/project.mak +++ b/core/project.mak @@ -10,7 +10,7 @@ PRO_VERSION_MAJOR = 2 PRO_VERSION_MINOR = 5 # the project alter version -PRO_VERSION_ALTER = 8 +PRO_VERSION_ALTER = 9 # the project prefix PRO_PREFIX = XM_ diff --git a/core/xmake.lua b/core/xmake.lua index a176adf76..0070a3ca9 100644 --- a/core/xmake.lua +++ b/core/xmake.lua @@ -2,7 +2,7 @@ set_project("xmake") -- version -set_version("2.5.8", {build = "%Y%m%d%H%M"}) +set_version("2.5.9", {build = "%Y%m%d%H%M"}) -- set xmake min version set_xmakever("2.2.3") @@ -43,7 +43,7 @@ end -- the runtime option option("runtime") set_showmenu(true) - set_default("lua") + set_default("luajit") set_description("Use luajit or lua runtime") set_values("luajit", "lua") option_end() diff --git a/makefile b/makefile index 63d019542..c54d6cecd 100644 --- a/makefile +++ b/makefile @@ -17,7 +17,7 @@ endif # use luajit or lua backend ifeq ($(RUNTIME),) -RUNTIME :=lua +RUNTIME :=luajit endif # the temporary directory -- cgit v1.3.1 From 809ee9806f7ce18a30ef9628ff861b76385453b4 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 31 Oct 2021 20:33:08 +0800 Subject: update spec --- scripts/rpmbuild/SPECS/xmake.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/rpmbuild/SPECS/xmake.spec b/scripts/rpmbuild/SPECS/xmake.spec index 17d30d457..5540c4e76 100644 --- a/scripts/rpmbuild/SPECS/xmake.spec +++ b/scripts/rpmbuild/SPECS/xmake.spec @@ -1,4 +1,4 @@ -%define xmake_revision 3f673bdf28f6351e6f8ca83d4b84f598079a8e1f +%define xmake_revision b41c432c85d82d7e7c5503635b1d04820c6fb783 %define tbox_revision 7ca5145d40aa906fdc48b0b0e75e80412241be7e %define sv_revision 9a3cf7c8e589de4f70378824329882c4a047fffc %define lua_cjson_revision 515bab6d6d80b164b94db73af69609ea02f3a798 @@ -8,7 +8,7 @@ %undefine _disable_source_fetch Name: xmake -Version: 2.5.8 +Version: 2.5.9 Release: 1%{?dist} Summary: A cross-platform build utility based on Lua BuildArch: noarch -- cgit v1.3.1 From a9b29cac29628640c200a652a1c77f29d8aafd67 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 31 Oct 2021 20:49:24 +0800 Subject: update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aca5b9485..6f517a47c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## master (unreleased) +## v2.5.9 + ### New features * [#1736](https://github.com/xmake-io/xmake/issues/1736): Support wasi-sdk toolchain @@ -1113,6 +1115,8 @@ ## master (开发中) +## v2.5.9 + ### 新特性 * [#1736](https://github.com/xmake-io/xmake/issues/1736): 支持 wasi-sdk 工具链 -- cgit v1.3.1 From c637e4f21d22c5db2621bccb923ff2eb3ef596ec Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 31 Oct 2021 20:55:41 +0800 Subject: switch to lua5.4 --- core/xmake.lua | 2 +- makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/xmake.lua b/core/xmake.lua index 0070a3ca9..08fc49301 100644 --- a/core/xmake.lua +++ b/core/xmake.lua @@ -43,7 +43,7 @@ end -- the runtime option option("runtime") set_showmenu(true) - set_default("luajit") + set_default("lua") set_description("Use luajit or lua runtime") set_values("luajit", "lua") option_end() diff --git a/makefile b/makefile index c54d6cecd..63d019542 100644 --- a/makefile +++ b/makefile @@ -17,7 +17,7 @@ endif # use luajit or lua backend ifeq ($(RUNTIME),) -RUNTIME :=luajit +RUNTIME :=lua endif # the temporary directory -- cgit v1.3.1 From ec4c68a6da6522194916679e976161941e8d7462 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 31 Oct 2021 23:54:52 +0800 Subject: remove bin --- core/src/lua/lua | 2 +- core/src/tbox/tbox | 2 +- xmake/templates/nim/console/project/src/main | Bin 92184 -> 0 bytes 3 files changed, 2 insertions(+), 2 deletions(-) delete mode 100755 xmake/templates/nim/console/project/src/main diff --git a/core/src/lua/lua b/core/src/lua/lua index eadd8c717..75ea9ccbe 160000 --- a/core/src/lua/lua +++ b/core/src/lua/lua @@ -1 +1 @@ -Subproject commit eadd8c7178c79c814ecca9652973a9b9dd4cc71b +Subproject commit 75ea9ccbea7c4886f30da147fb67b693b2624c26 diff --git a/core/src/tbox/tbox b/core/src/tbox/tbox index 7ca5145d4..cde8c8ad9 160000 --- a/core/src/tbox/tbox +++ b/core/src/tbox/tbox @@ -1 +1 @@ -Subproject commit 7ca5145d40aa906fdc48b0b0e75e80412241be7e +Subproject commit cde8c8ad90aac79d277a1891967be3c1a58e0858 diff --git a/xmake/templates/nim/console/project/src/main b/xmake/templates/nim/console/project/src/main deleted file mode 100755 index 84f0819ac..000000000 Binary files a/xmake/templates/nim/console/project/src/main and /dev/null differ -- cgit v1.3.1 From bef276b8037a1a80972d1332acecb9ff1013f431 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 1 Nov 2021 22:35:01 +0800 Subject: update changelog --- core/src/lua/lua | 2 +- core/src/tbox/tbox | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/lua/lua b/core/src/lua/lua index 75ea9ccbe..eadd8c717 160000 --- a/core/src/lua/lua +++ b/core/src/lua/lua @@ -1 +1 @@ -Subproject commit 75ea9ccbea7c4886f30da147fb67b693b2624c26 +Subproject commit eadd8c7178c79c814ecca9652973a9b9dd4cc71b diff --git a/core/src/tbox/tbox b/core/src/tbox/tbox index cde8c8ad9..7ca5145d4 160000 --- a/core/src/tbox/tbox +++ b/core/src/tbox/tbox @@ -1 +1 @@ -Subproject commit cde8c8ad90aac79d277a1891967be3c1a58e0858 +Subproject commit 7ca5145d40aa906fdc48b0b0e75e80412241be7e -- cgit v1.3.1 From 1c667ecedce4a2f90f32787f7f667f967421ec1f Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 2 Nov 2021 00:39:57 +0800 Subject: improve fpic for gcc --- xmake/modules/core/tools/gcc.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index 224dc6c2d..240ec2855 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -42,7 +42,11 @@ function init(self) self:set("shflags", "-shared") -- add -fPIC for shared - if not is_plat("windows", "mingw") then + -- + -- we need check it for clang/gcc with window target + -- @see https://github.com/xmake-io/xmake/issues/1392 + -- + if not is_plat("windows", "mingw") and self:has_flags("-fPIC", "cxflags") then self:add("shflags", "-fPIC") self:add("shared.cxflags", "-fPIC") end -- cgit v1.3.1 From 57ac15ded63c921ca913dd51adf039af842b8a1b Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 2 Nov 2021 22:38:56 +0800 Subject: improve apt::find_package --- xmake/modules/package/manager/apt/find_package.lua | 63 +++++++++++++++------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/xmake/modules/package/manager/apt/find_package.lua b/xmake/modules/package/manager/apt/find_package.lua index 27a0ebbe1..e2617b4ec 100644 --- a/xmake/modules/package/manager/apt/find_package.lua +++ b/xmake/modules/package/manager/apt/find_package.lua @@ -24,26 +24,8 @@ import("core.project.config") import("core.project.target") import("lib.detect.find_tool") --- find package using the dpkg package manager --- --- @param name the package name --- @param opt the options, e.g. {verbose = true, version = "1.12.0") --- -function main(name, opt) - - -- check - opt = opt or {} - if not is_host(opt.plat) or os.arch() ~= opt.arch then - return - end - - -- find dpkg - local dpkg = find_tool("dpkg") - if not dpkg then - return - end - - -- find package +-- find package +function _find_package(dpkg, name, opt) local result = nil local listinfo = try {function () return os.iorunv(dpkg.program, {"--listfiles", name}) end} if listinfo then @@ -70,6 +52,24 @@ function main(name, opt) end end + -- meta/alias package? e.g. libboost-dev -> libboost1.74-dev + -- @see https://github.com/xmake-io/xmake/issues/1786 + if not result then + local statusinfo = try {function () return os.iorunv(dpkg.program, {"--status", name}) end} + if statusinfo then + for _, line in ipairs(statusinfo:split("\n", {plain = true})) do + -- parse depends, e.g. Depends: libboost1.74-dev + if line:startswith("Depends:") then + local depends = line:sub(9):split("%s+") + if #depends == 1 then + return _find_package(dpkg, depends[1], opt) + end + break + end + end + end + end + -- remove repeat if result then if result.links then @@ -84,3 +84,26 @@ function main(name, opt) end return result end + +-- find package using the dpkg package manager +-- +-- @param name the package name +-- @param opt the options, e.g. {verbose = true, version = "1.12.0") +-- +function main(name, opt) + + -- check + opt = opt or {} + if not is_host(opt.plat) or os.arch() ~= opt.arch then + return + end + + -- find dpkg + local dpkg = find_tool("dpkg") + if not dpkg then + return + end + + -- find package + return _find_package(dpkg, name, opt) +end -- cgit v1.3.1 From f736ff4bcafeec2faf1cc95818d5fb1578b61aa6 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 2 Nov 2021 22:42:36 +0800 Subject: improve system::find_package --- .../package/manager/system/find_package.lua | 95 +++++++++++++++------- 1 file changed, 65 insertions(+), 30 deletions(-) diff --git a/xmake/modules/package/manager/system/find_package.lua b/xmake/modules/package/manager/system/find_package.lua index 692241309..1e0d58c77 100644 --- a/xmake/modules/package/manager/system/find_package.lua +++ b/xmake/modules/package/manager/system/find_package.lua @@ -26,36 +26,8 @@ import("lib.detect.pkgconfig") import("detect.sdks.find_xcode") import("core.project.config") --- find package from the unix-like system directories -function _find_package_from_unixdirs(name, links, opt) - - -- add default search includedirs on pc host - local includedirs = table.wrap(opt.includedirs) - if #includedirs == 0 then - if opt.plat == "linux" or opt.plat == "macosx" then - table.insert(includedirs, "/usr/local/include") - table.insert(includedirs, "/usr/include") - table.insert(includedirs, "/opt/local/include") - table.insert(includedirs, "/opt/include") - end - end - - -- add default search linkdirs on pc host - local linkdirs = table.wrap(opt.linkdirs) - if #linkdirs == 0 then - if opt.plat == "linux" or opt.plat == "macosx" then - table.insert(linkdirs, "/usr/local/lib") - table.insert(linkdirs, "/usr/lib") - table.insert(linkdirs, "/opt/local/lib") - table.insert(linkdirs, "/opt/lib") - if opt.plat == "linux" and opt.arch == "x86_64" then - table.insert(linkdirs, "/usr/local/lib/x86_64-linux-gnu") - table.insert(linkdirs, "/usr/lib/x86_64-linux-gnu") - table.insert(linkdirs, "/usr/lib64") - table.insert(linkdirs, "/opt/lib64") - end - end - end +-- find package +function _find_package(name, links, linkdirs, includedirs, opt) -- find library local result = nil @@ -91,6 +63,68 @@ function _find_package_from_unixdirs(name, links, opt) return result end +-- find package from the environment variables +-- @see https://github.com/xmake-io/xmake/issues/1776 +-- +function _find_package_from_envs(name, links, opt) + + -- add default search includedirs on pc host + local includedirs = table.wrap(opt.includedirs) + if #includedirs == 0 then + if opt.plat == "windows" then + table.insert(includedirs, "$(env INCLUDE)") + else + table.insert(includedirs, "$(env CPATH)") + table.insert(includedirs, "$(env C_INCLUDE_PATH)") + table.insert(includedirs, "$(env CPLUS_INCLUDE_PATH)") + end + end + + -- add default search linkdirs on pc host + local linkdirs = table.wrap(opt.linkdirs) + if #linkdirs == 0 then + if opt.plat == "windows" then + table.insert(linkdirs, "$(env LIB)") + else + table.insert(linkdirs, "$(env LIBRARY_PATH)") + end + end + return _find_package(name, links, linkdirs, includedirs, opt) +end + +-- find package from the unix-like system directories +function _find_package_from_unixdirs(name, links, opt) + + -- add default search includedirs on pc host + local includedirs = table.wrap(opt.includedirs) + if #includedirs == 0 then + if opt.plat == "linux" or opt.plat == "macosx" then + table.insert(includedirs, "/usr/local/include") + table.insert(includedirs, "/usr/include") + table.insert(includedirs, "/opt/local/include") + table.insert(includedirs, "/opt/include") + end + end + + -- add default search linkdirs on pc host + local linkdirs = table.wrap(opt.linkdirs) + if #linkdirs == 0 then + if opt.plat == "linux" or opt.plat == "macosx" then + table.insert(linkdirs, "/usr/local/lib") + table.insert(linkdirs, "/usr/lib") + table.insert(linkdirs, "/opt/local/lib") + table.insert(linkdirs, "/opt/lib") + if opt.plat == "linux" and opt.arch == "x86_64" then + table.insert(linkdirs, "/usr/local/lib/x86_64-linux-gnu") + table.insert(linkdirs, "/usr/lib/x86_64-linux-gnu") + table.insert(linkdirs, "/usr/lib64") + table.insert(linkdirs, "/opt/lib64") + end + end + end + return _find_package(name, links, linkdirs, includedirs, opt) +end + -- find package from the xcode directories function _find_package_from_xcodedirs(name, links, opt) @@ -166,6 +200,7 @@ function main(name, opt) if opt.plat ~= "windows" then table.insert(finders, _find_package_from_unixdirs) end + table.insert(finders, _find_package_from_envs) end if opt.plat == "macosx" or opt.plat == "iphoneos" or opt.plat == "watchos" then table.insert(finders, _find_package_from_xcodedirs) -- cgit v1.3.1 From c208120425331d82c1b363bf94a515b6511c0d71 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 2 Nov 2021 22:43:24 +0800 Subject: update changelog --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f517a47c..77abaa0bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## master (unreleased) +### Changes + +* Switch to Lua5.4 runtime by default +* [#1776](https://github.com/xmake-io/xmake/issues/1776): Improve system::find_package, support to find package from envs +* [#1786](https://github.com/xmake-io/xmake/issues/1786): Improve apt:find_package, support to find alias package + ## v2.5.9 ### New features @@ -1115,6 +1121,12 @@ ## master (开发中) +### 改进 + +* 默认切换到 Lua5.4 运行时 +* [#1776](https://github.com/xmake-io/xmake/issues/1776): 改进 system::find_package,支持从环境变量中查找系统库 +* [#1786](https://github.com/xmake-io/xmake/issues/1786): 改进 apt:find_package,支持查找 alias 包 + ## v2.5.9 ### 新特性 -- cgit v1.3.1 From b500cca33c3c8bb73b275344b5b39dd06366adf3 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 2 Nov 2021 13:57:57 +0800 Subject: Update README.md --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fe3fa6864..4bfd7307e 100644 --- a/README.md +++ b/README.md @@ -60,9 +60,13 @@ Support this project by becoming a sponsor. Your logo will show up here with a l ## Introduction ([中文](/README_zh.md)) -xmake is a lightweight cross-platform build utility based on Lua. It uses xmake.lua to maintain project builds. Compared with makefile/CMakeLists.txt, the configuration syntax is more concise and intuitive. It is very friendly to novices and can quickly get started in a short time. Let users focus more on actual project development. +Xmake is a lightweight cross-platform build utility based on Lua. -It can compile the project directly like Make/Ninja, or generate project files like CMake/Meson, and it also has a built-in package management system to help users solve the integrated use of C/C++ dependent libraries. +It is very lightweight and does not have any dependencies because it has a built-in Lua runtime. + +It uses xmake.lua to maintain project builds and its configuration syntax is very simple and readable. + +We can use it to build project directly like Make/Ninja, or generate project files like CMake/Meson, and it also has a built-in package management system to help users solve the integrated use of C/C++ dependent libraries. ``` Xmake = Build backend + Project Generator + Package Manager -- cgit v1.3.1 From a116fc0875787d332f61e87b703a9a047dffbc39 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 2 Nov 2021 14:01:04 +0800 Subject: Update README_zh.md --- README_zh.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README_zh.md b/README_zh.md index 5fa08e133..05c8b39e6 100644 --- a/README_zh.md +++ b/README_zh.md @@ -60,11 +60,15 @@ ## 简介 -xmake 是一个基于 Lua 的轻量级跨平台构建工具,使用 xmake.lua 维护项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对新手非常友好,短时间内就能快速入门,能够让用户把更多的精力集中在实际的项目开发上。 +Xmake 是一个基于 Lua 的轻量级跨平台构建工具。 -虽然,简单易用是 xmake 的一大特色,但 xmake 的功能也是非常强大的,既能够像 Make/Ninja 那样可以直接编译项目,也可以像 CMake/Meson 那样生成工程文件,还有内置的包管理系统来帮助用户解决 C/C++依赖库的集成使用问题。 +它非常的轻量,没有任何依赖,因为它内置了 Lua 运行时。 -目前,xmake主要用于 C/C++ 项目的构建,但是同时也支持其他native语言的构建,可以实现跟C/C++进行混合编译,同时编译速度也是非常的快,可以跟Ninja持平。 +它使用 xmake.lua 维护项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对新手非常友好,短时间内就能快速入门,能够让用户把更多的精力集中在实际的项目开发上。 + +我们能够使用它像 Make/Ninja 那样可以直接编译项目,也可以像 CMake/Meson 那样生成工程文件,另外它还有内置的包管理系统来帮助用户解决 C/C++ 依赖库的集成使用问题。 + +目前,Xmake 主要用于 C/C++ 项目的构建,但是同时也支持其他 native 语言的构建,可以实现跟 C/C++ 进行混合编译,同时编译速度也是非常的快,可以跟 Ninja 持平。 ``` Xmake = Build backend + Project Generator + Package Manager -- cgit v1.3.1 From ded70c3ac78a8df456d743788f37c328bcf7e570 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 2 Nov 2021 14:02:53 +0800 Subject: Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4bfd7307e..296f1d4b7 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ Support this project by becoming a sponsor. Your logo will show up here with a l Xmake is a lightweight cross-platform build utility based on Lua. -It is very lightweight and does not have any dependencies because it has a built-in Lua runtime. +It is very lightweight and has no dependencies because it has a built-in Lua runtime. It uses xmake.lua to maintain project builds and its configuration syntax is very simple and readable. -- cgit v1.3.1 From 2f85a8bab49296991464812a3c70570561748a98 Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Wed, 3 Nov 2021 22:19:40 +0800 Subject: add find_llvm_as.lua --- xmake/modules/detect/tools/find_llvm_as.lua | 57 +++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 xmake/modules/detect/tools/find_llvm_as.lua diff --git a/xmake/modules/detect/tools/find_llvm_as.lua b/xmake/modules/detect/tools/find_llvm_as.lua new file mode 100644 index 000000000..213f63abf --- /dev/null +++ b/xmake/modules/detect/tools/find_llvm_as.lua @@ -0,0 +1,57 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author xq114 +-- @file find_llvm_as.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find llvm-ar +-- +-- @param opt the argument options, e.g. {version = true, program = "c:\xxx\llvm-as.exe"} +-- +-- @return program, version +-- +-- @code +-- +-- local llvm_as = find_llvm_as() +-- local llvm_as, version = find_llvm_as({version = true}) +-- local llvm_as, version = find_llvm_as({version = true, program = "c:\xxx\llvm-as.exe"}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + opt.check = opt.check or "-version" + opt.command = opt.command or "-version" + + -- find program + local program = find_program(opt.program or "llvm-as", opt) + + -- find program version + local version = nil + if program and opt.version then + version = find_programver(program, opt) + end + + -- ok? + return program, version +end -- cgit v1.3.1 From 66c32d141498f7ae51f7afc6d08848c83e86d88b Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 5 Nov 2021 00:38:22 +0800 Subject: update tbox --- core/src/tbox/tbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/tbox/tbox b/core/src/tbox/tbox index 7ca5145d4..122a479e6 160000 --- a/core/src/tbox/tbox +++ b/core/src/tbox/tbox @@ -1 +1 @@ -Subproject commit 7ca5145d40aa906fdc48b0b0e75e80412241be7e +Subproject commit 122a479e626ee3fdd7d6c1117ec7c19212a1e087 -- cgit v1.3.1 From 4a6eadfbde73cff1f707c48310e5f0535ff7f242 Mon Sep 17 00:00:00 2001 From: Yaozhenghang Ma Date: Fri, 5 Nov 2021 14:45:29 +0800 Subject: update cmake package finding add include dir finding pattern: xxx_CXX_INCLUDEDIRS --- xmake/modules/package/manager/cmake/find_package.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua index c954f024d..085851205 100644 --- a/xmake/modules/package/manager/cmake/find_package.lua +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -72,6 +72,8 @@ function _find_package(cmake, name, opt) name, name, name) cmakefile:print(" target_include_directories(%s PRIVATE ${%s_INCLUDE_DIR} ${%s_INCLUDE_DIRS})", name, name:upper(), name:upper()) + cmakefile:print(" target_include_directories(%s PRIVATE ${%s_CXX_INCLUDE_DIRS})", + name, name) cmakefile:print(" target_link_libraries(%s ${%s_LIBRARY} ${%s_LIBRARIES} ${%s_LIBS})", name, name, name, name) cmakefile:print(" target_link_libraries(%s ${%s_LIBRARY} ${%s_LIBRARIES} ${%s_LIBS})", -- cgit v1.3.1 From e79e2886eb22d78910a6c52c5b9f77c698d5d8b9 Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Fri, 5 Nov 2021 16:02:33 +0800 Subject: improve env scripts to support binding --- scripts/register-virtualenvs.sh | 23 +++++++++++++++- scripts/xrepo.bat | 42 ++++++++++++++++++++++++++++++ scripts/xrepo.ps1 | 16 +++++++++++- xmake/modules/private/xrepo/action/env.lua | 38 +++++++++++++++------------ xmake/scripts/xrepo-hook.psm1 | 42 ++++++++++++++++++++---------- 5 files changed, 129 insertions(+), 32 deletions(-) diff --git a/scripts/register-virtualenvs.sh b/scripts/register-virtualenvs.sh index aa97afec5..8518060f8 100644 --- a/scripts/register-virtualenvs.sh +++ b/scripts/register-virtualenvs.sh @@ -8,7 +8,7 @@ else fi function xrepo { - if [ $# -eq 2 ] && [ "$1" = "env" ]; then + if [ $# -ge 2 ] && [ "$1" = "env" ]; then local cmd="${2-x}" case "$cmd" in shell) @@ -38,6 +38,27 @@ function xrepo { unset XMAKE_ENV_BACKUP fi ;; + -b|--bind) + if [ "$4" = "shell" ]; then + local bnd="${3-x}" + if test "${XMAKE_PROMPT_BACKUP}"; then + PS1="${XMAKE_PROMPT_BACKUP}" + source "${XMAKE_ENV_BACKUP}" || return 1 + unset XMAKE_PROMPT_BACKUP + unset XMAKE_ENV_BACKUP + fi + local prompt="$("$XMAKE_EXE" lua --quiet private.xrepo.action.env.info prompt $bnd)" || return 1 + if [ -z "${prompt+x}" ]; then + return 1 + fi + local activateCommand="$("$XMAKE_EXE" lua --quiet private.xrepo.action.env.info script.bash $bnd)" || return 1 + export XMAKE_ENV_BACKUP="$("$XMAKE_EXE" lua private.xrepo.action.env.info envfile $bnd)" + export XMAKE_PROMPT_BACKUP="${PS1}" + "$XMAKE_EXE" lua --quiet private.xrepo.action.env.info backup.bash $bnd 1>"$XMAKE_ENV_BACKUP" + eval "$activateCommand" + PS1="${prompt} $PS1" + fi + ;; *) "$XMAKE_EXE" lua private.xrepo "$@" ;; diff --git a/scripts/xrepo.bat b/scripts/xrepo.bat index 77acf7d24..82180398a 100755 --- a/scripts/xrepo.bat +++ b/scripts/xrepo.bat @@ -60,6 +60,48 @@ ) goto :ENDXREPO ) + set XREPO_BIND_FLAG= + if [%2]==[-b] if [%4]==[shell] ( + set XREPO_BIND_FLAG=1 + ) + if [%2]==[--bind] if [%4]==[shell] ( + set XREPO_BIND_FLAG=1 + ) + if defined XREPO_BIND_FLAG ( + set XREPO_BIND_FLAG= + if defined XMAKE_PROMPT_BACKUP ( + call %XMAKE_ENV_BACKUP% + setlocal EnableDelayedExpansion + if !errorlevel! neq 0 exit /B !errorlevel! + endlocal + set PROMPT=%XMAKE_PROMPT_BACKUP% + set XMAKE_ENV_BACKUP= + set XMAKE_PROMPT_BACKUP= + echo Please rerun `xrepo env shell` to enter the environment. + exit /B 1 + ) else ( + setlocal EnableDelayedExpansion + @%XMAKE_EXE% lua --quiet private.xrepo.action.env.info prompt %3 1>nul + if !errorlevel! neq 0 ( + echo error: environment not found^^! + exit /B !errorlevel! + ) + endlocal + for /f %%i in ('@%XMAKE_EXE% lua --quiet private.xrepo.action.env.info prompt %3') do @( + @set "PROMPT=%%i %PROMPT%" + ) + @set XMAKE_PROMPT_BACKUP=%PROMPT% + ) + for /f %%i in ('@%XMAKE_EXE% lua private.xrepo.action.env.info envfile %3') do @( + @set "XMAKE_ENV_BACKUP=%%i.bat" + @"%XMAKE_EXE%" lua --quiet private.xrepo.action.env.info backup.cmd %3 1>"%%i.bat" + ) + for /f %%i in ('@%XMAKE_EXE% lua private.xrepo.action.env.info envfile %3') do @( + @"%XMAKE_EXE%" lua --quiet private.xrepo.action.env.info script.cmd %3 1>"%%i.bat" + call "%%i.bat" + ) + goto :ENDXREPO + ) ) @call %XMAKE_EXE% lua private.xrepo %* diff --git a/scripts/xrepo.ps1 b/scripts/xrepo.ps1 index a821d8057..74e5e4682 100644 --- a/scripts/xrepo.ps1 +++ b/scripts/xrepo.ps1 @@ -19,13 +19,27 @@ if ($Args.Count -eq 0) { if ((Test-Path 'Env:XMAKE_PROMPT_MODIFIER') -and ($Env:XMAKE_PROMPT_MODIFIER -ne "")) { Exit-XrepoEnvironment; } - Enter-XrepoEnvironment; + Enter-XrepoEnvironment $Null; return; } "quit" { Exit-XrepoEnvironment; return; } + {$_ -in "-b", "--bind"} { + if (($Args.Count -ge 4) -and ($Args[3] -eq "shell")) { + if (-not (Test-Path 'Env:XMAKE_ROOTDIR')) { + $Env:XMAKE_ROOTDIR = $BASE_DIR; + Import-Module "$Env:XMAKE_ROOTDIR\scripts\xrepo-hook.psm1"; + Add-XrepoEnvironmentToPrompt; + } + if ((Test-Path 'Env:XMAKE_PROMPT_MODIFIER') -and ($Env:XMAKE_PROMPT_MODIFIER -ne "")) { + Exit-XrepoEnvironment; + } + Enter-XrepoEnvironment $Args[2]; + return; + } + } } } diff --git a/xmake/modules/private/xrepo/action/env.lua b/xmake/modules/private/xrepo/action/env.lua index 8590fcab9..18b59c0e6 100644 --- a/xmake/modules/private/xrepo/action/env.lua +++ b/xmake/modules/private/xrepo/action/env.lua @@ -199,8 +199,8 @@ function _get_envsdir() end -- get bound environment or packages -function _get_boundenv() - local bind = option.get("bind") +function _get_boundenv(opt) + local bind = (opt and opt.bind) or option.get("bind") if bind then local envfile = path.join(_get_envsdir(), bind .. ".lua") if envfile and os.isfile(envfile) then @@ -287,9 +287,9 @@ function _toolchain_addenvs(envs) end -- get package environments -function _package_getenvs() +function _package_getenvs(opt) local envs = os.getenvs() - local boundenv = _get_boundenv() + local boundenv = _get_boundenv(opt) local has_envfile = false local packages = nil if boundenv and os.isfile(boundenv) then @@ -341,15 +341,15 @@ function _get_env_script(envs, shell, del) suffix = "\"" elseif shell:endswith("sh") then if del then - prefix = "unset " - connector = "" + prefix = "unset '" + connector = "'" else - prefix = "export " - connector = "='" + prefix = "export '" + connector = "'='" suffix = "'" end end - local exceptions = hashset.of("_", "PS1", "PROMPT") + local exceptions = hashset.of("_", "PS1", "PROMPT", "!;", "!EXITCODE") local ret = "" if del then for name, _ in pairs(envs) do @@ -368,25 +368,31 @@ function _get_env_script(envs, shell, del) end -- get information of current virtual environment -function info(key) +function info(key, bnd) if key == "prompt" then - assert(os.isfile(os.projectfile()), "xmake.lua not found!") - io.write("[" .. path.filename(os.projectdir()) .. "]") + local boundenv = _get_boundenv({bind = bnd}) + if boundenv then + assert(os.isfile(boundenv), "environment not found!") + io.write("[" .. path.basename(boundenv) .. "]") + elseif not bnd then + assert(os.isfile(os.projectfile()), "xmake.lua not found!") + io.write("[" .. path.filename(os.projectdir()) .. "]") + end elseif key == "envfile" then print(os.tmpfile()) elseif key == "config" then - if os.isfile(os.projectfile()) then + if not bnd and os.isfile(os.projectfile()) then task.run("config", {target = "all"}, {disable_dump = true}) end elseif key:startswith("script.") then local shell = key:match("script%.(.+)") - print(_get_env_script(_package_getenvs(), shell, false)) + io.write(_get_env_script(_package_getenvs({bind = bnd}), shell, false)) elseif key:startswith("backup.") then local shell = key:match("backup%.(.+)") -- remove current environment variables first - print(_get_env_script(_package_getenvs(), shell, true)) - print(_get_env_script(os.getenvs(), shell, false)) + io.write(_get_env_script(_package_getenvs({bind = bnd}), shell, true)) + io.write(_get_env_script(os.getenvs(), shell, false)) end end diff --git a/xmake/scripts/xrepo-hook.psm1 b/xmake/scripts/xrepo-hook.psm1 index 53342fba0..2210f10ef 100644 --- a/xmake/scripts/xrepo-hook.psm1 +++ b/xmake/scripts/xrepo-hook.psm1 @@ -10,26 +10,40 @@ #> function Enter-XrepoEnvironment { [CmdletBinding()] - param(); + param( + [string]$bnd + ); begin { $script:xrepoOldEnvs = (Get-ChildItem -Path Env:); - & $Env:XMAKE_EXE lua private.xrepo.action.env.info config; - if (-not $?) { - Exit 1; - } - - $xmakeColorTermBackup, $Env:XMAKE_COLORTERM = $Env:XMAKE_COLORTERM, "nocolor"; - $xrepoPrompt = (& $Env:XMAKE_EXE lua --quiet private.xrepo.action.env.info prompt | Out-String); - $Env:XMAKE_COLORTERM = $xmakeColorTermBackup; - if (-not $xrepoPrompt.StartsWith("[")) { - Write-Host $xrepoPrompt; - Exit 1; + if ($bnd -eq $Null) { + & $Env:XMAKE_EXE lua private.xrepo.action.env.info config; + if (-not $?) { + Exit 1; + } + + $xmakeColorTermBackup, $Env:XMAKE_COLORTERM = $Env:XMAKE_COLORTERM, "nocolor"; + $xrepoPrompt = (& $Env:XMAKE_EXE lua --quiet private.xrepo.action.env.info prompt | Out-String); + $Env:XMAKE_COLORTERM = $xmakeColorTermBackup; + if (-not $xrepoPrompt.StartsWith("[")) { + Write-Host "error: xmake.lua not found!"; + Exit 1; + } + + $activateCommand = (& $Env:XMAKE_EXE lua --quiet private.xrepo.action.env.info script.powershell | Out-String); + } else { + $xmakeColorTermBackup, $Env:XMAKE_COLORTERM = $Env:XMAKE_COLORTERM, "nocolor"; + $xrepoPrompt = (& $Env:XMAKE_EXE lua --quiet private.xrepo.action.env.info prompt $bnd | Out-String); + $Env:XMAKE_COLORTERM = $xmakeColorTermBackup; + if (-not $xrepoPrompt.StartsWith("[")) { + Write-Host "error: invalid environment!"; + Exit 1; + } + + $activateCommand = (& $Env:XMAKE_EXE lua --quiet private.xrepo.action.env.info script.powershell $bnd | Out-String); } - $activateCommand = (& $Env:XMAKE_EXE lua private.xrepo.action.env.info script.powershell | Out-String); - Write-Verbose "[xrepo env script.powershell]`n$activateCommand"; Invoke-Expression -Command $activateCommand; -- cgit v1.3.1 From 95dea5af25edb9f1eda15ad8412342e26ef39525 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 5 Nov 2021 21:08:33 +0800 Subject: Update installer.nsi --- scripts/installer.nsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/installer.nsi b/scripts/installer.nsi index a01b6feea..4c7ea290b 100644 --- a/scripts/installer.nsi +++ b/scripts/installer.nsi @@ -248,7 +248,7 @@ Section "XMake (required)" InstallExeutable WriteRegStr ${RootKey} ${RegUninstall} "NoAdmin" "$NOADMIN" ; Write the uninstall keys for Windows - WriteRegStr ${RootKey} ${RegUninstall} "DisplayName" "XMake build utility" + WriteRegStr ${RootKey} ${RegUninstall} "DisplayName" "XMake build utility (${ARCH})" WriteRegStr ${RootKey} ${RegUninstall} "DisplayIcon" '"$InstDir\xmake.exe"' WriteRegStr ${RootKey} ${RegUninstall} "Comments" "A cross-platform build utility based on Lua" WriteRegStr ${RootKey} ${RegUninstall} "Publisher" "The TBOOX Open Source Group" -- cgit v1.3.1 From 2ed6222d854d03441d24314595cae550b4b842e0 Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Sat, 6 Nov 2021 15:30:38 +0800 Subject: improve env config --- scripts/register-virtualenvs.sh | 1 + scripts/xrepo.bat | 4 ++++ xmake/modules/private/xrepo/action/env.lua | 8 +++++++- xmake/scripts/xrepo-hook.psm1 | 5 +++++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/scripts/register-virtualenvs.sh b/scripts/register-virtualenvs.sh index 8518060f8..cf067d040 100644 --- a/scripts/register-virtualenvs.sh +++ b/scripts/register-virtualenvs.sh @@ -47,6 +47,7 @@ function xrepo { unset XMAKE_PROMPT_BACKUP unset XMAKE_ENV_BACKUP fi + "$XMAKE_EXE" lua private.xrepo.action.env.info config $bnd || return 1 local prompt="$("$XMAKE_EXE" lua --quiet private.xrepo.action.env.info prompt $bnd)" || return 1 if [ -z "${prompt+x}" ]; then return 1 diff --git a/scripts/xrepo.bat b/scripts/xrepo.bat index 82180398a..0416d4a10 100755 --- a/scripts/xrepo.bat +++ b/scripts/xrepo.bat @@ -81,6 +81,10 @@ exit /B 1 ) else ( setlocal EnableDelayedExpansion + %XMAKE_EXE% lua private.xrepo.action.env.info config %3 + if !errorlevel! neq 0 ( + exit /B !errorlevel! + ) @%XMAKE_EXE% lua --quiet private.xrepo.action.env.info prompt %3 1>nul if !errorlevel! neq 0 ( echo error: environment not found^^! diff --git a/xmake/modules/private/xrepo/action/env.lua b/xmake/modules/private/xrepo/action/env.lua index 18b59c0e6..07709b7bd 100644 --- a/xmake/modules/private/xrepo/action/env.lua +++ b/xmake/modules/private/xrepo/action/env.lua @@ -381,7 +381,13 @@ function info(key, bnd) elseif key == "envfile" then print(os.tmpfile()) elseif key == "config" then - if not bnd and os.isfile(os.projectfile()) then + local boundenv = _get_boundenv({bind = bnd}) + local has_envfile = (boundenv and os.isfile(boundenv)) and true or false + if has_envfile or os.isfile(os.projectfile()) then + if has_envfile then + _enter_project({enteronly = true}) + table.insert(project.rcfiles(), boundenv) + end task.run("config", {target = "all"}, {disable_dump = true}) end elseif key:startswith("script.") then diff --git a/xmake/scripts/xrepo-hook.psm1 b/xmake/scripts/xrepo-hook.psm1 index 2210f10ef..2a2c24c05 100644 --- a/xmake/scripts/xrepo-hook.psm1 +++ b/xmake/scripts/xrepo-hook.psm1 @@ -33,6 +33,11 @@ function Enter-XrepoEnvironment { $activateCommand = (& $Env:XMAKE_EXE lua --quiet private.xrepo.action.env.info script.powershell | Out-String); } else { + & $Env:XMAKE_EXE lua private.xrepo.action.env.info config $bnd; + if (-not $?) { + Exit 1; + } + $xmakeColorTermBackup, $Env:XMAKE_COLORTERM = $Env:XMAKE_COLORTERM, "nocolor"; $xrepoPrompt = (& $Env:XMAKE_EXE lua --quiet private.xrepo.action.env.info prompt $bnd | Out-String); $Env:XMAKE_COLORTERM = $xmakeColorTermBackup; -- cgit v1.3.1 From b7adc419e76eef4604f778b86732469a4e9c0471 Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Sat, 6 Nov 2021 16:11:10 +0800 Subject: update load.lua --- xmake/toolchains/msvc/load.lua | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/xmake/toolchains/msvc/load.lua b/xmake/toolchains/msvc/load.lua index b6b9175f0..f6547fed0 100644 --- a/xmake/toolchains/msvc/load.lua +++ b/xmake/toolchains/msvc/load.lua @@ -60,9 +60,28 @@ function main(toolchain) _add_vsenv(toolchain, "LIB") _add_vsenv(toolchain, "INCLUDE") _add_vsenv(toolchain, "LIBPATH") - -- find_rc.lua need them _add_vsenv(toolchain, "WindowsSdkDir") _add_vsenv(toolchain, "WindowsSDKVersion") + _add_vsenv(toolchain, "WindowsSdkBinPath") + _add_vsenv(toolchain, "WindowsSDKLibVersion") + _add_vsenv(toolchain, "WindowsSdkVerBinPath") + _add_vsenv(toolchain, "DevEnvDir") + _add_vsenv(toolchain, "ExtensionSdkDir") + _add_vsenv(toolchain, "VCIDEInstallDir") + _add_vsenv(toolchain, "VCINSTALLDIR") + _add_vsenv(toolchain, "VCToolsInstallDir") + _add_vsenv(toolchain, "VCToolsRedistDir") + _add_vsenv(toolchain, "VCToolsVersion") + _add_vsenv(toolchain, "VisualStudioVersion") + _add_vsenv(toolchain, "VSINSTALLDIR") + _add_vsenv(toolchain, "VSCMD_VER") + _add_vsenv(toolchain, "VSCMD_ARG_app_plat") + _add_vsenv(toolchain, "VSCMD_ARG_HOST_ARCH") + _add_vsenv(toolchain, "VSCMD_ARG_TGT_ARCH") + _add_vsenv(toolchain, "VS140COMNTOOLS") + _add_vsenv(toolchain, "VS150COMNTOOLS") + _add_vsenv(toolchain, "VS160COMNTOOLS") + _add_vsenv(toolchain, "VS170COMNTOOLS") -- add some default flags toolchain:add("cl.cxxflags", "/EHsc") -- cgit v1.3.1 From 6bbb5f94c3beadf5d5dfc6db59d05a686647a39b Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Sat, 6 Nov 2021 18:55:28 +0800 Subject: improve find_vstudio.lua as well --- xmake/modules/detect/sdks/find_vstudio.lua | 100 ++++++++++++++++++----------- xmake/toolchains/msvc/load.lua | 35 +++------- 2 files changed, 70 insertions(+), 65 deletions(-) diff --git a/xmake/modules/detect/sdks/find_vstudio.lua b/xmake/modules/detect/sdks/find_vstudio.lua index 2934d23c8..0abbb131c 100644 --- a/xmake/modules/detect/sdks/find_vstudio.lua +++ b/xmake/modules/detect/sdks/find_vstudio.lua @@ -28,15 +28,72 @@ local vcvars = {"path", "libpath", "include", "DevEnvdir", - "VSInstallDir", - "VCInstallDir", + "VSINSTALLDIR", + "VCINSTALLDIR", "WindowsSdkDir", "WindowsLibPath", "WindowsSDKVersion", "WindowsSdkBinPath", + "WindowsSdkVerBinPath", + "ExtensionSdkDir", "UniversalCRTSdkDir", "UCRTVersion", - "VCToolsVersion"} + "VCToolsVersion", + "VCIDEInstallDir", + "VCToolsInstallDir", + "VCToolsRedistDir", + "VisualStudioVersion", + "VSCMD_VER", + "VSCMD_ARG_app_plat", + "VSCMD_ARG_HOST_ARCH", + "VSCMD_ARG_TGT_ARCH"} + +-- init vsvers +local vsvers = +{ + ["17.0"] = "2022" +, ["16.0"] = "2019" +, ["15.0"] = "2017" +, ["14.0"] = "2015" +, ["12.0"] = "2013" +, ["11.0"] = "2012" +, ["10.0"] = "2010" +, ["9.0"] = "2008" +, ["8.0"] = "2005" +, ["7.1"] = "2003" +, ["7.0"] = "7.0" +, ["6.0"] = "6.0" +, ["5.0"] = "5.0" +, ["4.2"] = "4.2" +} + +-- init vsenvs +local vsenvs = +{ + ["17.0"] = "VS170COMNTOOLS" +, ["16.0"] = "VS160COMNTOOLS" +, ["15.0"] = "VS150COMNTOOLS" +, ["14.0"] = "VS140COMNTOOLS" +, ["12.0"] = "VS120COMNTOOLS" +, ["11.0"] = "VS110COMNTOOLS" +, ["10.0"] = "VS100COMNTOOLS" +, ["9.0"] = "VS90COMNTOOLS" +, ["8.0"] = "VS80COMNTOOLS" +, ["7.1"] = "VS71COMNTOOLS" +, ["7.0"] = "VS70COMNTOOLS" +, ["6.0"] = "VS60COMNTOOLS" +, ["5.0"] = "VS50COMNTOOLS" +, ["4.2"] = "VS42COMNTOOLS" +} + +-- get all known Visual Studio environment variables +function get_vcvars() + local realvcvars = vcvars + for _, v in pairs(vsenvs) do + table.insert(realvcvars, v) + end + return realvcvars +end -- load vcvarsall environment variables function _load_vcvarsall(vcvarsall, vsver, arch, opt) @@ -59,7 +116,7 @@ function _load_vcvarsall(vcvarsall, vsver, arch, opt) else file:print("call \"%s\" %s %s > nul", vcvarsall, arch, opt.sdkver and opt.sdkver or "") end - for idx, var in ipairs(vcvars) do + for idx, var in ipairs(get_vcvars()) do file:print("echo " .. var .. " = %%" .. var .. "%%") end file:close() @@ -148,41 +205,6 @@ function main(opt) return end - -- init vsvers - local vsvers = - { - ["17.0"] = "2022" - , ["16.0"] = "2019" - , ["15.0"] = "2017" - , ["14.0"] = "2015" - , ["12.0"] = "2013" - , ["11.0"] = "2012" - , ["10.0"] = "2010" - , ["9.0"] = "2008" - , ["8.0"] = "2005" - , ["7.1"] = "2003" - , ["7.0"] = "7.0" - , ["6.0"] = "6.0" - , ["5.0"] = "5.0" - , ["4.2"] = "4.2" - } - - -- init vsenvs - local vsenvs = - { - ["14.0"] = "VS140COMNTOOLS" - , ["12.0"] = "VS120COMNTOOLS" - , ["11.0"] = "VS110COMNTOOLS" - , ["10.0"] = "VS100COMNTOOLS" - , ["9.0"] = "VS90COMNTOOLS" - , ["8.0"] = "VS80COMNTOOLS" - , ["7.1"] = "VS71COMNTOOLS" - , ["7.0"] = "VS70COMNTOOLS" - , ["6.0"] = "VS60COMNTOOLS" - , ["5.0"] = "VS50COMNTOOLS" - , ["4.2"] = "VS42COMNTOOLS" - } - -- init options opt = opt or {} diff --git a/xmake/toolchains/msvc/load.lua b/xmake/toolchains/msvc/load.lua index f6547fed0..ee61b46ab 100644 --- a/xmake/toolchains/msvc/load.lua +++ b/xmake/toolchains/msvc/load.lua @@ -56,32 +56,15 @@ function main(toolchain) toolchain:set("toolset", "ar", "link.exe") -- add vs environments - _add_vsenv(toolchain, "PATH") - _add_vsenv(toolchain, "LIB") - _add_vsenv(toolchain, "INCLUDE") - _add_vsenv(toolchain, "LIBPATH") - _add_vsenv(toolchain, "WindowsSdkDir") - _add_vsenv(toolchain, "WindowsSDKVersion") - _add_vsenv(toolchain, "WindowsSdkBinPath") - _add_vsenv(toolchain, "WindowsSDKLibVersion") - _add_vsenv(toolchain, "WindowsSdkVerBinPath") - _add_vsenv(toolchain, "DevEnvDir") - _add_vsenv(toolchain, "ExtensionSdkDir") - _add_vsenv(toolchain, "VCIDEInstallDir") - _add_vsenv(toolchain, "VCINSTALLDIR") - _add_vsenv(toolchain, "VCToolsInstallDir") - _add_vsenv(toolchain, "VCToolsRedistDir") - _add_vsenv(toolchain, "VCToolsVersion") - _add_vsenv(toolchain, "VisualStudioVersion") - _add_vsenv(toolchain, "VSINSTALLDIR") - _add_vsenv(toolchain, "VSCMD_VER") - _add_vsenv(toolchain, "VSCMD_ARG_app_plat") - _add_vsenv(toolchain, "VSCMD_ARG_HOST_ARCH") - _add_vsenv(toolchain, "VSCMD_ARG_TGT_ARCH") - _add_vsenv(toolchain, "VS140COMNTOOLS") - _add_vsenv(toolchain, "VS150COMNTOOLS") - _add_vsenv(toolchain, "VS160COMNTOOLS") - _add_vsenv(toolchain, "VS170COMNTOOLS") + local expect_vars = {"PATH", "LIB", "INCLUDE", "LIBPATH"} + for _, name in ipairs(expect_vars) do + _add_vsenv(toolchain, name) + end + for _, name in ipairs(find_vstudio.get_vcvars()) do + if not table.contains(expect_vars, name:upper()) then + _add_vsenv(toolchain, name) + end + end -- add some default flags toolchain:add("cl.cxxflags", "/EHsc") -- cgit v1.3.1 From 1e4cbd0ad277904bf86366dfba44c965fc640f73 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 6 Nov 2021 21:41:57 +0800 Subject: add pkgconf --- tests/test_utils/test_build.lua | 2 +- xmake/modules/detect/tools/find_pkg_config.lua | 2 - xmake/modules/detect/tools/find_pkgconf.lua | 52 ++++++++++++++++++++++ xmake/modules/lib/detect/pkgconfig.lua | 16 +++++-- .../action/install/pkgconfig_importfiles.lua | 4 +- 5 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 xmake/modules/detect/tools/find_pkgconf.lua diff --git a/tests/test_utils/test_build.lua b/tests/test_utils/test_build.lua index 2a42e67d8..c08e80dc5 100644 --- a/tests/test_utils/test_build.lua +++ b/tests/test_utils/test_build.lua @@ -9,7 +9,7 @@ function test_build:build(argv) os.exec("xmake g -c") -- generic? - os.exec("xmake f -c -D -y") + os.exec("xmake f -c -vD -y") os.exec("xmake") os.exec("xmake p -D") if not is_host("windows") then diff --git a/xmake/modules/detect/tools/find_pkg_config.lua b/xmake/modules/detect/tools/find_pkg_config.lua index 00698d2cc..0dc83454a 100644 --- a/xmake/modules/detect/tools/find_pkg_config.lua +++ b/xmake/modules/detect/tools/find_pkg_config.lua @@ -48,7 +48,5 @@ function main(opt) if program and opt and opt.version then version = find_programver(program, opt) end - - -- ok? return program, version end diff --git a/xmake/modules/detect/tools/find_pkgconf.lua b/xmake/modules/detect/tools/find_pkgconf.lua new file mode 100644 index 000000000..563989268 --- /dev/null +++ b/xmake/modules/detect/tools/find_pkgconf.lua @@ -0,0 +1,52 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_pkgconf.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find pkgconf +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local pkgconf = find_pkgconf() +-- local pkgconf, version = find_pkgconf({version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "pkgconf", opt) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, opt) + end + return program, version +end diff --git a/xmake/modules/lib/detect/pkgconfig.lua b/xmake/modules/lib/detect/pkgconfig.lua index 57726bae0..cf6b6d97d 100644 --- a/xmake/modules/lib/detect/pkgconfig.lua +++ b/xmake/modules/lib/detect/pkgconfig.lua @@ -24,7 +24,15 @@ import("core.project.target") import("core.project.config") import("lib.detect.find_file") import("lib.detect.find_library") -import("detect.tools.find_pkg_config") +import("lib.detect.find_tool") + +-- get pkgconfig +function _get_pkgconfig() + local pkgconfig = find_tool("pkg-config") or find_tool("pkgconf") + if pkgconfig then + return pkgconfig.program + end +end -- get version -- @@ -34,7 +42,7 @@ import("detect.tools.find_pkg_config") function version(name, opt) -- attempt to add search paths from pkg-config - local pkgconfig = find_pkg_config() + local pkgconfig = _get_pkgconfig() if not pkgconfig then return end @@ -73,7 +81,7 @@ end function variables(name, variables, opt) -- attempt to add search paths from pkg-config - local pkgconfig = find_pkg_config() + local pkgconfig = _get_pkgconfig() if not pkgconfig then return end @@ -125,7 +133,7 @@ end function libinfo(name, opt) -- attempt to add search paths from pkg-config - local pkgconfig = find_pkg_config() + local pkgconfig = _get_pkgconfig() if not pkgconfig then return end diff --git a/xmake/modules/target/action/install/pkgconfig_importfiles.lua b/xmake/modules/target/action/install/pkgconfig_importfiles.lua index 820d7ef54..6954a1bb5 100644 --- a/xmake/modules/target/action/install/pkgconfig_importfiles.lua +++ b/xmake/modules/target/action/install/pkgconfig_importfiles.lua @@ -24,10 +24,8 @@ function main(target, opt) -- check opt = opt or {} assert(target:is_library(), 'pkgconfig_importfiles: only support for library target(%s)!', target:name()) - - -- only for unix platform local installdir = target:installdir() - if target:is_plat("windows") or not installdir then + if not installdir then return end -- cgit v1.3.1 From f99e03f31339461d56b00056986bc893aebee057 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 6 Nov 2021 21:46:23 +0800 Subject: revert test_build --- tests/test_utils/test_build.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_utils/test_build.lua b/tests/test_utils/test_build.lua index c08e80dc5..2a42e67d8 100644 --- a/tests/test_utils/test_build.lua +++ b/tests/test_utils/test_build.lua @@ -9,7 +9,7 @@ function test_build:build(argv) os.exec("xmake g -c") -- generic? - os.exec("xmake f -c -vD -y") + os.exec("xmake f -c -D -y") os.exec("xmake") os.exec("xmake p -D") if not is_host("windows") then -- cgit v1.3.1 From c4a60cd9ec943182e4ec0258d5f9330c162181a2 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 7 Nov 2021 23:23:02 +0800 Subject: Update main.lua --- xmake/actions/package/local/main.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/xmake/actions/package/local/main.lua b/xmake/actions/package/local/main.lua index dd7be7de0..03b2ed1ca 100644 --- a/xmake/actions/package/local/main.lua +++ b/xmake/actions/package/local/main.lua @@ -155,6 +155,8 @@ function _package_library(target) end file:print("") file:print([[ + add_configs("shared", {description = "Build shared library.", default = %s, type = "boolean", readonly = true}) + on_load(function (package) package:set("installdir", path.join(os.scriptdir(), package:plat(), package:arch(), package:mode())) end) @@ -164,8 +166,11 @@ function _package_library(target) result.links = "%s" result.linkdirs = package:installdir("lib") result.includedirs = package:installdir("include") + result.libfiles = path.join(package:installdir("%s"), "%s") return result - end)]], target:linkname(), + end)]], target:is_shared() and "true" or "false", + target:linkname(), + (target:is_shared() and target:is_plat("windows", "mingw")) and "bin" or "lib", path.filename(targetfile)) file:close() end -- cgit v1.3.1 From e8275027282796ec9e79f24f18e8ae87ed946209 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 7 Nov 2021 23:35:30 +0800 Subject: Update main.lua --- xmake/actions/package/local/main.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/actions/package/local/main.lua b/xmake/actions/package/local/main.lua index 03b2ed1ca..1a3a0a190 100644 --- a/xmake/actions/package/local/main.lua +++ b/xmake/actions/package/local/main.lua @@ -163,14 +163,14 @@ function _package_library(target) on_fetch(function (package) local result = {} + local libfiledir = (package:config("shared") and package:is_plat("windows", "mingw")) and "bin" or "lib" result.links = "%s" result.linkdirs = package:installdir("lib") result.includedirs = package:installdir("include") - result.libfiles = path.join(package:installdir("%s"), "%s") + result.libfiles = path.join(package:installdir(libfiledir), "%s") return result end)]], target:is_shared() and "true" or "false", target:linkname(), - (target:is_shared() and target:is_plat("windows", "mingw")) and "bin" or "lib", path.filename(targetfile)) file:close() end -- cgit v1.3.1 From 96d398228e9ae045973af9c656a09c7376f9582c Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Nov 2021 23:00:00 +0800 Subject: fix sv --- core/src/sv/sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/sv/sv b/core/src/sv/sv index 9a3cf7c8e..035262773 160000 --- a/core/src/sv/sv +++ b/core/src/sv/sv @@ -1 +1 @@ -Subproject commit 9a3cf7c8e589de4f70378824329882c4a047fffc +Subproject commit 035262773da0500367cb88e6f30197908159a348 -- cgit v1.3.1 From 135638f4b805517e182015a1722f355f43b4eea5 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Nov 2021 23:00:11 +0800 Subject: update spec --- scripts/rpmbuild/SPECS/xmake.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/rpmbuild/SPECS/xmake.spec b/scripts/rpmbuild/SPECS/xmake.spec index 5540c4e76..e8eee1e75 100644 --- a/scripts/rpmbuild/SPECS/xmake.spec +++ b/scripts/rpmbuild/SPECS/xmake.spec @@ -1,6 +1,6 @@ -%define xmake_revision b41c432c85d82d7e7c5503635b1d04820c6fb783 +%define xmake_revision 96d398228e9ae045973af9c656a09c7376f9582c %define tbox_revision 7ca5145d40aa906fdc48b0b0e75e80412241be7e -%define sv_revision 9a3cf7c8e589de4f70378824329882c4a047fffc +%define sv_revision 035262773da0500367cb88e6f30197908159a348 %define lua_cjson_revision 515bab6d6d80b164b94db73af69609ea02f3a798 %define luajit_revision e9af1abec542e6f9851ff2368e7f196b6382a44c %define lua_revision eadd8c7178c79c814ecca9652973a9b9dd4cc71b -- cgit v1.3.1 From 7862d3f7c88f9afe1898b8447854754614094bc3 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Nov 2021 23:01:26 +0800 Subject: update changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77abaa0bd..301fca4ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ * [#1776](https://github.com/xmake-io/xmake/issues/1776): Improve system::find_package, support to find package from envs * [#1786](https://github.com/xmake-io/xmake/issues/1786): Improve apt:find_package, support to find alias package +### Bugs Fixed + +* Fix semver to parse build string with zero prefix + ## v2.5.9 ### New features @@ -1127,6 +1131,10 @@ * [#1776](https://github.com/xmake-io/xmake/issues/1776): 改进 system::find_package,支持从环境变量中查找系统库 * [#1786](https://github.com/xmake-io/xmake/issues/1786): 改进 apt:find_package,支持查找 alias 包 +### Bugs 修复 + +* 修复语义版本中解析带有 0 前缀的 build 字符串问题 + ## v2.5.9 ### 新特性 -- cgit v1.3.1 From 97f278eff5579ceef47ff86ad028746ff0713153 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Nov 2021 15:07:07 +0800 Subject: Update find_package.lua --- xmake/modules/package/manager/brew/find_package.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xmake/modules/package/manager/brew/find_package.lua b/xmake/modules/package/manager/brew/find_package.lua index d5f679f7a..9706bfd8e 100644 --- a/xmake/modules/package/manager/brew/find_package.lua +++ b/xmake/modules/package/manager/brew/find_package.lua @@ -67,14 +67,16 @@ function main(name, opt) -- find package from pkg-config/*.pc, attempt to find it from `brew --prefix`/package first local result = nil - local pcfile = find_file(pcname .. ".pc", path.join(brew_pkg_rootdir, nameinfo[1], "*/lib/pkgconfig")) + local pcfile = find_file(pcname .. ".pc", path.join(brew_pkg_rootdir, nameinfo[1], "*/lib/pkgconfig")) or + find_file(pcname .. ".pc", path.join(brew_pkg_rootdir, nameinfo[1], "*/share/pkgconfig")) if not pcfile then -- attempt to find it from `brew --prefix package` local brew = find_tool("brew") local brew_pkgdir = brew and try {function () return os.iorunv(brew.program, {"--prefix", nameinfo[1]}) end} if brew_pkgdir then brew_pkgdir = brew_pkgdir:trim() - pcfile = find_file(pcname .. ".pc", path.join(brew_pkgdir, "lib/pkgconfig")) + pcfile = find_file(pcname .. ".pc", path.join(brew_pkgdir, "lib/pkgconfig")) or + find_file(pcname .. ".pc", path.join(brew_pkgdir, "share/pkgconfig")) end end if pcfile then -- cgit v1.3.1 From 97ae2e38c5394903b0ed41ac6b5ba080963a4907 Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Mon, 8 Nov 2021 18:32:42 +0800 Subject: fix a bug with venv on unix --- scripts/register-virtualenvs.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/register-virtualenvs.sh b/scripts/register-virtualenvs.sh index cf067d040..6b0c25160 100644 --- a/scripts/register-virtualenvs.sh +++ b/scripts/register-virtualenvs.sh @@ -58,6 +58,8 @@ function xrepo { "$XMAKE_EXE" lua --quiet private.xrepo.action.env.info backup.bash $bnd 1>"$XMAKE_ENV_BACKUP" eval "$activateCommand" PS1="${prompt} $PS1" + else + "$XMAKE_EXE" lua private.xrepo "$@" fi ;; *) -- cgit v1.3.1 From dd91627cc9baf3a1376b617c76358f7ce99ba2cd Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Nov 2021 21:01:49 +0800 Subject: Update cmakelists.lua --- xmake/plugins/project/cmake/cmakelists.lua | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 3223f1c9f..12bc5306c 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -162,6 +162,18 @@ function _add_target_sources(cmakelists, target) cmakelists:print(")") end +-- add target precompilied header +function _add_target_precompiled_header(cmakelists, target) + local precompiled_header = target:get("pcheader") or target:get("pcxxheader") + if precompiled_header then + cmakelists:print("target_precompile_headers(%s PRIVATE", target:name()) + cmakelists:print(" $<$:${CMAKE_CURRENT_SOURCE_DIR}/%s>", + target:get("pcxxheader") and "CXX" or "C", + _get_unix_path(precompiled_header)) + cmakelists:print(")") + end +end + -- add target include directories function _add_target_include_directories(cmakelists, target) local includedirs = _get_configs_from_target(target, "includedirs") @@ -656,6 +668,9 @@ function _add_target(cmakelists, target) -- add target dependencies _add_target_dependencies(cmakelists, target) + -- add target precompilied header + _add_target_precompiled_header(cmakelists, target) + -- add target include directories _add_target_include_directories(cmakelists, target) -- cgit v1.3.1 From f0d88dbc6bf6b06724edf942488a8e21050c9484 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Nov 2021 21:04:35 +0800 Subject: Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 301fca4ac..1dd967e01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Switch to Lua5.4 runtime by default * [#1776](https://github.com/xmake-io/xmake/issues/1776): Improve system::find_package, support to find package from envs * [#1786](https://github.com/xmake-io/xmake/issues/1786): Improve apt:find_package, support to find alias package +* [#1819](https://github.com/xmake-io/xmake/issues/1819): Add precompiled header to cmake generator ### Bugs Fixed @@ -1130,6 +1131,7 @@ * 默认切换到 Lua5.4 运行时 * [#1776](https://github.com/xmake-io/xmake/issues/1776): 改进 system::find_package,支持从环境变量中查找系统库 * [#1786](https://github.com/xmake-io/xmake/issues/1786): 改进 apt:find_package,支持查找 alias 包 +* [#1819](https://github.com/xmake-io/xmake/issues/1819): 添加预编译头到 cmake 生成器 ### Bugs 修复 -- cgit v1.3.1 From 0a17c9c9d9143dfa4281efb13b0f550533d96a18 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 10 Nov 2021 00:21:29 +0800 Subject: support std for c++ modules/msvc --- core/src/xmake/engine.c | 2 + core/src/xmake/makefile | 3 +- core/src/xmake/winos/short_path.c | 79 ++++++++++++++++++++++++++ tests/projects/c++/modules/hello/src/main.cpp | 2 +- xmake/core/sandbox/modules/winos.lua | 9 +++ xmake/modules/detect/sdks/find_vstudio.lua | 4 +- xmake/rules/c++/modules/build_modules/msvc.lua | 25 ++++++++ 7 files changed, 120 insertions(+), 4 deletions(-) create mode 100644 core/src/xmake/winos/short_path.c diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index 34ed7a196..53ec0d1d0 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -187,6 +187,7 @@ tb_int_t xm_winos_logical_drives(lua_State* lua); tb_int_t xm_winos_registry_query(lua_State* lua); tb_int_t xm_winos_registry_keys(lua_State* lua); tb_int_t xm_winos_registry_values(lua_State* lua); +tb_int_t xm_winos_short_path(lua_State* lua); #endif // the string functions @@ -301,6 +302,7 @@ static luaL_Reg const g_winos_functions[] = , { "registry_query", xm_winos_registry_query } , { "registry_keys", xm_winos_registry_keys } , { "registry_values", xm_winos_registry_values } +, { "short_path", xm_winos_short_path } , { tb_null, tb_null } }; #endif diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index f45d834e2..9e0a3decb 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -145,7 +145,8 @@ xmake_C_FILES += \ winos/logical_drives \ winos/registry_keys \ winos/registry_values \ - winos/registry_query + winos/registry_query \ + winos/short_path endif # flags diff --git a/core/src/xmake/winos/short_path.c b/core/src/xmake/winos/short_path.c new file mode 100644 index 000000000..040b33209 --- /dev/null +++ b/core/src/xmake/winos/short_path.c @@ -0,0 +1,79 @@ +/*!A cross-platform build utility based on Lua + * + * 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 + * + * http://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. + * + * Copyright (C) 2015-present, TBOOX Open Source Group. + * + * @author ruki + * @file short_path.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "short_path" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ + +/* get windows short path from long path + * + * local short_path, errors = winos.short_path(long_path) + */ +tb_int_t xm_winos_short_path(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + // get the arguments + tb_char_t const* long_path = luaL_checkstring(lua, 1); + tb_check_return_val(long_path, 0); + + // convert long path to wide characters + tb_wchar_t long_path_w[TB_PATH_MAXN]; + if (tb_atow(long_path_w, long_path, TB_PATH_MAXN) == (tb_size_t)-1) + { + lua_pushnil(lua); + lua_pushfstring(lua, "invalid long path: %s", long_path); + return 2; + } + + // get short path + tb_wchar_t short_path_w[TB_PATH_MAXN]; + if (GetShortPathNameW(long_path_w, short_path_w, TB_PATH_MAXN) == 0) + { + lua_pushnil(lua); + lua_pushfstring(lua, "cannot get short path from: %s", long_path); + return 2; + } + + // return result + tb_char_t* short_path_a = (tb_char_t*)long_path_w; + tb_size_t short_path_n = tb_wtoa(short_path_a, short_path_w, TB_PATH_MAXN); + if (short_path_n == (tb_size_t)-1) + { + lua_pushnil(lua); + lua_pushfstring(lua, "invalid short path from %s!", long_path); + return 2; + } + lua_pushlstring(lua, short_path_a, short_path_n); + return 1; +} diff --git a/tests/projects/c++/modules/hello/src/main.cpp b/tests/projects/c++/modules/hello/src/main.cpp index 175b4d348..1e5cc698f 100644 --- a/tests/projects/c++/modules/hello/src/main.cpp +++ b/tests/projects/c++/modules/hello/src/main.cpp @@ -3,4 +3,4 @@ import hello; int main() { hello::say("hello module!"); return 0; -} \ No newline at end of file +} diff --git a/xmake/core/sandbox/modules/winos.lua b/xmake/core/sandbox/modules/winos.lua index 0a0192470..6bc5ce0c4 100644 --- a/xmake/core/sandbox/modules/winos.lua +++ b/xmake/core/sandbox/modules/winos.lua @@ -70,6 +70,15 @@ function sandbox_winos.registry_values(keypath) return values end +-- get short path +function sandbox_winos.short_path(long_path) + local short_path, errors = winos.short_path(long_path) + if not short_path then + raise(errors) + end + return short_path +end + -- return module return sandbox_winos diff --git a/xmake/modules/detect/sdks/find_vstudio.lua b/xmake/modules/detect/sdks/find_vstudio.lua index 0abbb131c..0d3d98f2c 100644 --- a/xmake/modules/detect/sdks/find_vstudio.lua +++ b/xmake/modules/detect/sdks/find_vstudio.lua @@ -28,8 +28,8 @@ local vcvars = {"path", "libpath", "include", "DevEnvdir", - "VSINSTALLDIR", - "VCINSTALLDIR", + "VSInstallDir", + "VCInstallDir", "WindowsSdkDir", "WindowsLibPath", "WindowsSDKVersion", diff --git a/xmake/rules/c++/modules/build_modules/msvc.lua b/xmake/rules/c++/modules/build_modules/msvc.lua index 831b5cd88..8b28d68f6 100644 --- a/xmake/rules/c++/modules/build_modules/msvc.lua +++ b/xmake/rules/c++/modules/build_modules/msvc.lua @@ -37,7 +37,9 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) -- get output flag local cachedir local outputflag + local hasifc = false if compinst:has_flags("/ifcOutput") then + hasifc = true outputflag = "/ifcOutput" cachedir = path.join(target:autogendir(), "rules", "modules", "cache") if not os.isdir(cachedir) then @@ -66,6 +68,15 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) end assert(referenceflag, "compiler(msvc): does not support c++ module!") + -- get stdifcdir flag + local stdifcdirflag + if compinst:has_flags("/stdIfcDir") then + stdifcdirflag = "/stdIfcDir" + elseif compinst:has_flags("/module:stdIfcDir") then + stdifcdirflag = "/module:stdIfcDir" + end + assert(stdifcdirflag, "compiler(msvc): does not support c++ module!") + -- we need patch objectfiles to sourcebatch for linking module objects local modulefiles = {} sourcebatch.sourcekind = "cxx" @@ -116,6 +127,20 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) if cachedir then target:add("cxxflags", "/ifcSearchDir " .. os.args(cachedir)) end + if stdifcdirflag then + for _, toolchain_inst in ipairs(target:toolchains()) do + if toolchain_inst:name() == "msvc" then + local vcvars = toolchain_inst:config("vcvars") + if vcvars.VCInstallDir and vcvars.VCToolsVersion then + local stdifcdir = path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "ifc", target:is_arch("x64") and "x64" or "x86") + if os.isdir(stdifcdir) then + target:add("cxxflags", stdifcdirflag .. " " .. winos.short_path(stdifcdir)) + end + end + break + end + end + end -- build batchjobs local rootjob = opt.rootjob -- cgit v1.3.1 From e99fa03712fb749bd1e689b3df63b98daa1210cc Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 10 Nov 2021 00:24:14 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dd967e01..432e5fb03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * [#1776](https://github.com/xmake-io/xmake/issues/1776): Improve system::find_package, support to find package from envs * [#1786](https://github.com/xmake-io/xmake/issues/1786): Improve apt:find_package, support to find alias package * [#1819](https://github.com/xmake-io/xmake/issues/1819): Add precompiled header to cmake generator +* Improve C++20 module to support std libraries for msvc ### Bugs Fixed @@ -1132,6 +1133,7 @@ * [#1776](https://github.com/xmake-io/xmake/issues/1776): 改进 system::find_package,支持从环境变量中查找系统库 * [#1786](https://github.com/xmake-io/xmake/issues/1786): 改进 apt:find_package,支持查找 alias 包 * [#1819](https://github.com/xmake-io/xmake/issues/1819): 添加预编译头到 cmake 生成器 +* 改进 C++20 Modules 为 msvc 支持 std 标准库 ### Bugs 修复 -- cgit v1.3.1 From b6ed301feb4b223a8c0faa9dd979a722b6e04555 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 10 Nov 2021 22:43:37 +0800 Subject: improve rust tests --- tests/projects/rust/console_with_cxx_library/src/foo.cc | 4 ++++ tests/projects/rust/console_with_cxx_library/src/main.rs | 9 +++++++++ tests/projects/rust/console_with_cxx_library/test.lua | 10 ++++++++++ tests/projects/rust/console_with_cxx_library/xmake.lua | 12 ++++++++++++ tests/projects/rust/static_library/src/foo.rs | 5 +++++ tests/projects/rust/static_library/src/interfaces.rs | 5 ----- tests/projects/rust/static_library/src/main.rs | 6 +++--- tests/projects/rust/static_library/xmake.lua | 6 +++--- xmake/templates/rust/static/project/src/foo.rs | 5 +++++ xmake/templates/rust/static/project/src/interfaces.rs | 5 ----- xmake/templates/rust/static/project/src/main.rs | 4 ++-- xmake/templates/rust/static/project/xmake.lua | 7 +++---- 12 files changed, 56 insertions(+), 22 deletions(-) create mode 100644 tests/projects/rust/console_with_cxx_library/src/foo.cc create mode 100644 tests/projects/rust/console_with_cxx_library/src/main.rs create mode 100644 tests/projects/rust/console_with_cxx_library/test.lua create mode 100644 tests/projects/rust/console_with_cxx_library/xmake.lua create mode 100644 tests/projects/rust/static_library/src/foo.rs delete mode 100644 tests/projects/rust/static_library/src/interfaces.rs create mode 100644 xmake/templates/rust/static/project/src/foo.rs delete mode 100644 xmake/templates/rust/static/project/src/interfaces.rs diff --git a/tests/projects/rust/console_with_cxx_library/src/foo.cc b/tests/projects/rust/console_with_cxx_library/src/foo.cc new file mode 100644 index 000000000..9d989119e --- /dev/null +++ b/tests/projects/rust/console_with_cxx_library/src/foo.cc @@ -0,0 +1,4 @@ +extern "C" int add(int a, int b) +{ + return a + b; +} diff --git a/tests/projects/rust/console_with_cxx_library/src/main.rs b/tests/projects/rust/console_with_cxx_library/src/main.rs new file mode 100644 index 000000000..1eac379d2 --- /dev/null +++ b/tests/projects/rust/console_with_cxx_library/src/main.rs @@ -0,0 +1,9 @@ +extern "C" { + fn add(a: i32, b: i32) -> i32; +} + +fn main() { + unsafe { + println!("add(1, 2) = {}", add(1, 2)); + } +} diff --git a/tests/projects/rust/console_with_cxx_library/test.lua b/tests/projects/rust/console_with_cxx_library/test.lua new file mode 100644 index 000000000..92168a8c1 --- /dev/null +++ b/tests/projects/rust/console_with_cxx_library/test.lua @@ -0,0 +1,10 @@ +-- main entry +function main(t) + + -- build project + if is_host("macosx") and os.arch() ~= "arm64" then + t:build() + else + return t:skip("wrong host platform") + end +end diff --git a/tests/projects/rust/console_with_cxx_library/xmake.lua b/tests/projects/rust/console_with_cxx_library/xmake.lua new file mode 100644 index 000000000..e150aca4a --- /dev/null +++ b/tests/projects/rust/console_with_cxx_library/xmake.lua @@ -0,0 +1,12 @@ +add_rules("mode.debug", "mode.release") + +target("foo") + set_kind("static") + add_files("src/foo.cc") + +target("test") + set_kind("binary") + add_deps("foo") + add_files("src/main.rs") + + diff --git a/tests/projects/rust/static_library/src/foo.rs b/tests/projects/rust/static_library/src/foo.rs new file mode 100644 index 000000000..277008ba4 --- /dev/null +++ b/tests/projects/rust/static_library/src/foo.rs @@ -0,0 +1,5 @@ +pub fn add(a: i32, b: i32) -> i32 +{ + return a + b; +} + diff --git a/tests/projects/rust/static_library/src/interfaces.rs b/tests/projects/rust/static_library/src/interfaces.rs deleted file mode 100644 index 277008ba4..000000000 --- a/tests/projects/rust/static_library/src/interfaces.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub fn add(a: i32, b: i32) -> i32 -{ - return a + b; -} - diff --git a/tests/projects/rust/static_library/src/main.rs b/tests/projects/rust/static_library/src/main.rs index 0cd4449d1..24f23d84b 100644 --- a/tests/projects/rust/static_library/src/main.rs +++ b/tests/projects/rust/static_library/src/main.rs @@ -1,7 +1,7 @@ -extern crate interfaces; +extern crate foo; -fn main() +fn main() { println!("hello xmake!"); - println!("add: {}", interfaces::add(1, 1)); + println!("add: {}", foo::add(1, 1)); } diff --git a/tests/projects/rust/static_library/xmake.lua b/tests/projects/rust/static_library/xmake.lua index fa38d17e5..c50e50874 100644 --- a/tests/projects/rust/static_library/xmake.lua +++ b/tests/projects/rust/static_library/xmake.lua @@ -1,12 +1,12 @@ add_rules("mode.debug", "mode.release") -target("interfaces") +target("foo") set_kind("static") - add_files("src/interfaces.rs") + add_files("src/foo.rs") target("test") set_kind("binary") - add_deps("interfaces") + add_deps("foo") add_files("src/main.rs") diff --git a/xmake/templates/rust/static/project/src/foo.rs b/xmake/templates/rust/static/project/src/foo.rs new file mode 100644 index 000000000..277008ba4 --- /dev/null +++ b/xmake/templates/rust/static/project/src/foo.rs @@ -0,0 +1,5 @@ +pub fn add(a: i32, b: i32) -> i32 +{ + return a + b; +} + diff --git a/xmake/templates/rust/static/project/src/interfaces.rs b/xmake/templates/rust/static/project/src/interfaces.rs deleted file mode 100644 index 277008ba4..000000000 --- a/xmake/templates/rust/static/project/src/interfaces.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub fn add(a: i32, b: i32) -> i32 -{ - return a + b; -} - diff --git a/xmake/templates/rust/static/project/src/main.rs b/xmake/templates/rust/static/project/src/main.rs index 24049d150..24f23d84b 100644 --- a/xmake/templates/rust/static/project/src/main.rs +++ b/xmake/templates/rust/static/project/src/main.rs @@ -1,7 +1,7 @@ -extern crate interfaces; +extern crate foo; fn main() { println!("hello xmake!"); - println!("add: {}", interfaces::add(1, 1)); + println!("add: {}", foo::add(1, 1)); } diff --git a/xmake/templates/rust/static/project/xmake.lua b/xmake/templates/rust/static/project/xmake.lua index a4761d2dc..79a9ac569 100644 --- a/xmake/templates/rust/static/project/xmake.lua +++ b/xmake/templates/rust/static/project/xmake.lua @@ -1,11 +1,10 @@ -target("interfaces") +target("foo") set_kind("static") - add_files("src/interfaces.rs") + add_files("src/foo.rs") target("${TARGETNAME}_demo") set_kind("binary") - add_deps("interfaces") + add_deps("foo") add_files("src/main.rs") - add_linkdirs("$(buildir)") ${FAQ} -- cgit v1.3.1 From bc404bc6481de0c934aa5ff4523924688b72a2d4 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 10 Nov 2021 23:05:38 +0800 Subject: fix rpath for rust --- xmake/languages/rust/xmake.lua | 14 ++++++ xmake/modules/core/tools/rustc.lua | 52 +++++++++++++++++------ xmake/modules/detect/tools/rustc/has_flags.lua | 28 +++++++++--- xmake/rules/rust/xmake.lua | 17 ++++++++ xmake/rules/utils/inherit_links/inherit_links.lua | 16 ++++--- 5 files changed, 100 insertions(+), 27 deletions(-) diff --git a/xmake/languages/rust/xmake.lua b/xmake/languages/rust/xmake.lua index dc6ae3d15..fef2af363 100644 --- a/xmake/languages/rust/xmake.lua +++ b/xmake/languages/rust/xmake.lua @@ -45,13 +45,27 @@ language("rust") , "target.symbols" , "toolchain.linkdirs" , "toolchain.rpathdirs" + , "config.links" + , "target.links" + , "toolchain.links" + , "config.syslinks" + , "target.syslinks" + , "toolchain.syslinks" } , shared = { "config.linkdirs" , "target.linkdirs" + , "target.rpathdirs" , "target.strip" , "target.symbols" , "toolchain.linkdirs" + , "toolchain.rpathdirs" + , "config.links" + , "target.links" + , "toolchain.links" + , "config.syslinks" + , "target.syslinks" + , "toolchain.syslinks" } , static = { "target.strip" diff --git a/xmake/modules/core/tools/rustc.lua b/xmake/modules/core/tools/rustc.lua index a30a389af..fa358e897 100644 --- a/xmake/modules/core/tools/rustc.lua +++ b/xmake/modules/core/tools/rustc.lua @@ -25,18 +25,6 @@ import("core.project.project") -- init it function init(self) - - -- init arflags - self:set("rcarflags", "--crate-type=lib") - - -- init shflags - self:set("rcshflags", "--crate-type=dylib") - - -- init ldflags - self:set("rcldflags", "--crate-type=bin") - - -- init the file formats - self:set("formats", { static = "lib$(name).rlib" }) end -- make the optimize flag @@ -67,9 +55,47 @@ function nf_linkdir(self, dir) return {"-L" .. dir} end +-- make the link flag +function nf_link(self, lib) + return "-l" .. lib +end + +-- make the syslink flag +function nf_syslink(self, lib) + return nf_link(self, lib) +end + +-- make the rpathdir flag +function nf_rpathdir(self, dir) + dir = path.translate(dir) + if self:has_flags({"-C", "link-arg=-Wl,-rpath=$ORIGIN"}, "ldflags") then + return {"-C", "link-arg=-Wl,-rpath=" .. (dir:gsub("@[%w_]+", function (name) + local maps = {["@loader_path"] = "$ORIGIN", ["@executable_path"] = "$ORIGIN"} + return maps[name] + end))} + elseif self:has_flags({"-C", "link-arg=-Xlinker", "-C", "link-arg=-rpath", "-C", "link-arg=-Xlinker", "-C", "link-arg=@loader_path"}, "ldflags") then + return {"-C", "link-arg=-Xlinker", + "-C", "link-arg=-rpath", + "-C", "link-arg=-Xlinker", + "-C", "link-arg=" .. (dir:gsub("%$ORIGIN", "@loader_path"))} + end +end + -- make the build arguments list function buildargv(self, sourcefiles, targetkind, targetfile, flags) - return self:program(), table.join(flags, "-o", targetfile, sourcefiles) + -- add rpath for dylib (macho), e.g. -install_name @rpath/file.dylib + local flags_extra = {} + if targetkind == "shared" and is_plat("macosx", "iphoneos", "watchos") then + table.insert(flags_extra, "-C") + table.insert(flags_extra, "link-arg=-Xlinker") + table.insert(flags_extra, "-C") + table.insert(flags_extra, "link-arg=-install_name") + table.insert(flags_extra, "-C") + table.insert(flags_extra, "link-arg=-Xlinker") + table.insert(flags_extra, "-C") + table.insert(flags_extra, "link-arg=@rpath/" .. path.filename(targetfile)) + end + return self:program(), table.join(flags, flags_extra, "-o", targetfile, sourcefiles) end -- build the target file diff --git a/xmake/modules/detect/tools/rustc/has_flags.lua b/xmake/modules/detect/tools/rustc/has_flags.lua index 904a3c85a..e1696e454 100644 --- a/xmake/modules/detect/tools/rustc/has_flags.lua +++ b/xmake/modules/detect/tools/rustc/has_flags.lua @@ -21,6 +21,16 @@ -- imports import("core.cache.detectcache") +-- is linker? +function _islinker(flags, opt) + local flags_str = table.concat(flags, " ") + if flags_str:startswith("-C linkarg=") then + return true + end + local toolkind = opt.toolkind or "" + return toolkind == "ld" or toolkind == "sh" or toolkind:endswith("ld") or toolkind:endswith("sh") +end + -- try running function _try_running(...) @@ -64,7 +74,7 @@ function _check_from_arglist(flags, opt) end -- try running to check flags -function _check_try_running(flags, opt) +function _check_try_running(flags, opt, islinker) -- make an stub source file local sourcefile = path.join(os.tmpdir(), "detect", "rustc_has_flags.rs") @@ -72,14 +82,15 @@ function _check_try_running(flags, opt) io.writefile(sourcefile, "fn main() {\n}") end - -- check it + -- check flags for linker + if islinker then + return _try_running(opt.program, table.join("--crate-type=bin", flags, "-o", os.tmpfile(), sourcefile), opt) + end + + -- check flags for compiler local objectfile = os.tmpfile() .. ".o" local ok, errors = _try_running(opt.program, table.join("--emit", "obj", flags, "-o", objectfile, sourcefile)) - - -- remove files os.tryrm(objectfile) - - -- ok? return ok, errors end @@ -91,12 +102,15 @@ end -- function main(flags, opt) + -- is linker? + local islinker = _islinker(flags, opt) + -- attempt to check it from the argument list if _check_from_arglist(flags, opt) then return true end -- try running to check it - return _check_try_running(flags, opt) + return _check_try_running(flags, opt, islinker) end diff --git a/xmake/rules/rust/xmake.lua b/xmake/rules/rust/xmake.lua index a8ccae429..b823ef753 100644 --- a/xmake/rules/rust/xmake.lua +++ b/xmake/rules/rust/xmake.lua @@ -21,6 +21,23 @@ -- define rule: rust.build rule("rust.build") set_sourcekinds("rc") + on_load(function (target) + if target:is_static() then + target:set("extension", ".rlib") + target:add("arflags", "--crate-type=lib") + elseif target:is_shared() then + target:add("shflags", "--crate-type=dylib") + -- fix cannot satisfy dependencies so `std` only shows up once + -- https://github.com/rust-lang/rust/issues/19680 + -- + -- but it will link dynamic @rpath/libstd-xxx.dylib, + -- so we can no longer modify and set other rpath paths + target:add("shflags", "-C prefer-dynamic") + elseif target:is_binary() then + target:add("ldflags", "--crate-type=bin") + end + target:data_set("inherit.links.deplink", false) + end) on_build("build.target") -- define rule: rust diff --git a/xmake/rules/utils/inherit_links/inherit_links.lua b/xmake/rules/utils/inherit_links/inherit_links.lua index d5567b605..805f535d8 100644 --- a/xmake/rules/utils/inherit_links/inherit_links.lua +++ b/xmake/rules/utils/inherit_links/inherit_links.lua @@ -46,7 +46,6 @@ function _add_export_value(target, name, value) end end --- main entry function main(target) -- disable inherit.links for `add_deps()`? @@ -59,12 +58,15 @@ function main(target) if targetkind == "shared" or targetkind == "static" then local targetfile = target:targetfile() - -- we need move target link to head - _add_export_value(target, "links", target:linkname()) - local links = target:get("links", {rawref = true}) - if links and type(links) == "table" and #links > 1 then - table.insert(links, 1, links[#links]) - table.remove(links, #links) + -- rust maybe will disable inherit links, only inherit linkdirs + if target:data("inherit.links.deplink") ~= false then + -- we need move target link to head + _add_export_value(target, "links", target:linkname()) + local links = target:get("links", {rawref = true}) + if links and type(links) == "table" and #links > 1 then + table.insert(links, 1, links[#links]) + table.remove(links, #links) + end end _add_export_value(target, "linkdirs", path.directory(targetfile)) -- cgit v1.3.1 From 4d457bd1f9f8e1c899d14e67439d13cf3de2b510 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 10 Nov 2021 23:12:50 +0800 Subject: add shared library for rust --- tests/projects/rust/shared_library/src/foo.rs | 5 +++++ tests/projects/rust/shared_library/src/main.rs | 7 +++++++ tests/projects/rust/shared_library/xmake.lua | 12 ++++++++++++ 3 files changed, 24 insertions(+) create mode 100644 tests/projects/rust/shared_library/src/foo.rs create mode 100644 tests/projects/rust/shared_library/src/main.rs create mode 100644 tests/projects/rust/shared_library/xmake.lua diff --git a/tests/projects/rust/shared_library/src/foo.rs b/tests/projects/rust/shared_library/src/foo.rs new file mode 100644 index 000000000..277008ba4 --- /dev/null +++ b/tests/projects/rust/shared_library/src/foo.rs @@ -0,0 +1,5 @@ +pub fn add(a: i32, b: i32) -> i32 +{ + return a + b; +} + diff --git a/tests/projects/rust/shared_library/src/main.rs b/tests/projects/rust/shared_library/src/main.rs new file mode 100644 index 000000000..24f23d84b --- /dev/null +++ b/tests/projects/rust/shared_library/src/main.rs @@ -0,0 +1,7 @@ +extern crate foo; + +fn main() +{ + println!("hello xmake!"); + println!("add: {}", foo::add(1, 1)); +} diff --git a/tests/projects/rust/shared_library/xmake.lua b/tests/projects/rust/shared_library/xmake.lua new file mode 100644 index 000000000..edacfe4d6 --- /dev/null +++ b/tests/projects/rust/shared_library/xmake.lua @@ -0,0 +1,12 @@ +add_rules("mode.debug", "mode.release") + +target("foo") + set_kind("shared") + add_files("src/foo.rs") + +target("test") + set_kind("binary") + add_deps("foo") + add_files("src/main.rs") + + -- cgit v1.3.1 From f75426a0b6317900298bfdda15a88b546b0d7564 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 11 Nov 2021 00:32:13 +0800 Subject: improve has_flags for msvc --- xmake/core/tool/builder.lua | 4 ++-- xmake/core/tool/tool.lua | 4 ++-- xmake/modules/detect/tools/cl/has_flags.lua | 8 +++++++- xmake/modules/detect/tools/gcc/has_flags.lua | 12 +++++++----- xmake/rules/c++/modules/build_modules/msvc.lua | 18 +++++++++--------- 5 files changed, 27 insertions(+), 19 deletions(-) diff --git a/xmake/core/tool/builder.lua b/xmake/core/tool/builder.lua index 33733eaab..91bb707f8 100644 --- a/xmake/core/tool/builder.lua +++ b/xmake/core/tool/builder.lua @@ -420,8 +420,8 @@ function builder:get(name) end -- has flags? -function builder:has_flags(flags, flagkind) - return self:_tool():has_flags(flags, flagkind) +function builder:has_flags(flags, flagkind, opt) + return self:_tool():has_flags(flags, flagkind, opt) end -- map flags from name and values, e.g. linkdirs, links, defines diff --git a/xmake/core/tool/tool.lua b/xmake/core/tool/tool.lua index c118179d6..af62c7f8e 100644 --- a/xmake/core/tool/tool.lua +++ b/xmake/core/tool/tool.lua @@ -140,8 +140,8 @@ function _instance:has_flags(flags, flagkind, opt) -- get system flags opt.sysflags = opt.sysflags or self:get(self:kind() .. 'flags') - if not opt.sysflags and flagkind then - opt.sysflags = self:get(flagkind) + if not opt.sysflags and opt.flagkind then + opt.sysflags = self:get(opt.flagkind) end -- import has_flags() diff --git a/xmake/modules/detect/tools/cl/has_flags.lua b/xmake/modules/detect/tools/cl/has_flags.lua index a1cb9ace7..1c7f65325 100644 --- a/xmake/modules/detect/tools/cl/has_flags.lua +++ b/xmake/modules/detect/tools/cl/has_flags.lua @@ -20,6 +20,7 @@ -- imports import("core.cache.detectcache") +import("core.language.language") -- attempt to check it from the argument list function _check_from_arglist(flags, opt) @@ -55,12 +56,17 @@ function _check_from_arglist(flags, opt) return allflags[flags[1]:gsub("/", "-")] end +-- get extension +function _get_extension(opt) + return opt.flagkind == "cxxflags" and ".cpp" or (table.wrap(language.sourcekinds()[opt.toolkind or "cc"])[1] or ".c") +end + -- try running to check flags function _check_try_running(flags, opt) -- make an stub source file local tmpdir = path.join(os.tmpdir(), "detect") - local sourcefile = path.join(tmpdir, "cl_has_flags.c") + local sourcefile = path.join(tmpdir, "cl_has_flags" .. _get_extension(opt)) if not os.isfile(sourcefile) then io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}") end diff --git a/xmake/modules/detect/tools/gcc/has_flags.lua b/xmake/modules/detect/tools/gcc/has_flags.lua index 391ff2bfb..7b4a40fd2 100644 --- a/xmake/modules/detect/tools/gcc/has_flags.lua +++ b/xmake/modules/detect/tools/gcc/has_flags.lua @@ -76,15 +76,17 @@ function _check_from_arglist(flags, opt, islinker) return allflags[flags[1]] end +-- get extension +function _get_extension(opt) + -- @note we need detect extension for ndk/clang++.exe: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated] + return (opt.program:endswith("++") or opt.flagkind == "cxxflags") and ".cpp" or (table.wrap(language.sourcekinds()[opt.toolkind or "cc"])[1] or ".c") +end + -- try running to check flags function _check_try_running(flags, opt, islinker) - -- get extension - -- @note we need detect extension for ndk/clang++.exe: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated] - local extension = opt.program:endswith("++") and ".cpp" or (table.wrap(language.sourcekinds()[opt.toolkind or "cc"])[1] or ".c") - -- make an stub source file - local sourcefile = path.join(os.tmpdir(), "detect", "gcc_has_flags" .. extension) + local sourcefile = path.join(os.tmpdir(), "detect", "gcc_has_flags" .. _get_extension(opt)) if not os.isfile(sourcefile) then io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}") end diff --git a/xmake/rules/c++/modules/build_modules/msvc.lua b/xmake/rules/c++/modules/build_modules/msvc.lua index 8b28d68f6..4606edb7e 100644 --- a/xmake/rules/c++/modules/build_modules/msvc.lua +++ b/xmake/rules/c++/modules/build_modules/msvc.lua @@ -29,7 +29,7 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) -- get modules flag local modulesflag local compinst = compiler.load("cxx", {target = target}) - if compinst:has_flags("/experimental:module") then + if compinst:has_flags("/experimental:module", "cxxflags") then modulesflag = "/experimental:module" end assert(modulesflag, "compiler(msvc): does not support c++ module!") @@ -38,41 +38,41 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) local cachedir local outputflag local hasifc = false - if compinst:has_flags("/ifcOutput") then + if compinst:has_flags("/ifcOutput", "cxxflags") then hasifc = true outputflag = "/ifcOutput" cachedir = path.join(target:autogendir(), "rules", "modules", "cache") if not os.isdir(cachedir) then os.mkdir(cachedir) end - elseif compinst:has_flags("/module:output") then + elseif compinst:has_flags("/module:output", "cxxflags") then outputflag = "/module:output" end assert(outputflag, "compiler(msvc): does not support c++ module!") -- get interface flag local interfaceflag - if compinst:has_flags("/interface") then + if compinst:has_flags("/interface", "cxxflags") then interfaceflag = "/interface" - elseif compinst:has_flags("/module:interface") then + elseif compinst:has_flags("/module:interface", "cxxflags") then interfaceflag = "/module:interface" end assert(interfaceflag, "compiler(msvc): does not support c++ module!") -- get reference flag local referenceflag - if compinst:has_flags("/reference") then + if compinst:has_flags("/reference", "cxxflags") then referenceflag = "/reference" - elseif compinst:has_flags("/module:interface") then + elseif compinst:has_flags("/module:interface", "cxxflags") then referenceflag = "/module:reference" end assert(referenceflag, "compiler(msvc): does not support c++ module!") -- get stdifcdir flag local stdifcdirflag - if compinst:has_flags("/stdIfcDir") then + if compinst:has_flags("/stdIfcDir", "cxxflags") then stdifcdirflag = "/stdIfcDir" - elseif compinst:has_flags("/module:stdIfcDir") then + elseif compinst:has_flags("/module:stdIfcDir", "cxxflags") then stdifcdirflag = "/module:stdIfcDir" end assert(stdifcdirflag, "compiler(msvc): does not support c++ module!") -- cgit v1.3.1 From 886c51e8ce29b07adb96d4db0f73e38ce9318990 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 11 Nov 2021 00:49:33 +0800 Subject: improve rust tests --- tests/projects/rust/console_with_cxx_library/src/foo.cc | 4 ---- tests/projects/rust/console_with_cxx_library/src/main.rs | 9 --------- tests/projects/rust/console_with_cxx_library/test.lua | 10 ---------- tests/projects/rust/console_with_cxx_library/xmake.lua | 12 ------------ tests/projects/rust/cxx_call_rust_library/src/bridge.rs | 6 ++++++ tests/projects/rust/cxx_call_rust_library/src/foo.rs | 6 ++++++ tests/projects/rust/cxx_call_rust_library/src/main.cc | 8 ++++++++ tests/projects/rust/cxx_call_rust_library/xmake.lua | 13 +++++++++++++ tests/projects/rust/rust_call_cxx_library/src/foo.cc | 4 ++++ tests/projects/rust/rust_call_cxx_library/src/main.rs | 9 +++++++++ tests/projects/rust/rust_call_cxx_library/test.lua | 10 ++++++++++ tests/projects/rust/rust_call_cxx_library/xmake.lua | 12 ++++++++++++ 12 files changed, 68 insertions(+), 35 deletions(-) delete mode 100644 tests/projects/rust/console_with_cxx_library/src/foo.cc delete mode 100644 tests/projects/rust/console_with_cxx_library/src/main.rs delete mode 100644 tests/projects/rust/console_with_cxx_library/test.lua delete mode 100644 tests/projects/rust/console_with_cxx_library/xmake.lua create mode 100644 tests/projects/rust/cxx_call_rust_library/src/bridge.rs create mode 100644 tests/projects/rust/cxx_call_rust_library/src/foo.rs create mode 100644 tests/projects/rust/cxx_call_rust_library/src/main.cc create mode 100644 tests/projects/rust/cxx_call_rust_library/xmake.lua create mode 100644 tests/projects/rust/rust_call_cxx_library/src/foo.cc create mode 100644 tests/projects/rust/rust_call_cxx_library/src/main.rs create mode 100644 tests/projects/rust/rust_call_cxx_library/test.lua create mode 100644 tests/projects/rust/rust_call_cxx_library/xmake.lua diff --git a/tests/projects/rust/console_with_cxx_library/src/foo.cc b/tests/projects/rust/console_with_cxx_library/src/foo.cc deleted file mode 100644 index 9d989119e..000000000 --- a/tests/projects/rust/console_with_cxx_library/src/foo.cc +++ /dev/null @@ -1,4 +0,0 @@ -extern "C" int add(int a, int b) -{ - return a + b; -} diff --git a/tests/projects/rust/console_with_cxx_library/src/main.rs b/tests/projects/rust/console_with_cxx_library/src/main.rs deleted file mode 100644 index 1eac379d2..000000000 --- a/tests/projects/rust/console_with_cxx_library/src/main.rs +++ /dev/null @@ -1,9 +0,0 @@ -extern "C" { - fn add(a: i32, b: i32) -> i32; -} - -fn main() { - unsafe { - println!("add(1, 2) = {}", add(1, 2)); - } -} diff --git a/tests/projects/rust/console_with_cxx_library/test.lua b/tests/projects/rust/console_with_cxx_library/test.lua deleted file mode 100644 index 92168a8c1..000000000 --- a/tests/projects/rust/console_with_cxx_library/test.lua +++ /dev/null @@ -1,10 +0,0 @@ --- main entry -function main(t) - - -- build project - if is_host("macosx") and os.arch() ~= "arm64" then - t:build() - else - return t:skip("wrong host platform") - end -end diff --git a/tests/projects/rust/console_with_cxx_library/xmake.lua b/tests/projects/rust/console_with_cxx_library/xmake.lua deleted file mode 100644 index e150aca4a..000000000 --- a/tests/projects/rust/console_with_cxx_library/xmake.lua +++ /dev/null @@ -1,12 +0,0 @@ -add_rules("mode.debug", "mode.release") - -target("foo") - set_kind("static") - add_files("src/foo.cc") - -target("test") - set_kind("binary") - add_deps("foo") - add_files("src/main.rs") - - diff --git a/tests/projects/rust/cxx_call_rust_library/src/bridge.rs b/tests/projects/rust/cxx_call_rust_library/src/bridge.rs new file mode 100644 index 000000000..3710f4bfd --- /dev/null +++ b/tests/projects/rust/cxx_call_rust_library/src/bridge.rs @@ -0,0 +1,6 @@ +#[cxx::bridge] +mod foo { + extern "Rust" { + fn add(a: i32, b: i32) -> i32; + } +} diff --git a/tests/projects/rust/cxx_call_rust_library/src/foo.rs b/tests/projects/rust/cxx_call_rust_library/src/foo.rs new file mode 100644 index 000000000..38727c484 --- /dev/null +++ b/tests/projects/rust/cxx_call_rust_library/src/foo.rs @@ -0,0 +1,6 @@ +pub fn add(a: i32, b: i32) -> i32 +{ + return a + b; +} + + diff --git a/tests/projects/rust/cxx_call_rust_library/src/main.cc b/tests/projects/rust/cxx_call_rust_library/src/main.cc new file mode 100644 index 000000000..c0d600fd3 --- /dev/null +++ b/tests/projects/rust/cxx_call_rust_library/src/main.cc @@ -0,0 +1,8 @@ +#include +#include "bridge.rs.h" + +int main(int argc, char** argv) +{ + printf("add(1, 2) == %d\n", add(1, 2)); + return 0; +} diff --git a/tests/projects/rust/cxx_call_rust_library/xmake.lua b/tests/projects/rust/cxx_call_rust_library/xmake.lua new file mode 100644 index 000000000..b8bc7c9a8 --- /dev/null +++ b/tests/projects/rust/cxx_call_rust_library/xmake.lua @@ -0,0 +1,13 @@ +add_rules("mode.debug", "mode.release") + +target("foo") + set_kind("static") + add_files("src/foo.rs") + +target("test") + set_kind("binary") + add_deps("foo") + add_files("src/main.cc") + add_files("src/bridge.rs", {rules = "rust.cxxbridge"}) + + diff --git a/tests/projects/rust/rust_call_cxx_library/src/foo.cc b/tests/projects/rust/rust_call_cxx_library/src/foo.cc new file mode 100644 index 000000000..9d989119e --- /dev/null +++ b/tests/projects/rust/rust_call_cxx_library/src/foo.cc @@ -0,0 +1,4 @@ +extern "C" int add(int a, int b) +{ + return a + b; +} diff --git a/tests/projects/rust/rust_call_cxx_library/src/main.rs b/tests/projects/rust/rust_call_cxx_library/src/main.rs new file mode 100644 index 000000000..1eac379d2 --- /dev/null +++ b/tests/projects/rust/rust_call_cxx_library/src/main.rs @@ -0,0 +1,9 @@ +extern "C" { + fn add(a: i32, b: i32) -> i32; +} + +fn main() { + unsafe { + println!("add(1, 2) = {}", add(1, 2)); + } +} diff --git a/tests/projects/rust/rust_call_cxx_library/test.lua b/tests/projects/rust/rust_call_cxx_library/test.lua new file mode 100644 index 000000000..92168a8c1 --- /dev/null +++ b/tests/projects/rust/rust_call_cxx_library/test.lua @@ -0,0 +1,10 @@ +-- main entry +function main(t) + + -- build project + if is_host("macosx") and os.arch() ~= "arm64" then + t:build() + else + return t:skip("wrong host platform") + end +end diff --git a/tests/projects/rust/rust_call_cxx_library/xmake.lua b/tests/projects/rust/rust_call_cxx_library/xmake.lua new file mode 100644 index 000000000..e150aca4a --- /dev/null +++ b/tests/projects/rust/rust_call_cxx_library/xmake.lua @@ -0,0 +1,12 @@ +add_rules("mode.debug", "mode.release") + +target("foo") + set_kind("static") + add_files("src/foo.cc") + +target("test") + set_kind("binary") + add_deps("foo") + add_files("src/main.rs") + + -- cgit v1.3.1 From bd26b472129bc61043a69ffecbddabbd83eb0650 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 11 Nov 2021 00:59:01 +0800 Subject: improve target.sourcekinds --- tests/projects/rust/cxx_call_rust_library/xmake.lua | 5 ++--- xmake/core/project/target.lua | 4 ++-- xmake/languages/rust/xmake.lua | 2 +- xmake/rules/rust/xmake.lua | 8 ++++++++ 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/projects/rust/cxx_call_rust_library/xmake.lua b/tests/projects/rust/cxx_call_rust_library/xmake.lua index b8bc7c9a8..00725b02f 100644 --- a/tests/projects/rust/cxx_call_rust_library/xmake.lua +++ b/tests/projects/rust/cxx_call_rust_library/xmake.lua @@ -6,8 +6,7 @@ target("foo") target("test") set_kind("binary") + add_rules("rust.cxxbridge", {override = true}) add_deps("foo") add_files("src/main.cc") - add_files("src/bridge.rs", {rules = "rust.cxxbridge"}) - - + add_files("src/bridge.rs") diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 08ab720c0..c48d64c47 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -1609,8 +1609,8 @@ function _instance:sourcekinds() local sourcekinds = self._SOURCEKINDS if not sourcekinds then sourcekinds = {} - for _, sourcefile in pairs(self:sourcefiles()) do - local sourcekind = self:sourcekind_of(sourcefile) + for _, sourcebatch in pairs(self:sourcebatches()) do + local sourcekind = sourcebatch.sourcekind if sourcekind then table.insert(sourcekinds, sourcekind) end diff --git a/xmake/languages/rust/xmake.lua b/xmake/languages/rust/xmake.lua index fef2af363..b07617a61 100644 --- a/xmake/languages/rust/xmake.lua +++ b/xmake/languages/rust/xmake.lua @@ -25,7 +25,7 @@ language("rust") set_targetkinds {binary = "rcld", static = "rcar", shared = "rcsh"} set_targetflags {binary = "ldflags", static = "arflags", shared = "shflags"} set_langkinds {rust = "rc"} - set_mixingkinds("rc") + set_mixingkinds("rc", "cc", "cxx") on_load("load") on_check_main("check_main") diff --git a/xmake/rules/rust/xmake.lua b/xmake/rules/rust/xmake.lua index b823ef753..08fcf11f0 100644 --- a/xmake/rules/rust/xmake.lua +++ b/xmake/rules/rust/xmake.lua @@ -18,6 +18,14 @@ -- @file xmake.lua -- +-- generate bridge.rs.cc/h to call rust library in c++ code +-- @see https://cxx.rs/build/other.html +rule("rust.cxxbridge") + set_extensions(".rs") + before_build_file(function (target, sourcefile, opt) + print(sourcefile) + end) + -- define rule: rust.build rule("rust.build") set_sourcekinds("rc") -- cgit v1.3.1 From d4de88729159b7c331b3b268fdcc67627e9678d4 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 11 Nov 2021 21:00:09 +0800 Subject: rename to .rsx --- tests/projects/rust/cxx_call_rust_library/src/bridge.rs | 6 ------ tests/projects/rust/cxx_call_rust_library/src/bridge.rsx | 6 ++++++ tests/projects/rust/cxx_call_rust_library/xmake.lua | 4 ++-- xmake/rules/rust/xmake.lua | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) delete mode 100644 tests/projects/rust/cxx_call_rust_library/src/bridge.rs create mode 100644 tests/projects/rust/cxx_call_rust_library/src/bridge.rsx diff --git a/tests/projects/rust/cxx_call_rust_library/src/bridge.rs b/tests/projects/rust/cxx_call_rust_library/src/bridge.rs deleted file mode 100644 index 3710f4bfd..000000000 --- a/tests/projects/rust/cxx_call_rust_library/src/bridge.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[cxx::bridge] -mod foo { - extern "Rust" { - fn add(a: i32, b: i32) -> i32; - } -} diff --git a/tests/projects/rust/cxx_call_rust_library/src/bridge.rsx b/tests/projects/rust/cxx_call_rust_library/src/bridge.rsx new file mode 100644 index 000000000..3710f4bfd --- /dev/null +++ b/tests/projects/rust/cxx_call_rust_library/src/bridge.rsx @@ -0,0 +1,6 @@ +#[cxx::bridge] +mod foo { + extern "Rust" { + fn add(a: i32, b: i32) -> i32; + } +} diff --git a/tests/projects/rust/cxx_call_rust_library/xmake.lua b/tests/projects/rust/cxx_call_rust_library/xmake.lua index 00725b02f..cfd0e035e 100644 --- a/tests/projects/rust/cxx_call_rust_library/xmake.lua +++ b/tests/projects/rust/cxx_call_rust_library/xmake.lua @@ -6,7 +6,7 @@ target("foo") target("test") set_kind("binary") - add_rules("rust.cxxbridge", {override = true}) + add_rules("rust.cxxbridge") add_deps("foo") add_files("src/main.cc") - add_files("src/bridge.rs") + add_files("src/bridge.rsx") diff --git a/xmake/rules/rust/xmake.lua b/xmake/rules/rust/xmake.lua index 08fcf11f0..51e27fcc8 100644 --- a/xmake/rules/rust/xmake.lua +++ b/xmake/rules/rust/xmake.lua @@ -21,8 +21,8 @@ -- generate bridge.rs.cc/h to call rust library in c++ code -- @see https://cxx.rs/build/other.html rule("rust.cxxbridge") - set_extensions(".rs") - before_build_file(function (target, sourcefile, opt) + set_extensions(".rsx") + before_buildcmd_file(function (target, batchcmds, sourcefile, opt) print(sourcefile) end) -- cgit v1.3.1 From cf9d3bacd0b0d47946e517dae67800fa7b8f3e1e Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 11 Nov 2021 21:00:59 +0800 Subject: add find_cxxbridge --- xmake/modules/detect/tools/find_cxxbridge.lua | 52 +++++++++++++++++++++++++++ xmake/rules/rust/build/cxxbridge.lua | 27 ++++++++++++++ xmake/rules/rust/xmake.lua | 4 +-- 3 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 xmake/modules/detect/tools/find_cxxbridge.lua create mode 100644 xmake/rules/rust/build/cxxbridge.lua diff --git a/xmake/modules/detect/tools/find_cxxbridge.lua b/xmake/modules/detect/tools/find_cxxbridge.lua new file mode 100644 index 000000000..400573fa7 --- /dev/null +++ b/xmake/modules/detect/tools/find_cxxbridge.lua @@ -0,0 +1,52 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_cxxbridge.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find nim +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local nim = find_cxxbridge() +-- local nim, version = find_cxxbridge({program = "cxxbridge", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "cxxbridge", opt) + + -- find program version + local version = nil + if program and opt.version then + version = find_programver(program, opt) + end + return program, version +end diff --git a/xmake/rules/rust/build/cxxbridge.lua b/xmake/rules/rust/build/cxxbridge.lua new file mode 100644 index 000000000..909006632 --- /dev/null +++ b/xmake/rules/rust/build/cxxbridge.lua @@ -0,0 +1,27 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file cxxbridge.lua +-- + +-- imports +import("core.base.option") +import("lib.detect.find_tool") + +function main(target, batchcmds, sourcefile, opt) + print(sourcefile) +end diff --git a/xmake/rules/rust/xmake.lua b/xmake/rules/rust/xmake.lua index 51e27fcc8..b3599e43b 100644 --- a/xmake/rules/rust/xmake.lua +++ b/xmake/rules/rust/xmake.lua @@ -22,9 +22,7 @@ -- @see https://cxx.rs/build/other.html rule("rust.cxxbridge") set_extensions(".rsx") - before_buildcmd_file(function (target, batchcmds, sourcefile, opt) - print(sourcefile) - end) + before_buildcmd_file("build.cxxbridge") -- define rule: rust.build rule("rust.build") -- cgit v1.3.1 From 147f4005fe0c549244ebddb660964585c5414652 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 11 Nov 2021 22:37:39 +0800 Subject: add rust.cxxbridge rules --- .../projects/rust/cxx_call_rust_library/xmake.lua | 1 + xmake/rules/rust/build/cxxbridge.lua | 25 +++++++++++++++++++++- xmake/rules/rust/xmake.lua | 23 +++++++++++++------- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/tests/projects/rust/cxx_call_rust_library/xmake.lua b/tests/projects/rust/cxx_call_rust_library/xmake.lua index cfd0e035e..fb3a48171 100644 --- a/tests/projects/rust/cxx_call_rust_library/xmake.lua +++ b/tests/projects/rust/cxx_call_rust_library/xmake.lua @@ -3,6 +3,7 @@ add_rules("mode.debug", "mode.release") target("foo") set_kind("static") add_files("src/foo.rs") + set_values("rust.cratetype", "staticlib") target("test") set_kind("binary") diff --git a/xmake/rules/rust/build/cxxbridge.lua b/xmake/rules/rust/build/cxxbridge.lua index 909006632..84b1f7fea 100644 --- a/xmake/rules/rust/build/cxxbridge.lua +++ b/xmake/rules/rust/build/cxxbridge.lua @@ -23,5 +23,28 @@ import("core.base.option") import("lib.detect.find_tool") function main(target, batchcmds, sourcefile, opt) - print(sourcefile) + local cxxbridge = assert(find_tool("cxxbridge"), "cxxbridge not found!") + + -- get c/c++ source file for cxxbridge + local headerfile = path.join(target:autogendir(), "rules", "cxxbridge", path.basename(sourcefile) .. ".rs.h") + local sourcefile_cx = path.join(target:autogendir(), "rules", "cxxbridge", path.basename(sourcefile) .. ".rs.cc") + + -- add includedirs + target:add("includedirs", path.directory(headerfile)) + + -- add objectfile + local objectfile = target:objectfile(sourcefile_cx) + table.insert(target:objectfiles(), objectfile) + + -- add commands + batchcmds:show_progress(opt.progress, "${color.build.object}compiling.cxxbridge %s", sourcefile) + batchcmds:mkdir(path.directory(sourcefile_cx)) + batchcmds:vrunv(cxxbridge.program, {sourcefile}, {stdout = sourcefile_cx}) + batchcmds:vrunv(cxxbridge.program, {sourcefile, "--header"}, {stdout = headerfile}) + batchcmds:compile(sourcefile_cx, objectfile) + + -- add deps + batchcmds:add_depfiles(sourcefile) + batchcmds:set_depmtime(os.mtime(objectfile)) + batchcmds:set_depcache(target:dependfile(objectfile)) end diff --git a/xmake/rules/rust/xmake.lua b/xmake/rules/rust/xmake.lua index b3599e43b..e0952b72e 100644 --- a/xmake/rules/rust/xmake.lua +++ b/xmake/rules/rust/xmake.lua @@ -22,15 +22,28 @@ -- @see https://cxx.rs/build/other.html rule("rust.cxxbridge") set_extensions(".rsx") + on_load(function (target) + if not target:get("languages") then + target:set("languages", "c++11") + end + end) before_buildcmd_file("build.cxxbridge") --- define rule: rust.build rule("rust.build") set_sourcekinds("rc") on_load(function (target) - if target:is_static() then + local cratetype = target:values("rust.cratetype") + if cratetype == "staticlib" then + assert(target:is_static(), "target(%s) must be static kind for cratetype(staticlib)!", target:name()) + target:add("arflags", "--crate-type=staticlib") + elseif cratetype == "cdylib" then + assert(target:is_shared(), "target(%s) must be shared kind for cratetype(cdylib)!", target:name()) + target:add("shflags", "--crate-type=cdylib") + target:add("shflags", "-C prefer-dynamic") + elseif target:is_static() then target:set("extension", ".rlib") target:add("arflags", "--crate-type=lib") + target:data_set("inherit.links.deplink", false) elseif target:is_shared() then target:add("shflags", "--crate-type=dylib") -- fix cannot satisfy dependencies so `std` only shows up once @@ -42,15 +55,9 @@ rule("rust.build") elseif target:is_binary() then target:add("ldflags", "--crate-type=bin") end - target:data_set("inherit.links.deplink", false) end) on_build("build.target") --- define rule: rust rule("rust") - - -- add build rules add_deps("rust.build") - - -- inherit links and linkdirs of all dependent targets by default add_deps("utils.inherit.links") -- cgit v1.3.1 From 1130f7b98a942da147a92040dd640ce84b561128 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 12 Nov 2021 00:54:54 +0800 Subject: improve rust test --- tests/projects/rust/cxx_call_rust_library/src/foo.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/projects/rust/cxx_call_rust_library/src/foo.rs b/tests/projects/rust/cxx_call_rust_library/src/foo.rs index 38727c484..0c4975fa2 100644 --- a/tests/projects/rust/cxx_call_rust_library/src/foo.rs +++ b/tests/projects/rust/cxx_call_rust_library/src/foo.rs @@ -1,3 +1,10 @@ +#[cxx::bridge] +mod foo { + extern "Rust" { + fn add(a: i32, b: i32) -> i32; + } +} + pub fn add(a: i32, b: i32) -> i32 { return a + b; -- cgit v1.3.1 From ad765e29055fc0d0913fc25849af4fca7732fd0e Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 12 Nov 2021 12:40:42 +0800 Subject: Update find_package.lua --- xmake/modules/package/manager/cmake/find_package.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua index 085851205..e4099f73d 100644 --- a/xmake/modules/package/manager/cmake/find_package.lua +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -186,6 +186,11 @@ function _find_package(cmake, name, opt) end values = line:match("(.+)") + if not values then + -- we need also parse libraries from here + -- https://github.com/xmake-io/xmake/issues/1822 + values = line:match("(.+)") + end if values then for _, library in ipairs(path.splitenv(values)) do -- get libfiles -- cgit v1.3.1 From 65f1179b9df1886c23dce6bbe4dfdb25ae912b9b Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 12 Nov 2021 13:38:05 +0800 Subject: Update package.lua --- xmake/core/package/package.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 80f7e9904..6b7f22a4e 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -1258,6 +1258,7 @@ function _instance:find_tool(name, opt) self._find_tool = self._find_tool or sandbox_module.import("lib.detect.find_tool", {anonymous = true}) return self._find_tool(name, {cachekey = opt.cachekey or "fetch_package_system", installdir = self:installdir(), + version = true, -- we alway check version require_version = opt.require_version, norun = opt.norun, force = opt.force}) @@ -1274,6 +1275,7 @@ function _instance:find_package(name, opt) return self._find_package(name, { force = opt.force, installdir = self:installdir(), + version = true, -- we alway check version require_version = opt.require_version, mode = self:mode(), plat = self:plat(), -- cgit v1.3.1 From 15520b0859aa54c9d0853765cdeaf14c3b52960d Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Nov 2021 10:39:14 +0800 Subject: fix float number --- xmake/modules/private/action/require/impl/package.lua | 2 +- xmake/modules/private/action/require/impl/remove_packages.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 77c20648b..7a8502326 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -959,7 +959,7 @@ function get_configs_str(package) table.insert(configs, "from:" .. parents_str) end local configs_str = #configs > 0 and "[" .. table.concat(configs, ", ") .. "]" or "" - local limitwidth = os.getwinsize().width * 2 / 3 + local limitwidth = math.floor(os.getwinsize().width * 2 / 3) if #configs_str > limitwidth then configs_str = configs_str:sub(1, limitwidth) .. " ..)" end diff --git a/xmake/modules/private/action/require/impl/remove_packages.lua b/xmake/modules/private/action/require/impl/remove_packages.lua index b65627256..f8f93c663 100644 --- a/xmake/modules/private/action/require/impl/remove_packages.lua +++ b/xmake/modules/private/action/require/impl/remove_packages.lua @@ -36,7 +36,7 @@ function _get_package_configs_str(manifest_file) end end local configs_str = #configs > 0 and "[" .. table.concat(configs, ", ") .. "]" or "" - local limitwidth = os.getwinsize().width * 2 / 3 + local limitwidth = math.floor(os.getwinsize().width * 2 / 3) if #configs_str > limitwidth then configs_str = configs_str:sub(1, limitwidth) .. " ..)" end -- cgit v1.3.1 From af799e0501b6255616ddc8f610267dbd33f93291 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Nov 2021 11:58:51 +0800 Subject: add cargo deps --- tests/projects/rust/cargo_deps/Cargo.toml | 9 +++++++++ tests/projects/rust/cargo_deps/src/main.rs | 11 +++++++++++ tests/projects/rust/cargo_deps/xmake.lua | 7 +++++++ 3 files changed, 27 insertions(+) create mode 100644 tests/projects/rust/cargo_deps/Cargo.toml create mode 100644 tests/projects/rust/cargo_deps/src/main.rs create mode 100644 tests/projects/rust/cargo_deps/xmake.lua diff --git a/tests/projects/rust/cargo_deps/Cargo.toml b/tests/projects/rust/cargo_deps/Cargo.toml new file mode 100644 index 000000000..df461d550 --- /dev/null +++ b/tests/projects/rust/cargo_deps/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "cargo_deps" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +base64 = "0.13.0" diff --git a/tests/projects/rust/cargo_deps/src/main.rs b/tests/projects/rust/cargo_deps/src/main.rs new file mode 100644 index 000000000..92a120ec9 --- /dev/null +++ b/tests/projects/rust/cargo_deps/src/main.rs @@ -0,0 +1,11 @@ +extern crate base64; + +use base64::{encode, decode}; + +fn main() { + let a = b"hello world"; + let b = "aGVsbG8gd29ybGQ="; + + assert_eq!(encode(a), b); + assert_eq!(a, &decode(b).unwrap()[..]); +} diff --git a/tests/projects/rust/cargo_deps/xmake.lua b/tests/projects/rust/cargo_deps/xmake.lua new file mode 100644 index 000000000..e8a06699b --- /dev/null +++ b/tests/projects/rust/cargo_deps/xmake.lua @@ -0,0 +1,7 @@ +add_rules("mode.release", "mode.debug") +add_requires("cargo::base64") + +target("test") + set_kind("binary") + add_files("src/main.rs") + add_packages("cargo::base64") -- cgit v1.3.1 From e0c6eda852156eba4a177bb67c5775d41f207734 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Nov 2021 12:04:00 +0800 Subject: add find_cargo --- xmake/modules/detect/tools/find_cargo.lua | 52 +++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 xmake/modules/detect/tools/find_cargo.lua diff --git a/xmake/modules/detect/tools/find_cargo.lua b/xmake/modules/detect/tools/find_cargo.lua new file mode 100644 index 000000000..a67b29821 --- /dev/null +++ b/xmake/modules/detect/tools/find_cargo.lua @@ -0,0 +1,52 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_cargo.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find nim +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local nim = find_cargo() +-- local nim, version = find_cargo({program = "cargo", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "cargo", opt) + + -- find program version + local version = nil + if program and opt.version then + version = find_programver(program, opt) + end + return program, version +end -- cgit v1.3.1 From 7625d0368ebf5dd461566b802ebb464cda2b1c9d Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Nov 2021 12:09:14 +0800 Subject: add cargo.install_package stub --- .../modules/package/manager/cargo/find_package.lua | 35 ++++++++++++++++ .../package/manager/cargo/install_package.lua | 46 ++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 xmake/modules/package/manager/cargo/find_package.lua create mode 100644 xmake/modules/package/manager/cargo/install_package.lua diff --git a/xmake/modules/package/manager/cargo/find_package.lua b/xmake/modules/package/manager/cargo/find_package.lua new file mode 100644 index 000000000..8ed72efec --- /dev/null +++ b/xmake/modules/package/manager/cargo/find_package.lua @@ -0,0 +1,35 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_package.lua +-- + +-- imports +import("core.base.option") +import("core.base.semver") +import("core.project.config") +import("core.project.target") +import("lib.detect.find_tool") +import("lib.detect.find_file") + +-- find package using the cargo package manager +-- +-- @param name the package name +-- @param opt the options, e.g. {verbose = true, require_version = "1.12.x") +-- +function main(name, opt) +end diff --git a/xmake/modules/package/manager/cargo/install_package.lua b/xmake/modules/package/manager/cargo/install_package.lua new file mode 100644 index 000000000..cbf1df8f2 --- /dev/null +++ b/xmake/modules/package/manager/cargo/install_package.lua @@ -0,0 +1,46 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file install_package.lua +-- + +-- imports +import("core.base.option") +import("core.project.config") +import("lib.detect.find_tool") + +-- install package +-- +-- e.g. +-- add_requires("cargo::zip") +-- add_requires("cargo::zip >0.3") +-- add_requires("cargo::zip 0.3.1") +-- +-- @param name the package name, e.g. cargo::zip +-- @param opt the options, e.g. { verbose = true, mode = "release", plat = , arch = , require_version = "x.x.x"} +-- +-- @return true or false +-- +function main(name, opt) + + -- find cargo + local cargo = find_tool("cargo") + if not cargo then + raise("cargo not found!") + end + +end -- cgit v1.3.1 From daef54e8a91ae742e18057756fcaa7548bc83930 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Nov 2021 13:03:38 +0800 Subject: install cargo deps --- tests/projects/rust/cargo_deps/xmake.lua | 5 +- xmake/core/package/package.lua | 2 + .../package/manager/cargo/install_package.lua | 61 ++++++++++++++++++++-- .../private/action/require/impl/package.lua | 2 +- 4 files changed, 63 insertions(+), 7 deletions(-) diff --git a/tests/projects/rust/cargo_deps/xmake.lua b/tests/projects/rust/cargo_deps/xmake.lua index e8a06699b..73340dedf 100644 --- a/tests/projects/rust/cargo_deps/xmake.lua +++ b/tests/projects/rust/cargo_deps/xmake.lua @@ -1,7 +1,8 @@ add_rules("mode.release", "mode.debug") -add_requires("cargo::base64") +add_requires("cargo::base64 0.13.0") +add_requires("cargo::flate2 1.0.17", {configs = {features = "zlib"}}) target("test") set_kind("binary") add_files("src/main.rs") - add_packages("cargo::base64") + add_packages("cargo::base64", "cargo::flate2") diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 6b7f22a4e..d5d683741 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -1867,6 +1867,8 @@ function package.load_from_system(packagename) opt.arch = pkg:arch() opt.require_version = pkg:version_str() opt.buildhash = pkg:buildhash() + opt.cachedir = pkg:cachedir() + opt.installdir = pkg:installdir() import("package.manager.install_package")(pkg:name(), opt) end diff --git a/xmake/modules/package/manager/cargo/install_package.lua b/xmake/modules/package/manager/cargo/install_package.lua index cbf1df8f2..a500bb6a7 100644 --- a/xmake/modules/package/manager/cargo/install_package.lua +++ b/xmake/modules/package/manager/cargo/install_package.lua @@ -23,14 +23,23 @@ import("core.base.option") import("core.project.config") import("lib.detect.find_tool") +-- get configurations +function configurations() + return + { + features = {description = "set the features of dependency."}, + default_features = {description = "enables or disables any defaults provided by the dependency.", default = true}, + } +end + -- install package -- -- e.g. --- add_requires("cargo::zip") --- add_requires("cargo::zip >0.3") --- add_requires("cargo::zip 0.3.1") +-- add_requires("cargo::base64") +-- add_requires("cargo::base64 0.13.0") +-- add_requires("cargo::flate2 1.0.17", {configs = {features = {"zlib"}, ["default-features"] = false}}) -- --- @param name the package name, e.g. cargo::zip +-- @param name the package name, e.g. cargo::base64 -- @param opt the options, e.g. { verbose = true, mode = "release", plat = , arch = , require_version = "x.x.x"} -- -- @return true or false @@ -43,4 +52,48 @@ function main(name, opt) raise("cargo not found!") end + -- get required version + local require_version = assert(opt.require_version, "cargo::%s version not found!", name) + + -- build dependencies + local sourcedir = path.join(opt.cachedir, "source") + local cargotoml = path.join(sourcedir, "Cargo.toml") + os.tryrm(sourcedir) + local tomlfile = io.open(cargotoml, "w") + tomlfile:print("[package]") + tomlfile:print("name = \"cargodeps\"") + tomlfile:print("version = \"0.1.0\"") + tomlfile:print("edition = \"2018\"") + tomlfile:print("") + tomlfile:print("[dependencies]") + local features = opt.features + if features then + features = table.wrap(features) + tomlfile:print("%s = {version = \"%s\", features = [\"%s\"], default-features = %s}", name, require_version, table.concat(features, "\", \""), opt.default_features) + else + tomlfile:print("%s = \"%s\"", name, require_version) + end + tomlfile:close() + + -- generate main.rs + io.writefile(path.join(sourcedir, "src", "main.rs"), [[ +fn main() { + println!("Hello, world!"); +} + ]]) + + -- do build + local argv = {"build"} + if opt.mode ~= "debug" then + table.insert(argv, "--release") + end + if option.get("verbose") then + table.insert(argv, option.get("diagnosis") and "-vv" or "-v") + end + os.vrunv(cargo.program, argv, {curdir = sourcedir}) + + -- do install + local installdir = opt.installdir + os.tryrm(path.join(installdir, "lib")) + os.vcp(path.join(sourcedir, "target", opt.mode == "debug" and "debug" or "release", "deps"), path.join(installdir, "lib")) end diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 7a8502326..3bb12ac30 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -950,7 +950,7 @@ function get_configs_str(package) if type(v) == "boolean" then table.insert(configs, k .. ":" .. (v and "y" or "n")) else - table.insert(configs, k .. ":" .. v) + table.insert(configs, k .. ":" .. string.serialize(v, {strip = true, indent = false})) end end end -- cgit v1.3.1 From 8907c57014dedbd68da377cb25a92096c0c713d8 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Nov 2021 13:23:21 +0800 Subject: add find_package for cargo --- tests/projects/rust/cargo_deps/src/main.rs | 1 + tests/projects/rust/cxx_call_rust_library/xmake.lua | 3 +++ xmake/modules/package/manager/cargo/find_package.lua | 19 +++++++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/tests/projects/rust/cargo_deps/src/main.rs b/tests/projects/rust/cargo_deps/src/main.rs index 92a120ec9..f1ec987bf 100644 --- a/tests/projects/rust/cargo_deps/src/main.rs +++ b/tests/projects/rust/cargo_deps/src/main.rs @@ -8,4 +8,5 @@ fn main() { assert_eq!(encode(a), b); assert_eq!(a, &decode(b).unwrap()[..]); + println!("{}", encode(a)); } diff --git a/tests/projects/rust/cxx_call_rust_library/xmake.lua b/tests/projects/rust/cxx_call_rust_library/xmake.lua index fb3a48171..30d54cc02 100644 --- a/tests/projects/rust/cxx_call_rust_library/xmake.lua +++ b/tests/projects/rust/cxx_call_rust_library/xmake.lua @@ -1,9 +1,12 @@ add_rules("mode.debug", "mode.release") +add_requires("cargo::cxx 1.0") + target("foo") set_kind("static") add_files("src/foo.rs") set_values("rust.cratetype", "staticlib") + add_packages("cargo::cxx") target("test") set_kind("binary") diff --git a/xmake/modules/package/manager/cargo/find_package.lua b/xmake/modules/package/manager/cargo/find_package.lua index 8ed72efec..336b4243a 100644 --- a/xmake/modules/package/manager/cargo/find_package.lua +++ b/xmake/modules/package/manager/cargo/find_package.lua @@ -32,4 +32,23 @@ import("lib.detect.find_file") -- @param opt the options, e.g. {verbose = true, require_version = "1.12.x") -- function main(name, opt) + local linkdirs + local librarydir = path.join(opt.installdir, "lib") + local libfiles = os.files(path.join(librarydir, "*.rlib")) + for _, libraryfile in ipairs(libfiles) do + local filename = path.filename(libraryfile) + if filename:startswith("lib" .. name .. "-") then + linkdirs = linkdirs or {} + table.insert(linkdirs, librarydir) + break + end + end + local result + if linkdirs then + result = result or {} + result.libfiles = libfiles + result.linkdirs = linkdirs + result.version = opt.require_version + end + return result end -- cgit v1.3.1 From 6b684d5cc448124c31a51fff71e4043667677a57 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Nov 2021 13:46:36 +0800 Subject: add frameworks for rust --- tests/projects/rust/cxx_call_rust_library/xmake.lua | 1 + xmake/languages/rust/xmake.lua | 14 +++++++++++++- xmake/modules/core/tools/rustc.lua | 9 +++++++++ xmake/modules/package/manager/cargo/find_package.lua | 6 +++++- xmake/rules/rust/xmake.lua | 1 + xmake/rules/utils/inherit_links/inherit_links.lua | 12 +++++++----- 6 files changed, 36 insertions(+), 7 deletions(-) diff --git a/tests/projects/rust/cxx_call_rust_library/xmake.lua b/tests/projects/rust/cxx_call_rust_library/xmake.lua index 30d54cc02..cafd349ee 100644 --- a/tests/projects/rust/cxx_call_rust_library/xmake.lua +++ b/tests/projects/rust/cxx_call_rust_library/xmake.lua @@ -7,6 +7,7 @@ target("foo") add_files("src/foo.rs") set_values("rust.cratetype", "staticlib") add_packages("cargo::cxx") + add_rcflags("--edition=2018") target("test") set_kind("binary") diff --git a/xmake/languages/rust/xmake.lua b/xmake/languages/rust/xmake.lua index b07617a61..1335225e3 100644 --- a/xmake/languages/rust/xmake.lua +++ b/xmake/languages/rust/xmake.lua @@ -45,6 +45,9 @@ language("rust") , "target.symbols" , "toolchain.linkdirs" , "toolchain.rpathdirs" + , "config.frameworks" + , "target.frameworks" + , "toolchain.frameworks" , "config.links" , "target.links" , "toolchain.links" @@ -60,6 +63,9 @@ language("rust") , "target.symbols" , "toolchain.linkdirs" , "toolchain.rpathdirs" + , "config.frameworks" + , "target.frameworks" + , "toolchain.frameworks" , "config.links" , "target.links" , "toolchain.links" @@ -68,8 +74,14 @@ language("rust") , "toolchain.syslinks" } , static = { - "target.strip" + "config.linkdirs" + , "target.linkdirs" + , "target.strip" , "target.symbols" + , "toolchain.linkdirs" + , "config.frameworks" + , "target.frameworks" + , "toolchain.frameworks" } } diff --git a/xmake/modules/core/tools/rustc.lua b/xmake/modules/core/tools/rustc.lua index fa358e897..19588136a 100644 --- a/xmake/modules/core/tools/rustc.lua +++ b/xmake/modules/core/tools/rustc.lua @@ -65,6 +65,15 @@ function nf_syslink(self, lib) return nf_link(self, lib) end +-- make the framework flag, crate module +function nf_framework(self, framework) + local basename = path.basename(framework) + local cratename = basename:match("lib(.-)%-.-") or basename:match("lib(.-)") + if cratename then + return {"--extern", cratename .. "=" .. framework} + end +end + -- make the rpathdir flag function nf_rpathdir(self, dir) dir = path.translate(dir) diff --git a/xmake/modules/package/manager/cargo/find_package.lua b/xmake/modules/package/manager/cargo/find_package.lua index 336b4243a..cc546704e 100644 --- a/xmake/modules/package/manager/cargo/find_package.lua +++ b/xmake/modules/package/manager/cargo/find_package.lua @@ -33,21 +33,25 @@ import("lib.detect.find_file") -- function main(name, opt) local linkdirs + local frameworks local librarydir = path.join(opt.installdir, "lib") local libfiles = os.files(path.join(librarydir, "*.rlib")) for _, libraryfile in ipairs(libfiles) do local filename = path.filename(libraryfile) if filename:startswith("lib" .. name .. "-") then linkdirs = linkdirs or {} + frameworks = frameworks or {} table.insert(linkdirs, librarydir) + table.insert(frameworks, libraryfile) break end end local result - if linkdirs then + if frameworks and linkdirs then result = result or {} result.libfiles = libfiles result.linkdirs = linkdirs + result.frameworks = frameworks result.version = opt.require_version end return result diff --git a/xmake/rules/rust/xmake.lua b/xmake/rules/rust/xmake.lua index e0952b72e..f371692e1 100644 --- a/xmake/rules/rust/xmake.lua +++ b/xmake/rules/rust/xmake.lua @@ -36,6 +36,7 @@ rule("rust.build") if cratetype == "staticlib" then assert(target:is_static(), "target(%s) must be static kind for cratetype(staticlib)!", target:name()) target:add("arflags", "--crate-type=staticlib") + target:data_set("inherit.links.exportlinks", false) elseif cratetype == "cdylib" then assert(target:is_shared(), "target(%s) must be shared kind for cratetype(cdylib)!", target:name()) target:add("shflags", "--crate-type=cdylib") diff --git a/xmake/rules/utils/inherit_links/inherit_links.lua b/xmake/rules/utils/inherit_links/inherit_links.lua index 805f535d8..79c737503 100644 --- a/xmake/rules/utils/inherit_links/inherit_links.lua +++ b/xmake/rules/utils/inherit_links/inherit_links.lua @@ -80,11 +80,13 @@ function main(target) -- @note we only export links for static target, -- and we need pass `{public = true}` to add_packages/add_links/... to export it if want to export links for shared target -- - if targetkind == "static" then - for _, name in ipairs({"rpathdirs", "frameworkdirs", "frameworks", "linkdirs", "links", "syslinks"}) do - local values = _get_values_from_target(target, name) - if values and #values > 0 then - target:add(name, values, {public = true}) + if target:data("inherit.links.exportlinks") ~= false then + if targetkind == "static" then + for _, name in ipairs({"rpathdirs", "frameworkdirs", "frameworks", "linkdirs", "links", "syslinks"}) do + local values = _get_values_from_target(target, name) + if values and #values > 0 then + target:add(name, values, {public = true}) + end end end end -- cgit v1.3.1 From 80326fdfb7fa838d3dc79aa24c9dcc01519b173b Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Nov 2021 13:52:57 +0800 Subject: add edition for rust --- tests/projects/rust/cxx_call_rust_library/xmake.lua | 1 - xmake/languages/rust/xmake.lua | 9 +++++++++ xmake/modules/core/tools/rustc.lua | 5 +++++ xmake/modules/package/manager/cargo/find_package.lua | 10 +++++----- xmake/rules/rust/xmake.lua | 5 +++++ 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/tests/projects/rust/cxx_call_rust_library/xmake.lua b/tests/projects/rust/cxx_call_rust_library/xmake.lua index cafd349ee..30d54cc02 100644 --- a/tests/projects/rust/cxx_call_rust_library/xmake.lua +++ b/tests/projects/rust/cxx_call_rust_library/xmake.lua @@ -7,7 +7,6 @@ target("foo") add_files("src/foo.rs") set_values("rust.cratetype", "staticlib") add_packages("cargo::cxx") - add_rcflags("--edition=2018") target("test") set_kind("binary") diff --git a/xmake/languages/rust/xmake.lua b/xmake/languages/rust/xmake.lua index 1335225e3..ea71910b7 100644 --- a/xmake/languages/rust/xmake.lua +++ b/xmake/languages/rust/xmake.lua @@ -39,11 +39,14 @@ language("rust") } , binary = { "config.linkdirs" + , "config.frameworkdirs" , "target.linkdirs" + , "target.frameworkdirs" , "target.rpathdirs" , "target.strip" , "target.symbols" , "toolchain.linkdirs" + , "toolchain.frameworkdirs" , "toolchain.rpathdirs" , "config.frameworks" , "target.frameworks" @@ -57,11 +60,14 @@ language("rust") } , shared = { "config.linkdirs" + , "config.frameworkdirs" , "target.linkdirs" + , "target.frameworkdirs" , "target.rpathdirs" , "target.strip" , "target.symbols" , "toolchain.linkdirs" + , "toolchain.frameworkdirs" , "toolchain.rpathdirs" , "config.frameworks" , "target.frameworks" @@ -75,10 +81,13 @@ language("rust") } , static = { "config.linkdirs" + , "config.frameworkdirs" , "target.linkdirs" + , "target.frameworkdirs" , "target.strip" , "target.symbols" , "toolchain.linkdirs" + , "toolchain.frameworkdirs" , "config.frameworks" , "target.frameworks" , "toolchain.frameworks" diff --git a/xmake/modules/core/tools/rustc.lua b/xmake/modules/core/tools/rustc.lua index 19588136a..ab41620cd 100644 --- a/xmake/modules/core/tools/rustc.lua +++ b/xmake/modules/core/tools/rustc.lua @@ -65,6 +65,11 @@ function nf_syslink(self, lib) return nf_link(self, lib) end +-- make the frameworkdir flag, crate module dependency directories +function nf_frameworkdir(self, frameworkdir) + return {"-L", "dependency=" .. frameworkdir} +end + -- make the framework flag, crate module function nf_framework(self, framework) local basename = path.basename(framework) diff --git a/xmake/modules/package/manager/cargo/find_package.lua b/xmake/modules/package/manager/cargo/find_package.lua index cc546704e..7fd151d5c 100644 --- a/xmake/modules/package/manager/cargo/find_package.lua +++ b/xmake/modules/package/manager/cargo/find_package.lua @@ -32,25 +32,25 @@ import("lib.detect.find_file") -- @param opt the options, e.g. {verbose = true, require_version = "1.12.x") -- function main(name, opt) - local linkdirs + local frameworkdirs local frameworks local librarydir = path.join(opt.installdir, "lib") local libfiles = os.files(path.join(librarydir, "*.rlib")) for _, libraryfile in ipairs(libfiles) do local filename = path.filename(libraryfile) if filename:startswith("lib" .. name .. "-") then - linkdirs = linkdirs or {} + frameworkdirs = frameworkdirs or {} frameworks = frameworks or {} - table.insert(linkdirs, librarydir) + table.insert(frameworkdirs, librarydir) table.insert(frameworks, libraryfile) break end end local result - if frameworks and linkdirs then + if frameworks and frameworkdirs then result = result or {} result.libfiles = libfiles - result.linkdirs = linkdirs + result.frameworkdirs = frameworkdirs result.frameworks = frameworks result.version = opt.require_version end diff --git a/xmake/rules/rust/xmake.lua b/xmake/rules/rust/xmake.lua index f371692e1..e31e2f046 100644 --- a/xmake/rules/rust/xmake.lua +++ b/xmake/rules/rust/xmake.lua @@ -32,6 +32,7 @@ rule("rust.cxxbridge") rule("rust.build") set_sourcekinds("rc") on_load(function (target) + -- set cratetype local cratetype = target:values("rust.cratetype") if cratetype == "staticlib" then assert(target:is_static(), "target(%s) must be static kind for cratetype(staticlib)!", target:name()) @@ -56,6 +57,10 @@ rule("rust.build") elseif target:is_binary() then target:add("ldflags", "--crate-type=bin") end + + -- set edition + local edition = target:values("rust.edition") or "2018" + target:add("rcflags", "--edition", edition, {force = true}) end) on_build("build.target") -- cgit v1.3.1 From f48b0a3fe109284d9bb08a1f5ecb7dee39ff40a2 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Nov 2021 13:58:51 +0800 Subject: update changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 432e5fb03..7599eddfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### New features + +* [#1799](https://github.com/xmake-io/xmake/issues/1799): Support mixed rust & c++ target and cargo dependences + ### Changes * Switch to Lua5.4 runtime by default @@ -1127,6 +1131,10 @@ ## master (开发中) +### 新特性 + +* [#1799](https://github.com/xmake-io/xmake/issues/1799): 支持混合 Rust 和 C++ 程序,以及集成 Cargo 依赖库 + ### 改进 * 默认切换到 Lua5.4 运行时 -- cgit v1.3.1 From c25ecb6bccb5046496d6990f3e4ce3ed64748408 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Nov 2021 14:07:48 +0800 Subject: remove cargo.toml --- tests/projects/rust/cargo_deps/Cargo.toml | 9 --------- tests/projects/rust/cxx_call_rust_library/src/foo.rs | 3 +-- 2 files changed, 1 insertion(+), 11 deletions(-) delete mode 100644 tests/projects/rust/cargo_deps/Cargo.toml diff --git a/tests/projects/rust/cargo_deps/Cargo.toml b/tests/projects/rust/cargo_deps/Cargo.toml deleted file mode 100644 index df461d550..000000000 --- a/tests/projects/rust/cargo_deps/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "cargo_deps" -version = "0.1.0" -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -base64 = "0.13.0" diff --git a/tests/projects/rust/cxx_call_rust_library/src/foo.rs b/tests/projects/rust/cxx_call_rust_library/src/foo.rs index 0c4975fa2..f78bfa99d 100644 --- a/tests/projects/rust/cxx_call_rust_library/src/foo.rs +++ b/tests/projects/rust/cxx_call_rust_library/src/foo.rs @@ -5,8 +5,7 @@ mod foo { } } -pub fn add(a: i32, b: i32) -> i32 -{ +pub fn add(a: i32, b: i32) -> i32 { return a + b; } -- cgit v1.3.1 From f500e8b44d60c9f94fde6d99027a992d1b85e367 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Nov 2021 14:13:24 +0800 Subject: improve rust tests --- tests/projects/rust/console/src/main.rs | 3 +-- tests/projects/rust/cxx_call_rust_library/src/main.cc | 3 +-- tests/projects/rust/rust_call_cxx_library/src/foo.cc | 3 +-- tests/projects/rust/shared_library/src/foo.rs | 3 +-- tests/projects/rust/shared_library/src/main.rs | 3 +-- tests/projects/rust/static_library/src/foo.rs | 3 +-- tests/projects/rust/static_library/src/main.rs | 4 +--- xmake/templates/rust/console/project/src/main.rs | 3 +-- xmake/templates/rust/static/project/src/foo.rs | 3 +-- xmake/templates/rust/static/project/src/main.rs | 3 +-- 10 files changed, 10 insertions(+), 21 deletions(-) diff --git a/tests/projects/rust/console/src/main.rs b/tests/projects/rust/console/src/main.rs index e8d2ae9b2..88d5e2749 100644 --- a/tests/projects/rust/console/src/main.rs +++ b/tests/projects/rust/console/src/main.rs @@ -1,4 +1,3 @@ -fn main() -{ +fn main() { println!("hello xmake!"); } diff --git a/tests/projects/rust/cxx_call_rust_library/src/main.cc b/tests/projects/rust/cxx_call_rust_library/src/main.cc index c0d600fd3..d79b319f9 100644 --- a/tests/projects/rust/cxx_call_rust_library/src/main.cc +++ b/tests/projects/rust/cxx_call_rust_library/src/main.cc @@ -1,8 +1,7 @@ #include #include "bridge.rs.h" -int main(int argc, char** argv) -{ +int main(int argc, char** argv) { printf("add(1, 2) == %d\n", add(1, 2)); return 0; } diff --git a/tests/projects/rust/rust_call_cxx_library/src/foo.cc b/tests/projects/rust/rust_call_cxx_library/src/foo.cc index 9d989119e..bb2eb9292 100644 --- a/tests/projects/rust/rust_call_cxx_library/src/foo.cc +++ b/tests/projects/rust/rust_call_cxx_library/src/foo.cc @@ -1,4 +1,3 @@ -extern "C" int add(int a, int b) -{ +extern "C" int add(int a, int b) { return a + b; } diff --git a/tests/projects/rust/shared_library/src/foo.rs b/tests/projects/rust/shared_library/src/foo.rs index 277008ba4..a3a3aa4a6 100644 --- a/tests/projects/rust/shared_library/src/foo.rs +++ b/tests/projects/rust/shared_library/src/foo.rs @@ -1,5 +1,4 @@ -pub fn add(a: i32, b: i32) -> i32 -{ +pub fn add(a: i32, b: i32) -> i32 { return a + b; } diff --git a/tests/projects/rust/shared_library/src/main.rs b/tests/projects/rust/shared_library/src/main.rs index 24f23d84b..205d23da3 100644 --- a/tests/projects/rust/shared_library/src/main.rs +++ b/tests/projects/rust/shared_library/src/main.rs @@ -1,7 +1,6 @@ extern crate foo; -fn main() -{ +fn main() { println!("hello xmake!"); println!("add: {}", foo::add(1, 1)); } diff --git a/tests/projects/rust/static_library/src/foo.rs b/tests/projects/rust/static_library/src/foo.rs index 277008ba4..a3a3aa4a6 100644 --- a/tests/projects/rust/static_library/src/foo.rs +++ b/tests/projects/rust/static_library/src/foo.rs @@ -1,5 +1,4 @@ -pub fn add(a: i32, b: i32) -> i32 -{ +pub fn add(a: i32, b: i32) -> i32 { return a + b; } diff --git a/tests/projects/rust/static_library/src/main.rs b/tests/projects/rust/static_library/src/main.rs index 24f23d84b..de8604a65 100644 --- a/tests/projects/rust/static_library/src/main.rs +++ b/tests/projects/rust/static_library/src/main.rs @@ -1,7 +1,5 @@ extern crate foo; - -fn main() -{ +fn main() { println!("hello xmake!"); println!("add: {}", foo::add(1, 1)); } diff --git a/xmake/templates/rust/console/project/src/main.rs b/xmake/templates/rust/console/project/src/main.rs index fe3b8813c..88d5e2749 100644 --- a/xmake/templates/rust/console/project/src/main.rs +++ b/xmake/templates/rust/console/project/src/main.rs @@ -1,4 +1,3 @@ -fn main() -{ +fn main() { println!("hello xmake!"); } diff --git a/xmake/templates/rust/static/project/src/foo.rs b/xmake/templates/rust/static/project/src/foo.rs index 277008ba4..a3a3aa4a6 100644 --- a/xmake/templates/rust/static/project/src/foo.rs +++ b/xmake/templates/rust/static/project/src/foo.rs @@ -1,5 +1,4 @@ -pub fn add(a: i32, b: i32) -> i32 -{ +pub fn add(a: i32, b: i32) -> i32 { return a + b; } diff --git a/xmake/templates/rust/static/project/src/main.rs b/xmake/templates/rust/static/project/src/main.rs index 24f23d84b..205d23da3 100644 --- a/xmake/templates/rust/static/project/src/main.rs +++ b/xmake/templates/rust/static/project/src/main.rs @@ -1,7 +1,6 @@ extern crate foo; -fn main() -{ +fn main() { println!("hello xmake!"); println!("add: {}", foo::add(1, 1)); } -- cgit v1.3.1 From 7a08a27b135bd606bce98c8641b9800269554137 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Nov 2021 14:17:49 +0800 Subject: update readme --- README.md | 1 + README_zh.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 296f1d4b7..c922cd554 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,7 @@ The test project: [xmake-core](https://github.com/xmake-io/xmake/tree/master/cor * Dub (dub::log 0.4.3) * Portage on Gentoo/Linux (portage::libhandy) * Nimble for nimlang (nimble::zip >1.3) +* Cargo for rust (cargo::base64 0.13.0) ### Package management features diff --git a/README_zh.md b/README_zh.md index 05c8b39e6..806f25274 100644 --- a/README_zh.md +++ b/README_zh.md @@ -195,6 +195,7 @@ $ xmake f --menu * Dub (dub::log 0.4.3) * Portage on Gentoo/Linux (portage::libhandy) * Nimble for nimlang (nimble::zip >1.3) +* Cargo for rust (cargo::base64 0.13.0) ### 包管理特性 -- cgit v1.3.1 From 13fd7fc7dd6a554e3304e85074bdaa82c19ddec7 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Nov 2021 14:54:02 +0800 Subject: improve cargo package version --- xmake/modules/package/manager/cargo/install_package.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xmake/modules/package/manager/cargo/install_package.lua b/xmake/modules/package/manager/cargo/install_package.lua index a500bb6a7..0f06a8f6b 100644 --- a/xmake/modules/package/manager/cargo/install_package.lua +++ b/xmake/modules/package/manager/cargo/install_package.lua @@ -53,7 +53,10 @@ function main(name, opt) end -- get required version - local require_version = assert(opt.require_version, "cargo::%s version not found!", name) + local require_version = opt.require_version + if not require_version or require_version == "latest" then + require_version = "*" + end -- build dependencies local sourcedir = path.join(opt.cachedir, "source") -- cgit v1.3.1 From c5a673cd097db197d81debadf693cb4e2866ac17 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 13 Nov 2021 23:08:12 +0800 Subject: show architectures --- xmake/plugins/show/lists/architectures.lua | 51 ++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 xmake/plugins/show/lists/architectures.lua diff --git a/xmake/plugins/show/lists/architectures.lua b/xmake/plugins/show/lists/architectures.lua new file mode 100644 index 000000000..8eba152f2 --- /dev/null +++ b/xmake/plugins/show/lists/architectures.lua @@ -0,0 +1,51 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file platforms.lua +-- + +-- imports +import("core.project.project") +import("core.platform.platform") +import("core.base.text") + +-- show all platforms +function main() + + -- get all platforms + local plats = try {function () return project.allowed_plats() end} + if plats then + plats = plats:to_array() + end + plats = plats or platform.plats() + + -- get all architectures + local result = {align = 'l', sep = " "} + for i, plat in ipairs(plats) do + local archs = try {function () return project.allowed_archs(plat) end} + if archs then + archs = archs:to_array() + end + if not archs then + archs = platform.archs(plat) + end + if archs and #archs > 0 then + table.insert(result, table.join(plat, archs)) + end + end + print(text.table(result)) +end -- cgit v1.3.1 From 3a6d721b691b8235dd6189d6e24a59537640f702 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 14 Nov 2021 22:28:59 +0800 Subject: improve on_fetch --- xmake/core/package/package.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index d5d683741..2d7534878 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -1227,6 +1227,10 @@ function _instance:_fetch_library(opt) fetchinfo.sysincludedirs = nil end end + if fetchinfo and option.get("verbose") then + local reponame = self:repo() and self:repo():name() or "" + utils.cprint("checking for %s::%s ... ${color.success}%s %s", reponame, self:name(), self:name(), fetchinfo.version and fetchinfo.version or "") + end end if fetchinfo == nil then if opt.system then -- cgit v1.3.1 From 8ea70c741c233e8ddc1523cc8f2e91eb7baa2de7 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 14 Nov 2021 22:51:32 +0800 Subject: add table.remove_if --- tests/modules/table/test.lua | 4 +++ xmake/core/base/table.lua | 60 +++++++++++++++++++++----------------------- 2 files changed, 33 insertions(+), 31 deletions(-) create mode 100644 tests/modules/table/test.lua diff --git a/tests/modules/table/test.lua b/tests/modules/table/test.lua new file mode 100644 index 000000000..fc17fcb62 --- /dev/null +++ b/tests/modules/table/test.lua @@ -0,0 +1,4 @@ +function test_remove_if(t) + t:are_equal(table.remove_if({1, 2, 3, 4, 5, 6}, function (t, i, v) return (v % 2) == 0 end), {1, 3, 5}) + t:are_equal(table.remove_if({a = 1, b = 2, c = 3}, function (t, i, v) return (v % 2) == 0 end), {a = 1, c = 3}) +end diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua index 21fa185a0..4f59e7a65 100644 --- a/xmake/core/base/table.lua +++ b/xmake/core/base/table.lua @@ -276,9 +276,6 @@ end -- usage: table.to_array(ipairs("a", "b")) -> {{1,"a",n=2},{2,"b",n=2}},2 -- usage: table.to_array(io.lines("file")) -> {"line 1","line 2", ... , "line n"},n function table.to_array(iterator, state, var) - - assert(iterator) - local result = {} local count = 0 while true do @@ -383,13 +380,10 @@ end table.unpack = table.unpack or unpack -- get keys of a table -function table.keys(tab) - - assert(tab) - +function table.keys(tbl) local keyset = {} local n = 0 - for k, _ in pairs(tab) do + for k, _ in pairs(tbl) do n = n + 1 keyset[n] = k end @@ -397,8 +391,8 @@ function table.keys(tab) end -- get order keys of a table -function table.orderkeys(tab) - local keys = table.keys(tab) +function table.orderkeys(tbl) + local keys = table.keys(tbl) table.sort(keys) return keys end @@ -419,13 +413,10 @@ function table.orderpairs(t) end -- get values of a table -function table.values(tab) - - assert(tab) - +function table.values(tbl) local valueset = {} local n = 0 - for _, v in pairs(tab) do + for _, v in pairs(tbl) do n = n + 1 valueset[n] = v end @@ -433,24 +424,16 @@ function table.values(tab) end -- map values to a new table -function table.map(tab, mapper) - - assert(tab) - assert(mapper) - - local newtab = {} - for k, v in pairs(tab) do - newtab[k] = mapper(k, v) +function table.map(tbl, mapper) + local newtbl = {} + for k, v in pairs(tbl) do + newtbl[k] = mapper(k, v) end - return newtab + return newtbl end -- map values to a new array function table.imap(arr, mapper) - - assert(arr) - assert(mapper) - local newarr = {} for k, v in ipairs(arr) do table.insert(newarr, mapper(k, v)) @@ -460,9 +443,6 @@ end -- reverse table values function table.reverse(arr) - - assert(arr) - local revarr = {} local l = #arr for i = 1, l do @@ -471,5 +451,23 @@ function table.reverse(arr) return revarr end +-- remove values if predicate is matched +function table.remove_if(tbl, pred) + if table.is_array(tbl) then + for i = #tbl, 1, -1 do + if pred(tbl, i, tbl[i]) then + table.remove(tbl, i) + end + end + else + for k, v in pairs(tbl) do + if pred(tbl, k, v) then + tbl[k] = nil + end + end + end + return tbl +end + -- return module: table return table -- cgit v1.3.1 From 474998e342c779f71ff5591ddc936304411fa46a Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 14 Nov 2021 23:25:19 +0800 Subject: add table.find_xxx --- tests/modules/table/test.lua | 11 ++++++-- xmake/core/base/table.lua | 64 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/tests/modules/table/test.lua b/tests/modules/table/test.lua index fc17fcb62..5ed17620c 100644 --- a/tests/modules/table/test.lua +++ b/tests/modules/table/test.lua @@ -1,4 +1,11 @@ function test_remove_if(t) - t:are_equal(table.remove_if({1, 2, 3, 4, 5, 6}, function (t, i, v) return (v % 2) == 0 end), {1, 3, 5}) - t:are_equal(table.remove_if({a = 1, b = 2, c = 3}, function (t, i, v) return (v % 2) == 0 end), {a = 1, c = 3}) + t:are_equal(table.remove_if({1, 2, 3, 4, 5, 6}, function (i, v) return (v % 2) == 0 end), {1, 3, 5}) + t:are_equal(table.remove_if({a = 1, b = 2, c = 3}, function (i, v) return (v % 2) == 0 end), {a = 1, c = 3}) +end + +function test_find_if(t) + t:are_equal(table.find_if({1, 2, 3, 4, 5, 6}, function (i, v) return (v % 2) == 0 end), {2, 4, 6}) + t:are_equal(table.find_first_if({1, 2, 3, 4, 5, 6}, function (i, v) return (v % 2) == 0 end), 2) + t:are_equal(table.find({1, 2, 4, 4, 5, 6}, 4), {3, 4}) + t:are_equal(table.find_first({1, 2, 3, 4, 5, 6}, 4), 4) end diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua index 4f59e7a65..2bf776151 100644 --- a/xmake/core/base/table.lua +++ b/xmake/core/base/table.lua @@ -455,13 +455,13 @@ end function table.remove_if(tbl, pred) if table.is_array(tbl) then for i = #tbl, 1, -1 do - if pred(tbl, i, tbl[i]) then + if pred(i, tbl[i]) then table.remove(tbl, i) end end else for k, v in pairs(tbl) do - if pred(tbl, k, v) then + if pred(k, v) then tbl[k] = nil end end @@ -469,5 +469,65 @@ function table.remove_if(tbl, pred) return tbl end +-- return indices or keys for the given value +function table.find(tbl, value) + local result + if table.is_array(tbl) then + for i, v in ipairs(tbl) do + if v == value then + result = result or {} + table.insert(result, i) + end + end + else + for k, v in pairs(tbl) do + if v == value then + result = result or {} + table.insert(result, k) + end + end + end + return result +end + +-- return indices or keys if predicate is matched +function table.find_if(tbl, pred) + local result + if table.is_array(tbl) then + for i, v in ipairs(tbl) do + if pred(i, v) then + result = result or {} + table.insert(result, i) + end + end + else + for k, v in pairs(tbl) do + if pred(k, v) then + result = result or {} + table.insert(result, k) + end + end + end + return result +end + +-- return first index for the given value +function table.find_first(tbl, value) + for i, v in ipairs(tbl) do + if v == value then + return i + end + end +end + +-- return first index if predicate is matched +function table.find_first_if(tbl, pred) + for i, v in ipairs(tbl) do + if pred(i, v) then + return i + end + end +end + -- return module: table return table -- cgit v1.3.1 From f8679754274d3b7d7897d81387d36d1df9921056 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 15 Nov 2021 21:04:00 +0800 Subject: support buildcmd --- xmake/actions/build/build.lua | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/xmake/actions/build/build.lua b/xmake/actions/build/build.lua index c3817fb0a..38e95f4b1 100644 --- a/xmake/actions/build/build.lua +++ b/xmake/actions/build/build.lua @@ -24,6 +24,7 @@ import("core.project.config") import("core.project.project") import("private.async.jobpool") import("private.async.runjobs") +import("private.utils.batchcmds") import("core.base.hashset") -- clean target for rebuilding @@ -49,6 +50,15 @@ function _add_batchjobs_builtin(batchjobs, rootjob, target) script(target, {progress = (index * 100) / total}) end, {rootjob = job or rootjob}) end + else + local buildcmd = r:script("buildcmd") + if buildcmd then + job = batchjobs:addjob("rule/" .. r:name() .. "/build", function (index, total) + local batchcmds_ = batchcmds.new({target = target}) + buildcmd(target, batchcmds_, {progress = (index * 100) / total}) + batchcmds_:runcmds({dryrun = option.get("dry-run")}) + end, {rootjob = job or rootjob}) + end end end @@ -117,6 +127,13 @@ function _add_batchjobs_for_target(batchjobs, rootjob, target) local after_build = r:script("build_after") if after_build then after_build(target, {progress = progress}) + else + local after_buildcmd = r:script("buildcmd_after") + if after_buildcmd then + local batchcmds_ = batchcmds.new({target = target}) + after_buildcmd(target, batchcmds_, {progress = progress}) + batchcmds_:runcmds({dryrun = option.get("dry-run")}) + end end end @@ -151,6 +168,13 @@ function _add_batchjobs_for_target(batchjobs, rootjob, target) local before_build = r:script("build_before") if before_build then before_build(target, {progress = progress}) + else + local before_buildcmd = r:script("buildcmd_before") + if before_buildcmd then + local batchcmds_ = batchcmds.new({target = target}) + before_buildcmd(target, batchcmds_, {progress = progress}) + batchcmds_:runcmds({dryrun = option.get("dry-run")}) + end end end end, {rootjob = job_build_leaf}) -- cgit v1.3.1 From f31338f204618c41ebadede7f99b15a0d2bb61a5 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 15 Nov 2021 21:38:01 +0800 Subject: add custom commands for vs --- xmake/plugins/project/vstudio/impl/vs201x.lua | 1 + .../project/vstudio/impl/vs201x_vcxproj.lua | 124 +++++++++++++++++++++ 2 files changed, 125 insertions(+) diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua index da0dd9317..7101c3331 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x.lua @@ -330,6 +330,7 @@ function make(outputdir, vsinfo) _target.pcxxheader = target:pcheaderfile("cxx") -- header.[hpp|inl] -- init target info + _target.targetinst = target _target.name = targetname _target.kind = target:kind() _target.scriptdir = target:scriptdir() diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index b1bd6f764..1a55eb551 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -20,7 +20,9 @@ -- imports import("core.project.config") +import("core.project.project") import("core.language.language") +import("private.utils.batchcmds") import("vsfile") -- get toolset version @@ -369,6 +371,125 @@ function _make_source_options(vcxprojfile, flags, condition) end end +-- get command string +function _get_command_string(cmd) + local kind = cmd.kind + local opt = cmd.opt + if cmd.program then + elseif kind == "cp" then + elseif kind == "rm" then + elseif kind == "mv" then + elseif kind == "cd" then + elseif kind == "mkdir" then + elseif kind == "show" then + return string.format("echo %s", cmd.showtext) + end +end + +-- add custom command +function _make_custom_command(vcxprojfile, target, command, suffix) + if suffix == "after" then + vcxprojfile:print("") + elseif suffix == "before" then + vcxprojfile:print("") + end + vcxprojfile:print("") + vcxprojfile:print("setlocal") + vcxprojfile:print("%s", command) + vcxprojfile:write([[if %errorlevel% neq 0 goto :xmEnd +:xmEnd +endlocal & call :xmErrorLevel %errorlevel% & goto :xmDone +:xmErrorLevel +exit /b %1 +:xmDone +if %errorlevel% neq 0 goto :VCEnd +]]) + if suffix == "after" then + vcxprojfile:print("") + elseif suffix == "before" then + vcxprojfile:print("") + end +end + +-- add target custom commands for target +function _make_custom_commands_for_target(vcxprojfile, target, suffix) + for _, ruleinst in ipairs(target:orderules()) do + local scriptname = "buildcmd" .. (suffix and ("_" .. suffix) or "") + local script = ruleinst:script(scriptname) + if script then + local batchcmds_ = batchcmds.new({target = target}) + script(target, batchcmds_, {}) + if not batchcmds_:empty() then + for _, cmd in ipairs(batchcmds_:cmds()) do + local command = _get_command_string(cmd) + if command then + _make_custom_command(vcxprojfile, target, command, suffix) + end + end + end + end + end +end + +-- add target custom commands for object rules +function _make_custom_commands_for_objectrules(vcxprojfile, target, sourcebatch, suffix) + + -- get rule + local rulename = assert(sourcebatch.rulename, "unknown rule for sourcebatch!") + local ruleinst = assert(project.rule(rulename) or rule.rule(rulename), "unknown rule: %s", rulename) + + -- generate commands for xx_buildcmd_files + local scriptname = "buildcmd_files" .. (suffix and ("_" .. suffix) or "") + local script = ruleinst:script(scriptname) + if script then + local batchcmds_ = batchcmds.new({target = target}) + script(target, batchcmds_, sourcebatch, {}) + if not batchcmds_:empty() then + for _, cmd in ipairs(batchcmds_:cmds()) do + local command = _get_command_string(cmd) + if command then + _make_custom_command(vcxprojfile, target, command, suffix) + end + end + end + end + + -- generate commands for xx_buildcmd_file + if not script then + scriptname = "buildcmd_file" .. (suffix and ("_" .. suffix) or "") + script = ruleinst:script(scriptname) + if script then + local sourcekind = sourcebatch.sourcekind + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local batchcmds_ = batchcmds.new({target = target}) + script(target, batchcmds_, sourcefile, {}) + if not batchcmds_:empty() then + for _, cmd in ipairs(batchcmds_:cmds()) do + local command = _get_command_string(cmd) + if command then + _make_custom_command(vcxprojfile, target, command, suffix) + end + end + end + end + end + end +end + +-- make custom commands +function _make_custom_commands(vcxprojfile, target) + _make_custom_commands_for_target(vcxprojfile, target, "before") + for _, sourcebatch in pairs(target:sourcebatches()) do + local sourcekind = sourcebatch.sourcekind + if sourcekind ~= "cc" and sourcekind ~= "cxx" and sourcekind ~= "as" then + _make_custom_commands_for_objectrules(vcxprojfile, target, sourcebatch, "before") + _make_custom_commands_for_objectrules(vcxprojfile, target, sourcebatch) + _make_custom_commands_for_objectrules(vcxprojfile, target, sourcebatch, "after") + end + end + _make_custom_commands_for_target(vcxprojfile, target, "after") +end + -- make common item function _make_common_item(vcxprojfile, vsinfo, target, targetinfo, vcxprojdir) @@ -456,6 +577,9 @@ function _make_common_item(vcxprojfile, vsinfo, target, targetinfo, vcxprojdir) vcxprojfile:leave("") + -- make custom commands + _make_custom_commands(vcxprojfile, target.targetinst) + -- leave ItemDefinitionGroup vcxprojfile:leave("") end -- cgit v1.3.1 From 0f6b878602f3d8e003b51ff34f9d12e6653129a9 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 15 Nov 2021 22:01:20 +0800 Subject: improve custom commands for vs --- .../project/vstudio/impl/vs201x_vcxproj.lua | 43 ++++++++++++++-------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index 1a55eb551..b7bc9c728 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -386,8 +386,9 @@ function _get_command_string(cmd) end end --- add custom command -function _make_custom_command(vcxprojfile, target, command, suffix) +-- make custom commands item +function _make_custom_commands_item(vcxprojfile, commands, suffix) + vcxprojfile:print("") if suffix == "after" then vcxprojfile:print("") elseif suffix == "before" then @@ -395,7 +396,9 @@ function _make_custom_command(vcxprojfile, target, command, suffix) end vcxprojfile:print("") vcxprojfile:print("setlocal") - vcxprojfile:print("%s", command) + for _, command in ipairs(commands) do + vcxprojfile:print("%s", command) + end vcxprojfile:write([[if %errorlevel% neq 0 goto :xmEnd :xmEnd endlocal & call :xmErrorLevel %errorlevel% & goto :xmDone @@ -409,10 +412,11 @@ if %errorlevel% neq 0 goto :VCEnd elseif suffix == "before" then vcxprojfile:print("") end + vcxprojfile:print("") end -- add target custom commands for target -function _make_custom_commands_for_target(vcxprojfile, target, suffix) +function _make_custom_commands_for_target(commands, target, suffix) for _, ruleinst in ipairs(target:orderules()) do local scriptname = "buildcmd" .. (suffix and ("_" .. suffix) or "") local script = ruleinst:script(scriptname) @@ -423,7 +427,8 @@ function _make_custom_commands_for_target(vcxprojfile, target, suffix) for _, cmd in ipairs(batchcmds_:cmds()) do local command = _get_command_string(cmd) if command then - _make_custom_command(vcxprojfile, target, command, suffix) + commands[suffix] = commands[suffix] or {} + table.insert(commands[suffix], command) end end end @@ -432,7 +437,7 @@ function _make_custom_commands_for_target(vcxprojfile, target, suffix) end -- add target custom commands for object rules -function _make_custom_commands_for_objectrules(vcxprojfile, target, sourcebatch, suffix) +function _make_custom_commands_for_objectrules(commands, target, sourcebatch, suffix) -- get rule local rulename = assert(sourcebatch.rulename, "unknown rule for sourcebatch!") @@ -448,7 +453,8 @@ function _make_custom_commands_for_objectrules(vcxprojfile, target, sourcebatch, for _, cmd in ipairs(batchcmds_:cmds()) do local command = _get_command_string(cmd) if command then - _make_custom_command(vcxprojfile, target, command, suffix) + commands[suffix] = commands[suffix] or {} + table.insert(commands[suffix], command) end end end @@ -467,7 +473,8 @@ function _make_custom_commands_for_objectrules(vcxprojfile, target, sourcebatch, for _, cmd in ipairs(batchcmds_:cmds()) do local command = _get_command_string(cmd) if command then - _make_custom_command(vcxprojfile, target, command, suffix) + commands[suffix] = commands[suffix] or {} + table.insert(commands[suffix], command) end end end @@ -478,16 +485,20 @@ end -- make custom commands function _make_custom_commands(vcxprojfile, target) - _make_custom_commands_for_target(vcxprojfile, target, "before") + local commands = {} + _make_custom_commands_for_target(commands, target, "before") for _, sourcebatch in pairs(target:sourcebatches()) do local sourcekind = sourcebatch.sourcekind if sourcekind ~= "cc" and sourcekind ~= "cxx" and sourcekind ~= "as" then - _make_custom_commands_for_objectrules(vcxprojfile, target, sourcebatch, "before") - _make_custom_commands_for_objectrules(vcxprojfile, target, sourcebatch) - _make_custom_commands_for_objectrules(vcxprojfile, target, sourcebatch, "after") + _make_custom_commands_for_objectrules(commands, target, sourcebatch, "before") + _make_custom_commands_for_objectrules(commands, target, sourcebatch) + _make_custom_commands_for_objectrules(commands, target, sourcebatch, "after") end end - _make_custom_commands_for_target(vcxprojfile, target, "after") + _make_custom_commands_for_target(commands, target, "after") + for suffix, cmds in pairs(commands) do + _make_custom_commands_item(vcxprojfile, cmds, suffix) + end end -- make common item @@ -577,9 +588,6 @@ function _make_common_item(vcxprojfile, vsinfo, target, targetinfo, vcxprojdir) vcxprojfile:leave("") - -- make custom commands - _make_custom_commands(vcxprojfile, target.targetinst) - -- leave ItemDefinitionGroup vcxprojfile:leave("") end @@ -913,6 +921,9 @@ function make(vsinfo, target) -- make common items _make_common_items(vcxprojfile, vsinfo, target, vcxprojdir) + -- make custom commands + _make_custom_commands(vcxprojfile, target.targetinst) + -- make source files _make_source_files(vcxprojfile, vsinfo, target, vcxprojdir) -- cgit v1.3.1 From 6d4d034345f2332b47d8149322fea4237d53978f Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 15 Nov 2021 22:52:04 +0800 Subject: fix rule --- xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index b7bc9c728..25bfad70a 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -19,6 +19,7 @@ -- -- imports +import("core.project.rule") import("core.project.config") import("core.project.project") import("core.language.language") @@ -376,11 +377,21 @@ function _get_command_string(cmd) local kind = cmd.kind local opt = cmd.opt if cmd.program then + local command = os.args(table.join(cmd.program, cmd.argv)) + if opt and opt.curdir then + command = "cd \"" .. opt.curdir .. "\"\n" .. command + end + return command elseif kind == "cp" then + return string.format("copy /Y \"%s\" \"%s\"", cmd.srcpath, cmd.dstpath) elseif kind == "rm" then + return string.format("del /F /Q \"%s\" || rmdir /S /Q \"%s\"", cmd.filepath, cmd.filepath) elseif kind == "mv" then + return string.format("rename \"%s\" \"%s\"", cmd.srcpath, cmd.dstpath) elseif kind == "cd" then + return string.format("cd \"%s\"", cmd.dir) elseif kind == "mkdir" then + return string.format("mkdir \"%s\"", cmd.dir) elseif kind == "show" then return string.format("echo %s", cmd.showtext) end -- cgit v1.3.1 From 526ffd93c0bb0bfcaf73c9e3109cdcce291f916d Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 15 Nov 2021 22:57:50 +0800 Subject: improve custom commands --- xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index 25bfad70a..b5caf100c 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -399,7 +399,6 @@ end -- make custom commands item function _make_custom_commands_item(vcxprojfile, commands, suffix) - vcxprojfile:print("") if suffix == "after" then vcxprojfile:print("") elseif suffix == "before" then @@ -423,7 +422,6 @@ if %errorlevel% neq 0 goto :VCEnd elseif suffix == "before" then vcxprojfile:print("") end - vcxprojfile:print("") end -- add target custom commands for target @@ -599,6 +597,9 @@ function _make_common_item(vcxprojfile, vsinfo, target, targetinfo, vcxprojdir) vcxprojfile:leave("") + -- make custom commands + _make_custom_commands(vcxprojfile, target.targetinst) + -- leave ItemDefinitionGroup vcxprojfile:leave("") end @@ -932,9 +933,6 @@ function make(vsinfo, target) -- make common items _make_common_items(vcxprojfile, vsinfo, target, vcxprojdir) - -- make custom commands - _make_custom_commands(vcxprojfile, target.targetinst) - -- make source files _make_source_files(vcxprojfile, vsinfo, target, vcxprojdir) -- cgit v1.3.1 From 339c48a72a3708f19b74036d3fc5811e63f157f3 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 15 Nov 2021 23:15:46 +0800 Subject: fix custom command for mode and arch --- xmake/plugins/project/vstudio/impl/vs201x.lua | 115 ++++++++++++++++++++- .../project/vstudio/impl/vs201x_vcxproj.lua | 108 +------------------ 2 files changed, 116 insertions(+), 107 deletions(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua index 7101c3331..11803cf45 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x.lua @@ -20,6 +20,7 @@ -- imports import("core.base.option") +import("core.project.rule") import("core.project.config") import("core.project.project") import("core.platform.platform") @@ -34,6 +35,7 @@ import("core.cache.localcache") import("private.action.require.install", {alias = "install_requires"}) import("actions.config.configfiles", {alias = "generate_configfiles", rootdir = os.programdir()}) import("actions.config.configheader", {alias = "generate_configheader", rootdir = os.programdir()}) +import("private.utils.batchcmds") -- clear cache configuration function _clear_cacheconf() @@ -47,6 +49,115 @@ function _clear_cacheconf() localcache.save() end +-- get command string +function _get_command_string(cmd) + local kind = cmd.kind + local opt = cmd.opt + if cmd.program then + local command = os.args(table.join(cmd.program, cmd.argv)) + if opt and opt.curdir then + command = "cd \"" .. opt.curdir .. "\"\n" .. command + end + return command + elseif kind == "cp" then + return string.format("copy /Y \"%s\" \"%s\"", cmd.srcpath, cmd.dstpath) + elseif kind == "rm" then + return string.format("del /F /Q \"%s\" || rmdir /S /Q \"%s\"", cmd.filepath, cmd.filepath) + elseif kind == "mv" then + return string.format("rename \"%s\" \"%s\"", cmd.srcpath, cmd.dstpath) + elseif kind == "cd" then + return string.format("cd \"%s\"", cmd.dir) + elseif kind == "mkdir" then + return string.format("mkdir \"%s\"", cmd.dir) + elseif kind == "show" then + return string.format("echo %s", cmd.showtext) + end +end + +-- add target custom commands for target +function _make_custom_commands_for_target(commands, target, suffix) + for _, ruleinst in ipairs(target:orderules()) do + local scriptname = "buildcmd" .. (suffix and ("_" .. suffix) or "") + local script = ruleinst:script(scriptname) + if script then + local batchcmds_ = batchcmds.new({target = target}) + script(target, batchcmds_, {}) + if not batchcmds_:empty() then + for _, cmd in ipairs(batchcmds_:cmds()) do + local command = _get_command_string(cmd) + if command then + commands[suffix] = commands[suffix] or {} + table.insert(commands[suffix], command) + end + end + end + end + end +end + +-- add target custom commands for object rules +function _make_custom_commands_for_objectrules(commands, target, sourcebatch, suffix) + + -- get rule + local rulename = assert(sourcebatch.rulename, "unknown rule for sourcebatch!") + local ruleinst = assert(project.rule(rulename) or rule.rule(rulename), "unknown rule: %s", rulename) + + -- generate commands for xx_buildcmd_files + local scriptname = "buildcmd_files" .. (suffix and ("_" .. suffix) or "") + local script = ruleinst:script(scriptname) + if script then + local batchcmds_ = batchcmds.new({target = target}) + script(target, batchcmds_, sourcebatch, {}) + if not batchcmds_:empty() then + for _, cmd in ipairs(batchcmds_:cmds()) do + local command = _get_command_string(cmd) + if command then + commands[suffix] = commands[suffix] or {} + table.insert(commands[suffix], command) + end + end + end + end + + -- generate commands for xx_buildcmd_file + if not script then + scriptname = "buildcmd_file" .. (suffix and ("_" .. suffix) or "") + script = ruleinst:script(scriptname) + if script then + local sourcekind = sourcebatch.sourcekind + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local batchcmds_ = batchcmds.new({target = target}) + script(target, batchcmds_, sourcefile, {}) + if not batchcmds_:empty() then + for _, cmd in ipairs(batchcmds_:cmds()) do + local command = _get_command_string(cmd) + if command then + commands[suffix] = commands[suffix] or {} + table.insert(commands[suffix], command) + end + end + end + end + end + end +end + +-- make custom commands +function _make_custom_commands(target) + local commands = {} + _make_custom_commands_for_target(commands, target, "before") + for _, sourcebatch in pairs(target:sourcebatches()) do + local sourcekind = sourcebatch.sourcekind + if sourcekind ~= "cc" and sourcekind ~= "cxx" and sourcekind ~= "as" then + _make_custom_commands_for_objectrules(commands, target, sourcebatch, "before") + _make_custom_commands_for_objectrules(commands, target, sourcebatch) + _make_custom_commands_for_objectrules(commands, target, sourcebatch, "after") + end + end + _make_custom_commands_for_target(commands, target, "after") + return commands +end + -- make target info function _make_targetinfo(mode, arch, target) @@ -126,6 +237,9 @@ function _make_targetinfo(mode, arch, target) end end + -- save custom commands + targetinfo.commands = _make_custom_commands(target) + -- ok return targetinfo end @@ -330,7 +444,6 @@ function make(outputdir, vsinfo) _target.pcxxheader = target:pcheaderfile("cxx") -- header.[hpp|inl] -- init target info - _target.targetinst = target _target.name = targetname _target.kind = target:kind() _target.scriptdir = target:scriptdir() diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index b5caf100c..93e8633d9 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -372,31 +372,6 @@ function _make_source_options(vcxprojfile, flags, condition) end end --- get command string -function _get_command_string(cmd) - local kind = cmd.kind - local opt = cmd.opt - if cmd.program then - local command = os.args(table.join(cmd.program, cmd.argv)) - if opt and opt.curdir then - command = "cd \"" .. opt.curdir .. "\"\n" .. command - end - return command - elseif kind == "cp" then - return string.format("copy /Y \"%s\" \"%s\"", cmd.srcpath, cmd.dstpath) - elseif kind == "rm" then - return string.format("del /F /Q \"%s\" || rmdir /S /Q \"%s\"", cmd.filepath, cmd.filepath) - elseif kind == "mv" then - return string.format("rename \"%s\" \"%s\"", cmd.srcpath, cmd.dstpath) - elseif kind == "cd" then - return string.format("cd \"%s\"", cmd.dir) - elseif kind == "mkdir" then - return string.format("mkdir \"%s\"", cmd.dir) - elseif kind == "show" then - return string.format("echo %s", cmd.showtext) - end -end - -- make custom commands item function _make_custom_commands_item(vcxprojfile, commands, suffix) if suffix == "after" then @@ -424,88 +399,9 @@ if %errorlevel% neq 0 goto :VCEnd end end --- add target custom commands for target -function _make_custom_commands_for_target(commands, target, suffix) - for _, ruleinst in ipairs(target:orderules()) do - local scriptname = "buildcmd" .. (suffix and ("_" .. suffix) or "") - local script = ruleinst:script(scriptname) - if script then - local batchcmds_ = batchcmds.new({target = target}) - script(target, batchcmds_, {}) - if not batchcmds_:empty() then - for _, cmd in ipairs(batchcmds_:cmds()) do - local command = _get_command_string(cmd) - if command then - commands[suffix] = commands[suffix] or {} - table.insert(commands[suffix], command) - end - end - end - end - end -end - --- add target custom commands for object rules -function _make_custom_commands_for_objectrules(commands, target, sourcebatch, suffix) - - -- get rule - local rulename = assert(sourcebatch.rulename, "unknown rule for sourcebatch!") - local ruleinst = assert(project.rule(rulename) or rule.rule(rulename), "unknown rule: %s", rulename) - - -- generate commands for xx_buildcmd_files - local scriptname = "buildcmd_files" .. (suffix and ("_" .. suffix) or "") - local script = ruleinst:script(scriptname) - if script then - local batchcmds_ = batchcmds.new({target = target}) - script(target, batchcmds_, sourcebatch, {}) - if not batchcmds_:empty() then - for _, cmd in ipairs(batchcmds_:cmds()) do - local command = _get_command_string(cmd) - if command then - commands[suffix] = commands[suffix] or {} - table.insert(commands[suffix], command) - end - end - end - end - - -- generate commands for xx_buildcmd_file - if not script then - scriptname = "buildcmd_file" .. (suffix and ("_" .. suffix) or "") - script = ruleinst:script(scriptname) - if script then - local sourcekind = sourcebatch.sourcekind - for _, sourcefile in ipairs(sourcebatch.sourcefiles) do - local batchcmds_ = batchcmds.new({target = target}) - script(target, batchcmds_, sourcefile, {}) - if not batchcmds_:empty() then - for _, cmd in ipairs(batchcmds_:cmds()) do - local command = _get_command_string(cmd) - if command then - commands[suffix] = commands[suffix] or {} - table.insert(commands[suffix], command) - end - end - end - end - end - end -end - -- make custom commands function _make_custom_commands(vcxprojfile, target) - local commands = {} - _make_custom_commands_for_target(commands, target, "before") - for _, sourcebatch in pairs(target:sourcebatches()) do - local sourcekind = sourcebatch.sourcekind - if sourcekind ~= "cc" and sourcekind ~= "cxx" and sourcekind ~= "as" then - _make_custom_commands_for_objectrules(commands, target, sourcebatch, "before") - _make_custom_commands_for_objectrules(commands, target, sourcebatch) - _make_custom_commands_for_objectrules(commands, target, sourcebatch, "after") - end - end - _make_custom_commands_for_target(commands, target, "after") - for suffix, cmds in pairs(commands) do + for suffix, cmds in pairs(target.commands) do _make_custom_commands_item(vcxprojfile, cmds, suffix) end end @@ -598,7 +494,7 @@ function _make_common_item(vcxprojfile, vsinfo, target, targetinfo, vcxprojdir) vcxprojfile:leave("") -- make custom commands - _make_custom_commands(vcxprojfile, target.targetinst) + _make_custom_commands(vcxprojfile, targetinfo) -- leave ItemDefinitionGroup vcxprojfile:leave("") -- cgit v1.3.1 From 23b6a0d891f91c83a790dee9a10775b595099461 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 15 Nov 2021 23:26:35 +0800 Subject: improve mkdir --- xmake/plugins/project/vstudio/impl/vs201x.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua index 11803cf45..82409c64a 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x.lua @@ -68,7 +68,7 @@ function _get_command_string(cmd) elseif kind == "cd" then return string.format("cd \"%s\"", cmd.dir) elseif kind == "mkdir" then - return string.format("mkdir \"%s\"", cmd.dir) + return string.format("if not exist \"%s\" mkdir \"%s\"", cmd.dir, cmd.dir) elseif kind == "show" then return string.format("echo %s", cmd.showtext) end -- cgit v1.3.1 From 6060388361136e757cc2e3f189ffdd1276b47993 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Nov 2021 00:56:53 +0800 Subject: add todo --- xmake/plugins/project/vstudio/impl/vs201x.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua index 82409c64a..1db739f1d 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x.lua @@ -57,6 +57,7 @@ function _get_command_string(cmd) local command = os.args(table.join(cmd.program, cmd.argv)) if opt and opt.curdir then command = "cd \"" .. opt.curdir .. "\"\n" .. command + -- TODO cd oldir end return command elseif kind == "cp" then -- cgit v1.3.1 From 8c67fe903098afed989fb9ba64881fb7267bca49 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Nov 2021 09:31:17 +0800 Subject: improve vs generator --- xmake/plugins/project/vstudio/impl/vs201x.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua index 1db739f1d..d366649da 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x.lua @@ -56,8 +56,7 @@ function _get_command_string(cmd) if cmd.program then local command = os.args(table.join(cmd.program, cmd.argv)) if opt and opt.curdir then - command = "cd \"" .. opt.curdir .. "\"\n" .. command - -- TODO cd oldir + command = string.format("pushd \"%s\"\n%s\npopd", opt.curdir, command) end return command elseif kind == "cp" then -- cgit v1.3.1 From 26ccb97f322fd3414001979d2d325522e7378868 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Nov 2021 09:48:53 +0800 Subject: add linkcmd for vs generator --- xmake/plugins/project/vstudio/impl/vs201x.lua | 33 ++++++++++++++++++---- .../project/vstudio/impl/vs201x_vcxproj.lua | 8 ++++-- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua index d366649da..3c7d62737 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x.lua @@ -86,8 +86,26 @@ function _make_custom_commands_for_target(commands, target, suffix) for _, cmd in ipairs(batchcmds_:cmds()) do local command = _get_command_string(cmd) if command then - commands[suffix] = commands[suffix] or {} - table.insert(commands[suffix], command) + local key = suffix and suffix or "before" + commands[key] = commands[key] or {} + table.insert(commands[key], command) + end + end + end + end + + scriptname = "linkcmd" .. (suffix and ("_" .. suffix) or "") + script = ruleinst:script(scriptname) + if script then + local batchcmds_ = batchcmds.new({target = target}) + script(target, batchcmds_, {}) + if not batchcmds_:empty() then + for _, cmd in ipairs(batchcmds_:cmds()) do + local command = _get_command_string(cmd) + if command then + local key = (suffix and suffix or "before") .. "_link" + commands[key] = commands[key] or {} + table.insert(commands[key], command) end end end @@ -112,8 +130,9 @@ function _make_custom_commands_for_objectrules(commands, target, sourcebatch, su for _, cmd in ipairs(batchcmds_:cmds()) do local command = _get_command_string(cmd) if command then - commands[suffix] = commands[suffix] or {} - table.insert(commands[suffix], command) + local key = suffix and suffix or "before" + commands[key] = commands[key] or {} + table.insert(commands[key], command) end end end @@ -132,8 +151,9 @@ function _make_custom_commands_for_objectrules(commands, target, sourcebatch, su for _, cmd in ipairs(batchcmds_:cmds()) do local command = _get_command_string(cmd) if command then - commands[suffix] = commands[suffix] or {} - table.insert(commands[suffix], command) + local key = suffix and suffix or "before" + commands[key] = commands[key] or {} + table.insert(commands[key], command) end end end @@ -146,6 +166,7 @@ end function _make_custom_commands(target) local commands = {} _make_custom_commands_for_target(commands, target, "before") + _make_custom_commands_for_target(commands, target) for _, sourcebatch in pairs(target:sourcebatches()) do local sourcekind = sourcebatch.sourcekind if sourcekind ~= "cc" and sourcekind ~= "cxx" and sourcekind ~= "as" then diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index 93e8633d9..6e77caf9b 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -374,10 +374,12 @@ end -- make custom commands item function _make_custom_commands_item(vcxprojfile, commands, suffix) - if suffix == "after" then + if suffix == "after" or suffix == "after_link" then vcxprojfile:print("") elseif suffix == "before" then vcxprojfile:print("") + elseif suffix == "before_link" then + vcxprojfile:print("") end vcxprojfile:print("") vcxprojfile:print("setlocal") @@ -392,10 +394,12 @@ exit /b %1 :xmDone if %errorlevel% neq 0 goto :VCEnd ]]) - if suffix == "after" then + if suffix == "after" or suffix == "after_link" then vcxprojfile:print("") elseif suffix == "before" then vcxprojfile:print("") + elseif suffix == "before_link" then + vcxprojfile:print("") end end -- cgit v1.3.1 From bf6635bb416c380091d1d6ef14bdf31e28049085 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Nov 2021 10:02:24 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7599eddfa..0bd0af27b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * [#1786](https://github.com/xmake-io/xmake/issues/1786): Improve apt:find_package, support to find alias package * [#1819](https://github.com/xmake-io/xmake/issues/1819): Add precompiled header to cmake generator * Improve C++20 module to support std libraries for msvc +* [#1792](https://github.com/xmake-io/xmake/issues/1792): Add custom command in vs project generator ### Bugs Fixed @@ -1142,6 +1143,7 @@ * [#1786](https://github.com/xmake-io/xmake/issues/1786): 改进 apt:find_package,支持查找 alias 包 * [#1819](https://github.com/xmake-io/xmake/issues/1819): 添加预编译头到 cmake 生成器 * 改进 C++20 Modules 为 msvc 支持 std 标准库 +* [#1792](https://github.com/xmake-io/xmake/issues/1792): 添加自定义命令到 vs 工程生成器 ### Bugs 修复 -- cgit v1.3.1 From dce21455e0aead37e5115c820bc1f23f61b738eb Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Nov 2021 22:46:17 +0800 Subject: improve compile errors --- xmake/modules/core/tools/cl.lua | 5 ++++- xmake/modules/core/tools/gcc.lua | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/xmake/modules/core/tools/cl.lua b/xmake/modules/core/tools/cl.lua index 7bbb6ff8b..c4cf109bf 100644 --- a/xmake/modules/core/tools/cl.lua +++ b/xmake/modules/core/tools/cl.lua @@ -454,7 +454,10 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) end end end - os.raise(results) + if not option.get("verbose") then + results = results .. "\n ${yellow}> in ${bright}" .. sourcefile + end + raise(results) end }, finally diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index 240ec2855..a871f62e5 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -494,7 +494,12 @@ function compile(self, sourcefile, objectfile, dependinfo, flags) end -- raise compiling errors - raise(#lines > 0 and table.concat(lines, "\n") or "") + local results = #lines > 0 and table.concat(lines, "\n") or "" + if not option.get("verbose") then + results = results .. "\n ${yellow}> in ${bright}" .. sourcefile + end + raise(results) + end }, finally -- cgit v1.3.1 From b7cb5bb0c219bf4c8cdb7fffc40388c13de5e213 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 16 Nov 2021 17:52:28 +0800 Subject: Update xmake.lua --- xmake/rules/utils/bin2c/xmake.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/rules/utils/bin2c/xmake.lua b/xmake/rules/utils/bin2c/xmake.lua index 81e042c41..03d27a534 100644 --- a/xmake/rules/utils/bin2c/xmake.lua +++ b/xmake/rules/utils/bin2c/xmake.lua @@ -32,6 +32,7 @@ rule("utils.bin2c") -- get header file local headerdir = path.join(target:autogendir(), "rules", "c++", "bin2c") local headerfile = path.join(headerdir, path.filename(sourcefile_bin) .. ".h") + target:add("includedirs", headerdir) -- add commands batchcmds:show_progress(opt.progress, "${color.build.object}generating.bin2c %s", sourcefile_bin) -- cgit v1.3.1 From a3996b2dbd5a294598a8f5122fa33b2dd92ea602 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 17 Nov 2021 10:38:06 +0800 Subject: fix rule --- xmake/core/project/target.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index c48d64c47..922d7d483 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -1166,17 +1166,17 @@ function _instance:filerules(sourcefile) end -- get target rules from the given sourcekind or extension + -- + -- @note we prefer to use rules with extension because we need to be able to + -- override the language code rules set by set_sourcekinds + -- + -- e.g. set_extensions(".bpf.c") will override c++ rules + -- local rules_override = {} local filename = path.filename(sourcefile):lower() for _, r in ipairs(table.wrap(key2rules[path.extension(filename, 2)] or - key2rules[path.extension(filename)])) do - if self:extraconf("rules", r:name(), "override") then - table.insert(rules_override, r) - else - table.insert(rules, r) - end - end - for _, r in ipairs(table.wrap(key2rules[self:sourcekind_of(filename)])) do + key2rules[path.extension(filename)] or + key2rules[self:sourcekind_of(filename)])) do if self:extraconf("rules", r:name(), "override") then table.insert(rules_override, r) else -- cgit v1.3.1 From 41173c58e23377477355306769bd5b5808f9ca23 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 17 Nov 2021 10:55:21 +0800 Subject: Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bd0af27b..a997a38e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ ### Bugs Fixed * Fix semver to parse build string with zero prefix +* [#50](https://github.com/libbpf/libbpf-bootstrap/issues/50): Fix rule and build bpf program errors ## v2.5.9 @@ -1148,6 +1149,7 @@ ### Bugs 修复 * 修复语义版本中解析带有 0 前缀的 build 字符串问题 +* [#50](https://github.com/libbpf/libbpf-bootstrap/issues/50): 修复 rule 和构建 bpf 程序 bug ## v2.5.9 -- cgit v1.3.1 From b7e124e4f8e77e75025717cee6b6066dfa34d813 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 17 Nov 2021 11:04:24 +0800 Subject: Update armasm.lua --- xmake/modules/core/tools/armasm.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xmake/modules/core/tools/armasm.lua b/xmake/modules/core/tools/armasm.lua index 181d8b7e8..3065fe0a3 100644 --- a/xmake/modules/core/tools/armasm.lua +++ b/xmake/modules/core/tools/armasm.lua @@ -92,6 +92,11 @@ function nf_language(self, stdname) end end +-- make the define flag +function nf_define(self, macro) + return {"--pd", macro .. " SETA 1"} +end + -- make the includedir flag function nf_includedir(self, dir) return {"-I" .. dir} -- cgit v1.3.1 From 7f3706c2ad219d6632b3be0a4705042ced0d0233 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 17 Nov 2021 11:29:56 +0800 Subject: Update program.lua --- xmake/core/ui/program.lua | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/xmake/core/ui/program.lua b/xmake/core/ui/program.lua index 0ebd6377a..f537a2daf 100644 --- a/xmake/core/ui/program.lua +++ b/xmake/core/ui/program.lua @@ -345,6 +345,15 @@ function program:_key_map() [curses.KEY_SHOME ] = "ShiftHome", [curses.KEY_SLEFT ] = "ShiftLeft", [curses.KEY_SRIGHT ] = "ShiftRight", + + -- register virtual keys + -- + -- @see https://github.com/xmake-io/xmake/issues/1610 + -- https://github.com/wmcbrine/PDCurses/blob/HEAD/curses.h#L766-L774 + [curses.KEY_C2 ] = "Down", + [curses.KEY_A2 ] = "Up", + [curses.KEY_B1 ] = "Left", + [curses.KEY_B3 ] = "Right" } end return self._KEYMAP -- cgit v1.3.1 From 90efbbce0bbfb8403e1581414a289e7de48e23cc Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 17 Nov 2021 11:38:29 +0800 Subject: Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a997a38e3..5fb400b04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,11 +14,13 @@ * [#1819](https://github.com/xmake-io/xmake/issues/1819): Add precompiled header to cmake generator * Improve C++20 module to support std libraries for msvc * [#1792](https://github.com/xmake-io/xmake/issues/1792): Add custom command in vs project generator +* [#1835](https://github.com/xmake-io/xmake/issues/1835): Improve MDK program supports ### Bugs Fixed * Fix semver to parse build string with zero prefix * [#50](https://github.com/libbpf/libbpf-bootstrap/issues/50): Fix rule and build bpf program errors +* [#1610](https://github.com/xmake-io/xmake/issues/1610): Fix `xmake f --menu` not responding in vscode and support ConPTY terminal virtkeys ## v2.5.9 @@ -1145,11 +1147,13 @@ * [#1819](https://github.com/xmake-io/xmake/issues/1819): 添加预编译头到 cmake 生成器 * 改进 C++20 Modules 为 msvc 支持 std 标准库 * [#1792](https://github.com/xmake-io/xmake/issues/1792): 添加自定义命令到 vs 工程生成器 +* [#1835](https://github.com/xmake-io/xmake/issues/1835): 改进 MDK 程序构建支持 ### Bugs 修复 * 修复语义版本中解析带有 0 前缀的 build 字符串问题 * [#50](https://github.com/libbpf/libbpf-bootstrap/issues/50): 修复 rule 和构建 bpf 程序 bug +* [#1610](https://github.com/xmake-io/xmake/issues/1610): 修复 `xmake f --menu` 在 vscode 终端下按键无响应,并且支持 ConPTY 终端虚拟按键 ## v2.5.9 -- cgit v1.3.1 From dcffc69b622da2048f6ee529f5974cb66cd6dc1a Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 17 Nov 2021 12:14:04 +0800 Subject: add microlib runtime for mdk --- tests/projects/mdk/hello/xmake.lua | 3 ++- xmake/languages/asm/xmake.lua | 3 +++ xmake/modules/core/tools/armasm.lua | 7 +++++++ xmake/modules/core/tools/armcc.lua | 7 +++++++ xmake/modules/core/tools/armclang.lua | 7 +++++++ xmake/modules/core/tools/armlink.lua | 7 +++++++ xmake/rules/mdk/xmake.lua | 1 + 7 files changed, 34 insertions(+), 1 deletion(-) diff --git a/tests/projects/mdk/hello/xmake.lua b/tests/projects/mdk/hello/xmake.lua index 97d640297..6afb714af 100644 --- a/tests/projects/mdk/hello/xmake.lua +++ b/tests/projects/mdk/hello/xmake.lua @@ -1,5 +1,7 @@ add_rules("mode.debug", "mode.release") +set_runtimes("microlib") + target("foo") add_rules("mdk.static") add_files("src/foo/*.c") @@ -8,5 +10,4 @@ target("hello") add_deps("foo") add_rules("mdk.console") add_files("src/*.c", "src/*.s") - add_defines("__EVAL", "__MICROLIB") add_includedirs("src/lib/cmsis") diff --git a/xmake/languages/asm/xmake.lua b/xmake/languages/asm/xmake.lua index cb9aa22f5..bdf4a4514 100644 --- a/xmake/languages/asm/xmake.lua +++ b/xmake/languages/asm/xmake.lua @@ -40,6 +40,7 @@ language("asm") , "target.includedirs" , "target.defines" , "target.undefines" + , "target.runtimes" , "toolchain.includedirs" , "toolchain.defines" , "toolchain.undefines" @@ -52,6 +53,7 @@ language("asm") , "target.rpathdirs" , "target.strip" , "target.symbols" + , "target.runtimes" , "toolchain.linkdirs" , "toolchain.rpathdirs" , "config.links" @@ -63,6 +65,7 @@ language("asm") , "target.linkdirs" , "target.strip" , "target.symbols" + , "target.runtimes" , "toolchain.linkdirs" , "config.links" , "target.links" diff --git a/xmake/modules/core/tools/armasm.lua b/xmake/modules/core/tools/armasm.lua index 3065fe0a3..3ae578c55 100644 --- a/xmake/modules/core/tools/armasm.lua +++ b/xmake/modules/core/tools/armasm.lua @@ -92,6 +92,13 @@ function nf_language(self, stdname) end end +-- make runtime flag +function nf_runtime(self, runtime) + if runtime == "microlib" then + return {"--pd", "__MICROLIB SETA 1"} + end +end + -- make the define flag function nf_define(self, macro) return {"--pd", macro .. " SETA 1"} diff --git a/xmake/modules/core/tools/armcc.lua b/xmake/modules/core/tools/armcc.lua index 6215242ec..403e143f0 100644 --- a/xmake/modules/core/tools/armcc.lua +++ b/xmake/modules/core/tools/armcc.lua @@ -45,6 +45,13 @@ function nf_symbol(self, level) end end +-- make runtime flag +function nf_runtime(self, runtime) + if runtime == "microlib" then + return "-D__MICROLIB" + end +end + -- make the optimize flag function nf_optimize(self, level) local maps = diff --git a/xmake/modules/core/tools/armclang.lua b/xmake/modules/core/tools/armclang.lua index 42bec8fd5..dcec82015 100644 --- a/xmake/modules/core/tools/armclang.lua +++ b/xmake/modules/core/tools/armclang.lua @@ -23,3 +23,10 @@ inherit("gcc") function init(self) _super.init(self) end + +-- make runtime flag +function nf_runtime(self, runtime) + if runtime == "microlib" then + return "-D__MICROLIB" + end +end diff --git a/xmake/modules/core/tools/armlink.lua b/xmake/modules/core/tools/armlink.lua index 02c2b4800..e25a81967 100644 --- a/xmake/modules/core/tools/armlink.lua +++ b/xmake/modules/core/tools/armlink.lua @@ -41,6 +41,13 @@ function nf_linkdir(self, dir) return {"--userlibpath", dir} end +-- make runtime flag +function nf_runtime(self, runtime) + if runtime == "microlib" then + return "--library_type=microlib" + end +end + -- make the link arguments list function linkargv(self, objectfiles, targetkind, targetfile, flags) return self:program(), table.join("-o", targetfile, objectfiles, flags) diff --git a/xmake/rules/mdk/xmake.lua b/xmake/rules/mdk/xmake.lua index f45e04c6e..0c491b528 100644 --- a/xmake/rules/mdk/xmake.lua +++ b/xmake/rules/mdk/xmake.lua @@ -40,3 +40,4 @@ rule("mdk.static") -- set default output binary target:set("kind", "static") end) + -- cgit v1.3.1 From e11da30f5fa33d81172864ba336a8dd6992d5331 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 17 Nov 2021 12:35:09 +0800 Subject: fix keymap --- core/src/lcurses/lcurses.c | 6 ++++++ xmake/core/ui/program.lua | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/core/src/lcurses/lcurses.c b/core/src/lcurses/lcurses.c index a55b86606..6e7758ccf 100644 --- a/core/src/lcurses/lcurses.c +++ b/core/src/lcurses/lcurses.c @@ -609,6 +609,12 @@ static void register_curses_constants(lua_State *L) CC(KEY_COPY) CC(KEY_CREATE) CC(KEY_END) CC(KEY_EXIT) CC(KEY_FIND) CC(KEY_HELP) CC(KEY_MARK) CC(KEY_MESSAGE) +#ifdef PDCURSES + // https://github.com/xmake-io/xmake/issues/1610#issuecomment-971149885 + CC(KEY_C2) CC(KEY_A2) CC(KEY_B1) + CC(KEY_B3) +#endif + #if !defined(XCURSES) #ifndef NOMOUSE CC(KEY_MOUSE) diff --git a/xmake/core/ui/program.lua b/xmake/core/ui/program.lua index f537a2daf..49eff8679 100644 --- a/xmake/core/ui/program.lua +++ b/xmake/core/ui/program.lua @@ -350,10 +350,10 @@ function program:_key_map() -- -- @see https://github.com/xmake-io/xmake/issues/1610 -- https://github.com/wmcbrine/PDCurses/blob/HEAD/curses.h#L766-L774 - [curses.KEY_C2 ] = "Down", - [curses.KEY_A2 ] = "Up", - [curses.KEY_B1 ] = "Left", - [curses.KEY_B3 ] = "Right" + [curses.KEY_C2 or -1 ] = "Down", + [curses.KEY_A2 or -1 ] = "Up", + [curses.KEY_B1 or -1 ] = "Left", + [curses.KEY_B3 or -1 ] = "Right" } end return self._KEYMAP -- cgit v1.3.1 From fa24e12bd740b6fd57a8787aebe14d0784c4ce32 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 17 Nov 2021 23:07:32 +0800 Subject: update changelog --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fb400b04..d35c7d86f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ * [#1819](https://github.com/xmake-io/xmake/issues/1819): Add precompiled header to cmake generator * Improve C++20 module to support std libraries for msvc * [#1792](https://github.com/xmake-io/xmake/issues/1792): Add custom command in vs project generator -* [#1835](https://github.com/xmake-io/xmake/issues/1835): Improve MDK program supports +* [#1835](https://github.com/xmake-io/xmake/issues/1835): Improve MDK program supports and add `set_runtimes("microlib")` ### Bugs Fixed @@ -1147,7 +1147,7 @@ * [#1819](https://github.com/xmake-io/xmake/issues/1819): 添加预编译头到 cmake 生成器 * 改进 C++20 Modules 为 msvc 支持 std 标准库 * [#1792](https://github.com/xmake-io/xmake/issues/1792): 添加自定义命令到 vs 工程生成器 -* [#1835](https://github.com/xmake-io/xmake/issues/1835): 改进 MDK 程序构建支持 +* [#1835](https://github.com/xmake-io/xmake/issues/1835): 改进 MDK 程序构建支持,增加 `set_runtimes("microlib")` ### Bugs 修复 -- cgit v1.3.1 From b995865e5b4211ed455703b242cf3614677bf296 Mon Sep 17 00:00:00 2001 From: xq114 <1140735506@qq.com> Date: Fri, 19 Nov 2021 18:17:43 +0800 Subject: update install scripts --- scripts/get.ps1 | 4 ++-- scripts/get.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/get.ps1 b/scripts/get.ps1 index f03d80fa4..449e0e3a1 100755 --- a/scripts/get.ps1 +++ b/scripts/get.ps1 @@ -11,7 +11,7 @@ param ( ) & { - $LastRelease = "v2.5.8" + $LastRelease = "v2.5.9" $ErrorActionPreference = 'Stop' function writeErrorTip($msg) { @@ -157,7 +157,7 @@ param ( writeErrorTip 'Check your network or... the news of S3 break' return } - Set-Content $file "$content`n$appendcontent" -NoNewline + Set-Content $file "$content`n# >>> xmake >>>`n$appendcontent`n# <<< xmake <<<`n" -NoNewline . $file Write-Host "Tab completion installed" } diff --git a/scripts/get.sh b/scripts/get.sh index 01634a967..b32c28b6f 100755 --- a/scripts/get.sh +++ b/scripts/get.sh @@ -225,7 +225,7 @@ else fi write_profile() { - grep -sq ".xmake/profile" $1 || echo -e "\n[[ -s \"\$HOME/.xmake/profile\" ]] && source \"\$HOME/.xmake/profile\" # load xmake profile" >> $1 + grep -sq ".xmake/profile" $1 || echo -e "\n# >>> xmake >>>\n[[ -s \"\$HOME/.xmake/profile\" ]] && source \"\$HOME/.xmake/profile\" # load xmake profile\n# <<< xmake <<<" >> $1 } install_profile() { -- cgit v1.3.1 From a834aa4e27d7fb597f53fe0be24b81e8cb7c28ef Mon Sep 17 00:00:00 2001 From: nasso <11479594+nasso@users.noreply.github.com> Date: Sun, 21 Nov 2021 18:24:41 +0100 Subject: Install `bzip2` with `yum` --- scripts/get.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/get.sh b/scripts/get.sh index b32c28b6f..ca009407d 100755 --- a/scripts/get.sh +++ b/scripts/get.sh @@ -150,7 +150,7 @@ test_tools() install_tools() { { apt --version >/dev/null 2>&1 && $sudoprefix apt install -y git build-essential libreadline-dev ccache; } || - { yum --version >/dev/null 2>&1 && $sudoprefix yum install -y git readline-devel ccache && $sudoprefix yum groupinstall -y 'Development Tools'; } || + { yum --version >/dev/null 2>&1 && $sudoprefix yum install -y git readline-devel ccache bzip2 && $sudoprefix yum groupinstall -y 'Development Tools'; } || { zypper --version >/dev/null 2>&1 && $sudoprefix zypper --non-interactive install git readline-devel ccache && $sudoprefix zypper --non-interactive install -t pattern devel_C_C++; } || { pacman -V >/dev/null 2>&1 && $sudoprefix pacman -S --noconfirm --needed git base-devel ccache; } || { emerge -V >/dev/null 2>&1 && $sudoprefix emerge -atv dev-vcs/git ccache; } || -- cgit v1.3.1 From 2dae9ae6afe1bb25ceff0e52b6c1e5c0c9a00f03 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 23 Nov 2021 13:09:10 +0800 Subject: Update xmake.lua --- core/src/lua/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/lua/xmake.lua b/core/src/lua/xmake.lua index 62326e748..379bdc46a 100644 --- a/core/src/lua/xmake.lua +++ b/core/src/lua/xmake.lua @@ -1,5 +1,5 @@ target("lua") - if not is_config("lua") then + if not is_config("runtime", "lua") then set_default(false) end set_kind("static") -- cgit v1.3.1 From 2e144373c6f1f1d945e9c632adb469f858d4a004 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 23 Nov 2021 13:09:30 +0800 Subject: Update xmake.lua --- core/src/luajit/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/luajit/xmake.lua b/core/src/luajit/xmake.lua index f6f351394..a3c7120df 100644 --- a/core/src/luajit/xmake.lua +++ b/core/src/luajit/xmake.lua @@ -23,7 +23,7 @@ local autogendir = path.join("autogen", plat, jit and "jit" or "nojit", arch) -- add target target("luajit") - if not is_config("luajit") then + if not is_config("runtime", "luajit") then set_default(false) end -- cgit v1.3.1 From 499b857f587073a09145c44d4ab9c312afb9a69a Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 24 Nov 2021 00:51:30 +0800 Subject: add more c++module test --- tests/projects/c++/modules/staticlib/src/main.cpp | 8 ++++++++ tests/projects/c++/modules/staticlib/src/mod.cpp | 7 +++++++ tests/projects/c++/modules/staticlib/src/mod.mpp | 5 +++++ tests/projects/c++/modules/staticlib/xmake.lua | 12 ++++++++++++ 4 files changed, 32 insertions(+) create mode 100644 tests/projects/c++/modules/staticlib/src/main.cpp create mode 100644 tests/projects/c++/modules/staticlib/src/mod.cpp create mode 100644 tests/projects/c++/modules/staticlib/src/mod.mpp create mode 100644 tests/projects/c++/modules/staticlib/xmake.lua diff --git a/tests/projects/c++/modules/staticlib/src/main.cpp b/tests/projects/c++/modules/staticlib/src/main.cpp new file mode 100644 index 000000000..af2c328eb --- /dev/null +++ b/tests/projects/c++/modules/staticlib/src/main.cpp @@ -0,0 +1,8 @@ +#include +import mod; + +int main() { + printf("%d\n", mod::foo()); + return 0; +} + diff --git a/tests/projects/c++/modules/staticlib/src/mod.cpp b/tests/projects/c++/modules/staticlib/src/mod.cpp new file mode 100644 index 000000000..9c7cf5290 --- /dev/null +++ b/tests/projects/c++/modules/staticlib/src/mod.cpp @@ -0,0 +1,7 @@ +module mod; + +namespace mod { + int foo() { + return 2; + } +} diff --git a/tests/projects/c++/modules/staticlib/src/mod.mpp b/tests/projects/c++/modules/staticlib/src/mod.mpp new file mode 100644 index 000000000..ac30a31c8 --- /dev/null +++ b/tests/projects/c++/modules/staticlib/src/mod.mpp @@ -0,0 +1,5 @@ +export module mod; + +export namespace mod { + int foo(); +} diff --git a/tests/projects/c++/modules/staticlib/xmake.lua b/tests/projects/c++/modules/staticlib/xmake.lua new file mode 100644 index 000000000..3aa743c64 --- /dev/null +++ b/tests/projects/c++/modules/staticlib/xmake.lua @@ -0,0 +1,12 @@ +set_languages("c++20") + +add_cxxflags("-fmodules-ts") + +target("mod") + set_kind("static") + add_files("src/mod.mpp", "src/mod.cpp") + +target("test") + set_kind("binary") + add_deps("mod") + add_files("src/main.cpp") -- cgit v1.3.1 From 12ee3ed6eb196f5d9e5cdeb619c40f51b2bec144 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 24 Nov 2021 00:56:24 +0800 Subject: improve c++ modules --- tests/projects/c++/modules/staticlib/xmake.lua | 2 -- xmake/rules/c++/modules/build_modules/clang.lua | 26 +++++++++++++++++++ xmake/rules/c++/modules/build_modules/gcc.lua | 14 ++++++++++ xmake/rules/c++/modules/build_modules/msvc.lua | 15 +++++++++++ xmake/rules/c++/modules/xmake.lua | 34 +++++++++++++++++++++---- 5 files changed, 84 insertions(+), 7 deletions(-) diff --git a/tests/projects/c++/modules/staticlib/xmake.lua b/tests/projects/c++/modules/staticlib/xmake.lua index 3aa743c64..93045c18f 100644 --- a/tests/projects/c++/modules/staticlib/xmake.lua +++ b/tests/projects/c++/modules/staticlib/xmake.lua @@ -1,7 +1,5 @@ set_languages("c++20") -add_cxxflags("-fmodules-ts") - target("mod") set_kind("static") add_files("src/mod.mpp", "src/mod.cpp") diff --git a/xmake/rules/c++/modules/build_modules/clang.lua b/xmake/rules/c++/modules/build_modules/clang.lua index 06b5aa1db..523c61ad9 100644 --- a/xmake/rules/c++/modules/build_modules/clang.lua +++ b/xmake/rules/c++/modules/build_modules/clang.lua @@ -23,6 +23,32 @@ import("core.tool.compiler") import("private.action.build.object", {alias = "objectbuilder"}) import("module_parser") +-- load parent target with modules files +function load_parent(target, opt) + -- get modules flag + local modulesflag + local compinst = compiler.load("cxx", {target = target}) + if compinst:has_flags("-fmodules") then + modulesflag = "-fmodules" + elseif compinst:has_flags("-fmodules-ts") then + modulesflag = "-fmodules-ts" + end + assert(modulesflag, "compiler(clang): does not support c++ module!") + + -- add module flags + target:add("cxxflags", modulesflag) + + -- the module cache directory + for _, dep in ipairs(target:orderdeps()) do + local sourcebatches = dep:sourcebatches() + if sourcebatches and sourcebatches["c++.build.modules"] then + local cachedir = path.join(dep:autogendir(), "rules", "modules", "cache") + target:add("cxxflags", "-fmodules-cache-path=" .. cachedir, {force = true}) + target:add("cxxflags", "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir, {force = true}) + end + end +end + -- build module files function build_with_batchjobs(target, batchjobs, sourcebatch, opt) diff --git a/xmake/rules/c++/modules/build_modules/gcc.lua b/xmake/rules/c++/modules/build_modules/gcc.lua index 1264f29c2..2abaa4f7f 100644 --- a/xmake/rules/c++/modules/build_modules/gcc.lua +++ b/xmake/rules/c++/modules/build_modules/gcc.lua @@ -23,6 +23,20 @@ import("core.tool.compiler") import("private.action.build.object", {alias = "objectbuilder"}) import("module_parser") +-- load parent target with modules files +function load_parent(target, opt) + -- get modules flag + local modulesflag + local compinst = compiler.load("cxx", {target = target}) + if compinst:has_flags("-fmodules-ts") then + modulesflag = "-fmodules-ts" + end + assert(modulesflag, "compiler(gcc): does not support c++ module!") + + -- add module flags + target:add("cxxflags", modulesflag) +end + -- build module files function build_with_batchjobs(target, batchjobs, sourcebatch, opt) diff --git a/xmake/rules/c++/modules/build_modules/msvc.lua b/xmake/rules/c++/modules/build_modules/msvc.lua index 4606edb7e..4cc8500ab 100644 --- a/xmake/rules/c++/modules/build_modules/msvc.lua +++ b/xmake/rules/c++/modules/build_modules/msvc.lua @@ -23,6 +23,21 @@ import("core.tool.compiler") import("private.action.build.object", {alias = "objectbuilder"}) import("module_parser") +-- load parent target with modules files +function load_parent(target, opt) + + -- get modules flag + local modulesflag + local compinst = compiler.load("cxx", {target = target}) + if compinst:has_flags("/experimental:module", "cxxflags") then + modulesflag = "/experimental:module" + end + assert(modulesflag, "compiler(msvc): does not support c++ module!") + + -- add module flags + target:add("cxxflags", modulesflag) +end + -- build module files function build_with_batchjobs(target, batchjobs, sourcebatch, opt) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 9018f5e2d..78f754521 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -21,12 +21,36 @@ -- define rule: c++.build.modules rule("c++.build.modules") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") - before_build_files(function (target, batchjobs, sourcebatch, opt) + after_load(function (target) -- we disable to build across targets in parallel, because the source files may depend on other target modules - -- @note we cannot set it in on_load, because it will affect all c++ projects - target:set("policy", "build.across_targets_in_parallel", false) - - -- build module files with batchjobs + -- @see https://github.com/xmake-io/xmake/issues/1858 + local target_with_modules + for _, dep in ipairs(target:orderdeps()) do + local sourcebatches = dep:sourcebatches() + if sourcebatches and sourcebatches["c++.build.modules"] then + target_with_modules = true + break + end + end + if target_with_modules then + -- @note this will cause cross-parallel builds to be disabled for all sub-dependent targets, + -- even if some sub-targets do not contain C++ modules. + -- + -- maybe we will have a more fine-grained configuration strategy to disable it in the future. + target:set("policy", "build.across_targets_in_parallel", false) + local _, toolname = target:tool("cxx") + if toolname:find("clang", 1, true) then + import("build_modules.clang").load_parent(target, opt) + elseif toolname:find("gcc", 1, true) then + import("build_modules.gcc").load_parent(target, opt) + elseif toolname == "cl" then + import("build_modules.msvc").load_parent(target, opt) + else + raise("compiler(%s): does not support c++ module!", toolname) + end + end + end) + before_build_files(function (target, batchjobs, sourcebatch, opt) local _, toolname = target:tool("cxx") if toolname:find("clang", 1, true) then import("build_modules.clang").build_with_batchjobs(target, batchjobs, sourcebatch, opt) -- cgit v1.3.1 From 2ebc0bd03cf7f2d6be736cc01d6a808e3e03b3f1 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 24 Nov 2021 09:30:36 +0800 Subject: Update msvc.lua --- xmake/rules/c++/modules/build_modules/msvc.lua | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/xmake/rules/c++/modules/build_modules/msvc.lua b/xmake/rules/c++/modules/build_modules/msvc.lua index 4cc8500ab..1dc04618f 100644 --- a/xmake/rules/c++/modules/build_modules/msvc.lua +++ b/xmake/rules/c++/modules/build_modules/msvc.lua @@ -36,6 +36,17 @@ function load_parent(target, opt) -- add module flags target:add("cxxflags", modulesflag) + + -- get output flag + if compinst:has_flags("/ifcOutput", "cxxflags") then + for _, dep in ipairs(target:orderdeps()) do + local sourcebatches = dep:sourcebatches() + if sourcebatches and sourcebatches["c++.build.modules"] then + local cachedir = path.join(dep:autogendir(), "rules", "modules", "cache") + target:add("cxxflags", "/ifcSearchDir " .. os.args(cachedir), {force = true}) + end + end + end end -- build module files @@ -52,9 +63,7 @@ function build_with_batchjobs(target, batchjobs, sourcebatch, opt) -- get output flag local cachedir local outputflag - local hasifc = false if compinst:has_flags("/ifcOutput", "cxxflags") then - hasifc = true outputflag = "/ifcOutput" cachedir = path.join(target:autogendir(), "rules", "modules", "cache") if not os.isdir(cachedir) then -- cgit v1.3.1 From ba8988915b8c25eb7b407779b5c6aac9b7ae22ee Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 24 Nov 2021 09:32:49 +0800 Subject: Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d35c7d86f..fbe71a6c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ * Improve C++20 module to support std libraries for msvc * [#1792](https://github.com/xmake-io/xmake/issues/1792): Add custom command in vs project generator * [#1835](https://github.com/xmake-io/xmake/issues/1835): Improve MDK program supports and add `set_runtimes("microlib")` +* [#1858](https://github.com/xmake-io/xmake/issues/1858): Improve to build c++20 modules with libraries ### Bugs Fixed @@ -1148,6 +1149,7 @@ * 改进 C++20 Modules 为 msvc 支持 std 标准库 * [#1792](https://github.com/xmake-io/xmake/issues/1792): 添加自定义命令到 vs 工程生成器 * [#1835](https://github.com/xmake-io/xmake/issues/1835): 改进 MDK 程序构建支持,增加 `set_runtimes("microlib")` +* [#1858](https://github.com/xmake-io/xmake/issues/1858): 改进构建 c++20 modules,修复跨 target 构建问题 ### Bugs 修复 -- cgit v1.3.1 From b25c430d5ebfce6c04e37e1cfe9edba0a7233556 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 24 Nov 2021 10:42:08 +0800 Subject: Update autoconf.lua --- xmake/modules/package/tools/autoconf.lua | 62 ++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/xmake/modules/package/tools/autoconf.lua b/xmake/modules/package/tools/autoconf.lua index f06a18bb0..833aa2f02 100644 --- a/xmake/modules/package/tools/autoconf.lua +++ b/xmake/modules/package/tools/autoconf.lua @@ -25,12 +25,20 @@ import("core.tool.linker") import("core.tool.compiler") import("lib.detect.find_tool") --- translate path -function _translate_path(package, p) - if p and is_host("windows") and (package:is_plat("mingw") or package:is_plat("msys") or package:is_plat("cygwin")) then - p = p:gsub("\\", "/") +-- translate paths +function _translate_paths(package, paths) + if paths and is_host("windows") and (package:is_plat("mingw") or package:is_plat("msys") or package:is_plat("cygwin")) then + if type(paths) == "string" then + return (paths:gsub("\\", "/")) + elseif type(paths) == "table" then + local result = {} + for _, p in ipairs(paths) do + table.insert(result, (p:gsub("\\", "/"))) + end + return result + end end - return p + return paths end -- translate windows bin path @@ -57,7 +65,7 @@ function _get_configs(package, configs) -- add prefix local configs = configs or {} - table.insert(configs, "--prefix=" .. _translate_path(package, package:installdir())) + table.insert(configs, "--prefix=" .. _translate_paths(package, package:installdir())) -- add host for cross-complation if not configs.host and not package:is_plat(os.subhost()) then @@ -109,6 +117,40 @@ function _get_configs(package, configs) return configs end +-- get cflags from package deps +function _get_cflags_from_packagedeps(package, opt) + local result = {} + for _, depname in ipairs(opt.packagedeps) do + local dep = package:dep(depname) + if dep then + local fetchinfo = dep:fetch({external = false}) + if fetchinfo then + table.join2(result, _map_compflags(package, "cxx", "define", fetchinfo.defines)) + table.join2(result, _translate_paths(package, _map_compflags(package, "cxx", "includedir", fetchinfo.includedirs))) + table.join2(result, _translate_paths(package, _map_compflags(package, "cxx", "sysincludedir", fetchinfo.sysincludedirs))) + end + end + end + return result +end + +-- get ldflags from package deps +function _get_ldflags_from_packagedeps(package, opt) + local result = {} + for _, depname in ipairs(opt.packagedeps) do + local dep = package:dep(depname) + if dep then + local fetchinfo = dep:fetch({external = false}) + if fetchinfo then + table.join2(result, _translate_paths(package, _map_linkflags(package, "binary", {"cxx"}, "linkdir", fetchinfo.linkdirs))) + table.join2(result, _map_linkflags(package, "binary", {"cxx"}, "link", fetchinfo.links)) + table.join2(result, _translate_paths(package, _map_linkflags(package, "binary", {"cxx"}, "syslink", fetchinfo.syslinks))) + end + end + end + return result +end + -- get the build environments function buildenvs(package, opt) opt = opt or {} @@ -132,6 +174,10 @@ function buildenvs(package, opt) table.join2(cppflags, opt.cppflags) -- @see https://github.com/xmake-io/xmake/issues/1688 table.join2(asflags, opt.asflags) table.join2(ldflags, opt.ldflags) + table.join2(cflags, _get_cflags_from_packagedeps(package, opt)) + table.join2(cxxflags, _get_cflags_from_packagedeps(package, opt)) + table.join2(cppflags, _get_cflags_from_packagedeps(package, opt)) + table.join2(ldflags, _get_ldflags_from_packagedeps(package, opt)) envs.CFLAGS = table.concat(cflags, ' ') envs.CXXFLAGS = table.concat(cxxflags, ' ') envs.CPPFLAGS = table.concat(cppflags, ' ') @@ -158,6 +204,10 @@ function buildenvs(package, opt) table.join2(asflags, opt.asflags) table.join2(ldflags, opt.ldflags) table.join2(shflags, opt.shflags) + table.join2(cflags, _get_cflags_from_packagedeps(package, opt)) + table.join2(cxxflags, _get_cflags_from_packagedeps(package, opt)) + table.join2(cppflags, _get_cflags_from_packagedeps(package, opt)) + table.join2(ldflags, _get_ldflags_from_packagedeps(package, opt)) table.join2(cflags, _map_compflags(package, "c", "define", defines)) table.join2(cflags, _map_compflags(package, "c", "includedir", includedirs)) table.join2(cflags, _map_compflags(package, "c", "sysincludedir", sysincludedirs)) -- cgit v1.3.1 From 679c463806be46f4c0d3184bcbe56dbd6a4e1598 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 24 Nov 2021 11:06:47 +0800 Subject: Update meson.lua --- xmake/modules/package/tools/meson.lua | 87 +++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 5 deletions(-) diff --git a/xmake/modules/package/tools/meson.lua b/xmake/modules/package/tools/meson.lua index a57497343..70e52f923 100644 --- a/xmake/modules/package/tools/meson.lua +++ b/xmake/modules/package/tools/meson.lua @@ -22,6 +22,8 @@ import("core.base.option") import("core.project.config") import("core.tool.toolchain") +import("core.tool.linker") +import("core.tool.compiler") import("package.tools.ninja") -- get build directory @@ -34,6 +36,16 @@ function _get_buildir(package, opt) end end +-- map compiler flags +function _map_compflags(package, langkind, name, values) + return compiler.map_flags(langkind, name, values, {target = package}) +end + +-- map linker flags +function _map_linkflags(package, targetkind, sourcekinds, name, values) + return linker.map_flags(targetkind, sourcekinds, name, values, {target = package}) +end + -- get configs function _get_configs(package, configs, opt) @@ -79,21 +91,86 @@ function _fix_libname_on_windows(package) end end +-- get cflags from package deps +function _get_cflags_from_packagedeps(package, opt) + local result = {} + for _, depname in ipairs(opt.packagedeps) do + local dep = package:dep(depname) + if dep then + local fetchinfo = dep:fetch({external = false}) + if fetchinfo then + table.join2(result, _map_compflags(package, "cxx", "define", fetchinfo.defines)) + table.join2(result, _map_compflags(package, "cxx", "includedir", fetchinfo.includedirs)) + table.join2(result, _map_compflags(package, "cxx", "sysincludedir", fetchinfo.sysincludedirs)) + end + end + end + return result +end + +-- get ldflags from package deps +function _get_ldflags_from_packagedeps(package, opt) + local result = {} + for _, depname in ipairs(opt.packagedeps) do + local dep = package:dep(depname) + if dep then + local fetchinfo = dep:fetch({external = false}) + if fetchinfo then + table.join2(result, _map_linkflags(package, "binary", {"cxx"}, "linkdir", fetchinfo.linkdirs)) + table.join2(result, _map_linkflags(package, "binary", {"cxx"}, "link", fetchinfo.links)) + table.join2(result, _map_linkflags(package, "binary", {"cxx"}, "syslink", fetchinfo.syslinks)) + end + end + end + return result +end + -- get the build environments function buildenvs(package) local envs = {} if package:is_plat(os.host()) then local cflags = table.join(table.wrap(package:config("cxflags")), package:config("cflags")) local cxxflags = table.join(table.wrap(package:config("cxflags")), package:config("cxxflags")) + local asflags = table.wrap(package:config("asflags")) + local ldflags = table.wrap(package:config("ldflags")) + local shflags = table.wrap(package:config("shflags")) + table.join2(cflags, opt.cflags) + table.join2(cflags, opt.cxflags) + table.join2(cxxflags, opt.cxxflags) + table.join2(cxxflags, opt.cxflags) + table.join2(asflags, opt.asflags) + table.join2(ldflags, opt.ldflags) + table.join2(shflags, opt.shflags) + table.join2(cflags, _get_cflags_from_packagedeps(package, opt)) + table.join2(cxxflags, _get_cflags_from_packagedeps(package, opt)) + table.join2(ldflags, _get_ldflags_from_packagedeps(package, opt)) + table.join2(shflags, _get_ldflags_from_packagedeps(package, opt)) envs.CFLAGS = table.concat(cflags, ' ') envs.CXXFLAGS = table.concat(cxxflags, ' ') - envs.ASFLAGS = table.concat(table.wrap(package:config("asflags")), ' ') + envs.ASFLAGS = table.concat(asflags, ' ') + envs.LDFLAGS = table.concat(ldflags, ' ') + envs.SHFLAGS = table.concat(shflags, ' ') if package:is_plat("windows") then envs = os.joinenvs(envs, _get_msvc_runenvs(package)) end else local cflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cflags")) local cxxflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cxxflags")) + local asflags = table.wrap(package:build_getenv("asflags")) + local arflags = table.wrap(package:build_getenv("arflags")) + local ldflags = table.wrap(package:build_getenv("ldflags")) + local shflags = table.wrap(package:build_getenv("shflags")) + table.join2(cflags, opt.cflags) + table.join2(cflags, opt.cxflags) + table.join2(cxxflags, opt.cxxflags) + table.join2(cxxflags, opt.cxflags) + table.join2(asflags, opt.asflags) + table.join2(ldflags, opt.ldflags) + table.join2(shflags, opt.shflags) + table.join2(cflags, _get_cflags_from_packagedeps(package, opt)) + table.join2(cxxflags, _get_cflags_from_packagedeps(package, opt)) + table.join2(ldflags, _get_ldflags_from_packagedeps(package, opt)) + table.join2(shflags, _get_ldflags_from_packagedeps(package, opt)) envs.CC = package:build_getenv("cc") envs.AS = package:build_getenv("as") envs.AR = package:build_getenv("ar") @@ -103,10 +180,10 @@ function buildenvs(package) envs.RANLIB = package:build_getenv("ranlib") envs.CFLAGS = table.concat(cflags, ' ') envs.CXXFLAGS = table.concat(cxxflags, ' ') - envs.ASFLAGS = table.concat(table.wrap(package:build_getenv("asflags")), ' ') - envs.ARFLAGS = table.concat(table.wrap(package:build_getenv("arflags")), ' ') - envs.LDFLAGS = table.concat(table.wrap(package:build_getenv("ldflags")), ' ') - envs.SHFLAGS = table.concat(table.wrap(package:build_getenv("shflags")), ' ') + envs.ASFLAGS = table.concat(asflags, ' ') + envs.ARFLAGS = table.concat(arflags, ' ') + envs.LDFLAGS = table.concat(ldflags, ' ') + envs.SHFLAGS = table.concat(shflags, ' ') end local ACLOCAL_PATH = {} local PKG_CONFIG_PATH = {} -- cgit v1.3.1 From b5e74bb739c7e56e65f1f1103c16e7ac4dcfcfa1 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 24 Nov 2021 17:49:07 +0800 Subject: Update main.cpp --- tests/projects/c++/protobuf/src/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/projects/c++/protobuf/src/main.cpp b/tests/projects/c++/protobuf/src/main.cpp index 1e7830c17..dc06458ae 100644 --- a/tests/projects/c++/protobuf/src/main.cpp +++ b/tests/projects/c++/protobuf/src/main.cpp @@ -1,10 +1,11 @@ #include #include "test.pb.h" +#include "subdir/test2.pb.h" using namespace std; int main(int argc, char** argv) { - cout << "hello world!" << endl; + cout << "hello world!" << endl; return 0; } -- cgit v1.3.1 From a3e6076aff9fa5b3ad43ac2a3b1de88c61319a7d Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 24 Nov 2021 22:39:41 +0800 Subject: Update package.lua --- xmake/modules/private/action/require/impl/package.lua | 3 --- 1 file changed, 3 deletions(-) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 3bb12ac30..d920a95a1 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -573,9 +573,6 @@ function _inherit_parent_configs(requireinfo, package, parentinfo) if parentinfo.arch then requireinfo.arch = parentinfo.arch end - if parentinfo.private ~= nil then - requireinfo.private = parentinfo.private - end requireinfo_configs.toolchains = requireinfo_configs.toolchains or parentinfo_configs.toolchains requireinfo_configs.vs_runtime = requireinfo_configs.vs_runtime or parentinfo_configs.vs_runtime requireinfo.configs = requireinfo_configs -- cgit v1.3.1 From b7588b6bc50d511154b18bad81c3a659ce3e9437 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 25 Nov 2021 10:22:08 +0800 Subject: add mirror for repo --- xmake/modules/private/action/require/impl/repository.lua | 7 +++++-- xmake/plugins/repo/main.lua | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/xmake/modules/private/action/require/impl/repository.lua b/xmake/modules/private/action/require/impl/repository.lua index 8bd92aa04..189fad594 100644 --- a/xmake/modules/private/action/require/impl/repository.lua +++ b/xmake/modules/private/action/require/impl/repository.lua @@ -24,6 +24,7 @@ import("core.base.global") import("core.project.config") import("core.package.repository") import("devel.git") +import("net.proxy") -- get package directory from the locked repository function _get_packagedir_from_locked_repo(packagename, locked_repo) @@ -55,7 +56,8 @@ function _get_packagedir_from_locked_repo(packagename, locked_repo) git.clone(repo_global:directory(), {verbose = option.get("verbose"), outputdir = repodir_local}) lastcommit = repo_global:commit() elseif global.get("network") ~= "private" then - git.clone(locked_repo.url, {verbose = option.get("verbose"), branch = locked_repo.branch, outputdir = repodir_local}) + local remoteurl = proxy.mirror(locked_repo.url) or locked_repo.url + git.clone(remoteurl, {verbose = option.get("verbose"), branch = locked_repo.branch, outputdir = repodir_local}) else wprint("we cannot lock repository(%s) in private network mode!", locked_repo.url) return @@ -73,7 +75,8 @@ function _get_packagedir_from_locked_repo(packagename, locked_repo) if not ok then if global.get("network") ~= "private" then -- pull the latest commit - git.pull({verbose = option.get("verbose"), remote = locked_repo.url, branch = locked_repo.branch, repodir = repodir_local}) + local remoteurl = proxy.mirror(locked_repo.url) or locked_repo.url + git.pull({verbose = option.get("verbose"), remote = remoteurl, branch = locked_repo.branch, repodir = repodir_local}) -- re-checkout to the given commit ok = try {function () git.checkout(locked_repo.commit, {verbose = option.get("verbose"), repodir = repodir_local}); return true end} else diff --git a/xmake/plugins/repo/main.lua b/xmake/plugins/repo/main.lua index a4ec01b90..4baa1f540 100644 --- a/xmake/plugins/repo/main.lua +++ b/xmake/plugins/repo/main.lua @@ -25,6 +25,7 @@ import("core.project.project") import("core.platform.platform") import("core.package.repository") import("devel.git") +import("net.proxy") import("private.async.runjobs") import("private.action.require.impl.environment") @@ -45,7 +46,8 @@ function _add(name, url, branch, is_global) -- clone repository if not os.isdir(url) then - git.clone(url, {verbose = option.get("verbose"), branch = branch or "master", outputdir = repodir}) + local remoteurl = proxy.mirror(url) or url + git.clone(remoteurl, {verbose = option.get("verbose"), branch = branch or "master", outputdir = repodir}) end -- trace @@ -117,7 +119,8 @@ function _update() vprint("cloning repository(%s): %s to %s ..", repo:name(), repo:url(), repodir) -- clone it - git.clone(repo:url(), {verbose = option.get("verbose"), branch = repo:branch() or "master", outputdir = repodir}) + local remoteurl = proxy.mirror(repo:url()) or repo:url() + git.clone(remoteurl, {verbose = option.get("verbose"), branch = repo:branch() or "master", outputdir = repodir}) -- mark as updated io.save(path.join(repodir, "updated"), {}) -- cgit v1.3.1 From a77a0dc5b6c996e5a2a4296237fd0431f8804b09 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 25 Nov 2021 13:11:13 +0800 Subject: add rc/has flags --- xmake/modules/core/tools/rc.lua | 2 +- xmake/modules/detect/tools/rc/has_flags.lua | 68 +++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 xmake/modules/detect/tools/rc/has_flags.lua diff --git a/xmake/modules/core/tools/rc.lua b/xmake/modules/core/tools/rc.lua index 208161b67..6796c0fe0 100644 --- a/xmake/modules/core/tools/rc.lua +++ b/xmake/modules/core/tools/rc.lua @@ -25,7 +25,7 @@ import("private.tools.vstool") -- init it function init(self) - if winos.version():gt("winxp") then + if self:has_flags("-nologo", "mrcflags") then -- fix vs2008 on xp, e.g. fatal error RC1106: invalid option: -ologo self:set("mrcflags", "-nologo") end diff --git a/xmake/modules/detect/tools/rc/has_flags.lua b/xmake/modules/detect/tools/rc/has_flags.lua new file mode 100644 index 000000000..ac023c466 --- /dev/null +++ b/xmake/modules/detect/tools/rc/has_flags.lua @@ -0,0 +1,68 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file has_flags.lua +-- + +-- imports +import("core.cache.detectcache") +import("core.language.language") + +-- attempt to check it from the argument list +function _check_from_arglist(flags, opt) + + -- only one flag? + if #flags > 1 then + return + end + + -- make cache key + local key = "detect.tools.rc.has_flags" + + -- make allflags key + local flagskey = opt.program .. "_" .. (opt.programver or "") + + -- get all allflags from argument list + local allflags = detectcache:get2(key, flagskey) + if not allflags then + + -- get argument list + allflags = {} + local arglist = os.iorunv(opt.program, {"-?"}, {envs = opt.envs}) + if arglist then + for arg in arglist:gmatch("(/[%-%a%d]+)%s+") do + allflags[arg:gsub("/", "-")] = true + end + end + + -- save cache + detectcache:set2(key, flagskey, allflags) + detectcache:save() + end + return allflags[flags[1]:gsub("/", "-")] +end + +-- has_flags(flags)? +-- +-- @param opt the argument options, e.g. {toolname = "", program = "", programver = ""} +-- +-- @return true or false +-- +function main(flags, opt) + return _check_from_arglist(flags, opt) +end + -- cgit v1.3.1 From 7d58f6d48d9124e30c3613b4a62d3b940b929335 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 25 Nov 2021 16:53:41 +0800 Subject: Update find_package.lua --- xmake/modules/package/manager/vcpkg/find_package.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/package/manager/vcpkg/find_package.lua b/xmake/modules/package/manager/vcpkg/find_package.lua index 36df275ba..4b587be0a 100644 --- a/xmake/modules/package/manager/vcpkg/find_package.lua +++ b/xmake/modules/package/manager/vcpkg/find_package.lua @@ -109,7 +109,7 @@ function main(name, opt) end -- get linkdirs and links - if (plat == "windows" and line:endswith(".lib")) or line:endswith(".a") then + if (plat == "windows" and line:endswith(".lib")) or line:endswith(".a") or line:endswith(".so") then if line:find(triplet .. (mode == "debug" and "/debug" or "") .. "/lib/", 1, true) then result = result or {} result.links = result.links or {} -- cgit v1.3.1 From e2e14bba2335d9ea0a1de60a318c21efa4d067ef Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 26 Nov 2021 00:03:14 +0800 Subject: Update main.lua --- xmake/actions/update/main.lua | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/xmake/actions/update/main.lua b/xmake/actions/update/main.lua index ed403f47a..7437606fa 100644 --- a/xmake/actions/update/main.lua +++ b/xmake/actions/update/main.lua @@ -158,9 +158,17 @@ function _install(sourcedir) if os.isfile(win_installer_name) then -- /D sets the default installation directory ($INSTDIR), overriding InstallDir and InstallDirRegKey. It must be the last parameter used in the command line and must not contain any quotes, even if the path contains spaces. Only absolute paths are supported. local params = ("/D=" .. os.programdir()):split("%s", { strict = true }) - local testfile = path.join(os.programdir(), "temp-install") - local no_admin = os.trycp(path.join(os.programdir(), "scripts", "run.vbs"), testfile) - os.tryrm(testfile) + local no_admin = try {function () return winos.registry_query("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\XMake;NoAdmin") end} + if no_admin == nil then + no_admin = try {function () return winos.registry_query("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\XMake;NoAdmin") end} + end + if no_admin ~= nil then + no_admin = tostring(value):lower() == "true" + else + local testfile = path.join(os.programdir(), "temp-install") + no_admin = os.trycp(path.join(os.programdir(), "scripts", "run.vbs"), testfile) + os.tryrm(testfile) + end if no_admin then table.insert(params, 1, "/NOADMIN") end -- need UAC? if winos:version():gt("winxp") then -- cgit v1.3.1 From 7be0259a5187143abf2ae798ff0ca5720c15dc3d Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 26 Nov 2021 08:01:30 +0800 Subject: Update main.lua --- xmake/actions/update/main.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/actions/update/main.lua b/xmake/actions/update/main.lua index 7437606fa..94ea1b7aa 100644 --- a/xmake/actions/update/main.lua +++ b/xmake/actions/update/main.lua @@ -158,6 +158,7 @@ function _install(sourcedir) if os.isfile(win_installer_name) then -- /D sets the default installation directory ($INSTDIR), overriding InstallDir and InstallDirRegKey. It must be the last parameter used in the command line and must not contain any quotes, even if the path contains spaces. Only absolute paths are supported. local params = ("/D=" .. os.programdir()):split("%s", { strict = true }) + -- @see https://github.com/xmake-io/xmake/issues/1576 local no_admin = try {function () return winos.registry_query("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\XMake;NoAdmin") end} if no_admin == nil then no_admin = try {function () return winos.registry_query("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\XMake;NoAdmin") end} -- cgit v1.3.1 From ca005b27b32f68a990f1837a559e4a7d28785956 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 26 Nov 2021 12:45:20 +0800 Subject: Update select.c --- core/src/xmake/semver/select.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/core/src/xmake/semver/select.c b/core/src/xmake/semver/select.c index 395dc6f37..e820010b5 100644 --- a/core/src/xmake/semver/select.c +++ b/core/src/xmake/semver/select.c @@ -87,10 +87,11 @@ static tb_bool_t xm_semver_select_from_versions_tags2(lua_State* lua, tb_int_t f lua_gettable(lua, fromidx); tb_char_t const* source_str = luaL_checkstring(lua, -1); - if (source_str && tb_strncmp(source_str, version_str, version_len) == 0) + tb_size_t source_len = tb_strlen(source_str); + if (source_len == version_len && tb_strncmp(source_str, version_str, version_len) == 0) { lua_createtable(lua, 0, 2); - lua_pushstring(lua, source_str); + lua_pushlstring(lua, source_str, source_len); lua_setfield(lua, -2, "version"); lua_pushstring(lua, fromidx == 2? "version" : "tag"); lua_setfield(lua, -2, "source"); @@ -109,25 +110,17 @@ static tb_bool_t xm_semver_select_from_branches(lua_State* lua, tb_int_t fromidx lua_gettable(lua, fromidx); tb_char_t const* source_str = luaL_checkstring(lua, -1); - tb_check_continue(source_str); - tb_size_t source_len = tb_strlen(source_str); if (source_len == range_len && tb_memcmp(source_str, range_str, source_len) == 0) { lua_createtable(lua, 0, 2); - lua_pushlstring(lua, source_str, source_len); lua_setfield(lua, -2, "version"); - lua_pushstring(lua, "branch"); lua_setfield(lua, -2, "source"); - - // ok return tb_true; } } - - // no matches return tb_false; } static tb_bool_t xm_semver_select_latest_from_versions_tags(lua_State* lua, tb_int_t fromidx, semver_t* semver, semvers_t* matches) @@ -147,8 +140,6 @@ static tb_bool_t xm_semver_select_latest_from_versions_tags(lua_State* lua, tb_i if (source_str && semver_tryn(semver, source_str, tb_strlen(source_str)) == 0) semvers_ppush(matches, *semver); } - - // no matches? tb_check_return_val(matches->length, tb_false); // sort matches @@ -165,10 +156,7 @@ static tb_bool_t xm_semver_select_latest_from_versions_tags(lua_State* lua, tb_i lua_pushstring(lua, fromidx == 2? "version" : "tag"); lua_setfield(lua, -2, "source"); - // exit the popped semver semver_dtor(&top); - - // ok return tb_true; } -- cgit v1.3.1 From f25a332634cc2af78721212edf8c7713412c71e4 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 26 Nov 2021 13:02:11 +0800 Subject: Update main.lua --- xmake/actions/update/main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/actions/update/main.lua b/xmake/actions/update/main.lua index 94ea1b7aa..7db7eda58 100644 --- a/xmake/actions/update/main.lua +++ b/xmake/actions/update/main.lua @@ -164,7 +164,7 @@ function _install(sourcedir) no_admin = try {function () return winos.registry_query("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\XMake;NoAdmin") end} end if no_admin ~= nil then - no_admin = tostring(value):lower() == "true" + no_admin = tostring(no_admin):lower() == "true" else local testfile = path.join(os.programdir(), "temp-install") no_admin = os.trycp(path.join(os.programdir(), "scripts", "run.vbs"), testfile) -- cgit v1.3.1 From 312e6d46f70051ee012bc42bf75d386018d43b51 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 26 Nov 2021 14:35:04 +0800 Subject: Update repository.lua --- .../modules/import/core/package/repository.lua | 46 +++++++++++++--------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/xmake/core/sandbox/modules/import/core/package/repository.lua b/xmake/core/sandbox/modules/import/core/package/repository.lua index 5d8406094..5c21f5de5 100644 --- a/xmake/core/sandbox/modules/import/core/package/repository.lua +++ b/xmake/core/sandbox/modules/import/core/package/repository.lua @@ -110,15 +110,20 @@ function sandbox_core_package_repository.repositories(is_global) -- add artifacts urls local artifacts_urls = localcache.cache("repository"):get("artifacts_urls") if not artifacts_urls then - artifacts_urls = {"https://github.com/xmake-mirror/build-artifacts.git", - "https://gitlab.com/xmake-mirror/build-artifacts.git", - "https://gitee.com/xmake-mirror/build-artifacts.git"} - if global.get("network") ~= "private" then - import("net.fasturl") - fasturl.add(artifacts_urls) - artifacts_urls = fasturl.sort(artifacts_urls) - localcache.cache("repository"):set("artifacts_urls", artifacts_urls) - localcache.cache("repository"):save() + local binary_repo = os.getenv("XMAKE_BINARY_REPO") + if binary_repo then + artifacts_urls = {binary_repo} + else + artifacts_urls = {"https://github.com/xmake-mirror/build-artifacts.git", + "https://gitlab.com/xmake-mirror/build-artifacts.git", + "https://gitee.com/xmake-mirror/build-artifacts.git"} + if global.get("network") ~= "private" then + import("net.fasturl") + fasturl.add(artifacts_urls) + artifacts_urls = fasturl.sort(artifacts_urls) + localcache.cache("repository"):set("artifacts_urls", artifacts_urls) + localcache.cache("repository"):save() + end end end if #artifacts_urls > 0 then @@ -131,15 +136,20 @@ function sandbox_core_package_repository.repositories(is_global) -- add main urls local mainurls = localcache.cache("repository"):get("mainurls") if not mainurls then - mainurls = {"https://github.com/xmake-io/xmake-repo.git", - "https://gitlab.com/tboox/xmake-repo.git", - "https://gitee.com/tboox/xmake-repo.git"} - if global.get("network") ~= "private" then - import("net.fasturl") - fasturl.add(mainurls) - mainurls = fasturl.sort(mainurls) - localcache.cache("repository"):set("mainurls", mainurls) - localcache.cache("repository"):save() + local mainrepo = os.getenv("XMAKE_MAIN_REPO") + if mainrepo then + mainurls = {mainrepo} + else + mainurls = {"https://github.com/xmake-io/xmake-repo.git", + "https://gitlab.com/tboox/xmake-repo.git", + "https://gitee.com/tboox/xmake-repo.git"} + if global.get("network") ~= "private" then + import("net.fasturl") + fasturl.add(mainurls) + mainurls = fasturl.sort(mainurls) + localcache.cache("repository"):set("mainurls", mainurls) + localcache.cache("repository"):save() + end end end if #mainurls > 0 then -- cgit v1.3.1 From 7ea4d75b5d4162836663e79fbad29faf1fa82752 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 26 Nov 2021 14:37:03 +0800 Subject: Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbe71a6c9..8d634002b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ * [#1792](https://github.com/xmake-io/xmake/issues/1792): Add custom command in vs project generator * [#1835](https://github.com/xmake-io/xmake/issues/1835): Improve MDK program supports and add `set_runtimes("microlib")` * [#1858](https://github.com/xmake-io/xmake/issues/1858): Improve to build c++20 modules with libraries +* Add $XMAKE_BINARY_REPO and $XMAKE_MAIN_REPO repositories envs ### Bugs Fixed @@ -1150,6 +1151,7 @@ * [#1792](https://github.com/xmake-io/xmake/issues/1792): 添加自定义命令到 vs 工程生成器 * [#1835](https://github.com/xmake-io/xmake/issues/1835): 改进 MDK 程序构建支持,增加 `set_runtimes("microlib")` * [#1858](https://github.com/xmake-io/xmake/issues/1858): 改进构建 c++20 modules,修复跨 target 构建问题 +* 添加 $XMAKE_BINARY_REPO 和 $XMAKE_MAIN_REPO 仓库设置环境变量 ### Bugs 修复 -- cgit v1.3.1 From 81557919a07c23217cb3cd649d5641b771fca28b Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 26 Nov 2021 15:59:09 +0800 Subject: Update windows.yml --- .github/workflows/windows.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 1516a5984..b0eff3e40 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -68,6 +68,7 @@ jobs: Copy-Item ./core/build/xmake.exe ./xmake Copy-Item ./scripts/xrepo.bat ./xmake Copy-Item ./scripts/xrepo.ps1 ./xmake + $Env:XMAKE_MAIN_REPO = https://github.com/xmake-io/xmake-repo.git $Env:XMAKE_PROGRAM_DIR = $(Resolve-Path ./xmake) Set-Item -Path Env:Path -Value ($Env:XMAKE_PROGRAM_DIR + ";" + $Env:Path) xrepo --version -- cgit v1.3.1 From 61b187583720d27208d3976b1636d165f88e5d14 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 26 Nov 2021 16:08:53 +0800 Subject: Update windows.yml --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index b0eff3e40..03df3a38e 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -68,7 +68,7 @@ jobs: Copy-Item ./core/build/xmake.exe ./xmake Copy-Item ./scripts/xrepo.bat ./xmake Copy-Item ./scripts/xrepo.ps1 ./xmake - $Env:XMAKE_MAIN_REPO = https://github.com/xmake-io/xmake-repo.git + $Env:XMAKE_MAIN_REPO = "https://github.com/xmake-io/xmake-repo.git" $Env:XMAKE_PROGRAM_DIR = $(Resolve-Path ./xmake) Set-Item -Path Env:Path -Value ($Env:XMAKE_PROGRAM_DIR + ";" + $Env:Path) xrepo --version -- cgit v1.3.1 From 96964e1b26464abce774ba7d7524c7178b071195 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 26 Nov 2021 17:56:11 +0800 Subject: Update xmake-requires.lock --- .../package/toolchain_muslcc/xmake-requires.lock | 36 +++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock index 8cb57d3f4..05f143646 100644 --- a/tests/projects/package/toolchain_muslcc/xmake-requires.lock +++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock @@ -7,7 +7,7 @@ repo = { branch = "master", commit = "4498f11267de5112199152ab030ed139c985ad5a", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "2.71" }, @@ -15,7 +15,7 @@ repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "1.16.4" }, @@ -23,7 +23,7 @@ repo = { branch = "master", commit = "4498f11267de5112199152ab030ed139c985ad5a", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "3.21.0" }, @@ -31,7 +31,7 @@ repo = { branch = "master", commit = "89ac4c1e2d360bc3a8c3f4cdedf4ee683701de74", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "6.2.1" }, @@ -39,7 +39,7 @@ repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "0.22" }, @@ -47,7 +47,7 @@ repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "v1.3.4" }, @@ -55,7 +55,7 @@ repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "2.2.0" }, @@ -63,7 +63,7 @@ repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "2.4.6" }, @@ -71,7 +71,7 @@ repo = { branch = "master", commit = "89ac4c1e2d360bc3a8c3f4cdedf4ee683701de74", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "1.4.19" }, @@ -79,7 +79,7 @@ repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "20210202" }, @@ -87,7 +87,7 @@ repo = { branch = "master", commit = "89ac4c1e2d360bc3a8c3f4cdedf4ee683701de74", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "0.29.2" }, @@ -95,7 +95,7 @@ repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "1.2.11" } @@ -105,7 +105,7 @@ repo = { branch = "master", commit = "8e8c5e4d1c7e8b047b23333594d23b4b85163aed", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "3.21.0" }, @@ -113,7 +113,7 @@ repo = { branch = "master", commit = "2b1cb74b289ae3221241985db4401a495c42fde3", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "v1.3.4" }, @@ -121,7 +121,7 @@ repo = { branch = "master", commit = "2b1cb74b289ae3221241985db4401a495c42fde3", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "4.3" }, @@ -129,7 +129,7 @@ repo = { branch = "master", commit = "2b1cb74b289ae3221241985db4401a495c42fde3", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "20210202" }, @@ -137,9 +137,9 @@ repo = { branch = "master", commit = "2b1cb74b289ae3221241985db4401a495c42fde3", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "1.2.11" } } -} \ No newline at end of file +} -- cgit v1.3.1 From c5e54bde7d9b0cdbc0cf84c0cc9ca1590c60fb6b Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 26 Nov 2021 17:56:41 +0800 Subject: Update xmake-requires.lock --- tests/projects/package/multiconfig/xmake-requires.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/projects/package/multiconfig/xmake-requires.lock b/tests/projects/package/multiconfig/xmake-requires.lock index af73d677c..359015a18 100644 --- a/tests/projects/package/multiconfig/xmake-requires.lock +++ b/tests/projects/package/multiconfig/xmake-requires.lock @@ -7,7 +7,7 @@ repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "1.2.11" }, @@ -15,7 +15,7 @@ repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "1.2.11" }, @@ -23,9 +23,9 @@ repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", - url = "https://gitee.com/tboox/xmake-repo.git" + url = "https://github.com/xmake-io/xmake-repo.git" }, version = "1.2.11" } } -} \ No newline at end of file +} -- cgit v1.3.1 From 4e40a9197b6e2ec738fa882eade00777b89e23d9 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 27 Nov 2021 12:17:36 +0800 Subject: Update meson.lua --- xmake/modules/package/tools/meson.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/modules/package/tools/meson.lua b/xmake/modules/package/tools/meson.lua index 70e52f923..e4fa993ff 100644 --- a/xmake/modules/package/tools/meson.lua +++ b/xmake/modules/package/tools/meson.lua @@ -128,6 +128,7 @@ end -- get the build environments function buildenvs(package) local envs = {} + opt = opt or {} if package:is_plat(os.host()) then local cflags = table.join(table.wrap(package:config("cxflags")), package:config("cflags")) local cxxflags = table.join(table.wrap(package:config("cxflags")), package:config("cxxflags")) -- cgit v1.3.1 From 04a13fd238c754b55338f9debdcf09aff27427ee Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 28 Nov 2021 03:03:50 +0800 Subject: add builder:is --- xmake/core/tool/builder.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/xmake/core/tool/builder.lua b/xmake/core/tool/builder.lua index 91bb707f8..e3c5de456 100644 --- a/xmake/core/tool/builder.lua +++ b/xmake/core/tool/builder.lua @@ -442,6 +442,16 @@ function builder:map_flags(name, values, opt) end end +-- is the given name? +function builder:is(...) + local name = self:name() + for _, v in ipairs(table.join(...)) do + if v and name:find("^" .. v:gsub("%-", "%%-") .. "$") then + return true + end + end +end + -- get the format of the given target kind function builder:format(targetkind) local formats = self:get("formats") -- cgit v1.3.1 From 3726f42847029c73301a87937e80a9c78465fdb2 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 28 Nov 2021 03:11:08 +0800 Subject: add target:compiler --- xmake/core/project/target.lua | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 922d7d483..572764c90 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -582,21 +582,35 @@ function _instance:basename() return self:get("basename") or self:name() end --- get the target linker -function _instance:linker() - - -- get it from cache first - if self._LINKER then - return self._LINKER +-- get the target compiler +function _instance:compiler(sourcekind) + local compilerinst = self:_memcache():get("compiler") + if not compilerinst then + if not sourcekind then + os.raise("please pass sourcekind to the first argument of target:compiler(), e.g. cc, cxx, as") + end + local instance, errors = compiler.load(sourcekind, self) + if not instance then + os.raise(errors) + end + compilerinst = instance + self:_memcache():set("compiler", compilerinst) end + return compilerinst +end - -- get the linker instance - local instance, errors = linker.load(self:kind(), self:sourcekinds(), self) - if not instance then - os.raise(errors) +-- get the target linker +function _instance:linker() + local linkerinst = self:_memcache():get("linker") + if not linkerinst then + local instance, errors = linker.load(self:kind(), self:sourcekinds(), self) + if not instance then + os.raise(errors) + end + linkerinst = instance + self:_memcache():set("linker", linkerinst) end - self._LINKER = instance - return instance + return linkerinst end -- make linking command for this target -- cgit v1.3.1 From 6a315bad9fd1370c41ddd0f6cd48ae51dbf0d3f9 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 28 Nov 2021 13:36:54 +0800 Subject: add has_tool --- xmake/core/package/package.lua | 16 ++++++++++++++++ xmake/core/project/target.lua | 16 ++++++++++++++++ xmake/core/tool/builder.lua | 10 ---------- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 2d7534878..d47858e55 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -845,6 +845,22 @@ function _instance:toolconfig(name) end end +-- has the given tool for the current package? +-- +-- e.g. +-- +-- if package:has_tool("cc", "clang", "gcc") then +-- ... +-- end +function _instance:has_tool(toolkind, ...) + local _, toolname = self:tool(toolkind) + for _, v in ipairs(table.join(...)) do + if v and toolname:find("^" .. v:gsub("%-", "%%-") .. "$") then + return true + end + end +end + -- get the user private data function _instance:data(name) return self._DATA and self._DATA[name] or nil diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 572764c90..499db099c 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -1951,6 +1951,22 @@ function _instance:toolconfig(name) end}) end +-- has the given tool for the current target? +-- +-- e.g. +-- +-- if target:has_tool("cc", "clang", "gcc") then +-- ... +-- end +function _instance:has_tool(toolkind, ...) + local _, toolname = self:tool(toolkind) + for _, v in ipairs(table.join(...)) do + if v and toolname:find("^" .. v:gsub("%-", "%%-") .. "$") then + return true + end + end +end + -- get target apis function target.apis() diff --git a/xmake/core/tool/builder.lua b/xmake/core/tool/builder.lua index e3c5de456..91bb707f8 100644 --- a/xmake/core/tool/builder.lua +++ b/xmake/core/tool/builder.lua @@ -442,16 +442,6 @@ function builder:map_flags(name, values, opt) end end --- is the given name? -function builder:is(...) - local name = self:name() - for _, v in ipairs(table.join(...)) do - if v and name:find("^" .. v:gsub("%-", "%%-") .. "$") then - return true - end - end -end - -- get the format of the given target kind function builder:format(targetkind) local formats = self:get("formats") -- cgit v1.3.1 From 2a4d32b2d71850d1b78c5ffe93b1e164920f290a Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 28 Nov 2021 14:05:22 +0800 Subject: improve openmp tests --- tests/projects/openmp/hello/xmake.lua | 1 - tests/projects/openmp/loop/xmake.lua | 1 - 2 files changed, 2 deletions(-) diff --git a/tests/projects/openmp/hello/xmake.lua b/tests/projects/openmp/hello/xmake.lua index c1f837287..3bf3dccc4 100644 --- a/tests/projects/openmp/hello/xmake.lua +++ b/tests/projects/openmp/hello/xmake.lua @@ -2,5 +2,4 @@ add_requires("libomp", {optional = true}) target("hello") set_kind("binary") add_files("src/*.c") - add_rules("c.openmp") add_packages("libomp") diff --git a/tests/projects/openmp/loop/xmake.lua b/tests/projects/openmp/loop/xmake.lua index eb14be1a3..200e5f09f 100644 --- a/tests/projects/openmp/loop/xmake.lua +++ b/tests/projects/openmp/loop/xmake.lua @@ -2,5 +2,4 @@ add_requires("libomp", {optional = true}) target("loop") set_kind("binary") add_files("src/*.cpp") - add_rules("c++.openmp") add_packages("libomp") -- cgit v1.3.1 From ba46c0c19a03042c08943728a1d94b4df556a436 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 28 Nov 2021 14:08:38 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d634002b..63ba68175 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ * [#1835](https://github.com/xmake-io/xmake/issues/1835): Improve MDK program supports and add `set_runtimes("microlib")` * [#1858](https://github.com/xmake-io/xmake/issues/1858): Improve to build c++20 modules with libraries * Add $XMAKE_BINARY_REPO and $XMAKE_MAIN_REPO repositories envs +* [#1865](https://github.com/xmake-io/xmake/issues/1865): Improve openmp projects ### Bugs Fixed @@ -1152,6 +1153,7 @@ * [#1835](https://github.com/xmake-io/xmake/issues/1835): 改进 MDK 程序构建支持,增加 `set_runtimes("microlib")` * [#1858](https://github.com/xmake-io/xmake/issues/1858): 改进构建 c++20 modules,修复跨 target 构建问题 * 添加 $XMAKE_BINARY_REPO 和 $XMAKE_MAIN_REPO 仓库设置环境变量 +* [#1865](https://github.com/xmake-io/xmake/issues/1865): 改进 openmp 工程 ### Bugs 修复 -- cgit v1.3.1 From ea128c2d17c1d8bbfd8ac8ece36c708021c7b4b5 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 28 Nov 2021 14:12:30 +0800 Subject: add warning --- xmake/rules/c++/openmp/load.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/rules/c++/openmp/load.lua b/xmake/rules/c++/openmp/load.lua index a4535f553..86828cc52 100644 --- a/xmake/rules/c++/openmp/load.lua +++ b/xmake/rules/c++/openmp/load.lua @@ -20,6 +20,7 @@ -- main entry function main(target, sourcekind) + wprint("we no longer need add_rules(\"%s.openmp\") now, you just need to add add_packages(\"libomp\").", sourcekind == "cxx" and "c++" or "c") local _, compiler_name = target:tool(sourcekind) local flag_name = sourcekind == "cxx" and "cxxflags" or "cflags" if compiler_name == "cl" then -- cgit v1.3.1 From b3ee2219d8d1ec98de9fabfeb12be7675e178cd1 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 30 Nov 2021 10:12:03 +0800 Subject: Update xmake.lua --- tests/projects/openmp/hello/xmake.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/projects/openmp/hello/xmake.lua b/tests/projects/openmp/hello/xmake.lua index 3bf3dccc4..db12f0487 100644 --- a/tests/projects/openmp/hello/xmake.lua +++ b/tests/projects/openmp/hello/xmake.lua @@ -1,5 +1,5 @@ -add_requires("libomp", {optional = true}) +add_requires("openmp") target("hello") set_kind("binary") add_files("src/*.c") - add_packages("libomp") + add_packages("openmp") -- cgit v1.3.1 From cfa1ead056d11aef08971bcf9dcb2996d989515a Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 30 Nov 2021 10:12:29 +0800 Subject: Update xmake.lua --- tests/projects/openmp/loop/xmake.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/projects/openmp/loop/xmake.lua b/tests/projects/openmp/loop/xmake.lua index 200e5f09f..e1d0ab721 100644 --- a/tests/projects/openmp/loop/xmake.lua +++ b/tests/projects/openmp/loop/xmake.lua @@ -1,5 +1,5 @@ -add_requires("libomp", {optional = true}) +add_requires("openmp") target("loop") set_kind("binary") add_files("src/*.cpp") - add_packages("libomp") + add_packages("openmp") -- cgit v1.3.1 From 5463aadf3a10a0c13d6df3de714a45b422d38df0 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 30 Nov 2021 10:39:10 +0800 Subject: Update find_package.lua --- .../package/manager/pacman/find_package.lua | 24 +++++++--------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/xmake/modules/package/manager/pacman/find_package.lua b/xmake/modules/package/manager/pacman/find_package.lua index 0f38a92fc..fd936af40 100644 --- a/xmake/modules/package/manager/pacman/find_package.lua +++ b/xmake/modules/package/manager/pacman/find_package.lua @@ -20,6 +20,7 @@ -- imports import("core.base.option") +import("core.project.target") import("lib.detect.find_tool") import("package.manager.pkgconfig.find_package", {alias = "find_package_from_pkgconfig"}) @@ -56,31 +57,20 @@ function _find_package_from_list(list, name, pacman, opt) -- remove lib and .a, .dll.a and .so to have the links elseif line:endswith(".dll.a") then -- only for mingw local apath = os.iorunv(cygpath.program, {"--windows", line}) + apath = apath:trim() table.insert(result.linkdirs, path.directory(apath)) - apath = path.filename(apath) - if apath:startswith("lib") then - apath = apath:sub(4, apath:len()) - end - table.insert(result.links, apath:sub(1, apath:len() - 7)) + table.insert(result.links, target.linkname(path.filename(apath), {plat = opt.plat})) elseif line:endswith(".so") then - local apath = line - table.insert(result.linkdirs, path.directory(apath)) - apath = path.filename(apath) - if apath:startswith("lib") then - apath = apath:sub(4, apath:len()) - end - table.insert(result.links, apath:sub(1, apath:len() - 4)) + table.insert(result.linkdirs, path.directory(line)) + table.insert(result.links, target.linkname(path.filename(line), {plat = opt.plat})) elseif line:endswith(".a") then local apath = line if is_subhost("msys") and opt.plat == "mingw" then apath = os.iorunv(cygpath.program, {"--windows", line}) + apath = apath:trim() end table.insert(result.linkdirs, path.directory(apath)) - apath = path.filename(apath) - if apath:startswith("lib") then - apath = apath:sub(4, apath:len()) - end - table.insert(result.links, apath:sub(1, apath:len() - 3)) + table.insert(result.links, target.linkname(path.filename(apath), {plat = opt.plat})) end end result.includedirs = table.unique(result.includedirs) -- cgit v1.3.1 From 2cbe2a372389e8a20b6e509b74b6ce331fa1a626 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 30 Nov 2021 12:14:55 +0800 Subject: Update package.lua --- xmake/core/package/package.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index d47858e55..5da349187 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -1421,9 +1421,7 @@ function _instance:fetch_linkdeps() fetchinfo = table.copy(fetchinfo) -- avoid the cached fetchinfo be modified local linkdeps = self:linkdeps() if linkdeps then - local total = #linkdeps - for idx, _ in ipairs(linkdeps) do - local dep = linkdeps[total + 1 - idx] + for _, dep in ipairs(linkdeps) do local depinfo = dep:fetch() if depinfo then for name, values in pairs(depinfo) do -- cgit v1.3.1 From dad63cc0315dc2e6a39e415addab470ecb1dd8c7 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 30 Nov 2021 19:43:22 +0800 Subject: Update load.lua --- xmake/rules/c++/openmp/load.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/c++/openmp/load.lua b/xmake/rules/c++/openmp/load.lua index 86828cc52..3f0508512 100644 --- a/xmake/rules/c++/openmp/load.lua +++ b/xmake/rules/c++/openmp/load.lua @@ -20,7 +20,7 @@ -- main entry function main(target, sourcekind) - wprint("we no longer need add_rules(\"%s.openmp\") now, you just need to add add_packages(\"libomp\").", sourcekind == "cxx" and "c++" or "c") + wprint("we no longer need add_rules(\"%s.openmp\") now, you just need to add add_packages(\"openmp\").", sourcekind == "cxx" and "c++" or "c") local _, compiler_name = target:tool(sourcekind) local flag_name = sourcekind == "cxx" and "cxxflags" or "cflags" if compiler_name == "cl" then -- cgit v1.3.1 From b5af4b27137ab12de8a53a7e62cf004eb488ba5f Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 30 Nov 2021 20:37:49 +0800 Subject: Update PKGBUILD --- scripts/archlinux/PKGBUILD | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/archlinux/PKGBUILD b/scripts/archlinux/PKGBUILD index 2d17c0dfe..445e51047 100755 --- a/scripts/archlinux/PKGBUILD +++ b/scripts/archlinux/PKGBUILD @@ -2,15 +2,16 @@ # PKGBuild Create By: lumpyzhu pkgname=xmake -pkgver=2.3.2 +pkgver=2.5.9 pkgrel=1 -pkgdesc="A make-like build utility based on Lua" +pkgdesc="A cross-platform build utility based on Lua" +depends=('bash') arch=('i686' 'x86_64') url="https://github.com/xmake-io/xmake" license=('Apache') makedepends=() -source=("$pkgname.tar.gz::https://github.com/xmake-io/xmake/releases/download/v${pkgver}/xmake-v${pkgver}.tar.gz") -sha256sums=('b189074320ce1b215f85f8f20142fe173d981eb17c2c157f0fa6756fc00dac4e') +source=("https://github.com/xmake-io/xmake/releases/download/v${pkgver}/xmake-v${pkgver}.tar.gz") +sha256sums=('5b50e3f28956cabcaa153624c91781730387ceb7c056f3f9b5306b1c77460d8f') build() { cd "$srcdir" -- cgit v1.3.1 From 03ba395bd4e5057853907ba0d536707d710379a4 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 30 Nov 2021 23:09:45 +0800 Subject: add utils.glsl2spc --- tests/projects/other/glsl2spv/.gitignore | 8 ++ tests/projects/other/glsl2spv/src/main.c | 16 ++++ tests/projects/other/glsl2spv/src/test.frag | 6 ++ tests/projects/other/glsl2spv/src/test.vert | 5 ++ tests/projects/other/glsl2spv/xmake.lua | 9 +++ .../modules/detect/tools/find_glslangValidator.lua | 52 +++++++++++++ xmake/modules/detect/tools/find_glslc.lua | 61 +++++++++++++++ xmake/rules/utils/bin2c/xmake.lua | 4 +- xmake/rules/utils/glsl2spv/xmake.lua | 90 ++++++++++++++++++++++ 9 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 tests/projects/other/glsl2spv/.gitignore create mode 100644 tests/projects/other/glsl2spv/src/main.c create mode 100644 tests/projects/other/glsl2spv/src/test.frag create mode 100644 tests/projects/other/glsl2spv/src/test.vert create mode 100644 tests/projects/other/glsl2spv/xmake.lua create mode 100644 xmake/modules/detect/tools/find_glslangValidator.lua create mode 100644 xmake/modules/detect/tools/find_glslc.lua create mode 100644 xmake/rules/utils/glsl2spv/xmake.lua diff --git a/tests/projects/other/glsl2spv/.gitignore b/tests/projects/other/glsl2spv/.gitignore new file mode 100644 index 000000000..152105761 --- /dev/null +++ b/tests/projects/other/glsl2spv/.gitignore @@ -0,0 +1,8 @@ +# Xmake cache +.xmake/ +build/ + +# MacOS Cache +.DS_Store + + diff --git a/tests/projects/other/glsl2spv/src/main.c b/tests/projects/other/glsl2spv/src/main.c new file mode 100644 index 000000000..56e54d771 --- /dev/null +++ b/tests/projects/other/glsl2spv/src/main.c @@ -0,0 +1,16 @@ +#include + +static unsigned char g_test_vert_spv_data[] = { + #include "test.vert.spv.h" +}; + +static unsigned char g_test_frag_spv_data[] = { + #include "test.frag.spv.h" +}; + +int main(int argc, char** argv) +{ + printf("test.vert.spv: %s, size: %d\n", g_test_vert_spv_data, (int)sizeof(g_test_vert_spv_data)); + printf("test.frag.spv: %s, size: %d\n", g_test_frag_spv_data, (int)sizeof(g_test_frag_spv_data)); + return 0; +} diff --git a/tests/projects/other/glsl2spv/src/test.frag b/tests/projects/other/glsl2spv/src/test.frag new file mode 100644 index 000000000..9aeec4257 --- /dev/null +++ b/tests/projects/other/glsl2spv/src/test.frag @@ -0,0 +1,6 @@ +#version 330 +precision mediump float; + +void main() { +} + diff --git a/tests/projects/other/glsl2spv/src/test.vert b/tests/projects/other/glsl2spv/src/test.vert new file mode 100644 index 000000000..31dedf3e7 --- /dev/null +++ b/tests/projects/other/glsl2spv/src/test.vert @@ -0,0 +1,5 @@ +#version 330 +precision mediump float; + +void main() { +} diff --git a/tests/projects/other/glsl2spv/xmake.lua b/tests/projects/other/glsl2spv/xmake.lua new file mode 100644 index 000000000..3dfce3ed4 --- /dev/null +++ b/tests/projects/other/glsl2spv/xmake.lua @@ -0,0 +1,9 @@ +add_rules("mode.debug", "mode.release") + +target("test") + set_kind("binary") + add_rules("utils.glsl2spv", {bin2c = true}) + add_files("src/*.c") + add_files("src/*.vert", "src/*.frag") + + diff --git a/xmake/modules/detect/tools/find_glslangValidator.lua b/xmake/modules/detect/tools/find_glslangValidator.lua new file mode 100644 index 000000000..93bc94670 --- /dev/null +++ b/xmake/modules/detect/tools/find_glslangValidator.lua @@ -0,0 +1,52 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_glslangValidator.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find glslangValidator +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local glslangValidator = find_glslangValidator() +-- local glslangValidator, version = find_glslangValidator({program = "glslangValidator", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "glslangValidator", opt) + + -- find program version + local version = nil + if program and opt.version then + version = find_programver(program, opt) + end + return program, version +end diff --git a/xmake/modules/detect/tools/find_glslc.lua b/xmake/modules/detect/tools/find_glslc.lua new file mode 100644 index 000000000..ada89e672 --- /dev/null +++ b/xmake/modules/detect/tools/find_glslc.lua @@ -0,0 +1,61 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_glslc.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") +import("core.tool.toolchain") + +-- find glslc +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local glslc = find_glslc() +-- local glslc, version = find_glslc({program = "glslc", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "glslc", opt) + if not program and is_plat("android") then + local ndk = toolchain.load("ndk"):config("ndk") + if ndk then + local prebuilt = (is_host("macosx") and "darwin" or os.host()) .. "-x86_64" + opt.paths = path.join(ndk, "shader-tools", prebuilt) + program = find_program(opt.program or "glslc", opt) + end + end + + -- find program version + local version = nil + if program and opt.version then + version = find_programver(program, opt) + end + return program, version +end diff --git a/xmake/rules/utils/bin2c/xmake.lua b/xmake/rules/utils/bin2c/xmake.lua index 03d27a534..77f81125c 100644 --- a/xmake/rules/utils/bin2c/xmake.lua +++ b/xmake/rules/utils/bin2c/xmake.lua @@ -21,7 +21,7 @@ rule("utils.bin2c") set_extensions(".bin") on_load(function (target) - local headerdir = path.join(target:autogendir(), "rules", "c++", "bin2c") + local headerdir = path.join(target:autogendir(), "rules", "utils", "bin2c") if not os.isdir(headerdir) then os.mkdir(headerdir) end @@ -30,7 +30,7 @@ rule("utils.bin2c") before_buildcmd_file(function (target, batchcmds, sourcefile_bin, opt) -- get header file - local headerdir = path.join(target:autogendir(), "rules", "c++", "bin2c") + local headerdir = path.join(target:autogendir(), "rules", "utils", "bin2c") local headerfile = path.join(headerdir, path.filename(sourcefile_bin) .. ".h") target:add("includedirs", headerdir) diff --git a/xmake/rules/utils/glsl2spv/xmake.lua b/xmake/rules/utils/glsl2spv/xmake.lua new file mode 100644 index 000000000..d34c670ec --- /dev/null +++ b/xmake/rules/utils/glsl2spv/xmake.lua @@ -0,0 +1,90 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +-- compile glsl shader to spirv file, .spv +-- +-- e.g. +-- compile *.vert/*.frag to *.vert.spv/*.frag.spv files +-- add_rules("utils.glsl2spv", {outputdir = "build"}) +-- +-- compile *.vert/*.frag and generate binary c header files +-- add_rules("utils.glsl2spv", {bin2c = true}) +-- +-- in c code: +-- static unsigned char g_test_frag_spv_data[] = { +-- #include "test.frag.spv.h" +-- }; +-- +-- +rule("utils.glsl2spv") + set_extensions(".vert", ".frag") + on_load(function (target) + local is_bin2c = target:extraconf("rules", "utils.glsl2spv", "bin2c") + if is_bin2c then + local headerdir = path.join(target:autogendir(), "rules", "utils", "glsl2spv") + if not os.isdir(headerdir) then + os.mkdir(headerdir) + end + target:add("includedirs", headerdir) + end + end) + before_buildcmd_file(function (target, batchcmds, sourcefile_glsl, opt) + import("lib.detect.find_tool") + + -- get glslangValidator + local glslc + local glslangValidator = find_tool("glslangValidator") + if not glslangValidator then + glslc = find_tool("glslc") + end + assert(glslangValidator or glslc, "glslangValidator or glslc not found!") + + -- glsl to spv + local outputdir = target:extraconf("rules", "utils.glsl2spv", "outputdir") or path.join(target:autogendir(), "rules", "utils", "glsl2spv") + local spvfilepath = path.join(outputdir, path.filename(sourcefile_glsl) .. ".spv") + batchcmds:show_progress(opt.progress, "${color.build.object}generating.glsl2spv %s", sourcefile_glsl) + batchcmds:mkdir(outputdir) + if glslangValidator then + batchcmds:vrunv(glslangValidator.program, {"-V", "-o", spvfilepath, sourcefile_glsl}) + else + batchcmds:vrunv(glslc.program, {"-o", spvfilepath, sourcefile_glsl}) + end + + -- do bin2c + local outputfile = spvfilepath + local is_bin2c = target:extraconf("rules", "utils.glsl2spv", "bin2c") + if is_bin2c then + -- get header file + local headerdir = outputdir + local headerfile = path.join(headerdir, path.filename(spvfilepath) .. ".h") + target:add("includedirs", headerdir) + outputfile = headerfile + + -- add commands + local argv = {"lua", "private.utils.bin2c", "-i", spvfilepath, "-o", headerfile} + batchcmds:vrunv(os.programfile(), argv, {envs = {XMAKE_SKIP_HISTORY = "y"}}) + end + + -- add deps + batchcmds:add_depfiles(sourcefile_glsl) + batchcmds:set_depmtime(os.mtime(outputfile)) + batchcmds:set_depcache(target:dependfile(outputfile)) + end) + -- cgit v1.3.1 From f5ebc92c117205a3996d06252beca1f6cecdb8f4 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 30 Nov 2021 23:10:03 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63ba68175..27dfd9f39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### New features * [#1799](https://github.com/xmake-io/xmake/issues/1799): Support mixed rust & c++ target and cargo dependences +* Add `utils.glsl2spv` rules to compile *.vert/*.frag shader files to spirv file and binary c header file ### Changes @@ -1141,6 +1142,7 @@ ### 新特性 * [#1799](https://github.com/xmake-io/xmake/issues/1799): 支持混合 Rust 和 C++ 程序,以及集成 Cargo 依赖库 +* 添加 `utils.glsl2spv` 规则去编译 *.vert/*.frag shader 文件生成 spirv 文件和二进制 C 头文件 ### 改进 -- cgit v1.3.1 From aa1e9800160ce3de87630f0f619d422538b35d11 Mon Sep 17 00:00:00 2001 From: biobot Date: Wed, 1 Dec 2021 11:27:57 +0800 Subject: Add more glsl extensions Signed-off-by: biobot --- xmake/rules/utils/glsl2spv/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/utils/glsl2spv/xmake.lua b/xmake/rules/utils/glsl2spv/xmake.lua index d34c670ec..1ffd02089 100644 --- a/xmake/rules/utils/glsl2spv/xmake.lua +++ b/xmake/rules/utils/glsl2spv/xmake.lua @@ -34,7 +34,7 @@ -- -- rule("utils.glsl2spv") - set_extensions(".vert", ".frag") + set_extensions(".vert", ".frag", ".tesc", ".tese", ".geom", ".comp", ".glsl") on_load(function (target) local is_bin2c = target:extraconf("rules", "utils.glsl2spv", "bin2c") if is_bin2c then -- cgit v1.3.1 From a4b6edd7ec3c8115caf883c6ea23e7d0c9f649eb Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Dec 2021 09:10:02 +0800 Subject: Update xmake.lua --- tests/projects/other/glsl2spv/xmake.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/projects/other/glsl2spv/xmake.lua b/tests/projects/other/glsl2spv/xmake.lua index 3dfce3ed4..111927e56 100644 --- a/tests/projects/other/glsl2spv/xmake.lua +++ b/tests/projects/other/glsl2spv/xmake.lua @@ -1,9 +1,11 @@ add_rules("mode.debug", "mode.release") +add_requires("glslang", {configs = {binaryonly = true}}) + target("test") set_kind("binary") add_rules("utils.glsl2spv", {bin2c = true}) add_files("src/*.c") add_files("src/*.vert", "src/*.frag") - + add_packages("glslang") -- cgit v1.3.1 From a90ff45e12c17e3888716bd9dfcdebf4faadd704 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Dec 2021 09:29:59 +0800 Subject: Update cl.lua --- xmake/modules/core/tools/cl.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/core/tools/cl.lua b/xmake/modules/core/tools/cl.lua index c4cf109bf..d84f4c7c1 100644 --- a/xmake/modules/core/tools/cl.lua +++ b/xmake/modules/core/tools/cl.lua @@ -118,7 +118,7 @@ function nf_symbols(self, levels, target) end -- check and add symbol output file - local pdbflags = "-Fd" .. path.join(symboldir, "compile." .. path.filename(symbolfile)) + local pdbflags = "-Fd" .. (target:is_static() and symbolfile or path.join(symboldir, "compile." .. path.filename(symbolfile))) if self:has_flags({"-FS", "-Fd" .. os.nuldev() .. ".pdb"}, "cxflags", { flagskey = "-FS -Fd" }) then pdbflags = {"-FS", pdbflags} end -- cgit v1.3.1 From bac9526a3f5ed8a634edea456e22cb5e17e3eba9 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Dec 2021 09:35:54 +0800 Subject: Update windows.lua --- xmake/modules/target/action/install/windows.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xmake/modules/target/action/install/windows.lua b/xmake/modules/target/action/install/windows.lua index 0ea1e22b6..dfbcad11f 100644 --- a/xmake/modules/target/action/install/windows.lua +++ b/xmake/modules/target/action/install/windows.lua @@ -76,6 +76,7 @@ function install_binary(target, opt) local binarydir = path.join(target:installdir(), opt and opt.bindir or "bin") os.mkdir(binarydir) os.vcp(target:targetfile(), binarydir) + os.trycp(target:symbolfile(), binarydir) -- install the dependent shared/windows (*.dll) target -- @see https://github.com/xmake-io/xmake/issues/961 @@ -105,6 +106,7 @@ function install_shared(target, opt) local binarydir = path.join(target:installdir(), opt and opt.bindir or "bin") os.mkdir(binarydir) os.vcp(target:targetfile(), binarydir) + os.trycp(target:symbolfile(), binarydir) -- install *.lib for shared/windows (*.dll) target -- @see https://github.com/xmake-io/xmake/issues/714 @@ -130,6 +132,7 @@ function install_static(target, opt) local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib") os.mkdir(librarydir) os.vcp(target:targetfile(), librarydir) + os.trycp(target:symbolfile(), librarydir) -- install headers _install_headers(target, opt) -- cgit v1.3.1 From 86bcaa84dea7e8bbc6f61b14b33fc7c47fd47afd Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Dec 2021 09:37:49 +0800 Subject: Update windows.lua --- xmake/modules/target/action/uninstall/windows.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xmake/modules/target/action/uninstall/windows.lua b/xmake/modules/target/action/uninstall/windows.lua index 73c43cc0a..ed6923567 100644 --- a/xmake/modules/target/action/uninstall/windows.lua +++ b/xmake/modules/target/action/uninstall/windows.lua @@ -56,6 +56,7 @@ function uninstall_binary(target, opt) -- remove the target file local binarydir = path.join(target:installdir(), opt and opt.bindir or "bin") os.vrm(path.join(binarydir, path.filename(target:targetfile()))) + os.tryrm(path.join(binarydir, path.filename(target:symbolfile()))) -- remove the dependent shared/windows (*.dll) target -- @see https://github.com/xmake-io/xmake/issues/961 @@ -76,6 +77,7 @@ function uninstall_shared(target, opt) -- remove the target file local binarydir = path.join(target:installdir(), opt and opt.bindir or "bin") os.vrm(path.join(binarydir, path.filename(target:targetfile()))) + os.tryrm(path.join(binarydir, path.filename(target:symbolfile()))) -- remove *.lib for shared/windows (*.dll) target -- @see https://github.com/xmake-io/xmake/issues/714 @@ -96,6 +98,7 @@ function uninstall_static(target, opt) -- remove the target file local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib") os.vrm(path.join(librarydir, path.filename(target:targetfile()))) + os.tryrm(path.join(librarydir, path.filename(target:symbolfile()))) -- remove headers from the include directory _uninstall_headers(target, opt) -- cgit v1.3.1 From 690d8ae73adb4e568d62c3b082f4b2d079a20bb6 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Dec 2021 09:46:43 +0800 Subject: Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27dfd9f39..a0360f917 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ * [#1858](https://github.com/xmake-io/xmake/issues/1858): Improve to build c++20 modules with libraries * Add $XMAKE_BINARY_REPO and $XMAKE_MAIN_REPO repositories envs * [#1865](https://github.com/xmake-io/xmake/issues/1865): Improve openmp projects +* [#1845](https://github.com/xmake-io/xmake/issues/1845): Install pdb files for static library ### Bugs Fixed @@ -1156,6 +1157,7 @@ * [#1858](https://github.com/xmake-io/xmake/issues/1858): 改进构建 c++20 modules,修复跨 target 构建问题 * 添加 $XMAKE_BINARY_REPO 和 $XMAKE_MAIN_REPO 仓库设置环境变量 * [#1865](https://github.com/xmake-io/xmake/issues/1865): 改进 openmp 工程 +* [#1845](https://github.com/xmake-io/xmake/issues/1845): 为静态库安装 pdb 文件 ### Bugs 修复 -- cgit v1.3.1 From f29f664a99086e336b40e02dda29d60a22f300e7 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Thu, 2 Dec 2021 11:55:12 +0100 Subject: Add -FC after depends check (fix #1824) --- xmake/modules/core/tools/cl.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/xmake/modules/core/tools/cl.lua b/xmake/modules/core/tools/cl.lua index d84f4c7c1..14bc19544 100644 --- a/xmake/modules/core/tools/cl.lua +++ b/xmake/modules/core/tools/cl.lua @@ -34,12 +34,6 @@ function init(self) -- init cxflags self:set("cxflags", "-nologo") - -- we need show full file path to goto error position if xmake is called in vstudio - -- https://github.com/xmake-io/xmake/issues/1049 - if os.getenv("XMAKE_IN_VSTUDIO") then - self:add("cxflags", "-FC") - end - -- init flags map self:set("mapflags", { @@ -413,12 +407,19 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) -- generate includes file local compflags = flags + + -- we need show full file path to goto error position if xmake is called in vstudio + -- https://github.com/xmake-io/xmake/issues/1049 + if os.getenv("XMAKE_IN_VSTUDIO") then + compflags = table.join(compflags, "-FC") + end + if dependinfo then if _has_source_dependencies(self) then depfile = os.tmpfile() - compflags = table.join(flags, "/sourceDependencies", depfile) + compflags = table.join(compflags, "/sourceDependencies", depfile) else - compflags = table.join(flags, "-showIncludes") + compflags = table.join(compflags, "-showIncludes") end end @@ -504,4 +505,3 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) end end end - -- cgit v1.3.1 From 1772c8d130113aabc407f1824919c79e4a0b8488 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Thu, 2 Dec 2021 12:18:43 +0100 Subject: Cache XMAKE_IN_VSTUDIO --- xmake/modules/core/tools/cl.lua | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/xmake/modules/core/tools/cl.lua b/xmake/modules/core/tools/cl.lua index 14bc19544..ba88a0d03 100644 --- a/xmake/modules/core/tools/cl.lua +++ b/xmake/modules/core/tools/cl.lua @@ -375,6 +375,15 @@ function _has_source_dependencies(self) return has_source_dependencies end +function _is_in_vstudio() + local is_in_vstudio = _g._IS_IN_VSTUDIO + if is_in_vstudio == nil then + is_in_vstudio = os.getenv("XMAKE_IN_VSTUDIO") + _g._IS_IN_VSTUDIO = is_in_vstudio + end + return is_in_vstudio +end + -- make the compile arguments list function compargv(self, sourcefile, objectfile, flags, opt) @@ -410,7 +419,7 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) -- we need show full file path to goto error position if xmake is called in vstudio -- https://github.com/xmake-io/xmake/issues/1049 - if os.getenv("XMAKE_IN_VSTUDIO") then + if _is_in_vstudio() then compflags = table.join(compflags, "-FC") end -- cgit v1.3.1 From 5bd0628dace1c00671055e03d26b8de180e223ac Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Thu, 2 Dec 2021 12:21:16 +0100 Subject: Don't copy table everytime --- xmake/modules/core/tools/cl.lua | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/xmake/modules/core/tools/cl.lua b/xmake/modules/core/tools/cl.lua index ba88a0d03..b8beceac1 100644 --- a/xmake/modules/core/tools/cl.lua +++ b/xmake/modules/core/tools/cl.lua @@ -417,18 +417,22 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) -- generate includes file local compflags = flags - -- we need show full file path to goto error position if xmake is called in vstudio - -- https://github.com/xmake-io/xmake/issues/1049 - if _is_in_vstudio() then - compflags = table.join(compflags, "-FC") - end - if dependinfo then if _has_source_dependencies(self) then depfile = os.tmpfile() - compflags = table.join(compflags, "/sourceDependencies", depfile) + compflags = table.join(flags, "/sourceDependencies", depfile) + else + compflags = table.join(flags, "-showIncludes") + end + end + + -- we need show full file path to goto error position if xmake is called in vstudio + -- https://github.com/xmake-io/xmake/issues/1049 + if _is_in_vstudio() then + if compflags == flags then + compflags = table.join(flags, "-FC") else - compflags = table.join(compflags, "-showIncludes") + table.join2(compflags, "-FC") end end -- cgit v1.3.1 From 10f997a414f875212d41964fdea503f89a95f87f Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Thu, 2 Dec 2021 12:30:45 +0100 Subject: Fix _is_in_vstudio caching --- xmake/modules/core/tools/cl.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/core/tools/cl.lua b/xmake/modules/core/tools/cl.lua index b8beceac1..a519d1618 100644 --- a/xmake/modules/core/tools/cl.lua +++ b/xmake/modules/core/tools/cl.lua @@ -378,7 +378,7 @@ end function _is_in_vstudio() local is_in_vstudio = _g._IS_IN_VSTUDIO if is_in_vstudio == nil then - is_in_vstudio = os.getenv("XMAKE_IN_VSTUDIO") + is_in_vstudio = os.getenv("XMAKE_IN_VSTUDIO") or false _g._IS_IN_VSTUDIO = is_in_vstudio end return is_in_vstudio -- cgit v1.3.1 From c24bb8112427a14e8ef0e0232750e2e740e5355d Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Dec 2021 22:44:32 +0800 Subject: Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c922cd554..89b4e2111 100644 --- a/README.md +++ b/README.md @@ -461,11 +461,11 @@ target("test") ## Plugins -#### Generate IDE project file plugin(makefile, vs2002 - vs2019 .. ) +#### Generate IDE project file plugin(makefile, vs2002 - vs2022 .. ) ```bash -$ xmake project -k vsxmake -m "debug;release" # New vsproj generator (Recommended) -$ xmake project -k vs -m "debug;release" +$ xmake project -k vsxmake -m "debug,release" # New vsproj generator (Recommended) +$ xmake project -k vs -m "debug,release" $ xmake project -k cmake $ xmake project -k ninja $ xmake project -k compile_commands @@ -513,7 +513,7 @@ We can uses [xmake-gradle](https://github.com/xmake-io/xmake-gradle) plugin to c ``` plugins { - id 'org.tboox.gradle-xmake-plugin' version '1.1.4' + id 'org.tboox.gradle-xmake-plugin' version '1.1.5' } android { -- cgit v1.3.1 From ee078474ce694c21ccf8f3a3689696929d61a809 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Dec 2021 22:45:14 +0800 Subject: Update README_zh.md --- README_zh.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README_zh.md b/README_zh.md index 806f25274..9f26f1f56 100644 --- a/README_zh.md +++ b/README_zh.md @@ -469,11 +469,11 @@ target("test") ## 插件 -#### 生成IDE工程文件插件(makefile, vs2002 - vs2019, ...) +#### 生成IDE工程文件插件(makefile, vs2002 - vs2022, ...) ```bash -$ xmake project -k vsxmake -m "debug;release" # 新版vs工程生成插件(推荐) -$ xmake project -k vs -m "debug;release" +$ xmake project -k vsxmake -m "debug,release" # 新版vs工程生成插件(推荐) +$ xmake project -k vs -m "debug,release" $ xmake project -k cmake $ xmake project -k ninja $ xmake project -k compile_commands @@ -521,7 +521,7 @@ $ xmake l ``` plugins { - id 'org.tboox.gradle-xmake-plugin' version '1.1.4' + id 'org.tboox.gradle-xmake-plugin' version '1.1.5' } android { -- cgit v1.3.1 From 82983f1e86061f3a867aef4fc4636fb8d04fd8ae Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Dec 2021 22:49:15 +0800 Subject: Update xmake.spec --- scripts/rpmbuild/SPECS/xmake.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/rpmbuild/SPECS/xmake.spec b/scripts/rpmbuild/SPECS/xmake.spec index e8eee1e75..f512d59c7 100644 --- a/scripts/rpmbuild/SPECS/xmake.spec +++ b/scripts/rpmbuild/SPECS/xmake.spec @@ -1,5 +1,5 @@ %define xmake_revision 96d398228e9ae045973af9c656a09c7376f9582c -%define tbox_revision 7ca5145d40aa906fdc48b0b0e75e80412241be7e +%define tbox_revision 122a479e626ee3fdd7d6c1117ec7c19212a1e087 %define sv_revision 035262773da0500367cb88e6f30197908159a348 %define lua_cjson_revision 515bab6d6d80b164b94db73af69609ea02f3a798 %define luajit_revision e9af1abec542e6f9851ff2368e7f196b6382a44c -- cgit v1.3.1 From c986baaa3b9f79d3add7b26e5ab8dd0cb75b735b Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Dec 2021 22:55:26 +0800 Subject: fix vs2022 toolset --- xmake/plugins/project/vsxmake/vsproj/Xmake.props | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/plugins/project/vsxmake/vsproj/Xmake.props b/xmake/plugins/project/vsxmake/vsproj/Xmake.props index a783c8ebc..5bd30e2f9 100644 --- a/xmake/plugins/project/vsxmake/vsproj/Xmake.props +++ b/xmake/plugins/project/vsxmake/vsproj/Xmake.props @@ -58,6 +58,7 @@ v140 v141 v142 + v143 -- cgit v1.3.1 From 27dedfe3fa08bd184c5a8d0c5b7cd4dc24091ca8 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Dec 2021 23:07:04 +0800 Subject: Update vs201x_vcxproj.lua --- xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index 6e77caf9b..d56c1015d 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -23,6 +23,7 @@ import("core.project.rule") import("core.project.config") import("core.project.project") import("core.language.language") +import("core.tool.toolchain") import("private.utils.batchcmds") import("vsfile") @@ -31,10 +32,12 @@ function _get_toolset_ver(targetinfo, vsinfo) -- get toolset version from vs version local toolset_ver = nil - local vs_toolset = config.get("vs_toolset") + local vs_toolset = toolchain.load("msvc"):config("vs_toolset") or config.get("vs_toolset") if vs_toolset then local verinfo = vs_toolset:split('%.') - toolset_ver = "v" .. verinfo[1] .. (verinfo[2] or "0") + if #verinfo >= 2 then + toolset_ver = "v" .. verinfo[1] .. (verinfo[2]:sub(1, 1) or "0") + end end if not toolset_ver then toolset_ver = vsinfo.toolset_version -- cgit v1.3.1 From ec8a29530ef5c7a60cb21a32fb07557d12c12cb7 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 2 Dec 2021 23:11:22 +0800 Subject: Update ar.lua --- xmake/modules/core/tools/ar.lua | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/xmake/modules/core/tools/ar.lua b/xmake/modules/core/tools/ar.lua index abb1e9695..0496238b4 100644 --- a/xmake/modules/core/tools/ar.lua +++ b/xmake/modules/core/tools/ar.lua @@ -30,42 +30,26 @@ end -- make the strip flag function strip(self, level) - - -- the maps local maps = { debug = "-S" , all = "-s" } - - -- make it return maps[level] end -- make the link arguments list function linkargv(self, objectfiles, targetkind, targetfile, flags, opt) - - -- check - assert(targetkind == "static") - - -- init arguments opt = opt or {} local argv = table.join(flags, targetfile, objectfiles) if is_host("windows") and not opt.rawargs then argv = winos.cmdargv(argv, {escape = true}) end - - -- make it return self:program(), argv end -- link the library file function link(self, objectfiles, targetkind, targetfile, flags) - - -- check - assert(targetkind == "static", "the target kind: %s is not support for ar", targetkind) - - -- ensure the target directory os.mkdir(path.directory(targetfile)) -- @note remove the previous archived file first to force recreating a new file -- cgit v1.3.1 From 7ae3c378f897fac7e0bf7dc9e0f7562a589514c8 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 3 Dec 2021 21:09:48 +0800 Subject: update version --- CHANGELOG.md | 4 ++++ core/project.mak | 4 ++-- core/xmake.lua | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0360f917..83bdf65ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## master (unreleased) +## v2.6.1 + ### New features * [#1799](https://github.com/xmake-io/xmake/issues/1799): Support mixed rust & c++ target and cargo dependences @@ -1140,6 +1142,8 @@ ## master (开发中) +## v2.6.1 + ### 新特性 * [#1799](https://github.com/xmake-io/xmake/issues/1799): 支持混合 Rust 和 C++ 程序,以及集成 Cargo 依赖库 diff --git a/core/project.mak b/core/project.mak index 99e6ca226..945871e92 100644 --- a/core/project.mak +++ b/core/project.mak @@ -7,10 +7,10 @@ PRO_NAME = xmake PRO_VERSION_MAJOR = 2 # the project minor version -PRO_VERSION_MINOR = 5 +PRO_VERSION_MINOR = 6 # the project alter version -PRO_VERSION_ALTER = 9 +PRO_VERSION_ALTER = 1 # the project prefix PRO_PREFIX = XM_ diff --git a/core/xmake.lua b/core/xmake.lua index 08fc49301..5b72c672a 100644 --- a/core/xmake.lua +++ b/core/xmake.lua @@ -2,7 +2,7 @@ set_project("xmake") -- version -set_version("2.5.9", {build = "%Y%m%d%H%M"}) +set_version("2.6.1", {build = "%Y%m%d%H%M"}) -- set xmake min version set_xmakever("2.2.3") -- cgit v1.3.1 From 666dc54797f2cc37ecfc5a952b1e9862820e8b86 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 3 Dec 2021 21:09:57 +0800 Subject: update spec --- scripts/rpmbuild/SPECS/xmake.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/rpmbuild/SPECS/xmake.spec b/scripts/rpmbuild/SPECS/xmake.spec index f512d59c7..8b03b8634 100644 --- a/scripts/rpmbuild/SPECS/xmake.spec +++ b/scripts/rpmbuild/SPECS/xmake.spec @@ -1,4 +1,4 @@ -%define xmake_revision 96d398228e9ae045973af9c656a09c7376f9582c +%define xmake_revision 7ae3c378f897fac7e0bf7dc9e0f7562a589514c8 %define tbox_revision 122a479e626ee3fdd7d6c1117ec7c19212a1e087 %define sv_revision 035262773da0500367cb88e6f30197908159a348 %define lua_cjson_revision 515bab6d6d80b164b94db73af69609ea02f3a798 @@ -8,7 +8,7 @@ %undefine _disable_source_fetch Name: xmake -Version: 2.5.9 +Version: 2.6.1 Release: 1%{?dist} Summary: A cross-platform build utility based on Lua BuildArch: noarch -- cgit v1.3.1 From 7790baafb16afb45fbf81fafcfc60001f0e1afe1 Mon Sep 17 00:00:00 2001 From: Hoildkv <42310255+xq114@users.noreply.github.com> Date: Sat, 4 Dec 2021 14:26:02 +0800 Subject: Update get.ps1 --- scripts/get.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/get.ps1 b/scripts/get.ps1 index 449e0e3a1..d1c1c22a9 100755 --- a/scripts/get.ps1 +++ b/scripts/get.ps1 @@ -11,7 +11,7 @@ param ( ) & { - $LastRelease = "v2.5.9" + $LastRelease = "v2.6.1" $ErrorActionPreference = 'Stop' function writeErrorTip($msg) { -- cgit v1.3.1 From dc56afae5c2f826878b06c066436971fd95f8087 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 4 Dec 2021 22:52:21 +0800 Subject: Update package.lua --- .../private/action/require/impl/package.lua | 29 +++++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index d920a95a1..1d013b91e 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -254,18 +254,39 @@ end -- -- orderdeps: c -> b -> a -- -function _sort_packagedeps(package, onlylink) +function _sort_packagedeps(package) -- we must use native deps list instead of package:deps() to generate correct linkdeps local orderdeps = {} for _, dep in ipairs(package:plaindeps()) do - if dep and (onlylink ~= true or (dep:is_library() and not dep:is_private())) then - table.join2(orderdeps, _sort_packagedeps(dep, onlylink)) + if dep then + table.join2(orderdeps, _sort_packagedeps(dep)) table.insert(orderdeps, dep) end end return orderdeps end +-- sort link deps +-- +-- e.g. +-- +-- a.deps = b +-- b.deps = c +-- +-- orderdeps: a -> b -> c +-- +function _sort_linkdeps(package) + -- we must use native deps list instead of package:deps() to generate correct linkdeps + local orderdeps = {} + for _, dep in ipairs(package:plaindeps()) do + if dep and dep:is_library() and not dep:is_private() then + table.insert(orderdeps, dep) + table.join2(orderdeps, _sort_linkdeps(dep)) + end + end + return orderdeps +end + -- add some builtin configurations to package function _add_package_configurations(package) -- we can define configs to override it and it's default value in package() @@ -818,7 +839,7 @@ function _load_packages(requires, opt) package._DEPS = packagedeps package._PLAINDEPS = plaindeps package._ORDERDEPS = table.unique(_sort_packagedeps(package)) - package._LINKDEPS = table.reverse_unique(_sort_packagedeps(package, true)) + package._LINKDEPS = table.reverse_unique(_sort_linkdeps(package)) end end -- cgit v1.3.1 From 2fd3431a70ce00bf882866404c2d17c7441f701b Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 4 Dec 2021 22:53:33 +0800 Subject: Update register_packages.lua --- .../private/action/require/impl/register_packages.lua | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/xmake/modules/private/action/require/impl/register_packages.lua b/xmake/modules/private/action/require/impl/register_packages.lua index 4c326e770..afc84eb98 100644 --- a/xmake/modules/private/action/require/impl/register_packages.lua +++ b/xmake/modules/private/action/require/impl/register_packages.lua @@ -88,16 +88,9 @@ function _register_required_package(instance, required_package) _register_required_package_base(instance, required_package) _register_required_package_libs(instance, required_package) _register_required_package_envs(instance, envs) - local linkdeps = instance:linkdeps() - if linkdeps then - local total = #linkdeps - for idx, _ in ipairs(linkdeps) do - local dep = linkdeps[total + 1 - idx] - if dep then - if instance:is_library() then - _register_required_package_libs(dep, required_package, true) - end - end + for _, dep in ipairs(instance:linkdeps()) do + if instance:is_library() then + _register_required_package_libs(dep, required_package, true) end end for _, dep in ipairs(instance:orderdeps()) do -- cgit v1.3.1 From 373595ff5a55ffa8288f9667096de6b88c5c0dc5 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 5 Dec 2021 16:17:23 +0800 Subject: Update cxxbridge.lua --- xmake/rules/rust/build/cxxbridge.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/rust/build/cxxbridge.lua b/xmake/rules/rust/build/cxxbridge.lua index 84b1f7fea..1fc9b3778 100644 --- a/xmake/rules/rust/build/cxxbridge.lua +++ b/xmake/rules/rust/build/cxxbridge.lua @@ -23,7 +23,7 @@ import("core.base.option") import("lib.detect.find_tool") function main(target, batchcmds, sourcefile, opt) - local cxxbridge = assert(find_tool("cxxbridge"), "cxxbridge not found!") + local cxxbridge = assert(find_tool("cxxbridge"), "cxxbridge not found, please run `cargo install cxxbridge` to install it first!") -- get c/c++ source file for cxxbridge local headerfile = path.join(target:autogendir(), "rules", "cxxbridge", path.basename(sourcefile) .. ".rs.h") -- cgit v1.3.1 From 20302ed8c53084e891a79af04deddc7e21cb63f8 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 5 Dec 2021 16:33:23 +0800 Subject: Update CHANGELOG.md --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83bdf65ea..eef12e1b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### Bugs fixed + +* [#1885](https://github.com/xmake-io/xmake/issues/1885): Fix package:fetch_linkdeps + ## v2.6.1 ### New features @@ -1142,6 +1146,10 @@ ## master (开发中) +### Bugs 修复 + +* [#1885](https://github.com/xmake-io/xmake/issues/1885): 修复 package:fetch_linkdeps 链接顺序问题 + ## v2.6.1 ### 新特性 -- cgit v1.3.1 From b062cae6275c91a0c415524353daa49220cbb3f8 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 5 Dec 2021 21:24:46 +0800 Subject: Update installer.nsi --- scripts/installer.nsi | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/installer.nsi b/scripts/installer.nsi index 4c7ea290b..03204558e 100644 --- a/scripts/installer.nsi +++ b/scripts/installer.nsi @@ -230,7 +230,11 @@ Section "XMake (required)" InstallExeutable SetOutPath $InstDir ; Remove previous directories used - RMDir /r "$InstDir" + IfFileExists "$InstDir\xmake.exe" file_found file_not_found_or_end + file_found: + RMDir /r "$InstDir" + goto file_not_found_or_end + file_not_found_or_end: ; Put file there File /r /x ".DS_Store" /x "*.swp" "..\xmake\*.*" -- cgit v1.3.1 From babc5cb8dadcdb774de506ca0d2478381181d2e4 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 5 Dec 2021 21:25:40 +0800 Subject: Update installer.nsi --- scripts/installer.nsi | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/installer.nsi b/scripts/installer.nsi index 03204558e..8ef9e2e6d 100644 --- a/scripts/installer.nsi +++ b/scripts/installer.nsi @@ -230,6 +230,7 @@ Section "XMake (required)" InstallExeutable SetOutPath $InstDir ; Remove previous directories used + ; https://github.com/xmake-io/xmake/issues/1888 IfFileExists "$InstDir\xmake.exe" file_found file_not_found_or_end file_found: RMDir /r "$InstDir" -- cgit v1.3.1 From 7dc1142890a81e5aed622b2832cca5e39b897ce7 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 5 Dec 2021 21:51:04 +0800 Subject: Update configfiles.lua --- xmake/actions/config/configfiles.lua | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/xmake/actions/config/configfiles.lua b/xmake/actions/config/configfiles.lua index 933ee4e66..72891136a 100644 --- a/xmake/actions/config/configfiles.lua +++ b/xmake/actions/config/configfiles.lua @@ -253,11 +253,25 @@ function _generate_configfile(srcfile, dstfile, fileinfo, targets) elseif type(value) == "number" then value = ("#define %s %d"):format(variable, value) elseif type(value) == "string" then - -- disable to wrap quote, @see https://github.com/xmake-io/xmake/issues/1694 - if extraconf and extraconf.quote == false then - value = ("#define %s %s"):format(variable, value) - else + local quote = true + local escape = false + if extraconf then + -- disable to wrap quote, @see https://github.com/xmake-io/xmake/issues/1694 + if extraconf.quote == false then + quote = false + end + -- escape path seperator when with quote, @see https://github.com/xmake-io/xmake/issues/1872 + if quote and extraconf.escape then + escape = true + end + end + if quote then + if escape then + value = value:gsub("\\", "\\\\") + end value = ("#define %s \"%s\""):format(variable, value) + else + value = ("#define %s %s"):format(variable, value) end else raise("unknown variable(%s) type: %s", variable, type(value)) -- cgit v1.3.1 From 1032fc64a13221a674ebbfce59542b7a6dd536c7 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 5 Dec 2021 21:53:26 +0800 Subject: Update CHANGELOG.md --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index eef12e1b8..20fbc3cde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### Change + +* [#1872](https://github.com/xmake-io/xmake/issues/1872): Escape characters for set_configvar + ### Bugs fixed * [#1885](https://github.com/xmake-io/xmake/issues/1885): Fix package:fetch_linkdeps @@ -1146,6 +1150,10 @@ ## master (开发中) +### 改进 + +* [#1872](https://github.com/xmake-io/xmake/issues/1872): 支持转义 set_configvar 中字符串值 + ### Bugs 修复 * [#1885](https://github.com/xmake-io/xmake/issues/1885): 修复 package:fetch_linkdeps 链接顺序问题 -- cgit v1.3.1 From 00aa83d2e17880f3c22bbe36ddf960616103bc2a Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 5 Dec 2021 22:45:19 +0800 Subject: Update bin2c.lua --- xmake/modules/private/utils/bin2c.lua | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/xmake/modules/private/utils/bin2c.lua b/xmake/modules/private/utils/bin2c.lua index 91ea1eafe..edb89731c 100644 --- a/xmake/modules/private/utils/bin2c.lua +++ b/xmake/modules/private/utils/bin2c.lua @@ -23,9 +23,10 @@ import("core.base.bytes") import("core.base.option") local options = { - {'w', "linewidth", "kv", nil, "Set the line width"}, - {'i', "binarypath", "kv", nil, "Set the binary file path."}, - {'o', "outputpath", "kv", nil, "Set the output file path."} + {'w', "linewidth", "kv", nil, "Set the line width"}, + {'z', "zeroend", "k", true, "Patch zero terminating character"}, + {'i', "binarypath", "kv", nil, "Set the binary file path."}, + {'o', "outputpath", "kv", nil, "Set the output file path."} } function _do_dump(binarydata, outputfile, opt) @@ -84,7 +85,9 @@ function _do_bin2c(binarypath, outputpath, opt) local binarydata = bytes(io.readfile(binarypath, {encoding = "binary"})) local outputfile = io.open(outputpath, 'w') if outputfile then - binarydata = binarydata .. bytes('\0') + if opt.zeroend then + binarydata = binarydata .. bytes('\0') + end _do_dump(binarydata, outputfile, opt) outputfile:close() end @@ -96,6 +99,7 @@ end -- main entry function main(...) + print("sss") -- parse arguments local argv = {...} local opt = option.parse(argv, options, "Print c/c++ code files from the given binary file." -- cgit v1.3.1 From 2817f6844f6e1a5ed8c17a9c3b83bc18690b1f1f Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 5 Dec 2021 22:46:06 +0800 Subject: Update xmake.lua --- xmake/rules/utils/glsl2spv/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/utils/glsl2spv/xmake.lua b/xmake/rules/utils/glsl2spv/xmake.lua index 1ffd02089..cf4f113fe 100644 --- a/xmake/rules/utils/glsl2spv/xmake.lua +++ b/xmake/rules/utils/glsl2spv/xmake.lua @@ -78,7 +78,7 @@ rule("utils.glsl2spv") outputfile = headerfile -- add commands - local argv = {"lua", "private.utils.bin2c", "-i", spvfilepath, "-o", headerfile} + local argv = {"lua", "private.utils.bin2c", "-z", "-i", spvfilepath, "-o", headerfile} batchcmds:vrunv(os.programfile(), argv, {envs = {XMAKE_SKIP_HISTORY = "y"}}) end -- cgit v1.3.1 From 23c04732766ba2db5e5caea09d7d31f7d8631a97 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 5 Dec 2021 22:59:47 +0800 Subject: Update xmake.lua --- xmake/rules/utils/bin2c/xmake.lua | 118 ++++++++++++++++++++++++++++---------- 1 file changed, 88 insertions(+), 30 deletions(-) diff --git a/xmake/rules/utils/bin2c/xmake.lua b/xmake/rules/utils/bin2c/xmake.lua index 77f81125c..79b52fe73 100644 --- a/xmake/rules/utils/bin2c/xmake.lua +++ b/xmake/rules/utils/bin2c/xmake.lua @@ -15,39 +15,97 @@ -- Copyright (C) 2015-present, TBOOX Open Source Group. -- -- @author ruki --- @file xmake.lua +-- @file bin2c.lua -- -rule("utils.bin2c") - set_extensions(".bin") - on_load(function (target) - local headerdir = path.join(target:autogendir(), "rules", "utils", "bin2c") - if not os.isdir(headerdir) then - os.mkdir(headerdir) +-- imports +import("core.base.bytes") +import("core.base.option") + +local options = { + {'w', "linewidth", "kv", nil, "Set the line width"}, + {nil, "nozeroend", "k", false, "Disable to patch zero terminating character"}, + {'i', "binarypath", "kv", nil, "Set the binary file path."}, + {'o', "outputpath", "kv", nil, "Set the output file path."} +} + +function _do_dump(binarydata, outputfile, opt) + local i = 0 + local n = 147 + local p = 0 + local e = binarydata:size() + local line = nil + local linewidth = opt.linewidth or 0x20 + local first = true + while p < e do + line = "" + if p + linewidth <= e then + for i = 0, linewidth - 1 do + if first then + first = false + line = line .. " " + else + line = line .. "," + end + line = line .. string.format(" 0x%02X", binarydata[p + i + 1]) + end + outputfile:print(line) + p = p + linewidth + elseif p < e then + local left = e - p + for i = 0, left - 1 do + if first then + first = false + line = line .. " " + else + line = line .. "," + end + line = line .. string.format(" 0x%02X", binarydata[p + i + 1]) + end + outputfile:print(line) + p = p + left + else + break end - target:add("includedirs", headerdir) - end) - before_buildcmd_file(function (target, batchcmds, sourcefile_bin, opt) - - -- get header file - local headerdir = path.join(target:autogendir(), "rules", "utils", "bin2c") - local headerfile = path.join(headerdir, path.filename(sourcefile_bin) .. ".h") - target:add("includedirs", headerdir) - - -- add commands - batchcmds:show_progress(opt.progress, "${color.build.object}generating.bin2c %s", sourcefile_bin) - batchcmds:mkdir(headerdir) - local argv = {"lua", "private.utils.bin2c", "-i", sourcefile_bin, "-o", headerfile} - local linewidth = target:extraconf("rules", "utils.bin2c", "linewidth") - if linewidth then - table.insert(argv, "-w") - table.insert(argv, tostring(linewidth)) + end +end + +function _do_bin2c(binarypath, outputpath, opt) + + -- init source directory and options + opt = opt or {} + binarypath = path.absolute(binarypath) + outputpath = path.absolute(outputpath) + assert(os.isfile(binarypath), "%s not found!", binarypath) + + -- trace + print("generating code data file from %s ..", binarypath) + + -- do dump + local binarydata = bytes(io.readfile(binarypath, {encoding = "binary"})) + local outputfile = io.open(outputpath, 'w') + if outputfile then + if opt.nozeroend then + binarydata = binarydata .. bytes('\0') end - batchcmds:vrunv(os.programfile(), argv, {envs = {XMAKE_SKIP_HISTORY = "y"}}) + _do_dump(binarydata, outputfile, opt) + outputfile:close() + end + + -- trace + cprint("${bright}%s generated!", outputpath) +end + +-- main entry +function main(...) - -- add deps - batchcmds:add_depfiles(sourcefile_bin) - batchcmds:set_depmtime(os.mtime(headerfile)) - batchcmds:set_depcache(target:dependfile(headerfile)) - end) + print("sss") + -- parse arguments + local argv = {...} + local opt = option.parse(argv, options, "Print c/c++ code files from the given binary file." + , "" + , "Usage: xmake l private.utils.bin2c [options]") + -- do bin2c + _do_bin2c(opt.binarypath, opt.outputpath, opt) +end -- cgit v1.3.1 From eab65cb4c758e0d9c16fc6c606dfa7616a491787 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 5 Dec 2021 23:00:01 +0800 Subject: Update xmake.lua --- xmake/rules/utils/bin2c/xmake.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/xmake/rules/utils/bin2c/xmake.lua b/xmake/rules/utils/bin2c/xmake.lua index 79b52fe73..409162f00 100644 --- a/xmake/rules/utils/bin2c/xmake.lua +++ b/xmake/rules/utils/bin2c/xmake.lua @@ -99,7 +99,6 @@ end -- main entry function main(...) - print("sss") -- parse arguments local argv = {...} local opt = option.parse(argv, options, "Print c/c++ code files from the given binary file." -- cgit v1.3.1 From d0a57e1b4faf83e28ac6ab3a1f1e857eb4d3263f Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 5 Dec 2021 23:00:55 +0800 Subject: Update xmake.lua --- xmake/rules/utils/glsl2spv/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/utils/glsl2spv/xmake.lua b/xmake/rules/utils/glsl2spv/xmake.lua index cf4f113fe..faf655ec6 100644 --- a/xmake/rules/utils/glsl2spv/xmake.lua +++ b/xmake/rules/utils/glsl2spv/xmake.lua @@ -78,7 +78,7 @@ rule("utils.glsl2spv") outputfile = headerfile -- add commands - local argv = {"lua", "private.utils.bin2c", "-z", "-i", spvfilepath, "-o", headerfile} + local argv = {"lua", "private.utils.bin2c", "--nozeroend", "-i", spvfilepath, "-o", headerfile} batchcmds:vrunv(os.programfile(), argv, {envs = {XMAKE_SKIP_HISTORY = "y"}}) end -- cgit v1.3.1 From dd73ec4a233de28620627e8025ce8f83ab901f3b Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 5 Dec 2021 23:02:59 +0800 Subject: Update xmake.lua --- xmake/rules/utils/bin2c/xmake.lua | 117 ++++++++++---------------------------- 1 file changed, 30 insertions(+), 87 deletions(-) diff --git a/xmake/rules/utils/bin2c/xmake.lua b/xmake/rules/utils/bin2c/xmake.lua index 409162f00..77f81125c 100644 --- a/xmake/rules/utils/bin2c/xmake.lua +++ b/xmake/rules/utils/bin2c/xmake.lua @@ -15,96 +15,39 @@ -- Copyright (C) 2015-present, TBOOX Open Source Group. -- -- @author ruki --- @file bin2c.lua +-- @file xmake.lua -- --- imports -import("core.base.bytes") -import("core.base.option") - -local options = { - {'w', "linewidth", "kv", nil, "Set the line width"}, - {nil, "nozeroend", "k", false, "Disable to patch zero terminating character"}, - {'i', "binarypath", "kv", nil, "Set the binary file path."}, - {'o', "outputpath", "kv", nil, "Set the output file path."} -} - -function _do_dump(binarydata, outputfile, opt) - local i = 0 - local n = 147 - local p = 0 - local e = binarydata:size() - local line = nil - local linewidth = opt.linewidth or 0x20 - local first = true - while p < e do - line = "" - if p + linewidth <= e then - for i = 0, linewidth - 1 do - if first then - first = false - line = line .. " " - else - line = line .. "," - end - line = line .. string.format(" 0x%02X", binarydata[p + i + 1]) - end - outputfile:print(line) - p = p + linewidth - elseif p < e then - local left = e - p - for i = 0, left - 1 do - if first then - first = false - line = line .. " " - else - line = line .. "," - end - line = line .. string.format(" 0x%02X", binarydata[p + i + 1]) - end - outputfile:print(line) - p = p + left - else - break +rule("utils.bin2c") + set_extensions(".bin") + on_load(function (target) + local headerdir = path.join(target:autogendir(), "rules", "utils", "bin2c") + if not os.isdir(headerdir) then + os.mkdir(headerdir) end - end -end - -function _do_bin2c(binarypath, outputpath, opt) - - -- init source directory and options - opt = opt or {} - binarypath = path.absolute(binarypath) - outputpath = path.absolute(outputpath) - assert(os.isfile(binarypath), "%s not found!", binarypath) - - -- trace - print("generating code data file from %s ..", binarypath) - - -- do dump - local binarydata = bytes(io.readfile(binarypath, {encoding = "binary"})) - local outputfile = io.open(outputpath, 'w') - if outputfile then - if opt.nozeroend then - binarydata = binarydata .. bytes('\0') + target:add("includedirs", headerdir) + end) + before_buildcmd_file(function (target, batchcmds, sourcefile_bin, opt) + + -- get header file + local headerdir = path.join(target:autogendir(), "rules", "utils", "bin2c") + local headerfile = path.join(headerdir, path.filename(sourcefile_bin) .. ".h") + target:add("includedirs", headerdir) + + -- add commands + batchcmds:show_progress(opt.progress, "${color.build.object}generating.bin2c %s", sourcefile_bin) + batchcmds:mkdir(headerdir) + local argv = {"lua", "private.utils.bin2c", "-i", sourcefile_bin, "-o", headerfile} + local linewidth = target:extraconf("rules", "utils.bin2c", "linewidth") + if linewidth then + table.insert(argv, "-w") + table.insert(argv, tostring(linewidth)) end - _do_dump(binarydata, outputfile, opt) - outputfile:close() - end - - -- trace - cprint("${bright}%s generated!", outputpath) -end - --- main entry -function main(...) + batchcmds:vrunv(os.programfile(), argv, {envs = {XMAKE_SKIP_HISTORY = "y"}}) - -- parse arguments - local argv = {...} - local opt = option.parse(argv, options, "Print c/c++ code files from the given binary file." - , "" - , "Usage: xmake l private.utils.bin2c [options]") + -- add deps + batchcmds:add_depfiles(sourcefile_bin) + batchcmds:set_depmtime(os.mtime(headerfile)) + batchcmds:set_depcache(target:dependfile(headerfile)) + end) - -- do bin2c - _do_bin2c(opt.binarypath, opt.outputpath, opt) -end -- cgit v1.3.1 From 8787117f775151203132c228d40f5d1f672b0dda Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 5 Dec 2021 23:03:30 +0800 Subject: Update bin2c.lua --- xmake/modules/private/utils/bin2c.lua | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/xmake/modules/private/utils/bin2c.lua b/xmake/modules/private/utils/bin2c.lua index edb89731c..409162f00 100644 --- a/xmake/modules/private/utils/bin2c.lua +++ b/xmake/modules/private/utils/bin2c.lua @@ -23,10 +23,10 @@ import("core.base.bytes") import("core.base.option") local options = { - {'w', "linewidth", "kv", nil, "Set the line width"}, - {'z', "zeroend", "k", true, "Patch zero terminating character"}, - {'i', "binarypath", "kv", nil, "Set the binary file path."}, - {'o', "outputpath", "kv", nil, "Set the output file path."} + {'w', "linewidth", "kv", nil, "Set the line width"}, + {nil, "nozeroend", "k", false, "Disable to patch zero terminating character"}, + {'i', "binarypath", "kv", nil, "Set the binary file path."}, + {'o', "outputpath", "kv", nil, "Set the output file path."} } function _do_dump(binarydata, outputfile, opt) @@ -85,7 +85,7 @@ function _do_bin2c(binarypath, outputpath, opt) local binarydata = bytes(io.readfile(binarypath, {encoding = "binary"})) local outputfile = io.open(outputpath, 'w') if outputfile then - if opt.zeroend then + if opt.nozeroend then binarydata = binarydata .. bytes('\0') end _do_dump(binarydata, outputfile, opt) @@ -99,7 +99,6 @@ end -- main entry function main(...) - print("sss") -- parse arguments local argv = {...} local opt = option.parse(argv, options, "Print c/c++ code files from the given binary file." -- cgit v1.3.1 From b48381cda166808c879fabf2a263b66012e7c2aa Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 5 Dec 2021 23:10:06 +0800 Subject: Update bin2c.lua --- xmake/modules/private/utils/bin2c.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/private/utils/bin2c.lua b/xmake/modules/private/utils/bin2c.lua index 409162f00..6f18833fc 100644 --- a/xmake/modules/private/utils/bin2c.lua +++ b/xmake/modules/private/utils/bin2c.lua @@ -85,7 +85,7 @@ function _do_bin2c(binarypath, outputpath, opt) local binarydata = bytes(io.readfile(binarypath, {encoding = "binary"})) local outputfile = io.open(outputpath, 'w') if outputfile then - if opt.nozeroend then + if not opt.nozeroend then binarydata = binarydata .. bytes('\0') end _do_dump(binarydata, outputfile, opt) -- cgit v1.3.1 From 1db61fa633f64f3d7465e3d960016934b0fedc80 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 6 Dec 2021 20:53:27 +0800 Subject: Update config.lua --- xmake/core/project/config.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/core/project/config.lua b/xmake/core/project/config.lua index 16912ab68..00d06e878 100644 --- a/xmake/core/project/config.lua +++ b/xmake/core/project/config.lua @@ -175,9 +175,9 @@ function config.save(filepath, opt) configs[name] = value end end - return io.save(filepath, configs) + return io.save(filepath, configs, {orderkeys = true}) else - return io.save(filepath, config.options()) + return io.save(filepath, config.options(), {orderkeys = true}) end end -- cgit v1.3.1 From 9d19f1a747c0ebf692fbeca25a78f41b7fcd55e3 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 7 Dec 2021 09:48:27 +0800 Subject: Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20fbc3cde..5765824ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Change * [#1872](https://github.com/xmake-io/xmake/issues/1872): Escape characters for set_configvar +* [#1888](https://github.com/xmake-io/xmake/issues/1888): Improve windows installer to avoid remove other files ### Bugs fixed @@ -1153,6 +1154,7 @@ ### 改进 * [#1872](https://github.com/xmake-io/xmake/issues/1872): 支持转义 set_configvar 中字符串值 +* [#1888](https://github.com/xmake-io/xmake/issues/1888): 改进 windows 安装器,避免错误删除其他安装目录下的文件 ### Bugs 修复 -- cgit v1.3.1 From b17b42b8130a7b736c2668cc37445234c9e8301f Mon Sep 17 00:00:00 2001 From: PucklaMotzer09 Date: Tue, 7 Dec 2021 12:29:26 +0100 Subject: Use correct path and bat for ifort 2021 --- xmake/modules/detect/sdks/find_ifortenv.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/xmake/modules/detect/sdks/find_ifortenv.lua b/xmake/modules/detect/sdks/find_ifortenv.lua index f3aafad06..6d4b32b7d 100644 --- a/xmake/modules/detect/sdks/find_ifortenv.lua +++ b/xmake/modules/detect/sdks/find_ifortenv.lua @@ -100,8 +100,14 @@ function _find_intel_on_windows(opt) opt = opt or {} -- find ifortvars_bat.bat - local paths = {"$(env IFORT_COMPILER20)"} + local paths = {os.getenv("IFORT_COMPILER20")} local ifortvars_bat = find_file("bin/ifortvars.bat", paths) + -- look for setvars.bat which is new in 2021 + if not ifortvars_bat then + paths = {os.getenv("IFORT_COMPILER21")} + ifortvars_bat = find_file("../../../setvars.bat", paths) + end + if ifortvars_bat then -- load ifortvars_bat -- cgit v1.3.1 From 9ba620afb2edd9af07f84cc9cdbcd06b39dde29b Mon Sep 17 00:00:00 2001 From: PucklaMotzer09 Date: Tue, 7 Dec 2021 14:32:47 +0100 Subject: Use $(env ) instead of os.getenv() --- xmake/modules/detect/sdks/find_ifortenv.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/modules/detect/sdks/find_ifortenv.lua b/xmake/modules/detect/sdks/find_ifortenv.lua index 6d4b32b7d..42f29c6a0 100644 --- a/xmake/modules/detect/sdks/find_ifortenv.lua +++ b/xmake/modules/detect/sdks/find_ifortenv.lua @@ -100,11 +100,11 @@ function _find_intel_on_windows(opt) opt = opt or {} -- find ifortvars_bat.bat - local paths = {os.getenv("IFORT_COMPILER20")} + local paths = {"$(env IFORT_COMPILER20)"} local ifortvars_bat = find_file("bin/ifortvars.bat", paths) -- look for setvars.bat which is new in 2021 if not ifortvars_bat then - paths = {os.getenv("IFORT_COMPILER21")} + paths = {"$(env IFORT_COMPILER21)"} ifortvars_bat = find_file("../../../setvars.bat", paths) end -- cgit v1.3.1 From 0944d5ac92facee9d6b41bf0f7d8b049a31eb01f Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 7 Dec 2021 22:32:28 +0800 Subject: Update find_ifort.lua --- xmake/modules/detect/tools/find_ifort.lua | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/xmake/modules/detect/tools/find_ifort.lua b/xmake/modules/detect/tools/find_ifort.lua index ecdb94dfd..dfa8f254c 100644 --- a/xmake/modules/detect/tools/find_ifort.lua +++ b/xmake/modules/detect/tools/find_ifort.lua @@ -36,7 +36,6 @@ import("lib.detect.find_programver") -- @endcode -- function main(opt) - opt = opt or {} if is_host("windows") then -- find program @@ -53,6 +52,20 @@ function main(opt) return program, version else -- find program + if is_host("linux") then + local arch = os.arch() == "x86_64" and "intel64" or "ia32" + local dirs = {"~/intel/oneapi/compiler/latest/linux"} + opt.envs = opt.envs or {} + opt.paths = opt.paths or {} + local LD_LIBRARY_PATH = {} + for _, dir in ipairs(dirs) do + if os.isdir(dir) then + table.insert(LD_LIBRARY_PATH, path.join(dir, "compiler/lib", arch)) + table.insert(opt.paths, path.join(dir, "bin", arch)) + end + end + opt.envs.LD_LIBRARY_PATH = path.joinenv(LD_LIBRARY_PATH) + end local program = find_program(opt.program or "ifort", opt) -- find program version -- cgit v1.3.1 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 Eltricos S.A. - Automao" }, + { 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 Vsters 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 Eltricos S.A. - Automao" }, - { 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 Vsters 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 From 1c25801d85b1e90e24aa2661c7c8574aa729e4d7 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 8 Dec 2021 09:42:00 +0800 Subject: Update xmake.lua --- xmake/rules/plugin/vsxmake/xmake.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xmake/rules/plugin/vsxmake/xmake.lua b/xmake/rules/plugin/vsxmake/xmake.lua index 88693599f..557d8ed4b 100644 --- a/xmake/rules/plugin/vsxmake/xmake.lua +++ b/xmake/rules/plugin/vsxmake/xmake.lua @@ -21,7 +21,7 @@ -- update vsxmake project automatically -- -- @code --- add_rules("plugin.vsxmake.autoupdate") +-- add_rules("plugin.vsxmake.autoupdate", {outputdir = "xxx"}) -- target("test") -- set_kind("binary") -- add_files("src/*.c") @@ -41,6 +41,7 @@ rule("plugin.vsxmake.autoupdate") local tmpfile = path.join(config.buildir(), ".gens", "rules", "plugin.vsxmake.autoupdate") local dependfile = tmpfile .. ".d" local lockfile = io.openlock(tmpfile .. ".lock") + local outputdir = project.extraconf("target.rules", "plugin.vsxmake.autoupdate", "outputdir") if lockfile:trylock() then if os.getenv("XMAKE_IN_VSTUDIO") then local sourcefiles = {} @@ -51,7 +52,7 @@ rule("plugin.vsxmake.autoupdate") depend.on_changed(function () -- we use task instead of os.exec("xmake") to avoid the project lock print("update vsxmake project ..") - task.run("project", {kind = "vsxmake"}) + task.run("project", {kind = "vsxmake", outputdir = outputdir}) print("update vsxmake project ok") end, {dependfile = dependfile, files = project.allfiles(), -- cgit v1.3.1 From 87b5cd1ed777dda284462e56d67a92332116c17d Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 8 Dec 2021 10:13:10 +0800 Subject: Update extension.lua --- xmake/modules/utils/archive/extension.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/utils/archive/extension.lua b/xmake/modules/utils/archive/extension.lua index 3a8554efd..ae8b97153 100644 --- a/xmake/modules/utils/archive/extension.lua +++ b/xmake/modules/utils/archive/extension.lua @@ -26,7 +26,7 @@ function main(archivefile) local extension = "" local filename = path.filename(archivefile) - local extensionset = hashset.from({".zip", ".7z", ".gz", ".xz", ".tgz", ".bz2", ".tar", ".tar.gz", ".tar.xz", ".tar.bz2"}) + local extensionset = hashset.from({".zip", ".7z", ".gz", ".xz", ".tgz", ".bz2", ".tar", ".tar.gz", ".tar.xz", ".tar.bz2", ".tar.lz"}) local i = filename:lastof(".", true) if i then local p = filename:sub(1, i - 1):lastof(".", true) -- cgit v1.3.1 From 389a91f20c60e49249821659df72b84235adc517 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 8 Dec 2021 10:13:32 +0800 Subject: Update extract.lua --- xmake/modules/utils/archive/extract.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xmake/modules/utils/archive/extract.lua b/xmake/modules/utils/archive/extract.lua index b853e2c8e..d4a41e542 100644 --- a/xmake/modules/utils/archive/extract.lua +++ b/xmake/modules/utils/archive/extract.lua @@ -409,6 +409,7 @@ function main(archivefile, outputdir, opt) , [".tar.gz"] = {_extract_using_7z, _extract_using_gzip} , [".tar.xz"] = {_extract_using_7z, _extract_using_xz} , [".tar.bz2"] = {_extract_using_7z, _extract_using_bzip2} + , [".tar.lz"] = {_extract_using_7z} } else extractors = @@ -423,6 +424,7 @@ function main(archivefile, outputdir, opt) , [".tar.gz"] = {_extract_using_tar, _extract_using_7z, _extract_using_gzip} , [".tar.xz"] = {_extract_using_tar, _extract_using_7z, _extract_using_xz} , [".tar.bz2"] = {_extract_using_tar, _extract_using_7z, _extract_using_bzip2} + , [".tar.lz"] = {_extract_using_tar, _extract_using_7z} } end -- cgit v1.3.1 From 86eaab2842abf6570895da359ed484805bf759a5 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 8 Dec 2021 14:44:54 +0800 Subject: Update make.lua --- xmake/modules/package/tools/make.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/package/tools/make.lua b/xmake/modules/package/tools/make.lua index af5f977fa..cbc58c9e2 100644 --- a/xmake/modules/package/tools/make.lua +++ b/xmake/modules/package/tools/make.lua @@ -100,7 +100,7 @@ function make(package, argv, opt) end end assert(program, "make not found!") - os.vrunv(program, argv, {envs = runenvs}) + os.vrunv(program, argv, {envs = runenvs, curdir = opt.curdir}) end -- build package -- cgit v1.3.1 From 23494057ededc3a8ae786c751c781de9c2c50564 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 8 Dec 2021 17:49:34 +0800 Subject: Update vsxmake.lua --- xmake/plugins/project/vsxmake/vsxmake.lua | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/xmake/plugins/project/vsxmake/vsxmake.lua b/xmake/plugins/project/vsxmake/vsxmake.lua index cc50cb2d3..894a1895b 100644 --- a/xmake/plugins/project/vsxmake/vsxmake.lua +++ b/xmake/plugins/project/vsxmake/vsxmake.lua @@ -19,6 +19,7 @@ -- -- imports +import("core.base.option") import("core.base.hashset") import("vstudio.impl.vsinfo", { rootdir = path.directory(os.scriptdir()) }) import("render") @@ -172,6 +173,17 @@ function _writefileifneeded(file, content) io.writefile(file, content, {encoding = "utf8bom"}) end +-- save plugin arguments for `plugin.vsxmake.autoupdate` +-- @see https://github.com/xmake-io/xmake/issues/1895 +function _save_plugin_arguments() + local vsxmake_cache = localcache.cache("vsxmake") + for _, name in ipairs({"kind", "modes", "archs", "outputdir"}) do + vsxmake_cache:set(name, option.get(name)) + end + vsxmake_cache:save() +end + +-- clear configuration cache function _clear_cacheconf() config.clear() config.save() @@ -235,5 +247,8 @@ function make(version) -- clear config and local cache _clear_cacheconf() + + -- save plugin arguments for autoupdate + _save_plugin_arguments() end end -- cgit v1.3.1 From db817226c8c99eb497a2350c609321e2422f7041 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 8 Dec 2021 17:50:23 +0800 Subject: Update xmake.lua --- xmake/rules/plugin/vsxmake/xmake.lua | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/xmake/rules/plugin/vsxmake/xmake.lua b/xmake/rules/plugin/vsxmake/xmake.lua index 557d8ed4b..bb0f231e4 100644 --- a/xmake/rules/plugin/vsxmake/xmake.lua +++ b/xmake/rules/plugin/vsxmake/xmake.lua @@ -21,7 +21,7 @@ -- update vsxmake project automatically -- -- @code --- add_rules("plugin.vsxmake.autoupdate", {outputdir = "xxx"}) +-- add_rules("plugin.vsxmake.autoupdate") -- target("test") -- set_kind("binary") -- add_files("src/*.c") @@ -35,13 +35,17 @@ rule("plugin.vsxmake.autoupdate") import("core.project.config") import("core.project.depend") import("core.project.project") + import("core.cache.localcache") import("core.base.task") -- run only once for all xmake process in vs local tmpfile = path.join(config.buildir(), ".gens", "rules", "plugin.vsxmake.autoupdate") local dependfile = tmpfile .. ".d" local lockfile = io.openlock(tmpfile .. ".lock") - local outputdir = project.extraconf("target.rules", "plugin.vsxmake.autoupdate", "outputdir") + local kind = localcache.get("vsxmake", "kind") + local modes = localcache.get("vsxmake", "modes") + local archs = localcache.get("vsxmake", "archs") + local outputdir = localcache.get("vsxmake", "outputdir") if lockfile:trylock() then if os.getenv("XMAKE_IN_VSTUDIO") then local sourcefiles = {} @@ -51,8 +55,8 @@ rule("plugin.vsxmake.autoupdate") table.sort(sourcefiles) depend.on_changed(function () -- we use task instead of os.exec("xmake") to avoid the project lock - print("update vsxmake project ..") - task.run("project", {kind = "vsxmake", outputdir = outputdir}) + print("update vsxmake project -k %s %s ..", kind or "vsxmake", outputdir or "") + task.run("project", {kind = kind or "vsxmake", modes = modes, archs = archs, outputdir = outputdir}) print("update vsxmake project ok") end, {dependfile = dependfile, files = project.allfiles(), -- cgit v1.3.1 From d35c013b15bdd24b31665d1c812115075bbd926c Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 8 Dec 2021 17:52:24 +0800 Subject: Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5765824ff..7ce9d0225 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * [#1872](https://github.com/xmake-io/xmake/issues/1872): Escape characters for set_configvar * [#1888](https://github.com/xmake-io/xmake/issues/1888): Improve windows installer to avoid remove other files +* [#1895](https://github.com/xmake-io/xmake/issues/1895): Improve `plugin.vsxmake.autoupdate` rule ### Bugs fixed @@ -1155,6 +1156,7 @@ * [#1872](https://github.com/xmake-io/xmake/issues/1872): 支持转义 set_configvar 中字符串值 * [#1888](https://github.com/xmake-io/xmake/issues/1888): 改进 windows 安装器,避免错误删除其他安装目录下的文件 +* [#1895](https://github.com/xmake-io/xmake/issues/1895): 改进 `plugin.vsxmake.autoupdate` 规则 ### Bugs 修复 -- cgit v1.3.1 From dedcd548ec31ad936128b272c705f8f30fb01eb2 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 8 Dec 2021 22:30:38 +0800 Subject: improve ifort --- xmake/modules/detect/sdks/find_ifortenv.lua | 18 ++++++++++++++--- xmake/modules/detect/tools/find_ifort.lua | 14 ------------- xmake/toolchains/ifort/check.lua | 31 +++++++++++++++++++---------- xmake/toolchains/ifort/load.lua | 9 ++++++++- 4 files changed, 43 insertions(+), 29 deletions(-) diff --git a/xmake/modules/detect/sdks/find_ifortenv.lua b/xmake/modules/detect/sdks/find_ifortenv.lua index f3aafad06..f45bda0d5 100644 --- a/xmake/modules/detect/sdks/find_ifortenv.lua +++ b/xmake/modules/detect/sdks/find_ifortenv.lua @@ -116,12 +116,24 @@ end -- find intel fortran envirnoment on linux function _find_intel_on_linux(opt) - -- attempt to find the sdk directory local paths = {"/opt/intel/bin", "/usr/local/bin", "/usr/bin"} local ifort = find_file("ifort", paths) if ifort then - local sdkdir = path.directory(path.directory(ifort)) - return {sdkdir = sdkdir, bindir = path.directory(ifort), path.join(sdkdir, "include"), libdir = path.join(sdkdir, "lib")} + local bindir = path.directory(ifort) + local sdkdir = path.directory(bindir) + return {sdkdir = sdkdir, bindir = bindir, libdir = path.join(sdkdir, "lib")} + end + + if is_host("linux") then + local arch = os.arch() == "x86_64" and "intel64" or "ia32" + local host = is_host("macosx") and "macos" or "linux" + local paths = {"~/intel/oneapi/compiler/latest/" .. host .. "/bin/" .. arch} + local ifort = find_file("ifort", paths) + if ifort then + local bindir = path.directory(ifort) + local sdkdir = path.directory(bindir) + return {sdkdir = sdkdir, bindir = bindir, libdir = path.join(sdkdir, "compiler", "lib", arch)} + end end end diff --git a/xmake/modules/detect/tools/find_ifort.lua b/xmake/modules/detect/tools/find_ifort.lua index dfa8f254c..31f158996 100644 --- a/xmake/modules/detect/tools/find_ifort.lua +++ b/xmake/modules/detect/tools/find_ifort.lua @@ -52,20 +52,6 @@ function main(opt) return program, version else -- find program - if is_host("linux") then - local arch = os.arch() == "x86_64" and "intel64" or "ia32" - local dirs = {"~/intel/oneapi/compiler/latest/linux"} - opt.envs = opt.envs or {} - opt.paths = opt.paths or {} - local LD_LIBRARY_PATH = {} - for _, dir in ipairs(dirs) do - if os.isdir(dir) then - table.insert(LD_LIBRARY_PATH, path.join(dir, "compiler/lib", arch)) - table.insert(opt.paths, path.join(dir, "bin", arch)) - end - end - opt.envs.LD_LIBRARY_PATH = path.joinenv(LD_LIBRARY_PATH) - end local program = find_program(opt.program or "ifort", opt) -- find program version diff --git a/xmake/toolchains/ifort/check.lua b/xmake/toolchains/ifort/check.lua index 67d4e3931..cb37666b7 100644 --- a/xmake/toolchains/ifort/check.lua +++ b/xmake/toolchains/ifort/check.lua @@ -28,7 +28,8 @@ import("lib.detect.find_tool") function _check_intel_on_windows(toolchain) -- have been checked? - if config.get("__ifortvarsall") then + local varsall = toolchain:config("varsall") + if varsall then return true end @@ -38,18 +39,11 @@ function _check_intel_on_windows(toolchain) local ifortvarsall = ifortenv.ifortvars local ifortenv = ifortvarsall[toolchain:arch()] if ifortenv and ifortenv.PATH and ifortenv.INCLUDE and ifortenv.LIB then - - -- save ifortvars - config.set("__ifortvarsall", ifortvarsall) - - -- check compiler - local program = nil local tool = find_tool("ifort.exe", {force = true, envs = ifortenv, version = true}) if tool then - program = tool.program - end - if program then cprint("checking for Intel Fortran Compiler (%s) ... ${color.success}${text.success}", toolchain:arch()) + toolchain:config_set("varsall", ifortvarsall) + toolchain:config_save() return true end end @@ -58,7 +52,22 @@ end -- check intel on linux function _check_intel_on_linux(toolchain) - return find_tool("ifort") + local ifortenv = toolchain:config("ifortenv") + if ifortenv then + return true + end + ifortenv = find_ifortenv() + if ifortenv then + local ldname = is_host("macosx") and "DYLD_LIBRARY_PATH" or "LD_LIBRARY_PATH" + local tool = find_tool("ifort", {force = true, envs = {[ldname] = ifortenv.libdir}, paths = ifortenv.bindir}) + if tool then + cprint("checking for Intel Fortran Compiler (%s) ... ${color.success}${text.success}", toolchain:arch()) + toolchain:config_set("ifortenv", ifortenv) + toolchain:config_save() + return true + end + return true + end end -- main entry diff --git a/xmake/toolchains/ifort/load.lua b/xmake/toolchains/ifort/load.lua index 804f3a914..2cb212a57 100644 --- a/xmake/toolchains/ifort/load.lua +++ b/xmake/toolchains/ifort/load.lua @@ -26,7 +26,7 @@ import("core.project.config") function _add_ifortenv(toolchain, name) -- get ifortvarsall - local ifortvarsall = config.get("__ifortvarsall") + local ifortvarsall = toolchain:config("varsall") if not ifortvarsall then return end @@ -85,6 +85,13 @@ function _load_intel_on_linux(toolchain) toolchain:add("fcldflags", march) toolchain:add("fcshflags", march) end + + -- get ifort environments + local ifortenv = toolchain:config("ifortenv") + if ifortenv then + local ldname = is_host("macosx") and "DYLD_LIBRARY_PATH" or "LD_LIBRARY_PATH" + toolchain:add("runenvs", ldname, ifortenv.libdir) + end end -- main entry -- cgit v1.3.1 From 42c73afaf38ab2645944c8bccd4e24aedba62d7e Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 8 Dec 2021 23:08:41 +0800 Subject: improve ifort toolchain --- xmake/modules/detect/sdks/find_ifortenv.lua | 12 ++++++++---- xmake/toolchains/ifort/check.lua | 5 +++-- xmake/toolchains/ifort/load.lua | 1 - 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/xmake/modules/detect/sdks/find_ifortenv.lua b/xmake/modules/detect/sdks/find_ifortenv.lua index f45bda0d5..3aca40524 100644 --- a/xmake/modules/detect/sdks/find_ifortenv.lua +++ b/xmake/modules/detect/sdks/find_ifortenv.lua @@ -124,10 +124,14 @@ function _find_intel_on_linux(opt) return {sdkdir = sdkdir, bindir = bindir, libdir = path.join(sdkdir, "lib")} end - if is_host("linux") then - local arch = os.arch() == "x86_64" and "intel64" or "ia32" - local host = is_host("macosx") and "macos" or "linux" - local paths = {"~/intel/oneapi/compiler/latest/" .. host .. "/bin/" .. arch} + -- find it from oneapi sdk directory + local oneapi_rootdirs = {"~/intel/oneapi/compiler", "/opt/intel/oneapi/compiler"} + local arch = os.arch() == "x86_64" and "intel64" or "ia32" + paths = {} + for _, rootdir in ipairs(oneapi_rootdirs) do + table.insert(paths, path.join(rootdir, "*", is_host("macosx") and "mac" or "linux", "bin", arch)) + end + if #paths > 0 then local ifort = find_file("ifort", paths) if ifort then local bindir = path.directory(ifort) diff --git a/xmake/toolchains/ifort/check.lua b/xmake/toolchains/ifort/check.lua index cb37666b7..285f5c86c 100644 --- a/xmake/toolchains/ifort/check.lua +++ b/xmake/toolchains/ifort/check.lua @@ -43,7 +43,7 @@ function _check_intel_on_windows(toolchain) if tool then cprint("checking for Intel Fortran Compiler (%s) ... ${color.success}${text.success}", toolchain:arch()) toolchain:config_set("varsall", ifortvarsall) - toolchain:config_save() + toolchain:configs_save() return true end end @@ -63,7 +63,8 @@ function _check_intel_on_linux(toolchain) if tool then cprint("checking for Intel Fortran Compiler (%s) ... ${color.success}${text.success}", toolchain:arch()) toolchain:config_set("ifortenv", ifortenv) - toolchain:config_save() + toolchain:config_set("bindir", ifortenv.bindir) + toolchain:configs_save() return true end return true diff --git a/xmake/toolchains/ifort/load.lua b/xmake/toolchains/ifort/load.lua index 2cb212a57..1d8eb870f 100644 --- a/xmake/toolchains/ifort/load.lua +++ b/xmake/toolchains/ifort/load.lua @@ -87,7 +87,6 @@ function _load_intel_on_linux(toolchain) end -- get ifort environments - local ifortenv = toolchain:config("ifortenv") if ifortenv then local ldname = is_host("macosx") and "DYLD_LIBRARY_PATH" or "LD_LIBRARY_PATH" toolchain:add("runenvs", ldname, ifortenv.libdir) -- cgit v1.3.1 From 74e0376c16f033d1a72a280808f83c9e4aeb4874 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 8 Dec 2021 23:10:12 +0800 Subject: improve icc toolchain --- xmake/modules/detect/sdks/find_iccenv.lua | 21 ++++++++++++++++++++ xmake/toolchains/icc/check.lua | 32 ++++++++++++++++++++----------- xmake/toolchains/icc/load.lua | 9 ++++++++- xmake/toolchains/ifort/load.lua | 1 + 4 files changed, 51 insertions(+), 12 deletions(-) diff --git a/xmake/modules/detect/sdks/find_iccenv.lua b/xmake/modules/detect/sdks/find_iccenv.lua index 0e432a99c..2eb2c353c 100644 --- a/xmake/modules/detect/sdks/find_iccenv.lua +++ b/xmake/modules/detect/sdks/find_iccenv.lua @@ -102,6 +102,11 @@ function _find_intel_on_windows(opt) -- find iclvars_bat.bat local paths = {"$(env ICPP_COMPILER20)"} local iclvars_bat = find_file("bin/iclvars.bat", paths) + -- look for setvars.bat which is new in 2021 + if not iclvars_bat then + paths = {"$(env ICPP_COMPILER21)"} + iclvars_bat = find_file("../../../setvars.bat", paths) + end if iclvars_bat then -- load iclvars_bat @@ -123,6 +128,22 @@ function _find_intel_on_linux(opt) local sdkdir = path.directory(path.directory(icc)) return {sdkdir = sdkdir, bindir = path.directory(icc), path.join(sdkdir, "include"), libdir = path.join(sdkdir, "lib")} end + + -- find it from oneapi sdk directory + local oneapi_rootdirs = {"~/intel/oneapi/compiler", "/opt/intel/oneapi/compiler"} + local arch = os.arch() == "x86_64" and "intel64" or "ia32" + paths = {} + for _, rootdir in ipairs(oneapi_rootdirs) do + table.insert(paths, path.join(rootdir, "*", is_host("macosx") and "mac" or "linux", "bin", arch)) + end + if #paths > 0 then + local icc = find_file("icc", paths) + if icc then + local bindir = path.directory(icc) + local sdkdir = path.directory(bindir) + return {sdkdir = sdkdir, bindir = bindir, libdir = path.join(sdkdir, "compiler", "lib", arch)} + end + end end -- find intel c/c++ environment diff --git a/xmake/toolchains/icc/check.lua b/xmake/toolchains/icc/check.lua index 3b9c7b953..9dde538f0 100644 --- a/xmake/toolchains/icc/check.lua +++ b/xmake/toolchains/icc/check.lua @@ -28,7 +28,8 @@ import("lib.detect.find_tool") function _check_intel_on_windows(toolchain) -- have been checked? - if config.get("__iclvarsall") then + local varsall = toolchain:config("varsall") + if varsall then return true end @@ -38,18 +39,11 @@ function _check_intel_on_windows(toolchain) local iclvarsall = iccenv.iclvars local iclenv = iclvarsall[toolchain:arch()] if iclenv and iclenv.PATH and iclenv.INCLUDE and iclenv.LIB then - - -- save iclvars - config.set("__iclvarsall", iclvarsall) - - -- check compiler - local program = nil local tool = find_tool("icl.exe", {force = true, envs = iclenv, version = true}) if tool then - program = tool.program - end - if program then cprint("checking for Intel C/C++ Compiler (%s) ... ${color.success}${text.success}", toolchain:arch()) + toolchain:config_set("varsall", iclvarsall) + toolchain:configs_save() return true end end @@ -58,7 +52,23 @@ end -- check intel on linux function _check_intel_on_linux(toolchain) - return find_tool("icc") + local iccenv = toolchain:config("iccenv") + if iccenv then + return true + end + iccenv = find_iccenv() + if iccenv then + local ldname = is_host("macosx") and "DYLD_LIBRARY_PATH" or "LD_LIBRARY_PATH" + local tool = find_tool("icc", {force = true, envs = {[ldname] = iccenv.libdir}, paths = iccenv.bindir}) + if tool then + cprint("checking for Intel C/C++ Compiler (%s) ... ${color.success}${text.success}", toolchain:arch()) + toolchain:config_set("iccenv", iccenv) + toolchain:config_set("bindir", iccenv.bindir) + toolchain:configs_save() + return true + end + return true + end end -- main entry diff --git a/xmake/toolchains/icc/load.lua b/xmake/toolchains/icc/load.lua index 5784fc5c8..e1ceba260 100644 --- a/xmake/toolchains/icc/load.lua +++ b/xmake/toolchains/icc/load.lua @@ -26,7 +26,7 @@ import("core.project.config") function _add_iclenv(toolchain, name) -- get iclvarsall - local iclvarsall = config.get("__iclvarsall") + local iclvarsall = toolchain:config("varsall") if not iclvarsall then return end @@ -100,6 +100,13 @@ function _load_intel_on_linux(toolchain) toolchain:add("ldflags", march) toolchain:add("shflags", march) end + + -- get icc environments + local iccenv = toolchain:config("iccenv") + if iccenv then + local ldname = is_host("macosx") and "DYLD_LIBRARY_PATH" or "LD_LIBRARY_PATH" + toolchain:add("runenvs", ldname, iccenv.libdir) + end end -- main entry diff --git a/xmake/toolchains/ifort/load.lua b/xmake/toolchains/ifort/load.lua index 1d8eb870f..2cb212a57 100644 --- a/xmake/toolchains/ifort/load.lua +++ b/xmake/toolchains/ifort/load.lua @@ -87,6 +87,7 @@ function _load_intel_on_linux(toolchain) end -- get ifort environments + local ifortenv = toolchain:config("ifortenv") if ifortenv then local ldname = is_host("macosx") and "DYLD_LIBRARY_PATH" or "LD_LIBRARY_PATH" toolchain:add("runenvs", ldname, ifortenv.libdir) -- cgit v1.3.1 From 49de8dfa264e55943390b6cfbd2f407ef42e4313 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 8 Dec 2021 23:10:33 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ce9d0225..1e08e7d5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * [#1872](https://github.com/xmake-io/xmake/issues/1872): Escape characters for set_configvar * [#1888](https://github.com/xmake-io/xmake/issues/1888): Improve windows installer to avoid remove other files * [#1895](https://github.com/xmake-io/xmake/issues/1895): Improve `plugin.vsxmake.autoupdate` rule +* [#1893](https://github.com/xmake-io/xmake/issues/1893): Improve to detect icc and ifort toolchains ### Bugs fixed @@ -1157,6 +1158,7 @@ * [#1872](https://github.com/xmake-io/xmake/issues/1872): 支持转义 set_configvar 中字符串值 * [#1888](https://github.com/xmake-io/xmake/issues/1888): 改进 windows 安装器,避免错误删除其他安装目录下的文件 * [#1895](https://github.com/xmake-io/xmake/issues/1895): 改进 `plugin.vsxmake.autoupdate` 规则 +* [#1893](https://github.com/xmake-io/xmake/issues/1893): 改进探测 icc 和 ifort 工具链 ### Bugs 修复 -- cgit v1.3.1 From b76de4c1fb632724c412a1638af8694fb35e021d Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 8 Dec 2021 23:15:44 +0800 Subject: add linux driver rule stub --- tests/projects/linux/driver/hello/Makefile | 2 +- tests/projects/linux/driver/hello/hello.c | 21 --------------------- tests/projects/linux/driver/hello/src/hello.c | 21 +++++++++++++++++++++ tests/projects/linux/driver/hello/xmake.lua | 9 +++++++++ xmake/rules/platform/linux/driver/xmake.lua | 27 +++++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 22 deletions(-) delete mode 100644 tests/projects/linux/driver/hello/hello.c create mode 100644 tests/projects/linux/driver/hello/src/hello.c create mode 100644 tests/projects/linux/driver/hello/xmake.lua create mode 100644 xmake/rules/platform/linux/driver/xmake.lua diff --git a/tests/projects/linux/driver/hello/Makefile b/tests/projects/linux/driver/hello/Makefile index d69924339..0cac0535c 100644 --- a/tests/projects/linux/driver/hello/Makefile +++ b/tests/projects/linux/driver/hello/Makefile @@ -1,5 +1,5 @@ ifneq ($(KERNELRELEASE),) - obj-m := hello.o + obj-m := src/hello.o else KERN_DIR ?= /usr/src/linux-headers-5.11.0-41-generic/ PWD := $(shell pwd) diff --git a/tests/projects/linux/driver/hello/hello.c b/tests/projects/linux/driver/hello/hello.c deleted file mode 100644 index 2614fb2cc..000000000 --- a/tests/projects/linux/driver/hello/hello.c +++ /dev/null @@ -1,21 +0,0 @@ -#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/linux/driver/hello/src/hello.c b/tests/projects/linux/driver/hello/src/hello.c new file mode 100644 index 000000000..2614fb2cc --- /dev/null +++ b/tests/projects/linux/driver/hello/src/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/linux/driver/hello/xmake.lua b/tests/projects/linux/driver/hello/xmake.lua new file mode 100644 index 000000000..079c31754 --- /dev/null +++ b/tests/projects/linux/driver/hello/xmake.lua @@ -0,0 +1,9 @@ +add_rules("mode.release", "mode.debug") + +add_requires("linux-headers", {configs = {driver_modules = true}}) + +target("hello") + add_rules("platform.linux.driver") + add_files("src/*.c") + add_packages("linux-headers") + set_license("GPL-2.0") diff --git a/xmake/rules/platform/linux/driver/xmake.lua b/xmake/rules/platform/linux/driver/xmake.lua new file mode 100644 index 000000000..dcecf4a1b --- /dev/null +++ b/xmake/rules/platform/linux/driver/xmake.lua @@ -0,0 +1,27 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +-- build linux driver module +rule("platform.linux.driver") + on_load(function (target) + target:set("kind", "binary") + -- TODO + end) + -- cgit v1.3.1 From bf56b9e48181726b6764ea47ea271fbde47a6f3c Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 8 Dec 2021 23:26:11 +0800 Subject: update tbox --- core/src/tbox/tbox | 2 +- xmake/core/base/os.lua | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/core/src/tbox/tbox b/core/src/tbox/tbox index 122a479e6..f301f5eca 160000 --- a/core/src/tbox/tbox +++ b/core/src/tbox/tbox @@ -1 +1 @@ -Subproject commit 122a479e626ee3fdd7d6c1117ec7c19212a1e087 +Subproject commit f301f5eca1e909ffd6bcf688f14646d8226acfd9 diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index a4fdb570e..812451afd 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -143,18 +143,21 @@ end -- remove single file or directory function os._rm(filedir) + print("rm", filedir) -- check assert(filedir) -- is file or link? if os.isfile(filedir) or os.islink(filedir) then + print("rmfile") -- remove file if not os.rmfile(filedir) then return false, string.format("cannot remove file %s %s", filedir, os.strerror()) end -- is directory? elseif os.isdir(filedir) then + print("rmdir") -- remove directory if not os.rmdir(filedir) then return false, string.format("cannot remove directory %s %s", filedir, os.strerror()) @@ -450,6 +453,7 @@ end -- remove files or directories function os.rm(filepath) + print("rmssss", filepath) -- check arguments if not filepath then -- cgit v1.3.1 From 6bd17831f2f68610a229f8802e4cd7d3060c7ee8 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 8 Dec 2021 23:27:16 +0800 Subject: remove debug lines --- xmake/core/base/os.lua | 4 ---- 1 file changed, 4 deletions(-) diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index 812451afd..a4fdb570e 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -143,21 +143,18 @@ end -- remove single file or directory function os._rm(filedir) - print("rm", filedir) -- check assert(filedir) -- is file or link? if os.isfile(filedir) or os.islink(filedir) then - print("rmfile") -- remove file if not os.rmfile(filedir) then return false, string.format("cannot remove file %s %s", filedir, os.strerror()) end -- is directory? elseif os.isdir(filedir) then - print("rmdir") -- remove directory if not os.rmdir(filedir) then return false, string.format("cannot remove directory %s %s", filedir, os.strerror()) @@ -453,7 +450,6 @@ end -- remove files or directories function os.rm(filepath) - print("rmssss", filepath) -- check arguments if not filepath then -- cgit v1.3.1 From c28b02c55c235f02fad3edb5c0855ca186eeff14 Mon Sep 17 00:00:00 2001 From: PucklaMotzer09 Date: Thu, 9 Dec 2021 12:27:37 +0100 Subject: Fix sdkdir in ifortenv and iccenv --- xmake/modules/detect/sdks/find_iccenv.lua | 2 +- xmake/modules/detect/sdks/find_ifortenv.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/modules/detect/sdks/find_iccenv.lua b/xmake/modules/detect/sdks/find_iccenv.lua index 2eb2c353c..84b40fade 100644 --- a/xmake/modules/detect/sdks/find_iccenv.lua +++ b/xmake/modules/detect/sdks/find_iccenv.lua @@ -140,7 +140,7 @@ function _find_intel_on_linux(opt) local icc = find_file("icc", paths) if icc then local bindir = path.directory(icc) - local sdkdir = path.directory(bindir) + local sdkdir = path.directory(path.directory(bindir)) return {sdkdir = sdkdir, bindir = bindir, libdir = path.join(sdkdir, "compiler", "lib", arch)} end end diff --git a/xmake/modules/detect/sdks/find_ifortenv.lua b/xmake/modules/detect/sdks/find_ifortenv.lua index 131c4b930..d851b3f6a 100644 --- a/xmake/modules/detect/sdks/find_ifortenv.lua +++ b/xmake/modules/detect/sdks/find_ifortenv.lua @@ -141,7 +141,7 @@ function _find_intel_on_linux(opt) local ifort = find_file("ifort", paths) if ifort then local bindir = path.directory(ifort) - local sdkdir = path.directory(bindir) + local sdkdir = path.directory(path.directory(bindir)) return {sdkdir = sdkdir, bindir = bindir, libdir = path.join(sdkdir, "compiler", "lib", arch)} end end -- cgit v1.3.1 From a70d5148d402195a411c590fd049c045ed5b5c7b Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 9 Dec 2021 23:03:28 +0800 Subject: Update engine.c --- core/src/xmake/engine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index 53ec0d1d0..f407f2cd6 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -612,7 +612,7 @@ static tb_bool_t xm_engine_get_program_directory(xm_engine_t* engine, tb_char_t* tb_size_t i; tb_file_info_t info; tb_char_t scriptpath[TB_PATH_MAXN]; - tb_char_t const* subdirs[] = {"", sharedir}; + tb_char_t const* subdirs[] = {".", sharedir}; for (i = 0; i < tb_arrayn(subdirs); i++) { // get program directory -- cgit v1.3.1 From 8455cec237846afa4b43f0f35fe1d2e0305f97b9 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 9 Dec 2021 23:08:47 +0800 Subject: update ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a8573ebd9..b8b148d94 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,7 @@ compile_commands.json !/xmake/actions/build/ # for linux driver +*.o *.ko *.mod .*.cmd -- cgit v1.3.1 From fb2378cff6c3ecd97e179ae91284ee1bd5e60553 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 10 Dec 2021 22:47:13 +0800 Subject: improve linux driver rule --- .gitignore | 1 + .../rules/platform/linux/driver/driver_modules.lua | 48 ++++++++++++++++++++++ xmake/rules/platform/linux/driver/xmake.lua | 6 ++- 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 xmake/rules/platform/linux/driver/driver_modules.lua diff --git a/.gitignore b/.gitignore index b8b148d94..b9f47f1b4 100644 --- a/.gitignore +++ b/.gitignore @@ -56,5 +56,6 @@ compile_commands.json *.ko *.mod .*.cmd +*.mod.c Module.symvers modules.order diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua new file mode 100644 index 000000000..ac2dbbb85 --- /dev/null +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -0,0 +1,48 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file driver_modules.lua +-- + +-- get linux-headers sdk +function _get_linux_headers_sdk(target) + local linux_headers = assert(target:pkg("linux-headers"), "please add `add_requires(\"linux-headers\", {configs = {driver_modules = true}})` and `add_packages(\"linux-headers\")` to the given target!") + local includedirs = linux_headers:get("includedirs") or linux_headers:get("sysincludedirs") + local version = linux_headers:version() + local linux_headersdir + for _, includedir in ipairs(includedirs) do + if includedir:find("linux-headers", 1, true) then + linux_headersdir = path.directory(includedir) + break + end + end + assert(linux_headersdir, "linux-headers not found!") + return {version = version, sdkdir = linux_headersdir, includedirs = includedirs} +end + +function load(target) + -- we need only need binary kind, because we will rewrite on_link + target:set("kind", "binary") + + -- get and save linux-headers sdk + local linux_headers = _get_linux_headers_sdk(target) + target:data_set("linux.driver.linux_headers", linux_headers) + print(linux_headers) +end + +function link(target, opt) +end diff --git a/xmake/rules/platform/linux/driver/xmake.lua b/xmake/rules/platform/linux/driver/xmake.lua index dcecf4a1b..84960049d 100644 --- a/xmake/rules/platform/linux/driver/xmake.lua +++ b/xmake/rules/platform/linux/driver/xmake.lua @@ -21,7 +21,9 @@ -- build linux driver module rule("platform.linux.driver") on_load(function (target) - target:set("kind", "binary") - -- TODO + import("driver_modules").load(target) + end) + on_link(function (target, opt) + import("driver_modules").link(target, opt) end) -- cgit v1.3.1 From 0a7b457f417e5426221a35381db4d40fdc696874 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 10 Dec 2021 22:51:20 +0800 Subject: check kernel configuration --- xmake/rules/platform/linux/driver/driver_modules.lua | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index ac2dbbb85..839a479e6 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -23,15 +23,21 @@ function _get_linux_headers_sdk(target) local linux_headers = assert(target:pkg("linux-headers"), "please add `add_requires(\"linux-headers\", {configs = {driver_modules = true}})` and `add_packages(\"linux-headers\")` to the given target!") local includedirs = linux_headers:get("includedirs") or linux_headers:get("sysincludedirs") local version = linux_headers:version() + local includedir local linux_headersdir - for _, includedir in ipairs(includedirs) do - if includedir:find("linux-headers", 1, true) then - linux_headersdir = path.directory(includedir) + for _, dir in ipairs(includedirs) do + if dir:find("linux-headers", 1, true) then + includedir = dir + linux_headersdir = path.directory(dir) break end end assert(linux_headersdir, "linux-headers not found!") - return {version = version, sdkdir = linux_headersdir, includedirs = includedirs} + if not os.isfile(path.join(includedir, "generated/autoconf.h")) and + not os.isfile(path.join(includedir, "config/auto.conf")) then + raise("kernel configuration is invalid. include/generated/autoconf.h or include/config/auto.conf are missing.") + end + return {version = version, sdkdir = linux_headersdir, includedir = includedir} end function load(target) -- cgit v1.3.1 From b2f5ac94d400d99614d2b33219ca7aac69894557 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 10 Dec 2021 23:00:53 +0800 Subject: add some basic flags for driver --- .../rules/platform/linux/driver/driver_modules.lua | 45 +++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 839a479e6..2f476dacf 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -47,7 +47,50 @@ function load(target) -- get and save linux-headers sdk local linux_headers = _get_linux_headers_sdk(target) target:data_set("linux.driver.linux_headers", linux_headers) - print(linux_headers) + + -- check compiler, we must use gcc + assert(target:has_tool("cc", "gcc"), "we must use gcc compiler!") + + -- add includedirs + local sdkdir = linux_headers.sdkdir + local includedir = linux_headers.includedir + local archsubdir + if target:is_arch("x86_64", "i386") then + archsubdir = path.join(sdkdir, "arch", "x86") + end + assert(archsubdir, "unknown arch(%s) for linux driver modules!", target:arch()) + target:add("sysincludedirs", "/usr/lib/gcc/x86_64-linux-gnu/10/include") + target:add("includedirs", includedir) + target:add("includedirs", path.join(includedir, "uapi")) + target:add("includedirs", path.join(includedir, "generated", "uapi")) + target:add("includedirs", path.join(archsubdir, "include")) + target:add("includedirs", path.join(archsubdir, "include", "generated")) + target:add("includedirs", path.join(archsubdir, "include", "uapi")) + target:add("includedirs", path.join(archsubdir, "include", "generated", "uapi")) + target:add("cflags", "-include", path.join(includedir, "linux", "kconfig.h")) + target:add("cflags", "-include", path.join(includedir, "linux", "compiler_types.h")) + + -- add compilation flags + target:set("policy", "check.auto_ignore_flags", false) + target:add("defines", "__KERNEL__", "MODULE", "CC_USING_FENTRY") + target:add("defines", "KBUILD_BASENAME=\"" .. target:name() .. "\"", "KBUILD_MODNAME=\"" .. target:name() .. "\"") + if target:is_arch("x86_64", "i386") then + target:add("defines", "CONFIG_X86_X32_ABI") + end + target:set("optimize", "faster") -- we need use -O2 for gcc + target:set("languages", "gnu89") + target:add("cflags", "-nostdinc") + target:add("cflags", "-mno-sse", "-mno-mmx", "-mno-sse2", "-mno-3dnow", "-mno-avx", "-mno-80387", "-mno-fp-ret-in-387") + target:add("cflags", "-mpreferred-stack-boundary=3", "-mskip-rax-setup", "-mtune=generic", "-mno-red-zone", "-mcmodel=kernel") + target:add("cflags", "-mindirect-branch=thunk-extern", "-mindirect-branch-register", "-mrecord-mcount", "-mfentry") + target:add("cflags", "-fmacro-prefix-map=./=", " -fno-strict-aliasing", "-fno-common", "-fshort-wchar", "-fno-PIE") + target:add("cflags", "-fcf-protection=none", "-falign-jumps=1", "-falign-loops=1", "-fno-asynchronous-unwind-tables") + target:add("cflags", "-fno-jump-tables", "-fno-delete-null-pointer-checks", "-fno-allow-store-data-races") + target:add("cflags", "-fno-reorder-blocks", "-fno-ipa-cp-clone", "-fno-partial-inlining", "-fstack-protector-strong") + target:add("cflags", "-fno-inline-functions-called-once", "-falign-functions=32") + target:add("cflags", "-fno-strict-overflow", "-fno-stack-check", "-fconserve-stack") + target:add("cflags", "-fsanitize=kernel-address", "-fasan-shadow-offset=0xdffffc0000000000", "-fsanitize-coverage=trace-pc", "-fsanitize-coverage=trace-cmp") + target:add("cflags", "--param asan-globals=1", "--param asan-instrumentation-with-call-threshold=0", "--param asan-stack=1", "--param asan-instrument-allocas=1") end function link(target, opt) -- cgit v1.3.1 From c9ae6a487e00c5403551234ba8e76b3aee05a58e Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 10 Dec 2021 23:02:43 +0800 Subject: fix include flags --- xmake/rules/platform/linux/driver/driver_modules.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 2f476dacf..964a41766 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -67,8 +67,8 @@ function load(target) target:add("includedirs", path.join(archsubdir, "include", "generated")) target:add("includedirs", path.join(archsubdir, "include", "uapi")) target:add("includedirs", path.join(archsubdir, "include", "generated", "uapi")) - target:add("cflags", "-include", path.join(includedir, "linux", "kconfig.h")) - target:add("cflags", "-include", path.join(includedir, "linux", "compiler_types.h")) + target:add("cflags", "-include " .. path.join(includedir, "linux", "kconfig.h")) + target:add("cflags", "-include " .. path.join(includedir, "linux", "compiler_types.h")) -- add compilation flags target:set("policy", "check.auto_ignore_flags", false) -- cgit v1.3.1 From e21d37159291bf7d3908307922ed71a5cf95e31e Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 10 Dec 2021 23:20:22 +0800 Subject: fix includedirs --- xmake/rules/platform/linux/driver/driver_modules.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 964a41766..0c1f8b9cd 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -60,15 +60,16 @@ function load(target) end assert(archsubdir, "unknown arch(%s) for linux driver modules!", target:arch()) target:add("sysincludedirs", "/usr/lib/gcc/x86_64-linux-gnu/10/include") - target:add("includedirs", includedir) - target:add("includedirs", path.join(includedir, "uapi")) - target:add("includedirs", path.join(includedir, "generated", "uapi")) target:add("includedirs", path.join(archsubdir, "include")) target:add("includedirs", path.join(archsubdir, "include", "generated")) + target:add("includedirs", includedir) target:add("includedirs", path.join(archsubdir, "include", "uapi")) target:add("includedirs", path.join(archsubdir, "include", "generated", "uapi")) + target:add("includedirs", path.join(includedir, "uapi")) + target:add("includedirs", path.join(includedir, "generated", "uapi")) target:add("cflags", "-include " .. path.join(includedir, "linux", "kconfig.h")) target:add("cflags", "-include " .. path.join(includedir, "linux", "compiler_types.h")) + target:pkg("linux-headers"):set("includedirs", nil) -- TODO -- add compilation flags target:set("policy", "check.auto_ignore_flags", false) -- cgit v1.3.1 From b5e483352b76ff0d18635bc0b33912552e11bc74 Mon Sep 17 00:00:00 2001 From: charles seizilles Date: Fri, 10 Dec 2021 12:46:50 +0100 Subject: Fix typos --- xmake/plugins/project/vstudio/impl/vsinfo.lua | 2 +- xmake/plugins/project/vsxmake/render.lua | 4 ++-- xmake/plugins/project/vsxmake/vsxmake.lua | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/xmake/plugins/project/vstudio/impl/vsinfo.lua b/xmake/plugins/project/vstudio/impl/vsinfo.lua index 9b6cc829c..e210f6705 100644 --- a/xmake/plugins/project/vstudio/impl/vsinfo.lua +++ b/xmake/plugins/project/vstudio/impl/vsinfo.lua @@ -90,7 +90,7 @@ local vsinfo = , project_version = "17" , filters_version = "4.0" , solution_version = "12" - , toolset_version = "v142" + , toolset_version = "v143" , sdk_version = "10.0.19041.0" } } diff --git a/xmake/plugins/project/vsxmake/render.lua b/xmake/plugins/project/vsxmake/render.lua index 99be35197..d599f1dde 100644 --- a/xmake/plugins/project/vsxmake/render.lua +++ b/xmake/plugins/project/vsxmake/render.lua @@ -18,7 +18,7 @@ -- @file render.lua -- -function _fill(opt, parmas) +function _fill(opt, params) return function(match) local imp = match:match("^Import%((.+)%)$") if imp then @@ -28,7 +28,7 @@ function _fill(opt, parmas) local args = path.filename(func):match("%((.+)%)$"):split(",") return _render(func, opt, args) end - return opt.paramsprovider(match, parmas) or "" + return opt.paramsprovider(match, params) or "" end end diff --git a/xmake/plugins/project/vsxmake/vsxmake.lua b/xmake/plugins/project/vsxmake/vsxmake.lua index 894a1895b..469448764 100644 --- a/xmake/plugins/project/vsxmake/vsxmake.lua +++ b/xmake/plugins/project/vsxmake/vsxmake.lua @@ -202,7 +202,7 @@ function make(version) version = tonumber(config.get("vs")) if not version then return function(outputdir) - raise("invalid vs version, run `xmake f --vs=201x`") + raise("invalid vs version, run `xmake f --vs=20xx`") end end end -- cgit v1.3.1 From 7908560287910061c942125db6f76884aa2e51b2 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 00:26:46 +0800 Subject: remove builtin sysincludedirs --- xmake/rules/platform/linux/driver/driver_modules.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 0c1f8b9cd..a94319e8e 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -69,7 +69,9 @@ function load(target) target:add("includedirs", path.join(includedir, "generated", "uapi")) target:add("cflags", "-include " .. path.join(includedir, "linux", "kconfig.h")) target:add("cflags", "-include " .. path.join(includedir, "linux", "compiler_types.h")) - target:pkg("linux-headers"):set("includedirs", nil) -- TODO + -- we need disable includedirs from add_packages("linux-headers") + target:pkg("linux-headers"):set("includedirs", nil) + target:pkg("linux-headers"):set("sysincludedirs", nil) -- add compilation flags target:set("policy", "check.auto_ignore_flags", false) -- cgit v1.3.1 From 349a22942e600821aa72424bbfa58f021357b1cf Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 00:41:41 +0800 Subject: improve module tests --- tests/projects/linux/driver/hello/Makefile | 4 ++- tests/projects/linux/driver/hello/src/add.c | 3 ++ tests/projects/linux/driver/hello/src/hello.c | 4 ++- .../rules/platform/linux/driver/driver_modules.lua | 33 ++++++++++++++++++++++ xmake/rules/platform/linux/driver/xmake.lua | 1 + 5 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 tests/projects/linux/driver/hello/src/add.c diff --git a/tests/projects/linux/driver/hello/Makefile b/tests/projects/linux/driver/hello/Makefile index 0cac0535c..1d5aa92b4 100644 --- a/tests/projects/linux/driver/hello/Makefile +++ b/tests/projects/linux/driver/hello/Makefile @@ -1,5 +1,6 @@ ifneq ($(KERNELRELEASE),) - obj-m := src/hello.o + obj-m := hello.o + hello-objs := ./src/hello.o ./src/add.o else KERN_DIR ?= /usr/src/linux-headers-5.11.0-41-generic/ PWD := $(shell pwd) @@ -10,4 +11,5 @@ endif clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions + rm -rf src/*.o src/*~ core src/.depend src/.*.cmd src/*.ko src/*.mod.c src/.tmp_versions diff --git a/tests/projects/linux/driver/hello/src/add.c b/tests/projects/linux/driver/hello/src/add.c new file mode 100644 index 000000000..59aab4983 --- /dev/null +++ b/tests/projects/linux/driver/hello/src/add.c @@ -0,0 +1,3 @@ +int add(int a, int b) { + return a + b; +} diff --git a/tests/projects/linux/driver/hello/src/hello.c b/tests/projects/linux/driver/hello/src/hello.c index 2614fb2cc..414a03bb2 100644 --- a/tests/projects/linux/driver/hello/src/hello.c +++ b/tests/projects/linux/driver/hello/src/hello.c @@ -6,9 +6,11 @@ MODULE_AUTHOR("Ruki"); MODULE_DESCRIPTION("A simple Hello World Module"); MODULE_ALIAS("a simplest module"); +int add(int a, int b); + int hello_init(void) { - printk(KERN_INFO "Hello World\n"); + printk(KERN_INFO "Hello World: %d\n", add(1, 2)); return 0; } diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index a94319e8e..a4a4f8691 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -18,6 +18,12 @@ -- @file driver_modules.lua -- +-- imports +import("core.base.option") +import("core.project.depend") +import("utils.progress") +import("private.tools.ccache") + -- get linux-headers sdk function _get_linux_headers_sdk(target) local linux_headers = assert(target:pkg("linux-headers"), "please add `add_requires(\"linux-headers\", {configs = {driver_modules = true}})` and `add_packages(\"linux-headers\")` to the given target!") @@ -96,5 +102,32 @@ function load(target) target:add("cflags", "--param asan-globals=1", "--param asan-instrumentation-with-call-threshold=0", "--param asan-stack=1", "--param asan-instrument-allocas=1") end +--[[ +function after_build_file(target, sourcefile, opt) + + -- get modepost + local modpost + local linux_headers = target:data("linux.driver.linux_headers") + if linux_headers then + modpost = path.join(linux_headers.sdkdir, "scripts", "mod", "modpost") + end + assert(modpost and os.isfile(modpost), "modpost not found!") + + -- compile .mod.c file + local objectfile = target:objectfile(sourcefile) + local modfile = objectfile:gsub("%.o$", ".mod") + local modfile_c = objectfile:gsub("%.o$", ".mod.c") + local modfile_o = objectfile:gsub("%.o$", ".mod.o") + local dependfile = target:dependfile(modfile_o) + local exists_ccache = ccache.exists() + depend.on_changed(function () + progress.show(opt.progress, "${color.build.object}%scompiling.mod.$(mode) %s", exists_ccache and "ccache " or "", modfile_c) + os.vrunv(modpost, {"-m", "-a", "-o", }) + end, {dependfile = dependfile, files = {sourcefile}}) + + -- echo build/.objs/hello/linux/x86_64/release/src/hello.c.o | + -- scripts/mod/modpost -m -a -o /tmp/Module.symvers -e -N -T - +end]] + function link(target, opt) end diff --git a/xmake/rules/platform/linux/driver/xmake.lua b/xmake/rules/platform/linux/driver/xmake.lua index 84960049d..78ba6d089 100644 --- a/xmake/rules/platform/linux/driver/xmake.lua +++ b/xmake/rules/platform/linux/driver/xmake.lua @@ -20,6 +20,7 @@ -- build linux driver module rule("platform.linux.driver") + set_sourcekinds("cc") on_load(function (target) import("driver_modules").load(target) end) -- cgit v1.3.1 From 41da093977e662321899f0a4e980097ca8dd295b Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 00:54:05 +0800 Subject: impl linux driver rule --- xmake/core/project/target.lua | 2 +- .../rules/platform/linux/driver/driver_modules.lua | 102 ++++++++++++++++----- 2 files changed, 78 insertions(+), 26 deletions(-) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 499db099c..cb470a3c8 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -2092,7 +2092,7 @@ function target.filename(targetname, targetkind, opt) -- make filename by format local filename = targetname - local format = opt.format or platform.format(targetkind, opt.plat, opt.arch) + local format = opt.format or platform.format(targetkind, opt.plat, opt.arch) or "$(name)" if format then local splitinfo = format:split("$(name)", {plain = true, strict = true}) local prefixname = splitinfo[1] or "" diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index a4a4f8691..812fda022 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -49,6 +49,7 @@ end function load(target) -- we need only need binary kind, because we will rewrite on_link target:set("kind", "binary") + target:set("extension", ".ko") -- get and save linux-headers sdk local linux_headers = _get_linux_headers_sdk(target) @@ -102,32 +103,83 @@ function load(target) target:add("cflags", "--param asan-globals=1", "--param asan-instrumentation-with-call-threshold=0", "--param asan-stack=1", "--param asan-instrument-allocas=1") end ---[[ -function after_build_file(target, sourcefile, opt) - - -- get modepost - local modpost - local linux_headers = target:data("linux.driver.linux_headers") - if linux_headers then - modpost = path.join(linux_headers.sdkdir, "scripts", "mod", "modpost") - end - assert(modpost and os.isfile(modpost), "modpost not found!") - - -- compile .mod.c file - local objectfile = target:objectfile(sourcefile) - local modfile = objectfile:gsub("%.o$", ".mod") - local modfile_c = objectfile:gsub("%.o$", ".mod.c") - local modfile_o = objectfile:gsub("%.o$", ".mod.o") - local dependfile = target:dependfile(modfile_o) - local exists_ccache = ccache.exists() +function link(target, opt) + local targetfile = target:targetfile() + local dependfile = target:dependfile(targetfile) + local objectfiles = target:objectfiles() depend.on_changed(function () - progress.show(opt.progress, "${color.build.object}%scompiling.mod.$(mode) %s", exists_ccache and "ccache " or "", modfile_c) - os.vrunv(modpost, {"-m", "-a", "-o", }) - end, {dependfile = dependfile, files = {sourcefile}}) - -- echo build/.objs/hello/linux/x86_64/release/src/hello.c.o | - -- scripts/mod/modpost -m -a -o /tmp/Module.symvers -e -N -T - -end]] + -- trace + progress.show(opt.progress, "${color.build.object}linking.$(mode) %s", targetfile) -function link(target, opt) + -- get module scripts + local modpost, ldscriptfile + local linux_headers = target:data("linux.driver.linux_headers") + if linux_headers then + modpost = path.join(linux_headers.sdkdir, "scripts", "mod", "modpost") + ldscriptfile = path.join(linux_headers.sdkdir, "scripts", "module.lds") + end + assert(modpost and os.isfile(modpost), "scripts/mod/modpost not found!") + assert(ldscriptfile and os.isfile(ldscriptfile), "scripts/module.lds not found!") + + -- link target.o + local argv = {"-m"} + if target:is_arch("x86_64") then + table.insert(argv, "elf_x86_64") + end + local targetfile_o = target:objectfile(targetfile) + table.insert(argv, "-r") + table.insert(argv, "-o") + table.insert(argv, targetfile_o) + table.join2(argv, objectfiles) + os.mkdir(path.directory(targetfile_o)) + os.vrunv("ld", argv) + + -- generate target.mod + local targetfile_mod = targetfile_o:gsub("%.o$", ".mod") + io.writefile(targetfile_mod, table.concat(objectfiles, " ") .. "\n\n") + + -- generate .sourcename.o.cmd + -- we need only touch an empty file, otherwise modpost command will raise error. + for _, objectfile in ipairs(objectfiles) do + local objectdir = path.directory(objectfile) + local objectname = path.filename(objectfile) + local cmdfile = path.join(objectdir, "." .. objectname .. ".cmd") + io.writefile(cmdfile, "") + end + + -- generate target.mod.c + local orderfile = path.join(path.directory(targetfile_o), "modules.order") + local symversfile = path.join(path.directory(targetfile_o), "Module.symvers") + argv = {"-m", "-a", "-o", symversfile, "-e", "-N", "-T", "-"} + io.writefile(orderfile, targetfile_o .. "\n") + os.vrunv(modpost, argv, {stdin = orderfile}) + + -- compile target.mod.c + local targetfile_mod_c = targetfile_o:gsub("%.o$", ".mod.c") + local targetfile_mod_o = targetfile_o:gsub("%.o$", ".mod.o") + local compinst = target:compiler("cc") + if option.get("verbose") then + print(compinst:compcmd(targetfile_mod_c, targetfile_mod_o, {target = target, rawargs = true})) + end + assert(compinst:compile(targetfile_mod_c, targetfile_mod_o, {target = target})) + + -- link target.ko + argv = {"-m"} + if target:is_arch("x86_64") then + table.insert(argv, "elf_x86_64") + end + local targetfile_o = target:objectfile(targetfile) + table.insert(argv, "-r") + table.insert(argv, "--build-id=sha1") + table.insert(argv, "-T") + table.insert(argv, ldscriptfile) + table.insert(argv, "-o") + table.insert(argv, targetfile) + table.insert(argv, targetfile_o) + table.insert(argv, targetfile_mod_o) + os.mkdir(path.directory(targetfile)) + os.vrunv("ld", argv) + + end, {dependfile = dependfile, lastmtime = os.mtime(target:targetfile()), files = objectfiles}) end -- cgit v1.3.1 From ec7711e4c84733a71b1932eeb59eed9844ea5b2d Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 00:54:16 +0800 Subject: add todo --- xmake/rules/platform/linux/driver/driver_modules.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 812fda022..a482b8527 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -66,7 +66,7 @@ function load(target) archsubdir = path.join(sdkdir, "arch", "x86") end assert(archsubdir, "unknown arch(%s) for linux driver modules!", target:arch()) - target:add("sysincludedirs", "/usr/lib/gcc/x86_64-linux-gnu/10/include") + target:add("sysincludedirs", "/usr/lib/gcc/x86_64-linux-gnu/10/include") -- TODO target:add("includedirs", path.join(archsubdir, "include")) target:add("includedirs", path.join(archsubdir, "include", "generated")) target:add("includedirs", includedir) @@ -83,7 +83,7 @@ function load(target) -- add compilation flags target:set("policy", "check.auto_ignore_flags", false) target:add("defines", "__KERNEL__", "MODULE", "CC_USING_FENTRY") - target:add("defines", "KBUILD_BASENAME=\"" .. target:name() .. "\"", "KBUILD_MODNAME=\"" .. target:name() .. "\"") + target:add("defines", "KBUILD_BASENAME=\"" .. target:name() .. "\"", "KBUILD_MODNAME=\"" .. target:name() .. "\"") -- TODO if target:is_arch("x86_64", "i386") then target:add("defines", "CONFIG_X86_X32_ABI") end -- cgit v1.3.1 From a64f493f3b6812bef7f78fa973f11cc963d1b8a3 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 10:10:28 +0800 Subject: get gcc_incluedir --- .../rules/platform/linux/driver/driver_modules.lua | 42 +++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index a482b8527..7addb3764 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -46,6 +46,43 @@ function _get_linux_headers_sdk(target) return {version = version, sdkdir = linux_headersdir, includedir = includedir} end +-- get c system search include directory of gcc +-- +-- e.g. gcc -E -Wp,-v -xc /dev/null +-- +-- ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" +-- ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/include-fixed" +-- ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include" +-- #include "..." search starts here: +-- #include <...> search starts here: +-- /usr/lib/gcc/x86_64-linux-gnu/10/include <-- we need get it +-- /usr/local/include +-- /usr/include/x86_64-linux-gnu +-- /usr/include +-- End of search list. +function _get_gcc_includedir(target) + local includedir = _g.includedir + if includedir == nil then + local gcc, toolname = target:tool("cc") + assert(toolname, "gcc") + + local _, result = try {function () return os.iorunv(gcc, {"-E", "-Wp,-v", "-xc", os.nuldev()}) end} + if result then + for _, line in ipairs(result:split("\n", {plain = true})) do + line = line:trim() + if os.isdir(line) then + includedir = line + break + elseif line:startswith("End") then + break + end + end + end + _g.includedir = includedir or false + end + return includedir or nil +end + function load(target) -- we need only need binary kind, because we will rewrite on_link target:set("kind", "binary") @@ -66,7 +103,10 @@ function load(target) archsubdir = path.join(sdkdir, "arch", "x86") end assert(archsubdir, "unknown arch(%s) for linux driver modules!", target:arch()) - target:add("sysincludedirs", "/usr/lib/gcc/x86_64-linux-gnu/10/include") -- TODO + local gcc_includedir = _get_gcc_includedir(target) + if gcc_includedir then + target:add("sysincludedirs", gcc_includedir) + end target:add("includedirs", path.join(archsubdir, "include")) target:add("includedirs", path.join(archsubdir, "include", "generated")) target:add("includedirs", includedir) -- cgit v1.3.1 From b2e2bf3bfb508bdff576a6eea3b8928d4d9ae50b Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 10:12:33 +0800 Subject: find ld --- xmake/rules/platform/linux/driver/driver_modules.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 7addb3764..47d5dcf54 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -21,6 +21,7 @@ -- imports import("core.base.option") import("core.project.depend") +import("lib.detect.find_tool") import("utils.progress") import("private.tools.ccache") @@ -162,6 +163,9 @@ function link(target, opt) assert(modpost and os.isfile(modpost), "scripts/mod/modpost not found!") assert(ldscriptfile and os.isfile(ldscriptfile), "scripts/module.lds not found!") + -- get ld + local ld = assert(find_tool("ld"), "ld not found!") + -- link target.o local argv = {"-m"} if target:is_arch("x86_64") then @@ -173,7 +177,7 @@ function link(target, opt) table.insert(argv, targetfile_o) table.join2(argv, objectfiles) os.mkdir(path.directory(targetfile_o)) - os.vrunv("ld", argv) + os.vrunv(ld.program, argv) -- generate target.mod local targetfile_mod = targetfile_o:gsub("%.o$", ".mod") @@ -219,7 +223,7 @@ function link(target, opt) table.insert(argv, targetfile_o) table.insert(argv, targetfile_mod_o) os.mkdir(path.directory(targetfile)) - os.vrunv("ld", argv) + os.vrunv(ld.program, argv) end, {dependfile = dependfile, lastmtime = os.mtime(target:targetfile()), files = objectfiles}) end -- cgit v1.3.1 From 93f860b16f91d46b703840d81fb1fc57904b4ead Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 10:22:59 +0800 Subject: import ld arch --- .../rules/platform/linux/driver/driver_modules.lua | 35 ++++++++++------------ 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 47d5dcf54..e3aef8c55 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -84,6 +84,13 @@ function _get_gcc_includedir(target) return includedir or nil end +-- get ld arch, e.g. ld -m elf_x86_64 +function _get_ld_arch(target) + if target:is_arch("x86_64", "i386") then + return "elf_" .. target:arch() + end +end + function load(target) -- we need only need binary kind, because we will rewrite on_link target:set("kind", "binary") @@ -102,6 +109,8 @@ function load(target) local archsubdir if target:is_arch("x86_64", "i386") then archsubdir = path.join(sdkdir, "arch", "x86") + else + raise("rule(platform.linux.driver): unsupported arch(%s)!", target:arch()) end assert(archsubdir, "unknown arch(%s) for linux driver modules!", target:arch()) local gcc_includedir = _get_gcc_includedir(target) @@ -129,7 +138,9 @@ function load(target) target:add("defines", "CONFIG_X86_X32_ABI") end target:set("optimize", "faster") -- we need use -O2 for gcc - target:set("languages", "gnu89") + if not target:get("language") then + target:set("languages", "gnu89") + end target:add("cflags", "-nostdinc") target:add("cflags", "-mno-sse", "-mno-mmx", "-mno-sse2", "-mno-3dnow", "-mno-avx", "-mno-80387", "-mno-fp-ret-in-387") target:add("cflags", "-mpreferred-stack-boundary=3", "-mskip-rax-setup", "-mtune=generic", "-mno-red-zone", "-mcmodel=kernel") @@ -167,14 +178,9 @@ function link(target, opt) local ld = assert(find_tool("ld"), "ld not found!") -- link target.o - local argv = {"-m"} - if target:is_arch("x86_64") then - table.insert(argv, "elf_x86_64") - end + local ldarch = assert(_get_ld_arch(target), "unknown ld arch!") local targetfile_o = target:objectfile(targetfile) - table.insert(argv, "-r") - table.insert(argv, "-o") - table.insert(argv, targetfile_o) + local argv = {"-m", ldarch, "-r", "-o", targetfile_o} table.join2(argv, objectfiles) os.mkdir(path.directory(targetfile_o)) os.vrunv(ld.program, argv) @@ -209,19 +215,8 @@ function link(target, opt) assert(compinst:compile(targetfile_mod_c, targetfile_mod_o, {target = target})) -- link target.ko - argv = {"-m"} - if target:is_arch("x86_64") then - table.insert(argv, "elf_x86_64") - end local targetfile_o = target:objectfile(targetfile) - table.insert(argv, "-r") - table.insert(argv, "--build-id=sha1") - table.insert(argv, "-T") - table.insert(argv, ldscriptfile) - table.insert(argv, "-o") - table.insert(argv, targetfile) - table.insert(argv, targetfile_o) - table.insert(argv, targetfile_mod_o) + argv = {"-m", ldarch, "-r", "--build-id=sha1", "-T", ldscriptfile, "-o", targetfile, targetfile_o, targetfile_mod_o} os.mkdir(path.directory(targetfile)) os.vrunv(ld.program, argv) -- cgit v1.3.1 From 990712a20eb2f54d01113e85ae7ce0ef13bf0363 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 10:32:32 +0800 Subject: fix basename for kbuild --- xmake/core/project/target.lua | 11 +++++------ xmake/rules/platform/linux/driver/driver_modules.lua | 5 ++++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index cb470a3c8..07327362d 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -398,6 +398,11 @@ function _instance:extraconf(name, item, key) return self._INFO:extraconf(name, item, key) end +-- set the extra configuration +function _instance:extraconf_set(name, item, key, value) + self._INFO:extraconf_set(name, item, key, value) +end + -- get user private data function _instance:data(name) return self._DATA and self._DATA[name] @@ -1239,14 +1244,8 @@ end -- set the config info to the given source file function _instance:fileconfig_set(sourcefile, info) - - -- get files config local filesconfig = self._FILESCONFIG or {} - - -- set config info filesconfig[sourcefile] = info - - -- update files config self._FILESCONFIG = filesconfig end diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index e3aef8c55..230a190b3 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -133,7 +133,10 @@ function load(target) -- add compilation flags target:set("policy", "check.auto_ignore_flags", false) target:add("defines", "__KERNEL__", "MODULE", "CC_USING_FENTRY") - target:add("defines", "KBUILD_BASENAME=\"" .. target:name() .. "\"", "KBUILD_MODNAME=\"" .. target:name() .. "\"") -- TODO + target:add("defines", "KBUILD_MODNAME=\"" .. target:name() .. "\"") + for _, sourcefile in ipairs(target:sourcefiles()) do + target:fileconfig_set(sourcefile, {defines = "KBUILD_BASENAME=\"" .. path.basename(sourcefile) .. "\""}) + end if target:is_arch("x86_64", "i386") then target:add("defines", "CONFIG_X86_X32_ABI") end -- cgit v1.3.1 From f469658bd0f104a854abd6d301b6d6b24a3e8398 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 10:46:11 +0800 Subject: check rules --- tests/projects/linux/driver/hello/xmake.lua | 2 -- xmake/rules/platform/linux/driver/driver_modules.lua | 15 +++++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/projects/linux/driver/hello/xmake.lua b/tests/projects/linux/driver/hello/xmake.lua index 079c31754..bac728434 100644 --- a/tests/projects/linux/driver/hello/xmake.lua +++ b/tests/projects/linux/driver/hello/xmake.lua @@ -1,5 +1,3 @@ -add_rules("mode.release", "mode.debug") - add_requires("linux-headers", {configs = {driver_modules = true}}) target("hello") diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 230a190b3..52414c582 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -103,6 +103,11 @@ function load(target) -- check compiler, we must use gcc assert(target:has_tool("cc", "gcc"), "we must use gcc compiler!") + -- check rules + for _, rulename in ipairs({"mode.release", "mode.debug", "mode.releasedbg", "mode.minsizerel", "mode.asan", "mode.tsan"}) do + assert(not target:rule(rulename), "target(%s) is linux driver module, it need not rule(%s)!", target:name(), rulename) + end + -- add includedirs local sdkdir = linux_headers.sdkdir local includedir = linux_headers.includedir @@ -132,7 +137,7 @@ function load(target) -- add compilation flags target:set("policy", "check.auto_ignore_flags", false) - target:add("defines", "__KERNEL__", "MODULE", "CC_USING_FENTRY") + target:add("defines", "__KERNEL__", "MODULE") target:add("defines", "KBUILD_MODNAME=\"" .. target:name() .. "\"") for _, sourcefile in ipairs(target:sourcefiles()) do target:fileconfig_set(sourcefile, {defines = "KBUILD_BASENAME=\"" .. path.basename(sourcefile) .. "\""}) @@ -147,13 +152,19 @@ function load(target) target:add("cflags", "-nostdinc") target:add("cflags", "-mno-sse", "-mno-mmx", "-mno-sse2", "-mno-3dnow", "-mno-avx", "-mno-80387", "-mno-fp-ret-in-387") target:add("cflags", "-mpreferred-stack-boundary=3", "-mskip-rax-setup", "-mtune=generic", "-mno-red-zone", "-mcmodel=kernel") - target:add("cflags", "-mindirect-branch=thunk-extern", "-mindirect-branch-register", "-mrecord-mcount", "-mfentry") + target:add("cflags", "-mindirect-branch=thunk-extern", "-mindirect-branch-register", "-mrecord-mcount") target:add("cflags", "-fmacro-prefix-map=./=", " -fno-strict-aliasing", "-fno-common", "-fshort-wchar", "-fno-PIE") target:add("cflags", "-fcf-protection=none", "-falign-jumps=1", "-falign-loops=1", "-fno-asynchronous-unwind-tables") target:add("cflags", "-fno-jump-tables", "-fno-delete-null-pointer-checks", "-fno-allow-store-data-races") target:add("cflags", "-fno-reorder-blocks", "-fno-ipa-cp-clone", "-fno-partial-inlining", "-fstack-protector-strong") target:add("cflags", "-fno-inline-functions-called-once", "-falign-functions=32") target:add("cflags", "-fno-strict-overflow", "-fno-stack-check", "-fconserve-stack") + + -- add optional flags (fentry) + target:add("cflags", "-mfentry") + target:add("defines", "CC_USING_FENTRY") + + -- add optional flags (asan) target:add("cflags", "-fsanitize=kernel-address", "-fasan-shadow-offset=0xdffffc0000000000", "-fsanitize-coverage=trace-pc", "-fsanitize-coverage=trace-cmp") target:add("cflags", "--param asan-globals=1", "--param asan-instrumentation-with-call-threshold=0", "--param asan-stack=1", "--param asan-instrument-allocas=1") end -- cgit v1.3.1 From f6a2a9d3cbbe4e1d7748ca91dc4fb7fcf2c4af54 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 10:56:16 +0800 Subject: improve driver config --- xmake/rules/platform/linux/driver/driver_modules.lua | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 52414c582..7fd4f9bcf 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -161,12 +161,18 @@ function load(target) target:add("cflags", "-fno-strict-overflow", "-fno-stack-check", "-fconserve-stack") -- add optional flags (fentry) - target:add("cflags", "-mfentry") - target:add("defines", "CC_USING_FENTRY") + local has_fentry = target:values("linux.driver.fentry") + if has_fentry then + target:add("cflags", "-mfentry") + target:add("defines", "CC_USING_FENTRY") + end -- add optional flags (asan) - target:add("cflags", "-fsanitize=kernel-address", "-fasan-shadow-offset=0xdffffc0000000000", "-fsanitize-coverage=trace-pc", "-fsanitize-coverage=trace-cmp") - target:add("cflags", "--param asan-globals=1", "--param asan-instrumentation-with-call-threshold=0", "--param asan-stack=1", "--param asan-instrument-allocas=1") + local has_asan = target:values("linux.driver.asan") + if has_asan then + target:add("cflags", "-fsanitize=kernel-address", "-fasan-shadow-offset=0xdffffc0000000000", "-fsanitize-coverage=trace-pc", "-fsanitize-coverage=trace-cmp") + target:add("cflags", "--param asan-globals=1", "--param asan-instrumentation-with-call-threshold=0", "--param asan-stack=1", "--param asan-instrument-allocas=1") + end end function link(target, opt) -- cgit v1.3.1 From 76d2f0f84976180935865f3f125ecc8c8b57bd7d Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 11:00:10 +0800 Subject: modify config --- xmake/rules/platform/linux/driver/driver_modules.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 7fd4f9bcf..ceb3c6336 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -170,7 +170,8 @@ function load(target) -- add optional flags (asan) local has_asan = target:values("linux.driver.asan") if has_asan then - target:add("cflags", "-fsanitize=kernel-address", "-fasan-shadow-offset=0xdffffc0000000000", "-fsanitize-coverage=trace-pc", "-fsanitize-coverage=trace-cmp") + target:add("cflags", "-fsanitize=kernel-address") + target:add("cflags", "-fasan-shadow-offset=0xdffffc0000000000", "-fsanitize-coverage=trace-pc", "-fsanitize-coverage=trace-cmp") target:add("cflags", "--param asan-globals=1", "--param asan-instrumentation-with-call-threshold=0", "--param asan-stack=1", "--param asan-instrument-allocas=1") end end -- cgit v1.3.1 From 6c4c605b19b38bc34fa3a09e2087e11fe2103484 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 11:10:20 +0800 Subject: add hello_makefile --- tests/projects/linux/driver/hello/Makefile | 15 -------------- .../projects/linux/driver/hello_makefile/Makefile | 15 ++++++++++++++ .../projects/linux/driver/hello_makefile/src/add.c | 3 +++ .../linux/driver/hello_makefile/src/hello.c | 23 ++++++++++++++++++++++ 4 files changed, 41 insertions(+), 15 deletions(-) delete mode 100644 tests/projects/linux/driver/hello/Makefile create mode 100644 tests/projects/linux/driver/hello_makefile/Makefile create mode 100644 tests/projects/linux/driver/hello_makefile/src/add.c create mode 100644 tests/projects/linux/driver/hello_makefile/src/hello.c diff --git a/tests/projects/linux/driver/hello/Makefile b/tests/projects/linux/driver/hello/Makefile deleted file mode 100644 index 1d5aa92b4..000000000 --- a/tests/projects/linux/driver/hello/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -ifneq ($(KERNELRELEASE),) - obj-m := hello.o - hello-objs := ./src/hello.o ./src/add.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 - rm -rf src/*.o src/*~ core src/.depend src/.*.cmd src/*.ko src/*.mod.c src/.tmp_versions - diff --git a/tests/projects/linux/driver/hello_makefile/Makefile b/tests/projects/linux/driver/hello_makefile/Makefile new file mode 100644 index 000000000..1d5aa92b4 --- /dev/null +++ b/tests/projects/linux/driver/hello_makefile/Makefile @@ -0,0 +1,15 @@ +ifneq ($(KERNELRELEASE),) + obj-m := hello.o + hello-objs := ./src/hello.o ./src/add.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 + rm -rf src/*.o src/*~ core src/.depend src/.*.cmd src/*.ko src/*.mod.c src/.tmp_versions + diff --git a/tests/projects/linux/driver/hello_makefile/src/add.c b/tests/projects/linux/driver/hello_makefile/src/add.c new file mode 100644 index 000000000..59aab4983 --- /dev/null +++ b/tests/projects/linux/driver/hello_makefile/src/add.c @@ -0,0 +1,3 @@ +int add(int a, int b) { + return a + b; +} diff --git a/tests/projects/linux/driver/hello_makefile/src/hello.c b/tests/projects/linux/driver/hello_makefile/src/hello.c new file mode 100644 index 000000000..414a03bb2 --- /dev/null +++ b/tests/projects/linux/driver/hello_makefile/src/hello.c @@ -0,0 +1,23 @@ +#include +#include + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Ruki"); +MODULE_DESCRIPTION("A simple Hello World Module"); +MODULE_ALIAS("a simplest module"); + +int add(int a, int b); + +int hello_init(void) +{ + printk(KERN_INFO "Hello World: %d\n", add(1, 2)); + return 0; +} + +void hello_exit(void) +{ + printk(KERN_INFO "Goodbye World\n"); +} + +module_init(hello_init); +module_exit(hello_exit); -- cgit v1.3.1 From 719155858d0cdd7a42ecaae354908d6744572279 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 13:18:57 +0800 Subject: Update CHANGELOG.md --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e08e7d5a..19a189c63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### New features + +* [#1902](https://github.com/xmake-io/xmake/issues/1902): Support to build linux kernel driver modules + ### Change * [#1872](https://github.com/xmake-io/xmake/issues/1872): Escape characters for set_configvar @@ -1153,6 +1157,10 @@ ## master (开发中) +### 新特性 + +* [#1902](https://github.com/xmake-io/xmake/issues/1902): 支持构建 linux 内核驱动模块 + ### 改进 * [#1872](https://github.com/xmake-io/xmake/issues/1872): 支持转义 set_configvar 中字符串值 -- cgit v1.3.1 From e16cabdf859963a296eadf53d40f47c9f5cb42ac Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 13:21:11 +0800 Subject: Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 89b4e2111..17eed1810 100644 --- a/README.md +++ b/README.md @@ -302,6 +302,7 @@ armclang ARM Compiler Version 6 of Keil MDK * Protobuf Program * Lex/yacc program * C++20 Modules +* Linux Kernel Driver Modules ## More Examples -- cgit v1.3.1 From 28c2452f5ba77e264dbd4b212e21956741b9ccfb Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 13:22:03 +0800 Subject: Update README_zh.md --- README_zh.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README_zh.md b/README_zh.md index 9f26f1f56..b62c7fa8e 100644 --- a/README_zh.md +++ b/README_zh.md @@ -300,7 +300,7 @@ armclang ARM Compiler Version 6 of Keil MDK * 控制台程序 * Cuda 程序 * Qt 应用程序 -* WDK 驱动程序 +* WDK Windows 驱动程序 * WinSDK 应用程序 * MFC 应用程序 * iOS/MacOS 应用程序(支持.metal) @@ -310,6 +310,7 @@ armclang ARM Compiler Version 6 of Keil MDK * Protobuf 程序 * Lex/yacc 程序 * C++20 模块 +* Linux 内核驱动模块 ## 更多例子 -- cgit v1.3.1 From f40be9121cbf87a3345801b27337ddb7ecdab3d8 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 18:54:53 +0800 Subject: Update make.lua --- xmake/modules/package/tools/make.lua | 337 +++++++++++++++++++++++++++++++---- 1 file changed, 306 insertions(+), 31 deletions(-) diff --git a/xmake/modules/package/tools/make.lua b/xmake/modules/package/tools/make.lua index cbc58c9e2..12b94d64f 100644 --- a/xmake/modules/package/tools/make.lua +++ b/xmake/modules/package/tools/make.lua @@ -15,18 +15,148 @@ -- Copyright (C) 2015-present, TBOOX Open Source Group. -- -- @author ruki --- @file make.lua +-- @file autoconf.lua -- -- imports import("core.base.option") import("core.project.config") +import("core.tool.linker") +import("core.tool.compiler") import("lib.detect.find_tool") +-- translate paths +function _translate_paths(package, paths) + if paths and is_host("windows") and (package:is_plat("mingw") or package:is_plat("msys") or package:is_plat("cygwin")) then + if type(paths) == "string" then + return (paths:gsub("\\", "/")) + elseif type(paths) == "table" then + local result = {} + for _, p in ipairs(paths) do + table.insert(result, (p:gsub("\\", "/"))) + end + return result + end + end + return paths +end + +-- translate windows bin path +function _translate_windows_bin_path(bin_path) + if bin_path then + local argv = os.argv(bin_path) + argv[1] = argv[1]:gsub("\\", "/") .. ".exe" + return os.args(argv) + end +end + +-- map compiler flags +function _map_compflags(package, langkind, name, values) + return compiler.map_flags(langkind, name, values, {target = package}) +end + +-- map linker flags +function _map_linkflags(package, targetkind, sourcekinds, name, values) + return linker.map_flags(targetkind, sourcekinds, name, values, {target = package}) +end + +-- get configs +function _get_configs(package, configs) + + -- add prefix + local configs = configs or {} + table.insert(configs, "--prefix=" .. _translate_paths(package, package:installdir())) + + -- add host for cross-complation + if not configs.host and not package:is_plat(os.subhost()) then + if package:is_plat("iphoneos") then + local triples = + { + arm64 = "aarch64-apple-darwin", + arm64e = "aarch64-apple-darwin", + armv7 = "armv7-apple-darwin", + armv7s = "armv7s-apple-darwin", + i386 = "i386-apple-darwin", + x86_64 = "x86_64-apple-darwin" + } + table.insert(configs, "--host=" .. (triples[package:arch()] or triples.arm64)) + elseif package:is_plat("android") then + -- @see https://developer.android.com/ndk/guides/other_build_systems#autoconf + local triples = + { + ["armv5te"] = "arm-linux-androideabi", -- deprecated + ["armv7-a"] = "arm-linux-androideabi", -- deprecated + ["armeabi"] = "arm-linux-androideabi", -- removed in ndk r17 + ["armeabi-v7a"] = "arm-linux-androideabi", + ["arm64-v8a"] = "aarch64-linux-android", + i386 = "i686-linux-android", -- deprecated + x86 = "i686-linux-android", + x86_64 = "x86_64-linux-android", + mips = "mips-linux-android", -- removed in ndk r17 + mips64 = "mips64-linux-android" -- removed in ndk r17 + } + table.insert(configs, "--host=" .. (triples[package:arch()] or triples["armeabi-v7a"])) + elseif package:is_plat("mingw") then + local triples = + { + i386 = "i686-w64-mingw32", + x86_64 = "x86_64-w64-mingw32" + } + table.insert(configs, "--host=" .. (triples[package:arch()] or triples.i386)) + elseif package:is_plat("cross") then + local host = package:arch() + if package:is_arch("arm64") then + host = "aarch64" + elseif package:is_arch("arm.*") then + host = "arm" + end + host = host .. "-" .. package:targetos() + table.insert(configs, "--host=" .. host) + end + end + return configs +end + +-- get cflags from package deps +function _get_cflags_from_packagedeps(package, opt) + local result = {} + for _, depname in ipairs(opt.packagedeps) do + local dep = package:dep(depname) + if dep then + local fetchinfo = dep:fetch({external = false}) + if fetchinfo then + table.join2(result, _map_compflags(package, "cxx", "define", fetchinfo.defines)) + table.join2(result, _translate_paths(package, _map_compflags(package, "cxx", "includedir", fetchinfo.includedirs))) + table.join2(result, _translate_paths(package, _map_compflags(package, "cxx", "sysincludedir", fetchinfo.sysincludedirs))) + end + end + end + return result +end + +-- get ldflags from package deps +function _get_ldflags_from_packagedeps(package, opt) + local result = {} + for _, depname in ipairs(opt.packagedeps) do + local dep = package:dep(depname) + if dep then + local fetchinfo = dep:fetch({external = false}) + if fetchinfo then + table.join2(result, _translate_paths(package, _map_linkflags(package, "binary", {"cxx"}, "linkdir", fetchinfo.linkdirs))) + table.join2(result, _map_linkflags(package, "binary", {"cxx"}, "link", fetchinfo.links)) + table.join2(result, _translate_paths(package, _map_linkflags(package, "binary", {"cxx"}, "syslink", fetchinfo.syslinks))) + end + end + end + return result +end + -- get the build environments -function buildenvs(package) +function buildenvs(package, opt) + opt = opt or {} local envs = {} - if package:is_plat(os.host()) then + local cppflags = {} + if package:is_plat(os.subhost()) then local cflags = table.join(table.wrap(package:config("cxflags")), package:config("cflags")) local cxxflags = table.join(table.wrap(package:config("cxflags")), package:config("cxxflags")) local asflags = table.copy(table.wrap(package:config("asflags"))) @@ -37,15 +167,63 @@ function buildenvs(package) table.insert(asflags, "-m32") table.insert(ldflags, "-m32") end + table.join2(cflags, opt.cflags) + table.join2(cflags, opt.cxflags) + table.join2(cxxflags, opt.cxxflags) + table.join2(cxxflags, opt.cxflags) + table.join2(cppflags, opt.cppflags) -- @see https://github.com/xmake-io/xmake/issues/1688 + table.join2(asflags, opt.asflags) + table.join2(ldflags, opt.ldflags) + table.join2(cflags, _get_cflags_from_packagedeps(package, opt)) + table.join2(cxxflags, _get_cflags_from_packagedeps(package, opt)) + table.join2(cppflags, _get_cflags_from_packagedeps(package, opt)) + table.join2(ldflags, _get_ldflags_from_packagedeps(package, opt)) envs.CFLAGS = table.concat(cflags, ' ') envs.CXXFLAGS = table.concat(cxxflags, ' ') + envs.CPPFLAGS = table.concat(cppflags, ' ') envs.ASFLAGS = table.concat(asflags, ' ') envs.LDFLAGS = table.concat(ldflags, ' ') else - local cflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cflags")) - local cxxflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cxxflags")) + local cflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cflags")) + local cxxflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cxxflags")) + local asflags = table.copy(table.wrap(package:build_getenv("asflags"))) + local ldflags = table.copy(table.wrap(package:build_getenv("ldflags"))) + local shflags = table.copy(table.wrap(package:build_getenv("shflags"))) + local arflags = table.copy(table.wrap(package:build_getenv("arflags"))) + local defines = package:build_getenv("defines") + local includedirs = package:build_getenv("includedirs") + local sysincludedirs = package:build_getenv("sysincludedirs") + local links = package:build_getenv("links") + local syslinks = package:build_getenv("syslinks") + local linkdirs = package:build_getenv("linkdirs") + table.join2(cflags, opt.cflags) + table.join2(cflags, opt.cxflags) + table.join2(cxxflags, opt.cxxflags) + table.join2(cxxflags, opt.cxflags) + table.join2(cppflags, opt.cppflags) -- @see https://github.com/xmake-io/xmake/issues/1688 + table.join2(asflags, opt.asflags) + table.join2(ldflags, opt.ldflags) + table.join2(shflags, opt.shflags) + table.join2(cflags, _get_cflags_from_packagedeps(package, opt)) + table.join2(cxxflags, _get_cflags_from_packagedeps(package, opt)) + table.join2(cppflags, _get_cflags_from_packagedeps(package, opt)) + table.join2(ldflags, _get_ldflags_from_packagedeps(package, opt)) + table.join2(cflags, _map_compflags(package, "c", "define", defines)) + table.join2(cflags, _map_compflags(package, "c", "includedir", includedirs)) + table.join2(cflags, _map_compflags(package, "c", "sysincludedir", sysincludedirs)) + table.join2(asflags, _map_compflags(package, "as", "define", defines)) + table.join2(asflags, _map_compflags(package, "as", "includedir", includedirs)) + table.join2(asflags, _map_compflags(package, "as", "sysincludedir", sysincludedirs)) + table.join2(cxxflags, _map_compflags(package, "cxx", "define", defines)) + table.join2(cxxflags, _map_compflags(package, "cxx", "includedir", includedirs)) + table.join2(cxxflags, _map_compflags(package, "cxx", "sysincludedir", sysincludedirs)) + table.join2(ldflags, _map_linkflags(package, "binary", {"cxx"}, "link", links)) + table.join2(ldflags, _map_linkflags(package, "binary", {"cxx"}, "syslink", syslinks)) + table.join2(ldflags, _map_linkflags(package, "binary", {"cxx"}, "linkdir", linkdirs)) + table.join2(shflags, _map_linkflags(package, "shared", {"cxx"}, "link", links)) + table.join2(shflags, _map_linkflags(package, "shared", {"cxx"}, "syslink", syslinks)) + table.join2(shflags, _map_linkflags(package, "shared", {"cxx"}, "linkdir", linkdirs)) envs.CC = package:build_getenv("cc") - envs.CXX = package:build_getenv("cxx") envs.AS = package:build_getenv("as") envs.AR = package:build_getenv("ar") envs.LD = package:build_getenv("ld") @@ -54,10 +232,39 @@ function buildenvs(package) envs.RANLIB = package:build_getenv("ranlib") envs.CFLAGS = table.concat(cflags, ' ') envs.CXXFLAGS = table.concat(cxxflags, ' ') - envs.ASFLAGS = table.concat(table.wrap(package:build_getenv("asflags")), ' ') - envs.ARFLAGS = table.concat(table.wrap(package:build_getenv("arflags")), ' ') - envs.LDFLAGS = table.concat(table.wrap(package:build_getenv("ldflags")), ' ') - envs.SHFLAGS = table.concat(table.wrap(package:build_getenv("shflags")), ' ') + envs.CPPFLAGS = table.concat(cppflags, ' ') + envs.ASFLAGS = table.concat(asflags, ' ') + envs.ARFLAGS = table.concat(arflags, ' ') + envs.LDFLAGS = table.concat(ldflags, ' ') + envs.SHFLAGS = table.concat(shflags, ' ') + if package:is_plat("mingw") then + -- fix linker error, @see https://github.com/xmake-io/xmake/issues/574 + -- libtool: line 1855: lib: command not found + envs.ARFLAGS = nil + local ld = envs.LD + if ld then + if ld:endswith("x86_64-w64-mingw32-g++") then + envs.LD = path.join(path.directory(ld), is_host("windows") and "ld" or "x86_64-w64-mingw32-ld") + elseif ld:endswith("i686-w64-mingw32-g++") then + envs.LD = path.join(path.directory(ld), is_host("windows") and "ld" or "i686-w64-mingw32-ld") + end + end + if is_host("windows") then + envs.CC = _translate_windows_bin_path(envs.CC) + envs.AS = _translate_windows_bin_path(envs.AS) + envs.AR = _translate_windows_bin_path(envs.AR) + envs.LD = _translate_windows_bin_path(envs.LD) + envs.LDSHARED = _translate_windows_bin_path(envs.LDSHARED) + envs.CPP = _translate_windows_bin_path(envs.CPP) + envs.RANLIB = _translate_windows_bin_path(envs.RANLIB) + end + elseif package:is_plat("cross") then + -- only for cross-toolchain + envs.CXX = package:build_getenv("cxx") + if not envs.ARFLAGS or envs.ARFLAGS == "" then + envs.ARFLAGS = "-cr" + end + end end local ACLOCAL_PATH = {} local PKG_CONFIG_PATH = {} @@ -77,56 +284,111 @@ function buildenvs(package) end envs.ACLOCAL_PATH = path.joinenv(ACLOCAL_PATH) envs.PKG_CONFIG_PATH = path.joinenv(PKG_CONFIG_PATH) - -- some Makefile use ComSpec to detect Windows (e.g. Makefiles generated by Premake) and require this env - if is_subhost("windows") then - envs.ComSpec = os.getenv("ComSpec") - end + return envs +end +-- get the autogen environments +function autogen_envs(package, opt) + opt = opt or {} + local envs = {NOCONFIGURE = "yes"} + local ACLOCAL_PATH = {} + local PKG_CONFIG_PATH = {} + for _, dep in ipairs(package:orderdeps()) do + local pkgconfig = path.join(dep:installdir(), "lib", "pkgconfig") + if os.isdir(pkgconfig) then + table.insert(PKG_CONFIG_PATH, pkgconfig) + end + pkgconfig = path.join(dep:installdir(), "share", "pkgconfig") + if os.isdir(pkgconfig) then + table.insert(PKG_CONFIG_PATH, pkgconfig) + end + local aclocal = path.join(dep:installdir(), "share", "aclocal") + if os.isdir(aclocal) then + table.insert(ACLOCAL_PATH, aclocal) + end + end + envs.ACLOCAL_PATH = path.joinenv(ACLOCAL_PATH) + envs.PKG_CONFIG_PATH = path.joinenv(PKG_CONFIG_PATH) return envs end +-- configure package +function configure(package, configs, opt) + + -- init options + opt = opt or {} + + -- get envs + local envs = opt.envs or buildenvs(package, opt) + + -- generate configure file + if not os.isfile("configure") then + if os.isfile("autogen.sh") then + os.vrunv("sh", {"./autogen.sh"}, {envs = autogen_envs(package, opt)}) + elseif os.isfile("configure.ac") then + os.vrunv("sh", {"autoreconf", "--install", "--symlink"}, {envs = autogen_envs(package, opt)}) + end + end + + -- pass configurations + local argv = {"./configure"} + for name, value in pairs(_get_configs(package, configs)) do + value = tostring(value):trim() + if value ~= "" then + if type(name) == "number" then + table.insert(argv, value) + else + table.insert(argv, "--" .. name .. "=" .. value) + end + end + end + + -- do configure + os.vrunv("sh", argv, {envs = envs}) +end + -- do make function make(package, argv, opt) opt = opt or {} local program - local runenvs = opt.envs or buildenvs(package) if package:is_plat("mingw") and is_subhost("windows") then local mingw = assert(package:build_getenv("mingw") or package:build_getenv("sdk"), "mingw not found!") program = path.join(mingw, "bin", "mingw32-make.exe") else - local tool = find_tool("make", {envs = runenvs}) + local tool = find_tool("make") if tool then program = tool.program end end assert(program, "make not found!") - os.vrunv(program, argv, {envs = runenvs, curdir = opt.curdir}) + os.vrunv(program, argv) end -- build package function build(package, configs, opt) - -- init options - opt = opt or {} + -- do configure + configure(package, configs, opt) - -- pass configurations + -- do make and install + opt = opt or {} local njob = opt.jobs or option.get("jobs") or tostring(os.default_njob()) local argv = {"-j" .. njob} if option.get("verbose") then - table.insert(argv, "VERBOSE=1") + table.insert(argv, "V=1") end - for name, value in pairs(configs) do - value = tostring(value):trim() - if value ~= "" then - if type(name) == "number" then - table.insert(argv, value) - else - table.insert(argv, name .. "=" .. value) + if opt.makeconfigs then + for name, value in pairs(opt.makeconfigs) do + value = tostring(value):trim() + if value ~= "" then + if type(name) == "number" then + table.insert(argv, value) + else + table.insert(argv, name .. "=" .. value) + end end end end - - -- do build make(package, argv, opt) end @@ -140,7 +402,20 @@ function install(package, configs, opt) -- do install local argv = {"install"} if option.get("verbose") then - table.insert(argv, "VERBOSE=1") + table.insert(argv, "V=1") + end + if opt.makeconfigs then + for name, value in pairs(opt.makeconfigs) do + value = tostring(value):trim() + if value ~= "" then + if type(name) == "number" then + table.insert(argv, value) + else + table.insert(argv, name .. "=" .. value) + end + end + end end make(package, argv, opt) end + -- cgit v1.3.1 From 16c681c62506a2512ce8717ae377fa3e8d5d2f26 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 18:55:21 +0800 Subject: Update make.lua --- xmake/modules/package/tools/make.lua | 337 ++++------------------------------- 1 file changed, 31 insertions(+), 306 deletions(-) diff --git a/xmake/modules/package/tools/make.lua b/xmake/modules/package/tools/make.lua index 12b94d64f..cbc58c9e2 100644 --- a/xmake/modules/package/tools/make.lua +++ b/xmake/modules/package/tools/make.lua @@ -15,148 +15,18 @@ -- Copyright (C) 2015-present, TBOOX Open Source Group. -- -- @author ruki --- @file autoconf.lua +-- @file make.lua -- -- imports import("core.base.option") import("core.project.config") -import("core.tool.linker") -import("core.tool.compiler") import("lib.detect.find_tool") --- translate paths -function _translate_paths(package, paths) - if paths and is_host("windows") and (package:is_plat("mingw") or package:is_plat("msys") or package:is_plat("cygwin")) then - if type(paths) == "string" then - return (paths:gsub("\\", "/")) - elseif type(paths) == "table" then - local result = {} - for _, p in ipairs(paths) do - table.insert(result, (p:gsub("\\", "/"))) - end - return result - end - end - return paths -end - --- translate windows bin path -function _translate_windows_bin_path(bin_path) - if bin_path then - local argv = os.argv(bin_path) - argv[1] = argv[1]:gsub("\\", "/") .. ".exe" - return os.args(argv) - end -end - --- map compiler flags -function _map_compflags(package, langkind, name, values) - return compiler.map_flags(langkind, name, values, {target = package}) -end - --- map linker flags -function _map_linkflags(package, targetkind, sourcekinds, name, values) - return linker.map_flags(targetkind, sourcekinds, name, values, {target = package}) -end - --- get configs -function _get_configs(package, configs) - - -- add prefix - local configs = configs or {} - table.insert(configs, "--prefix=" .. _translate_paths(package, package:installdir())) - - -- add host for cross-complation - if not configs.host and not package:is_plat(os.subhost()) then - if package:is_plat("iphoneos") then - local triples = - { - arm64 = "aarch64-apple-darwin", - arm64e = "aarch64-apple-darwin", - armv7 = "armv7-apple-darwin", - armv7s = "armv7s-apple-darwin", - i386 = "i386-apple-darwin", - x86_64 = "x86_64-apple-darwin" - } - table.insert(configs, "--host=" .. (triples[package:arch()] or triples.arm64)) - elseif package:is_plat("android") then - -- @see https://developer.android.com/ndk/guides/other_build_systems#autoconf - local triples = - { - ["armv5te"] = "arm-linux-androideabi", -- deprecated - ["armv7-a"] = "arm-linux-androideabi", -- deprecated - ["armeabi"] = "arm-linux-androideabi", -- removed in ndk r17 - ["armeabi-v7a"] = "arm-linux-androideabi", - ["arm64-v8a"] = "aarch64-linux-android", - i386 = "i686-linux-android", -- deprecated - x86 = "i686-linux-android", - x86_64 = "x86_64-linux-android", - mips = "mips-linux-android", -- removed in ndk r17 - mips64 = "mips64-linux-android" -- removed in ndk r17 - } - table.insert(configs, "--host=" .. (triples[package:arch()] or triples["armeabi-v7a"])) - elseif package:is_plat("mingw") then - local triples = - { - i386 = "i686-w64-mingw32", - x86_64 = "x86_64-w64-mingw32" - } - table.insert(configs, "--host=" .. (triples[package:arch()] or triples.i386)) - elseif package:is_plat("cross") then - local host = package:arch() - if package:is_arch("arm64") then - host = "aarch64" - elseif package:is_arch("arm.*") then - host = "arm" - end - host = host .. "-" .. package:targetos() - table.insert(configs, "--host=" .. host) - end - end - return configs -end - --- get cflags from package deps -function _get_cflags_from_packagedeps(package, opt) - local result = {} - for _, depname in ipairs(opt.packagedeps) do - local dep = package:dep(depname) - if dep then - local fetchinfo = dep:fetch({external = false}) - if fetchinfo then - table.join2(result, _map_compflags(package, "cxx", "define", fetchinfo.defines)) - table.join2(result, _translate_paths(package, _map_compflags(package, "cxx", "includedir", fetchinfo.includedirs))) - table.join2(result, _translate_paths(package, _map_compflags(package, "cxx", "sysincludedir", fetchinfo.sysincludedirs))) - end - end - end - return result -end - --- get ldflags from package deps -function _get_ldflags_from_packagedeps(package, opt) - local result = {} - for _, depname in ipairs(opt.packagedeps) do - local dep = package:dep(depname) - if dep then - local fetchinfo = dep:fetch({external = false}) - if fetchinfo then - table.join2(result, _translate_paths(package, _map_linkflags(package, "binary", {"cxx"}, "linkdir", fetchinfo.linkdirs))) - table.join2(result, _map_linkflags(package, "binary", {"cxx"}, "link", fetchinfo.links)) - table.join2(result, _translate_paths(package, _map_linkflags(package, "binary", {"cxx"}, "syslink", fetchinfo.syslinks))) - end - end - end - return result -end - -- get the build environments -function buildenvs(package, opt) - opt = opt or {} +function buildenvs(package) local envs = {} - local cppflags = {} - if package:is_plat(os.subhost()) then + if package:is_plat(os.host()) then local cflags = table.join(table.wrap(package:config("cxflags")), package:config("cflags")) local cxxflags = table.join(table.wrap(package:config("cxflags")), package:config("cxxflags")) local asflags = table.copy(table.wrap(package:config("asflags"))) @@ -167,63 +37,15 @@ function buildenvs(package, opt) table.insert(asflags, "-m32") table.insert(ldflags, "-m32") end - table.join2(cflags, opt.cflags) - table.join2(cflags, opt.cxflags) - table.join2(cxxflags, opt.cxxflags) - table.join2(cxxflags, opt.cxflags) - table.join2(cppflags, opt.cppflags) -- @see https://github.com/xmake-io/xmake/issues/1688 - table.join2(asflags, opt.asflags) - table.join2(ldflags, opt.ldflags) - table.join2(cflags, _get_cflags_from_packagedeps(package, opt)) - table.join2(cxxflags, _get_cflags_from_packagedeps(package, opt)) - table.join2(cppflags, _get_cflags_from_packagedeps(package, opt)) - table.join2(ldflags, _get_ldflags_from_packagedeps(package, opt)) envs.CFLAGS = table.concat(cflags, ' ') envs.CXXFLAGS = table.concat(cxxflags, ' ') - envs.CPPFLAGS = table.concat(cppflags, ' ') envs.ASFLAGS = table.concat(asflags, ' ') envs.LDFLAGS = table.concat(ldflags, ' ') else - local cflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cflags")) - local cxxflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cxxflags")) - local asflags = table.copy(table.wrap(package:build_getenv("asflags"))) - local ldflags = table.copy(table.wrap(package:build_getenv("ldflags"))) - local shflags = table.copy(table.wrap(package:build_getenv("shflags"))) - local arflags = table.copy(table.wrap(package:build_getenv("arflags"))) - local defines = package:build_getenv("defines") - local includedirs = package:build_getenv("includedirs") - local sysincludedirs = package:build_getenv("sysincludedirs") - local links = package:build_getenv("links") - local syslinks = package:build_getenv("syslinks") - local linkdirs = package:build_getenv("linkdirs") - table.join2(cflags, opt.cflags) - table.join2(cflags, opt.cxflags) - table.join2(cxxflags, opt.cxxflags) - table.join2(cxxflags, opt.cxflags) - table.join2(cppflags, opt.cppflags) -- @see https://github.com/xmake-io/xmake/issues/1688 - table.join2(asflags, opt.asflags) - table.join2(ldflags, opt.ldflags) - table.join2(shflags, opt.shflags) - table.join2(cflags, _get_cflags_from_packagedeps(package, opt)) - table.join2(cxxflags, _get_cflags_from_packagedeps(package, opt)) - table.join2(cppflags, _get_cflags_from_packagedeps(package, opt)) - table.join2(ldflags, _get_ldflags_from_packagedeps(package, opt)) - table.join2(cflags, _map_compflags(package, "c", "define", defines)) - table.join2(cflags, _map_compflags(package, "c", "includedir", includedirs)) - table.join2(cflags, _map_compflags(package, "c", "sysincludedir", sysincludedirs)) - table.join2(asflags, _map_compflags(package, "as", "define", defines)) - table.join2(asflags, _map_compflags(package, "as", "includedir", includedirs)) - table.join2(asflags, _map_compflags(package, "as", "sysincludedir", sysincludedirs)) - table.join2(cxxflags, _map_compflags(package, "cxx", "define", defines)) - table.join2(cxxflags, _map_compflags(package, "cxx", "includedir", includedirs)) - table.join2(cxxflags, _map_compflags(package, "cxx", "sysincludedir", sysincludedirs)) - table.join2(ldflags, _map_linkflags(package, "binary", {"cxx"}, "link", links)) - table.join2(ldflags, _map_linkflags(package, "binary", {"cxx"}, "syslink", syslinks)) - table.join2(ldflags, _map_linkflags(package, "binary", {"cxx"}, "linkdir", linkdirs)) - table.join2(shflags, _map_linkflags(package, "shared", {"cxx"}, "link", links)) - table.join2(shflags, _map_linkflags(package, "shared", {"cxx"}, "syslink", syslinks)) - table.join2(shflags, _map_linkflags(package, "shared", {"cxx"}, "linkdir", linkdirs)) + local cflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cflags")) + local cxxflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cxxflags")) envs.CC = package:build_getenv("cc") + envs.CXX = package:build_getenv("cxx") envs.AS = package:build_getenv("as") envs.AR = package:build_getenv("ar") envs.LD = package:build_getenv("ld") @@ -232,39 +54,10 @@ function buildenvs(package, opt) envs.RANLIB = package:build_getenv("ranlib") envs.CFLAGS = table.concat(cflags, ' ') envs.CXXFLAGS = table.concat(cxxflags, ' ') - envs.CPPFLAGS = table.concat(cppflags, ' ') - envs.ASFLAGS = table.concat(asflags, ' ') - envs.ARFLAGS = table.concat(arflags, ' ') - envs.LDFLAGS = table.concat(ldflags, ' ') - envs.SHFLAGS = table.concat(shflags, ' ') - if package:is_plat("mingw") then - -- fix linker error, @see https://github.com/xmake-io/xmake/issues/574 - -- libtool: line 1855: lib: command not found - envs.ARFLAGS = nil - local ld = envs.LD - if ld then - if ld:endswith("x86_64-w64-mingw32-g++") then - envs.LD = path.join(path.directory(ld), is_host("windows") and "ld" or "x86_64-w64-mingw32-ld") - elseif ld:endswith("i686-w64-mingw32-g++") then - envs.LD = path.join(path.directory(ld), is_host("windows") and "ld" or "i686-w64-mingw32-ld") - end - end - if is_host("windows") then - envs.CC = _translate_windows_bin_path(envs.CC) - envs.AS = _translate_windows_bin_path(envs.AS) - envs.AR = _translate_windows_bin_path(envs.AR) - envs.LD = _translate_windows_bin_path(envs.LD) - envs.LDSHARED = _translate_windows_bin_path(envs.LDSHARED) - envs.CPP = _translate_windows_bin_path(envs.CPP) - envs.RANLIB = _translate_windows_bin_path(envs.RANLIB) - end - elseif package:is_plat("cross") then - -- only for cross-toolchain - envs.CXX = package:build_getenv("cxx") - if not envs.ARFLAGS or envs.ARFLAGS == "" then - envs.ARFLAGS = "-cr" - end - end + envs.ASFLAGS = table.concat(table.wrap(package:build_getenv("asflags")), ' ') + envs.ARFLAGS = table.concat(table.wrap(package:build_getenv("arflags")), ' ') + envs.LDFLAGS = table.concat(table.wrap(package:build_getenv("ldflags")), ' ') + envs.SHFLAGS = table.concat(table.wrap(package:build_getenv("shflags")), ' ') end local ACLOCAL_PATH = {} local PKG_CONFIG_PATH = {} @@ -284,111 +77,56 @@ function buildenvs(package, opt) end envs.ACLOCAL_PATH = path.joinenv(ACLOCAL_PATH) envs.PKG_CONFIG_PATH = path.joinenv(PKG_CONFIG_PATH) - return envs -end - --- get the autogen environments -function autogen_envs(package, opt) - opt = opt or {} - local envs = {NOCONFIGURE = "yes"} - local ACLOCAL_PATH = {} - local PKG_CONFIG_PATH = {} - for _, dep in ipairs(package:orderdeps()) do - local pkgconfig = path.join(dep:installdir(), "lib", "pkgconfig") - if os.isdir(pkgconfig) then - table.insert(PKG_CONFIG_PATH, pkgconfig) - end - pkgconfig = path.join(dep:installdir(), "share", "pkgconfig") - if os.isdir(pkgconfig) then - table.insert(PKG_CONFIG_PATH, pkgconfig) - end - local aclocal = path.join(dep:installdir(), "share", "aclocal") - if os.isdir(aclocal) then - table.insert(ACLOCAL_PATH, aclocal) - end - end - envs.ACLOCAL_PATH = path.joinenv(ACLOCAL_PATH) - envs.PKG_CONFIG_PATH = path.joinenv(PKG_CONFIG_PATH) - return envs -end - --- configure package -function configure(package, configs, opt) - - -- init options - opt = opt or {} - - -- get envs - local envs = opt.envs or buildenvs(package, opt) - - -- generate configure file - if not os.isfile("configure") then - if os.isfile("autogen.sh") then - os.vrunv("sh", {"./autogen.sh"}, {envs = autogen_envs(package, opt)}) - elseif os.isfile("configure.ac") then - os.vrunv("sh", {"autoreconf", "--install", "--symlink"}, {envs = autogen_envs(package, opt)}) - end - end - - -- pass configurations - local argv = {"./configure"} - for name, value in pairs(_get_configs(package, configs)) do - value = tostring(value):trim() - if value ~= "" then - if type(name) == "number" then - table.insert(argv, value) - else - table.insert(argv, "--" .. name .. "=" .. value) - end - end + -- some Makefile use ComSpec to detect Windows (e.g. Makefiles generated by Premake) and require this env + if is_subhost("windows") then + envs.ComSpec = os.getenv("ComSpec") end - -- do configure - os.vrunv("sh", argv, {envs = envs}) + return envs end -- do make function make(package, argv, opt) opt = opt or {} local program + local runenvs = opt.envs or buildenvs(package) if package:is_plat("mingw") and is_subhost("windows") then local mingw = assert(package:build_getenv("mingw") or package:build_getenv("sdk"), "mingw not found!") program = path.join(mingw, "bin", "mingw32-make.exe") else - local tool = find_tool("make") + local tool = find_tool("make", {envs = runenvs}) if tool then program = tool.program end end assert(program, "make not found!") - os.vrunv(program, argv) + os.vrunv(program, argv, {envs = runenvs, curdir = opt.curdir}) end -- build package function build(package, configs, opt) - -- do configure - configure(package, configs, opt) - - -- do make and install + -- init options opt = opt or {} + + -- pass configurations local njob = opt.jobs or option.get("jobs") or tostring(os.default_njob()) local argv = {"-j" .. njob} if option.get("verbose") then - table.insert(argv, "V=1") + table.insert(argv, "VERBOSE=1") end - if opt.makeconfigs then - for name, value in pairs(opt.makeconfigs) do - value = tostring(value):trim() - if value ~= "" then - if type(name) == "number" then - table.insert(argv, value) - else - table.insert(argv, name .. "=" .. value) - end + for name, value in pairs(configs) do + value = tostring(value):trim() + if value ~= "" then + if type(name) == "number" then + table.insert(argv, value) + else + table.insert(argv, name .. "=" .. value) end end end + + -- do build make(package, argv, opt) end @@ -402,20 +140,7 @@ function install(package, configs, opt) -- do install local argv = {"install"} if option.get("verbose") then - table.insert(argv, "V=1") - end - if opt.makeconfigs then - for name, value in pairs(opt.makeconfigs) do - value = tostring(value):trim() - if value ~= "" then - if type(name) == "number" then - table.insert(argv, value) - else - table.insert(argv, name .. "=" .. value) - end - end - end + table.insert(argv, "VERBOSE=1") end make(package, argv, opt) end - -- cgit v1.3.1 From b45552a5f4a026d298b8cd944200713189f9f952 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 18:55:58 +0800 Subject: Update autoconf.lua --- xmake/modules/package/tools/autoconf.lua | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/xmake/modules/package/tools/autoconf.lua b/xmake/modules/package/tools/autoconf.lua index 833aa2f02..12b94d64f 100644 --- a/xmake/modules/package/tools/autoconf.lua +++ b/xmake/modules/package/tools/autoconf.lua @@ -377,6 +377,18 @@ function build(package, configs, opt) if option.get("verbose") then table.insert(argv, "V=1") end + if opt.makeconfigs then + for name, value in pairs(opt.makeconfigs) do + value = tostring(value):trim() + if value ~= "" then + if type(name) == "number" then + table.insert(argv, value) + else + table.insert(argv, name .. "=" .. value) + end + end + end + end make(package, argv, opt) end @@ -392,6 +404,18 @@ function install(package, configs, opt) if option.get("verbose") then table.insert(argv, "V=1") end + if opt.makeconfigs then + for name, value in pairs(opt.makeconfigs) do + value = tostring(value):trim() + if value ~= "" then + if type(name) == "number" then + table.insert(argv, value) + else + table.insert(argv, name .. "=" .. value) + end + end + end + end make(package, argv, opt) end -- cgit v1.3.1 From 13585a08f101e70d640feb045d02137cdf3d6114 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 20:45:21 +0800 Subject: support arm for linux driver --- core/src/tbox/tbox | 2 +- .../rules/platform/linux/driver/driver_modules.lua | 61 ++++++++++++++-------- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/core/src/tbox/tbox b/core/src/tbox/tbox index f301f5eca..122a479e6 160000 --- a/core/src/tbox/tbox +++ b/core/src/tbox/tbox @@ -1 +1 @@ -Subproject commit f301f5eca1e909ffd6bcf688f14646d8226acfd9 +Subproject commit 122a479e626ee3fdd7d6c1117ec7c19212a1e087 diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index ceb3c6336..9e8c7c613 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -21,7 +21,6 @@ -- imports import("core.base.option") import("core.project.depend") -import("lib.detect.find_tool") import("utils.progress") import("private.tools.ccache") @@ -84,13 +83,6 @@ function _get_gcc_includedir(target) return includedir or nil end --- get ld arch, e.g. ld -m elf_x86_64 -function _get_ld_arch(target) - if target:is_arch("x86_64", "i386") then - return "elf_" .. target:arch() - end -end - function load(target) -- we need only need binary kind, because we will rewrite on_link target:set("kind", "binary") @@ -114,6 +106,10 @@ function load(target) local archsubdir if target:is_arch("x86_64", "i386") then archsubdir = path.join(sdkdir, "arch", "x86") + elseif target:is_arch("arm", "armv7") then + archsubdir = path.join(sdkdir, "arch", "arm") + elseif target:is_arch("arm64", "arm64-v8a") then + archsubdir = path.join(sdkdir, "arch", "arm64") else raise("rule(platform.linux.driver): unsupported arch(%s)!", target:arch()) end @@ -142,23 +138,28 @@ function load(target) for _, sourcefile in ipairs(target:sourcefiles()) do target:fileconfig_set(sourcefile, {defines = "KBUILD_BASENAME=\"" .. path.basename(sourcefile) .. "\""}) end - if target:is_arch("x86_64", "i386") then - target:add("defines", "CONFIG_X86_X32_ABI") - end target:set("optimize", "faster") -- we need use -O2 for gcc if not target:get("language") then target:set("languages", "gnu89") end target:add("cflags", "-nostdinc") - target:add("cflags", "-mno-sse", "-mno-mmx", "-mno-sse2", "-mno-3dnow", "-mno-avx", "-mno-80387", "-mno-fp-ret-in-387") - target:add("cflags", "-mpreferred-stack-boundary=3", "-mskip-rax-setup", "-mtune=generic", "-mno-red-zone", "-mcmodel=kernel") - target:add("cflags", "-mindirect-branch=thunk-extern", "-mindirect-branch-register", "-mrecord-mcount") - target:add("cflags", "-fmacro-prefix-map=./=", " -fno-strict-aliasing", "-fno-common", "-fshort-wchar", "-fno-PIE") - target:add("cflags", "-fcf-protection=none", "-falign-jumps=1", "-falign-loops=1", "-fno-asynchronous-unwind-tables") - target:add("cflags", "-fno-jump-tables", "-fno-delete-null-pointer-checks", "-fno-allow-store-data-races") + target:add("cflags", "-fno-strict-aliasing", "-fno-common", "-fshort-wchar", "-fno-PIE") + target:add("cflags", "-falign-jumps=1", "-falign-loops=1", "-fno-asynchronous-unwind-tables") + target:add("cflags", "-fno-jump-tables", "-fno-delete-null-pointer-checks") target:add("cflags", "-fno-reorder-blocks", "-fno-ipa-cp-clone", "-fno-partial-inlining", "-fstack-protector-strong") target:add("cflags", "-fno-inline-functions-called-once", "-falign-functions=32") target:add("cflags", "-fno-strict-overflow", "-fno-stack-check", "-fconserve-stack") + if target:is_arch("x86_64", "i386") then + target:add("defines", "CONFIG_X86_X32_ABI") + target:add("cflags", "-mno-sse", "-mno-mmx", "-mno-sse2", "-mno-3dnow", "-mno-avx", "-mno-80387", "-mno-fp-ret-in-387") + target:add("cflags", "-mpreferred-stack-boundary=3", "-mskip-rax-setup", "-mtune=generic", "-mno-red-zone", "-mcmodel=kernel") + target:add("cflags", "-mindirect-branch=thunk-extern", "-mindirect-branch-register", "-mrecord-mcount") + target:add("cflags", "-fmacro-prefix-map=./=", "-fcf-protection=none", "-fno-allow-store-data-races") + elseif target:is_arch("arm", "armv7") then + target:add("cflags", "-mbig-endian", "-mabi=aapcs-linux", "-mfpu=vfp", "-marm", "-march=armv6k", "-mtune=arm1136j-s", "-msoft-float", "-Uarm") + target:add("defines", "__LINUX_ARM_ARCH__=6") + elseif target:is_arch("arm64", "arm64-v8a") then + end -- add optional flags (fentry) local has_fentry = target:values("linux.driver.fentry") @@ -196,15 +197,23 @@ function link(target, opt) assert(ldscriptfile and os.isfile(ldscriptfile), "scripts/module.lds not found!") -- get ld - local ld = assert(find_tool("ld"), "ld not found!") + local ld = target:tool("ld") + assert(ld, "ld not found!") + ld = ld:gsub("gcc$", "ld") + ld = ld:gsub("g%+%+$", "ld") -- link target.o - local ldarch = assert(_get_ld_arch(target), "unknown ld arch!") + local argv = {} + if target:is_arch("x86_64", "i386") then + table.join2(argv, "-m", "elf_" .. target:arch()) + elseif target:is_arch("arm", "armv7") then + table.join2(argv, "-EB") + end local targetfile_o = target:objectfile(targetfile) - local argv = {"-m", ldarch, "-r", "-o", targetfile_o} + table.join2(argv, "-r", "-o", targetfile_o) table.join2(argv, objectfiles) os.mkdir(path.directory(targetfile_o)) - os.vrunv(ld.program, argv) + os.vrunv(ld, argv) -- generate target.mod local targetfile_mod = targetfile_o:gsub("%.o$", ".mod") @@ -236,10 +245,16 @@ function link(target, opt) assert(compinst:compile(targetfile_mod_c, targetfile_mod_o, {target = target})) -- link target.ko + argv = {} + if target:is_arch("x86_64", "i386") then + table.join2(argv, "-m", "elf_" .. target:arch()) + elseif target:is_arch("arm", "armv7") then + table.join2(argv, "-EB", "--be8") + end local targetfile_o = target:objectfile(targetfile) - argv = {"-m", ldarch, "-r", "--build-id=sha1", "-T", ldscriptfile, "-o", targetfile, targetfile_o, targetfile_mod_o} + table.join2(argv, "-r", "--build-id=sha1", "-T", ldscriptfile, "-o", targetfile, targetfile_o, targetfile_mod_o) os.mkdir(path.directory(targetfile)) - os.vrunv(ld.program, argv) + os.vrunv(ld, argv) end, {dependfile = dependfile, lastmtime = os.mtime(target:targetfile()), files = objectfiles}) end -- cgit v1.3.1 From 47ba653b6417a2fe8897e58e446406497dca4fac Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 21:02:59 +0800 Subject: support arm64 for linux driver --- tests/projects/linux/driver/hello_makefile/Makefile | 2 +- xmake/rules/platform/linux/driver/driver_modules.lua | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/projects/linux/driver/hello_makefile/Makefile b/tests/projects/linux/driver/hello_makefile/Makefile index 1d5aa92b4..f5fd14b88 100644 --- a/tests/projects/linux/driver/hello_makefile/Makefile +++ b/tests/projects/linux/driver/hello_makefile/Makefile @@ -6,7 +6,7 @@ else PWD := $(shell pwd) default: - $(MAKE) -C $(KERN_DIR) V=1 M=$(PWD) modules + $(MAKE) -C $(KERN_DIR) V=1 ARCH=arm64 CROSS_COMPILE=/mnt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- M=$(PWD) modules endif clean: diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 9e8c7c613..31f56a36f 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -159,6 +159,7 @@ function load(target) target:add("cflags", "-mbig-endian", "-mabi=aapcs-linux", "-mfpu=vfp", "-marm", "-march=armv6k", "-mtune=arm1136j-s", "-msoft-float", "-Uarm") target:add("defines", "__LINUX_ARM_ARCH__=6") elseif target:is_arch("arm64", "arm64-v8a") then + target:add("cflags", "-mlittle-endian", "-mgeneral-regs-only", "-mabi=lp64") end -- add optional flags (fentry) @@ -208,6 +209,8 @@ function link(target, opt) table.join2(argv, "-m", "elf_" .. target:arch()) elseif target:is_arch("arm", "armv7") then table.join2(argv, "-EB") + elseif target:is_arch("arm64", "arm64-v8a") then + table.join2(argv, "-EL", "-maarch64elf") end local targetfile_o = target:objectfile(targetfile) table.join2(argv, "-r", "-o", targetfile_o) @@ -250,6 +253,8 @@ function link(target, opt) table.join2(argv, "-m", "elf_" .. target:arch()) elseif target:is_arch("arm", "armv7") then table.join2(argv, "-EB", "--be8") + elseif target:is_arch("arm64", "arm64-v8a") then + table.join2(argv, "-EL", "-maarch64elf") end local targetfile_o = target:objectfile(targetfile) table.join2(argv, "-r", "--build-id=sha1", "-T", ldscriptfile, "-o", targetfile, targetfile_o, targetfile_mod_o) -- cgit v1.3.1 From ed0828575a18a66c08bde26086a867b27d6bc303 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 21:12:04 +0800 Subject: improve driver flags --- tests/projects/linux/driver/hello_makefile/Makefile | 2 +- xmake/rules/platform/linux/driver/driver_modules.lua | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/projects/linux/driver/hello_makefile/Makefile b/tests/projects/linux/driver/hello_makefile/Makefile index f5fd14b88..1d5aa92b4 100644 --- a/tests/projects/linux/driver/hello_makefile/Makefile +++ b/tests/projects/linux/driver/hello_makefile/Makefile @@ -6,7 +6,7 @@ else PWD := $(shell pwd) default: - $(MAKE) -C $(KERN_DIR) V=1 ARCH=arm64 CROSS_COMPILE=/mnt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- M=$(PWD) modules + $(MAKE) -C $(KERN_DIR) V=1 M=$(PWD) modules endif clean: diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 31f56a36f..41c61068f 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -125,14 +125,13 @@ function load(target) target:add("includedirs", path.join(archsubdir, "include", "generated", "uapi")) target:add("includedirs", path.join(includedir, "uapi")) target:add("includedirs", path.join(includedir, "generated", "uapi")) - target:add("cflags", "-include " .. path.join(includedir, "linux", "kconfig.h")) - target:add("cflags", "-include " .. path.join(includedir, "linux", "compiler_types.h")) + target:add("cflags", "-include " .. path.join(includedir, "linux", "kconfig.h"), {force = true}) + target:add("cflags", "-include " .. path.join(includedir, "linux", "compiler_types.h"), {force = true}) -- we need disable includedirs from add_packages("linux-headers") target:pkg("linux-headers"):set("includedirs", nil) target:pkg("linux-headers"):set("sysincludedirs", nil) -- add compilation flags - target:set("policy", "check.auto_ignore_flags", false) target:add("defines", "__KERNEL__", "MODULE") target:add("defines", "KBUILD_MODNAME=\"" .. target:name() .. "\"") for _, sourcefile in ipairs(target:sourcefiles()) do @@ -151,12 +150,14 @@ function load(target) target:add("cflags", "-fno-strict-overflow", "-fno-stack-check", "-fconserve-stack") if target:is_arch("x86_64", "i386") then target:add("defines", "CONFIG_X86_X32_ABI") + target:add("cflags", "-mcmodel=kernel", {force = true}) target:add("cflags", "-mno-sse", "-mno-mmx", "-mno-sse2", "-mno-3dnow", "-mno-avx", "-mno-80387", "-mno-fp-ret-in-387") - target:add("cflags", "-mpreferred-stack-boundary=3", "-mskip-rax-setup", "-mtune=generic", "-mno-red-zone", "-mcmodel=kernel") + target:add("cflags", "-mpreferred-stack-boundary=3", "-mskip-rax-setup", "-mtune=generic", "-mno-red-zone") target:add("cflags", "-mindirect-branch=thunk-extern", "-mindirect-branch-register", "-mrecord-mcount") target:add("cflags", "-fmacro-prefix-map=./=", "-fcf-protection=none", "-fno-allow-store-data-races") elseif target:is_arch("arm", "armv7") then - target:add("cflags", "-mbig-endian", "-mabi=aapcs-linux", "-mfpu=vfp", "-marm", "-march=armv6k", "-mtune=arm1136j-s", "-msoft-float", "-Uarm") + target:add("cflags", "-march=armv6k", {force = true}) + target:add("cflags", "-mbig-endian", "-mabi=aapcs-linux", "-mfpu=vfp", "-marm", "-mtune=arm1136j-s", "-msoft-float", "-Uarm") target:add("defines", "__LINUX_ARM_ARCH__=6") elseif target:is_arch("arm64", "arm64-v8a") then target:add("cflags", "-mlittle-endian", "-mgeneral-regs-only", "-mabi=lp64") -- cgit v1.3.1 From 7159b0cb2a5394a122ce4e300f31401444b7035a Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 22:15:20 +0800 Subject: improve to get cflags from make --- .../rules/platform/linux/driver/driver_modules.lua | 122 ++++++++++++++------- 1 file changed, 80 insertions(+), 42 deletions(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 41c61068f..c41ea474f 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -21,6 +21,8 @@ -- imports import("core.base.option") import("core.project.depend") +import("core.cache.memcache") +import("lib.detect.find_tool") import("utils.progress") import("private.tools.ccache") @@ -61,7 +63,8 @@ end -- /usr/include -- End of search list. function _get_gcc_includedir(target) - local includedir = _g.includedir + local key = "gcc.includedir." .. target:plat() .. target:arch() + local includedir = memcache.get("linux.driver", key) if includedir == nil then local gcc, toolname = target:tool("cc") assert(toolname, "gcc") @@ -78,11 +81,83 @@ function _get_gcc_includedir(target) end end end - _g.includedir = includedir or false + memcache.set("linux.driver", key, includedir or false) end return includedir or nil end +-- get cflags from make +function _get_cflags_from_make(target, sdkdir) + local key = "cflags." .. target:plat() .. target:arch() + local cflags = memcache.get("linux.driver", key) + if cflags == nil then + local make = assert(find_tool("make"), "make not found!") + local tmpdir = os.tmpfile() .. ".dir" + local makefile = path.join(tmpdir, "Makefile") + local stubfile = path.join(tmpdir, "stub.c") + io.writefile(makefile, "obj-m := stub.o") + io.writefile(stubfile, [[ +#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); + ]]) + local argv = {"-C", sdkdir, "V=1", "M=" .. tmpdir, "modules"} + if target:is_plat("cross") then + local arch + if target:is_arch("arm", "armv7") then + arch = "arm" + elseif target:is_arch("arm64", "arm64-v8a") then + arch = "arm64" + end + assert(arch, "unknown arch(%s)!", target:arch()) + local cc = target:tool("cc") + local cross = cc:gsub("%-gcc$", "-") + table.insert(argv, "ARCH=" .. arch) + table.insert(argv, "CROSS_COMPILE=" .. cross) + end + local result, errors = try {function () return os.iorunv(make.program, argv, {curdir = tmpdir}) end} + if result then + for _, line in ipairs(result:split("\n", {plain = true})) do + if line:endswith("stub.c") then + for _, cflag in ipairs(line:split("%s+")) do + if cflag:startswith("-f") or cflag:startswith("-m") + or (cflag:startswith("-W") and not cflag:startswith("-Wp,-MMD,")) + or (cflag:startswith("-D") and not cflag:startswith("-DKBUILD_")) then + cflags = cflags or {} + table.insert(cflags, cflag) + end + end + break + end + end + else + if option.get("diagnosis") then + print("rule(platform.linux.driver): cannot get cflags from make!") + print(errors) + end + end + os.tryrm(tmpdir) + memcache.set("linux.driver", key, cflags or false) + end + return cflags or nil +end + function load(target) -- we need only need binary kind, because we will rewrite on_link target:set("kind", "binary") @@ -132,50 +207,13 @@ function load(target) target:pkg("linux-headers"):set("sysincludedirs", nil) -- add compilation flags - target:add("defines", "__KERNEL__", "MODULE") target:add("defines", "KBUILD_MODNAME=\"" .. target:name() .. "\"") for _, sourcefile in ipairs(target:sourcefiles()) do target:fileconfig_set(sourcefile, {defines = "KBUILD_BASENAME=\"" .. path.basename(sourcefile) .. "\""}) end - target:set("optimize", "faster") -- we need use -O2 for gcc - if not target:get("language") then - target:set("languages", "gnu89") - end - target:add("cflags", "-nostdinc") - target:add("cflags", "-fno-strict-aliasing", "-fno-common", "-fshort-wchar", "-fno-PIE") - target:add("cflags", "-falign-jumps=1", "-falign-loops=1", "-fno-asynchronous-unwind-tables") - target:add("cflags", "-fno-jump-tables", "-fno-delete-null-pointer-checks") - target:add("cflags", "-fno-reorder-blocks", "-fno-ipa-cp-clone", "-fno-partial-inlining", "-fstack-protector-strong") - target:add("cflags", "-fno-inline-functions-called-once", "-falign-functions=32") - target:add("cflags", "-fno-strict-overflow", "-fno-stack-check", "-fconserve-stack") - if target:is_arch("x86_64", "i386") then - target:add("defines", "CONFIG_X86_X32_ABI") - target:add("cflags", "-mcmodel=kernel", {force = true}) - target:add("cflags", "-mno-sse", "-mno-mmx", "-mno-sse2", "-mno-3dnow", "-mno-avx", "-mno-80387", "-mno-fp-ret-in-387") - target:add("cflags", "-mpreferred-stack-boundary=3", "-mskip-rax-setup", "-mtune=generic", "-mno-red-zone") - target:add("cflags", "-mindirect-branch=thunk-extern", "-mindirect-branch-register", "-mrecord-mcount") - target:add("cflags", "-fmacro-prefix-map=./=", "-fcf-protection=none", "-fno-allow-store-data-races") - elseif target:is_arch("arm", "armv7") then - target:add("cflags", "-march=armv6k", {force = true}) - target:add("cflags", "-mbig-endian", "-mabi=aapcs-linux", "-mfpu=vfp", "-marm", "-mtune=arm1136j-s", "-msoft-float", "-Uarm") - target:add("defines", "__LINUX_ARM_ARCH__=6") - elseif target:is_arch("arm64", "arm64-v8a") then - target:add("cflags", "-mlittle-endian", "-mgeneral-regs-only", "-mabi=lp64") - end - - -- add optional flags (fentry) - local has_fentry = target:values("linux.driver.fentry") - if has_fentry then - target:add("cflags", "-mfentry") - target:add("defines", "CC_USING_FENTRY") - end - - -- add optional flags (asan) - local has_asan = target:values("linux.driver.asan") - if has_asan then - target:add("cflags", "-fsanitize=kernel-address") - target:add("cflags", "-fasan-shadow-offset=0xdffffc0000000000", "-fsanitize-coverage=trace-pc", "-fsanitize-coverage=trace-cmp") - target:add("cflags", "--param asan-globals=1", "--param asan-instrumentation-with-call-threshold=0", "--param asan-stack=1", "--param asan-instrument-allocas=1") + local cflags = _get_cflags_from_make(target, sdkdir) + if cflags then + target:add("cflags", cflags, {force = true}) end end -- cgit v1.3.1 From 18455773a1e0fa2377e6a05cf99c735066a8390c Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 22:36:48 +0800 Subject: get ldflags from make --- .../rules/platform/linux/driver/driver_modules.lua | 54 ++++++++++++++-------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index c41ea474f..60fb14a22 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -88,8 +88,10 @@ end -- get cflags from make function _get_cflags_from_make(target, sdkdir) - local key = "cflags." .. target:plat() .. target:arch() - local cflags = memcache.get("linux.driver", key) + local key = target:plat() .. target:arch() + local cflags = memcache.get2("linux.driver", key, "cflags") + local ldflags_o = memcache.get2("linux.driver", key, "ldflags_o") + local ldflags_ko = memcache.get2("linux.driver", key, "ldflags_ko") if cflags == nil then local make = assert(find_tool("make"), "make not found!") local tmpdir = os.tmpfile() .. ".dir" @@ -143,6 +145,24 @@ module_exit(hello_exit); table.insert(cflags, cflag) end end + end + local ldflags = line:match("%-ld (.+) %-o ") or line:match("ld (.+) %-o ") + if ldflags then + local ko = ldflags:find("-T ", 1, true) + for _, ldflag in ipairs(ldflags:split("%s+")) do + if ko then + if ldflag:startswith("--build-id=") or ldflag:startswith("-T ") then + break + end + ldflags_ko = ldflags_ko or {} + table.insert(ldflags_ko, ldflag) + else + ldflags_o = ldflags_o or {} + table.insert(ldflags_o, ldflag) + end + end + end + if cflags and ldflags_o and ldflags_ko then break end end @@ -153,9 +173,9 @@ module_exit(hello_exit); end end os.tryrm(tmpdir) - memcache.set("linux.driver", key, cflags or false) + memcache.set2("linux.driver", key, "cflags", cflags or false) end - return cflags or nil + return cflags or nil, ldflags_o or nil, ldflags_ko or nil end function load(target) @@ -211,9 +231,11 @@ function load(target) for _, sourcefile in ipairs(target:sourcefiles()) do target:fileconfig_set(sourcefile, {defines = "KBUILD_BASENAME=\"" .. path.basename(sourcefile) .. "\""}) end - local cflags = _get_cflags_from_make(target, sdkdir) + local cflags, ldflags_o, ldflags_ko = _get_cflags_from_make(target, sdkdir) if cflags then target:add("cflags", cflags, {force = true}) + target:data_set("linux.driver.ldflags_o", ldflags_o) + target:data_set("linux.driver.ldflags_ko", ldflags_ko) end end @@ -244,15 +266,12 @@ function link(target, opt) -- link target.o local argv = {} - if target:is_arch("x86_64", "i386") then - table.join2(argv, "-m", "elf_" .. target:arch()) - elseif target:is_arch("arm", "armv7") then - table.join2(argv, "-EB") - elseif target:is_arch("arm64", "arm64-v8a") then - table.join2(argv, "-EL", "-maarch64elf") + local ldflags_o = target:data("linux.driver.ldflags_o") + if ldflags_o then + table.join2(argv, ldflags_o) end local targetfile_o = target:objectfile(targetfile) - table.join2(argv, "-r", "-o", targetfile_o) + table.join2(argv, "-o", targetfile_o) table.join2(argv, objectfiles) os.mkdir(path.directory(targetfile_o)) os.vrunv(ld, argv) @@ -288,15 +307,12 @@ function link(target, opt) -- link target.ko argv = {} - if target:is_arch("x86_64", "i386") then - table.join2(argv, "-m", "elf_" .. target:arch()) - elseif target:is_arch("arm", "armv7") then - table.join2(argv, "-EB", "--be8") - elseif target:is_arch("arm64", "arm64-v8a") then - table.join2(argv, "-EL", "-maarch64elf") + local ldflags_ko = target:data("linux.driver.ldflags_ko") + if ldflags_ko then + table.join2(argv, ldflags_ko) end local targetfile_o = target:objectfile(targetfile) - table.join2(argv, "-r", "--build-id=sha1", "-T", ldscriptfile, "-o", targetfile, targetfile_o, targetfile_mod_o) + table.join2(argv, "--build-id=sha1", "-T", ldscriptfile, "-o", targetfile, targetfile_o, targetfile_mod_o) os.mkdir(path.directory(targetfile)) os.vrunv(ld, argv) -- cgit v1.3.1 From 4592135696009bd89d2ed50a29cbcc82bcc6efae Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 11 Dec 2021 22:42:03 +0800 Subject: add comments --- xmake/rules/platform/linux/driver/driver_modules.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 60fb14a22..710a6464f 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -121,6 +121,7 @@ module_exit(hello_exit); ]]) local argv = {"-C", sdkdir, "V=1", "M=" .. tmpdir, "modules"} if target:is_plat("cross") then + -- e.g. $(MAKE) -C $(KERN_DIR) V=1 ARCH=arm64 CROSS_COMPILE=/mnt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- M=$(PWD) modules local arch if target:is_arch("arm", "armv7") then arch = "arm" @@ -154,9 +155,11 @@ module_exit(hello_exit); if ldflag:startswith("--build-id=") or ldflag:startswith("-T ") then break end + -- e.g. aarch64-linux-gnu-ld -r -EL -maarch64elf --build-id=sha1 -T scripts/module.lds -o hello.ko hello.o hello.mod.o ldflags_ko = ldflags_ko or {} table.insert(ldflags_ko, ldflag) else + -- e.g. aarch64-linux-gnu-ld -EL -maarch64elf -r -o hello.o xxx.o ldflags_o = ldflags_o or {} table.insert(ldflags_o, ldflag) end -- cgit v1.3.1 From e0a66639122aef90577f67a1e2b7de664fe31e89 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Sat, 11 Dec 2021 23:44:24 +0100 Subject: Project: fix common flag search was wrongly handling the case where a flag was present multiple times --- xmake/plugins/project/make/makefile.lua | 4 ++-- xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/xmake/plugins/project/make/makefile.lua b/xmake/plugins/project/make/makefile.lua index f9f0581c0..601f920c9 100644 --- a/xmake/plugins/project/make/makefile.lua +++ b/xmake/plugins/project/make/makefile.lua @@ -109,7 +109,7 @@ function _make_common_flags(target, sourcekind, sourcebatch) -- make common flags local commonflags = {} for _, flag in ipairs(first_flags) do - if flags_stats[flag] == files_count then + if flags_stats[flag] >= files_count then table.insert(commonflags, flag) end end @@ -119,7 +119,7 @@ function _make_common_flags(target, sourcekind, sourcebatch) for sourcefile, flags in pairs(sourceflags) do local otherflags = {} for _, flag in ipairs(flags) do - if flags_stats[flag] ~= files_count then + if flags_stats[flag] < files_count then table.insert(otherflags, flag) end end diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index d56c1015d..94dd7150e 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -550,7 +550,7 @@ function _make_common_items(vcxprojfile, vsinfo, target, vcxprojdir) -- make common flags targetinfo.commonflags = {} for _, flag in ipairs(first_flags) do - if flags_stats[flag] == files_count then + if flags_stats[flag] >= files_count then table.insert(targetinfo.commonflags, flag) end end @@ -560,7 +560,7 @@ function _make_common_items(vcxprojfile, vsinfo, target, vcxprojdir) for sourcefile, flags in pairs(targetinfo.sourceflags) do local otherflags = {} for _, flag in ipairs(flags) do - if flags_stats[flag] ~= files_count then + if flags_stats[flag] < files_count then table.insert(otherflags, flag) end end -- cgit v1.3.1 From d978a21418a48d0c25b32805abd4ed2fa31f69d4 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Sat, 11 Dec 2021 23:45:23 +0100 Subject: project/vstudio: Enable MultiProcessorCompilation by default --- xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index 94dd7150e..74f219320 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -334,7 +334,7 @@ function _make_source_options(vcxprojfile, flags, condition) -- handle multi processor compilation if flagstr:find("[%-/]Gm-") or not flagstr:find("[%-/]Gm") then vcxprojfile:print("false", condition) - if flagstr:find("[%-/]MP") then + if not flagstr:find("[%-/]MP1") then vcxprojfile:print("true", condition) end end @@ -357,7 +357,7 @@ function _make_source_options(vcxprojfile, flags, condition) -- make AdditionalOptions local additional_flags = {} - local excludes = {"Od", "Os", "O0", "O1", "O2", "Ot", "Ox", "W0", "W1", "W2", "W3", "WX", "Wall", "Zi", "ZI", "Z7", "MT", "MTd", "MD", "MDd", "TP", "Fd", "fp", "I", "D", "Gm-", "Gm"} + local excludes = {"Od", "Os", "O0", "O1", "O2", "Ot", "Ox", "W0", "W1", "W2", "W3", "WX", "Wall", "Zi", "ZI", "Z7", "MT", "MTd", "MD", "MDd", "TP", "Fd", "fp", "I", "D", "Gm-", "Gm", "MP"} for _, flag in ipairs(flags) do local excluded = false for _, exclude in ipairs(excludes) do -- cgit v1.3.1 From d1cd32f266309971b033b2941abcf8aa02242501 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Sat, 11 Dec 2021 23:46:19 +0100 Subject: project/vstudio: Fix external include dirs --- .../project/vstudio/impl/vs201x_vcxproj.lua | 81 ++++++++++------------ 1 file changed, 37 insertions(+), 44 deletions(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index 74f219320..5b82dd7a2 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -27,6 +27,18 @@ import("core.tool.toolchain") import("private.utils.batchcmds") import("vsfile") +function _make_dirs(dir, vcxprojdir) + dir = dir:trim() + if #dir == 0 then + return "" + end + dir = path.translate(dir) + if not path.is_absolute(dir) then + dir = path.relative(path.absolute(dir), vcxprojdir) + end + return dir +end + -- get toolset version function _get_toolset_ver(targetinfo, vsinfo) @@ -66,18 +78,16 @@ function _make_compcmd(compargv, sourcefile, objectfile, vcxprojdir) end v = v:gsub("__sourcefile__", sourcefile) v = v:gsub("__objectfile__", objectfile) + -- -Idir or /Idir - v = v:gsub("([%-/]I)(.*)", function (I, dir) - dir = dir:trim() - if #dir == 0 then - return "" - end - dir = path.translate(dir) - if not path.is_absolute(dir) then - dir = path.relative(path.absolute(dir), vcxprojdir) - end - return I .. dir + -- handle external includes as well + for _, pattern in ipairs({"[%-/](I)(.*)", "[%-/](external:I)(.*)"}) do + v = v:gsub(pattern, function (flag, dir) + dir = _make_dirs(dir, vcxprojdir) + return "/" .. flag .. dir end) + end + table.insert(argv, v) end return table.concat(argv, " ") @@ -90,18 +100,15 @@ function _make_compflags(sourcefile, targetinfo, vcxprojdir) local flags = {} for _, flag in ipairs(targetinfo.compflags[sourcefile]) do - -- -Idir or /Idir - flag = flag:gsub("[%-/]I(.*)", function (dir) - dir = dir:trim() - if #dir == 0 then - return "" - end - dir = path.translate(dir) - if not path.is_absolute(dir) then - dir = path.relative(path.absolute(dir), vcxprojdir) - end - return "/I" .. dir - end) + -- handle external includes as well + for _, pattern in ipairs({"[%-/](I)(.*)", "[%-/](external:I)(.*)"}) do + + -- -Idir or /Idir + flag = flag:gsub(pattern, function (flag, dir) + dir = _make_dirs(dir, vcxprojdir) + return "/" .. flag .. dir + end) + end -- save flag table.insert(flags, flag) @@ -124,29 +131,15 @@ function _make_linkflags(targetinfo, vcxprojdir) -- replace -libpath:dir or /libpath:dir flag = flag:gsub(string.ipattern("[%-/]libpath:(.*)"), function (dir) - dir = dir:trim() - if #dir == 0 then - return "" - end - dir = path.translate(dir) - if not path.is_absolute(dir) then - dir = path.relative(path.absolute(dir), vcxprojdir) - end - return "/libpath:" .. dir - end) + dir = _make_dirs(dir, vcxprojdir) + return "/libpath:" .. dir + end) -- replace -def:dir or /def:dir flag = flag:gsub(string.ipattern("[%-/]def:(.*)"), function (dir) - dir = dir:trim() - if #dir == 0 then - return "" - end - dir = path.translate(dir) - if not path.is_absolute(dir) then - dir = path.relative(path.absolute(dir), vcxprojdir) - end - return "/def:" .. dir - end) + dir = _make_dirs(dir, vcxprojdir) + return "/def:" .. dir + end) -- save flag table.insert(flags, flag) @@ -240,8 +233,8 @@ function _make_configurations(vcxprojfile, vsinfo, target, vcxprojdir) -- make OutputDirectory and IntermediateDirectory for _, targetinfo in ipairs(target.info) do vcxprojfile:enter("", targetinfo.mode, targetinfo.arch) - vcxprojfile:print("%s\\", path.relative(path.absolute(targetinfo.targetdir), vcxprojdir)) - vcxprojfile:print("%s\\", path.relative(path.absolute(targetinfo.objectdir), vcxprojdir)) + vcxprojfile:print("%s\\", _make_dirs(targetinfo.targetdir, vcxprojdir)) + vcxprojfile:print("%s\\", _make_dirs(targetinfo.objectdir, vcxprojdir)) vcxprojfile:print("%s", path.basename(targetinfo.targetfile)) vcxprojfile:print("%s", path.extension(targetinfo.targetfile)) -- cgit v1.3.1 From 6291b59a2433a4349dbd51e88290297349130ca6 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Sat, 11 Dec 2021 23:46:36 +0100 Subject: project/vstudio: add rundir handling --- xmake/plugins/project/vstudio/impl/vs201x.lua | 4 ++++ xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua index 3c7d62737..d835a4270 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x.lua @@ -32,6 +32,7 @@ import("vs201x_vcxproj") import("vs201x_vcxproj_filters") import("core.cache.memcache") import("core.cache.localcache") +import("private.action.run.make_runenvs") import("private.action.require.install", {alias = "install_requires"}) import("actions.config.configfiles", {alias = "generate_configfiles", rootdir = os.programdir()}) import("actions.config.configheader", {alias = "generate_configheader", rootdir = os.programdir()}) @@ -243,6 +244,9 @@ function _make_targetinfo(mode, arch, target) local linkflags = linker.linkflags(target:kind(), target:sourcekinds(), {target = target}) targetinfo.linkflags = linkflags + -- save execution dir (when executed from VS) + targetinfo.rundir = target:rundir() + -- use mfc? save the mfc runtime kind if target:rule("win.sdk.mfc.shared_app") or target:rule("win.sdk.mfc.shared") then targetinfo.usemfc = "Dynamic" diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index 5b82dd7a2..19a1b20bd 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -213,6 +213,13 @@ function _make_configurations(vcxprojfile, vsinfo, target, vcxprojdir) vcxprojfile:leave("") end + -- make Debugger + for _, targetinfo in ipairs(target.info) do + vcxprojfile:enter("", targetinfo.mode, targetinfo.arch) + vcxprojfile:print("%s", targetinfo.rundir) + vcxprojfile:leave("") + end + -- import Microsoft.Cpp.props vcxprojfile:print("") -- cgit v1.3.1 From 0a9fa4f1f43ebde6f12bce1afcb968a5f3e850a6 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Sat, 11 Dec 2021 23:52:06 +0100 Subject: Remove make_runenvs imports (but it would be nice to handle runenvs as well) --- xmake/plugins/project/vstudio/impl/vs201x.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua index d835a4270..bf76b13dc 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x.lua @@ -32,7 +32,6 @@ import("vs201x_vcxproj") import("vs201x_vcxproj_filters") import("core.cache.memcache") import("core.cache.localcache") -import("private.action.run.make_runenvs") import("private.action.require.install", {alias = "install_requires"}) import("actions.config.configfiles", {alias = "generate_configfiles", rootdir = os.programdir()}) import("actions.config.configheader", {alias = "generate_configheader", rootdir = os.programdir()}) -- cgit v1.3.1 From ae349f87af3ceb312b3506e80e8c6a4ce9ecb91f Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Sun, 12 Dec 2021 00:06:32 +0100 Subject: msvc: add support of external headers without experimental --- xmake/modules/core/tools/cl.lua | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/xmake/modules/core/tools/cl.lua b/xmake/modules/core/tools/cl.lua index a519d1618..b76061cd7 100644 --- a/xmake/modules/core/tools/cl.lua +++ b/xmake/modules/core/tools/cl.lua @@ -270,13 +270,17 @@ end function nf_sysincludedir(self, dir) local has_external_includedir = _g._HAS_EXTERNAL_INCLUDEDIR if has_external_includedir == nil then - if self:has_flags({"-experimental:external", "-external:W0", "-external:I" .. os.args(path.translate(dir))}, "cxflags", {flagskey = "cl_external_includedir"}) then - has_external_includedir = true + if self:has_flags({"-external:W0", "-external:I" .. os.args(path.translate(dir))}, "cxflags", {flagskey = "cl_external_includedir"}) then + has_external_includedir = 2 -- full support + elseif self:has_flags({"-experimental:external", "-external:W0", "-external:I" .. os.args(path.translate(dir))}, "cxflags", {flagskey = "cl_external_includedir_experimental"}) then + has_external_includedir = 1 -- experimental support end - has_external_includedir = has_external_includedir or false + has_external_includedir = has_external_includedir or 0 _g._HAS_EXTERNAL_INCLUDEDIR = has_external_includedir end - if has_external_includedir then + if has_external_includedir >= 2 then + return {"-external:W0", "-external:I" .. path.translate(dir)} + elseif has_external_includedir >= 1 then return {"-experimental:external", "-external:W0", "-external:I" .. path.translate(dir)} else return nf_includedir(self, dir) -- cgit v1.3.1 From 94fff01ece05949fbc0cced5fff83f959b3f5ada Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Sun, 12 Dec 2021 00:19:38 +0100 Subject: project/vstudio: Add support for /W4 warning level --- xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index 19a1b20bd..b48d423a0 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -288,6 +288,8 @@ function _make_source_options(vcxprojfile, flags, condition) vcxprojfile:print("Level2", condition) elseif flagstr:find("[%-/]W3") then vcxprojfile:print("Level3", condition) + elseif flagstr:find("[%-/]W4") then + vcxprojfile:print("Level4", condition) elseif flagstr:find("[%-/]Wall") then vcxprojfile:print("EnableAllWarnings", condition) else @@ -357,7 +359,7 @@ function _make_source_options(vcxprojfile, flags, condition) -- make AdditionalOptions local additional_flags = {} - local excludes = {"Od", "Os", "O0", "O1", "O2", "Ot", "Ox", "W0", "W1", "W2", "W3", "WX", "Wall", "Zi", "ZI", "Z7", "MT", "MTd", "MD", "MDd", "TP", "Fd", "fp", "I", "D", "Gm-", "Gm", "MP"} + local excludes = {"Od", "Os", "O0", "O1", "O2", "Ot", "Ox", "W0", "W1", "W2", "W3", "W4", "WX", "Wall", "Zi", "ZI", "Z7", "MT", "MTd", "MD", "MDd", "TP", "Fd", "fp", "I", "D", "Gm-", "Gm", "MP"} for _, flag in ipairs(flags) do local excluded = false for _, exclude in ipairs(excludes) do -- cgit v1.3.1 From 3b0392340c94152238b2db03327415e553c44045 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Sun, 12 Dec 2021 01:32:28 +0100 Subject: project/vstudio: Add support for ExternalWarningLevel and ExternalTemplatesDiagnostics --- .../project/vstudio/impl/vs201x_vcxproj.lua | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index b48d423a0..fd14acbfe 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -299,6 +299,26 @@ function _make_source_options(vcxprojfile, flags, condition) vcxprojfile:print("true", condition) end + -- make ExternalWarningLevel + if flagstr:find("[%-/]external:W1") then + vcxprojfile:print("Level1", condition) + elseif flagstr:find("[%-/]external:W2") then + vcxprojfile:print("Level2", condition) + elseif flagstr:find("[%-/]external:W3") then + vcxprojfile:print("Level3", condition) + elseif flagstr:find("[%-/]external:W4") then + vcxprojfile:print("Level4", condition) + else + vcxprojfile:print("TurnOffAllWarnings", condition) + end + + -- make ExternalTemplatesDiagnostics + if flagstr:find("[%-/]external:templates-") then + vcxprojfile:print("true", condition) + else + vcxprojfile:print("false", condition) + end + -- make PreprocessorDefinitions local defstr = "" for _, flag in ipairs(flags) do @@ -359,7 +379,7 @@ function _make_source_options(vcxprojfile, flags, condition) -- make AdditionalOptions local additional_flags = {} - local excludes = {"Od", "Os", "O0", "O1", "O2", "Ot", "Ox", "W0", "W1", "W2", "W3", "W4", "WX", "Wall", "Zi", "ZI", "Z7", "MT", "MTd", "MD", "MDd", "TP", "Fd", "fp", "I", "D", "Gm-", "Gm", "MP"} + local excludes = {"Od", "Os", "O0", "O1", "O2", "Ot", "Ox", "W0", "W1", "W2", "W3", "W4", "WX", "Wall", "Zi", "ZI", "Z7", "MT", "MTd", "MD", "MDd", "TP", "Fd", "fp", "I", "D", "Gm-", "Gm", "MP", "external:W0", "external:W1", "external:W2", "external:W3", "external:W4", "external:templates-", "external:templates" } for _, flag in ipairs(flags) do local excluded = false for _, exclude in ipairs(excludes) do -- cgit v1.3.1 From faf3404c42491b7e1e1fa0ced8386321507f4c5c Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Sun, 12 Dec 2021 14:27:31 +0100 Subject: project/vstudio: Fix Debugger rundir --- xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index fd14acbfe..b167468d7 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -213,13 +213,6 @@ function _make_configurations(vcxprojfile, vsinfo, target, vcxprojdir) vcxprojfile:leave("
") end - -- make Debugger - for _, targetinfo in ipairs(target.info) do - vcxprojfile:enter("", targetinfo.mode, targetinfo.arch) - vcxprojfile:print("%s", targetinfo.rundir) - vcxprojfile:leave("") - end - -- import Microsoft.Cpp.props vcxprojfile:print("") @@ -250,6 +243,13 @@ function _make_configurations(vcxprojfile, vsinfo, target, vcxprojdir) end vcxprojfile:leave("") end + + -- make Debugger + for _, targetinfo in ipairs(target.info) do + vcxprojfile:enter("", targetinfo.mode, targetinfo.arch) + vcxprojfile:print("%s", targetinfo.rundir) + vcxprojfile:leave("") + end end -- make source options -- cgit v1.3.1 From f3b110572f3720905fc3ee97362d6055f5f29d78 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Sun, 12 Dec 2021 14:32:15 +0100 Subject: Update vs201x_vcxproj.lua --- xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index b167468d7..98f49c098 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -247,7 +247,7 @@ function _make_configurations(vcxprojfile, vsinfo, target, vcxprojdir) -- make Debugger for _, targetinfo in ipairs(target.info) do vcxprojfile:enter("", targetinfo.mode, targetinfo.arch) - vcxprojfile:print("%s", targetinfo.rundir) + vcxprojfile:print("%s", _make_dirs(targetinfo.rundir, vcxprojdir)) vcxprojfile:leave("") end end @@ -550,6 +550,7 @@ function _make_common_items(vcxprojfile, vsinfo, target, vcxprojdir) -- no common flags for asm if sourcekind ~= "as" then + local foundDebug = false for _, flag in ipairs(flags) do flags_stats[flag] = (flags_stats[flag] or 0) + 1 end -- cgit v1.3.1 From 89a488735ab235ee856bb61f5821f429013d6c2e Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Sun, 12 Dec 2021 14:45:05 +0100 Subject: Update vs201x_vcxproj.lua --- xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index 98f49c098..154e0763b 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -550,7 +550,6 @@ function _make_common_items(vcxprojfile, vsinfo, target, vcxprojdir) -- no common flags for asm if sourcekind ~= "as" then - local foundDebug = false for _, flag in ipairs(flags) do flags_stats[flag] = (flags_stats[flag] or 0) + 1 end -- cgit v1.3.1 From 5c4adb14e1f45b40bb3d90a9459386f67f08c15f Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 12 Dec 2021 22:16:53 +0800 Subject: Update package.lua --- xmake/core/package/package.lua | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 5da349187..3b778d617 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -110,6 +110,9 @@ end -- get the platform of package function _instance:plat() + if self._PLAT then + return self._PLAT + end -- @note we uses os.host() instead of them for the binary package if self:is_binary() then return os.subhost() @@ -123,6 +126,9 @@ end -- get the architecture of package function _instance:arch() + if self._ARCH then + return self._ARCH + end -- @note we uses os.arch() instead of them for the binary package if self:is_binary() then return os.subarch() @@ -130,6 +136,16 @@ function _instance:arch() return self:targetarch() end +-- set the package platform +function _instance:plat_set(plat) + self._PLAT = plat +end + +-- set the package architecture +function _instance:arch_set(arch) + self._ARCH = arch +end + -- get the target os function _instance:targetos() local requireinfo = self:requireinfo() -- cgit v1.3.1 From 4a4a40e259abd6b3a3925f698cc0444f12b66135 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 13 Dec 2021 07:25:56 +0800 Subject: Update main.lua --- xmake/core/main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/core/main.lua b/xmake/core/main.lua index e4d6f8f2a..e5feb7d14 100644 --- a/xmake/core/main.lua +++ b/xmake/core/main.lua @@ -218,7 +218,7 @@ function main.entry() end -- load theme - local theme_inst = theme.load(global.get("theme")) or theme.load("default") + local theme_inst = theme.load(os.getenv("XMAKE_THEME") or global.get("theme")) or theme.load("default") if theme_inst then colors.theme_set(theme_inst) end -- cgit v1.3.1 From 361944c326193b43507819a1c323894b921f8dbc Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 13 Dec 2021 23:18:07 +0800 Subject: add deduplication policy --- xmake/core/base/interpreter.lua | 52 ++++++++++++++++++++++++------ xmake/core/base/os.lua | 4 +-- xmake/core/base/scopeinfo.lua | 40 ++++++++++++----------- xmake/core/project/option.lua | 9 ++++++ xmake/core/project/project.lua | 13 ++++++-- xmake/core/project/target.lua | 6 ++-- xmake/modules/private/xrepo/action/env.lua | 4 +-- 7 files changed, 91 insertions(+), 37 deletions(-) diff --git a/xmake/core/base/interpreter.lua b/xmake/core/base/interpreter.lua index 90e0a57e5..01de8047d 100644 --- a/xmake/core/base/interpreter.lua +++ b/xmake/core/base/interpreter.lua @@ -481,7 +481,7 @@ function interpreter:_filter(values, level) end -- handle scope data -function interpreter:_handle(scope, remove_repeat, enable_filter) +function interpreter:_handle(scope, deduplicate, enable_filter) -- check assert(scope) @@ -499,8 +499,12 @@ function interpreter:_handle(scope, remove_repeat, enable_filter) end -- remove repeat first for each slice with deleted item (__del_xxx) - if remove_repeat and not table.is_dictionary(values) then - values = table.unique(values, function (v) return type(v) == "string" and v:startswith("__del_") end) + if deduplicate and not table.is_dictionary(values) then + local policy = self:deduplication_policy(name) + if policy ~= false then + local unique_func = policy == "toleft" and table.reverse_unique or table.unique + values = unique_func(values, function (v) return type(v) == "string" and v:startswith("__del_") end) + end end -- unwrap it if be only one @@ -513,7 +517,7 @@ function interpreter:_handle(scope, remove_repeat, enable_filter) end -- make results -function interpreter:_make(scope_kind, remove_repeat, enable_filter) +function interpreter:_make(scope_kind, deduplicate, enable_filter) -- check assert(self and self._PRIVATE) @@ -528,12 +532,12 @@ function interpreter:_make(scope_kind, remove_repeat, enable_filter) -- get the root scope info of the given scope kind, e.g. root.target local results = {} - local scope_opt = {interpreter = self, remove_repeat = remove_repeat, enable_filter = enable_filter} + local scope_opt = {interpreter = self, deduplicate = deduplicate, enable_filter = enable_filter} if scope_kind and scope_kind:startswith("root.") then local root_scope = scopes._ROOT[scope_kind:sub(6)] if root_scope then - results = self:_handle(root_scope, remove_repeat, enable_filter) + results = self:_handle(root_scope, deduplicate, enable_filter) end return scopeinfo.new(scope_kind, results, scope_opt) @@ -542,7 +546,7 @@ function interpreter:_make(scope_kind, remove_repeat, enable_filter) local root_scope = scopes._ROOT["__rootkind"] if root_scope then - results = self:_handle(root_scope, remove_repeat, enable_filter) + results = self:_handle(root_scope, deduplicate, enable_filter) end return scopeinfo.new(scope_kind, results, scope_opt) @@ -578,7 +582,7 @@ function interpreter:_make(scope_kind, remove_repeat, enable_filter) end -- add this scope - results[scope_name] = scopeinfo.new(scope_kind, self:_handle(scope_values, remove_repeat, enable_filter), scope_opt) + results[scope_name] = scopeinfo.new(scope_kind, self:_handle(scope_values, deduplicate, enable_filter), scope_opt) end end end @@ -751,11 +755,11 @@ function interpreter:load(file, opt) end -- make results -function interpreter:make(scope_kind, remove_repeat, enable_filter) +function interpreter:make(scope_kind, deduplicate, enable_filter) -- get the results with the given scope self._PENDING = true - local ok, results = xpcall(interpreter._make, interpreter._traceback, self, scope_kind, remove_repeat, enable_filter) + local ok, results = xpcall(interpreter._make, interpreter._traceback, self, scope_kind, deduplicate, enable_filter) self._PENDING = false if not ok then return nil, results @@ -813,6 +817,34 @@ function interpreter:rootscope_set(scope_kind) self._PRIVATE._ROOTSCOPE = scope_kind end +-- get the deduplication policy +function interpreter:deduplication_policy(name) + local policies = self._PRIVATE._DEDUPLICATION_POLICIES + if name then + return policies and policies[name] + else + return policies + end +end + +-- set the deduplication policy +-- +-- we need to be able to precisely control the direction of deduplication of different types of values. +-- the default is to de-duplicate from left to right, but like links/syslinks need to be de-duplicated from right to left. +-- +-- e.g +-- +-- interp:deduplication_set("defines", "right") -- remove duplicates to the right (default) +-- interp:deduplication_set("links", "left") -- remove duplicates to the left +-- interp:deduplication_set("links", false) -- disable deduplication +-- +-- @see https://github.com/xmake-io/xmake/issues/1903 +-- +function interpreter:deduplication_policy_set(name, policy) + self._PRIVATE._DEDUPLICATION_POLICIES = self._PRIVATE._DEDUPLICATION_POLICIES or {} + self._PRIVATE._DEDUPLICATION_POLICIES[name] = policy +end + -- get apis function interpreter:apis(scope_kind) diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index a4fdb570e..5c3057e5a 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -251,7 +251,7 @@ end -- @see https://github.com/xmake-io/xmake-repo/pull/489 -- https://stackoverflow.com/questions/34491244/environment-variable-is-too-large-on-windows-10 -- -function os._remove_repeat_pathenv(value) +function os._deduplicate_pathenv(value) if value and #value > 4096 then local itemset = {} local results = {} @@ -731,7 +731,7 @@ function os.execv(program, argv, opt) end -- we try to fix too long value before running process if type(v) == "string" and #v > 4096 and os.host() == "windows" then - v = os._remove_repeat_pathenv(v) + v = os._deduplicate_pathenv(v) end envars[k] = v end diff --git a/xmake/core/base/scopeinfo.lua b/xmake/core/base/scopeinfo.lua index 9d4888f1c..6b7e566b5 100644 --- a/xmake/core/base/scopeinfo.lua +++ b/xmake/core/base/scopeinfo.lua @@ -35,8 +35,8 @@ function _instance.new(kind, info, opt) local instance = table.inherit(_instance) instance._KIND = kind or "root" instance._INFO = info - instance._INTERPRETER = opt.interpreter - instance._REMOVE_REPEAT = opt.remove_repeat + instance._INTERPRETER = opt.interpreter + instance._DEDUPLICATE = opt.deduplicate instance._ENABLE_FILTER = opt.enable_filter return instance end @@ -58,13 +58,17 @@ function _instance:_api_type(name) end -- handle the api values -function _instance:_api_handle(values) +function _instance:_api_handle(name, values) local interp = self:interpreter() if interp then -- remove repeat first for each slice with deleted item (__del_xxx) - if self._REMOVE_REPEAT and not table.is_dictionary(values) then - values = table.unique(values, function (v) return type(v) == "string" and v:startswith("__del_") end) + if self._DEDUPLICATE and not table.is_dictionary(values) then + local policy = interp:deduplication_policy(name) + if policy ~= false then + local unique_func = policy == "toleft" and table.reverse_unique or table.unique + values = unique_func(values, function (v) return type(v) == "string" and v:startswith("__del_") end) + end end -- filter values @@ -112,7 +116,7 @@ function _instance:_api_set_values(name, ...) values = table.join(table.unpack(values)) -- handle values - local handled_values = self:_api_handle(values) + local handled_values = self:_api_handle(name, values) -- save values if type(handled_values) == "table" and #handled_values == 0 then @@ -151,7 +155,7 @@ function _instance:_api_add_values(name, ...) values = table.join(table.unpack(values)) -- save values - scope[name] = self:_api_handle(table.join2(table.wrap(scope[name]), values)) + scope[name] = self:_api_handle(name, table.join2(table.wrap(scope[name]), values)) -- save extra config if extra_config then @@ -180,7 +184,7 @@ function _instance:_api_set_keyvalues(name, key, ...) -- save values to "name" scope[name] = scope[name] or {} - scope[name][key] = self:_api_handle(values) + scope[name][key] = self:_api_handle(name, values) -- save values to "name.key" local name_key = name .. "." .. key @@ -218,9 +222,9 @@ function _instance:_api_add_keyvalues(name, key, ...) -- save values to "name" scope[name] = scope[name] or {} if scope[name][key] == nil then - scope[name][key] = self:_api_handle(values) + scope[name][key] = self:_api_handle(name, values) else - scope[name][key] = self:_api_handle(table.join2(table.wrap(scope[name][key]), values)) + scope[name][key] = self:_api_handle(name, table.join2(table.wrap(scope[name][key]), values)) end -- save values to "name.key" @@ -247,11 +251,11 @@ function _instance:_api_set_dictionary(name, dict_or_key, value, extra_config) if type(dict_or_key) == "table" then local dict = {} for k, v in pairs(dict_or_key) do - dict[k] = self:_api_handle(v) + dict[k] = self:_api_handle(name, v) end scope[name] = dict elseif type(dict_or_key) == "string" and value ~= nil then - scope[name] = {[dict_or_key] = self:_api_handle(value)} + scope[name] = {[dict_or_key] = self:_api_handle(name, value)} -- save extra config if extra_config and table.is_dictionary(extra_config) then scope["__extra_" .. name] = scope["__extra_" .. name] or {} @@ -275,11 +279,11 @@ function _instance:_api_add_dictionary(name, dict_or_key, value, extra_config) if type(dict_or_key) == "table" then local dict = {} for k, v in pairs(dict_or_key) do - dict[k] = self:_api_handle(v) + dict[k] = self:_api_handle(name, v) end table.join2(scope[name], dict) elseif type(dict_or_key) == "string" and value ~= nil then - scope[name][dict_or_key] = self:_api_handle(value) + scope[name][dict_or_key] = self:_api_handle(name, value) -- save extra config if extra_config and table.is_dictionary(extra_config) then scope["__extra_" .. name] = scope["__extra_" .. name] or {} @@ -317,7 +321,7 @@ function _instance:_api_set_paths(name, ...) local paths = interp:_api_translate_paths(values, "set_" .. name, 5) -- save values - scope[name] = self:_api_handle(paths) + scope[name] = self:_api_handle(name, paths) -- save extra config if extra_config then @@ -357,7 +361,7 @@ function _instance:_api_add_paths(name, ...) local paths = interp:_api_translate_paths(values, "add_" .. name, 5) -- save values - scope[name] = self:_api_handle(table.join2(table.wrap(scope[name]), paths)) + scope[name] = self:_api_handle(name, table.join2(table.wrap(scope[name]), paths)) -- save extra config if extra_config then @@ -394,7 +398,7 @@ function _instance:_api_del_paths(name, ...) end -- save values - scope[name] = self:_api_handle(table.join2(table.wrap(scope[name]), paths_deleted)) + scope[name] = self:_api_handle(name, table.join2(table.wrap(scope[name]), paths_deleted)) -- save api source info, e.g. call api() in sourcefile:linenumber self:_api_save_sourceinfo_to_scope(scope, name, paths) @@ -590,7 +594,7 @@ end -- clone a new instance from the current function _instance:clone() - return _instance.new(self:kind(), self:info(), {interpreter = self:interpreter(), remove_repeat = self._REMOVE_REPEAT, enable_filter = self._ENABLE_FILTER}) + return _instance.new(self:kind(), self:info(), {interpreter = self:interpreter(), deduplicate = self._DEDUPLICATE, enable_filter = self._ENABLE_FILTER}) end -- new a scope instance diff --git a/xmake/core/project/option.lua b/xmake/core/project/option.lua index d74b74996..8f5502390 100644 --- a/xmake/core/project/option.lua +++ b/xmake/core/project/option.lua @@ -534,6 +534,15 @@ function option.interpreter() -- define apis for language interp:api_define(language.apis()) + -- we need to be able to precisely control the direction of deduplication of different types of values. + -- the default is to de-duplicate from left to right, but like links/syslinks need to be de-duplicated from right to left. + -- + -- @see https://github.com/xmake-io/xmake/issues/1903 + -- + interp:deduplication_policy_set("links", "toleft") + interp:deduplication_policy_set("syslinks", "toleft") + interp:deduplication_policy_set("frameworks", "toleft") + -- register filter handler interp:filter():register("option", function (variable) diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 57a8c5c58..3aee363a3 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -240,7 +240,7 @@ function project._load_deps(instance, instances, deps, orderdeps, depspath) end -- load scope from the project file -function project._load_scope(scope_kind, remove_repeat, enable_filter) +function project._load_scope(scope_kind, deduplicate, enable_filter) -- enter the project directory local oldir, errors = os.cd(os.projectdir()) @@ -252,7 +252,7 @@ function project._load_scope(scope_kind, remove_repeat, enable_filter) local interp = project.interpreter() -- load scope - local results, errors = interp:make(scope_kind, remove_repeat, enable_filter) + local results, errors = interp:make(scope_kind, deduplicate, enable_filter) if not results then return nil, errors end @@ -727,6 +727,15 @@ function project.interpreter() -- define apis for project interp:api_define(project.apis()) + -- we need to be able to precisely control the direction of deduplication of different types of values. + -- the default is to de-duplicate from left to right, but like links/syslinks need to be de-duplicated from right to left. + -- + -- @see https://github.com/xmake-io/xmake/issues/1903 + -- + interp:deduplication_policy_set("links", "toleft") + interp:deduplication_policy_set("syslinks", "toleft") + interp:deduplication_policy_set("frameworks", "toleft") + -- register api: deprecated deprecated_project.api_register(interp) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 07327362d..1a489b1ce 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -1385,20 +1385,20 @@ function _instance:objectfiles() -- some object files may be repeat and appear link errors if multi-batches exists, so we need remove all repeat object files -- e.g. add_files("src/*.c", {rules = {"rule1", "rule2"}}) - local remove_repeat = batchcount > 1 + local deduplicate = batchcount > 1 -- get object files from all dependent targets (object kind) if self:orderdeps() then for _, dep in ipairs(self:orderdeps()) do if dep:kind() == "object" then table.join2(objectfiles, dep:objectfiles()) - remove_repeat = true + deduplicate = true end end end -- remove repeat object files - if remove_repeat then + if deduplicate then objectfiles = table.unique(objectfiles) end diff --git a/xmake/modules/private/xrepo/action/env.lua b/xmake/modules/private/xrepo/action/env.lua index 07709b7bd..bf5b2ec44 100644 --- a/xmake/modules/private/xrepo/action/env.lua +++ b/xmake/modules/private/xrepo/action/env.lua @@ -176,7 +176,7 @@ function _enter_project(opt) end -- remove repeat environment values -function _remove_repeat_pathenv(value) +function _deduplicate_pathenv(value) if value then local itemset = {} local results = {} @@ -320,7 +320,7 @@ function _package_getenvs(opt) end local results = {} for k, v in pairs(envs) do - results[k] = _remove_repeat_pathenv(v) + results[k] = _deduplicate_pathenv(v) end return results end -- cgit v1.3.1 From ca3def39b93d131405e8a676879bb0cec62e0b20 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 13 Dec 2021 23:18:51 +0800 Subject: update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19a189c63..5c6aec3d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,10 +12,13 @@ * [#1888](https://github.com/xmake-io/xmake/issues/1888): Improve windows installer to avoid remove other files * [#1895](https://github.com/xmake-io/xmake/issues/1895): Improve `plugin.vsxmake.autoupdate` rule * [#1893](https://github.com/xmake-io/xmake/issues/1893): Improve to detect icc and ifort toolchains +* [#1905](https://github.com/xmake-io/xmake/pull/1905): Add support of external headers without experimental for msvc +* [#1904](https://github.com/xmake-io/xmake/pull/1904): Improve vs201x generator ### Bugs fixed * [#1885](https://github.com/xmake-io/xmake/issues/1885): Fix package:fetch_linkdeps +* [#1903](https://github.com/xmake-io/xmake/issues/1903): Fix package link order ## v2.6.1 @@ -1167,10 +1170,13 @@ * [#1888](https://github.com/xmake-io/xmake/issues/1888): 改进 windows 安装器,避免错误删除其他安装目录下的文件 * [#1895](https://github.com/xmake-io/xmake/issues/1895): 改进 `plugin.vsxmake.autoupdate` 规则 * [#1893](https://github.com/xmake-io/xmake/issues/1893): 改进探测 icc 和 ifort 工具链 +* [#1905](https://github.com/xmake-io/xmake/pull/1905): 改进 msvc 对 external 头文件搜索探测支持 +* [#1904](https://github.com/xmake-io/xmake/pull/1904): 改进 vs201x 工程生成器 ### Bugs 修复 * [#1885](https://github.com/xmake-io/xmake/issues/1885): 修复 package:fetch_linkdeps 链接顺序问题 +* [#1903](https://github.com/xmake-io/xmake/issues/1903): 修复包链接顺序 ## v2.6.1 -- cgit v1.3.1 From 2f53f461e013176fe45959690ec709737f487a64 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 12 Dec 2021 17:26:53 +0800 Subject: update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c6aec3d6..a661d02b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ * [#1893](https://github.com/xmake-io/xmake/issues/1893): Improve to detect icc and ifort toolchains * [#1905](https://github.com/xmake-io/xmake/pull/1905): Add support of external headers without experimental for msvc * [#1904](https://github.com/xmake-io/xmake/pull/1904): Improve vs201x generator +* Add `XMAKE_THEME` envirnoment variable to switch theme ### Bugs fixed @@ -1172,6 +1173,7 @@ * [#1893](https://github.com/xmake-io/xmake/issues/1893): 改进探测 icc 和 ifort 工具链 * [#1905](https://github.com/xmake-io/xmake/pull/1905): 改进 msvc 对 external 头文件搜索探测支持 * [#1904](https://github.com/xmake-io/xmake/pull/1904): 改进 vs201x 工程生成器 +* 添加 `XMAKE_THEME` 环境变量去切换主题配置 ### Bugs 修复 @@ -2313,3 +2315,4 @@ * 修复在windows x86_64下,安装失败的问题 * 修复相对路径的一些bug + -- cgit v1.3.1 From 08cf4155370bb59af849f0d4ad70aec1523f03fb Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 13 Dec 2021 21:06:35 +0800 Subject: add -f/--force to xmake create --- xmake/actions/create/main.lua | 4 ++-- xmake/actions/create/xmake.lua | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/xmake/actions/create/main.lua b/xmake/actions/create/main.lua index 611c0a57c..560b3b457 100644 --- a/xmake/actions/create/main.lua +++ b/xmake/actions/create/main.lua @@ -76,13 +76,13 @@ function _create_project(language, templateid, targetname) end -- xmake.lua exists? - if os.isfile(path.join(projectdir, "xmake.lua")) then + if os.isfile(path.join(projectdir, "xmake.lua")) and not option.get("force") then raise("project (${underline}%s/xmake.lua${reset}) exists!", projectdir) end -- empty project? os.tryrm(path.join(projectdir, ".xmake")) - if not os.emptydir(projectdir) then + if not os.emptydir(projectdir) and not option.get("force") then -- otherwise, check whether it is empty raise("project directory (${underline}%s${reset}) is not empty!", projectdir) end diff --git a/xmake/actions/create/xmake.lua b/xmake/actions/create/xmake.lua index 005bdf6be..812411e03 100644 --- a/xmake/actions/create/xmake.lua +++ b/xmake/actions/create/xmake.lua @@ -38,7 +38,8 @@ task("create") -- options , options = { - {'l', "language", "kv", "c++", "The project language" + {'f', "force", "k", nil, "Force to create project in a non-empty directory."} + , {'l', "language", "kv", "c++", "The project language" -- show the description of all languages , values = function (complete, opt) -- cgit v1.3.1 From 87f599c961f5cbd8a8af63cb4ce3935357e130ee Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 13 Dec 2021 21:06:58 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a661d02b6..7198426d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ * [#1905](https://github.com/xmake-io/xmake/pull/1905): Add support of external headers without experimental for msvc * [#1904](https://github.com/xmake-io/xmake/pull/1904): Improve vs201x generator * Add `XMAKE_THEME` envirnoment variable to switch theme +* [#1907](https://github.com/xmake-io/xmake/issues/1907): Add `-f/--force` to force to create project in a non-empty directory ### Bugs fixed @@ -1174,6 +1175,7 @@ * [#1905](https://github.com/xmake-io/xmake/pull/1905): 改进 msvc 对 external 头文件搜索探测支持 * [#1904](https://github.com/xmake-io/xmake/pull/1904): 改进 vs201x 工程生成器 * 添加 `XMAKE_THEME` 环境变量去切换主题配置 +* [#1907](https://github.com/xmake-io/xmake/issues/1907): 添加 `-f/--force` 参数使得 `xmake create` 可以在费控目录被强制创建 ### Bugs 修复 -- cgit v1.3.1 From fd0a6c6821b5eff6ce4c945ffba1bfbb416f6031 Mon Sep 17 00:00:00 2001 From: Cherichy Date: Tue, 14 Dec 2021 17:05:05 +0800 Subject: Fix cmake find bug on windows. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在windows上由于issue 1822 添加了对ImportLibrary的查找,在vcproj里面会有一个与项目同名的lib文件也被加入到link目录。 比如find_package cmake::OpenCV 会导致需要link一个名为OpenCV.lib的文件,但实际上并不存在这一文件,所以需要将其排除。 --- xmake/modules/package/manager/cmake/find_package.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua index e4099f73d..0dd5751a4 100644 --- a/xmake/modules/package/manager/cmake/find_package.lua +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -201,7 +201,7 @@ function _find_package(cmake, name, opt) -- get links and linkdirs local linkdir = path.directory(library) - if linkdir ~= "." then + if linkdir ~= "." and string.find(string.gsub(linkdir,"/","\\"),workdir) == nil then linkdirs = linkdirs or {} table.insert(linkdirs, linkdir) local link = target.linkname(path.filename(library)) -- cgit v1.3.1 From b5ec6f34b6f72e8fcbf27042b53eb36ff26f63ad Mon Sep 17 00:00:00 2001 From: Cherichy Date: Tue, 14 Dec 2021 17:43:32 +0800 Subject: Update find_package.lua --- xmake/modules/package/manager/cmake/find_package.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua index 0dd5751a4..ddf0bc3a1 100644 --- a/xmake/modules/package/manager/cmake/find_package.lua +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -201,7 +201,8 @@ function _find_package(cmake, name, opt) -- get links and linkdirs local linkdir = path.directory(library) - if linkdir ~= "." and string.find(string.gsub(linkdir,"/","\\"),workdir) == nil then + linkdir = path.translate(linkdir) + if linkdir ~= "." and not linkdir:find(workdir) then linkdirs = linkdirs or {} table.insert(linkdirs, linkdir) local link = target.linkname(path.filename(library)) -- cgit v1.3.1 From 4a73b8dc0701c896a794deb751e6da5dfaebb28a Mon Sep 17 00:00:00 2001 From: Cherichy Date: Tue, 14 Dec 2021 19:39:02 +0800 Subject: Update find_package.lua --- xmake/modules/package/manager/cmake/find_package.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua index ddf0bc3a1..22ebc711b 100644 --- a/xmake/modules/package/manager/cmake/find_package.lua +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -202,7 +202,7 @@ function _find_package(cmake, name, opt) -- get links and linkdirs local linkdir = path.directory(library) linkdir = path.translate(linkdir) - if linkdir ~= "." and not linkdir:find(workdir) then + if linkdir ~= "." and not linkdir:startswith(workdir) then linkdirs = linkdirs or {} table.insert(linkdirs, linkdir) local link = target.linkname(path.filename(library)) -- cgit v1.3.1 From 6200b2a43dd9ddc7a031bf23430b82e807a7be74 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 15 Dec 2021 22:32:26 +0800 Subject: update rust tests --- tests/projects/rust/console/xmake.lua | 2 +- xmake/templates/rust/console/project/xmake.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/projects/rust/console/xmake.lua b/tests/projects/rust/console/xmake.lua index 2a5d3e012..d561403ac 100644 --- a/tests/projects/rust/console/xmake.lua +++ b/tests/projects/rust/console/xmake.lua @@ -2,5 +2,5 @@ add_rules("mode.debug", "mode.release") target("test") set_kind("binary") - add_files("src/*.rs") + add_files("src/main.rs") diff --git a/xmake/templates/rust/console/project/xmake.lua b/xmake/templates/rust/console/project/xmake.lua index 5c3f06804..2d0e19145 100644 --- a/xmake/templates/rust/console/project/xmake.lua +++ b/xmake/templates/rust/console/project/xmake.lua @@ -2,6 +2,6 @@ add_rules("mode.debug", "mode.release") target("${TARGETNAME}") set_kind("binary") - add_files("src/*.rs") + add_files("src/main.rs") ${FAQ} -- cgit v1.3.1 From f5aa67b72f9959a25532d4d03f08b1749ded3e30 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 15 Dec 2021 22:40:15 +0800 Subject: build and run targets with group --- xmake/actions/build/build.lua | 9 +++++---- xmake/actions/build/build_files.lua | 9 +++++---- xmake/actions/build/main.lua | 29 ++++++++++++++++++++--------- xmake/actions/build/xmake.lua | 5 +++++ xmake/actions/run/main.lua | 32 ++++++++++++++++++++------------ xmake/actions/run/xmake.lua | 13 ++++++++++--- 6 files changed, 65 insertions(+), 32 deletions(-) diff --git a/xmake/actions/build/build.lua b/xmake/actions/build/build.lua index 38e95f4b1..598d4b2cf 100644 --- a/xmake/actions/build/build.lua +++ b/xmake/actions/build/build.lua @@ -200,7 +200,7 @@ function _add_batchjobs_for_target_and_deps(batchjobs, rootjob, jobrefs, target) end -- get batch jobs, @note we need export it for private.diagnosis.dump_buildjobs -function get_batchjobs(targetname) +function get_batchjobs(targetname, group_pattern) -- get root targets local targets_root = {} @@ -210,7 +210,8 @@ function get_batchjobs(targetname) local depset = hashset.new() local targets = {} for _, target in pairs(project.targets()) do - if target:is_default() or option.get("all") then + local group = target:get("group") + if (target:is_default() and not group_pattern) or option.get("all") or (group_pattern and group and group:match(group_pattern)) then for _, depname in ipairs(target:get("deps")) do depset:insert(depname) end @@ -234,10 +235,10 @@ function get_batchjobs(targetname) end -- the main entry -function main(targetname) +function main(targetname, group_pattern) -- build all jobs - local batchjobs = get_batchjobs(targetname) + local batchjobs = get_batchjobs(targetname, group_pattern) if batchjobs and batchjobs:size() > 0 then local curdir = os.curdir() runjobs("build", batchjobs, {comax = option.get("jobs") or 1, on_exit = function (errors) diff --git a/xmake/actions/build/build_files.lua b/xmake/actions/build/build_files.lua index dd89ea311..2f8af59ec 100644 --- a/xmake/actions/build/build_files.lua +++ b/xmake/actions/build/build_files.lua @@ -114,7 +114,7 @@ function _add_batchjobs_for_target_and_deps(batchjobs, rootjob, jobrefs, target, end -- get batch jobs -function _get_batchjobs(targetname, filepatterns) +function _get_batchjobs(targetname, group_pattern, filepatterns) -- get root targets local targets_root = {} @@ -124,7 +124,8 @@ function _get_batchjobs(targetname, filepatterns) local depset = hashset.new() local targets = {} for _, target in pairs(project.targets()) do - if target:is_default() or option.get("all") then + local group = target:get("group") + if (target:is_default() and not group_pattern) or option.get("all") or (group_pattern and group and group:match(group_pattern)) then for _, depname in ipairs(target:get("deps")) do depset:insert(depname) end @@ -192,13 +193,13 @@ function _get_file_patterns(sourcefiles) end -- the main entry -function main(targetname, sourcefiles) +function main(targetname, group_pattern, sourcefiles) -- convert all sourcefiles to lua pattern local filepatterns = _get_file_patterns(sourcefiles) -- build all jobs - local batchjobs = _get_batchjobs(targetname, filepatterns) + local batchjobs = _get_batchjobs(targetname, group_pattern, filepatterns) if batchjobs and batchjobs:size() > 0 then local curdir = os.curdir() runjobs("build_files", batchjobs, {comax = option.get("jobs") or 1, curdir = curdir, count_as_index = true}) diff --git a/xmake/actions/build/main.lua b/xmake/actions/build/main.lua index 70d15d75e..c355ae4ae 100644 --- a/xmake/actions/build/main.lua +++ b/xmake/actions/build/main.lua @@ -92,6 +92,16 @@ function _do_project_rules(scriptname, opt) end end +-- do build +function _do_build(targetname, group_pattern) + local sourcefiles = option.get("files") + if sourcefiles then + build_files(targetname, group_pattern, sourcefiles) + else + build(targetname, group_pattern) + end +end + -- main function main() @@ -106,10 +116,14 @@ function main() -- lock the whole project project.lock() - -- get the target name - local targetname = option.get("target") - -- config it first + local targetname + local group_pattern = option.get("group") + if group_pattern then + group_pattern = "^" .. path.pattern(group_pattern) .. "$" + else + targetname = option.get("target") + end task.run("config", {target = targetname}, {disable_dump = true}) -- enter project directory @@ -126,12 +140,7 @@ function main() _do_project_rules("build_before") -- do build - local sourcefiles = option.get("files") - if sourcefiles then - build_files(targetname, sourcefiles) - else - build(targetname) - end + _do_build(targetname, group_pattern) end, catch @@ -144,6 +153,8 @@ function main() -- raise if errors then raise(errors) + elseif group_pattern then + raise("build targets with group(%s) failed!", group_pattern) elseif targetname then raise("build target: %s failed!", targetname) else diff --git a/xmake/actions/build/xmake.lua b/xmake/actions/build/xmake.lua index 631536f24..63677d594 100644 --- a/xmake/actions/build/xmake.lua +++ b/xmake/actions/build/xmake.lua @@ -44,6 +44,11 @@ task("build") {'b', "build", "k", nil , "Build target. This is default building mode and optional." } , {'r', "rebuild", "k", nil , "Rebuild the target." } , {'a', "all", "k", nil , "Build all targets." } + , {'g', "group", "kv", nil , "Run all targets of the given group. It support path pattern matching.", + "e.g.", + " xmake -g test", + " xmake -g test_*", + " xmake --group=benchmark/*" } , {nil, "dry-run", "k", nil , "Dry run to build target." } , {} diff --git a/xmake/actions/run/main.lua b/xmake/actions/run/main.lua index 3b51c3c81..72983c446 100644 --- a/xmake/actions/run/main.lua +++ b/xmake/actions/run/main.lua @@ -144,17 +144,19 @@ function _run(target) end -- check targets -function _check_targets(targetname) +function _check_targets(targetname, group_pattern) -- get targets local targets = {} - if targetname and not targetname:startswith("__") then + if targetname then table.insert(targets, project.target(targetname)) else - -- install default or all targets for _, target in ipairs(project.ordertargets()) do - if (target:is_default() or option.get("all")) and target:is_binary() then - table.insert(targets, target) + if target:is_binary() then + local group = target:get("group") + if (target:is_default() and not group_pattern) or option.get("all") or (group_pattern and group and group:match(group_pattern)) then + table.insert(targets, target) + end end end end @@ -179,14 +181,18 @@ end -- main function main() - -- get the target name - local targetname = option.get("target") - -- config it first + local targetname + local group_pattern = option.get("group") + if group_pattern then + group_pattern = "^" .. path.pattern(group_pattern) .. "$" + else + targetname = option.get("target") + end task.run("config", {target = targetname, require = "n", verbose = false}) -- check targets first - _check_targets(targetname) + _check_targets(targetname, group_pattern) -- enter project directory local oldir = os.cd(project.directory()) @@ -195,10 +201,12 @@ function main() if targetname then _run(project.target(targetname)) else - -- run default or all binary targets for _, target in ipairs(project.ordertargets()) do - if (target:is_default() or option.get("all")) and target:is_binary() then - _run(target) + if target:is_binary() then + local group = target:get("group") + if (target:is_default() and not group_pattern) or option.get("all") or (group_pattern and group and group:match(group_pattern)) then + _run(target) + end end end end diff --git a/xmake/actions/run/xmake.lua b/xmake/actions/run/xmake.lua index 83d4d3f9f..7c5b1086e 100644 --- a/xmake/actions/run/xmake.lua +++ b/xmake/actions/run/xmake.lua @@ -43,13 +43,20 @@ task("run") { {'d', "debug", "k", nil , "Run and debug the given target." } , {'a', "all", "k", nil , "Run all targets." } + , {'g', "group", "kv", nil , "Run all targets of the given group. It support path pattern matching.", + "e.g.", + " xmake run -g test", + " xmake run -g test_*", + " xmake run --group=benchmark/*" } , {'w', "workdir", "kv", nil , "Work directory of running targets, default is folder of targetfile", "e.g.", - " --workdir=.", - " --workdir=`pwd`" } + " xmake run -w .", + " xmake run --workdir=`pwd`" } , {} , {nil, "target", "v", nil , "The target name. It will run all default targets if this parameter is not specified." - , values = function (complete, opt) return import("private.utils.complete_helper.runable_targets")(complete, opt) end } + , values = function (complete, opt) + return import("private.utils.complete_helper.runable_targets")(complete, opt) + end } , {nil, "arguments", "vs", nil , "The target arguments" } } -- cgit v1.3.1 From 5f262b2602f29f1927e2a37dc81cd1c4c8dea722 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 15 Dec 2021 22:41:18 +0800 Subject: fix tips --- xmake/actions/build/xmake.lua | 2 +- xmake/actions/clean/main.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/actions/build/xmake.lua b/xmake/actions/build/xmake.lua index 63677d594..a1ed27952 100644 --- a/xmake/actions/build/xmake.lua +++ b/xmake/actions/build/xmake.lua @@ -44,7 +44,7 @@ task("build") {'b', "build", "k", nil , "Build target. This is default building mode and optional." } , {'r', "rebuild", "k", nil , "Rebuild the target." } , {'a', "all", "k", nil , "Build all targets." } - , {'g', "group", "kv", nil , "Run all targets of the given group. It support path pattern matching.", + , {'g', "group", "kv", nil , "Build all targets of the given group. It support path pattern matching.", "e.g.", " xmake -g test", " xmake -g test_*", diff --git a/xmake/actions/clean/main.lua b/xmake/actions/clean/main.lua index e9e574545..c508d0566 100644 --- a/xmake/actions/clean/main.lua +++ b/xmake/actions/clean/main.lua @@ -162,7 +162,7 @@ function main() -- enter project directory local oldir = os.cd(project.directory()) - -- clean the current target + -- clean target _clean(targetname) -- unlock the whole project -- cgit v1.3.1 From a0d7ded27f92784884e804f330231ec7a3e33b52 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 15 Dec 2021 22:43:07 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7198426d7..1cb2bf1d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### New features * [#1902](https://github.com/xmake-io/xmake/issues/1902): Support to build linux kernel driver modules +* [#1913](https://github.com/xmake-io/xmake/issues/1913): Build and run targets with given group pattern ### Change @@ -1165,6 +1166,7 @@ ### 新特性 * [#1902](https://github.com/xmake-io/xmake/issues/1902): 支持构建 linux 内核驱动模块 +* [#1913](https://github.com/xmake-io/xmake/issues/1913): 通过 group 模式匹配,指定构建和运行一批目标程序 ### 改进 -- cgit v1.3.1 From c6ece064664fce0623c000227de67dc33b16d302 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 16 Dec 2021 09:47:39 +0800 Subject: Update extension.lua --- xmake/modules/utils/archive/extension.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xmake/modules/utils/archive/extension.lua b/xmake/modules/utils/archive/extension.lua index ae8b97153..ca4c8abd8 100644 --- a/xmake/modules/utils/archive/extension.lua +++ b/xmake/modules/utils/archive/extension.lua @@ -23,15 +23,15 @@ import("core.base.hashset") -- get the archive extension function main(archivefile) - local extension = "" local filename = path.filename(archivefile) local extensionset = hashset.from({".zip", ".7z", ".gz", ".xz", ".tgz", ".bz2", ".tar", ".tar.gz", ".tar.xz", ".tar.bz2", ".tar.lz"}) local i = filename:lastof(".", true) if i then local p = filename:sub(1, i - 1):lastof(".", true) - if p and extensionset:has(filename:sub(p)) then i = p end - extension = filename:sub(i) + if p and extensionset:has(filename:sub(p)) then + extension = filename:sub(p) + end end return extension end -- cgit v1.3.1 From 214b9fe1440a05e83c84d5b4f216d48ef99b35bf Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 16 Dec 2021 09:48:04 +0800 Subject: Update download.lua --- xmake/modules/private/action/require/impl/actions/download.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/xmake/modules/private/action/require/impl/actions/download.lua b/xmake/modules/private/action/require/impl/actions/download.lua index 63e4c0d80..f2c8eeba7 100644 --- a/xmake/modules/private/action/require/impl/actions/download.lua +++ b/xmake/modules/private/action/require/impl/actions/download.lua @@ -151,15 +151,20 @@ function _download(package, url, sourcedir, url_alias, url_excludes) -- extract package file os.rm(sourcedir .. ".tmp") + local extension = archive.extension(packagefile) if archive.extract(packagefile, sourcedir .. ".tmp", {excludes = url_excludes}) then -- move to source directory os.rm(sourcedir) os.mv(sourcedir .. ".tmp", sourcedir) - else + elseif extension and extension ~= "" then -- create an empty source directory if do not extract package file os.tryrm(sourcedir) os.mkdir(sourcedir) raise("cannot extract %s, maybe missing extractor or invalid package file!", packagefile) + else + -- if it is not archive file, we need only create empty source file and use package:originfile() + os.tryrm(sourcedir) + os.mkdir(sourcedir) end -- save original file path -- cgit v1.3.1 From 9af42bcb37bde188b60d64d36c4e86873c2ece0b Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 16 Dec 2021 12:54:50 +0800 Subject: Update extension.lua --- xmake/modules/utils/archive/extension.lua | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/xmake/modules/utils/archive/extension.lua b/xmake/modules/utils/archive/extension.lua index ca4c8abd8..fe33a395f 100644 --- a/xmake/modules/utils/archive/extension.lua +++ b/xmake/modules/utils/archive/extension.lua @@ -25,13 +25,12 @@ import("core.base.hashset") function main(archivefile) local extension = "" local filename = path.filename(archivefile) - local extensionset = hashset.from({".zip", ".7z", ".gz", ".xz", ".tgz", ".bz2", ".tar", ".tar.gz", ".tar.xz", ".tar.bz2", ".tar.lz"}) + local extensionset = hashset.from({".zip", ".7z", ".gz", ".xz", ".tgz", ".bz2", ".tar", ".tar.gz", ".tar.xz", ".tar.bz2"}) local i = filename:lastof(".", true) if i then local p = filename:sub(1, i - 1):lastof(".", true) - if p and extensionset:has(filename:sub(p)) then - extension = filename:sub(p) - end + if p and extensionset:has(filename:sub(p)) then i = p end + extension = filename:sub(i) end - return extension + return extensionset:has(extension) and extension or "" end -- cgit v1.3.1 From 8512b8200ac982c4075c4707c3b2971c73159c9f Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 17 Dec 2021 00:51:02 +0800 Subject: modify package configurations --- tests/projects/package/conan/.gitignore | 8 ++++ tests/projects/package/conan/src/main.cpp | 9 +++++ tests/projects/package/conan/xmake.lua | 9 +++++ xmake/core/package/package.lua | 9 +++-- .../package/manager/cargo/configurations.lua | 28 ++++++++++++++ .../package/manager/cargo/install_package.lua | 15 ++------ .../package/manager/clib/configurations.lua | 30 +++++++++++++++ .../package/manager/clib/install_package.lua | 21 ++++------- .../package/manager/cmake/configurations.lua | 33 ++++++++++++++++ .../modules/package/manager/cmake/find_package.lua | 9 +++-- .../package/manager/conan/configurations.lua | 33 ++++++++++++++++ .../package/manager/conan/install_package.lua | 44 +++++++++------------- 12 files changed, 189 insertions(+), 59 deletions(-) create mode 100644 tests/projects/package/conan/.gitignore create mode 100644 tests/projects/package/conan/src/main.cpp create mode 100644 tests/projects/package/conan/xmake.lua create mode 100644 xmake/modules/package/manager/cargo/configurations.lua create mode 100644 xmake/modules/package/manager/clib/configurations.lua create mode 100644 xmake/modules/package/manager/cmake/configurations.lua create mode 100644 xmake/modules/package/manager/conan/configurations.lua diff --git a/tests/projects/package/conan/.gitignore b/tests/projects/package/conan/.gitignore new file mode 100644 index 000000000..152105761 --- /dev/null +++ b/tests/projects/package/conan/.gitignore @@ -0,0 +1,8 @@ +# Xmake cache +.xmake/ +build/ + +# MacOS Cache +.DS_Store + + diff --git a/tests/projects/package/conan/src/main.cpp b/tests/projects/package/conan/src/main.cpp new file mode 100644 index 000000000..7c435d251 --- /dev/null +++ b/tests/projects/package/conan/src/main.cpp @@ -0,0 +1,9 @@ +#include + +using namespace std; + +int main(int argc, char** argv) +{ + cout << "hello world!" << endl; + return 0; +} diff --git a/tests/projects/package/conan/xmake.lua b/tests/projects/package/conan/xmake.lua new file mode 100644 index 000000000..69f7d2052 --- /dev/null +++ b/tests/projects/package/conan/xmake.lua @@ -0,0 +1,9 @@ +add_requires("conan::zlib/1.2.11", {alias = "zlib", debug = true}) +add_requires("conan::openssl/1.1.1g", {alias = "openssl", + configs = {options = "OpenSSL:shared=True"}}) + +target("test") + set_kind("binary") + add_files("src/*.cpp") + add_packages("openssl", "zlib") + diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 3b778d617..602b0e58d 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -1895,7 +1895,8 @@ function package.load_from_system(packagename) -- on install script local on_install = function (pkg) - local opt = table.copy(pkg:configs()) + local opt = {} + opt.pkgconfigs = pkg:configs() opt.mode = pkg:is_debug() and "debug" or "release" opt.plat = pkg:plat() opt.arch = pkg:arch() @@ -1930,9 +1931,9 @@ function package.load_from_system(packagename) if is_thirdparty then -- add configurations for the 3rd package - local install_package = sandbox_module.import("package.manager." .. packagename:split("::")[1]:lower() .. ".install_package", {try = true, anonymous = true}) - if install_package and install_package.configurations then - for name, conf in pairs(install_package.configurations()) do + local configurations = sandbox_module.import("package.manager." .. packagename:split("::")[1]:lower() .. ".configurations", {try = true, anonymous = true}) + if configurations then + for name, conf in pairs(configurations()) do instance:add("configs", name, conf) end end diff --git a/xmake/modules/package/manager/cargo/configurations.lua b/xmake/modules/package/manager/cargo/configurations.lua new file mode 100644 index 000000000..a3f85a0ea --- /dev/null +++ b/xmake/modules/package/manager/cargo/configurations.lua @@ -0,0 +1,28 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file configurations.lua +-- + +-- get configurations +function main() + return + { + features = {description = "set the features of dependency."}, + default_features = {description = "enables or disables any defaults provided by the dependency.", default = true}, + } +end diff --git a/xmake/modules/package/manager/cargo/install_package.lua b/xmake/modules/package/manager/cargo/install_package.lua index 0f06a8f6b..dd2fde7e9 100644 --- a/xmake/modules/package/manager/cargo/install_package.lua +++ b/xmake/modules/package/manager/cargo/install_package.lua @@ -23,15 +23,6 @@ import("core.base.option") import("core.project.config") import("lib.detect.find_tool") --- get configurations -function configurations() - return - { - features = {description = "set the features of dependency."}, - default_features = {description = "enables or disables any defaults provided by the dependency.", default = true}, - } -end - -- install package -- -- e.g. @@ -53,6 +44,8 @@ function main(name, opt) end -- get required version + opt = opt or {} + local pkgconfigs = opt.pkgconfigs or {} local require_version = opt.require_version if not require_version or require_version == "latest" then require_version = "*" @@ -69,10 +62,10 @@ function main(name, opt) tomlfile:print("edition = \"2018\"") tomlfile:print("") tomlfile:print("[dependencies]") - local features = opt.features + local features = pkgconfigs.features if features then features = table.wrap(features) - tomlfile:print("%s = {version = \"%s\", features = [\"%s\"], default-features = %s}", name, require_version, table.concat(features, "\", \""), opt.default_features) + tomlfile:print("%s = {version = \"%s\", features = [\"%s\"], default-features = %s}", name, require_version, table.concat(features, "\", \""), pkgconfigs.default_features) else tomlfile:print("%s = \"%s\"", name, require_version) end diff --git a/xmake/modules/package/manager/clib/configurations.lua b/xmake/modules/package/manager/clib/configurations.lua new file mode 100644 index 000000000..4f59ea70d --- /dev/null +++ b/xmake/modules/package/manager/clib/configurations.lua @@ -0,0 +1,30 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author Adel Vilkov (aka RaZeR-RBI) +-- @file configurations.lua +-- + +-- get configurations +function main() + return + { + save = {description = "save dependency in project's package.json", default = false, type = "boolean"}, + save_dev = {description = "save as development dependency in project's package.json", default = false, type = "boolean"}, + outputdir = {description = "package installation directory relative to project root", default = "clib"}, + } +end + diff --git a/xmake/modules/package/manager/clib/install_package.lua b/xmake/modules/package/manager/clib/install_package.lua index 1b61af5b4..8ebac7829 100644 --- a/xmake/modules/package/manager/clib/install_package.lua +++ b/xmake/modules/package/manager/clib/install_package.lua @@ -23,42 +23,35 @@ import("core.base.option") import("core.project.config") import("lib.detect.find_tool") --- get configurations -function configurations() - return - { - save = {description = "save dependency in project's package.json", default = false, type = "boolean"}, - save_dev = {description = "save as development dependency in project's package.json", default = false, type = "boolean"}, - outputdir = {description = "package installation directory relative to project root", default = "clib"}, - } -end - -- install package -- @param name the package name, e.g. clib::clibs/bytes@0.4.0 -- @param opt the options, e.g. { verbose = true, --- settings = {outputdir = "clib", save = false, save_dev = false}} +-- pkgconfigs = {outputdir = "clib", save = false, save_dev = false}} -- -- @return true or false -- function main(name, opt) + -- find clib local clib = find_tool("clib") if not clib then raise("clib not found!") end + opt = opt or {} + local pkgconfigs = opt.pkgconfigs or {} local argv = {"install", name} - local abs_out = path.join(os.projectdir(), opt.outputdir) + local abs_out = path.join(os.projectdir(), pkgconfigs.outputdir) dprint("installing %s to %s", name, abs_out) table.insert(argv, "-o " .. abs_out) if not option.get("verbose") then table.insert(argv, "-q") end - if opt.save then + if pkgconfigs.save then table.insert(argv, "--save") end - if opt.save_dev then + if pkgconfigs.save_dev then table.insert(argv, "--save-dev") end diff --git a/xmake/modules/package/manager/cmake/configurations.lua b/xmake/modules/package/manager/cmake/configurations.lua new file mode 100644 index 000000000..ce9b21e17 --- /dev/null +++ b/xmake/modules/package/manager/cmake/configurations.lua @@ -0,0 +1,33 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file configurations.lua +-- + +-- get configurations +function main() + return + { + build = {description = "use it to choose if you want to build from sources.", default = "missing", values = {"all", "never", "missing", "outdated"}}, + remote = {description = "Set the conan remote server."}, + options = {description = "Set the options values, e.g. OpenSSL:shared=True"}, + imports = {description = "Set the imports for conan."}, + settings = {description = "Set the build settings for conan."}, + build_requires = {description = "Set the build requires for conan.", default = "xmake_generator/0.1.0@bincrafters/testing"} + } +end + diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua index 22ebc711b..e0e767145 100644 --- a/xmake/modules/package/manager/cmake/find_package.lua +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -243,10 +243,11 @@ end -- -- @param name the package name -- @param opt the options, e.g. {verbose = true, required_version = "1.0", --- components = {"regex", "system"}, --- moduledirs = "xxx", --- presets = {Boost_USE_STATIC_LIB = true}, --- envs = {CMAKE_PREFIX_PATH = "xxx"}) +-- pkgconfigs = { +-- components = {"regex", "system"}, +-- moduledirs = "xxx", +-- presets = {Boost_USE_STATIC_LIB = true}, +-- envs = {CMAKE_PREFIX_PATH = "xxx"}}) -- function main(name, opt) opt = opt or {} diff --git a/xmake/modules/package/manager/conan/configurations.lua b/xmake/modules/package/manager/conan/configurations.lua new file mode 100644 index 000000000..ce9b21e17 --- /dev/null +++ b/xmake/modules/package/manager/conan/configurations.lua @@ -0,0 +1,33 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file configurations.lua +-- + +-- get configurations +function main() + return + { + build = {description = "use it to choose if you want to build from sources.", default = "missing", values = {"all", "never", "missing", "outdated"}}, + remote = {description = "Set the conan remote server."}, + options = {description = "Set the options values, e.g. OpenSSL:shared=True"}, + imports = {description = "Set the imports for conan."}, + settings = {description = "Set the build settings for conan."}, + build_requires = {description = "Set the build requires for conan.", default = "xmake_generator/0.1.0@bincrafters/testing"} + } +end + diff --git a/xmake/modules/package/manager/conan/install_package.lua b/xmake/modules/package/manager/conan/install_package.lua index 97af3b4b8..d7f730e14 100644 --- a/xmake/modules/package/manager/conan/install_package.lua +++ b/xmake/modules/package/manager/conan/install_package.lua @@ -49,15 +49,15 @@ function _conan_get_build_directory(name) end -- generate conanfile.txt -function _conan_generate_conanfile(name, opt) +function _conan_generate_conanfile(name, pkgconfigs) -- trace dprint("generate %s ..", path.join(_conan_get_build_directory(name), "conanfile.txt")) -- get conan options, imports and build_requires - local options = table.wrap(opt.options) - local imports = table.wrap(opt.imports) - local build_requires = table.wrap(opt.build_requires) + local options = table.wrap(pkgconfigs.options) + local imports = table.wrap(pkgconfigs.imports) + local build_requires = table.wrap(pkgconfigs.build_requires) -- @see https://docs.conan.io/en/latest/systems_cross_building/cross_building.html -- generate it @@ -109,30 +109,22 @@ function _conan_install_xmake_generator(conan) end end --- get configurations -function configurations() - return - { - build = {description = "use it to choose if you want to build from sources.", default = "missing", values = {"all", "never", "missing", "outdated"}}, - remote = {description = "Set the conan remote server."}, - options = {description = "Set the options values, e.g. OpenSSL:shared=True"}, - imports = {description = "Set the imports for conan."}, - settings = {description = "Set the build settings for conan."}, - build_requires = {description = "Set the build requires for conan.", default = "xmake_generator/0.1.0@bincrafters/testing"} - } -end - -- install package -- -- @param name the package name, e.g. conan::OpenSSL/1.0.2n@conan/stable -- @param opt the options, e.g. { verbose = true, mode = "release", plat = , arch = , --- remote = "", build = "all", options = {}, imports = {}, build_requires = {}, --- settings = {"compiler=Visual Studio", "compiler.version=10", "compiler.runtime=MD"}} +-- pkgconfigs = { +-- remote = "", build = "all", options = {}, imports = {}, build_requires = {}, +-- settings = {"compiler=Visual Studio", "compiler.version=10", "compiler.runtime=MD"}}} -- -- @return true or false -- function main(name, opt) + -- get pkgconfigs + opt = opt or {} + local pkgconfigs = opt.pkgconfigs or {} + -- find conan local conan = find_tool("conan") if not conan then @@ -155,15 +147,15 @@ function main(name, opt) _conan_install_xmake_generator(conan) -- generate conanfile.txt - _conan_generate_conanfile(name, opt) + _conan_generate_conanfile(name, pkgconfigs) -- install package local argv = {"install", "."} - if opt.build then - if opt.build == "all" then + if pkgconfigs.build then + if pkgconfigs.build == "all" then table.insert(argv, "--build") else - table.insert(argv, "--build=" .. opt.build) + table.insert(argv, "--build=" .. pkgconfigs.build) end end @@ -241,15 +233,15 @@ function main(name, opt) end -- set custom settings - for _, setting in ipairs(opt.settings) do + for _, setting in ipairs(pkgconfigs.settings) do table.insert(argv, "-s") table.insert(argv, setting) end -- set remote - if opt.remote then + if pkgconfigs.remote then table.insert(argv, "-r") - table.insert(argv, opt.remote) + table.insert(argv, pkgconfigs.remote) end -- TODO set environments -- cgit v1.3.1 From 1bb127c6ddb9ca7928f827f04160dde828e54925 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 17 Dec 2021 00:53:13 +0800 Subject: improve cmake find_pacakge --- tests/projects/package/cmake/.gitignore | 8 ++++++ tests/projects/package/cmake/src/main.cpp | 9 ++++++ tests/projects/package/cmake/xmake.lua | 11 ++++++++ xmake/core/package/package.lua | 4 +-- .../package/manager/cargo/install_package.lua | 6 ++-- .../package/manager/clib/install_package.lua | 10 +++---- .../package/manager/cmake/configurations.lua | 10 +++---- .../modules/package/manager/cmake/find_package.lua | 33 +++++++++++++++------- .../package/manager/conan/configurations.lua | 2 +- .../package/manager/conan/install_package.lua | 28 +++++++++--------- .../modules/package/manager/vcpkg/find_package.lua | 6 ++-- 11 files changed, 83 insertions(+), 44 deletions(-) create mode 100644 tests/projects/package/cmake/.gitignore create mode 100644 tests/projects/package/cmake/src/main.cpp create mode 100644 tests/projects/package/cmake/xmake.lua diff --git a/tests/projects/package/cmake/.gitignore b/tests/projects/package/cmake/.gitignore new file mode 100644 index 000000000..152105761 --- /dev/null +++ b/tests/projects/package/cmake/.gitignore @@ -0,0 +1,8 @@ +# Xmake cache +.xmake/ +build/ + +# MacOS Cache +.DS_Store + + diff --git a/tests/projects/package/cmake/src/main.cpp b/tests/projects/package/cmake/src/main.cpp new file mode 100644 index 000000000..7c435d251 --- /dev/null +++ b/tests/projects/package/cmake/src/main.cpp @@ -0,0 +1,9 @@ +#include + +using namespace std; + +int main(int argc, char** argv) +{ + cout << "hello world!" << endl; + return 0; +} diff --git a/tests/projects/package/cmake/xmake.lua b/tests/projects/package/cmake/xmake.lua new file mode 100644 index 000000000..48aa74660 --- /dev/null +++ b/tests/projects/package/cmake/xmake.lua @@ -0,0 +1,11 @@ +add_rules("mode.debug", "mode.release") + +add_requires("cmake::ZLIB", {system = true}) +add_requires("cmake::Boost", {system = true, + configs = {components = {"regex", "system"}, presets = {Boost_USE_STATIC_LIB = true}}}) +target("test") + set_kind("binary") + add_files("src/*.cpp") + add_packages("cmake::ZLIB", "cmake::Boost") + + diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 602b0e58d..e255fa1ec 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -1316,7 +1316,7 @@ function _instance:find_package(name, opt) mode = self:mode(), plat = self:plat(), arch = self:arch(), - pkgconfigs = self:configs(), + configs = self:configs(), buildhash = self:buildhash(), -- for xmake package or 3rd package manager, e.g. go:: .. cachekey = opt.cachekey or "fetch_package_system", external = opt.external, @@ -1896,7 +1896,7 @@ function package.load_from_system(packagename) -- on install script local on_install = function (pkg) local opt = {} - opt.pkgconfigs = pkg:configs() + opt.configs = pkg:configs() opt.mode = pkg:is_debug() and "debug" or "release" opt.plat = pkg:plat() opt.arch = pkg:arch() diff --git a/xmake/modules/package/manager/cargo/install_package.lua b/xmake/modules/package/manager/cargo/install_package.lua index dd2fde7e9..9ea709dd7 100644 --- a/xmake/modules/package/manager/cargo/install_package.lua +++ b/xmake/modules/package/manager/cargo/install_package.lua @@ -45,7 +45,7 @@ function main(name, opt) -- get required version opt = opt or {} - local pkgconfigs = opt.pkgconfigs or {} + local configs = opt.configs or {} local require_version = opt.require_version if not require_version or require_version == "latest" then require_version = "*" @@ -62,10 +62,10 @@ function main(name, opt) tomlfile:print("edition = \"2018\"") tomlfile:print("") tomlfile:print("[dependencies]") - local features = pkgconfigs.features + local features = configs.features if features then features = table.wrap(features) - tomlfile:print("%s = {version = \"%s\", features = [\"%s\"], default-features = %s}", name, require_version, table.concat(features, "\", \""), pkgconfigs.default_features) + tomlfile:print("%s = {version = \"%s\", features = [\"%s\"], default-features = %s}", name, require_version, table.concat(features, "\", \""), configs.default_features) else tomlfile:print("%s = \"%s\"", name, require_version) end diff --git a/xmake/modules/package/manager/clib/install_package.lua b/xmake/modules/package/manager/clib/install_package.lua index 8ebac7829..0257ff8fe 100644 --- a/xmake/modules/package/manager/clib/install_package.lua +++ b/xmake/modules/package/manager/clib/install_package.lua @@ -26,7 +26,7 @@ import("lib.detect.find_tool") -- install package -- @param name the package name, e.g. clib::clibs/bytes@0.4.0 -- @param opt the options, e.g. { verbose = true, --- pkgconfigs = {outputdir = "clib", save = false, save_dev = false}} +-- configs = {outputdir = "clib", save = false, save_dev = false}} -- -- @return true or false -- @@ -39,19 +39,19 @@ function main(name, opt) end opt = opt or {} - local pkgconfigs = opt.pkgconfigs or {} + local configs = opt.configs or {} local argv = {"install", name} - local abs_out = path.join(os.projectdir(), pkgconfigs.outputdir) + local abs_out = path.join(os.projectdir(), configs.outputdir) dprint("installing %s to %s", name, abs_out) table.insert(argv, "-o " .. abs_out) if not option.get("verbose") then table.insert(argv, "-q") end - if pkgconfigs.save then + if configs.save then table.insert(argv, "--save") end - if pkgconfigs.save_dev then + if configs.save_dev then table.insert(argv, "--save-dev") end diff --git a/xmake/modules/package/manager/cmake/configurations.lua b/xmake/modules/package/manager/cmake/configurations.lua index ce9b21e17..e65525f6d 100644 --- a/xmake/modules/package/manager/cmake/configurations.lua +++ b/xmake/modules/package/manager/cmake/configurations.lua @@ -22,12 +22,10 @@ function main() return { - build = {description = "use it to choose if you want to build from sources.", default = "missing", values = {"all", "never", "missing", "outdated"}}, - remote = {description = "Set the conan remote server."}, - options = {description = "Set the options values, e.g. OpenSSL:shared=True"}, - imports = {description = "Set the imports for conan."}, - settings = {description = "Set the build settings for conan."}, - build_requires = {description = "Set the build requires for conan.", default = "xmake_generator/0.1.0@bincrafters/testing"} + components = {description = "Set the cmake package components, e.g. {\"regex\", \"system\"}"}, + moduledirs = {description = "Set the cmake modules directories."}, + presets = {description = "Set the preset values, e.g. {Boost_USE_STATIC_LIB = true}"}, + envs = {description = "Set the run environments of cmake, e.g. {CMAKE_PREFIX_PATH = \"xxx\"}"}, } end diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua index e0e767145..b78b784c5 100644 --- a/xmake/modules/package/manager/cmake/find_package.lua +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -41,23 +41,28 @@ function _find_package(cmake, name, opt) -- e.g. OpenCV 4.1.1, Boost COMPONENTS regex system local requirestr = name + local configs = opt.configs or {} if opt.required_version then requirestr = requirestr .. " " .. opt.required_version end - if opt.components then + -- use opt.components is for backward compatibility + local components = configs.components or opt.components + if components then requirestr = requirestr .. " COMPONENTS" - for _, component in ipairs(opt.components) do + for _, component in ipairs(components) do requirestr = requirestr .. " " .. component end end - if opt.moduledirs then - for _, moduledir in ipairs(opt.moduledirs) do + local moduledirs = configs.moduledirs or opt.moduledirs + if moduledirs then + for _, moduledir in ipairs(moduledirs) do cmakefile:print("add_cmake_modules(%s)", moduledir) end end -- e.g. set(Boost_USE_STATIC_LIB ON) - if opt.presets then - for k, v in pairs(opt.presets) do + local presets = configs.presets or opt.presets + if presets then + for k, v in pairs(presets) do if type(v) == "boolean" then cmakefile:print("set(%s %s)", k, v and "ON" or "OFF") else @@ -82,7 +87,8 @@ function _find_package(cmake, name, opt) cmakefile:close() -- run cmake - try {function() return os.vrunv(cmake.program, {workdir}, {curdir = workdir, envs = opt.envs}) end} + local envs = configs.envs or opt.envs + try {function() return os.vrunv(cmake.program, {workdir}, {curdir = workdir, envs = envs}) end} -- pares defines and includedirs for macosx/linux local links @@ -238,12 +244,19 @@ end -- -- find_package("cmake::ZLIB") -- find_package("cmake::OpenCV", {required_version = "4.1.1"}) --- find_package("cmake::Boost", {components = {"regex", "system"}, presets = {Boost_USE_STATIC_LIB = true}}) --- find_package("cmake::Foo", {moduledirs = "xxx"}) +-- find_package("cmake::Boost", {configs = {components = {"regex", "system"}, presets = {Boost_USE_STATIC_LIB = true}}}) +-- find_package("cmake::Foo", {configs = {moduledirs = "xxx"}}) +-- +-- we can use add_requires with {system = true} +-- +-- add_requires("cmake::ZLIB", {system = true}) +-- add_requires("cmake::OpenCV 4.1.1", {system = true}) +-- add_requires("cmake::Boost", {configs = {components = {"regex", "system"}, presets = {Boost_USE_STATIC_LIB = true}}}) +-- add_requires("cmake::Foo", {configs = {moduledirs = "xxx"}}) -- -- @param name the package name -- @param opt the options, e.g. {verbose = true, required_version = "1.0", --- pkgconfigs = { +-- configs = { -- components = {"regex", "system"}, -- moduledirs = "xxx", -- presets = {Boost_USE_STATIC_LIB = true}, diff --git a/xmake/modules/package/manager/conan/configurations.lua b/xmake/modules/package/manager/conan/configurations.lua index ce9b21e17..b4ed38fc3 100644 --- a/xmake/modules/package/manager/conan/configurations.lua +++ b/xmake/modules/package/manager/conan/configurations.lua @@ -22,7 +22,7 @@ function main() return { - build = {description = "use it to choose if you want to build from sources.", default = "missing", values = {"all", "never", "missing", "outdated"}}, + build = {description = "Use it to choose if you want to build from sources.", default = "missing", values = {"all", "never", "missing", "outdated"}}, remote = {description = "Set the conan remote server."}, options = {description = "Set the options values, e.g. OpenSSL:shared=True"}, imports = {description = "Set the imports for conan."}, diff --git a/xmake/modules/package/manager/conan/install_package.lua b/xmake/modules/package/manager/conan/install_package.lua index d7f730e14..9f5a52a18 100644 --- a/xmake/modules/package/manager/conan/install_package.lua +++ b/xmake/modules/package/manager/conan/install_package.lua @@ -49,15 +49,15 @@ function _conan_get_build_directory(name) end -- generate conanfile.txt -function _conan_generate_conanfile(name, pkgconfigs) +function _conan_generate_conanfile(name, configs) -- trace dprint("generate %s ..", path.join(_conan_get_build_directory(name), "conanfile.txt")) -- get conan options, imports and build_requires - local options = table.wrap(pkgconfigs.options) - local imports = table.wrap(pkgconfigs.imports) - local build_requires = table.wrap(pkgconfigs.build_requires) + local options = table.wrap(configs.options) + local imports = table.wrap(configs.imports) + local build_requires = table.wrap(configs.build_requires) -- @see https://docs.conan.io/en/latest/systems_cross_building/cross_building.html -- generate it @@ -113,7 +113,7 @@ end -- -- @param name the package name, e.g. conan::OpenSSL/1.0.2n@conan/stable -- @param opt the options, e.g. { verbose = true, mode = "release", plat = , arch = , --- pkgconfigs = { +-- configs = { -- remote = "", build = "all", options = {}, imports = {}, build_requires = {}, -- settings = {"compiler=Visual Studio", "compiler.version=10", "compiler.runtime=MD"}}} -- @@ -121,9 +121,9 @@ end -- function main(name, opt) - -- get pkgconfigs + -- get configs opt = opt or {} - local pkgconfigs = opt.pkgconfigs or {} + local configs = opt.configs or {} -- find conan local conan = find_tool("conan") @@ -147,15 +147,15 @@ function main(name, opt) _conan_install_xmake_generator(conan) -- generate conanfile.txt - _conan_generate_conanfile(name, pkgconfigs) + _conan_generate_conanfile(name, configs) -- install package local argv = {"install", "."} - if pkgconfigs.build then - if pkgconfigs.build == "all" then + if configs.build then + if configs.build == "all" then table.insert(argv, "--build") else - table.insert(argv, "--build=" .. pkgconfigs.build) + table.insert(argv, "--build=" .. configs.build) end end @@ -233,15 +233,15 @@ function main(name, opt) end -- set custom settings - for _, setting in ipairs(pkgconfigs.settings) do + for _, setting in ipairs(configs.settings) do table.insert(argv, "-s") table.insert(argv, setting) end -- set remote - if pkgconfigs.remote then + if configs.remote then table.insert(argv, "-r") - table.insert(argv, pkgconfigs.remote) + table.insert(argv, configs.remote) end -- TODO set environments diff --git a/xmake/modules/package/manager/vcpkg/find_package.lua b/xmake/modules/package/manager/vcpkg/find_package.lua index 4b587be0a..1547da40a 100644 --- a/xmake/modules/package/manager/vcpkg/find_package.lua +++ b/xmake/modules/package/manager/vcpkg/find_package.lua @@ -82,10 +82,10 @@ function main(name, opt) -- find the package info file, e.g. zlib_1.2.11-3_x86-windows[-static].list local triplet = arch .. "-" .. plat - local pkgconfigs = opt.pkgconfigs - if plat == "windows" and pkgconfigs and pkgconfigs.shared ~= true then + local configs = opt.configs + if plat == "windows" and configs and configs.shared ~= true then triplet = triplet .. "-static" - if pkgconfigs.vs_runtime and pkgconfigs.vs_runtime:startswith("MD") then + if configs.vs_runtime and configs.vs_runtime:startswith("MD") then triplet = triplet .. "-md" end end -- cgit v1.3.1 From 0644c09d6c75a669f976f8d4bf67041c83c3f1d4 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 17 Dec 2021 00:54:44 +0800 Subject: update cmake tests --- tests/projects/package/cmake/xmake.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/projects/package/cmake/xmake.lua b/tests/projects/package/cmake/xmake.lua index 48aa74660..b6490032d 100644 --- a/tests/projects/package/cmake/xmake.lua +++ b/tests/projects/package/cmake/xmake.lua @@ -1,11 +1,12 @@ add_rules("mode.debug", "mode.release") add_requires("cmake::ZLIB", {system = true}) +add_requires("cmake::LibXml2", {system = true}) add_requires("cmake::Boost", {system = true, configs = {components = {"regex", "system"}, presets = {Boost_USE_STATIC_LIB = true}}}) target("test") set_kind("binary") add_files("src/*.cpp") - add_packages("cmake::ZLIB", "cmake::Boost") + add_packages("cmake::ZLIB", "cmake::Boost", "cmake::LibXml2") -- cgit v1.3.1 From 0fdd42e56f478591a4876866af833273f2cc244f Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 17 Dec 2021 00:55:21 +0800 Subject: add vcpkg tests --- tests/projects/package/vcpkg/.gitignore | 8 ++++++++ tests/projects/package/vcpkg/src/main.cpp | 9 +++++++++ tests/projects/package/vcpkg/xmake.lua | 8 ++++++++ xmake/modules/package/manager/vcpkg/find_package.lua | 4 ++-- 4 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 tests/projects/package/vcpkg/.gitignore create mode 100644 tests/projects/package/vcpkg/src/main.cpp create mode 100644 tests/projects/package/vcpkg/xmake.lua diff --git a/tests/projects/package/vcpkg/.gitignore b/tests/projects/package/vcpkg/.gitignore new file mode 100644 index 000000000..152105761 --- /dev/null +++ b/tests/projects/package/vcpkg/.gitignore @@ -0,0 +1,8 @@ +# Xmake cache +.xmake/ +build/ + +# MacOS Cache +.DS_Store + + diff --git a/tests/projects/package/vcpkg/src/main.cpp b/tests/projects/package/vcpkg/src/main.cpp new file mode 100644 index 000000000..7c435d251 --- /dev/null +++ b/tests/projects/package/vcpkg/src/main.cpp @@ -0,0 +1,9 @@ +#include + +using namespace std; + +int main(int argc, char** argv) +{ + cout << "hello world!" << endl; + return 0; +} diff --git a/tests/projects/package/vcpkg/xmake.lua b/tests/projects/package/vcpkg/xmake.lua new file mode 100644 index 000000000..3f5dbcf55 --- /dev/null +++ b/tests/projects/package/vcpkg/xmake.lua @@ -0,0 +1,8 @@ +add_requires("vcpkg::zlib", "vcpkg::pcre2") +add_requires("vcpkg::boost[core]", {alias = "boost"}) + +target("test") + set_kind("binary") + add_files("src/*.cpp") + add_packages("vcpkg::zlib", "vcpkg::pcre2", "boost") + diff --git a/xmake/modules/package/manager/vcpkg/find_package.lua b/xmake/modules/package/manager/vcpkg/find_package.lua index 1547da40a..24500cc2a 100644 --- a/xmake/modules/package/manager/vcpkg/find_package.lua +++ b/xmake/modules/package/manager/vcpkg/find_package.lua @@ -82,8 +82,8 @@ function main(name, opt) -- find the package info file, e.g. zlib_1.2.11-3_x86-windows[-static].list local triplet = arch .. "-" .. plat - local configs = opt.configs - if plat == "windows" and configs and configs.shared ~= true then + local configs = opt.configs or {} + if plat == "windows" and configs.shared ~= true then triplet = triplet .. "-static" if configs.vs_runtime and configs.vs_runtime:startswith("MD") then triplet = triplet .. "-md" -- cgit v1.3.1 From 0c977557c4566c6aff800320998c9b3aea0c8f1d Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 17 Dec 2021 00:55:39 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cb2bf1d4..78c70ba9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ * [#1904](https://github.com/xmake-io/xmake/pull/1904): Improve vs201x generator * Add `XMAKE_THEME` envirnoment variable to switch theme * [#1907](https://github.com/xmake-io/xmake/issues/1907): Add `-f/--force` to force to create project in a non-empty directory +* [#1917](https://github.com/xmake-io/xmake/pull/1917): Improve to find_package and configurations ### Bugs fixed @@ -1178,6 +1179,7 @@ * [#1904](https://github.com/xmake-io/xmake/pull/1904): 改进 vs201x 工程生成器 * 添加 `XMAKE_THEME` 环境变量去切换主题配置 * [#1907](https://github.com/xmake-io/xmake/issues/1907): 添加 `-f/--force` 参数使得 `xmake create` 可以在费控目录被强制创建 +* [#1917](https://github.com/xmake-io/xmake/pull/1917): 改进 find_package 和配置 ### Bugs 修复 -- cgit v1.3.1 From e8aa2b2b36fc5977bb0997cf2697837435937e98 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 17 Dec 2021 22:33:57 +0800 Subject: improve cmake.find_package and check gcc ldflags --- xmake/modules/detect/tools/gcc/has_flags.lua | 27 ++++++++-------------- .../modules/package/manager/cmake/find_package.lua | 16 ++++++++++--- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/xmake/modules/detect/tools/gcc/has_flags.lua b/xmake/modules/detect/tools/gcc/has_flags.lua index 7b4a40fd2..f7cf1d29e 100644 --- a/xmake/modules/detect/tools/gcc/has_flags.lua +++ b/xmake/modules/detect/tools/gcc/has_flags.lua @@ -44,36 +44,27 @@ end -- attempt to check it from the argument list function _check_from_arglist(flags, opt, islinker) - - -- only for compiler - if islinker or #flags > 1 then - return - end - - -- make cache key - local key = "detect.tools.gcc.has_flags" - - -- make flags key + local key = "detect.tools.gcc." .. (islinker and "has_ldflags" or "has_cflags") local flagskey = opt.program .. "_" .. (opt.programver or "") - - -- get all flags from argument list local allflags = detectcache:get2(key, flagskey) if not allflags then - - -- get argument list allflags = {} - local arglist = os.iorunv(opt.program, {"--help"}, {envs = opt.envs}) + local arglist = try {function () return os.iorunv(opt.program, {islinker and "-Wl,--help" or "--help"}, {envs = opt.envs}) end} if arglist then for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do allflags[arg] = true end end - - -- save cache detectcache:set2(key, flagskey, allflags) detectcache:save() end - return allflags[flags[1]] + local flag = flags[1] + if islinker and flag then + if flag:startswith("-Wl,") then + flag = flag:match("-Wl,(.-),") or flag:sub(5) + end + end + return allflags[flag] end -- get extension diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua index b78b784c5..d9abd6b00 100644 --- a/xmake/modules/package/manager/cmake/find_package.lua +++ b/xmake/modules/package/manager/cmake/find_package.lua @@ -96,6 +96,7 @@ function _find_package(cmake, name, opt) local libfiles local defines local includedirs + local ldflags local flagsfile = path.join(workdir, "CMakeFiles", name .. ".dir", "flags.make") if os.isfile(flagsfile) then local flagsdata = io.readfile(flagsfile) @@ -144,14 +145,21 @@ function _find_package(cmake, name, opt) vprint(linkdata) end for _, line in ipairs(os.argv(linkdata)) do + local is_ldflags = false local is_library = false for _, suffix in ipairs({".so", ".dylib", ".dylib", ".tbd", ".lib"}) do - if line:find(suffix, 1, true) then + if line:startswith("-Wl,") then + is_ldflags = true + break + elseif line:find(suffix, 1, true) then is_library = true break end end - if is_library then + if is_ldflags then + ldflags = ldflags or {} + table.insert(ldflags, line) + elseif is_library then -- strip library version suffix, e.g. libxxx.so.1.1 -> libxxx.so if line:find(".so", 1, true) then line = line:gsub("lib(.-)%.so%..+$", "lib%1.so") @@ -207,7 +215,7 @@ function _find_package(cmake, name, opt) -- get links and linkdirs local linkdir = path.directory(library) - linkdir = path.translate(linkdir) + linkdir = path.translate(linkdir) if linkdir ~= "." and not linkdir:startswith(workdir) then linkdirs = linkdirs or {} table.insert(linkdirs, linkdir) @@ -230,10 +238,12 @@ function _find_package(cmake, name, opt) if links or includedirs then local results = {} results.links = table.reverse_unique(links) + results.ldflags = table.reverse_unique(ldflags) results.linkdirs = table.unique(linkdirs) results.defines = table.unique(defines) results.libfiles = table.unique(libfiles) results.includedirs = table.unique(includedirs) + print(results) return results end end -- cgit v1.3.1 From 2a332ca17cf5ae1a9f4029402d12ea1fcf609f87 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 17 Dec 2021 22:35:57 +0800 Subject: add brew test --- tests/projects/package/brew/.gitignore | 8 ++++ tests/projects/package/brew/src/main.cpp | 9 ++++ tests/projects/package/brew/xmake.lua | 78 ++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 tests/projects/package/brew/.gitignore create mode 100644 tests/projects/package/brew/src/main.cpp create mode 100644 tests/projects/package/brew/xmake.lua diff --git a/tests/projects/package/brew/.gitignore b/tests/projects/package/brew/.gitignore new file mode 100644 index 000000000..152105761 --- /dev/null +++ b/tests/projects/package/brew/.gitignore @@ -0,0 +1,8 @@ +# Xmake cache +.xmake/ +build/ + +# MacOS Cache +.DS_Store + + diff --git a/tests/projects/package/brew/src/main.cpp b/tests/projects/package/brew/src/main.cpp new file mode 100644 index 000000000..7c435d251 --- /dev/null +++ b/tests/projects/package/brew/src/main.cpp @@ -0,0 +1,9 @@ +#include + +using namespace std; + +int main(int argc, char** argv) +{ + cout << "hello world!" << endl; + return 0; +} diff --git a/tests/projects/package/brew/xmake.lua b/tests/projects/package/brew/xmake.lua new file mode 100644 index 000000000..214f5e5e0 --- /dev/null +++ b/tests/projects/package/brew/xmake.lua @@ -0,0 +1,78 @@ +add_rules("mode.debug", "mode.release") + +add_requires("brew::pcre2/libpcre2-8", {alias = "pcre2"}) + +target("brew") + set_kind("binary") + add_files("src/*.cpp") + add_packages("pcre2") + +-- +-- If you want to known more usage about xmake, please see https://xmake.io +-- +-- ## FAQ +-- +-- You can enter the project directory firstly before building project. +-- +-- $ cd projectdir +-- +-- 1. How to build project? +-- +-- $ xmake +-- +-- 2. How to configure project? +-- +-- $ xmake f -p [macosx|linux|iphoneos ..] -a [x86_64|i386|arm64 ..] -m [debug|release] +-- +-- 3. Where is the build output directory? +-- +-- The default output directory is `./build` and you can configure the output directory. +-- +-- $ xmake f -o outputdir +-- $ xmake +-- +-- 4. How to run and debug target after building project? +-- +-- $ xmake run [targetname] +-- $ xmake run -d [targetname] +-- +-- 5. How to install target to the system directory or other output directory? +-- +-- $ xmake install +-- $ xmake install -o installdir +-- +-- 6. Add some frequently-used compilation flags in xmake.lua +-- +-- @code +-- -- add debug and release modes +-- add_rules("mode.debug", "mode.release") +-- +-- -- add macro defination +-- add_defines("NDEBUG", "_GNU_SOURCE=1") +-- +-- -- set warning all as error +-- set_warnings("all", "error") +-- +-- -- set language: c99, c++11 +-- set_languages("c99", "c++11") +-- +-- -- set optimization: none, faster, fastest, smallest +-- set_optimize("fastest") +-- +-- -- add include search directories +-- add_includedirs("/usr/include", "/usr/local/include") +-- +-- -- add link libraries and search directories +-- add_links("tbox") +-- add_linkdirs("/usr/local/lib", "/usr/lib") +-- +-- -- add system link libraries +-- add_syslinks("z", "pthread") +-- +-- -- add compilation and link flags +-- add_cxflags("-stdnolib", "-fno-strict-aliasing") +-- add_ldflags("-L/usr/local/lib", "-lpthread", {force = true}) +-- +-- @endcode +-- + -- cgit v1.3.1 From 022ca13475739cee7e10bd0a3256ecd704fb2e6d Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Dec 2021 00:35:37 +0800 Subject: update version --- CHANGELOG.md | 4 ++++ core/project.mak | 2 +- core/xmake.lua | 2 +- scripts/rpmbuild/SPECS/xmake.spec | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78c70ba9d..efc18354a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## master (unreleased) +## v2.6.2 + ### New features * [#1902](https://github.com/xmake-io/xmake/issues/1902): Support to build linux kernel driver modules @@ -1164,6 +1166,8 @@ ## master (开发中) +## v2.6.2 + ### 新特性 * [#1902](https://github.com/xmake-io/xmake/issues/1902): 支持构建 linux 内核驱动模块 diff --git a/core/project.mak b/core/project.mak index 945871e92..3e3838897 100644 --- a/core/project.mak +++ b/core/project.mak @@ -10,7 +10,7 @@ PRO_VERSION_MAJOR = 2 PRO_VERSION_MINOR = 6 # the project alter version -PRO_VERSION_ALTER = 1 +PRO_VERSION_ALTER = 2 # the project prefix PRO_PREFIX = XM_ diff --git a/core/xmake.lua b/core/xmake.lua index 5b72c672a..552781c76 100644 --- a/core/xmake.lua +++ b/core/xmake.lua @@ -2,7 +2,7 @@ set_project("xmake") -- version -set_version("2.6.1", {build = "%Y%m%d%H%M"}) +set_version("2.6.2", {build = "%Y%m%d%H%M"}) -- set xmake min version set_xmakever("2.2.3") diff --git a/scripts/rpmbuild/SPECS/xmake.spec b/scripts/rpmbuild/SPECS/xmake.spec index 8b03b8634..98e9cef22 100644 --- a/scripts/rpmbuild/SPECS/xmake.spec +++ b/scripts/rpmbuild/SPECS/xmake.spec @@ -8,7 +8,7 @@ %undefine _disable_source_fetch Name: xmake -Version: 2.6.1 +Version: 2.6.2 Release: 1%{?dist} Summary: A cross-platform build utility based on Lua BuildArch: noarch -- cgit v1.3.1 From 90e499cb2992883fef7a0eb16640e1765581ba8e Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Dec 2021 00:35:45 +0800 Subject: update ps1 --- scripts/get.ps1 | 2 +- scripts/rpmbuild/SPECS/xmake.spec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/get.ps1 b/scripts/get.ps1 index d1c1c22a9..538220acd 100755 --- a/scripts/get.ps1 +++ b/scripts/get.ps1 @@ -11,7 +11,7 @@ param ( ) & { - $LastRelease = "v2.6.1" + $LastRelease = "v2.6.2" $ErrorActionPreference = 'Stop' function writeErrorTip($msg) { diff --git a/scripts/rpmbuild/SPECS/xmake.spec b/scripts/rpmbuild/SPECS/xmake.spec index 98e9cef22..3485dc68a 100644 --- a/scripts/rpmbuild/SPECS/xmake.spec +++ b/scripts/rpmbuild/SPECS/xmake.spec @@ -1,4 +1,4 @@ -%define xmake_revision 7ae3c378f897fac7e0bf7dc9e0f7562a589514c8 +%define xmake_revision 022ca13475739cee7e10bd0a3256ecd704fb2e6d %define tbox_revision 122a479e626ee3fdd7d6c1117ec7c19212a1e087 %define sv_revision 035262773da0500367cb88e6f30197908159a348 %define lua_cjson_revision 515bab6d6d80b164b94db73af69609ea02f3a798 -- cgit v1.3.1 From 2e7c3bb2459dc25e68a7241b8b8c2d2811849dd4 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Dec 2021 15:58:13 +0800 Subject: Update package.lua --- xmake/core/package/package.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index e255fa1ec..88a5d07fb 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -1316,7 +1316,7 @@ function _instance:find_package(name, opt) mode = self:mode(), plat = self:plat(), arch = self:arch(), - configs = self:configs(), + configs = table.join(self:configs(), opt.configs), buildhash = self:buildhash(), -- for xmake package or 3rd package manager, e.g. go:: .. cachekey = opt.cachekey or "fetch_package_system", external = opt.external, -- cgit v1.3.1 From ace207315a587321fb7d00a4803b87d58b6ea3d4 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Dec 2021 16:19:37 +0800 Subject: Update driver_modules.lua --- xmake/rules/platform/linux/driver/driver_modules.lua | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 710a6464f..eeed180ad 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -28,11 +28,14 @@ import("private.tools.ccache") -- get linux-headers sdk function _get_linux_headers_sdk(target) + local linux_headersdir = target:values("linux.driver.linux-headers") + if linux_headersdir then + return {sdkdir = linux_headersdir, includedir = path.join(linux_headersdir, "include")} + end local linux_headers = assert(target:pkg("linux-headers"), "please add `add_requires(\"linux-headers\", {configs = {driver_modules = true}})` and `add_packages(\"linux-headers\")` to the given target!") local includedirs = linux_headers:get("includedirs") or linux_headers:get("sysincludedirs") local version = linux_headers:version() local includedir - local linux_headersdir for _, dir in ipairs(includedirs) do if dir:find("linux-headers", 1, true) then includedir = dir @@ -226,8 +229,10 @@ function load(target) target:add("cflags", "-include " .. path.join(includedir, "linux", "kconfig.h"), {force = true}) target:add("cflags", "-include " .. path.join(includedir, "linux", "compiler_types.h"), {force = true}) -- we need disable includedirs from add_packages("linux-headers") - target:pkg("linux-headers"):set("includedirs", nil) - target:pkg("linux-headers"):set("sysincludedirs", nil) + if target:pkg("linux-headers") then + target:pkg("linux-headers"):set("includedirs", nil) + target:pkg("linux-headers"):set("sysincludedirs", nil) + end -- add compilation flags target:add("defines", "KBUILD_MODNAME=\"" .. target:name() .. "\"") -- cgit v1.3.1 From a062353449af599c22adf55906ad311103660b50 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Dec 2021 16:26:34 +0800 Subject: update changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index efc18354a..440b1c02e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### Changes + +* [#1923](https://github.com/xmake-io/xmake/issues/1923): Improve to build linux driver, support set custom linux-headers path + ## v2.6.2 ### New features @@ -1166,6 +1170,10 @@ ## master (开发中) +### 改进 + +* [#1923](https://github.com/xmake-io/xmake/issues/1923): 改进构建 linux 驱动,支持设置自定义 linux-headers 路径 + ## v2.6.2 ### 新特性 -- cgit v1.3.1 From 7be1bc272914b757a4a7fe1792f7590de4a91cdf Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Dec 2021 19:23:31 +0800 Subject: Update make.lua --- xmake/modules/package/tools/make.lua | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/xmake/modules/package/tools/make.lua b/xmake/modules/package/tools/make.lua index cbc58c9e2..27e73b412 100644 --- a/xmake/modules/package/tools/make.lua +++ b/xmake/modules/package/tools/make.lua @@ -23,6 +23,14 @@ import("core.base.option") import("core.project.config") import("lib.detect.find_tool") +-- translate bin path +function _translate_bin_path(bin_path) + if is_host("windows") and bin_path then + return bin_path:gsub("\\", "/") .. ".exe" + end + return bin_path +end + -- get the build environments function buildenvs(package) local envs = {} @@ -44,14 +52,14 @@ function buildenvs(package) else local cflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cflags")) local cxxflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cxxflags")) - envs.CC = package:build_getenv("cc") - envs.CXX = package:build_getenv("cxx") - envs.AS = package:build_getenv("as") - envs.AR = package:build_getenv("ar") - envs.LD = package:build_getenv("ld") - envs.LDSHARED = package:build_getenv("sh") - envs.CPP = package:build_getenv("cpp") - envs.RANLIB = package:build_getenv("ranlib") + envs.CC = _translate_bin_path(package:build_getenv("cc")) + envs.CXX = _translate_bin_path(package:build_getenv("cxx")) + envs.AS = _translate_bin_path(package:build_getenv("as")) + envs.AR = _translate_bin_path(package:build_getenv("ar")) + envs.LD = _translate_bin_path(package:build_getenv("ld")) + envs.LDSHARED = _translate_bin_path(package:build_getenv("sh")) + envs.CPP = _translate_bin_path(package:build_getenv("cpp")) + envs.RANLIB = _translate_bin_path(package:build_getenv("ranlib")) envs.CFLAGS = table.concat(cflags, ' ') envs.CXXFLAGS = table.concat(cxxflags, ' ') envs.ASFLAGS = table.concat(table.wrap(package:build_getenv("asflags")), ' ') -- cgit v1.3.1 From e02a05e5fa50f21a6d4128582bf8a15141d6a763 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Dec 2021 23:17:45 +0800 Subject: fix term mode --- core/src/xmake/engine.c | 13 ++++ core/src/xmake/makefile | 3 +- core/src/xmake/tty/prefix.h | 32 ++++++++++ core/src/xmake/tty/term_mode.c | 70 ++++++++++++++++++++++ xmake/core/base/os.lua | 2 - xmake/core/base/tty.lua | 20 +++++++ .../action/require/impl/install_packages.lua | 9 +++ 7 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 core/src/xmake/tty/prefix.h create mode 100644 core/src/xmake/tty/term_mode.c diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index f407f2cd6..e87fce465 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -232,6 +232,9 @@ tb_int_t xm_libc_dataptr(lua_State* lua); tb_int_t xm_libc_byteof(lua_State* lua); tb_int_t xm_libc_setbyte(lua_State* lua); +// the tty functions +tb_int_t xm_tty_term_mode(lua_State* lua); + #ifdef XM_CONFIG_API_HAVE_CURSES // register curses __tb_extern_c_enter__ @@ -438,6 +441,13 @@ static luaL_Reg const g_libc_functions[] = , { tb_null, tb_null } }; +// the tty functions +static luaL_Reg const g_tty_functions[] = +{ + { "term_mode", xm_tty_term_mode } +, { tb_null, tb_null } +}; + /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ @@ -883,6 +893,9 @@ xm_engine_ref_t xm_engine_init(tb_char_t const* name, xm_engine_lni_initalizer_c // bind libc functions xm_lua_register(engine->lua, "libc", g_libc_functions); + // bind tty functions + xm_lua_register(engine->lua, "tty", g_tty_functions); + #ifdef XM_CONFIG_API_HAVE_CURSES // bind curses xm_curses_register(engine->lua); diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index 9e0a3decb..c85696f1e 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -123,7 +123,8 @@ xmake_C_FILES += \ libc/dataptr \ libc/byteof \ libc/setbyte \ - libc/strndup + libc/strndup \ + tty/term_mode iswin = ifeq ($(PLAT),windows) diff --git a/core/src/xmake/tty/prefix.h b/core/src/xmake/tty/prefix.h new file mode 100644 index 000000000..82a2c3a76 --- /dev/null +++ b/core/src/xmake/tty/prefix.h @@ -0,0 +1,32 @@ +/*!A cross-platform build utility based on Lua + * + * 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 + * + * http://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. + * + * Copyright (C) 2015-present, TBOOX Open Source Group. + * + * @author ruki + * @file prefix.h + * + */ +#ifndef XM_PATH_PREFIX_H +#define XM_PATH_PREFIX_H + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "../prefix.h" + + +#endif + + diff --git a/core/src/xmake/tty/term_mode.c b/core/src/xmake/tty/term_mode.c new file mode 100644 index 000000000..c4500fdf5 --- /dev/null +++ b/core/src/xmake/tty/term_mode.c @@ -0,0 +1,70 @@ +/*!A cross-platform build utility based on Lua + * + * 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 + * + * http://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. + * + * Copyright (C) 2015-present, TBOOX Open Source Group. + * + * @author ruki + * @file term_mode.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "term_mode" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" +#ifdef TB_CONFIG_OS_WINDOWS +# include +#endif + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ + +/* local oldmode = tty.term_mode(stdtype) + * local oldmode = tty.term_mode(stdtype, newmode) + */ +tb_int_t xm_tty_term_mode(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + // get std type, (stdin: 1, stdout: 2, stderr: 3) + tb_int_t stdtype = (tb_int_t)luaL_checkinteger(lua, 1); + + // get terminal mode + DWORD mode = 0; +#ifdef TB_CONFIG_OS_WINDOWS + HANDLE console_handle; + switch (stdtype) + { + case 1: console_handle = GetStdHandle(STD_INPUT_HANDLE); break; + case 2: console_handle = GetStdHandle(STD_OUTPUT_HANDLE); break; + case 3: console_handle = GetStdHandle(STD_ERROR_HANDLE); break; + } + GetConsoleMode(console_handle, &mode); + if (lua_isinteger(lua, 2)) + { + tb_int_t newmode = (tb_int_t)lua_tointeger(lua, 2); + SetConsoleMode(console_handle, (DWORD)newmode); + } +#endif + lua_pushinteger(lua, (tb_int_t)mode); + return 1; +} diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index 5c3057e5a..18b59f61c 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -761,8 +761,6 @@ function os.execv(program, argv, opt) -- cannot execute process return nil, os.strerror() end - - -- ok? return ok end diff --git a/xmake/core/base/tty.lua b/xmake/core/base/tty.lua index 0417f9b8f..a744f12e0 100644 --- a/xmake/core/base/tty.lua +++ b/xmake/core/base/tty.lua @@ -24,6 +24,9 @@ local tty = tty or {} -- load modules local io = require("base/io") +-- save metatable and builtin functions +tty._term_mode = tty._term_mode or tty.term_mode + -- @see http://www.termsys.demon.co.uk/vtansi.htm -- write control characters @@ -392,5 +395,22 @@ function tty.has_color24() return has_color24 end +-- get term mode, e.g. stdin, stdout, stderr +-- +-- local oldmode = tty.term_mode(stdtype) +-- local oldmode = tty.term_mode(stdtype, newmode) +-- +function tty.term_mode(stdtype, newmode) + local oldmode = 0 + if stdtype == "stdin" then + oldmode = tty._term_mode(1, newmode) + elseif stdtype == "stdout" then + oldmode = tty._term_mode(2, newmode) + elseif stdtype == "stderr" then + oldmode = tty._term_mode(3, newmode) + end + return oldmode +end + -- return module return tty diff --git a/xmake/modules/private/action/require/impl/install_packages.lua b/xmake/modules/private/action/require/impl/install_packages.lua index 714b98461..f62a0fb52 100644 --- a/xmake/modules/private/action/require/impl/install_packages.lua +++ b/xmake/modules/private/action/require/impl/install_packages.lua @@ -268,6 +268,9 @@ function _install_packages(packages_install, packages_download, installdeps) packages_installed[tostring(instance)] = false end + -- save terminal mode for stdout, @see https://github.com/xmake-io/xmake/issues/1924 + local term_mode_stdout = tty.term_mode("stdout") + -- do install local progress_helper = show_wait and progress.new() or nil local packages_installing = {} @@ -438,6 +441,12 @@ function _install_packages(packages_install, packages_download, installdeps) end end + -- fix terminal mode to avoid some subprocess to change it + -- @see https://github.com/xmake-io/xmake/issues/1924 + if term_mode_stdout ~= tty.term_mode("stdout") then + tty.term_mode("stdout", term_mode_stdout) + end + -- trace progress_helper:clear() tty.erase_line_to_start().cr() -- cgit v1.3.1 From ad540b6b68843b139be61dc98b84de1ad354d564 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Dec 2021 23:21:48 +0800 Subject: fix compiler error --- core/src/xmake/tty/term_mode.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/src/xmake/tty/term_mode.c b/core/src/xmake/tty/term_mode.c index c4500fdf5..66a3887ea 100644 --- a/core/src/xmake/tty/term_mode.c +++ b/core/src/xmake/tty/term_mode.c @@ -49,8 +49,8 @@ tb_int_t xm_tty_term_mode(lua_State* lua) tb_int_t stdtype = (tb_int_t)luaL_checkinteger(lua, 1); // get terminal mode - DWORD mode = 0; #ifdef TB_CONFIG_OS_WINDOWS + DWORD mode = 0; HANDLE console_handle; switch (stdtype) { @@ -64,6 +64,8 @@ tb_int_t xm_tty_term_mode(lua_State* lua) tb_int_t newmode = (tb_int_t)lua_tointeger(lua, 2); SetConsoleMode(console_handle, (DWORD)newmode); } +#else + tb_int_t mode = 0; #endif lua_pushinteger(lua, (tb_int_t)mode); return 1; -- cgit v1.3.1 From 0c9e6e48e08bbfdfb029aeb1a8228a32fa047762 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Dec 2021 23:24:06 +0800 Subject: update macro --- core/src/xmake/tty/prefix.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/xmake/tty/prefix.h b/core/src/xmake/tty/prefix.h index 82a2c3a76..d1fa5ba07 100644 --- a/core/src/xmake/tty/prefix.h +++ b/core/src/xmake/tty/prefix.h @@ -18,8 +18,8 @@ * @file prefix.h * */ -#ifndef XM_PATH_PREFIX_H -#define XM_PATH_PREFIX_H +#ifndef XM_TTY_PREFIX_H +#define XM_TTY_PREFIX_H /* ////////////////////////////////////////////////////////////////////////////////////// * includes -- cgit v1.3.1 From 06a82b1a794b0481a91db073754f188d54b0d87f Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Dec 2021 23:43:19 +0800 Subject: Update term_mode.c --- core/src/xmake/tty/term_mode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/xmake/tty/term_mode.c b/core/src/xmake/tty/term_mode.c index 66a3887ea..e035236a5 100644 --- a/core/src/xmake/tty/term_mode.c +++ b/core/src/xmake/tty/term_mode.c @@ -45,11 +45,11 @@ tb_int_t xm_tty_term_mode(lua_State* lua) // check tb_assert_and_check_return_val(lua, 0); +#ifdef TB_CONFIG_OS_WINDOWS + // get std type, (stdin: 1, stdout: 2, stderr: 3) tb_int_t stdtype = (tb_int_t)luaL_checkinteger(lua, 1); - // get terminal mode -#ifdef TB_CONFIG_OS_WINDOWS DWORD mode = 0; HANDLE console_handle; switch (stdtype) -- cgit v1.3.1 From 2ab866f4457c9074255d0104b32fce420bb8b13e Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 19 Dec 2021 00:16:02 +0800 Subject: fix compile errors --- core/src/xmake/tty/term_mode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/xmake/tty/term_mode.c b/core/src/xmake/tty/term_mode.c index e035236a5..975c8fc37 100644 --- a/core/src/xmake/tty/term_mode.c +++ b/core/src/xmake/tty/term_mode.c @@ -50,6 +50,7 @@ tb_int_t xm_tty_term_mode(lua_State* lua) // get std type, (stdin: 1, stdout: 2, stderr: 3) tb_int_t stdtype = (tb_int_t)luaL_checkinteger(lua, 1); + // get and set terminal mode DWORD mode = 0; HANDLE console_handle; switch (stdtype) @@ -59,7 +60,7 @@ tb_int_t xm_tty_term_mode(lua_State* lua) case 3: console_handle = GetStdHandle(STD_ERROR_HANDLE); break; } GetConsoleMode(console_handle, &mode); - if (lua_isinteger(lua, 2)) + if (lua_isnumber(lua, 2)) { tb_int_t newmode = (tb_int_t)lua_tointeger(lua, 2); SetConsoleMode(console_handle, (DWORD)newmode); -- cgit v1.3.1 From 1a4cb99bd3e6738f79ecaf627114a0097f5b55a6 Mon Sep 17 00:00:00 2001 From: biobot Date: Sun, 19 Dec 2021 12:34:47 +0800 Subject: use ninja instead of make when generator is ninja Signed-off-by: biobot --- xmake/modules/package/tools/cmake.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xmake/modules/package/tools/cmake.lua b/xmake/modules/package/tools/cmake.lua index 1134339d0..4ced3e67d 100644 --- a/xmake/modules/package/tools/cmake.lua +++ b/xmake/modules/package/tools/cmake.lua @@ -378,6 +378,10 @@ function _get_configs_for_mingw(package, configs, opt) envs.CMAKE_MAKE_PROGRAM = path.join(mingw, "bin", "mingw32-make.exe") end + if opt.cmake_generator == "Ninja" then + envs.CMAKE_MAKE_PROGRAM = "ninja" + end + for k, v in pairs(envs) do table.insert(configs, "-D" .. k .. "=" .. v) end -- cgit v1.3.1 From 4b139c33e84d6f2261bea3ec07ec889b44cebd96 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 20 Dec 2021 22:59:51 +0800 Subject: add vcpkg tests for manifest --- tests/projects/package/vcpkg_manifest/.gitignore | 8 ++++ tests/projects/package/vcpkg_manifest/src/main.cpp | 9 +++++ tests/projects/package/vcpkg_manifest/xmake.lua | 8 ++++ .../package/manager/vcpkg/install_package.lua | 44 +++++++++++++++------- .../action/require/impl/install_packages.lua | 1 + 5 files changed, 56 insertions(+), 14 deletions(-) create mode 100644 tests/projects/package/vcpkg_manifest/.gitignore create mode 100644 tests/projects/package/vcpkg_manifest/src/main.cpp create mode 100644 tests/projects/package/vcpkg_manifest/xmake.lua diff --git a/tests/projects/package/vcpkg_manifest/.gitignore b/tests/projects/package/vcpkg_manifest/.gitignore new file mode 100644 index 000000000..152105761 --- /dev/null +++ b/tests/projects/package/vcpkg_manifest/.gitignore @@ -0,0 +1,8 @@ +# Xmake cache +.xmake/ +build/ + +# MacOS Cache +.DS_Store + + diff --git a/tests/projects/package/vcpkg_manifest/src/main.cpp b/tests/projects/package/vcpkg_manifest/src/main.cpp new file mode 100644 index 000000000..7c435d251 --- /dev/null +++ b/tests/projects/package/vcpkg_manifest/src/main.cpp @@ -0,0 +1,9 @@ +#include + +using namespace std; + +int main(int argc, char** argv) +{ + cout << "hello world!" << endl; + return 0; +} diff --git a/tests/projects/package/vcpkg_manifest/xmake.lua b/tests/projects/package/vcpkg_manifest/xmake.lua new file mode 100644 index 000000000..a10ec2347 --- /dev/null +++ b/tests/projects/package/vcpkg_manifest/xmake.lua @@ -0,0 +1,8 @@ +add_requires("vcpkg::zlib 1.2.11", "vcpkg::fmt >=8.0.1") +--add_requires("vcpkg::boost", {alias = "boost", {configs = {}}}) + +target("test") + set_kind("binary") + add_files("src/*.cpp") + add_packages("vcpkg::zlib", "vcpkg::fmt", "boost") + diff --git a/xmake/modules/package/manager/vcpkg/install_package.lua b/xmake/modules/package/manager/vcpkg/install_package.lua index eaf28710e..071eec03b 100644 --- a/xmake/modules/package/manager/vcpkg/install_package.lua +++ b/xmake/modules/package/manager/vcpkg/install_package.lua @@ -22,20 +22,13 @@ import("core.base.option") import("lib.detect.find_tool") --- install package --- --- @param name the package name, e.g. pcre2, pcre2/libpcre2-8 --- @param opt the options, e.g. {verbose = true} --- --- @return true or false --- -function main(name, opt) +-- need manifest mode? +function _need_manifest(opt) +-- print("_need_manifest", opt) +end - -- attempt to find vcpkg - local vcpkg = find_tool("vcpkg") - if not vcpkg then - raise("vcpkg not found!") - end +-- install for classic mode +function _install_for_classic(vcpkg, name, opt) -- get arch, plat and mode local arch = opt.arch @@ -81,5 +74,28 @@ function main(name, opt) end -- install package - os.vrunv(vcpkg.program, argv) + os.vrunv(vcpkg, argv) +end + +-- install package +-- +-- @param name the package name, e.g. pcre2, pcre2/libpcre2-8 +-- @param opt the options, e.g. {verbose = true} +-- +-- @return true or false +-- +function main(name, opt) + + -- attempt to find vcpkg + local vcpkg = find_tool("vcpkg") + if not vcpkg then + raise("vcpkg not found!") + end + + -- do install + if _need_manifest(opt) then + _install_for_manifest(vcpkg.program, name, opt) + else + _install_for_classic(vcpkg.program, name, opt) + end end diff --git a/xmake/modules/private/action/require/impl/install_packages.lua b/xmake/modules/private/action/require/impl/install_packages.lua index f62a0fb52..c1d9b4791 100644 --- a/xmake/modules/private/action/require/impl/install_packages.lua +++ b/xmake/modules/private/action/require/impl/install_packages.lua @@ -285,6 +285,7 @@ function _install_packages(packages_install, packages_download, installdeps) -- fetch a new package local instance = nil while instance == nil and #packages_pending > 0 do + print("packages_pending", #packages_pending) for idx, pkg in ipairs(packages_pending) do -- all dependences has been installed? we install it now -- cgit v1.3.1 From 6447e8ff1bdd11274049997f3f21b1430546e4f0 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 20 Dec 2021 23:09:16 +0800 Subject: impl vcpkg manifest --- tests/projects/package/vcpkg_manifest/xmake.lua | 6 +- .../package/manager/vcpkg/configurations.lua | 48 ++++++++++ .../modules/package/manager/vcpkg/find_package.lua | 22 +---- .../package/manager/vcpkg/install_package.lua | 106 +++++++++++++++++---- .../action/require/impl/install_packages.lua | 1 - 5 files changed, 138 insertions(+), 45 deletions(-) create mode 100644 xmake/modules/package/manager/vcpkg/configurations.lua diff --git a/tests/projects/package/vcpkg_manifest/xmake.lua b/tests/projects/package/vcpkg_manifest/xmake.lua index a10ec2347..d7150718c 100644 --- a/tests/projects/package/vcpkg_manifest/xmake.lua +++ b/tests/projects/package/vcpkg_manifest/xmake.lua @@ -1,8 +1,8 @@ -add_requires("vcpkg::zlib 1.2.11", "vcpkg::fmt >=8.0.1") ---add_requires("vcpkg::boost", {alias = "boost", {configs = {}}}) +--add_requires("vcpkg::zlib 1.2.11", "vcpkg::fmt >=8.0.1") +add_requires("vcpkg::arrow", {configs = {features = {"json"}}}) target("test") set_kind("binary") add_files("src/*.cpp") - add_packages("vcpkg::zlib", "vcpkg::fmt", "boost") + add_packages("vcpkg::zlib", "vcpkg::fmt", "vcpkg::arrow") diff --git a/xmake/modules/package/manager/vcpkg/configurations.lua b/xmake/modules/package/manager/vcpkg/configurations.lua new file mode 100644 index 000000000..9021edff0 --- /dev/null +++ b/xmake/modules/package/manager/vcpkg/configurations.lua @@ -0,0 +1,48 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file configurations.lua +-- + +-- get architecture for vcpkg +function arch(arch) + local archs = { + x86_64 = "x64", + i386 = "x86", + + -- android: armeabi armeabi-v7a arm64-v8a x86 x86_64 mips mip64 + -- Offers a doc: https://github.com/microsoft/vcpkg/blob/master/docs/users/android.md + ["armeabi-v7a"] = "arm", + ["arm64-v8a"] = "arm64", + + -- ios: arm64 armv7 armv7s i386 + armv7 = "arm", + armv7s = "arm", + arm64 = "arm64", + } + return archs[arch] or arch +end + +-- get configurations +function main() + return { + baseline = {description = "set the builtin baseline."}, + features = {description = "set the features of dependency."}, + default_features = {description = "enables or disables any defaults provided by the dependency.", default = true} + } +end + diff --git a/xmake/modules/package/manager/vcpkg/find_package.lua b/xmake/modules/package/manager/vcpkg/find_package.lua index 24500cc2a..e84833958 100644 --- a/xmake/modules/package/manager/vcpkg/find_package.lua +++ b/xmake/modules/package/manager/vcpkg/find_package.lua @@ -25,6 +25,7 @@ import("core.base.option") import("core.project.config") import("core.project.target") import("detect.sdks.find_vcpkgdir") +import("package.manager.vcpkg.configurations") -- find package from the vcpkg package manager -- @@ -50,29 +51,10 @@ function main(name, opt) local arch = opt.arch local plat = opt.plat local mode = opt.mode - - -- mapping plat if plat == "macosx" then plat = "osx" end - - -- archs mapping for vcpkg - local archs = { - x86_64 = "x64", - i386 = "x86", - - -- android: armeabi armeabi-v7a arm64-v8a x86 x86_64 mips mip64 - -- Offers a doc: https://github.com/microsoft/vcpkg/blob/master/docs/users/android.md - ["armeabi-v7a"] = "arm", - ["arm64-v8a"] = "arm64", - - -- ios: arm64 armv7 armv7s i386 - armv7 = "arm", - armv7s = "arm", - arm64 = "arm64", - } - -- mapping arch - arch = archs[arch] or arch + arch = configurations.arch(arch) -- get the vcpkg installed directory local installdir = path.join(vcpkgdir, "installed") diff --git a/xmake/modules/package/manager/vcpkg/install_package.lua b/xmake/modules/package/manager/vcpkg/install_package.lua index 071eec03b..de707d0d1 100644 --- a/xmake/modules/package/manager/vcpkg/install_package.lua +++ b/xmake/modules/package/manager/vcpkg/install_package.lua @@ -20,11 +20,21 @@ -- imports import("core.base.option") +import("core.base.json") +import("core.base.semver") import("lib.detect.find_tool") +import("package.manager.vcpkg.configurations") -- need manifest mode? function _need_manifest(opt) --- print("_need_manifest", opt) + local require_version = opt.require_version + if require_version ~= nil and require_version ~= "latest" then + return true + end + local configs = opt.configs + if configs and (configs.features or configs.default_features or configs.baseline) then + return true + end end -- install for classic mode @@ -34,29 +44,10 @@ function _install_for_classic(vcpkg, name, opt) local arch = opt.arch local plat = opt.plat local mode = opt.mode - - -- mapping plat if plat == "macosx" then plat = "osx" end - - -- archs mapping for vcpkg - local archs = { - x86_64 = "x64", - i386 = "x86", - - -- android: armeabi armeabi-v7a arm64-v8a x86 x86_64 mips mip64 - -- Offers a doc: https://github.com/microsoft/vcpkg/blob/master/docs/users/android.md - ["armeabi-v7a"] = "arm", - ["arm64-v8a"] = "arm64", - - -- ios: arm64 armv7 armv7s i386 - armv7 = "arm", - armv7s = "arm", - arm64 = "arm64", - } - -- mapping arch - arch = archs[arch] or arch + arch = configurations.arch(arch) -- init triplet local triplet = arch .. "-" .. plat @@ -77,6 +68,78 @@ function _install_for_classic(vcpkg, name, opt) os.vrunv(vcpkg, argv) end +-- install for manifest mode +function _install_for_manifest(vcpkg, name, opt) + + -- get configs + local configs = opt.configs or {} + + --[[ + -- get arch, plat and mode + + -- init triplet + local triplet = arch .. "-" .. plat + if opt.plat == "windows" and opt.shared ~= true then + triplet = triplet .. "-static" + if opt.vs_runtime and opt.vs_runtime:startswith("MD") then + triplet = triplet .. "-md" + end + end]] + + -- init argv + local argv = {"--feature-flags=\"versions\"", "install"} + if option.get("diagnosis") then + table.insert(argv, "--debug") + end + + -- generate platform + local arch = opt.arch + local plat = opt.plat + if plat == "macosx" then + plat = "osx" + end + arch = configurations.arch(arch) + local platform = plat .. " & " .. arch + + -- generate dependencies + local require_version = opt.require_version + if require_version == "latest" then + require_version = nil + end + local minversion = require_version + if minversion and minversion:startswith(">=") then + minversion = minversion:sub(3) + end + local dependencies = {} + table.insert(dependencies, { + name = name, + ["version>="] = minversion, + platform = platform, + features = configs.features, + ["default-features"] = configs.default_features}) + + -- generate overrides to use fixed version + local overrides + if require_version and semver.is_valid(require_version) then + overrides = {{name = name, version = require_version}} + end + + -- generate manifest + local baseline = configs.baseline or "44d94c2edbd44f0c01d66c2ad95eb6982a9a61bc" -- 2021.04.30 + local manifest = { + name = "stub", + version = "1.0", + dependencies = dependencies, + ["builtin-baseline"] = baseline, + overrides = overrides} + local tmpdir = os.tmpfile() .. ".dir" + json.savefile(path.join(tmpdir, "vcpkg.json"), manifest) + + -- install package + os.vrunv(vcpkg, argv, {curdir = tmpdir}) + os.tryrm(tmpdir) +end + -- install package -- -- @param name the package name, e.g. pcre2, pcre2/libpcre2-8 @@ -93,6 +156,7 @@ function main(name, opt) end -- do install + opt = opt or {} if _need_manifest(opt) then _install_for_manifest(vcpkg.program, name, opt) else diff --git a/xmake/modules/private/action/require/impl/install_packages.lua b/xmake/modules/private/action/require/impl/install_packages.lua index c1d9b4791..f62a0fb52 100644 --- a/xmake/modules/private/action/require/impl/install_packages.lua +++ b/xmake/modules/private/action/require/impl/install_packages.lua @@ -285,7 +285,6 @@ function _install_packages(packages_install, packages_download, installdeps) -- fetch a new package local instance = nil while instance == nil and #packages_pending > 0 do - print("packages_pending", #packages_pending) for idx, pkg in ipairs(packages_pending) do -- all dependences has been installed? we install it now -- cgit v1.3.1 From c36a12cccb8639154ac3caf6441a764f6c32a5db Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 20 Dec 2021 23:09:42 +0800 Subject: remove comments --- xmake/modules/package/manager/vcpkg/install_package.lua | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/xmake/modules/package/manager/vcpkg/install_package.lua b/xmake/modules/package/manager/vcpkg/install_package.lua index de707d0d1..114cd538c 100644 --- a/xmake/modules/package/manager/vcpkg/install_package.lua +++ b/xmake/modules/package/manager/vcpkg/install_package.lua @@ -74,18 +74,6 @@ function _install_for_manifest(vcpkg, name, opt) -- get configs local configs = opt.configs or {} - --[[ - -- get arch, plat and mode - - -- init triplet - local triplet = arch .. "-" .. plat - if opt.plat == "windows" and opt.shared ~= true then - triplet = triplet .. "-static" - if opt.vs_runtime and opt.vs_runtime:startswith("MD") then - triplet = triplet .. "-md" - end - end]] - -- init argv local argv = {"--feature-flags=\"versions\"", "install"} if option.get("diagnosis") then -- cgit v1.3.1 From 39349f1a4fbf510d434c01952fe1f8f7e7505259 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 20 Dec 2021 23:14:50 +0800 Subject: add triplet to vcpkg manifest --- tests/projects/package/vcpkg_manifest/xmake.lua | 2 +- .../package/manager/vcpkg/install_package.lua | 25 +++++++++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/tests/projects/package/vcpkg_manifest/xmake.lua b/tests/projects/package/vcpkg_manifest/xmake.lua index d7150718c..fd8a23e79 100644 --- a/tests/projects/package/vcpkg_manifest/xmake.lua +++ b/tests/projects/package/vcpkg_manifest/xmake.lua @@ -1,4 +1,4 @@ ---add_requires("vcpkg::zlib 1.2.11", "vcpkg::fmt >=8.0.1") +add_requires("vcpkg::zlib 1.2.11", "vcpkg::fmt >=8.0.1") add_requires("vcpkg::arrow", {configs = {features = {"json"}}}) target("test") diff --git a/xmake/modules/package/manager/vcpkg/install_package.lua b/xmake/modules/package/manager/vcpkg/install_package.lua index 114cd538c..ec00fcb85 100644 --- a/xmake/modules/package/manager/vcpkg/install_package.lua +++ b/xmake/modules/package/manager/vcpkg/install_package.lua @@ -74,19 +74,28 @@ function _install_for_manifest(vcpkg, name, opt) -- get configs local configs = opt.configs or {} - -- init argv - local argv = {"--feature-flags=\"versions\"", "install"} - if option.get("diagnosis") then - table.insert(argv, "--debug") - end - - -- generate platform + -- init triplet local arch = opt.arch local plat = opt.plat if plat == "macosx" then plat = "osx" end arch = configurations.arch(arch) + local triplet = arch .. "-" .. plat + if opt.plat == "windows" and opt.shared ~= true then + triplet = triplet .. "-static" + if opt.vs_runtime and opt.vs_runtime:startswith("MD") then + triplet = triplet .. "-md" + end + end + + -- init argv + local argv = {"--feature-flags=\"versions\"", "install", "--triplet", triplet} + if option.get("diagnosis") then + table.insert(argv, "--debug") + end + + -- generate platform local platform = plat .. " & " .. arch -- generate dependencies @@ -120,7 +129,7 @@ function _install_for_manifest(vcpkg, name, opt) dependencies = dependencies, ["builtin-baseline"] = baseline, overrides = overrides} - local tmpdir = os.tmpfile() .. ".dir" + local tmpdir = os.tmpfile({ramdisk = false}) .. ".dir" json.savefile(path.join(tmpdir, "vcpkg.json"), manifest) -- install package -- cgit v1.3.1 From a1abfda3ca119979f541876355471b026abcc3f9 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 20 Dec 2021 23:18:02 +0800 Subject: find package stub for vcpkg manifest mode --- tests/projects/package/vcpkg_manifest/xmake.lua | 3 +- .../modules/package/manager/vcpkg/find_package.lua | 40 ++++++++++++++-------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/tests/projects/package/vcpkg_manifest/xmake.lua b/tests/projects/package/vcpkg_manifest/xmake.lua index fd8a23e79..a6b24f1bc 100644 --- a/tests/projects/package/vcpkg_manifest/xmake.lua +++ b/tests/projects/package/vcpkg_manifest/xmake.lua @@ -1,4 +1,5 @@ -add_requires("vcpkg::zlib 1.2.11", "vcpkg::fmt >=8.0.1") +add_requires("vcpkg::zlib 1.2.11") +add_requires("vcpkg::fmt >=8.0.1", {configs = {baseline = "50fd3d9957195575849a49fa591e645f1d8e7156"}}) add_requires("vcpkg::arrow", {configs = {features = {"json"}}}) target("test") diff --git a/xmake/modules/package/manager/vcpkg/find_package.lua b/xmake/modules/package/manager/vcpkg/find_package.lua index e84833958..726eceea7 100644 --- a/xmake/modules/package/manager/vcpkg/find_package.lua +++ b/xmake/modules/package/manager/vcpkg/find_package.lua @@ -27,21 +27,8 @@ import("core.project.target") import("detect.sdks.find_vcpkgdir") import("package.manager.vcpkg.configurations") --- find package from the vcpkg package manager --- --- @param name the package name, e.g. zlib, pcre --- @param opt the options, e.g. {verbose = true) --- -function main(name, opt) - - -- attempt to find vcpkg directory - local vcpkgdir = find_vcpkgdir() - if not vcpkgdir then - if option.get("diagnosis") then - cprint("${color.warning}checkinfo: ${clear dim}vcpkg root directory not found, maybe you need set $VCPKG_ROOT!") - end - return - end +-- find it for classic mode +function _find_package_for_classic(vcpkgdir, name, opt) -- fix name, e.g. ffmpeg[x264] as ffmpeg -- @see https://github.com/xmake-io/xmake/issues/925 @@ -137,3 +124,26 @@ function main(name, opt) return result end +-- find it for manifest mode +function _find_package_for_manifest(vcpkgdir, name, opt) +end + +-- find package from the vcpkg package manager +-- +-- @param name the package name, e.g. zlib, pcre +-- @param opt the options, e.g. {verbose = true) +-- +function main(name, opt) + + -- attempt to find vcpkg directory + local vcpkgdir = find_vcpkgdir() + if not vcpkgdir then + if option.get("diagnosis") then + cprint("${color.warning}checkinfo: ${clear dim}vcpkg root directory not found, maybe you need set $VCPKG_ROOT!") + end + return + end + + -- do find + return _find_package_for_manifest(vcpkgdir, name, opt) or _find_package_for_classic(vcpkgdir, name, opt) +end -- cgit v1.3.1 From ce000fa3f72ea6c4ca684a3d08b1e6cf09f5fb68 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Dec 2021 22:50:26 +0800 Subject: improve to vcpkg.find_package for manifest --- tests/projects/package/vcpkg_manifest/xmake.lua | 4 +-- xmake/core/package/package.lua | 23 ++++++++++++---- .../modules/package/manager/vcpkg/find_package.lua | 31 +++++++++++----------- .../package/manager/vcpkg/install_package.lua | 16 +++++++---- 4 files changed, 46 insertions(+), 28 deletions(-) diff --git a/tests/projects/package/vcpkg_manifest/xmake.lua b/tests/projects/package/vcpkg_manifest/xmake.lua index a6b24f1bc..5c08f2869 100644 --- a/tests/projects/package/vcpkg_manifest/xmake.lua +++ b/tests/projects/package/vcpkg_manifest/xmake.lua @@ -1,9 +1,9 @@ add_requires("vcpkg::zlib 1.2.11") add_requires("vcpkg::fmt >=8.0.1", {configs = {baseline = "50fd3d9957195575849a49fa591e645f1d8e7156"}}) -add_requires("vcpkg::arrow", {configs = {features = {"json"}}}) +add_requires("vcpkg::libpng", {configs = {features = {"apng"}}}) target("test") set_kind("binary") add_files("src/*.cpp") - add_packages("vcpkg::zlib", "vcpkg::fmt", "vcpkg::arrow") + add_packages("vcpkg::zlib", "vcpkg::fmt", "vcpkg::libpng") diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 88a5d07fb..379d1ddea 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -486,7 +486,7 @@ end -- is local package? -- we will use local installdir and cachedir in current project function _instance:is_local() - return self:is_embed() + return self:is_embed() or self:is_thirdparty() end -- is debug package? (deprecated) @@ -570,10 +570,15 @@ function _instance:cachedir() cachedir = self:get("cachedir") if not cachedir then local name = self:name():lower():gsub("::", "_") + local version_str = self:version_str() + if self:is_thirdparty() then + -- strip `>= <=` + version_str = version_str:gsub("[>=<]", "") + end if self:is_local() then - cachedir = path.join(config.buildir({absolute = true}), ".packages", name:sub(1, 1):lower(), name, self:version_str(), "cache") + cachedir = path.join(config.buildir({absolute = true}), ".packages", name:sub(1, 1):lower(), name, version_str, "cache") else - cachedir = path.join(package.cachedir(), name:sub(1, 1):lower(), name, self:version_str()) + cachedir = path.join(package.cachedir(), name:sub(1, 1):lower(), name, version_str) end end self._CACHEDIR = cachedir @@ -593,8 +598,13 @@ function _instance:installdir(...) else installdir = path.join(package.installdir(), name:sub(1, 1):lower(), name) end - if self:version_str() then - installdir = path.join(installdir, self:version_str()) + local version_str = self:version_str() + if version_str then + if self:is_thirdparty() then + -- strip `>= <=` + version_str = version_str:gsub("[>=<]", "") + end + installdir = path.join(installdir, version_str) end installdir = path.join(installdir, self:buildhash()) end @@ -1054,6 +1064,9 @@ function _instance:buildhash() -- We cannot directly deserialize the table, so the result may be different each time local configs_order = {} for k, v in pairs(table.wrap(configs)) do + if type(v) == "table" then + v = string.serialize(v, {strip = true, indent = false, orderkeys = true}) + end table.insert(configs_order, k .. "=" .. tostring(v)) end table.sort(configs_order) diff --git a/xmake/modules/package/manager/vcpkg/find_package.lua b/xmake/modules/package/manager/vcpkg/find_package.lua index 726eceea7..c28f62b07 100644 --- a/xmake/modules/package/manager/vcpkg/find_package.lua +++ b/xmake/modules/package/manager/vcpkg/find_package.lua @@ -27,8 +27,7 @@ import("core.project.target") import("detect.sdks.find_vcpkgdir") import("package.manager.vcpkg.configurations") --- find it for classic mode -function _find_package_for_classic(vcpkgdir, name, opt) +function _find_package(vcpkgdir, name, opt) -- fix name, e.g. ffmpeg[x264] as ffmpeg -- @see https://github.com/xmake-io/xmake/issues/925 @@ -43,11 +42,11 @@ function _find_package_for_classic(vcpkgdir, name, opt) end arch = configurations.arch(arch) - -- get the vcpkg installed directory - local installdir = path.join(vcpkgdir, "installed") - - -- get the vcpkg info directory - local infodir = path.join(installdir, "vcpkg", "info") + -- get the vcpkg info directories + local infodirs = { + path.join(opt.installdir, "vcpkg_installed", "vcpkg", "info"), + path.join(vcpkgdir, "installed", "vcpkg", "info") + } -- find the package info file, e.g. zlib_1.2.11-3_x86-windows[-static].list local triplet = arch .. "-" .. plat @@ -58,11 +57,15 @@ function _find_package_for_classic(vcpkgdir, name, opt) triplet = triplet .. "-md" end end - local infofile = find_file(format("%s_*_%s.list", name, triplet), infodir) + local infofile = find_file(format("%s_*_%s.list", name, triplet), infodirs) + if not infofile then + return + end + local installdir = path.directory(path.directory(path.directory(infofile))) -- save includedirs, linkdirs and links local result = nil - local info = infofile and io.readfile(infofile) or nil + local info = io.readfile(infofile) if info then for _, line in ipairs(info:split('\n')) do line = line:trim() @@ -104,7 +107,7 @@ function _find_package_for_classic(vcpkgdir, name, opt) end -- save version - if result and infofile then + if result then local infoname = path.basename(infofile) result.version = infoname:match(name .. "_(%d+%.?%d*%.?%d*.-)_" .. arch) if not result.version then @@ -124,10 +127,6 @@ function _find_package_for_classic(vcpkgdir, name, opt) return result end --- find it for manifest mode -function _find_package_for_manifest(vcpkgdir, name, opt) -end - -- find package from the vcpkg package manager -- -- @param name the package name, e.g. zlib, pcre @@ -144,6 +143,6 @@ function main(name, opt) return end - -- do find - return _find_package_for_manifest(vcpkgdir, name, opt) or _find_package_for_classic(vcpkgdir, name, opt) + -- do find package + return _find_package(vcpkgdir, name, opt) end diff --git a/xmake/modules/package/manager/vcpkg/install_package.lua b/xmake/modules/package/manager/vcpkg/install_package.lua index ec00fcb85..9b7ded261 100644 --- a/xmake/modules/package/manager/vcpkg/install_package.lua +++ b/xmake/modules/package/manager/vcpkg/install_package.lua @@ -32,7 +32,7 @@ function _need_manifest(opt) return true end local configs = opt.configs - if configs and (configs.features or configs.default_features or configs.baseline) then + if configs and (configs.features or configs.default_features == false or configs.baseline) then return true end end @@ -129,12 +129,18 @@ function _install_for_manifest(vcpkg, name, opt) dependencies = dependencies, ["builtin-baseline"] = baseline, overrides = overrides} - local tmpdir = os.tmpfile({ramdisk = false}) .. ".dir" - json.savefile(path.join(tmpdir, "vcpkg.json"), manifest) + local installdir = assert(opt.installdir, "installdir not found!") + json.savefile(path.join(installdir, "vcpkg.json"), manifest) + if not os.isdir(installdir) then + os.mkdir(installdir) + end + if option.get("diagnosis") then + vprint(path.join(installdir, "vcpkg.json")) + vprint(manifest) + end -- install package - os.vrunv(vcpkg, argv, {curdir = tmpdir}) - os.tryrm(tmpdir) + os.vrunv(vcpkg, argv, {curdir = installdir}) end -- install package -- cgit v1.3.1 From 7eaaaab5699cc9a380b85dcefad270b3ff120cd8 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Dec 2021 11:40:31 +0800 Subject: update changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 440b1c02e..998e9d2ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### New features + +* [#1298](https://github.com/xmake-io/xmake/issues/1928): Support vcpkg manifest mode and select version for package/install + ### Changes * [#1923](https://github.com/xmake-io/xmake/issues/1923): Improve to build linux driver, support set custom linux-headers path @@ -1170,6 +1174,10 @@ ## master (开发中) +### 新特性 + +* [#1298](https://github.com/xmake-io/xmake/issues/1928): 支持 vcpkg 清单模式安装包,实现安装包的版本选择 + ### 改进 * [#1923](https://github.com/xmake-io/xmake/issues/1923): 改进构建 linux 驱动,支持设置自定义 linux-headers 路径 -- cgit v1.3.1 From 496c568a973cd1d313e6f5fae7629f307b980b6d Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Dec 2021 13:17:05 +0800 Subject: Update install_package.lua --- xmake/modules/package/manager/vcpkg/install_package.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/package/manager/vcpkg/install_package.lua b/xmake/modules/package/manager/vcpkg/install_package.lua index 9b7ded261..892697dcc 100644 --- a/xmake/modules/package/manager/vcpkg/install_package.lua +++ b/xmake/modules/package/manager/vcpkg/install_package.lua @@ -90,7 +90,7 @@ function _install_for_manifest(vcpkg, name, opt) end -- init argv - local argv = {"--feature-flags=\"versions\"", "install", "--triplet", triplet} + local argv = {"--feature-flags=\"versions\"", "install", "--x-wait-for-lock", "--triplet", triplet} if option.get("diagnosis") then table.insert(argv, "--debug") end -- cgit v1.3.1 From 7df39cd4843ed1f2239937aef2b227642ffa3af2 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Dec 2021 13:21:19 +0800 Subject: Update install_package.lua --- xmake/modules/package/manager/vcpkg/install_package.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xmake/modules/package/manager/vcpkg/install_package.lua b/xmake/modules/package/manager/vcpkg/install_package.lua index 892697dcc..962c72f83 100644 --- a/xmake/modules/package/manager/vcpkg/install_package.lua +++ b/xmake/modules/package/manager/vcpkg/install_package.lua @@ -103,6 +103,10 @@ function _install_for_manifest(vcpkg, name, opt) if require_version == "latest" then require_version = nil end + -- 1.2.11+13 -> 1.2.11#13 + if require_version then + require_version = require_version:gsub("%+", "#") + end local minversion = require_version if minversion and minversion:startswith(">=") then minversion = minversion:sub(3) -- cgit v1.3.1 From 4ec129f7b917c222c4c20838acef80315eb85adf Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 21 Dec 2021 13:21:37 +0800 Subject: Update xmake.lua --- tests/projects/package/vcpkg_manifest/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/projects/package/vcpkg_manifest/xmake.lua b/tests/projects/package/vcpkg_manifest/xmake.lua index 5c08f2869..8a851328b 100644 --- a/tests/projects/package/vcpkg_manifest/xmake.lua +++ b/tests/projects/package/vcpkg_manifest/xmake.lua @@ -1,4 +1,4 @@ -add_requires("vcpkg::zlib 1.2.11") +add_requires("vcpkg::zlib 1.2.11+10") add_requires("vcpkg::fmt >=8.0.1", {configs = {baseline = "50fd3d9957195575849a49fa591e645f1d8e7156"}}) add_requires("vcpkg::libpng", {configs = {features = {"apng"}}}) -- cgit v1.3.1 From af1618680f6ed2f90accafc534ffdfc7caf2f078 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 22 Dec 2021 22:40:40 +0800 Subject: add linux driver test for custom --- tests/projects/linux/driver/hello_custom/src/add.c | 3 +++ .../projects/linux/driver/hello_custom/src/hello.c | 23 ++++++++++++++++++++++ tests/projects/linux/driver/hello_custom/xmake.lua | 6 ++++++ 3 files changed, 32 insertions(+) create mode 100644 tests/projects/linux/driver/hello_custom/src/add.c create mode 100644 tests/projects/linux/driver/hello_custom/src/hello.c create mode 100644 tests/projects/linux/driver/hello_custom/xmake.lua diff --git a/tests/projects/linux/driver/hello_custom/src/add.c b/tests/projects/linux/driver/hello_custom/src/add.c new file mode 100644 index 000000000..59aab4983 --- /dev/null +++ b/tests/projects/linux/driver/hello_custom/src/add.c @@ -0,0 +1,3 @@ +int add(int a, int b) { + return a + b; +} diff --git a/tests/projects/linux/driver/hello_custom/src/hello.c b/tests/projects/linux/driver/hello_custom/src/hello.c new file mode 100644 index 000000000..414a03bb2 --- /dev/null +++ b/tests/projects/linux/driver/hello_custom/src/hello.c @@ -0,0 +1,23 @@ +#include +#include + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Ruki"); +MODULE_DESCRIPTION("A simple Hello World Module"); +MODULE_ALIAS("a simplest module"); + +int add(int a, int b); + +int hello_init(void) +{ + printk(KERN_INFO "Hello World: %d\n", add(1, 2)); + 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/linux/driver/hello_custom/xmake.lua b/tests/projects/linux/driver/hello_custom/xmake.lua new file mode 100644 index 000000000..846bddc55 --- /dev/null +++ b/tests/projects/linux/driver/hello_custom/xmake.lua @@ -0,0 +1,6 @@ +option("linux-headers", {showmenu = true, description = "Set linux-headers path."}) +target("hello") + add_rules("platform.linux.driver") + add_files("src/*.c") + set_values("linux.driver.linux-headers", "$(linux-headers)") + -- cgit v1.3.1 From 32cb3e689bdfa82a9f37488062b35625a3a3ba57 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 22 Dec 2021 22:41:13 +0800 Subject: update readme --- README.md | 4 ++++ README_zh.md | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/README.md b/README.md index 17eed1810..ade03e163 100644 --- a/README.md +++ b/README.md @@ -508,6 +508,10 @@ Please download and install more other plugins from the plugins repository [xmak * [xmake.vim](https://github.com/luzhlon/xmake.vim) (third-party, thanks [@luzhlon](https://github.com/luzhlon)) +* [xmake-visualstudio](https://github.com/HelloWorld886/xmake-visualstudio) (third-party, thanks [@HelloWorld886](https://github.com/HelloWorld886)) + +* [xmake-qtcreator](https://github.com/Arthapz/xmake-project-manager) (third-party, thanks [@Arthapz](https://github.com/Arthapz)) + ### XMake Gradle Plugin (JNI) We can uses [xmake-gradle](https://github.com/xmake-io/xmake-gradle) plugin to compile JNI library in gradle. diff --git a/README_zh.md b/README_zh.md index b62c7fa8e..9776597ea 100644 --- a/README_zh.md +++ b/README_zh.md @@ -516,6 +516,10 @@ $ xmake l * [xmake.vim](https://github.com/luzhlon/xmake.vim) (third-party, thanks [@luzhlon](https://github.com/luzhlon)) +* [xmake-visualstudio](https://github.com/HelloWorld886/xmake-visualstudio) (third-party, thanks [@HelloWorld886](https://github.com/HelloWorld886)) + +* [xmake-qtcreator](https://github.com/Arthapz/xmake-project-manager) (third-party, thanks [@Arthapz](https://github.com/Arthapz)) + ### XMake Gradle插件 (JNI) 我们也可以在Gradle中使用[xmake-gradle](https://github.com/xmake-io/xmake-gradle)插件来集成编译JNI库 -- cgit v1.3.1 From 9d5658ade35f41bb2c8a348e4d835c52eb33cf5d Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 22 Dec 2021 12:44:19 +0800 Subject: Update toolchain.lua --- xmake/core/tool/toolchain.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xmake/core/tool/toolchain.lua b/xmake/core/tool/toolchain.lua index 3779d9297..782b004cd 100644 --- a/xmake/core/tool/toolchain.lua +++ b/xmake/core/tool/toolchain.lua @@ -131,7 +131,7 @@ function _instance:get(name) return value end - -- lazy loading platform + -- lazy loading toolchain self:_load() -- get other platform info @@ -185,6 +185,7 @@ end -- get the program and name of the given tool kind function _instance:tool(toolkind) -- ensure to do load for initializing toolset first + self:check() self:_load() local toolpaths = self:get("toolset." .. toolkind) if toolpaths then -- cgit v1.3.1 From ef918f37ade05750fd533b7d6dcca32091eb1906 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 22 Dec 2021 22:50:16 +0800 Subject: Update config.lua --- xmake/core/project/config.lua | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/xmake/core/project/config.lua b/xmake/core/project/config.lua index 00d06e878..d6dbcc962 100644 --- a/xmake/core/project/config.lua +++ b/xmake/core/project/config.lua @@ -97,14 +97,7 @@ function config.buildir(opt) opt = opt or {} local buildir = config.get("buildir") or "build" if not path.is_absolute(buildir) then - local rootdir - if os.isdir(path.join(os.workingdir(), ".xmake")) then - -- we switch to independent working directory @see https://github.com/xmake-io/xmake/issues/820 - rootdir = os.workingdir() - else - rootdir = os.projectdir() - end - buildir = path.absolute(buildir, rootdir) + buildir = path.absolute(buildir, os.projectdir()) end -- adjust path for the current directory -- cgit v1.3.1 From 01b29068ec1effab05be538ed9df3e05727ae181 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Wed, 22 Dec 2021 20:56:39 +0100 Subject: projects/vstudio: add support for runenvs --- xmake/plugins/project/vstudio/impl/vs201x.lua | 104 ++++++++++++++++++++- .../project/vstudio/impl/vs201x_vcxproj.lua | 57 +++++------ 2 files changed, 131 insertions(+), 30 deletions(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua index bf76b13dc..759789fda 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x.lua @@ -33,10 +33,69 @@ import("vs201x_vcxproj_filters") import("core.cache.memcache") import("core.cache.localcache") import("private.action.require.install", {alias = "install_requires"}) +import("private.action.run.make_runenvs") import("actions.config.configfiles", {alias = "generate_configfiles", rootdir = os.programdir()}) import("actions.config.configheader", {alias = "generate_configheader", rootdir = os.programdir()}) import("private.utils.batchcmds") +-- escape special chars in msbuild file +function _escape(str) + if not str then + return nil + end + + local map = + { + ["%"] = "%25" -- Referencing metadata + , ["$"] = "%24" -- Referencing properties + , ["@"] = "%40" -- Referencing item lists + , ["'"] = "%27" -- Conditions and other expressions + , [";"] = "%3B" -- List separator + , ["?"] = "%3F" -- Wildcard character for file names in Include and Exclude attributes + , ["*"] = "%2A" -- Wildcard character for use in file names in Include and Exclude attributes + -- html entities + , ["\""] = """ + , ["<"] = "<" + , [">"] = ">" + , ["&"] = "&" + } + + return (string.gsub(str, "[%%%$@';%?%*\"<>&]", function (c) return assert(map[c]) end)) +end + +function _make_dirs(dir, vcxprojdir) + if dir == nil then + return "" + end + if type(dir) == "string" then + dir = path.translate(dir) + if dir == "" then + return "" + end + if path.is_absolute(dir) then + print("absolute") + print(dir) + print("projectdir", project.directory()) + if dir:startswith(project.directory()) then + print("relative to ", vcxprojdir) + print(dir) + return _escape(path.relative(dir, vcxprojdir)) + end + return _escape(dir) + else + print("relative") + print(dir) + return _escape(path.relative(path.absolute(dir), vcxprojdir)) + end + end + local r = {} + for k, v in ipairs(dir) do + r[k] = _make_dirs(v, vcxprojdir) + end + r = table.unique(r) + return path.joinenv(r) +end + -- clear cache configuration function _clear_cacheconf() config.clear() @@ -180,7 +239,7 @@ function _make_custom_commands(target) end -- make target info -function _make_targetinfo(mode, arch, target) +function _make_targetinfo(mode, arch, target, vcxprojdir) -- init target info local targetinfo = { mode = mode, arch = (arch == "x86" and "Win32" or "x64") } @@ -246,6 +305,44 @@ function _make_targetinfo(mode, arch, target) -- save execution dir (when executed from VS) targetinfo.rundir = target:rundir() + -- save runenvs + local runenvs = {} + local addrunenvs, setrunenvs = make_runenvs(target) + for k, v in pairs(target:pkgenvs()) do + addrunenvs = addrunenvs or {} + addrunenvs[k] = table.join(table.wrap(addrunenvs[k]), path.splitenv(v)) + end + for _, dep in ipairs(target:orderdeps()) do + for k, v in pairs(dep:pkgenvs()) do + addrunenvs = addrunenvs or {} + addrunenvs[k] = table.join(table.wrap(addrunenvs[k]), path.splitenv(v)) + end + end + for k, v in pairs(addrunenvs) do + if k:upper() == "PATH" then + runenvs[k] = format("%s;$([System.Environment]::GetEnvironmentVariable('%s'))", _make_dirs(v, vcxprojdir), k) + else + runenvs[k] = format("%s;$([System.Environment]::GetEnvironmentVariable('%s'))", path.joinenv(v), k) + end + end + for k, v in pairs(setrunenvs) do + if #v == 1 then + v = v[1] + if path.is_absolute(v) and v:startswith(project.directory()) then + runenvs[k] = _make_dirs(v, vcxprojdir) + else + runenvs[k] = v[1] + end + else + runenvs[k] = path.joinenv(v) + end + end + local runenvstr = {} + for k, v in pairs(runenvs) do + table.insert(runenvstr, k .. "=" .. v) + end + targetinfo.runenvs = table.concat(runenvstr, "\n") + -- use mfc? save the mfc runtime kind if target:rule("win.sdk.mfc.shared_app") or target:rule("win.sdk.mfc.shared") then targetinfo.usemfc = "Dynamic" @@ -462,6 +559,9 @@ function make(outputdir, vsinfo) -- make target with the given mode and arch targets[targetname] = targets[targetname] or {} local _target = targets[targetname] + + -- the vcxproj directory + _target.project_dir = path.join(vsinfo.solution_dir, targetname) -- save c/c++ precompiled header _target.pcheader = target:pcheaderfile("c") -- header.h @@ -472,7 +572,7 @@ function make(outputdir, vsinfo) _target.kind = target:kind() _target.scriptdir = target:scriptdir() _target.info = _target.info or {} - table.insert(_target.info, _make_targetinfo(mode, arch, target)) + table.insert(_target.info, _make_targetinfo(mode, arch, target, _target.project_dir)) -- save all sourcefiles and headerfiles _target.sourcefiles = table.unique(table.join(_target.sourcefiles or {}, (target:sourcefiles()))) diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index 154e0763b..0d3d06da5 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -166,7 +166,7 @@ function _make_tailer(vcxprojfile, vsinfo) end -- make Configurations -function _make_configurations(vcxprojfile, vsinfo, target, vcxprojdir) +function _make_configurations(vcxprojfile, vsinfo, target) -- the target name local targetname = target.name @@ -233,8 +233,8 @@ function _make_configurations(vcxprojfile, vsinfo, target, vcxprojdir) -- make OutputDirectory and IntermediateDirectory for _, targetinfo in ipairs(target.info) do vcxprojfile:enter("", targetinfo.mode, targetinfo.arch) - vcxprojfile:print("%s\\", _make_dirs(targetinfo.targetdir, vcxprojdir)) - vcxprojfile:print("%s\\", _make_dirs(targetinfo.objectdir, vcxprojdir)) + vcxprojfile:print("%s\\", _make_dirs(targetinfo.targetdir, target.project_dir)) + vcxprojfile:print("%s\\", _make_dirs(targetinfo.objectdir, target.project_dir)) vcxprojfile:print("%s", path.basename(targetinfo.targetfile)) vcxprojfile:print("%s", path.extension(targetinfo.targetfile)) @@ -247,7 +247,8 @@ function _make_configurations(vcxprojfile, vsinfo, target, vcxprojdir) -- make Debugger for _, targetinfo in ipairs(target.info) do vcxprojfile:enter("", targetinfo.mode, targetinfo.arch) - vcxprojfile:print("%s", _make_dirs(targetinfo.rundir, vcxprojdir)) + vcxprojfile:print("%s", _make_dirs(targetinfo.rundir, target.project_dir)) + vcxprojfile:print("%s;$(LocalDebuggerEnvironment)", targetinfo.runenvs) vcxprojfile:leave("") end end @@ -530,7 +531,7 @@ function _make_common_item(vcxprojfile, vsinfo, target, targetinfo, vcxprojdir) end -- make common items -function _make_common_items(vcxprojfile, vsinfo, target, vcxprojdir) +function _make_common_items(vcxprojfile, vsinfo, target) -- for each mode and arch for _, targetinfo in ipairs(target.info) do @@ -546,7 +547,7 @@ function _make_common_items(vcxprojfile, vsinfo, target, vcxprojdir) for _, sourcefile in ipairs(sourcebatch.sourcefiles) do -- make compiler flags - local flags = _make_compflags(sourcefile, targetinfo, vcxprojdir) + local flags = _make_compflags(sourcefile, targetinfo, target.project_dir) -- no common flags for asm if sourcekind ~= "as" then @@ -591,7 +592,7 @@ function _make_common_items(vcxprojfile, vsinfo, target, vcxprojdir) targetinfo.sourceflags = sourceflags -- make common item - _make_common_item(vcxprojfile, vsinfo, target, targetinfo, vcxprojdir) + _make_common_item(vcxprojfile, vsinfo, target, targetinfo, target.project_dir) end end @@ -601,7 +602,7 @@ function _make_header_file(vcxprojfile, includefile, vcxprojdir) end -- make source file for all modes -function _make_source_file_forall(vcxprojfile, vsinfo, target, sourcefile, sourceinfo, vcxprojdir) +function _make_source_file_forall(vcxprojfile, vsinfo, target, sourcefile, sourceinfo) -- get object file and source kind local sourcekind = nil @@ -612,7 +613,7 @@ function _make_source_file_forall(vcxprojfile, vsinfo, target, sourcefile, sourc -- enter it local nodename = (sourcekind == "as" and "CustomBuild" or (sourcekind == "mrc" and "ResourceCompile" or "ClCompile")) - sourcefile = path.relative(path.absolute(sourcefile), vcxprojdir) + sourcefile = path.relative(path.absolute(sourcefile), target.project_dir) vcxprojfile:enter("<%s Include=\"%s\">", nodename, sourcefile) -- for *.asm files @@ -620,8 +621,8 @@ function _make_source_file_forall(vcxprojfile, vsinfo, target, sourcefile, sourc vcxprojfile:print("false") vcxprojfile:print("Document") for _, info in ipairs(sourceinfo) do - local objectfile = path.relative(path.absolute(info.objectfile), vcxprojdir) - local compcmd = _make_compcmd(info.compargv, sourcefile, objectfile, vcxprojdir) + local objectfile = path.relative(path.absolute(info.objectfile), target.project_dir) + local compcmd = _make_compcmd(info.compargv, sourcefile, objectfile, target.project_dir) vcxprojfile:print("%s", info.mode .. '|' .. info.arch, objectfile) vcxprojfile:print("%s", info.mode .. '|' .. info.arch, compcmd) end @@ -630,7 +631,7 @@ function _make_source_file_forall(vcxprojfile, vsinfo, target, sourcefile, sourc -- for *.rc files elseif sourcekind == "mrc" then for _, info in ipairs(sourceinfo) do - local objectfile = path.relative(path.absolute(info.objectfile), vcxprojdir) + local objectfile = path.relative(path.absolute(info.objectfile), target.project_dir) vcxprojfile:print("%s", info.mode, info.arch, objectfile) end @@ -717,10 +718,10 @@ function _make_source_file_forall(vcxprojfile, vsinfo, target, sourcefile, sourc end -- make source file for specific modes -function _make_source_file_forspec(vcxprojfile, vsinfo, target, sourcefile, sourceinfo, vcxprojdir) +function _make_source_file_forspec(vcxprojfile, vsinfo, target, sourcefile, sourceinfo) -- add source file - sourcefile = path.relative(path.absolute(sourcefile), vcxprojdir) + sourcefile = path.relative(path.absolute(sourcefile), target.project_dir) for _, info in ipairs(sourceinfo) do -- enter it @@ -728,9 +729,9 @@ function _make_source_file_forspec(vcxprojfile, vsinfo, target, sourcefile, sour vcxprojfile:enter("<%s Condition=\"\'%$(Configuration)|%$(Platform)\'==\'%s|%s\'\" Include=\"%s\">", nodename, info.mode, info.arch, sourcefile) -- for *.asm files - local objectfile = path.relative(path.absolute(info.objectfile), vcxprojdir) + local objectfile = path.relative(path.absolute(info.objectfile), target.project_dir) if info.sourcekind == "as" then - local compcmd = _make_compcmd(info.compargv, sourcefile, objectfile, vcxprojdir) + local compcmd = _make_compcmd(info.compargv, sourcefile, objectfile, target.project_dir) vcxprojfile:print("false") vcxprojfile:print("Document") vcxprojfile:print("%s", objectfile) @@ -757,12 +758,12 @@ function _make_source_file_forspec(vcxprojfile, vsinfo, target, sourcefile, sour end -- make source file for precompiled header -function _make_source_file_forpch(vcxprojfile, vsinfo, target, vcxprojdir) +function _make_source_file_forpch(vcxprojfile, vsinfo, target) -- add precompiled source file local pcheader = target.pcxxheader or target.pcheader if pcheader then - local sourcefile = path.relative(path.absolute(pcheader), vcxprojdir) + local sourcefile = path.relative(path.absolute(pcheader), target.project_dir) vcxprojfile:enter("", sourcefile) vcxprojfile:print("Create") vcxprojfile:print("") @@ -776,7 +777,7 @@ function _make_source_file_forpch(vcxprojfile, vsinfo, target, vcxprojdir) -- add object file local pcoutputfile = info.pcxxoutputfile or info.pcoutputfile if pcoutputfile then - local objectfile = path.relative(path.absolute(pcoutputfile .. ".obj"), vcxprojdir) + local objectfile = path.relative(path.absolute(pcoutputfile .. ".obj"), target.project_dir) vcxprojfile:print("%s", info.mode, info.arch, objectfile) end end @@ -785,7 +786,7 @@ function _make_source_file_forpch(vcxprojfile, vsinfo, target, vcxprojdir) end -- make source files -function _make_source_files(vcxprojfile, vsinfo, target, vcxprojdir) +function _make_source_files(vcxprojfile, vsinfo, target) -- add source files vcxprojfile:enter("") @@ -810,14 +811,14 @@ function _make_source_files(vcxprojfile, vsinfo, target, vcxprojdir) -- make source files for sourcefile, sourceinfo in pairs(sourceinfos) do if #sourceinfo == #target.info then - _make_source_file_forall(vcxprojfile, vsinfo, target, sourcefile, sourceinfo, vcxprojdir) + _make_source_file_forall(vcxprojfile, vsinfo, target, sourcefile, sourceinfo) else - _make_source_file_forspec(vcxprojfile, vsinfo, target, sourcefile, sourceinfo, vcxprojdir) + _make_source_file_forspec(vcxprojfile, vsinfo, target, sourcefile, sourceinfo) end end -- make precompiled source file - _make_source_file_forpch(vcxprojfile, vsinfo, target, vcxprojdir) + _make_source_file_forpch(vcxprojfile, vsinfo, target) vcxprojfile:leave("") @@ -827,7 +828,7 @@ function _make_source_files(vcxprojfile, vsinfo, target, vcxprojdir) for _, includefile in ipairs(target.headerfiles) do -- we need ignore pcheader file to fix https://github.com/xmake-io/xmake/issues/1171 if not pcheader or includefile ~= pcheader then - _make_header_file(vcxprojfile, includefile, vcxprojdir) + _make_header_file(vcxprojfile, includefile, target.project_dir) end end vcxprojfile:leave("") @@ -840,7 +841,7 @@ function make(vsinfo, target) local targetname = target.name -- the vcxproj directory - local vcxprojdir = path.join(vsinfo.solution_dir, targetname) + local vcxprojdir = target.project_dir -- open vcxproj file local vcxprojpath = path.join(vcxprojdir, targetname .. ".vcxproj") @@ -853,13 +854,13 @@ function make(vsinfo, target) _make_header(vcxprojfile, vsinfo) -- make Configurations - _make_configurations(vcxprojfile, vsinfo, target, vcxprojdir) + _make_configurations(vcxprojfile, vsinfo, target) -- make common items - _make_common_items(vcxprojfile, vsinfo, target, vcxprojdir) + _make_common_items(vcxprojfile, vsinfo, target) -- make source files - _make_source_files(vcxprojfile, vsinfo, target, vcxprojdir) + _make_source_files(vcxprojfile, vsinfo, target) -- make tailer _make_tailer(vcxprojfile, vsinfo) -- cgit v1.3.1 From 69f7706a2b5d90ad54fcb88ce223e01476a2a33a Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Wed, 22 Dec 2021 20:57:19 +0100 Subject: Remove debug prints --- xmake/plugins/project/vstudio/impl/vs201x.lua | 7 ------- 1 file changed, 7 deletions(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua index 759789fda..7b337c867 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x.lua @@ -73,18 +73,11 @@ function _make_dirs(dir, vcxprojdir) return "" end if path.is_absolute(dir) then - print("absolute") - print(dir) - print("projectdir", project.directory()) if dir:startswith(project.directory()) then - print("relative to ", vcxprojdir) - print(dir) return _escape(path.relative(dir, vcxprojdir)) end return _escape(dir) else - print("relative") - print(dir) return _escape(path.relative(path.absolute(dir), vcxprojdir)) end end -- cgit v1.3.1 From a8d47c7ead29f76cfa3d59faa7ea233a82f45002 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 Dec 2021 22:28:38 +0800 Subject: fix typo --- xmake/core/base/json.lua | 2 +- xmake/rules/qt/xmake.lua | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/xmake/core/base/json.lua b/xmake/core/base/json.lua index e43ae7d52..0b38df42a 100644 --- a/xmake/core/base/json.lua +++ b/xmake/core/base/json.lua @@ -22,7 +22,7 @@ local json = json or {} local cjson = cjson or {} --- laod modules +-- load modules local io = require("base/io") local utils = require("base/utils") diff --git a/xmake/rules/qt/xmake.lua b/xmake/rules/qt/xmake.lua index df6f2e79d..b26a458a5 100644 --- a/xmake/rules/qt/xmake.lua +++ b/xmake/rules/qt/xmake.lua @@ -137,7 +137,7 @@ rule("qt.widgetapp_static") QtPlatformSupport = "QtPlatformCompositorSupport" end - -- laod some basic plugins and frameworks + -- load some basic plugins and frameworks local plugins = {} local frameworks = {"QtGui", "QtWidgets", "QtCore"} if qt_sdkver and qt_sdkver:lt("5.0") then @@ -211,7 +211,7 @@ rule("qt.quickapp_static") QtPlatformSupport = "QtPlatformCompositorSupport" end - -- laod some basic plugins and frameworks + -- load some basic plugins and frameworks local plugins = {} local frameworks = {"QtGui", "QtQuick", "QtQml", "QtQmlModels", "QtCore", "QtNetwork"} if target:is_plat("macosx") then -- cgit v1.3.1 From 0a65e25c02c36764ba09e5051565d41a137bd0b5 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 Dec 2021 22:34:53 +0800 Subject: add python.library rule --- tests/projects/pybind/example/src/example.cpp | 38 +++++++++++++++++++++++++++ tests/projects/pybind/example/xmake.lua | 8 ++++++ xmake/rules/python/xmake.lua | 34 ++++++++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 tests/projects/pybind/example/src/example.cpp create mode 100644 tests/projects/pybind/example/xmake.lua create mode 100644 xmake/rules/python/xmake.lua diff --git a/tests/projects/pybind/example/src/example.cpp b/tests/projects/pybind/example/src/example.cpp new file mode 100644 index 000000000..cb1bad194 --- /dev/null +++ b/tests/projects/pybind/example/src/example.cpp @@ -0,0 +1,38 @@ +#include + +#define STRINGIFY(x) #x +#define MACRO_STRINGIFY(x) STRINGIFY(x) + +int add(int i, int j) { + return i + j; +} + +namespace py = pybind11; + +PYBIND11_MODULE(example, m) { + m.doc() = R"pbdoc( + Pybind11 example plugin + ----------------------- + .. currentmodule:: example + .. autosummary:: + :toctree: _generate + add + subtract + )pbdoc"; + + m.def("add", &add, R"pbdoc( + Add two numbers + Some other explanation about the add function. + )pbdoc"); + + m.def("subtract", [](int i, int j) { return i - j; }, R"pbdoc( + Subtract two numbers + Some other explanation about the subtract function. + )pbdoc"); + +#ifdef VERSION_INFO + m.attr("__version__") = MACRO_STRINGIFY(VERSION_INFO); +#else + m.attr("__version__") = "dev"; +#endif +} diff --git a/tests/projects/pybind/example/xmake.lua b/tests/projects/pybind/example/xmake.lua new file mode 100644 index 000000000..19b7b5a9e --- /dev/null +++ b/tests/projects/pybind/example/xmake.lua @@ -0,0 +1,8 @@ +add_rules("mode.release", "mode.debug") +add_requires("pybind11") + +target("example") + add_rules("python.library") + add_files("src/*.cpp") + add_packages("pybind11") + set_languages("c++11") diff --git a/xmake/rules/python/xmake.lua b/xmake/rules/python/xmake.lua new file mode 100644 index 000000000..7af9b434b --- /dev/null +++ b/xmake/rules/python/xmake.lua @@ -0,0 +1,34 @@ +--!A cross-platform build utility based on Lua +-- +-- 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 +-- +-- http://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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file xmake.lua +-- + +-- @see https://github.com/xmake-io/xmake/issues/1896 +rule("python.library") + on_load(function (target) + target:set("kind", "shared") + target:set("prefixname", "_") + local soabi = target:extraconf("rules", "python.library", "soabi") + if soabi then + else + if target:is_plat("windows") then + target:set("extension", ".pyd") + end + end + end) + -- cgit v1.3.1 From 65e93fa30d57ad5823cbfbb7b70df621a5cce4fa Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 Dec 2021 22:37:09 +0800 Subject: add python soabi --- .../pybind/example_with_soabi/src/example.cpp | 38 ++++++++++++++++++++++ tests/projects/pybind/example_with_soabi/xmake.lua | 8 +++++ xmake/rules/python/xmake.lua | 9 +++++ 3 files changed, 55 insertions(+) create mode 100644 tests/projects/pybind/example_with_soabi/src/example.cpp create mode 100644 tests/projects/pybind/example_with_soabi/xmake.lua diff --git a/tests/projects/pybind/example_with_soabi/src/example.cpp b/tests/projects/pybind/example_with_soabi/src/example.cpp new file mode 100644 index 000000000..cb1bad194 --- /dev/null +++ b/tests/projects/pybind/example_with_soabi/src/example.cpp @@ -0,0 +1,38 @@ +#include + +#define STRINGIFY(x) #x +#define MACRO_STRINGIFY(x) STRINGIFY(x) + +int add(int i, int j) { + return i + j; +} + +namespace py = pybind11; + +PYBIND11_MODULE(example, m) { + m.doc() = R"pbdoc( + Pybind11 example plugin + ----------------------- + .. currentmodule:: example + .. autosummary:: + :toctree: _generate + add + subtract + )pbdoc"; + + m.def("add", &add, R"pbdoc( + Add two numbers + Some other explanation about the add function. + )pbdoc"); + + m.def("subtract", [](int i, int j) { return i - j; }, R"pbdoc( + Subtract two numbers + Some other explanation about the subtract function. + )pbdoc"); + +#ifdef VERSION_INFO + m.attr("__version__") = MACRO_STRINGIFY(VERSION_INFO); +#else + m.attr("__version__") = "dev"; +#endif +} diff --git a/tests/projects/pybind/example_with_soabi/xmake.lua b/tests/projects/pybind/example_with_soabi/xmake.lua new file mode 100644 index 000000000..12d8ad334 --- /dev/null +++ b/tests/projects/pybind/example_with_soabi/xmake.lua @@ -0,0 +1,8 @@ +add_rules("mode.release", "mode.debug") +add_requires("pybind11") + +target("example") + add_rules("python.library", {soabi = true}) + add_files("src/*.cpp") + add_packages("pybind11") + set_languages("c++11") diff --git a/xmake/rules/python/xmake.lua b/xmake/rules/python/xmake.lua index 7af9b434b..823495485 100644 --- a/xmake/rules/python/xmake.lua +++ b/xmake/rules/python/xmake.lua @@ -25,6 +25,15 @@ rule("python.library") target:set("prefixname", "_") local soabi = target:extraconf("rules", "python.library", "soabi") if soabi then + import("lib.detect.find_tool") + local python = assert(find_tool("python3"), "python not found!") + local result = try { function() return os.iorunv(python.program, {"-c", "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))"}) end} + if result then + result = result:trim() + if result ~= "None" then + target:set("extension", result) + end + end else if target:is_plat("windows") then target:set("extension", ".pyd") -- cgit v1.3.1 From 95b63301dd11e16b5039aa9c10cda77e8ddc1036 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 Dec 2021 22:37:46 +0800 Subject: add soabi for swig.python --- tests/projects/swig/python_c_with_soabi/src/example.c | 14 ++++++++++++++ tests/projects/swig/python_c_with_soabi/src/example.i | 11 +++++++++++ tests/projects/swig/python_c_with_soabi/xmake.lua | 8 ++++++++ xmake/rules/swig/xmake.lua | 17 +++++++++++++++-- 4 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 tests/projects/swig/python_c_with_soabi/src/example.c create mode 100644 tests/projects/swig/python_c_with_soabi/src/example.i create mode 100644 tests/projects/swig/python_c_with_soabi/xmake.lua diff --git a/tests/projects/swig/python_c_with_soabi/src/example.c b/tests/projects/swig/python_c_with_soabi/src/example.c new file mode 100644 index 000000000..b0ddc9c26 --- /dev/null +++ b/tests/projects/swig/python_c_with_soabi/src/example.c @@ -0,0 +1,14 @@ +double My_variable = 3.0; + +/* Compute factorial of n */ +int fact(int n) { + if (n <= 1) + return 1; + else + return n*fact(n-1); +} + +/* Compute n mod m */ +int my_mod(int n, int m) { + return(n % m); +} diff --git a/tests/projects/swig/python_c_with_soabi/src/example.i b/tests/projects/swig/python_c_with_soabi/src/example.i new file mode 100644 index 000000000..34193edc7 --- /dev/null +++ b/tests/projects/swig/python_c_with_soabi/src/example.i @@ -0,0 +1,11 @@ +%module example +%{ +/* Put headers and other declarations here */ +extern double My_variable; +extern int fact(int); +extern int my_mod(int n, int m); +%} + +extern double My_variable; +extern int fact(int); +extern int my_mod(int n, int m); diff --git a/tests/projects/swig/python_c_with_soabi/xmake.lua b/tests/projects/swig/python_c_with_soabi/xmake.lua new file mode 100644 index 000000000..81dd49926 --- /dev/null +++ b/tests/projects/swig/python_c_with_soabi/xmake.lua @@ -0,0 +1,8 @@ +add_rules("mode.release", "mode.debug") +add_requires("python 3.x") + +target("example") + add_rules("swig.c", {moduletype = "python", soabi = true}) + add_files("src/example.i", {scriptdir = "share"}) + add_files("src/example.c") + add_packages("python") diff --git a/xmake/rules/swig/xmake.lua b/xmake/rules/swig/xmake.lua index 29b2673a2..c0387a940 100644 --- a/xmake/rules/swig/xmake.lua +++ b/xmake/rules/swig/xmake.lua @@ -30,8 +30,21 @@ rule("swig.base") local moduletype = target:extraconf("rules", "swig.c", "moduletype") or target:extraconf("rules", "swig.cpp", "moduletype") if moduletype == "python" then target:set("prefixname", "_") - if target:is_plat("windows") then - target:set("extension", ".pyd") + local soabi = target:extraconf("rules", "swig.c", "soabi") or target:extraconf("rules", "swig.cpp", "soabi") + if soabi then + import("lib.detect.find_tool") + local python = assert(find_tool("python3"), "python not found!") + local result = try { function() return os.iorunv(python.program, {"-c", "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))"}) end} + if result then + result = result:trim() + if result ~= "None" then + target:set("extension", result) + end + end + else + if target:is_plat("windows") then + target:set("extension", ".pyd") + end end elseif moduletype == "lua" then target:set("prefixname", "") -- cgit v1.3.1 From f94275cc4a85e40ed6f05200c6a69a189f3d61df Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 23 Dec 2021 22:38:56 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 998e9d2ff..61bba3c68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### New features * [#1298](https://github.com/xmake-io/xmake/issues/1928): Support vcpkg manifest mode and select version for package/install +* [#1896](https://github.com/xmake-io/xmake/issues/1896): Add `python.library` rule to build pybind modules ### Changes @@ -1177,6 +1178,7 @@ ### 新特性 * [#1298](https://github.com/xmake-io/xmake/issues/1928): 支持 vcpkg 清单模式安装包,实现安装包的版本选择 +* [#1896](https://github.com/xmake-io/xmake/issues/1896): 添加 `python.library` 规则去构建 pybind 模块,并且支持 soabi ### 改进 -- cgit v1.3.1 From 058005193f33d0461bbe2ee11428ce41d4cd3083 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Dec 2021 22:38:21 +0800 Subject: improve strip for gcc --- xmake/modules/core/tools/gcc.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index a871f62e5..40d3b8a4e 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -76,13 +76,13 @@ function init(self) end -- make the strip flag -function nf_strip(self, level) +function nf_strip(self, level, target) local maps = { debug = "-Wl,-S" , all = "-s" } - if is_plat("macosx") or is_plat("iphoneos") then + if target:is_plat("macosx") or target:is_plat("iphoneos") then maps.all = "-Wl,-x" end return maps[level] -- cgit v1.3.1 From 96d63a27f174e4eba17903e5faec887de5c3d3e7 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Dec 2021 22:44:42 +0800 Subject: add remove_files --- xmake/core/base/interpreter.lua | 42 ++++++++++++++++++++++++----- xmake/core/base/scopeinfo.lua | 60 ++++++++++++++++++++++++++++++++++++----- xmake/core/project/option.lua | 6 +++++ xmake/core/project/target.lua | 47 +++++++++++++++++++------------- 4 files changed, 124 insertions(+), 31 deletions(-) diff --git a/xmake/core/base/interpreter.lua b/xmake/core/base/interpreter.lua index 01de8047d..62325b2ad 100644 --- a/xmake/core/base/interpreter.lua +++ b/xmake/core/base/interpreter.lua @@ -257,7 +257,7 @@ function interpreter:_api_register_xxx_values(scope_kind, action, apifunc, ...) assert(scope) -- set values (set, on, before, after ...)? mark as "override" - if apiname and (action ~= "add" and action ~= "del") then + if apiname and (action ~= "add" and action ~= "del" and action ~= "remove") then scope["__override_" .. apiname] = true end @@ -498,12 +498,12 @@ function interpreter:_handle(scope, deduplicate, enable_filter) values = self:_filter(values) end - -- remove repeat first for each slice with deleted item (__del_xxx) + -- remove repeat first for each slice with removed item (__remove_xxx) if deduplicate and not table.is_dictionary(values) then local policy = self:deduplication_policy(name) if policy ~= false then local unique_func = policy == "toleft" and table.reverse_unique or table.unique - values = unique_func(values, function (v) return type(v) == "string" and v:startswith("__del_") end) + values = unique_func(values, function (v) return type(v) == "string" and v:startswith("__remove_") end) end end @@ -1360,7 +1360,7 @@ function interpreter:api_register_set_paths(scope_kind, ...) self:_api_register_xxx_values(scope_kind, "set", implementation, ...) end --- register api for del_paths +-- register api for del_paths (deprecated) function interpreter:api_register_del_paths(scope_kind, ...) -- check @@ -1376,7 +1376,7 @@ function interpreter:api_register_del_paths(scope_kind, ...) -- mark these paths as deleted local paths_deleted = {} for _, pathname in ipairs(paths) do - table.insert(paths_deleted, "__del_" .. pathname) + table.insert(paths_deleted, "__remove_" .. pathname) end -- save values @@ -1390,6 +1390,36 @@ function interpreter:api_register_del_paths(scope_kind, ...) self:_api_register_xxx_values(scope_kind, "del", implementation, ...) end +-- register api for remove_paths +function interpreter:api_register_remove_paths(scope_kind, ...) + + -- check + assert(self) + + -- define implementation + local implementation = function (self, scope, name, ...) + + -- translate paths + local values = table.join(...) + local paths = self:_api_translate_paths(values, "remove_" .. name) + + -- mark these paths as removed + local paths_removed = {} + for _, pathname in ipairs(paths) do + table.insert(paths_removed, "__remove_" .. pathname) + end + + -- save values + scope[name] = table.join2(scope[name] or {}, paths_removed) + + -- save api source info, e.g. call api() in sourcefile:linenumber + self:_save_sourceinfo_to_scope(scope, name, paths) + end + + -- register implementation + self:_api_register_xxx_values(scope_kind, "remove", implementation, ...) +end + -- register api for add_paths function interpreter:api_register_add_paths(scope_kind, ...) @@ -1509,7 +1539,7 @@ function interpreter:api_define(apis) -- get function prefix local prefix = nil - for _, name in ipairs({"set", "add", "del", "on", "before", "after"}) do + for _, name in ipairs({"set", "add", "del", "remove", "on", "before", "after"}) do if funcname:startswith(name .. "_") then prefix = name break diff --git a/xmake/core/base/scopeinfo.lua b/xmake/core/base/scopeinfo.lua index 6b7e566b5..7141482bc 100644 --- a/xmake/core/base/scopeinfo.lua +++ b/xmake/core/base/scopeinfo.lua @@ -62,12 +62,12 @@ function _instance:_api_handle(name, values) local interp = self:interpreter() if interp then - -- remove repeat first for each slice with deleted item (__del_xxx) + -- remove repeat first for each slice with deleted item (__remove_xxx) if self._DEDUPLICATE and not table.is_dictionary(values) then local policy = interp:deduplication_policy(name) if policy ~= false then local unique_func = policy == "toleft" and table.reverse_unique or table.unique - values = unique_func(values, function (v) return type(v) == "string" and v:startswith("__del_") end) + values = unique_func(values, function (v) return type(v) == "string" and v:startswith("__remove_") end) end end @@ -376,7 +376,7 @@ function _instance:_api_add_paths(name, ...) self:_api_save_sourceinfo_to_scope(scope, name, paths) end --- remove the api paths to the scope info +-- remove the api paths to the scope info (deprecated) function _instance:_api_del_paths(name, ...) -- get the scope info @@ -394,7 +394,7 @@ function _instance:_api_del_paths(name, ...) -- mark these paths as deleted local paths_deleted = {} for _, pathname in ipairs(paths) do - table.insert(paths_deleted, "__del_" .. pathname) + table.insert(paths_deleted, "__remove_" .. pathname) end -- save values @@ -404,6 +404,34 @@ function _instance:_api_del_paths(name, ...) self:_api_save_sourceinfo_to_scope(scope, name, paths) end +-- remove the api paths to the scope info +function _instance:_api_remove_paths(name, ...) + + -- get the scope info + local scope = self._INFO + + -- get interpreter + local interp = self:interpreter() + + -- expand values + values = table.join(...) + + -- translate paths + local paths = interp:_api_translate_paths(values, "remove_" .. name, 5) + + -- mark these paths as removed + local paths_removed = {} + for _, pathname in ipairs(paths) do + table.insert(paths_removed, "__remove_" .. pathname) + end + + -- save values + scope[name] = self:_api_handle(name, table.join2(table.wrap(scope[name]), paths_removed)) + + -- save api source info, e.g. call api() in sourcefile:linenumber + self:_api_save_sourceinfo_to_scope(scope, name, paths) +end + -- get the scope kind function _instance:kind() return self._KIND @@ -506,12 +534,12 @@ function _instance:apival_add(name, ...) end end --- remove the api values to the scope info +-- remove the api values to the scope info (deprecated) function _instance:apival_del(name, ...) if type(name) == "string" then local api_type = self:_api_type("del_" .. name) if api_type then - local del_xxx = self["_api_del_" .. api_type] + local del_xxx = self["_api_remove_" .. api_type] if del_xxx then del_xxx(self, name, ...) else @@ -526,6 +554,26 @@ function _instance:apival_del(name, ...) end end +-- remove the api values to the scope info +function _instance:apival_remove(name, ...) + if type(name) == "string" then + local api_type = self:_api_type("remove_" .. name) + if api_type then + local remove_xxx = self["_api_remove_" .. api_type] + if remove_xxx then + remove_xxx(self, name, ...) + else + os.raise("unknown apitype(%s) for %s:remove(%s, ...)", api_type, self:kind(), name) + end + else + os.raise("unknown api(%s) for %s:remove(%s, ...)", name, self:kind(), name) + end + elseif name ~= nil then + -- TODO + os.raise("cannot support to remove a dictionary!") + end +end + -- get the extra configuration -- -- e.g. diff --git a/xmake/core/project/option.lua b/xmake/core/project/option.lua index 8f5502390..0364b3b47 100644 --- a/xmake/core/project/option.lua +++ b/xmake/core/project/option.lua @@ -420,6 +420,12 @@ function _instance:del(name, ...) self:_invalidate() end +-- remove the value to the option info (deprecated) +function _instance:remove(name, ...) + self._INFO:apival_remove(name, ...) + self:_invalidate() +end + -- get the extra configuration function _instance:extraconf(name, item, key) return self._INFO:extraconf(name, item, key) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 1a489b1ce..68073187b 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -387,12 +387,18 @@ function _instance:add(name, ...) self:_invalidate(name) end --- remove the value to the target info +-- remove the value to the target info (deprecated) function _instance:del(name, ...) self._INFO:apival_del(name, ...) self:_invalidate(name) end +-- remove the value to the target info +function _instance:remove(name, ...) + self._INFO:apival_remove(name, ...) + self:_invalidate(name) +end + -- get the extra configuration function _instance:extraconf(name, item, key) return self._INFO:extraconf(name, item, key) @@ -1267,24 +1273,25 @@ function _instance:sourcefiles() local i = 1 local count = 0 local sourcefiles = {} - local sourcefiles_deleted = {} + local sourcefiles_removed = {} local sourcefiles_inserted = {} - local deleted_count = 0 + local removed_count = 0 local targetcache = memcache.cache("core.project.target") for _, file in ipairs(table.wrap(files)) do - -- mark as deleted files? - local deleted = false - if file:startswith("__del_") then - file = file:sub(7) - deleted = true + -- mark as removed files? + local removed = false + local prefix = "__remove_" + if file:startswith(prefix) then + file = file:sub(#prefix + 1) + removed = true end -- find source files and try to cache the matching results of os.match across targets -- @see https://github.com/xmake-io/xmake/issues/1353 local results = targetcache:get2("sourcefiles", file) if not results then - if deleted then + if removed then results = {file} else results = os.files(file) @@ -1311,7 +1318,7 @@ function _instance:sourcefiles() end if #results == 0 then local sourceinfo = (self:get("__sourceinfo_files") or {})[file] or {} - utils.warning("cannot match %s(%s).%s_files(\"%s\") at %s:%d", self:type(), self:name(), (deleted and "del" or "add"), file, sourceinfo.file or "", sourceinfo.line or -1) + utils.warning("cannot match %s(%s).%s_files(\"%s\") at %s:%d", self:type(), self:name(), (removed and "remove" or "add"), file, sourceinfo.file or "", sourceinfo.line or -1) end -- process source files @@ -1322,10 +1329,10 @@ function _instance:sourcefiles() sourcefile = path.relative(sourcefile, os.projectdir()) end - -- add or delete it - if deleted then - deleted_count = deleted_count + 1 - table.insert(sourcefiles_deleted, sourcefile) + -- add or remove it + if removed then + removed_count = removed_count + 1 + table.insert(sourcefiles_removed, sourcefile) elseif not sourcefiles_inserted[sourcefile] then table.insert(sourcefiles, sourcefile) sourcefiles_inserted[sourcefile] = true @@ -1333,12 +1340,12 @@ function _instance:sourcefiles() end end - -- remove all deleted source files - if deleted_count > 0 then + -- remove all source files which need be removed + if removed_count > 0 then for i = #sourcefiles, 1, -1 do local sourcefile = sourcefiles[i] - for _, deletefile in ipairs(sourcefiles_deleted) do - local pattern = path.translate(deletefile:gsub("|.*$", "")) + for _, removed_file in ipairs(sourcefiles_removed) do + local pattern = path.translate(removed_file:gsub("|.*$", "")) if pattern:sub(1, 2):find('%.[/\\]') then pattern = pattern:sub(3) end @@ -2034,8 +2041,10 @@ function target.apis() , "target.add_cleanfiles" , "target.add_configfiles" , "target.add_installfiles" - -- target.del_xxx + -- target.del_xxx (deprecated) , "target.del_files" + -- target.remove_xxx + , "target.remove_files" } , dictionary = { -- cgit v1.3.1 From 97c7b59e9af2ec0833b6aa5207d11d7438317b73 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Dec 2021 22:44:51 +0800 Subject: remove deprecatd interpreter --- xmake/core/base/deprecated/interpreter.lua | 140 ----------------------------- xmake/core/project/deprecated/project.lua | 1 - 2 files changed, 141 deletions(-) delete mode 100644 xmake/core/base/deprecated/interpreter.lua diff --git a/xmake/core/base/deprecated/interpreter.lua b/xmake/core/base/deprecated/interpreter.lua deleted file mode 100644 index 4213de8a0..000000000 --- a/xmake/core/base/deprecated/interpreter.lua +++ /dev/null @@ -1,140 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- 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 --- --- http://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. --- --- Copyright (C) 2015-present, TBOOX Open Source Group. --- --- @author ruki --- @file deprecated_interpreter.lua --- - --- define module: deprecated_interpreter -local deprecated_interpreter = deprecated_interpreter or {} - --- load modules -local os = require("base/os") -local path = require("base/path") -local table = require("base/table") -local utils = require("base/utils") -local string = require("base/string") -local deprecated = require("base/deprecated") -local sandbox = require("sandbox/sandbox") - --- register api for set_scope() -function deprecated_interpreter:api_register_set_scope(...) - - -- check - assert(self) - - -- define implementation - local implementation = function (self, scopes, scope_kind, scope_name) - - -- init scope for kind - local scope_for_kind = scopes[scope_kind] or {} - scopes[scope_kind] = scope_for_kind - - -- deprecated - if not scope_name:startswith("__") then - deprecated.add("%s(\"%s\")", "set_%s(\"%s\")", scope_kind, scope_name) - end - - -- check - if not scope_for_kind[scope_name] then - utils.error("set_%s(\"%s\") failed, %s not found!", scope_kind, scope_name, scope_name) - os.raise("please uses add_%s(\"%s\") first!", scope_kind, scope_name) - end - - -- init scope for name - scope_for_kind[scope_name] = scope_for_kind[scope_name] or {} - - -- save the current scope - scopes._CURRENT = scope_for_kind[scope_name] - - -- update the current scope kind - scopes._CURRENT_KIND = scope_kind - - end - - -- register implementation - self:_api_register_scope_api(nil, "set", implementation, ...) -end - --- register api for add_scope() -function deprecated_interpreter:api_register_add_scope(...) - - -- check - assert(self) - - -- define implementation - local implementation = function (self, scopes, scope_kind, scope_name) - - -- init scope for kind - local scope_for_kind = scopes[scope_kind] or {} - scopes[scope_kind] = scope_for_kind - - -- deprecated - if not scope_name:startswith("__") then - deprecated.add("%s(\"%s\")", "add_%s(\"%s\")", scope_kind, scope_name) - end - - -- check - if scope_for_kind[scope_name] then - utils.error("add_%s(\"%s\") failed, %s have been defined!", scope_kind, scope_name, scope_name) - os.raise("please uses set_%s(\"%s\")!", scope_kind, scope_name) - end - - -- init scope for name - scope_for_kind[scope_name] = scope_for_kind[scope_name] or {} - - -- save the current scope - scopes._CURRENT = scope_for_kind[scope_name] - - -- update the current scope kind - scopes._CURRENT_KIND = scope_kind - - end - - -- register implementation - self:_api_register_scope_api(nil, "add", implementation, ...) -end - --- register api for set_script -function deprecated_interpreter:api_register_set_script(scope_kind, ...) - - -- check - assert(self) - - -- define implementation - local implementation = function (self, scope, name, script) - - -- deprecated - deprecated.add("on_%s()", "set_%s()", name) - - -- make sandbox instance with the given script - local instance, errors = sandbox.new(script, self:filter(), self:rootdir()) - if not instance then - os.raise("set_%s(): %s", name, errors) - end - - -- update script? - scope[name] = {} - table.insert(scope[name], instance:script()) - - end - - -- register implementation - self:_api_register_xxx_values(scope_kind, "set", implementation, ...) -end - --- return module: deprecated_interpreter -return deprecated_interpreter diff --git a/xmake/core/project/deprecated/project.lua b/xmake/core/project/deprecated/project.lua index dceeac9ba..46e06b7be 100644 --- a/xmake/core/project/deprecated/project.lua +++ b/xmake/core/project/deprecated/project.lua @@ -31,7 +31,6 @@ local rule = require("project/rule") local config = require("project/config") local platform = require("platform/platform") local deprecated = require("base/deprecated") -local deprecated_interpreter = require("base/deprecated/interpreter") -- add_headers for target function deprecated_project._api_target_add_headers(interp) -- cgit v1.3.1 From 48a2d0c64c39466190af8900e259f4ceb53a895f Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Dec 2021 22:46:29 +0800 Subject: mark del_files as deprecated --- xmake/core/base/interpreter.lua | 76 ++++++----------------------------------- xmake/core/base/scopeinfo.lua | 14 +++++--- 2 files changed, 20 insertions(+), 70 deletions(-) diff --git a/xmake/core/base/interpreter.lua b/xmake/core/base/interpreter.lua index 62325b2ad..e8e379e08 100644 --- a/xmake/core/base/interpreter.lua +++ b/xmake/core/base/interpreter.lua @@ -22,13 +22,14 @@ local interpreter = interpreter or {} -- load modules -local os = require("base/os") -local path = require("base/path") -local table = require("base/table") -local utils = require("base/utils") -local string = require("base/string") -local scopeinfo = require("base/scopeinfo") -local sandbox = require("sandbox/sandbox") +local os = require("base/os") +local path = require("base/path") +local table = require("base/table") +local utils = require("base/utils") +local string = require("base/string") +local scopeinfo = require("base/scopeinfo") +local deprecated = require("base/deprecated") +local sandbox = require("sandbox/sandbox") -- traceback function interpreter._traceback(errors) @@ -160,8 +161,6 @@ end -- register scope end: scopename_end() function interpreter:_api_register_scope_end(...) - - -- check assert(self and self._PUBLIC and self._PRIVATE) -- done @@ -191,8 +190,6 @@ end -- register scope api: xxx_apiname() function interpreter:_api_register_scope_api(scope_kind, action, apifunc, ...) - - -- check assert(self and self._PUBLIC and self._PRIVATE) assert(apifunc) @@ -226,8 +223,6 @@ end -- register api: xxx_values() function interpreter:_api_register_xxx_values(scope_kind, action, apifunc, ...) - - -- check assert(self and self._PUBLIC and self._PRIVATE) assert(action and apifunc) @@ -372,8 +367,6 @@ end -- get api function within scope function interpreter:_api_within_scope(scope_kind, apiname) - - -- the private local priv = self._PRIVATE assert(priv) @@ -394,8 +387,6 @@ end -- set api function within scope function interpreter:_api_within_scope_set(scope_kind, apiname, apifunc) - - -- the private local priv = self._PRIVATE assert(priv) @@ -416,8 +407,6 @@ end -- clear results function interpreter:_clear() - - -- check assert(self and self._PRIVATE) -- clear it @@ -427,8 +416,6 @@ end -- filter values function interpreter:_filter(values, level) - - -- check assert(self and values ~= nil) -- return values directly if no filter @@ -482,8 +469,6 @@ end -- handle scope data function interpreter:_handle(scope, deduplicate, enable_filter) - - -- check assert(scope) -- remove repeat values and unwrap it @@ -518,8 +503,6 @@ end -- make results function interpreter:_make(scope_kind, deduplicate, enable_filter) - - -- check assert(self and self._PRIVATE) -- the scopes @@ -719,8 +702,6 @@ end -- @param opt {on_load_data = function (data) return data end} -- function interpreter:load(file, opt) - - -- check assert(self and self._PUBLIC and self._PRIVATE and file) -- load the script @@ -847,8 +828,6 @@ end -- get apis function interpreter:apis(scope_kind) - - -- check assert(self and self._PRIVATE) -- get apis from the given scope kind @@ -889,8 +868,6 @@ end -- } -- function interpreter:api_register(scope_kind, name, func) - - -- check assert(self and self._PUBLIC and self._PRIVATE) assert(name and func) @@ -924,11 +901,7 @@ end -- register api for builtin function interpreter:api_register_builtin(name, func) - - -- check assert(self and self._PUBLIC and func) - - -- register it self._PUBLIC[name] = func end @@ -974,9 +947,6 @@ end -- function interpreter:api_register_scope(...) - -- check - assert(self) - -- define implementation local implementation = function (self, scopes, scope_kind, scope_name, scope_info) @@ -1259,9 +1229,6 @@ end -- register api for set_dictionary function interpreter:api_register_set_dictionary(scope_kind, ...) - -- check - assert(self) - -- define implementation local implementation = function (self, scope, name, dict_or_key, value, extra_config) @@ -1289,9 +1256,6 @@ end -- register api for add_dictionary function interpreter:api_register_add_dictionary(scope_kind, ...) - -- check - assert(self) - -- define implementation local implementation = function (self, scope, name, dict_or_key, value, extra_config) @@ -1321,9 +1285,6 @@ end -- register api for set_paths function interpreter:api_register_set_paths(scope_kind, ...) - -- check - assert(self) - -- define implementation local implementation = function (self, scope, name, ...) @@ -1363,9 +1324,6 @@ end -- register api for del_paths (deprecated) function interpreter:api_register_del_paths(scope_kind, ...) - -- check - assert(self) - -- define implementation local implementation = function (self, scope, name, ...) @@ -1373,6 +1331,9 @@ function interpreter:api_register_del_paths(scope_kind, ...) local values = table.join(...) local paths = self:_api_translate_paths(values, "del_" .. name) + -- it has been marked as deprecated + deprecated.add("remove_" .. name .. "(%s)", "del_" .. name .. "(%s)", table.concat(values, ", "), table.concat(values, ", ")) + -- mark these paths as deleted local paths_deleted = {} for _, pathname in ipairs(paths) do @@ -1393,9 +1354,6 @@ end -- register api for remove_paths function interpreter:api_register_remove_paths(scope_kind, ...) - -- check - assert(self) - -- define implementation local implementation = function (self, scope, name, ...) @@ -1423,9 +1381,6 @@ end -- register api for add_paths function interpreter:api_register_add_paths(scope_kind, ...) - -- check - assert(self) - -- define implementation local implementation = function (self, scope, name, ...) @@ -1764,27 +1719,18 @@ end -- get api function function interpreter:api_func(apiname) - - -- check assert(self and self._PUBLIC and apiname) - - -- get api function return self._PUBLIC[apiname] end -- call api function interpreter:api_call(apiname, ...) - - -- check assert(self and apiname) - -- get api function local apifunc = self:api_func(apiname) if not apifunc then os.raise("call %s() failed, this api not found!", apiname) end - - -- call api function return apifunc(...) end diff --git a/xmake/core/base/scopeinfo.lua b/xmake/core/base/scopeinfo.lua index 7141482bc..26be325eb 100644 --- a/xmake/core/base/scopeinfo.lua +++ b/xmake/core/base/scopeinfo.lua @@ -23,11 +23,12 @@ local scopeinfo = scopeinfo or {} local _instance = _instance or {} -- load modules -local io = require("base/io") -local os = require("base/os") -local path = require("base/path") -local table = require("base/table") -local utils = require("base/utils") +local io = require("base/io") +local os = require("base/os") +local path = require("base/path") +local table = require("base/table") +local utils = require("base/utils") +local deprecated = require("base/deprecated") -- new an instance function _instance.new(kind, info, opt) @@ -388,6 +389,9 @@ function _instance:_api_del_paths(name, ...) -- expand values values = table.join(...) + -- it has been marked as deprecated + deprecated.add("remove_" .. name .. "(%s)", "del_" .. name .. "(%s)", table.concat(values, ", "), table.concat(values, ", ")) + -- translate paths local paths = interp:_api_translate_paths(values, "del_" .. name, 5) -- cgit v1.3.1 From 86d94894f74e054bd170c7074b96f748ab81ed0e Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Dec 2021 22:49:53 +0800 Subject: add remove_headerfies --- xmake/core/project/target.lua | 88 ++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 35 deletions(-) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 68073187b..3541aa626 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -1342,8 +1342,7 @@ function _instance:sourcefiles() -- remove all source files which need be removed if removed_count > 0 then - for i = #sourcefiles, 1, -1 do - local sourcefile = sourcefiles[i] + table.remove_if(sourcefiles, function (i, sourcefile) for _, removed_file in ipairs(sourcefiles_removed) do local pattern = path.translate(removed_file:gsub("|.*$", "")) if pattern:sub(1, 2):find('%.[/\\]') then @@ -1351,10 +1350,10 @@ function _instance:sourcefiles() end pattern = path.pattern(pattern) if sourcefile:match(pattern) then - table.remove(sourcefiles, i) + return true end end - end + end) end self._SOURCEFILES = sourcefiles @@ -1449,58 +1448,76 @@ function _instance:headerfiles(outputdir, only_deprecated) -- get the source paths and destinate paths local srcheaders = {} local dstheaders = {} + local srcheaders_removed = {} + local removed_count = 0 for _, header in ipairs(table.wrap(headers)) do + -- mark as removed files? + local removed = false + local prefix = "__remove_" + if header:startswith(prefix) then + header = header:sub(#prefix + 1) + removed = true + end + -- get the root directory local rootdir, count = header:gsub("|.*$", ""):gsub("%(.*%)$", "") if count == 0 then rootdir = nil end - -- remove '(' and ')' + -- remove '(' and ')' first local srcpaths = header:gsub("[%(%)]", "") if srcpaths then -- get the source paths srcpaths = os.match(srcpaths) if srcpaths then - - -- add the source headers - table.join2(srcheaders, srcpaths) - - -- get the destinate directories if the install directory exists - if headerdir then - - -- get the prefix directory - local prefixdir = (extrainfo[header] or {}).prefixdir - - -- add the destinate headers - for _, srcpath in ipairs(srcpaths) do - - -- get the destinate directory - local dstdir = headerdir - if prefixdir then - dstdir = path.join(dstdir, prefixdir) - end - - -- the destinate header - local dstheader = nil - if rootdir then - dstheader = path.absolute(path.relative(srcpath, rootdir), dstdir) - else - dstheader = path.join(dstdir, path.filename(srcpath)) + if removed then + removed_count = removed_count + #srcpaths + table.join2(srcheaders_removed, srcpaths) + else + -- add the source headers + table.join2(srcheaders, srcpaths) + + -- get the destinate directories if the install directory exists + if headerdir then + local prefixdir = (extrainfo[header] or {}).prefixdir + for _, srcpath in ipairs(srcpaths) do + local dstdir = headerdir + if prefixdir then + dstdir = path.join(dstdir, prefixdir) + end + local dstheader = nil + if rootdir then + dstheader = path.absolute(path.relative(srcpath, rootdir), dstdir) + else + dstheader = path.join(dstdir, path.filename(srcpath)) + end + table.insert(dstheaders, dstheader) end - assert(dstheader) - - -- add it - table.insert(dstheaders, dstheader) end end end end end - -- ok? + -- remove all header files which need be removed + if removed_count > 0 then + table.remove_if(srcheaders, function (i, srcheader) + for _, removed_file in ipairs(srcheaders_removed) do + local pattern = path.translate(removed_file:gsub("|.*$", "")) + if pattern:sub(1, 2):find('%.[/\\]') then + pattern = pattern:sub(3) + end + pattern = path.pattern(pattern) + if srcheader:match(pattern) then + table.remove(dstheaders, i) + return true + end + end + end) + end return srcheaders, dstheaders end @@ -2045,6 +2062,7 @@ function target.apis() , "target.del_files" -- target.remove_xxx , "target.remove_files" + , "target.remove_headerfiles" } , dictionary = { -- cgit v1.3.1 From 35699384e0ef579b3b5e048bce311b139d3d1660 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Dec 2021 22:50:08 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61bba3c68..8f907817e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * [#1298](https://github.com/xmake-io/xmake/issues/1928): Support vcpkg manifest mode and select version for package/install * [#1896](https://github.com/xmake-io/xmake/issues/1896): Add `python.library` rule to build pybind modules +* [#1939](https://github.com/xmake-io/xmake/issues/1939): Add `remove_files`, `remove_headerfiles` and mark `del_files` as deprecated ### Changes @@ -1179,6 +1180,7 @@ * [#1298](https://github.com/xmake-io/xmake/issues/1928): 支持 vcpkg 清单模式安装包,实现安装包的版本选择 * [#1896](https://github.com/xmake-io/xmake/issues/1896): 添加 `python.library` 规则去构建 pybind 模块,并且支持 soabi +* [#1939](https://github.com/xmake-io/xmake/issues/1939): 添加 `remove_files`, `remove_headerfiles` 并且标记 `del_files` 作为废弃接口 ### 改进 -- cgit v1.3.1 From fc2d6099553595f692864a82c8037fe074ac64c7 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Dec 2021 17:34:43 +0800 Subject: Update target.lua --- xmake/core/project/target.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 3541aa626..837486b06 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -1512,7 +1512,9 @@ function _instance:headerfiles(outputdir, only_deprecated) end pattern = path.pattern(pattern) if srcheader:match(pattern) then - table.remove(dstheaders, i) + if i <= #dstheaders then + table.remove(dstheaders, i) + end return true end end -- cgit v1.3.1 From 0d82f76c3bd485409592b30c98be6b4f43b01a75 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Dec 2021 17:55:50 +0800 Subject: Update driver_modules.lua --- xmake/rules/platform/linux/driver/driver_modules.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index eeed180ad..c22d92cc0 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -130,6 +130,10 @@ module_exit(hello_exit); arch = "arm" elseif target:is_arch("arm64", "arm64-v8a") then arch = "arm64" + elseif target:is_arch("mips") then + arch = "mips" + elseif target:is_arch("ppc", "powerpc") then + arch = "powerpc" end assert(arch, "unknown arch(%s)!", target:arch()) local cc = target:tool("cc") @@ -211,6 +215,10 @@ function load(target) archsubdir = path.join(sdkdir, "arch", "arm") elseif target:is_arch("arm64", "arm64-v8a") then archsubdir = path.join(sdkdir, "arch", "arm64") + elseif target:is_arch("mips") then + archsubdir = path.join(sdkdir, "arch", "mips") + elseif target:is_arch("ppc", "powerpc") then + archsubdir = path.join(sdkdir, "arch", "powerpc") else raise("rule(platform.linux.driver): unsupported arch(%s)!", target:arch()) end -- cgit v1.3.1 From 79a34a0e3309a5afd3ceae10a7853b8fe7e63d11 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Fri, 24 Dec 2021 12:36:44 +0100 Subject: Project/vsxmake: Handle c++latest as stdcpplatest --- xmake/plugins/project/vsxmake/vsproj/Xmake.props | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/plugins/project/vsxmake/vsproj/Xmake.props b/xmake/plugins/project/vsxmake/vsproj/Xmake.props index 5bd30e2f9..8b4b721d0 100644 --- a/xmake/plugins/project/vsxmake/vsproj/Xmake.props +++ b/xmake/plugins/project/vsxmake/vsproj/Xmake.props @@ -95,6 +95,7 @@ stdcpp17 stdcpplatest stdcpplatest + stdcpplatest stdcpp11 stdcpp14 stdcpp17 -- cgit v1.3.1 From fce3e08add943d72d3af8e6e11e8e006585266a3 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Dec 2021 21:46:32 +0800 Subject: Update driver_modules.lua --- xmake/rules/platform/linux/driver/driver_modules.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index c22d92cc0..121f391ba 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -132,7 +132,7 @@ module_exit(hello_exit); arch = "arm64" elseif target:is_arch("mips") then arch = "mips" - elseif target:is_arch("ppc", "powerpc") then + elseif target:is_arch("ppc", "ppc64", "powerpc", "powerpc64") then arch = "powerpc" end assert(arch, "unknown arch(%s)!", target:arch()) @@ -217,7 +217,7 @@ function load(target) archsubdir = path.join(sdkdir, "arch", "arm64") elseif target:is_arch("mips") then archsubdir = path.join(sdkdir, "arch", "mips") - elseif target:is_arch("ppc", "powerpc") then + elseif target:is_arch("ppc", "ppc64", "powerpc", "powerpc64") then archsubdir = path.join(sdkdir, "arch", "powerpc") else raise("rule(platform.linux.driver): unsupported arch(%s)!", target:arch()) -- cgit v1.3.1 From 6ab8485ac0e8bf702cc15a278085e8e1b7e6f6a7 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 24 Dec 2021 22:23:35 +0800 Subject: Update filter.lua --- xmake/core/base/filter.lua | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/xmake/core/base/filter.lua b/xmake/core/base/filter.lua index d7595679c..f0dae3061 100644 --- a/xmake/core/base/filter.lua +++ b/xmake/core/base/filter.lua @@ -171,15 +171,21 @@ function filter:handle(value) value = value:gsub("%%([%$%(%)%%])", function (ch) return escape_table1[ch] end) -- filter the builtin variables - return (value:gsub("%$%((.-)%)", function (variable) - + local values = {} + local variables = {} + value:gsub("%$%((.-)%)", function (variable) + table.insert(variables, variable) + end) + -- we cannot call self:get() in gsub, because it will trigger "attempt to yield a c-call boundary" + for _, variable in ipairs(variables) do -- escape "%$", "%(", "%)", "%%" to "$", "(", ")", "%" - variable = variable:gsub("[\001\002\003\004]", function (ch) return escape_table2[ch] end) - - -- get variable value - return self:get(variable) or "" - - end):gsub("[\001\002\003\004]", function (ch) return escape_table2[ch] end)) + local name = variable:gsub("[\001\002\003\004]", function (ch) return escape_table2[ch] end) + values[variable] = self:get(name) or "" + end + value = value:gsub("%$%((.-)%)", function (variable) + return values[variable] + end) + return value:gsub("[\001\002\003\004]", function (ch) return escape_table2[ch] end) end -- return module: filter -- cgit v1.3.1 From 2166cd042494ecd3ffbad05a43aa336cb04ffd0e Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 26 Dec 2021 21:10:22 +0800 Subject: Update target.lua --- xmake/plugins/show/info/target.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/xmake/plugins/show/info/target.lua b/xmake/plugins/show/info/target.lua index fb99b31e4..7d86329ef 100644 --- a/xmake/plugins/show/info/target.lua +++ b/xmake/plugins/show/info/target.lua @@ -72,8 +72,12 @@ function main(name) cprint(" ${color.dump.string}sourcebatch${clear}(%s): with rule(%s)", sourcebatch.sourcekind, sourcebatch.rulename) for idx, sourcefile in ipairs(sourcebatch.sourcefiles) do cprint(" -> %s", sourcefile) - cprint(" ${dim}-> %s", sourcebatch.objectfiles[idx]) - cprint(" ${dim}-> %s", sourcebatch.dependfiles[idx]) + if sourcebatch.objectfiles then + cprint(" ${dim}-> %s", sourcebatch.objectfiles[idx]) + end + if sourcebatch.dependfiles then + cprint(" ${dim}-> %s", sourcebatch.dependfiles[idx]) + end end end end -- cgit v1.3.1 From 3ec0e76cda0df5be46d4df27c9e4513a3d63bf9e Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 27 Dec 2021 22:43:33 +0800 Subject: improve error tips --- xmake/core/tool/compiler.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xmake/core/tool/compiler.lua b/xmake/core/tool/compiler.lua index bddfea057..4c5b5f7cd 100644 --- a/xmake/core/tool/compiler.lua +++ b/xmake/core/tool/compiler.lua @@ -93,6 +93,7 @@ end -- load compiler tool function compiler._load_tool(sourcekind, target) + print(sourcekind, target:name()) -- get program from target local program, toolname, toolchain_info if target and target.tool then @@ -111,6 +112,9 @@ end -- load the compiler from the given source kind function compiler.load(sourcekind, target) + if not sourcekind then + return nil, "unknown source kind!" + end -- load compiler tool first (with cache) local compiler_tool, program_or_errors = compiler._load_tool(sourcekind, target) -- cgit v1.3.1 From 21e2abe305c819cd292bf6bac4f39f2778279288 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 27 Dec 2021 22:43:38 +0800 Subject: improve ci --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 03df3a38e..ee4c6659e 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -10,7 +10,7 @@ jobs: build: strategy: matrix: - os: [windows-latest, windows-2016] + os: [windows-2022, windows-2019] arch: [x64, x86] runs-on: ${{ matrix.os }} -- cgit v1.3.1 From a64d5808c1c2c8010139216249811545a11d636c Mon Sep 17 00:00:00 2001 From: Chu Date: Mon, 27 Dec 2021 11:48:21 +0800 Subject: add CMakeLists headeronly support --- xmake/plugins/project/cmake/cmakelists.lua | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 12bc5306c..7cbffc699 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -133,6 +133,11 @@ function _add_target_shared(cmakelists, target) cmakelists:print("set_target_properties(%s PROPERTIES LIBRARY_OUTPUT_DIRECTORY \"%s\")", target:name(), _get_unix_path(target:targetdir())) end +-- add target: headeronly +function _add_target_headeronly(cmakelists, target) + cmakelists:print("add_library(%s INTERFACE)", target:name()) +end + -- add target dependencies function _add_target_dependencies(cmakelists, target) local deps = target:get("deps") @@ -658,6 +663,10 @@ function _add_target(cmakelists, target) _add_target_static(cmakelists, target) elseif targetkind == "shared" then _add_target_shared(cmakelists, target) + elseif targetkind == 'headeronly' then + _add_target_headeronly(cmakelists, target) + _add_target_include_directories(cmakelists, target) + return else raise("unknown target kind %s", target:kind()) end -- cgit v1.3.1 From 8eef6fa5a87daf8f9446081e7038758660483b25 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 27 Dec 2021 22:44:18 +0800 Subject: remove unused logs --- xmake/core/tool/compiler.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/xmake/core/tool/compiler.lua b/xmake/core/tool/compiler.lua index 4c5b5f7cd..745453e0f 100644 --- a/xmake/core/tool/compiler.lua +++ b/xmake/core/tool/compiler.lua @@ -93,7 +93,6 @@ end -- load compiler tool function compiler._load_tool(sourcekind, target) - print(sourcekind, target:name()) -- get program from target local program, toolname, toolchain_info if target and target.tool then -- cgit v1.3.1 From 8d9927c1828e9ba50a7620d22a3ad3b40583381e Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 27 Dec 2021 22:48:38 +0800 Subject: restore ci --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index ee4c6659e..03df3a38e 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -10,7 +10,7 @@ jobs: build: strategy: matrix: - os: [windows-2022, windows-2019] + os: [windows-latest, windows-2016] arch: [x64, x86] runs-on: ${{ matrix.os }} -- cgit v1.3.1 From 4d38a848881c9795a98ec32c3baa39f612f27a07 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 27 Dec 2021 22:53:09 +0800 Subject: fix ci --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 03df3a38e..c84eba2cc 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -10,7 +10,7 @@ jobs: build: strategy: matrix: - os: [windows-latest, windows-2016] + os: [windows-latest] arch: [x64, x86] runs-on: ${{ matrix.os }} -- cgit v1.3.1 From 9ae636cf6851650151a0cf9dc19b464262e6116d Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 27 Dec 2021 23:16:28 +0800 Subject: Update windows.yml --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index c84eba2cc..29a630ea3 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -10,7 +10,7 @@ jobs: build: strategy: matrix: - os: [windows-latest] + os: [windows-2019, windows-2022] arch: [x64, x86] runs-on: ${{ matrix.os }} -- cgit v1.3.1 From 82b3bb99bfe8f441d77a07c29c31d4953eebf697 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 27 Dec 2021 23:16:54 +0800 Subject: Update windows_luajit.yml --- .github/workflows/windows_luajit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows_luajit.yml b/.github/workflows/windows_luajit.yml index 8bc06dbf6..f20553055 100644 --- a/.github/workflows/windows_luajit.yml +++ b/.github/workflows/windows_luajit.yml @@ -10,7 +10,7 @@ jobs: build: strategy: matrix: - os: [windows-latest, windows-2016] + os: [windows-2019, windows-2022] arch: [x64, x86] runs-on: ${{ matrix.os }} -- cgit v1.3.1 From 467b48b8320a7392f281a9f80b8428125f4bb96a Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 28 Dec 2021 23:46:31 +0800 Subject: Update find_package.lua --- .../modules/package/manager/vcpkg/find_package.lua | 50 ++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/xmake/modules/package/manager/vcpkg/find_package.lua b/xmake/modules/package/manager/vcpkg/find_package.lua index c28f62b07..e61e56c29 100644 --- a/xmake/modules/package/manager/vcpkg/find_package.lua +++ b/xmake/modules/package/manager/vcpkg/find_package.lua @@ -26,6 +26,42 @@ import("core.project.config") import("core.project.target") import("detect.sdks.find_vcpkgdir") import("package.manager.vcpkg.configurations") +import("package.manager.pkgconfig.find_package", {alias = "find_package_from_pkgconfig"}) + +-- we iterate over each pkgconfig file to extract the required data +function _find_package_from_pkgconfig(pkgconfig_files, opt) + opt = opt or {} + local foundpc = false + local result = {includedirs = {}, linkdirs = {}, links = {}} + for _, pkgconfig_file in ipairs(pkgconfig_files) do + local pkgconfig_dir = path.join(opt.installdir, path.directory(pkgconfig_file)) + local pkgconfig_name = path.basename(pkgconfig_file) + local pcresult = find_package_from_pkgconfig(pkgconfig_name, {configdirs = pkgconfig_dir, linkdirs = opt.linkdirs}) + + -- the pkgconfig file has been parse successfully + if pcresult then + for _, includedir in ipairs(pcresult.includedirs) do + table.insert(result.includedirs, includedir) + end + for _, linkdir in ipairs(pcresult.linkdirs) do + table.insert(result.linkdirs, linkdir) + end + for _, link in ipairs(pcresult.links) do + table.insert(result.links, link) + end + -- version should be the same if a pacman package contains multiples .pc + result.version = pcresult.version + foundpc = true + end + end + + if foundpc == true then + result.includedirs = table.unique(result.includedirs) + result.linkdirs = table.unique(result.linkdirs) + result.links = table.reverse_unique(result.links) + return result + end +end function _find_package(vcpkgdir, name, opt) @@ -65,6 +101,7 @@ function _find_package(vcpkgdir, name, opt) -- save includedirs, linkdirs and links local result = nil + local pkgconfig_files = {} local info = io.readfile(infofile) if info then for _, line in ipairs(info:split('\n')) do @@ -73,6 +110,11 @@ function _find_package(vcpkgdir, name, opt) line = line:lower() end + -- get pkgconfig files + if line:find(triplet .. (mode == "debug" and "/debug" or "") .. "/lib/pkgconfig/", 1, true) and line:endswith(".pc") then + table.insert(pkgconfig_files, line) + end + -- get includedirs if line:endswith("/include/") then result = result or {} @@ -106,6 +148,14 @@ function _find_package(vcpkgdir, name, opt) end end + -- find result from pkgconfig first + if #pkgconfig_files > 0 then + local pkgconfig_result = _find_package_from_pkgconfig(pkgconfig_files, {installdir = installdir, linkdirs = result and result.linkdirs}) + if pkgconfig_result then + result = pkgconfig_result + end + end + -- save version if result then local infoname = path.basename(infofile) -- cgit v1.3.1 From e1ef31c2ab61b06a31adac981cfd67c873b33829 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 28 Dec 2021 23:47:15 +0800 Subject: Update find_package.lua --- xmake/modules/package/manager/pacman/find_package.lua | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/xmake/modules/package/manager/pacman/find_package.lua b/xmake/modules/package/manager/pacman/find_package.lua index fd936af40..c47edaad6 100644 --- a/xmake/modules/package/manager/pacman/find_package.lua +++ b/xmake/modules/package/manager/pacman/find_package.lua @@ -75,7 +75,7 @@ function _find_package_from_list(list, name, pacman, opt) end result.includedirs = table.unique(result.includedirs) result.linkdirs = table.unique(result.linkdirs) - result.links = table.unique(result.links) + result.links = table.reverse_unique(result.links) -- use pacman package version as version local version = try { function() return os.iorunv(pacman.program, {"-Q", name}) end } @@ -115,17 +115,14 @@ function main(name, opt) -- parse package files list local linkdirs = {} - local has_includes = false local pkgconfig_files = {} for _, line in ipairs(list:split('\n', {plain = true})) do line = line:trim():split('%s+')[2] if line:find("/pkgconfig/", 1, true) and line:endswith(".pc") then - pkgconfig_files[path.basename(line)] = line + table.insert(pkgconfig_files, line) end if line:endswith(".so") or line:endswith(".a") or line:endswith(".lib") then table.insert(linkdirs, path.directory(line)) - elseif line:find("/include/", 1, true) and (line:endswith(".h") or line:endswith(".hpp")) then - has_includes = true end end linkdirs = table.unique(linkdirs) @@ -133,7 +130,7 @@ function main(name, opt) -- we iterate over each pkgconfig file to extract the required data local foundpc = false local result = {includedirs = {}, linkdirs = {}, links = {}} - for _, pkgconfig_file in pairs(pkgconfig_files) do + for _, pkgconfig_file in ipairs(pkgconfig_files) do local pkgconfig_dir = path.directory(pkgconfig_file) local pkgconfig_name = path.basename(pkgconfig_file) local pcresult = find_package_from_pkgconfig(pkgconfig_name, {configdirs = pkgconfig_dir, linkdirs = linkdirs}) @@ -158,7 +155,7 @@ function main(name, opt) if foundpc == true then result.includedirs = table.unique(result.includedirs) result.linkdirs = table.unique(result.linkdirs) - result.links = table.unique(result.links) + result.links = table.reverse_unique(result.links) else -- if there is no .pc, we parse the package content to obtain the data we want result = _find_package_from_list(list, name, pacman, opt) -- cgit v1.3.1 From 70e03f735c6f27e5e0d97c2c0bbeb03d239a6574 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Dec 2021 22:30:38 +0800 Subject: improve toolchain and linux driver --- xmake/core/project/target.lua | 12 ++++++++++-- xmake/core/tool/toolchain.lua | 2 +- xmake/rules/platform/linux/driver/driver_modules.lua | 3 +++ xmake/rules/platform/linux/driver/xmake.lua | 3 +++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 837486b06..88c3197eb 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -273,6 +273,11 @@ function _instance:_invalidate(name) end end +-- is loaded? +function _instance:_is_loaded() + return self._LOADED +end + -- get the target info -- -- e.g. @@ -649,7 +654,7 @@ end -- get target deps function _instance:deps() - if not self._LOADED then + if not self:_is_loaded() then os.raise("please call target:deps() or target:dep() in after_load()!") end return self._DEPS @@ -657,7 +662,7 @@ end -- get target ordered deps function _instance:orderdeps() - if not self._LOADED then + if not self:_is_loaded() then os.raise("please call target:orderdeps() in after_load()!") end return self._ORDERDEPS @@ -1941,6 +1946,9 @@ end -- get the program and name of the given tool kind function _instance:tool(toolkind) + if not self:_is_loaded() then + os.raise("we cannot get tool(%s) before target(%s) is loaded, maybe it is called on_load() now.", toolkind, self:name()) + end return toolchain.tool(self:toolchains(), toolkind, {cachekey = "target_" .. self:name(), plat = self:plat(), arch = self:arch(), before_get = function() -- get program from set_toolchain/set_tools (deprecated) diff --git a/xmake/core/tool/toolchain.lua b/xmake/core/tool/toolchain.lua index 782b004cd..f4a511f0f 100644 --- a/xmake/core/tool/toolchain.lua +++ b/xmake/core/tool/toolchain.lua @@ -185,7 +185,7 @@ end -- get the program and name of the given tool kind function _instance:tool(toolkind) -- ensure to do load for initializing toolset first - self:check() + -- @note we cannot call self:check() here, because it can only be called on config self:_load() local toolpaths = self:get("toolset." .. toolkind) if toolpaths then diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 121f391ba..b9c48e163 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -192,6 +192,9 @@ function load(target) -- we need only need binary kind, because we will rewrite on_link target:set("kind", "binary") target:set("extension", ".ko") +end + +function config(target) -- get and save linux-headers sdk local linux_headers = _get_linux_headers_sdk(target) diff --git a/xmake/rules/platform/linux/driver/xmake.lua b/xmake/rules/platform/linux/driver/xmake.lua index 78ba6d089..8192b9a7f 100644 --- a/xmake/rules/platform/linux/driver/xmake.lua +++ b/xmake/rules/platform/linux/driver/xmake.lua @@ -24,6 +24,9 @@ rule("platform.linux.driver") on_load(function (target) import("driver_modules").load(target) end) + on_config(function (target) + import("driver_modules").config(target) + end) on_link(function (target, opt) import("driver_modules").link(target, opt) end) -- cgit v1.3.1 From 8f8ab64567127d96af6bc7321633d157916e1c97 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Dec 2021 22:31:15 +0800 Subject: fix linux driver --- xmake/rules/platform/linux/driver/driver_modules.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index b9c48e163..f5e5ecc69 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -147,7 +147,7 @@ module_exit(hello_exit); if line:endswith("stub.c") then for _, cflag in ipairs(line:split("%s+")) do if cflag:startswith("-f") or cflag:startswith("-m") - or (cflag:startswith("-W") and not cflag:startswith("-Wp,-MMD,")) + or (cflag:startswith("-W") and not cflag:startswith("-Wp,-MMD,") and not cflag:startswith("-Wp,-MD,")) or (cflag:startswith("-D") and not cflag:startswith("-DKBUILD_")) then cflags = cflags or {} table.insert(cflags, cflag) -- cgit v1.3.1 From 66c17b716042be1c7d21c407a321cb4894924da5 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Dec 2021 22:35:22 +0800 Subject: improve tools/meson --- xmake/modules/package/tools/meson.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xmake/modules/package/tools/meson.lua b/xmake/modules/package/tools/meson.lua index e4fa993ff..b7a396a02 100644 --- a/xmake/modules/package/tools/meson.lua +++ b/xmake/modules/package/tools/meson.lua @@ -25,6 +25,7 @@ import("core.tool.toolchain") import("core.tool.linker") import("core.tool.compiler") import("package.tools.ninja") +import("lib.detect.find_tool") -- get build directory function _get_buildir(package, opt) @@ -153,6 +154,10 @@ function buildenvs(package) envs.SHFLAGS = table.concat(shflags, ' ') if package:is_plat("windows") then envs = os.joinenvs(envs, _get_msvc_runenvs(package)) + local pkgconf = find_tool("pkgconf") + if pkgconf then + envs.PKG_CONFIG = pkgconf.program + end end else local cflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cflags")) -- cgit v1.3.1 From 200fc56af3e51e081a306f91bc749619c298750b Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Dec 2021 17:47:50 +0800 Subject: Update meson.lua --- xmake/modules/package/tools/meson.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/modules/package/tools/meson.lua b/xmake/modules/package/tools/meson.lua index b7a396a02..0ee1839b6 100644 --- a/xmake/modules/package/tools/meson.lua +++ b/xmake/modules/package/tools/meson.lua @@ -127,7 +127,7 @@ function _get_ldflags_from_packagedeps(package, opt) end -- get the build environments -function buildenvs(package) +function buildenvs(package, opt) local envs = {} opt = opt or {} if package:is_plat(os.host()) then @@ -232,7 +232,7 @@ function generate(package, configs, opt) end -- do configure - os.vrunv("meson", argv, {envs = opt.envs or buildenvs(package)}) + os.vrunv("meson", argv, {envs = opt.envs or buildenvs(package, opt)}) end -- build package -- cgit v1.3.1 From 89a293330a83de932ddc114407e1fe051c80f61f Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 30 Dec 2021 00:51:51 +0800 Subject: improve pkgconfig --- xmake/modules/private/action/require/impl/actions/install.lua | 11 ++++++++--- xmake/modules/target/action/install/pkgconfig_importfiles.lua | 10 +++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/xmake/modules/private/action/require/impl/actions/install.lua b/xmake/modules/private/action/require/impl/actions/install.lua index fac545f8e..cbe836ed2 100644 --- a/xmake/modules/private/action/require/impl/actions/install.lua +++ b/xmake/modules/private/action/require/impl/actions/install.lua @@ -55,8 +55,11 @@ function _patch_pkgconfig(package) -- get libs local libs = "" + local installdir = package:installdir() for _, linkdir in ipairs(fetchinfo.linkdirs) do - libs = libs .. " -L" .. linkdir + if linkdir ~= path.join(installdir, "lib") then + libs = libs .. " -L" .. (linkdir:gsub("\\", "/")) + end end libs = libs .. " -L${libdir}" for _, link in ipairs(fetchinfo.links) do @@ -69,14 +72,16 @@ function _patch_pkgconfig(package) -- cflags local cflags = "" for _, includedir in ipairs(fetchinfo.includedirs) do - cflags = cflags .. " -I" .. includedir + if includedir ~= path.join(installdir, "include") then + cflags = cflags .. " -I" .. (includedir:gsub("\\", "/")) + end end cflags = cflags .. " -I${includedir}" -- patch a *.pc file local file = io.open(pcfile, 'w') if file then - file:print("prefix=%s", package:installdir()) + file:print("prefix=%s", installdir:gsub("\\", "/")) file:print("exec_prefix=${prefix}") file:print("libdir=${exec_prefix}/lib") file:print("includedir=${prefix}/include") diff --git a/xmake/modules/target/action/install/pkgconfig_importfiles.lua b/xmake/modules/target/action/install/pkgconfig_importfiles.lua index 6954a1bb5..979feaee2 100644 --- a/xmake/modules/target/action/install/pkgconfig_importfiles.lua +++ b/xmake/modules/target/action/install/pkgconfig_importfiles.lua @@ -42,7 +42,9 @@ function main(target, opt) -- get libs local libs = "" for _, linkdir in ipairs(linkdirs) do - libs = libs .. "-L" .. linkdir + if linkdir ~= path.join(installdir, "lib") then + libs = libs .. " -L" .. (linkdir:gsub("\\", "/")) + end end libs = libs .. " -L${libdir}" if not target:is_headeronly() then @@ -54,7 +56,9 @@ function main(target, opt) -- get cflags local cflags = "" for _, includedir in ipairs(includedirs) do - cflags = cflags .. "-I" .. includedir + if includedir ~= path.join(installdir, "include") then + cflags = cflags .. " -I" .. (includedir:gsub("\\", "/")) + end end cflags = cflags .. " -I${includedir}" @@ -64,7 +68,7 @@ function main(target, opt) -- generate a *.pc file local file = io.open(pcfile, 'w') if file then - file:print("prefix=%s", installdir) + file:print("prefix=%s", installdir:gsub("\\", "/")) file:print("exec_prefix=${prefix}") file:print("libdir=${exec_prefix}/lib") file:print("includedir=${prefix}/include") -- cgit v1.3.1 From a1e6b5f22318f8384d0710484706f804abce9c79 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 30 Dec 2021 22:56:30 +0800 Subject: pass cc/ld to tools/xmake --- xmake/modules/package/tools/xmake.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/xmake/modules/package/tools/xmake.lua b/xmake/modules/package/tools/xmake.lua index abcd7fc1e..9bfcffaff 100644 --- a/xmake/modules/package/tools/xmake.lua +++ b/xmake/modules/package/tools/xmake.lua @@ -74,6 +74,13 @@ function _get_configs(package, configs) if toolchain_name then table.insert(configs, "--toolchain=" .. toolchain_name) end + local names = {"ld", "sh", "ar", "cc", "cxx"} + for _, name in ipairs(names) do + local value = get_config(name) + if value ~= nil then + table.insert(configs, "--" .. name .. "=" .. tostring(value)) + end + end else local names = {"ndk", "ndk_sdkver", "vs", "mingw", "ld", "sh", "ar", "cc", "cxx", "mm", "mxx"} for _, name in ipairs(names) do -- cgit v1.3.1 From 9c4ea3fea86df68671b49b05e0dfabef99330db3 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 1 Jan 2022 16:41:02 +0800 Subject: Update driver_modules.lua --- xmake/rules/platform/linux/driver/driver_modules.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index f5e5ecc69..a8e4636aa 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -157,11 +157,13 @@ module_exit(hello_exit); local ldflags = line:match("%-ld (.+) %-o ") or line:match("ld (.+) %-o ") if ldflags then local ko = ldflags:find("-T ", 1, true) - for _, ldflag in ipairs(ldflags:split("%s+")) do - if ko then - if ldflag:startswith("--build-id=") or ldflag:startswith("-T ") then - break + for _, ldflag in ipairs(os.argv(ldflags)) do + if ldflag:endswith(".lds") then + if not path.is_absolute(ldflag) then + ldflag = path.absolute(ldflag, sdkdir) end + end + if ko then -- e.g. aarch64-linux-gnu-ld -r -EL -maarch64elf --build-id=sha1 -T scripts/module.lds -o hello.ko hello.o hello.mod.o ldflags_ko = ldflags_ko or {} table.insert(ldflags_ko, ldflag) @@ -268,14 +270,12 @@ function link(target, opt) progress.show(opt.progress, "${color.build.object}linking.$(mode) %s", targetfile) -- get module scripts - local modpost, ldscriptfile + local modpost local linux_headers = target:data("linux.driver.linux_headers") if linux_headers then modpost = path.join(linux_headers.sdkdir, "scripts", "mod", "modpost") - ldscriptfile = path.join(linux_headers.sdkdir, "scripts", "module.lds") end assert(modpost and os.isfile(modpost), "scripts/mod/modpost not found!") - assert(ldscriptfile and os.isfile(ldscriptfile), "scripts/module.lds not found!") -- get ld local ld = target:tool("ld") @@ -331,7 +331,7 @@ function link(target, opt) table.join2(argv, ldflags_ko) end local targetfile_o = target:objectfile(targetfile) - table.join2(argv, "--build-id=sha1", "-T", ldscriptfile, "-o", targetfile, targetfile_o, targetfile_mod_o) + table.join2(argv, "-o", targetfile, targetfile_o, targetfile_mod_o) os.mkdir(path.directory(targetfile)) os.vrunv(ld, argv) -- cgit v1.3.1 From 71c25db86af0945af538f3becf1587adabfd06b7 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 1 Jan 2022 16:47:53 +0800 Subject: Update xmake.lua --- xmake/actions/global/xmake.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/actions/global/xmake.lua b/xmake/actions/global/xmake.lua index b98305418..4c4abd06c 100644 --- a/xmake/actions/global/xmake.lua +++ b/xmake/actions/global/xmake.lua @@ -49,6 +49,7 @@ task("global") return import("core.theme.theme.names")() end} , {nil, "debugger", "kv", "auto" , "The debugger program path." } + , {nil, "ccache", "kv", nil , "Enable or disable the c/c++ compiler cache." } , {category = "Build Configuration"} , {nil, "build_warning", "kv", nil , "Enable the warnings output by default when building." } , {nil, "cachedir", "kv", nil , "The global cache directory." } -- cgit v1.3.1 From 6332548fd3948b25a5287b244d7f93471684bf40 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 1 Jan 2022 16:59:24 +0800 Subject: format global options --- xmake/actions/global/xmake.lua | 109 +++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 64 deletions(-) diff --git a/xmake/actions/global/xmake.lua b/xmake/actions/global/xmake.lua index 4c4abd06c..9765412a0 100644 --- a/xmake/actions/global/xmake.lua +++ b/xmake/actions/global/xmake.lua @@ -18,80 +18,61 @@ -- @file xmake.lua -- --- define task task("global") - - -- set category set_category("action") - - -- on run on_run("main") - - -- set menu set_menu { - -- usage - usage = "xmake global|g [options] [target]" - - -- description - , description = "Configure the global options for xmake." - - -- xmake g - , shortname = 'g' - - -- options - , options = - { - {'c', "clean", "k" , nil , "Clean the cached configure and configure all again." } - , {nil, "menu", "k" , nil , "Configure with a menu-driven user interface." } - , {category = "."} - , {nil, "theme", "kv", "default" , "The theme name." - , values = function () - return import("core.theme.theme.names")() - end} - , {nil, "debugger", "kv", "auto" , "The debugger program path." } - , {nil, "ccache", "kv", nil , "Enable or disable the c/c++ compiler cache." } - , {category = "Build Configuration"} - , {nil, "build_warning", "kv", nil , "Enable the warnings output by default when building." } - , {nil, "cachedir", "kv", nil , "The global cache directory." } + usage = "xmake global|g [options] [target]", + description = "Configure the global options for xmake.", + shortname = 'g', + options = { + {'c', "clean", "k" , nil , "Clean the cached configure and configure all again." }, + {nil, "menu", "k" , nil , "Configure with a menu-driven user interface." }, + {category = "."}, + {nil, "theme", "kv", "default" , "The theme name." + , values = function () + return import("core.theme.theme.names")() + end}, + {nil, "debugger", "kv", "auto" , "The debugger program path." }, + {nil, "ccache", "kv", nil , "Enable or disable the c/c++ compiler cache." }, + {category = "Build Configuration"}, + {nil, "build_warning", "kv", nil , "Enable the warnings output by default when building." }, + {nil, "cachedir", "kv", nil , "The global cache directory." }, -- network configuration - , {category = "Network Configuration"} - , {nil, "network", "kv", "public" , "Set the network mode." - , values = {"public", "private"} } - , {'x', "proxy", "kv", nil , "Use proxy on given port. [protocol://]host[:port]" - , " e.g." - , " - xmake g --proxy='http://host:port'" - , " - xmake g --proxy='https://host:port'" - , " - xmake g --proxy='socks5://host:port'" } - , {nil, "proxy_hosts", "kv", nil , "Only enable proxy for the given hosts list, it will enable all if be unset," - , "and we can pass match pattern to list:" - , " e.g." - , " - xmake g --proxy_hosts='github.com,gitlab.*,*.xmake.io'"} - , {nil, "proxy_pac", "kv", "pac.lua" , "Set the auto proxy configuration file." - , " e.g." - , " - xmake g --proxy_pac=pac.lua (in $(globaldir) or absolute path)" - , " - function main(url, host)" - , " if host == 'github.com' then" - , " return true" - , " end" - , " end"} + {category = "Network Configuration"}, + {nil, "network", "kv", "public" , "Set the network mode." + , values = {"public", "private"} }, + {'x', "proxy", "kv", nil , "Use proxy on given port. [protocol://]host[:port]" + , " e.g." + , " - xmake g --proxy='http://host:port'" + , " - xmake g --proxy='https://host:port'" + , " - xmake g --proxy='socks5://host:port'" }, + {nil, "proxy_hosts", "kv", nil , "Only enable proxy for the given hosts list, it will enable all if be unset," + , "and we can pass match pattern to list:" + , " e.g." + , " - xmake g --proxy_hosts='github.com,gitlab.*,*.xmake.io'"}, + {nil, "proxy_pac", "kv", "pac.lua" , "Set the auto proxy configuration file." + , " e.g." + , " - xmake g --proxy_pac=pac.lua (in $(globaldir) or absolute path)" + , " - function main(url, host)" + , " if host == 'github.com' then" + , " return true" + , " end" + , " end"}, -- package configuration - , {category = "Package Configuration"} - , {nil, "pkg_searchdirs", "kv", nil , "The search directories of the remote package." - , " e.g." - , " - xmake g --pkg_searchdirs=/dir1" .. path.envsep() .. "/dir2"} - , {nil, "pkg_installdir", "kv", nil , "The install root directory of the remote package." } + {category = "Package Configuration"}, + {nil, "pkg_searchdirs", "kv", nil , "The search directories of the remote package." + , " e.g." + , " - xmake g --pkg_searchdirs=/dir1" .. path.envsep() .. "/dir2"}, + {nil, "pkg_installdir", "kv", nil , "The install root directory of the remote package."}, -- show platform menu options - , {category = "Platform Configuration"} - , function () - - -- import platform menu - import("core.platform.menu") - - -- get global menu options - return menu.options("global") + {category = "Platform Configuration"}, + function () + import("core.platform.menu") + return menu.options("global") end } } -- cgit v1.3.1 From 57c342168e37e909741012bb03adfb18f91a10d5 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 2 Jan 2022 10:32:22 +0800 Subject: fix linux driver for kernel 4.x --- xmake/rules/platform/linux/driver/driver_modules.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index a8e4636aa..8d46c8c55 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -99,8 +99,11 @@ function _get_cflags_from_make(target, sdkdir) local make = assert(find_tool("make"), "make not found!") local tmpdir = os.tmpfile() .. ".dir" local makefile = path.join(tmpdir, "Makefile") - local stubfile = path.join(tmpdir, "stub.c") - io.writefile(makefile, "obj-m := stub.o") + local stubfile = path.join(tmpdir, "src/stub.c") + local foofile = path.join(tmpdir, "src/foo.c") + io.writefile(makefile, [[obj-m := stub.o +stub-objs := src/stub.o src/foo.o]]) + io.writefile(foofile, "") io.writefile(stubfile, [[ #include #include -- cgit v1.3.1 From 2027d01c63ca2c341847664c8abf3ff2cb74085e Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 2 Jan 2022 16:20:03 +0800 Subject: improve driver modules --- xmake/rules/platform/linux/driver/driver_modules.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 8d46c8c55..e9fd394e4 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -126,7 +126,7 @@ module_init(hello_init); module_exit(hello_exit); ]]) local argv = {"-C", sdkdir, "V=1", "M=" .. tmpdir, "modules"} - if target:is_plat("cross") then + if not target:is_plat(os.subhost()) then -- e.g. $(MAKE) -C $(KERN_DIR) V=1 ARCH=arm64 CROSS_COMPILE=/mnt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- M=$(PWD) modules local arch if target:is_arch("arm", "armv7") then -- cgit v1.3.1 From 833a6f50a0ce17cc88049c81691eb9e32483fe6b Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 2 Jan 2022 22:19:48 +0800 Subject: improve to find vs from wdk directory --- xmake/modules/detect/sdks/find_vstudio.lua | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/xmake/modules/detect/sdks/find_vstudio.lua b/xmake/modules/detect/sdks/find_vstudio.lua index 0d3d98f2c..12feceaad 100644 --- a/xmake/modules/detect/sdks/find_vstudio.lua +++ b/xmake/modules/detect/sdks/find_vstudio.lua @@ -19,6 +19,7 @@ -- -- imports +import("core.project.config") import("lib.detect.find_file") import("lib.detect.find_tool") @@ -304,7 +305,18 @@ function main(opt) if not vcvarsall then -- find vs from some logical drives paths paths = {} - for _, logical_drive in ipairs(winos.logical_drives()) do + local logical_drives = winos.logical_drives() + -- we attempt to find vs from wdk directory + -- wdk: E:\Program Files\Windows Kits\10 + -- vcvarsall: E:\Program Files\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build + local wdk = config.get("wdk") + if wdk and os.isdir(wdk) then + local p = wdk:find("Program Files") + if p then + table.insert(logical_drives, wdk:sub(1, p - 1)) + end + end + for _, logical_drive in ipairs(logical_drives) do if os.isdir(path.join(logical_drive, "Program Files (x86)")) then table.insert(paths, path.join(logical_drive, "Program Files (x86)", "Microsoft Visual Studio", vsvers[version], "*", "VC", "Auxiliary", "Build")) table.insert(paths, path.join(logical_drive, "Program Files (x86)", "Microsoft Visual Studio " .. version, "VC")) -- cgit v1.3.1 From 77b107604093b5a905df60092f92e20f380f084b Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 4 Jan 2022 13:40:51 +0800 Subject: improve to find qt 6.x --- xmake/modules/detect/sdks/find_qt.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xmake/modules/detect/sdks/find_qt.lua b/xmake/modules/detect/sdks/find_qt.lua index da98cd074..9c9cf43f0 100644 --- a/xmake/modules/detect/sdks/find_qt.lua +++ b/xmake/modules/detect/sdks/find_qt.lua @@ -35,7 +35,10 @@ function _find_sdkdir(sdkdir, sdkver) table.insert(subdirs, path.join(sdkver or "*", is_arch("x86_64") and "gcc_64" or "gcc_32", "bin")) table.insert(subdirs, path.join(sdkver or "*", is_arch("x86_64") and "clang_64" or "clang_32", "bin")) elseif is_plat("macosx") then + table.insert(subdirs, path.join(sdkver or "*", "macos", "bin")) -- for Qt 6.x table.insert(subdirs, path.join(sdkver or "*", is_arch("x86_64") and "clang_64" or "clang_32", "bin")) + elseif is_plat("iphoneos") then + table.insert(subdirs, path.join(sdkver or "*", "ios", "bin")) elseif is_plat("windows") then local vs = config.get("vs") if vs then -- cgit v1.3.1 From 001af5a8122223a2cacc514525f72aa5f853ab82 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 4 Jan 2022 23:27:22 +0800 Subject: improve to use qt libexec and bindir --- xmake/modules/detect/sdks/find_qt.lua | 27 +++++++++++++++++++++------ xmake/rules/qt/deploy/android.lua | 3 +++ xmake/rules/qt/moc/xmake.lua | 3 +++ xmake/rules/qt/qrc/xmake.lua | 3 +++ xmake/rules/qt/ui/xmake.lua | 3 +++ 5 files changed, 33 insertions(+), 6 deletions(-) diff --git a/xmake/modules/detect/sdks/find_qt.lua b/xmake/modules/detect/sdks/find_qt.lua index 9c9cf43f0..202b52d88 100644 --- a/xmake/modules/detect/sdks/find_qt.lua +++ b/xmake/modules/detect/sdks/find_qt.lua @@ -35,7 +35,7 @@ function _find_sdkdir(sdkdir, sdkver) table.insert(subdirs, path.join(sdkver or "*", is_arch("x86_64") and "gcc_64" or "gcc_32", "bin")) table.insert(subdirs, path.join(sdkver or "*", is_arch("x86_64") and "clang_64" or "clang_32", "bin")) elseif is_plat("macosx") then - table.insert(subdirs, path.join(sdkver or "*", "macos", "bin")) -- for Qt 6.x + table.insert(subdirs, path.join(sdkver or "*", "macos", "bin")) -- for Qt 6.2 table.insert(subdirs, path.join(sdkver or "*", is_arch("x86_64") and "clang_64" or "clang_32", "bin")) elseif is_plat("iphoneos") then table.insert(subdirs, path.join(sdkver or "*", "ios", "bin")) @@ -123,11 +123,7 @@ end -- find qmake function _find_qmake(sdkdir, sdkver) - - -- find qt directory sdkdir = _find_sdkdir(sdkdir, sdkver) - - -- get the bin directory local qmake = find_tool("qmake", {paths = sdkdir and path.join(sdkdir, "bin")}) if qmake then return qmake.program @@ -178,7 +174,26 @@ function _find_qt(sdkdir, sdkver) local pluginsdir = qtenvs.QT_INSTALL_PLUGINS local includedir = qtenvs.QT_INSTALL_HEADERS local mkspecsdir = qtenvs.QMAKE_MKSPECS or path.join(qtenvs.QT_INSTALL_ARCHDATA, "mkspecs") - return {sdkdir = sdkdir, bindir = bindir, libexecdir = libexecdir, libdir = libdir, includedir = includedir, qmldir = qmldir, pluginsdir = pluginsdir, mkspecsdir = mkspecsdir, sdkver = sdkver} + -- for 6.2 + local bindir_host + if libexecdir and is_plat("android", "iphoneos") then + local rootdir = path.directory(path.directory(bindir)) + if is_host("macosx") then + bindir_host = path.join(rootdir, "macos", "bin") + else + -- TODO + end + end + local libexecdir_host + if libexecdir and is_plat("android", "iphoneos") then + local rootdir = path.directory(path.directory(libexecdir)) + if is_host("macosx") then + libexecdir_host = path.join(rootdir, "macos", "libexec") + else + -- TODO + end + end + return {sdkdir = sdkdir, bindir = bindir, bindir_host = bindir_host, libexecdir = libexecdir, libexecdir_host = libexecdir_host, libdir = libdir, includedir = includedir, qmldir = qmldir, pluginsdir = pluginsdir, mkspecsdir = mkspecsdir, sdkver = sdkver} end -- find qt sdk toolchains diff --git a/xmake/rules/qt/deploy/android.lua b/xmake/rules/qt/deploy/android.lua index c1cad3b54..8076671e6 100644 --- a/xmake/rules/qt/deploy/android.lua +++ b/xmake/rules/qt/deploy/android.lua @@ -71,6 +71,9 @@ function main(target, opt) -- get androiddeployqt local androiddeployqt = path.join(qt.bindir, "androiddeployqt" .. (is_host("windows") and ".exe" or "")) + if not os.isexec(androiddeployqt) and qt.bindir_host then + androiddeployqt = path.join(qt.bindir_host, "androiddeployqt" .. (is_host("windows") and ".exe" or "")) + end assert(os.isexec(androiddeployqt), "androiddeployqt not found!") -- get working directory diff --git a/xmake/rules/qt/moc/xmake.lua b/xmake/rules/qt/moc/xmake.lua index 80ce37174..f12fcf217 100644 --- a/xmake/rules/qt/moc/xmake.lua +++ b/xmake/rules/qt/moc/xmake.lua @@ -32,6 +32,9 @@ rule("qt.moc") if not os.isexec(moc) and qt.libexecdir then moc = path.join(qt.libexecdir, is_host("windows") and "moc.exe" or "moc") end + if not os.isexec(moc) and qt.libexecdir_host then + moc = path.join(qt.libexecdir_host, is_host("windows") and "moc.exe" or "moc") + end assert(moc and os.isexec(moc), "moc not found!") -- get c++ source file for moc diff --git a/xmake/rules/qt/qrc/xmake.lua b/xmake/rules/qt/qrc/xmake.lua index df416c2a9..64e37d2ab 100644 --- a/xmake/rules/qt/qrc/xmake.lua +++ b/xmake/rules/qt/qrc/xmake.lua @@ -29,6 +29,9 @@ rule("qt.qrc") if not os.isexec(rcc) and qt.libexecdir then rcc = path.join(qt.libexecdir, is_host("windows") and "rcc.exe" or "rcc") end + if not os.isexec(rcc) and qt.libexecdir_host then + rcc = path.join(qt.libexecdir_host, is_host("windows") and "rcc.exe" or "rcc") + end assert(os.isexec(rcc), "rcc not found!") -- save rcc diff --git a/xmake/rules/qt/ui/xmake.lua b/xmake/rules/qt/ui/xmake.lua index dd377563b..2d02a134b 100644 --- a/xmake/rules/qt/ui/xmake.lua +++ b/xmake/rules/qt/ui/xmake.lua @@ -29,6 +29,9 @@ rule("qt.ui") if not os.isexec(uic) and qt.libexecdir then uic = path.join(qt.libexecdir, is_host("windows") and "uic.exe" or "uic") end + if not os.isexec(uic) and qt.libexecdir_host then + uic = path.join(qt.libexecdir_host, is_host("windows") and "uic.exe" or "uic") + end assert(uic and os.isexec(uic), "uic not found!") -- add includedirs, @note we need create this directory first to suppress warning (file not found). -- cgit v1.3.1 From 339599e277f031a701dad5aa9690a5db2cf3bc5e Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 4 Jan 2022 16:29:46 +0800 Subject: add qmlimportscanner --- xmake/rules/qt/deploy/android.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/xmake/rules/qt/deploy/android.lua b/xmake/rules/qt/deploy/android.lua index 8076671e6..23c0f5cb8 100644 --- a/xmake/rules/qt/deploy/android.lua +++ b/xmake/rules/qt/deploy/android.lua @@ -162,6 +162,14 @@ function main(target, opt) settings_file:print(' "ndk-host": "%s",', ndk_host) settings_file:print(' "target-architecture": "%s",', target_arch) settings_file:print(' "qml-root-path": "%s",', _escape_path(os.projectdir())) + -- for 6.2.x + local qmlimportscanner = path.join(qt.libexecdir, "qmlimportscanner" .. (is_host("windows") and "moc.exe" or "moc")) + if not os.isexec(qmlimportscanner) and qt.libexecdir_host then + qmlimportscanner = path.join(qt.libexecdir_host, "qmlimportscanner" .. (is_host("windows") and "moc.exe" or "moc")) + end + if os.isexec(qmlimportscanner) then + settings_file:print(' "qml-importscanner-binary": "%s",', qmlimportscanner) + end if android_srcs then settings_file:print(' "android-package-source-directory": "%s",', _escape_path(android_srcs)) --settings_file:print(' "android-extra-libs":"c:/libs",') -- cgit v1.3.1 From c3c7109c9a4a8b836af5f147ea38fb10b597ec70 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 4 Jan 2022 23:54:27 +0800 Subject: improve qt deploy for android --- xmake/rules/qt/deploy/android.lua | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/xmake/rules/qt/deploy/android.lua b/xmake/rules/qt/deploy/android.lua index 23c0f5cb8..e51723d2c 100644 --- a/xmake/rules/qt/deploy/android.lua +++ b/xmake/rules/qt/deploy/android.lua @@ -123,18 +123,6 @@ function main(target, opt) os.cp(target:targetfile(), path.join(android_buildir, "libs", target_arch, path.filename(target:targetfile()))) end - -- get the android srcs directory, e.g. android-build/java/res/values - local android_srcs - if qt_sdkver and qt_sdkver:ge("5.14") then - -- @note we need patch values/res/strings.xml for Qt 5.14.0 - local valuesdir = path.join(android_buildir, "java", "res", "values") - if not os.isdir(valuesdir) then - os.mkdir(valuesdir) - end - os.cp(path.join(qt.sdkdir, "src", "android", "java", "res", "values", "*"), valuesdir) - android_srcs = path.join(android_buildir, "java") - end - -- get stdcpp path local stdcpp_path = path.join(ndk, "sources/cxx-stl/llvm-libc++/libs", target_arch, "libc++_shared.so") if qt_sdkver and qt_sdkver:ge("5.14") then @@ -163,17 +151,16 @@ function main(target, opt) settings_file:print(' "target-architecture": "%s",', target_arch) settings_file:print(' "qml-root-path": "%s",', _escape_path(os.projectdir())) -- for 6.2.x - local qmlimportscanner = path.join(qt.libexecdir, "qmlimportscanner" .. (is_host("windows") and "moc.exe" or "moc")) + local qmlimportscanner = path.join(qt.libexecdir, "qmlimportscanner" .. (is_host("windows") and ".exe" or "")) if not os.isexec(qmlimportscanner) and qt.libexecdir_host then - qmlimportscanner = path.join(qt.libexecdir_host, "qmlimportscanner" .. (is_host("windows") and "moc.exe" or "moc")) + qmlimportscanner = path.join(qt.libexecdir_host, "qmlimportscanner" .. (is_host("windows") and ".exe" or "")) end if os.isexec(qmlimportscanner) then settings_file:print(' "qml-importscanner-binary": "%s",', qmlimportscanner) end - if android_srcs then - settings_file:print(' "android-package-source-directory": "%s",', _escape_path(android_srcs)) - --settings_file:print(' "android-extra-libs":"c:/libs",') - end + -- TODO + -- settings_file:print(' "android-min-sdk-version": "23",') + -- settings_file:print(' "android-target-sdk-version": "30",') settings_file:print(' "useLLVM": true,') if qt_sdkver and qt_sdkver:ge("5.14") then -- @see https://codereview.qt-project.org/c/qt-creator/qt-creator/+/287145 @@ -205,7 +192,6 @@ function main(target, opt) -- do deploy local argv = {"--input", android_deployment_settings, "--output", android_buildir, - "--android-platform", android_platform, "--jdk", java_home, "--gradle", "--no-gdbserver"} if option.get("verbose") and option.get("diagnosis") then -- cgit v1.3.1 From 0d3d8764a0c676b6e0cf18dbb459680da5c29e05 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 4 Jan 2022 23:55:12 +0800 Subject: improve deploy json --- xmake/rules/qt/deploy/android.lua | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/xmake/rules/qt/deploy/android.lua b/xmake/rules/qt/deploy/android.lua index e51723d2c..326addbc1 100644 --- a/xmake/rules/qt/deploy/android.lua +++ b/xmake/rules/qt/deploy/android.lua @@ -158,9 +158,14 @@ function main(target, opt) if os.isexec(qmlimportscanner) then settings_file:print(' "qml-importscanner-binary": "%s",', qmlimportscanner) end - -- TODO - -- settings_file:print(' "android-min-sdk-version": "23",') - -- settings_file:print(' "android-target-sdk-version": "30",') + local minsdkversion = target:values("qt.android.minsdkversion") + if minsdkversion then + settings_file:print(' "android-min-sdk-version": "%s",', tostring(minsdkversion)) + end + local targetsdkversion = target:values("qt.android.targetsdkversion") + if targetsdkversion then + settings_file:print(' "android-target-sdk-version": "%s",', tostring(targetsdkversion)) + end settings_file:print(' "useLLVM": true,') if qt_sdkver and qt_sdkver:ge("5.14") then -- @see https://codereview.qt-project.org/c/qt-creator/qt-creator/+/287145 -- cgit v1.3.1 From 19c7311b0427ff88cd679a9e75c76f9f686d3c43 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 4 Jan 2022 23:57:23 +0800 Subject: update changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f907817e..820a7278c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ * [#1923](https://github.com/xmake-io/xmake/issues/1923): Improve to build linux driver, support set custom linux-headers path +### Bugs fixed + +* [#1875](https://github.com/xmake-io/xmake/issues/1875): Fix deploy android qt apk issue + ## v2.6.2 ### New features @@ -1186,6 +1190,10 @@ * [#1923](https://github.com/xmake-io/xmake/issues/1923): 改进构建 linux 驱动,支持设置自定义 linux-headers 路径 +### Bugs 修复 + +* [#1875](https://github.com/xmake-io/xmake/issues/1875): 修复部署生成 Android Qt 程序包失败问题 + ## v2.6.2 ### 新特性 -- cgit v1.3.1 From 645c16057e2bc6c643d43af8dc29ccd76b1a480f Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 4 Jan 2022 22:43:33 +0800 Subject: Update main.lua --- xmake/actions/config/main.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xmake/actions/config/main.lua b/xmake/actions/config/main.lua index dcf5986dc..23ef3fe43 100644 --- a/xmake/actions/config/main.lua +++ b/xmake/actions/config/main.lua @@ -316,7 +316,8 @@ force to build in current directory via run `xmake -P .`]], os.projectdir()) -- merge configuration from the given import file local importfile = option.get("import") - if importfile and os.isfile(importfile) then + if importfile then + assert(os.isfile(importfile), "%s not found!", importfile) if config.load(importfile) then options_changed = true end -- cgit v1.3.1 From 6035907b774d2f325bf682b2b3456e52be55cc2d Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 5 Jan 2022 11:23:15 +0800 Subject: improve driver modules --- .../rules/platform/linux/driver/driver_modules.lua | 93 ++++++---------------- 1 file changed, 23 insertions(+), 70 deletions(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index e9fd394e4..69a51d80d 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -51,44 +51,6 @@ function _get_linux_headers_sdk(target) return {version = version, sdkdir = linux_headersdir, includedir = includedir} end --- get c system search include directory of gcc --- --- e.g. gcc -E -Wp,-v -xc /dev/null --- --- ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" --- ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/include-fixed" --- ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include" --- #include "..." search starts here: --- #include <...> search starts here: --- /usr/lib/gcc/x86_64-linux-gnu/10/include <-- we need get it --- /usr/local/include --- /usr/include/x86_64-linux-gnu --- /usr/include --- End of search list. -function _get_gcc_includedir(target) - local key = "gcc.includedir." .. target:plat() .. target:arch() - local includedir = memcache.get("linux.driver", key) - if includedir == nil then - local gcc, toolname = target:tool("cc") - assert(toolname, "gcc") - - local _, result = try {function () return os.iorunv(gcc, {"-E", "-Wp,-v", "-xc", os.nuldev()}) end} - if result then - for _, line in ipairs(result:split("\n", {plain = true})) do - line = line:trim() - if os.isdir(line) then - includedir = line - break - elseif line:startswith("End") then - break - end - end - end - memcache.set("linux.driver", key, includedir or false) - end - return includedir or nil -end - -- get cflags from make function _get_cflags_from_make(target, sdkdir) local key = target:plat() .. target:arch() @@ -148,10 +110,32 @@ module_exit(hello_exit); if result then for _, line in ipairs(result:split("\n", {plain = true})) do if line:endswith("stub.c") then + local include_cflag = false for _, cflag in ipairs(line:split("%s+")) do + local has_cflag = false if cflag:startswith("-f") or cflag:startswith("-m") or (cflag:startswith("-W") and not cflag:startswith("-Wp,-MMD,") and not cflag:startswith("-Wp,-MD,")) or (cflag:startswith("-D") and not cflag:startswith("-DKBUILD_")) then + has_cflag = true + elseif cflag == "-I" or cflag == "-isystem" or cflag == "-include" then + include_cflag = cflag + elseif cflag:startswith("-I") or include_cflag then + local includedir = cflag + if cflag:startswith("-I") then + includedir = cflag:sub(3) + end + if not path.is_absolute(includedir) then + includedir = path.absolute(includedir, sdkdir) + end + if cflag:startswith("-I") then + cflag = "-I" .. includedir + else + cflag = include_cflag .. " " .. includedir + end + has_cflag = true + include_cflag = nil + end + if has_cflag then cflags = cflags or {} table.insert(cflags, cflag) end @@ -213,37 +197,6 @@ function config(target) assert(not target:rule(rulename), "target(%s) is linux driver module, it need not rule(%s)!", target:name(), rulename) end - -- add includedirs - local sdkdir = linux_headers.sdkdir - local includedir = linux_headers.includedir - local archsubdir - if target:is_arch("x86_64", "i386") then - archsubdir = path.join(sdkdir, "arch", "x86") - elseif target:is_arch("arm", "armv7") then - archsubdir = path.join(sdkdir, "arch", "arm") - elseif target:is_arch("arm64", "arm64-v8a") then - archsubdir = path.join(sdkdir, "arch", "arm64") - elseif target:is_arch("mips") then - archsubdir = path.join(sdkdir, "arch", "mips") - elseif target:is_arch("ppc", "ppc64", "powerpc", "powerpc64") then - archsubdir = path.join(sdkdir, "arch", "powerpc") - else - raise("rule(platform.linux.driver): unsupported arch(%s)!", target:arch()) - end - assert(archsubdir, "unknown arch(%s) for linux driver modules!", target:arch()) - local gcc_includedir = _get_gcc_includedir(target) - if gcc_includedir then - target:add("sysincludedirs", gcc_includedir) - end - target:add("includedirs", path.join(archsubdir, "include")) - target:add("includedirs", path.join(archsubdir, "include", "generated")) - target:add("includedirs", includedir) - target:add("includedirs", path.join(archsubdir, "include", "uapi")) - target:add("includedirs", path.join(archsubdir, "include", "generated", "uapi")) - target:add("includedirs", path.join(includedir, "uapi")) - target:add("includedirs", path.join(includedir, "generated", "uapi")) - target:add("cflags", "-include " .. path.join(includedir, "linux", "kconfig.h"), {force = true}) - target:add("cflags", "-include " .. path.join(includedir, "linux", "compiler_types.h"), {force = true}) -- we need disable includedirs from add_packages("linux-headers") if target:pkg("linux-headers") then target:pkg("linux-headers"):set("includedirs", nil) @@ -255,7 +208,7 @@ function config(target) for _, sourcefile in ipairs(target:sourcefiles()) do target:fileconfig_set(sourcefile, {defines = "KBUILD_BASENAME=\"" .. path.basename(sourcefile) .. "\""}) end - local cflags, ldflags_o, ldflags_ko = _get_cflags_from_make(target, sdkdir) + local cflags, ldflags_o, ldflags_ko = _get_cflags_from_make(target, linux_headers.sdkdir) if cflags then target:add("cflags", cflags, {force = true}) target:data_set("linux.driver.ldflags_o", ldflags_o) -- cgit v1.3.1 From c85df33090946d24a5e514778bca7a2cbf2a144a Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 5 Jan 2022 14:38:01 +0800 Subject: improve cuda codegen --- xmake/rules/cuda/gencodes/xmake.lua | 42 ++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/xmake/rules/cuda/gencodes/xmake.lua b/xmake/rules/cuda/gencodes/xmake.lua index e208c1f4f..c7ee45050 100644 --- a/xmake/rules/cuda/gencodes/xmake.lua +++ b/xmake/rules/cuda/gencodes/xmake.lua @@ -34,7 +34,7 @@ rule("cuda.gencodes") -- if no available device is found, no `-gencode` flags will be added -- @seealso xmake/modules/lib/detect/find_cudadevices -- - on_load(function (target) + on_config(function (target) -- imports import("core.platform.platform") @@ -47,14 +47,14 @@ rule("cuda.gencodes") local known_r_archs = hashset.of(20, 30, 32, 35, 37, 50, 52, 53, 60, 61, 62, 70, 72, 75, 80) local function nf_cugencode(archs) - if type(archs) ~= 'string' then + if type(archs) ~= "string" then return nil end archs = archs:trim():lower() - if archs == 'native' then + if archs == "native" then local device = find_cudadevices({ skip_compute_mode_prohibited = true, order_by_flops = true })[1] if device then - return nf_cugencode('sm_' .. device.major .. device.minor) + return nf_cugencode("sm_" .. device.major .. device.minor) end return nil end @@ -68,13 +68,13 @@ rule("cuda.gencodes") end local arch = tonumber(value:sub(#prefix + 1)) or tonumber(value:sub(#prefix + 2)) if arch == nil then - raise("Unknown architecture: " .. value) + raise("unknown architecture: " .. value) end if not know_list:has(arch) then if arch <= table.maxn(know_list:data()) then - raise("Unknown architecture: " .. prefix .. "_" .. arch) + raise("unknown architecture: " .. prefix .. "_" .. arch) else - utils.warning("Unknown architecture: " .. prefix .. "_" .. arch) + utils.warning("unknown architecture: " .. prefix .. "_" .. arch) end end return arch @@ -82,20 +82,20 @@ rule("cuda.gencodes") for _, v in ipairs(archs:split(',')) do local arch = v:trim() - local temp_r_arch = parse_arch(arch, 'sm', known_r_archs) + local temp_r_arch = parse_arch(arch, "sm", known_r_archs) if temp_r_arch then table.insert(r_archs, temp_r_arch) end - local temp_v_arch = parse_arch(arch, 'compute', known_v_archs) + local temp_v_arch = parse_arch(arch, "compute", known_v_archs) if temp_v_arch then if v_arch ~= nil then - raise("More than one virtual architecture is defined in one gpu gencode option: compute_" .. v_arch .. " and compute_" .. temp_v_arch) + raise("more than one virtual architecture is defined in one gpu gencode option: compute_" .. v_arch .. " and compute_" .. temp_v_arch) end v_arch = temp_v_arch end if not (temp_r_arch or temp_v_arch) then - raise("Unknown architecture: " .. arch) + raise("unknown architecture: " .. arch) end end @@ -105,8 +105,9 @@ rule("cuda.gencodes") if #r_archs == 0 then return { - clang = '--cuda-gpu-arch=sm_' .. v_arch - , nvcc = '-gencode arch=compute_' .. v_arch .. ',code=compute_' .. v_arch } + clang = "--cuda-gpu-arch=sm_" .. v_arch, + nvcc = "-gencode arch=compute_" .. v_arch .. ",code=compute_" .. v_arch + } end if v_arch then @@ -118,14 +119,14 @@ rule("cuda.gencodes") local clang_flags = {} for _, r_arch in ipairs(r_archs) do - table.insert(clang_flags, '--cuda-gpu-arch=sm_' .. r_arch) + table.insert(clang_flags, "--cuda-gpu-arch=sm_" .. r_arch) end local nvcc_flags = nil if #r_archs == 1 then - nvcc_flags = '-gencode arch=compute_' .. v_arch .. ',code=sm_' .. r_archs[1] + nvcc_flags = "-gencode arch=compute_" .. v_arch .. ",code=sm_" .. r_archs[1] else - nvcc_flags = '-gencode arch=compute_' .. v_arch .. ',code=[sm_' .. table.concat(r_archs, ',sm_') .. ']' + nvcc_flags = "-gencode arch=compute_" .. v_arch .. ",code=[sm_" .. table.concat(r_archs, ",sm_") .. "]" end return { clang = clang_flags, nvcc = nvcc_flags } @@ -138,13 +139,12 @@ rule("cuda.gencodes") for _, v in ipairs(cugencodes) do local flag = nf_cugencode(v) if flag then - local tool, toolname = platform.tool("cu") - if (toolname or path.basename(tool)) == "nvcc" then - target:add('cuflags', flag.nvcc) + if target:has_tool("cu", "nvcc") then + target:add("cuflags", flag.nvcc) else - target:add('cuflags', flag.clang) + target:add("cuflags", flag.clang) end - target:add('culdflags', flag.nvcc) + target:add("culdflags", flag.nvcc) end end end) -- cgit v1.3.1 From 1d3a6b0e2b4f91d376899c11390f90c7f259b0ca Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 5 Jan 2022 15:29:28 +0800 Subject: Update target.lua --- xmake/core/project/target.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 88c3197eb..8ba375fb3 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -1993,9 +1993,11 @@ end -- end function _instance:has_tool(toolkind, ...) local _, toolname = self:tool(toolkind) - for _, v in ipairs(table.join(...)) do - if v and toolname:find("^" .. v:gsub("%-", "%%-") .. "$") then - return true + if toolname then + for _, v in ipairs(table.join(...)) do + if v and toolname:find("^" .. v:gsub("%-", "%%-") .. "$") then + return true + end end end end -- cgit v1.3.1 From b02472adabaeae71c2ee1d07de5b326960e49993 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 5 Jan 2022 22:13:43 +0800 Subject: Update driver_modules.lua --- xmake/rules/platform/linux/driver/driver_modules.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 69a51d80d..a333f5f6e 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -115,7 +115,7 @@ module_exit(hello_exit); local has_cflag = false if cflag:startswith("-f") or cflag:startswith("-m") or (cflag:startswith("-W") and not cflag:startswith("-Wp,-MMD,") and not cflag:startswith("-Wp,-MD,")) - or (cflag:startswith("-D") and not cflag:startswith("-DKBUILD_")) then + or (cflag:startswith("-D") and not cflag:find("KBUILD_MODNAME=") not cflag:find("KBUILD_BASENAME=")) then has_cflag = true elseif cflag == "-I" or cflag == "-isystem" or cflag == "-include" then include_cflag = cflag -- cgit v1.3.1 From 22573fd1defd7b2b9782f12d39b6a86f90588688 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 5 Jan 2022 22:14:18 +0800 Subject: Update driver_modules.lua --- xmake/rules/platform/linux/driver/driver_modules.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index a333f5f6e..9a8db4871 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -115,7 +115,7 @@ module_exit(hello_exit); local has_cflag = false if cflag:startswith("-f") or cflag:startswith("-m") or (cflag:startswith("-W") and not cflag:startswith("-Wp,-MMD,") and not cflag:startswith("-Wp,-MD,")) - or (cflag:startswith("-D") and not cflag:find("KBUILD_MODNAME=") not cflag:find("KBUILD_BASENAME=")) then + or (cflag:startswith("-D") and not cflag:find("KBUILD_MODNAME=") and not cflag:find("KBUILD_BASENAME=")) then has_cflag = true elseif cflag == "-I" or cflag == "-isystem" or cflag == "-include" then include_cflag = cflag -- cgit v1.3.1 From c942938c04325e6c49d869fce4d15e69c351f516 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 5 Jan 2022 22:42:52 +0800 Subject: Update driver_modules.lua --- xmake/rules/platform/linux/driver/driver_modules.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xmake/rules/platform/linux/driver/driver_modules.lua b/xmake/rules/platform/linux/driver/driver_modules.lua index 9a8db4871..4f2640c83 100644 --- a/xmake/rules/platform/linux/driver/driver_modules.lua +++ b/xmake/rules/platform/linux/driver/driver_modules.lua @@ -117,6 +117,10 @@ module_exit(hello_exit); or (cflag:startswith("-W") and not cflag:startswith("-Wp,-MMD,") and not cflag:startswith("-Wp,-MD,")) or (cflag:startswith("-D") and not cflag:find("KBUILD_MODNAME=") and not cflag:find("KBUILD_BASENAME=")) then has_cflag = true + local macro = cflag:match("%-D\"(.+)\"") -- -D"KBUILD_XXX=xxx" + if macro then + cflag = "-D" .. macro + end elseif cflag == "-I" or cflag == "-isystem" or cflag == "-include" then include_cflag = cflag elseif cflag:startswith("-I") or include_cflag then -- cgit v1.3.1 From 347f53abeb87def97c0e917a5cdebe6e616429ad Mon Sep 17 00:00:00 2001 From: yecate Date: Thu, 6 Jan 2022 12:34:41 +0800 Subject: improve support find visualstudio buildtools --- xmake/modules/detect/sdks/find_vstudio.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xmake/modules/detect/sdks/find_vstudio.lua b/xmake/modules/detect/sdks/find_vstudio.lua index 362a2a705..ca72952a7 100644 --- a/xmake/modules/detect/sdks/find_vstudio.lua +++ b/xmake/modules/detect/sdks/find_vstudio.lua @@ -254,7 +254,8 @@ function main(opt) local vswhere_VCAuxiliaryBuildDir = nil if (tonumber(version) >= 15) and vswhere then local vswhere_vrange = format("%s,%s)", version, (version + 1)) - local result = os.iorunv(vswhere.program, {"-prerelease", "-property", "installationpath", "-version", vswhere_vrange}) + -- build tools: https://github.com/microsoft/vswhere/issues/22 @@ https://aka.ms/vs/workloads + local result = os.iorunv(vswhere.program, {"-products", "*", "-prerelease", "-property", "installationpath", "-version", vswhere_vrange}) if result then vswhere_VCAuxiliaryBuildDir = path.join(result:trim(), "VC", "Auxiliary", "Build") end -- cgit v1.3.1 From 00c8c18e853766905f99759795c4fb9ac74ef467 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Thu, 6 Jan 2022 16:41:07 +0100 Subject: Improve vstudio projects --- xmake/plugins/project/vstudio/impl/vs201x.lua | 3 + .../project/vstudio/impl/vs201x_vcxproj.lua | 129 +++++++++++++++++++-- 2 files changed, 121 insertions(+), 11 deletions(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua index 7b337c867..4c5fc86f8 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x.lua @@ -252,6 +252,9 @@ function _make_targetinfo(mode, arch, target, vcxprojdir) target:set("pcheader", nil) target:set("pcxxheader", nil) + -- save languages + targetinfo.languages = table.wrap(target:get("languages")) + -- save symbols targetinfo.symbols = target:get("symbols") diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index 0d3d06da5..293896f8f 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -241,6 +241,15 @@ function _make_configurations(vcxprojfile, vsinfo, target) if target.kind == "binary" then vcxprojfile:print("true") end + + -- handle ExternalIncludePath (should we handle IncludePath here too?) + local externaldirs = {} + for _, flag in ipairs(targetinfo.commonflags) do + flag:gsub("[%-/]external:I(.*)", function (dir) table.insert(externaldirs, dir) end) + end + if #externaldirs > 0 then + vcxprojfile:print("%s;", table.concat(externaldirs, ";")) + end vcxprojfile:leave("") end @@ -320,6 +329,15 @@ function _make_source_options(vcxprojfile, flags, condition) vcxprojfile:print("false", condition) end + -- make DisableSpecificWarnings + local disabledwarnings = {} + for _, flag in ipairs(flags) do + flag:gsub("[%-/]wd(%d+)", function (warn) table.insert(disabledwarnings, warn) end) + end + if #disabledwarnings > 0 then + vcxprojfile:print("%s;%%(DisableSpecificWarnings)", table.concat(disabledwarnings, ";")) + end + -- make PreprocessorDefinitions local defstr = "" for _, flag in ipairs(flags) do @@ -380,7 +398,11 @@ function _make_source_options(vcxprojfile, flags, condition) -- make AdditionalOptions local additional_flags = {} - local excludes = {"Od", "Os", "O0", "O1", "O2", "Ot", "Ox", "W0", "W1", "W2", "W3", "W4", "WX", "Wall", "Zi", "ZI", "Z7", "MT", "MTd", "MD", "MDd", "TP", "Fd", "fp", "I", "D", "Gm-", "Gm", "MP", "external:W0", "external:W1", "external:W2", "external:W3", "external:W4", "external:templates-", "external:templates" } + local excludes = { + "Od", "Os", "O0", "O1", "O2", "Ot", "Ox", "W0", "W1", "W2", "W3", "W4", "WX", "Wall", "Zi", "ZI", "Z7", "MT", "MTd", "MD", "MDd", "TP", + "Fd", "fp", "I", "D", "Gm-", "Gm", "MP", "external:W0", "external:W1", "external:W2", "external:W3", "external:W4", "external:templates-?", "external:I", + "std:c11", "std:c17", "std:c%+%+11", "std:c%+%+14", "std:c%+%+17", "std:c%+%+20", "std:c%+%+latest", "nologo", "wd(%d+)" + } for _, flag in ipairs(flags) do local excluded = false for _, exclude in ipairs(excludes) do @@ -437,7 +459,7 @@ function _make_custom_commands(vcxprojfile, target) end -- make common item -function _make_common_item(vcxprojfile, vsinfo, target, targetinfo, vcxprojdir) +function _make_common_item(vcxprojfile, vsinfo, target, targetinfo) -- enter ItemDefinitionGroup vcxprojfile:enter("", targetinfo.mode, targetinfo.arch) @@ -458,22 +480,54 @@ function _make_common_item(vcxprojfile, vsinfo, target, targetinfo, vcxprojdir) -- make linker flags local flags = {} - for _, flag in ipairs(_make_linkflags(targetinfo, vcxprojdir)) do + local excludes = { + "nologo", "machine:%w+", "pdb:.+%.pdb", "debug" + } + local libdirs = {} + local links = {} + for _, flag in ipairs(_make_linkflags(targetinfo, target.project_dir)) do local flag_lower = flag:lower() -- remove "-subsystem:windows" if flag_lower:find("[%-/]subsystem:windows") then subsystem = "Windows" - -- remove "-machine:[x86|x64]", "-pdb:*.pdb" and "-debug" - elseif not flag_lower:find("[%-/]machine:%w+") and not flag_lower:find("[%-/]pdb:.+%.pdb") and not flag_lower:find("[%-/]debug") then - table.insert(flags, flag) + elseif flag_lower:find("[%-/]libpath") then + -- link dir + flag:gsub("[%-/]libpath:(.*)", function (dir) table.insert(libdirs, dir) end) + elseif flag_lower:find("[^%-/].+%.lib") then + -- link file + table.insert(links, flag) + else + local excluded = false + for _, exclude in ipairs(excludes) do + if flag:find("[%-/]" .. exclude) then + excluded = true + break + end + end + if not excluded then + table.insert(flags, flag) + end end + + end + + -- make AdditionalLibraryDirectories + if #libdirs > 0 then + vcxprojfile:print("%s;%%(AdditionalLibraryDirectories)", table.concat(libdirs, ";")) + end + + -- make AdditionalDependencies + if #links > 0 then + vcxprojfile:print("%s;%%(AdditionalDependencies)", table.concat(links, ";")) end - flags = os.args(flags) -- make AdditionalOptions - vcxprojfile:print("%s %%(AdditionalOptions)", flags) + if #flags > 0 then + flags = os.args(flags) + vcxprojfile:print("%s %%(AdditionalOptions)", flags) + end -- generate debug infomation? if linkerkinds[targetinfo.targetkind] == "Link" then @@ -506,6 +560,49 @@ function _make_common_item(vcxprojfile, vsinfo, target, targetinfo, vcxprojdir) -- make source options _make_source_options(vcxprojfile, targetinfo.commonflags) + -- add c and c++ standard + local clangflags = { + c11 = "stdc11", + c17 = "stdc17", + clatest = "stdc17", + gnu11 = "stdc11", + gnu17 = "stdc17", + gnulatest = "stdc17", + } + + local cxxlangflags = { + cxx11 = "stdcpp11", + cxx14 = "stdcpp14", + cxx17 = "stdcpp17", + cxx1z = "stdcpp17", + cxx20 = "stdcpp20", + cxx2a = "stdcpplatest", + cxxlatest = "stdcpplatest", + gnuxx11 = "stdcpp11", + gnuxx14 = "stdcpp14", + gnuxx17 = "stdcpp17", + gnuxx1z = "stdcpp20", + gnux20 = "stdcpp20", + gnux2a = "stdcpplatest", + } + + local cstandard + local cxxstandard + for _, lang in pairs(targetinfo.languages) do + if cxxlangflags[lang] then + cxxstandard = cxxlangflags[lang] + elseif clangflags[lang] then + cstandard = clangflags[lang] + end + end + + if cxxstandard then + vcxprojfile:print("%s", cxxstandard) + end + + if cstandard then + vcxprojfile:print("%s", cstandard) + end -- use c or c++ precompiled header local pcheader = target.pcxxheader or target.pcheader @@ -516,7 +613,7 @@ function _make_common_item(vcxprojfile, vsinfo, target, targetinfo, vcxprojdir) vcxprojfile:print("%s", path.filename(pcheader)) local pcoutputfile = targetinfo.pcxxoutputfile or targetinfo.pcoutputfile if pcoutputfile then - vcxprojfile:print("%s", path.relative(path.absolute(pcoutputfile), vcxprojdir)) + vcxprojfile:print("%s", path.relative(path.absolute(pcoutputfile), target.project_dir)) end vcxprojfile:print("%s;%%(ForcedIncludeFiles)", path.filename(pcheader)) end @@ -530,8 +627,8 @@ function _make_common_item(vcxprojfile, vsinfo, target, targetinfo, vcxprojdir) vcxprojfile:leave("") end --- make common items -function _make_common_items(vcxprojfile, vsinfo, target) +-- build common items (doesn't print anything) +function _build_common_items(vsinfo, target) -- for each mode and arch for _, targetinfo in ipairs(target.info) do @@ -590,7 +687,14 @@ function _make_common_items(vcxprojfile, vsinfo, target) sourceflags[sourcefile] = otherflags end targetinfo.sourceflags = sourceflags + end +end + +-- make common items +function _make_common_items(vcxprojfile, vsinfo, target) + -- for each mode and arch + for _, targetinfo in ipairs(target.info) do -- make common item _make_common_item(vcxprojfile, vsinfo, target, targetinfo, target.project_dir) end @@ -843,6 +947,9 @@ function make(vsinfo, target) -- the vcxproj directory local vcxprojdir = target.project_dir + -- build common flags + _build_common_items(vsinfo, target) + -- open vcxproj file local vcxprojpath = path.join(vcxprojdir, targetname .. ".vcxproj") local vcxprojfile = vsfile.open(vcxprojpath, "w") -- cgit v1.3.1 From e57f4688e7fa307a02e5352f392c9946dcd05c42 Mon Sep 17 00:00:00 2001 From: Jérôme Leclercq Date: Thu, 6 Jan 2022 17:11:44 +0100 Subject: Add $(VC_IncludePath);$(WindowsSDK_IncludePath); at the end of --- xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index 293896f8f..2cc84ff52 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -248,7 +248,7 @@ function _make_configurations(vcxprojfile, vsinfo, target) flag:gsub("[%-/]external:I(.*)", function (dir) table.insert(externaldirs, dir) end) end if #externaldirs > 0 then - vcxprojfile:print("%s;", table.concat(externaldirs, ";")) + vcxprojfile:print("%s;$(VC_IncludePath);$(WindowsSDK_IncludePath);", table.concat(externaldirs, ";")) end vcxprojfile:leave("") end -- cgit v1.3.1 From 704332f0dbb224ed4ef0fb6d4096e5eaf9f3e47b Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 7 Jan 2022 22:30:49 +0800 Subject: improve c++ modules --- xmake/core/project/target.lua | 6 ++++-- xmake/rules/c++/modules/xmake.lua | 16 +++++++--------- xmake/rules/c++/openmp/xmake.lua | 4 ++-- xmake/rules/platform/windows/def/xmake.lua | 3 +-- xmake/rules/platform/windows/manifest/xmake.lua | 3 +-- 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 8ba375fb3..9a4ca698c 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -166,6 +166,7 @@ function _instance:_load_after() -- leave the environments of the target packages os.setenvs(oldenvs) + self._LOADED_AFTER = true return true end @@ -1946,8 +1947,9 @@ end -- get the program and name of the given tool kind function _instance:tool(toolkind) - if not self:_is_loaded() then - os.raise("we cannot get tool(%s) before target(%s) is loaded, maybe it is called on_load() now.", toolkind, self:name()) + -- we cannot get tool in on_load, because target:toolchains() has been not checked in configuration stage. + if not self._LOADED_AFTER then + os.raise("we cannot get tool(%s) before target(%s) is loaded, maybe it is called on_load(), please call it in on_config().", toolkind, self:name()) end return toolchain.tool(self:toolchains(), toolkind, {cachekey = "target_" .. self:name(), plat = self:plat(), arch = self:arch(), before_get = function() diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 78f754521..c587a3912 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -21,7 +21,7 @@ -- define rule: c++.build.modules rule("c++.build.modules") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") - after_load(function (target) + on_config(function (target) -- we disable to build across targets in parallel, because the source files may depend on other target modules -- @see https://github.com/xmake-io/xmake/issues/1858 local target_with_modules @@ -38,12 +38,11 @@ rule("c++.build.modules") -- -- maybe we will have a more fine-grained configuration strategy to disable it in the future. target:set("policy", "build.across_targets_in_parallel", false) - local _, toolname = target:tool("cxx") - if toolname:find("clang", 1, true) then + if target:has_tool("cxx", "clang", "clangxx") then import("build_modules.clang").load_parent(target, opt) - elseif toolname:find("gcc", 1, true) then + elseif target:has_tool("cxx", "gcc", "gxx") then import("build_modules.gcc").load_parent(target, opt) - elseif toolname == "cl" then + elseif target:has_tool("cxx", "cl") then import("build_modules.msvc").load_parent(target, opt) else raise("compiler(%s): does not support c++ module!", toolname) @@ -51,12 +50,11 @@ rule("c++.build.modules") end end) before_build_files(function (target, batchjobs, sourcebatch, opt) - local _, toolname = target:tool("cxx") - if toolname:find("clang", 1, true) then + if target:has_tool("cxx", "clang", "clangxx") then import("build_modules.clang").build_with_batchjobs(target, batchjobs, sourcebatch, opt) - elseif toolname:find("gcc", 1, true) then + elseif target:has_tool("cxx", "gcc", "gxx") then import("build_modules.gcc").build_with_batchjobs(target, batchjobs, sourcebatch, opt) - elseif toolname == "cl" then + elseif target:has_tool("cxx", "cl") then import("build_modules.msvc").build_with_batchjobs(target, batchjobs, sourcebatch, opt) else raise("compiler(%s): does not support c++ module!", toolname) diff --git a/xmake/rules/c++/openmp/xmake.lua b/xmake/rules/c++/openmp/xmake.lua index 47dd2d07f..82e3cc562 100644 --- a/xmake/rules/c++/openmp/xmake.lua +++ b/xmake/rules/c++/openmp/xmake.lua @@ -20,12 +20,12 @@ -- define rule: c.openmp rule("c.openmp") - on_load(function (target) + on_config(function (target) import("load")(target, "cc") end) -- define rule: c++.openmp rule("c++.openmp") - on_load(function (target) + on_config(function (target) import("load")(target, "cxx") end) diff --git a/xmake/rules/platform/windows/def/xmake.lua b/xmake/rules/platform/windows/def/xmake.lua index 06e960380..7919553de 100644 --- a/xmake/rules/platform/windows/def/xmake.lua +++ b/xmake/rules/platform/windows/def/xmake.lua @@ -22,8 +22,7 @@ rule("platform.windows.def") set_extensions(".def") on_config("windows", function (target) - local _, toolname = target:tool("ld") - if toolname == "link" then + if target:has_tool("ld", "link") then for _, sourcebatch in pairs(target:sourcebatches()) do if sourcebatch.rulename == "platform.windows.def" then for _, sourcefile in ipairs(sourcebatch.sourcefiles) do diff --git a/xmake/rules/platform/windows/manifest/xmake.lua b/xmake/rules/platform/windows/manifest/xmake.lua index efb750edd..b476faeed 100644 --- a/xmake/rules/platform/windows/manifest/xmake.lua +++ b/xmake/rules/platform/windows/manifest/xmake.lua @@ -23,8 +23,7 @@ rule("platform.windows.manifest") set_extensions(".manifest") on_config("windows", function (target) - local _, toolname = target:tool("ld") - if toolname == "link" then + if target:has_tool("ld", "link") then local manifest = false for _, sourcebatch in pairs(target:sourcebatches()) do if sourcebatch.rulename == "platform.windows.manifest" then -- cgit v1.3.1 From 2414e25c660cda85d3b0831b93460a475e482e32 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 7 Jan 2022 22:31:54 +0800 Subject: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 820a7278c..5978f6445 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * [#1298](https://github.com/xmake-io/xmake/issues/1928): Support vcpkg manifest mode and select version for package/install * [#1896](https://github.com/xmake-io/xmake/issues/1896): Add `python.library` rule to build pybind modules * [#1939](https://github.com/xmake-io/xmake/issues/1939): Add `remove_files`, `remove_headerfiles` and mark `del_files` as deprecated +* Made on_config as the official api for rule/target ### Changes @@ -1185,6 +1186,7 @@ * [#1298](https://github.com/xmake-io/xmake/issues/1928): 支持 vcpkg 清单模式安装包,实现安装包的版本选择 * [#1896](https://github.com/xmake-io/xmake/issues/1896): 添加 `python.library` 规则去构建 pybind 模块,并且支持 soabi * [#1939](https://github.com/xmake-io/xmake/issues/1939): 添加 `remove_files`, `remove_headerfiles` 并且标记 `del_files` 作为废弃接口 +* 将 on_config 作为正式的公开接口,用于 target 和 rule ### 改进 -- cgit v1.3.1 From b5298ce3d6ccade7f651756b4f2627bd78478c36 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 7 Jan 2022 22:35:55 +0800 Subject: remove format from builder/tools --- xmake/core/project/target.lua | 3 +-- xmake/core/tool/builder.lua | 8 -------- xmake/modules/core/tools/go.lua | 18 +++--------------- xmake/rules/go/xmake.lua | 4 ++++ 4 files changed, 8 insertions(+), 25 deletions(-) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 9a4ca698c..be787619b 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -1068,8 +1068,7 @@ function _instance:filename() plat = self:plat(), arch = self:arch(), prefixname = prefixname, suffixname = suffixname, - extension = extension, - format = self:linker():format(targetkind)}) + extension = extension}) end return filename end diff --git a/xmake/core/tool/builder.lua b/xmake/core/tool/builder.lua index 91bb707f8..343eec0ae 100644 --- a/xmake/core/tool/builder.lua +++ b/xmake/core/tool/builder.lua @@ -442,13 +442,5 @@ function builder:map_flags(name, values, opt) end end --- get the format of the given target kind -function builder:format(targetkind) - local formats = self:get("formats") - if formats then - return formats[targetkind] - end -end - -- return module return builder diff --git a/xmake/modules/core/tools/go.lua b/xmake/modules/core/tools/go.lua index 34d096873..2b2b76623 100644 --- a/xmake/modules/core/tools/go.lua +++ b/xmake/modules/core/tools/go.lua @@ -25,18 +25,12 @@ import("core.project.project") -- init it function init(self) - - -- init arflags self:set("gcarflags", "grc") - - -- init the file formats - self:set("formats", { static = "$(name).a" }) end -- make the optimize flag function nf_optimize(self, level) - local maps = - { + local maps = { none = "-N" } return maps[level] @@ -44,15 +38,10 @@ end -- make the symbol flag function nf_symbol(self, level, target, mapkind) - - -- only for compiler if mapkind ~= "object" then return end - - -- the maps - local maps = - { + local maps = { debug = "-E" } return maps[level] @@ -60,8 +49,7 @@ end -- make the strip flag function nf_strip(self, level) - local maps = - { + local maps = { debug = "-s" , all = "-s" } diff --git a/xmake/rules/go/xmake.lua b/xmake/rules/go/xmake.lua index ef6f04321..58890e260 100644 --- a/xmake/rules/go/xmake.lua +++ b/xmake/rules/go/xmake.lua @@ -24,6 +24,10 @@ rule("go.build") on_load(function (target) -- we disable to build across targets in parallel, because the source files may depend on other target modules target:set("policy", "build.across_targets_in_parallel", false) + -- xxx.a + if target:is_static() then + target:set("prefixname", "") + end end) on_build_files("build.object") -- cgit v1.3.1 From 5ff975838378aa395751e719f647b2573ce4c834 Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 7 Jan 2022 11:45:25 +0800 Subject: Update xmake.lua --- xmake/rules/vala/xmake.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/xmake/rules/vala/xmake.lua b/xmake/rules/vala/xmake.lua index 058f68462..6c3d36213 100644 --- a/xmake/rules/vala/xmake.lua +++ b/xmake/rules/vala/xmake.lua @@ -103,6 +103,14 @@ rule("vala.build") table.insert(argv, headerfile) end end + local vapidir = target:data("vala.vapidir") + if vapidir then + table.insert(argv, "--vapidir=" .. vapidir) + end + local valaflags = target:data("vala.flags") + if valaflags then + table.join2(argv, valaflags) + end table.insert(argv, sourcefile_vala) batchcmds:vrunv(valac.program, argv) batchcmds:compile(sourcefile_c, objectfile) -- cgit v1.3.1 From c326af03e11a22b94dd0288d8e40772537074bad Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 7 Jan 2022 14:04:46 +0800 Subject: Update target.lua --- xmake/rules/pascal/build/target.lua | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/xmake/rules/pascal/build/target.lua b/xmake/rules/pascal/build/target.lua index 8d7662055..646474606 100644 --- a/xmake/rules/pascal/build/target.lua +++ b/xmake/rules/pascal/build/target.lua @@ -24,6 +24,7 @@ import("core.base.hashset") import("core.theme.theme") import("core.tool.compiler") import("core.project.depend") +import("utils.progress") -- build the source files function build_sourcefiles(target, sourcebatch, opt) @@ -31,9 +32,6 @@ function build_sourcefiles(target, sourcebatch, opt) -- is verbose? local verbose = option.get("verbose") - -- get progress range - local progress = assert(opt.progress, "no progress!") - -- get the target file local targetfile = target:targetfile() @@ -60,21 +58,13 @@ function build_sourcefiles(target, sourcebatch, opt) end -- trace progress into - cprintf("${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} ", progress) - if verbose then - cprint("${dim color.build.target}linking.$(mode) %s", path.filename(targetfile)) - else - cprint("${color.build.target}linking.$(mode) %s", path.filename(targetfile)) - end + progress.show(opt.progress, "${color.build.target}linking.$(mode) %s", path.filename(targetfile)) -- trace verbose info if verbose then print(compinst:buildcmd(sourcefiles, targetfile, {target = target, compflags = compflags})) end - -- flush io buffer to update progress info - io.flush() - -- compile it dependinfo.files = {} assert(compinst:build(sourcefiles, targetfile, {target = target, dependinfo = dependinfo, compflags = compflags})) -- cgit v1.3.1 From 28fe6eb7c1c68217c2df5d9ee3b818839743e3cc Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 7 Jan 2022 21:44:59 +0800 Subject: improve armclang --- xmake/toolchains/armclang/xmake.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xmake/toolchains/armclang/xmake.lua b/xmake/toolchains/armclang/xmake.lua index 7faf06f0d..46f22a2ba 100644 --- a/xmake/toolchains/armclang/xmake.lua +++ b/xmake/toolchains/armclang/xmake.lua @@ -29,7 +29,7 @@ toolchain("armclang") set_toolset("cxx", "armclang") set_toolset("ld", "armlink") set_toolset("ar", "armar") - set_toolset("as", "armasm") + set_toolset("as", "armclang") on_check(function (toolchain) import("lib.detect.find_tool") @@ -47,7 +47,8 @@ toolchain("armclang") if arch then toolchain:add("cxflags", "-target=arm-arm-none-eabi") toolchain:add("cxflags", "-mcpu=" .. arch:lower()) - toolchain:add("asflags", "--cpu " .. arch) + toolchain:add("asflags", "-target=arm-arm-none-eabi") + toolchain:add("asflags", "-mcpu=" .. arch:lower()) toolchain:add("ldflags", "--cpu " .. arch) end end) -- cgit v1.3.1 From 187da27473c69bd9d7b0009d8d689ec924f16dfb Mon Sep 17 00:00:00 2001 From: ruki Date: Fri, 7 Jan 2022 21:48:58 +0800 Subject: Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5978f6445..952094f40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ ### Changes * [#1923](https://github.com/xmake-io/xmake/issues/1923): Improve to build linux driver, support set custom linux-headers path +* [#1962](https://github.com/xmake-io/xmake/issues/1962): Improve armclang toolchain to support to build asm ### Bugs fixed @@ -1191,6 +1192,7 @@ ### 改进 * [#1923](https://github.com/xmake-io/xmake/issues/1923): 改进构建 linux 驱动,支持设置自定义 linux-headers 路径 +* [#1962](https://github.com/xmake-io/xmake/issues/1962): 改进 armclang 工具链去支持构建 asm ### Bugs 修复 -- cgit v1.3.1 From 4c95d421bd81c9b3279763a84f138f707f642c01 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 8 Jan 2022 10:07:31 +0800 Subject: fix add values --- xmake/core/base/interpreter.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xmake/core/base/interpreter.lua b/xmake/core/base/interpreter.lua index e8e379e08..6f5f0360b 100644 --- a/xmake/core/base/interpreter.lua +++ b/xmake/core/base/interpreter.lua @@ -1059,6 +1059,9 @@ function interpreter:api_register_set_values(scope_kind, ...) extra_config = nil end + -- expand values + values = table.join(table.unpack(values)) + -- save values if #values > 0 then scope[name] = values @@ -1096,6 +1099,9 @@ function interpreter:api_register_add_values(scope_kind, ...) extra_config = nil end + -- expand values + values = table.join(table.unpack(values)) + -- save values scope[name] = table.join2(scope[name] or {}, values) -- cgit v1.3.1 From c0576c2fc972a17797ac9fe98e5e6deb00ba822a Mon Sep 17 00:00:00 2001 From: zmmfly Date: Sun, 9 Jan 2022 15:03:31 +0800 Subject: add Arch switcher, and add adaptation for -mcpu and --cpu difference. --- xmake/toolchains/armclang/xmake.lua | 47 +++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/xmake/toolchains/armclang/xmake.lua b/xmake/toolchains/armclang/xmake.lua index 46f22a2ba..f72410389 100644 --- a/xmake/toolchains/armclang/xmake.lua +++ b/xmake/toolchains/armclang/xmake.lua @@ -43,12 +43,45 @@ toolchain("armclang") end) on_load(function (toolchain) - local arch = toolchain:arch() - if arch then - toolchain:add("cxflags", "-target=arm-arm-none-eabi") - toolchain:add("cxflags", "-mcpu=" .. arch:lower()) - toolchain:add("asflags", "-target=arm-arm-none-eabi") - toolchain:add("asflags", "-mcpu=" .. arch:lower()) - toolchain:add("ldflags", "--cpu " .. arch) + -- replace function + -- this function from https://blog.csdn.net/gouki04/article/details/88559872 + string.replace = function(s, pattern, repl) + local i,j = string.find(s, pattern, 1, true) + if i and j then + local ret = {} + local start = 1 + while i and j do + table.insert(ret, string.sub(s, start, i-1)) + table.insert(ret, repl) + start = j + 1 + i,j = string.find(s, pattern, start , true ) + end + table.insert(ret, string.sub(s, start)) + return table.concat(ret) + end + return s + end + + local arch = toolchain:arch() + local arch_lower = arch:lower() + local arch_replace = string.replace(arch_lower, "plus", "+") + local arch_target = "" + + -- convert for ldflag + if arch_lower:startswith("cortex-m") then + arch_replace = string.replace(arch_replace, "cortex-m", "Cortex-M") + arch_target = "arm-arm-none-eabi" + end + if arch_lower:startswith("cortex-a") then + arch_replace = string.replace(arch_replace, "cortex-a", "Cortex-A") + arch_target = "aarch64-arm-none-eabi" + end + + if arch_lower then + toolchain:add("cxflags", "-target=" .. arch_target) + toolchain:add("cxflags", "-mcpu=" .. arch_lower) + toolchain:add("asflags", "-target=" .. arch_target) + toolchain:add("asflags", "-mcpu=" .. arch_lower) + toolchain:add("ldflags", "--cpu " .. arch_replace) end end) -- cgit v1.3.1 From 0702f048e67ce16f83c9dd2540185bb9bd34a525 Mon Sep 17 00:00:00 2001 From: zmmfly Date: Sun, 9 Jan 2022 15:14:07 +0800 Subject: armlink not need replace 'plus' to '+' --- xmake/toolchains/armclang/xmake.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xmake/toolchains/armclang/xmake.lua b/xmake/toolchains/armclang/xmake.lua index f72410389..d78423849 100644 --- a/xmake/toolchains/armclang/xmake.lua +++ b/xmake/toolchains/armclang/xmake.lua @@ -64,16 +64,16 @@ toolchain("armclang") local arch = toolchain:arch() local arch_lower = arch:lower() - local arch_replace = string.replace(arch_lower, "plus", "+") + local arch_replace = "" local arch_target = "" -- convert for ldflag if arch_lower:startswith("cortex-m") then - arch_replace = string.replace(arch_replace, "cortex-m", "Cortex-M") + arch_replace = string.replace(arch_lower, "cortex-m", "Cortex-M") arch_target = "arm-arm-none-eabi" end if arch_lower:startswith("cortex-a") then - arch_replace = string.replace(arch_replace, "cortex-a", "Cortex-A") + arch_replace = string.replace(arch_lower, "cortex-a", "Cortex-A") arch_target = "aarch64-arm-none-eabi" end -- cgit v1.3.1 From c432697422a4177b755cf5c1396251ec0cd43d87 Mon Sep 17 00:00:00 2001 From: zmmfly Date: Sun, 9 Jan 2022 15:36:53 +0800 Subject: style sync. --- xmake/toolchains/armclang/xmake.lua | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/xmake/toolchains/armclang/xmake.lua b/xmake/toolchains/armclang/xmake.lua index d78423849..f35f9fbfb 100644 --- a/xmake/toolchains/armclang/xmake.lua +++ b/xmake/toolchains/armclang/xmake.lua @@ -43,25 +43,6 @@ toolchain("armclang") end) on_load(function (toolchain) - -- replace function - -- this function from https://blog.csdn.net/gouki04/article/details/88559872 - string.replace = function(s, pattern, repl) - local i,j = string.find(s, pattern, 1, true) - if i and j then - local ret = {} - local start = 1 - while i and j do - table.insert(ret, string.sub(s, start, i-1)) - table.insert(ret, repl) - start = j + 1 - i,j = string.find(s, pattern, start , true ) - end - table.insert(ret, string.sub(s, start)) - return table.concat(ret) - end - return s - end - local arch = toolchain:arch() local arch_lower = arch:lower() local arch_replace = "" @@ -69,19 +50,19 @@ toolchain("armclang") -- convert for ldflag if arch_lower:startswith("cortex-m") then - arch_replace = string.replace(arch_lower, "cortex-m", "Cortex-M") + arch_replace = arch_lower:replace("cortex-m", "Cortex-M", {plain=true}) arch_target = "arm-arm-none-eabi" end if arch_lower:startswith("cortex-a") then - arch_replace = string.replace(arch_lower, "cortex-a", "Cortex-A") + arch_replace = arch_lower:replace("cortex-a", "Cortex-A", {plain=true}) arch_target = "aarch64-arm-none-eabi" end if arch_lower then toolchain:add("cxflags", "-target=" .. arch_target) - toolchain:add("cxflags", "-mcpu=" .. arch_lower) + toolchain:add("cxflags", "-mcpu=" .. arch_lower) toolchain:add("asflags", "-target=" .. arch_target) - toolchain:add("asflags", "-mcpu=" .. arch_lower) - toolchain:add("ldflags", "--cpu " .. arch_replace) + toolchain:add("asflags", "-mcpu=" .. arch_lower) + toolchain:add("ldflags", "--cpu " .. arch_replace) end end) -- cgit v1.3.1 From 80e1bd8df356ab25802e518bac38aff7dfe45702 Mon Sep 17 00:00:00 2001 From: fasiondog Date: Sun, 9 Jan 2022 16:13:31 +0800 Subject: Improve cmake.tool, make and ninja supports the specified target --- xmake/modules/package/tools/cmake.lua | 6 +++++- xmake/modules/package/tools/ninja.lua | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/xmake/modules/package/tools/cmake.lua b/xmake/modules/package/tools/cmake.lua index 4ced3e67d..f49cedf0b 100644 --- a/xmake/modules/package/tools/cmake.lua +++ b/xmake/modules/package/tools/cmake.lua @@ -554,8 +554,12 @@ end -- do build for make function _build_for_make(package, configs, opt) + local argv = {} + if opt.target then + table.insert(argv, opt.target) + end local jobs = _get_parallel_njobs(opt) - local argv = {"-j" .. jobs} + table.insert(argv, "-j" .. jobs) if option.get("verbose") then table.insert(argv, "VERBOSE=1") end diff --git a/xmake/modules/package/tools/ninja.lua b/xmake/modules/package/tools/ninja.lua index e16731670..0d3ad9708 100644 --- a/xmake/modules/package/tools/ninja.lua +++ b/xmake/modules/package/tools/ninja.lua @@ -28,7 +28,12 @@ function build(package, configs, opt) local buildir = opt.buildir or os.curdir() local njob = opt.jobs or option.get("jobs") or tostring(os.default_njob()) local ninja = assert(find_tool("ninja"), "ninja not found!") - local argv = {"-C", buildir} + local argv = {} + if opt.target then + table.insert(argv, opt.target) + end + table.insert(argv, "-C") + table.insert(argv, buildir) if option.get("verbose") then table.insert(argv, "-v") end -- cgit v1.3.1 From 2cc2da4c49c4a6b6649a316b60865dab889e7f76 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 9 Jan 2022 21:39:22 +0800 Subject: Update xmake.lua --- xmake/toolchains/armclang/xmake.lua | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/xmake/toolchains/armclang/xmake.lua b/xmake/toolchains/armclang/xmake.lua index f35f9fbfb..dc8c1c696 100644 --- a/xmake/toolchains/armclang/xmake.lua +++ b/xmake/toolchains/armclang/xmake.lua @@ -43,26 +43,24 @@ toolchain("armclang") end) on_load(function (toolchain) - local arch = toolchain:arch() - local arch_lower = arch:lower() - local arch_replace = "" - local arch_target = "" - - -- convert for ldflag - if arch_lower:startswith("cortex-m") then - arch_replace = arch_lower:replace("cortex-m", "Cortex-M", {plain=true}) - arch_target = "arm-arm-none-eabi" - end - if arch_lower:startswith("cortex-a") then - arch_replace = arch_lower:replace("cortex-a", "Cortex-A", {plain=true}) - arch_target = "aarch64-arm-none-eabi" - end - - if arch_lower then + local arch = toolchain:arch() + if arch then + local arch_cpu = arch:lower() + local arch_cpu_ld = "" + local arch_target = "" + if arch_cpu:startswith("cortex-m") then + arch_cpu_ld = arch_cpu:replace("cortex-m", "Cortex-M", {plain = true}) + arch_target = "arm-arm-none-eabi" + end + if arch_cpu:startswith("cortex-a") then + arch_cpu_ld = arch_cpu:replace("cortex-a", "Cortex-A", {plain = true}) + arch_target = "aarch64-arm-none-eabi" + end toolchain:add("cxflags", "-target=" .. arch_target) - toolchain:add("cxflags", "-mcpu=" .. arch_lower) + toolchain:add("cxflags", "-mcpu=" .. arch_cpu) toolchain:add("asflags", "-target=" .. arch_target) - toolchain:add("asflags", "-mcpu=" .. arch_lower) - toolchain:add("ldflags", "--cpu " .. arch_replace) + toolchain:add("asflags", "-mcpu=" .. arch_cpu) + toolchain:add("ldflags", "--cpu " .. arch_cpu_ld) end end) + -- cgit v1.3.1