From dfec197495241d47a6a5c9f6d3fb5bc347b580b7 Mon Sep 17 00:00:00 2001 From: Shibby Date: Mon, 28 Sep 2015 11:00:13 +0200 Subject: [PATCH] QMI: add uqmi tool with all depends --- release/src/router/Makefile | 26 + release/src/router/libjson-c/.gitignore | 55 + release/src/router/libjson-c/AUTHORS | 5 + release/src/router/libjson-c/Android.configure.mk | 39 + release/src/router/libjson-c/COPYING | 42 + release/src/router/libjson-c/ChangeLog | 214 ++ release/src/router/libjson-c/Doxyfile | 1153 +++++++ release/src/router/libjson-c/Makefile.am | 74 + release/src/router/libjson-c/Makefile.am.inc | 2 + release/src/router/libjson-c/NEWS | 0 release/src/router/libjson-c/README | 45 + release/src/router/libjson-c/README-WIN32.html | 50 + release/src/router/libjson-c/README.html | 34 + release/src/router/libjson-c/RELEASE_CHECKLIST.txt | 117 + release/src/router/libjson-c/arraylist.c | 101 + release/src/router/libjson-c/arraylist.h | 56 + release/src/router/libjson-c/autogen.sh | 13 + release/src/router/libjson-c/bits.h | 28 + release/src/router/libjson-c/config.h.in | 174 ++ release/src/router/libjson-c/config.h.win32 | 94 + release/src/router/libjson-c/configure.ac | 101 + release/src/router/libjson-c/debug.c | 83 + release/src/router/libjson-c/debug.h | 71 + .../src/router/libjson-c/json-c-uninstalled.pc.in | 11 + release/src/router/libjson-c/json-c.pc.in | 11 + release/src/router/libjson-c/json-c.vcproj | 179 ++ release/src/router/libjson-c/json.h | 34 + release/src/router/libjson-c/json_c_version.c | 20 + release/src/router/libjson-c/json_c_version.h | 22 + release/src/router/libjson-c/json_config.h.in | 3 + release/src/router/libjson-c/json_inttypes.h | 28 + release/src/router/libjson-c/json_object.c | 855 ++++++ release/src/router/libjson-c/json_object.h | 612 ++++ .../src/router/libjson-c/json_object_iterator.c | 168 ++ .../src/router/libjson-c/json_object_iterator.h | 239 ++ release/src/router/libjson-c/json_object_private.h | 47 + release/src/router/libjson-c/json_tokener.c | 886 ++++++ release/src/router/libjson-c/json_tokener.h | 208 ++ release/src/router/libjson-c/json_util.c | 300 ++ release/src/router/libjson-c/json_util.h | 41 + release/src/router/libjson-c/libjson.c | 26 + release/src/router/libjson-c/linkhash.c | 602 ++++ release/src/router/libjson-c/linkhash.h | 292 ++ release/src/router/libjson-c/math_compat.h | 9 + release/src/router/libjson-c/printbuf.c | 192 ++ release/src/router/libjson-c/printbuf.h | 77 + release/src/router/libjson-c/random_seed.c | 237 ++ release/src/router/libjson-c/random_seed.h | 25 + release/src/router/libjson-c/tests/Makefile.am | 41 + release/src/router/libjson-c/tests/parse_flags.c | 50 + release/src/router/libjson-c/tests/parse_flags.h | 4 + release/src/router/libjson-c/tests/test-defs.sh | 128 + release/src/router/libjson-c/tests/test1.c | 134 + release/src/router/libjson-c/tests/test1.expected | 36 + release/src/router/libjson-c/tests/test1.test | 22 + .../libjson-c/tests/test1Formatted_plain.expected | 36 + .../libjson-c/tests/test1Formatted_pretty.expected | 59 + .../libjson-c/tests/test1Formatted_spaced.expected | 36 + release/src/router/libjson-c/tests/test2.c | 34 + release/src/router/libjson-c/tests/test2.expected | 1 + release/src/router/libjson-c/tests/test2.test | 22 + .../libjson-c/tests/test2Formatted_plain.expected | 1 + .../libjson-c/tests/test2Formatted_pretty.expected | 23 + .../libjson-c/tests/test2Formatted_spaced.expected | 1 + release/src/router/libjson-c/tests/test4.c | 53 + release/src/router/libjson-c/tests/test4.expected | 3 + release/src/router/libjson-c/tests/test4.test | 12 + .../router/libjson-c/tests/testReplaceExisting.c | 78 + .../libjson-c/tests/testReplaceExisting.expected | 15 + .../libjson-c/tests/testReplaceExisting.test | 12 + release/src/router/libjson-c/tests/test_cast.c | 106 + .../src/router/libjson-c/tests/test_cast.expected | 56 + release/src/router/libjson-c/tests/test_cast.test | 12 + release/src/router/libjson-c/tests/test_charcase.c | 40 + .../router/libjson-c/tests/test_charcase.expected | 1 + .../src/router/libjson-c/tests/test_charcase.test | 12 + release/src/router/libjson-c/tests/test_locale.c | 31 + .../router/libjson-c/tests/test_locale.expected | 2 + .../src/router/libjson-c/tests/test_locale.test | 12 + release/src/router/libjson-c/tests/test_null.c | 57 + .../src/router/libjson-c/tests/test_null.expected | 3 + release/src/router/libjson-c/tests/test_null.test | 12 + release/src/router/libjson-c/tests/test_parse.c | 322 ++ .../src/router/libjson-c/tests/test_parse.expected | 65 + release/src/router/libjson-c/tests/test_parse.test | 12 + .../src/router/libjson-c/tests/test_parse_int64.c | 115 + .../libjson-c/tests/test_parse_int64.expected | 29 + .../router/libjson-c/tests/test_parse_int64.test | 12 + release/src/router/libjson-c/tests/test_printbuf.c | 166 + .../router/libjson-c/tests/test_printbuf.expected | 32 + .../src/router/libjson-c/tests/test_printbuf.test | 12 + .../router/libjson-c/tests/test_set_serializer.c | 71 + .../libjson-c/tests/test_set_serializer.expected | 10 + .../libjson-c/tests/test_set_serializer.test | 12 + release/src/router/uqmi/CMakeLists.txt | 66 + release/src/router/uqmi/commands-dms.c | 410 +++ release/src/router/uqmi/commands-dms.h | 73 + release/src/router/uqmi/commands-nas.c | 371 +++ release/src/router/uqmi/commands-nas.h | 49 + release/src/router/uqmi/commands-wda.c | 79 + release/src/router/uqmi/commands-wda.h | 30 + release/src/router/uqmi/commands-wds.c | 323 ++ release/src/router/uqmi/commands-wds.h | 48 + release/src/router/uqmi/commands-wms.c | 668 +++++ release/src/router/uqmi/commands-wms.h | 41 + release/src/router/uqmi/commands.c | 264 ++ release/src/router/uqmi/commands.h | 79 + release/src/router/uqmi/data/gen-code.pl | 450 +++ release/src/router/uqmi/data/gen-common.pm | 89 + release/src/router/uqmi/data/gen-error-list.pl | 41 + release/src/router/uqmi/data/gen-header.pl | 116 + release/src/router/uqmi/data/lib/JSON.pm | 2267 ++++++++++++++ .../src/router/uqmi/data/lib/JSON/backportPP.pm | 2797 +++++++++++++++++ .../uqmi/data/lib/JSON/backportPP/Boolean.pm | 26 + .../uqmi/data/lib/JSON/backportPP/Compat5005.pm | 131 + .../uqmi/data/lib/JSON/backportPP/Compat5006.pm | 173 ++ release/src/router/uqmi/data/qmi-service-ctl.json | 162 + release/src/router/uqmi/data/qmi-service-dms.json | 1174 ++++++++ release/src/router/uqmi/data/qmi-service-nas.json | 3159 ++++++++++++++++++++ release/src/router/uqmi/data/qmi-service-oma.json | 223 ++ release/src/router/uqmi/data/qmi-service-pbm.json | 298 ++ release/src/router/uqmi/data/qmi-service-pds.json | 439 +++ release/src/router/uqmi/data/qmi-service-uim.json | 359 +++ release/src/router/uqmi/data/qmi-service-wda.json | 162 + release/src/router/uqmi/data/qmi-service-wds.json | 1069 +++++++ release/src/router/uqmi/data/qmi-service-wms.json | 567 ++++ release/src/router/uqmi/dev.c | 388 +++ release/src/router/uqmi/libubox/CMakeLists.txt | 69 + release/src/router/uqmi/libubox/avl-cmp.c | 24 + release/src/router/uqmi/libubox/avl-cmp.h | 21 + release/src/router/uqmi/libubox/avl.c | 735 +++++ release/src/router/uqmi/libubox/avl.h | 560 ++++ release/src/router/uqmi/libubox/blob.c | 287 ++ release/src/router/uqmi/libubox/blob.h | 257 ++ release/src/router/uqmi/libubox/blobmsg.c | 320 ++ release/src/router/uqmi/libubox/blobmsg.h | 241 ++ release/src/router/uqmi/libubox/blobmsg_json.c | 329 ++ release/src/router/uqmi/libubox/blobmsg_json.h | 45 + .../router/uqmi/libubox/examples/CMakeLists.txt | 24 + .../router/uqmi/libubox/examples/blobmsg-example.c | 139 + .../uqmi/libubox/examples/runqueue-example.c | 112 + .../router/uqmi/libubox/examples/uloop-example.lua | 78 + .../router/uqmi/libubox/examples/uloop_pid_test.sh | 11 + .../router/uqmi/libubox/examples/ustream-example.c | 148 + release/src/router/uqmi/libubox/jshn.c | 308 ++ release/src/router/uqmi/libubox/json_script.c | 651 ++++ release/src/router/uqmi/libubox/json_script.h | 123 + release/src/router/uqmi/libubox/kvlist.c | 96 + release/src/router/uqmi/libubox/kvlist.h | 54 + release/src/router/uqmi/libubox/list.h | 208 ++ release/src/router/uqmi/libubox/lua/CMakeLists.txt | 52 + release/src/router/uqmi/libubox/lua/uloop.c | 419 +++ release/src/router/uqmi/libubox/md5.c | 335 +++ release/src/router/uqmi/libubox/md5.h | 58 + release/src/router/uqmi/libubox/runqueue.c | 282 ++ release/src/router/uqmi/libubox/runqueue.h | 115 + release/src/router/uqmi/libubox/safe_list.c | 121 + release/src/router/uqmi/libubox/safe_list.h | 62 + release/src/router/uqmi/libubox/sh/jshn.sh | 280 ++ release/src/router/uqmi/libubox/uloop.c | 682 +++++ release/src/router/uqmi/libubox/uloop.h | 109 + release/src/router/uqmi/libubox/usock.c | 132 + release/src/router/uqmi/libubox/usock.h | 36 + release/src/router/uqmi/libubox/ustream-fd.c | 163 + release/src/router/uqmi/libubox/ustream.c | 514 ++++ release/src/router/uqmi/libubox/ustream.h | 214 ++ release/src/router/uqmi/libubox/utils.c | 94 + release/src/router/uqmi/libubox/utils.h | 182 ++ release/src/router/uqmi/libubox/vlist.c | 82 + release/src/router/uqmi/libubox/vlist.h | 75 + release/src/router/uqmi/main.c | 152 + release/src/router/uqmi/qmi-enums-dms.h | 337 +++ release/src/router/uqmi/qmi-enums-nas.h | 892 ++++++ release/src/router/uqmi/qmi-enums-pds.h | 182 ++ release/src/router/uqmi/qmi-enums-private.h | 85 + release/src/router/uqmi/qmi-enums-wda.h | 68 + release/src/router/uqmi/qmi-enums-wds.h | 1017 +++++++ release/src/router/uqmi/qmi-enums-wms.h | 425 +++ release/src/router/uqmi/qmi-enums.h | 135 + release/src/router/uqmi/qmi-errors.h | 270 ++ release/src/router/uqmi/qmi-flags64-dms.h | 198 ++ release/src/router/uqmi/qmi-flags64-nas.h | 194 ++ release/src/router/uqmi/qmi-message.c | 176 ++ release/src/router/uqmi/qmi-message.h | 123 + release/src/router/uqmi/qmi-struct.h | 62 + release/src/router/uqmi/uqmi.h | 124 + 186 files changed, 39582 insertions(+) create mode 100644 release/src/router/libjson-c/.gitignore create mode 100644 release/src/router/libjson-c/AUTHORS create mode 100644 release/src/router/libjson-c/Android.configure.mk create mode 100644 release/src/router/libjson-c/COPYING create mode 100644 release/src/router/libjson-c/ChangeLog create mode 100644 release/src/router/libjson-c/Doxyfile create mode 100644 release/src/router/libjson-c/Makefile.am create mode 100644 release/src/router/libjson-c/Makefile.am.inc create mode 100644 release/src/router/libjson-c/NEWS create mode 100644 release/src/router/libjson-c/README create mode 100644 release/src/router/libjson-c/README-WIN32.html create mode 100644 release/src/router/libjson-c/README.html create mode 100644 release/src/router/libjson-c/RELEASE_CHECKLIST.txt create mode 100644 release/src/router/libjson-c/arraylist.c create mode 100644 release/src/router/libjson-c/arraylist.h create mode 100755 release/src/router/libjson-c/autogen.sh create mode 100644 release/src/router/libjson-c/bits.h create mode 100644 release/src/router/libjson-c/config.h.in create mode 100644 release/src/router/libjson-c/config.h.win32 create mode 100644 release/src/router/libjson-c/configure.ac create mode 100644 release/src/router/libjson-c/debug.c create mode 100644 release/src/router/libjson-c/debug.h create mode 100644 release/src/router/libjson-c/json-c-uninstalled.pc.in create mode 100644 release/src/router/libjson-c/json-c.pc.in create mode 100644 release/src/router/libjson-c/json-c.vcproj create mode 100644 release/src/router/libjson-c/json.h create mode 100644 release/src/router/libjson-c/json_c_version.c create mode 100644 release/src/router/libjson-c/json_c_version.h create mode 100644 release/src/router/libjson-c/json_config.h.in create mode 100644 release/src/router/libjson-c/json_inttypes.h create mode 100644 release/src/router/libjson-c/json_object.c create mode 100644 release/src/router/libjson-c/json_object.h create mode 100644 release/src/router/libjson-c/json_object_iterator.c create mode 100644 release/src/router/libjson-c/json_object_iterator.h create mode 100644 release/src/router/libjson-c/json_object_private.h create mode 100644 release/src/router/libjson-c/json_tokener.c create mode 100644 release/src/router/libjson-c/json_tokener.h create mode 100644 release/src/router/libjson-c/json_util.c create mode 100644 release/src/router/libjson-c/json_util.h create mode 100644 release/src/router/libjson-c/libjson.c create mode 100644 release/src/router/libjson-c/linkhash.c create mode 100644 release/src/router/libjson-c/linkhash.h create mode 100644 release/src/router/libjson-c/math_compat.h create mode 100644 release/src/router/libjson-c/printbuf.c create mode 100644 release/src/router/libjson-c/printbuf.h create mode 100644 release/src/router/libjson-c/random_seed.c create mode 100644 release/src/router/libjson-c/random_seed.h create mode 100644 release/src/router/libjson-c/tests/Makefile.am create mode 100644 release/src/router/libjson-c/tests/parse_flags.c create mode 100644 release/src/router/libjson-c/tests/parse_flags.h create mode 100755 release/src/router/libjson-c/tests/test-defs.sh create mode 100644 release/src/router/libjson-c/tests/test1.c create mode 100644 release/src/router/libjson-c/tests/test1.expected create mode 100755 release/src/router/libjson-c/tests/test1.test create mode 100644 release/src/router/libjson-c/tests/test1Formatted_plain.expected create mode 100644 release/src/router/libjson-c/tests/test1Formatted_pretty.expected create mode 100644 release/src/router/libjson-c/tests/test1Formatted_spaced.expected create mode 100644 release/src/router/libjson-c/tests/test2.c create mode 100644 release/src/router/libjson-c/tests/test2.expected create mode 100755 release/src/router/libjson-c/tests/test2.test create mode 100644 release/src/router/libjson-c/tests/test2Formatted_plain.expected create mode 100644 release/src/router/libjson-c/tests/test2Formatted_pretty.expected create mode 100644 release/src/router/libjson-c/tests/test2Formatted_spaced.expected create mode 100644 release/src/router/libjson-c/tests/test4.c create mode 100644 release/src/router/libjson-c/tests/test4.expected create mode 100755 release/src/router/libjson-c/tests/test4.test create mode 100644 release/src/router/libjson-c/tests/testReplaceExisting.c create mode 100644 release/src/router/libjson-c/tests/testReplaceExisting.expected create mode 100755 release/src/router/libjson-c/tests/testReplaceExisting.test create mode 100644 release/src/router/libjson-c/tests/test_cast.c create mode 100644 release/src/router/libjson-c/tests/test_cast.expected create mode 100755 release/src/router/libjson-c/tests/test_cast.test create mode 100644 release/src/router/libjson-c/tests/test_charcase.c create mode 100644 release/src/router/libjson-c/tests/test_charcase.expected create mode 100755 release/src/router/libjson-c/tests/test_charcase.test create mode 100644 release/src/router/libjson-c/tests/test_locale.c create mode 100644 release/src/router/libjson-c/tests/test_locale.expected create mode 100755 release/src/router/libjson-c/tests/test_locale.test create mode 100644 release/src/router/libjson-c/tests/test_null.c create mode 100644 release/src/router/libjson-c/tests/test_null.expected create mode 100755 release/src/router/libjson-c/tests/test_null.test create mode 100644 release/src/router/libjson-c/tests/test_parse.c create mode 100644 release/src/router/libjson-c/tests/test_parse.expected create mode 100755 release/src/router/libjson-c/tests/test_parse.test create mode 100644 release/src/router/libjson-c/tests/test_parse_int64.c create mode 100644 release/src/router/libjson-c/tests/test_parse_int64.expected create mode 100755 release/src/router/libjson-c/tests/test_parse_int64.test create mode 100644 release/src/router/libjson-c/tests/test_printbuf.c create mode 100644 release/src/router/libjson-c/tests/test_printbuf.expected create mode 100755 release/src/router/libjson-c/tests/test_printbuf.test create mode 100644 release/src/router/libjson-c/tests/test_set_serializer.c create mode 100644 release/src/router/libjson-c/tests/test_set_serializer.expected create mode 100755 release/src/router/libjson-c/tests/test_set_serializer.test create mode 100644 release/src/router/uqmi/CMakeLists.txt create mode 100644 release/src/router/uqmi/commands-dms.c create mode 100644 release/src/router/uqmi/commands-dms.h create mode 100644 release/src/router/uqmi/commands-nas.c create mode 100644 release/src/router/uqmi/commands-nas.h create mode 100644 release/src/router/uqmi/commands-wda.c create mode 100644 release/src/router/uqmi/commands-wda.h create mode 100644 release/src/router/uqmi/commands-wds.c create mode 100644 release/src/router/uqmi/commands-wds.h create mode 100644 release/src/router/uqmi/commands-wms.c create mode 100644 release/src/router/uqmi/commands-wms.h create mode 100644 release/src/router/uqmi/commands.c create mode 100644 release/src/router/uqmi/commands.h create mode 100755 release/src/router/uqmi/data/gen-code.pl create mode 100644 release/src/router/uqmi/data/gen-common.pm create mode 100755 release/src/router/uqmi/data/gen-error-list.pl create mode 100755 release/src/router/uqmi/data/gen-header.pl create mode 100644 release/src/router/uqmi/data/lib/JSON.pm create mode 100644 release/src/router/uqmi/data/lib/JSON/backportPP.pm create mode 100644 release/src/router/uqmi/data/lib/JSON/backportPP/Boolean.pm create mode 100644 release/src/router/uqmi/data/lib/JSON/backportPP/Compat5005.pm create mode 100644 release/src/router/uqmi/data/lib/JSON/backportPP/Compat5006.pm create mode 100644 release/src/router/uqmi/data/qmi-service-ctl.json create mode 100644 release/src/router/uqmi/data/qmi-service-dms.json create mode 100644 release/src/router/uqmi/data/qmi-service-nas.json create mode 100644 release/src/router/uqmi/data/qmi-service-oma.json create mode 100644 release/src/router/uqmi/data/qmi-service-pbm.json create mode 100644 release/src/router/uqmi/data/qmi-service-pds.json create mode 100644 release/src/router/uqmi/data/qmi-service-uim.json create mode 100644 release/src/router/uqmi/data/qmi-service-wda.json create mode 100644 release/src/router/uqmi/data/qmi-service-wds.json create mode 100644 release/src/router/uqmi/data/qmi-service-wms.json create mode 100644 release/src/router/uqmi/dev.c create mode 100644 release/src/router/uqmi/libubox/CMakeLists.txt create mode 100644 release/src/router/uqmi/libubox/avl-cmp.c create mode 100644 release/src/router/uqmi/libubox/avl-cmp.h create mode 100644 release/src/router/uqmi/libubox/avl.c create mode 100644 release/src/router/uqmi/libubox/avl.h create mode 100644 release/src/router/uqmi/libubox/blob.c create mode 100644 release/src/router/uqmi/libubox/blob.h create mode 100644 release/src/router/uqmi/libubox/blobmsg.c create mode 100644 release/src/router/uqmi/libubox/blobmsg.h create mode 100644 release/src/router/uqmi/libubox/blobmsg_json.c create mode 100644 release/src/router/uqmi/libubox/blobmsg_json.h create mode 100644 release/src/router/uqmi/libubox/examples/CMakeLists.txt create mode 100644 release/src/router/uqmi/libubox/examples/blobmsg-example.c create mode 100644 release/src/router/uqmi/libubox/examples/runqueue-example.c create mode 100755 release/src/router/uqmi/libubox/examples/uloop-example.lua create mode 100755 release/src/router/uqmi/libubox/examples/uloop_pid_test.sh create mode 100644 release/src/router/uqmi/libubox/examples/ustream-example.c create mode 100644 release/src/router/uqmi/libubox/jshn.c create mode 100644 release/src/router/uqmi/libubox/json_script.c create mode 100644 release/src/router/uqmi/libubox/json_script.h create mode 100644 release/src/router/uqmi/libubox/kvlist.c create mode 100644 release/src/router/uqmi/libubox/kvlist.h create mode 100644 release/src/router/uqmi/libubox/list.h create mode 100644 release/src/router/uqmi/libubox/lua/CMakeLists.txt create mode 100644 release/src/router/uqmi/libubox/lua/uloop.c create mode 100644 release/src/router/uqmi/libubox/md5.c create mode 100644 release/src/router/uqmi/libubox/md5.h create mode 100644 release/src/router/uqmi/libubox/runqueue.c create mode 100644 release/src/router/uqmi/libubox/runqueue.h create mode 100644 release/src/router/uqmi/libubox/safe_list.c create mode 100644 release/src/router/uqmi/libubox/safe_list.h create mode 100644 release/src/router/uqmi/libubox/sh/jshn.sh create mode 100644 release/src/router/uqmi/libubox/uloop.c create mode 100644 release/src/router/uqmi/libubox/uloop.h create mode 100644 release/src/router/uqmi/libubox/usock.c create mode 100644 release/src/router/uqmi/libubox/usock.h create mode 100644 release/src/router/uqmi/libubox/ustream-fd.c create mode 100644 release/src/router/uqmi/libubox/ustream.c create mode 100644 release/src/router/uqmi/libubox/ustream.h create mode 100644 release/src/router/uqmi/libubox/utils.c create mode 100644 release/src/router/uqmi/libubox/utils.h create mode 100644 release/src/router/uqmi/libubox/vlist.c create mode 100644 release/src/router/uqmi/libubox/vlist.h create mode 100644 release/src/router/uqmi/main.c create mode 100644 release/src/router/uqmi/qmi-enums-dms.h create mode 100644 release/src/router/uqmi/qmi-enums-nas.h create mode 100644 release/src/router/uqmi/qmi-enums-pds.h create mode 100644 release/src/router/uqmi/qmi-enums-private.h create mode 100644 release/src/router/uqmi/qmi-enums-wda.h create mode 100644 release/src/router/uqmi/qmi-enums-wds.h create mode 100644 release/src/router/uqmi/qmi-enums-wms.h create mode 100644 release/src/router/uqmi/qmi-enums.h create mode 100644 release/src/router/uqmi/qmi-errors.h create mode 100644 release/src/router/uqmi/qmi-flags64-dms.h create mode 100644 release/src/router/uqmi/qmi-flags64-nas.h create mode 100644 release/src/router/uqmi/qmi-message.c create mode 100644 release/src/router/uqmi/qmi-message.h create mode 100644 release/src/router/uqmi/qmi-struct.h create mode 100644 release/src/router/uqmi/uqmi.h diff --git a/release/src/router/Makefile b/release/src/router/Makefile index 5fce920583..1e423f30e2 100644 --- a/release/src/router/Makefile +++ b/release/src/router/Makefile @@ -81,6 +81,7 @@ obj-$(TCONFIG_NOCAT) += nocat # !!TB obj-$(TCONFIG_USB) += p910nd obj-$(TCONFIG_USB) += comgt +obj-$(TCONFIG_USB) += uqmi obj-$(TCONFIG_UPS) += apcupsd @@ -2545,6 +2546,31 @@ ipset-install: ipset ipset-clean: -@$(MAKE) -C ipset clean +libjson-c/stamp-h1: + cd $(TOP)/libjson-c && CC=$(CC) STRIP=$(CROSS_COMPILE)strip \ + autoconf && \ + $(CONFIGURE) --prefix=/usr + touch libjson-c/stamp-h1 + +libjson-c: libjson-c/stamp-h1 + $(MAKE) -C libjson-c $(PARALLEL_BUILD) + +libjson-c-clean: + -$(MAKE) -C libjson-c clean + @rm -rf libjson-c/stamp-h1 + +uqmi: libjson-c + $(MAKE) -C uqmi/libubox + $(MAKE) -C uqmi SHARED=0 CC='$(CC) -static' + +uqmi-install: uqmi + install -D uqmi/uqmi $(INSTALLDIR)/uqmi/usr/sbin/uqmi + $(STRIP) $(INSTALLDIR)/uqmi/usr/sbin/uqmi + +uqmi-clean: libjson-c-clean + $(MAKE) -C uqmi/libubox clean + $(MAKE) -C uqmi clean + comgt: @$(MAKE) -C comgt CC=$(CC) CFLAGS="$(EXTRACFLAGS)" LDFLAGS="-ffunction-sections -fdata-sections -Wl,--gc-sections" comgt diff --git a/release/src/router/libjson-c/.gitignore b/release/src/router/libjson-c/.gitignore new file mode 100644 index 0000000000..15000ba02b --- /dev/null +++ b/release/src/router/libjson-c/.gitignore @@ -0,0 +1,55 @@ +*~ +*.swp +/INSTALL +.deps/ +.libs/ +/aclocal.m4 +/autom4te.cache +/config.guess +/json_config.h +/compile +/config.h +/config.log +/config.status +/config.sub +/configure +/depcomp +/doc +/install-sh +/json.pc +/json-c.pc +/json-c-uninstalled.pc +/libtool +/ltmain.sh +/Makefile +/Makefile.in +/missing +/stamp-h1 +/stamp-h2 +/test-driver +/tests/Makefile +/tests/Makefile.in +/tests/test1 +/tests/test1Formatted +/tests/test2 +/tests/test2Formatted +/tests/test4 +/tests/testReplaceExisting +/tests/testSubDir +/tests/test_parse_int64 +/tests/test_parse +/tests/test_cast +/tests/test_charcase +/tests/test_locale +/tests/test_null +/tests/test_printbuf +/tests/test_set_serializer +/tests/*.vg.out +/tests/*.log +/tests/*.trs +/Debug +/Release +*.lo +*.o +/libjson-c.la +/libjson.la diff --git a/release/src/router/libjson-c/AUTHORS b/release/src/router/libjson-c/AUTHORS new file mode 100644 index 0000000000..b389989c45 --- /dev/null +++ b/release/src/router/libjson-c/AUTHORS @@ -0,0 +1,5 @@ +Michael Clark +Jehiah Czebotar +Eric Haszlakiewicz +C. Watford (christopher.watford@gmail.com) + diff --git a/release/src/router/libjson-c/Android.configure.mk b/release/src/router/libjson-c/Android.configure.mk new file mode 100644 index 0000000000..a6265adac8 --- /dev/null +++ b/release/src/router/libjson-c/Android.configure.mk @@ -0,0 +1,39 @@ +# This file is the top android makefile for all sub-modules. + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +json_c_TOP := $(LOCAL_PATH) + +JSON_C_BUILT_SOURCES := Android.mk + +JSON_C_BUILT_SOURCES := $(patsubst %, $(abspath $(json_c_TOP))/%, $(JSON_C_BUILT_SOURCES)) + +.PHONY: json-c-configure json-c-configure-real +json-c-configure-real: + echo $(JSON_C_BUILT_SOURCES) + cd $(json_c_TOP) ; \ + $(abspath $(json_c_TOP))/autogen.sh && \ + CC="$(CONFIGURE_CC)" \ + CFLAGS="$(CONFIGURE_CFLAGS)" \ + LD=$(TARGET_LD) \ + LDFLAGS="$(CONFIGURE_LDFLAGS)" \ + CPP=$(CONFIGURE_CPP) \ + CPPFLAGS="$(CONFIGURE_CPPFLAGS)" \ + PKG_CONFIG_LIBDIR=$(CONFIGURE_PKG_CONFIG_LIBDIR) \ + PKG_CONFIG_TOP_BUILD_DIR=/ \ + ac_cv_func_malloc_0_nonnull=yes \ + ac_cv_func_realloc_0_nonnull=yes \ + $(abspath $(json_c_TOP))/$(CONFIGURE) --host=$(CONFIGURE_HOST) \ + --prefix=/system \ + && \ + for file in $(JSON_C_BUILT_SOURCES); do \ + rm -f $$file && \ + make -C $$(dirname $$file) $$(basename $$file) ; \ + done + +json-c-configure: json-c-configure-real + +PA_CONFIGURE_TARGETS += json-c-configure + +-include $(json_c_TOP)/Android.mk diff --git a/release/src/router/libjson-c/COPYING b/release/src/router/libjson-c/COPYING new file mode 100644 index 0000000000..740d1258d4 --- /dev/null +++ b/release/src/router/libjson-c/COPYING @@ -0,0 +1,42 @@ + +Copyright (c) 2009-2012 Eric Haszlakiewicz + +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. + +---------------------------------------------------------------- + +Copyright (c) 2004, 2005 Metaparadigm Pte Ltd + +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/release/src/router/libjson-c/ChangeLog b/release/src/router/libjson-c/ChangeLog new file mode 100644 index 0000000000..451b8f6840 --- /dev/null +++ b/release/src/router/libjson-c/ChangeLog @@ -0,0 +1,214 @@ + +0.12 + + * Address security issues: + * CVE-2013-6371: hash collision denial of service + * CVE-2013-6370: buffer overflow if size_t is larger than int + + * Avoid potential overflow in json_object_get_double + + * Eliminate the mc_abort() function and MC_ABORT macro. + + * Make the json_tokener_errors array local. It has been deprecated for + a while, and json_tokener_error_desc() should be used instead. + + * change the floating point output format to %.17g so values with + more than 6 digits show up in the output. + + * Remove the old libjson.so name compatibility support. The library is + only created as libjson-c.so now and headers are only installed + into the ${prefix}/json-c directory. + + * When supported by the linker, add the -Bsymbolic-functions flag. + + * Various changes to fix the build on MSVC. + + * Make strict mode more strict: + * number must not start with 0 + * no single-quote strings + * no comments + * trailing char not allowed + * only allow lowercase literals + + * Added a json_object_new_double_s() convenience function to allow + an exact string representation of a double to be specified when + creating the object and use it in json_tokener_parse_ex() so + a re-serialized object more exactly matches the input. + + * Add support NaN and Infinity + + +0.11 + + * IMPORTANT: the name of the library has changed to libjson-c.so and + the header files are now in include/json-c. + The pkgconfig name has also changed from json to json-c. + You should change your build to use appropriate -I and -l options. + A compatibility shim is in place so builds using the old name will + continue to work, but that will be removed in the next release. + * Maximum recursion depth is now a runtime option. + json_tokener_new() is provided for compatibility. + json_tokener_new_ex(depth) + * Include json_object_iterator.h in the installed headers. + * Add support for building on Android. + * Rewrite json_object_object_add to replace just the value if the key already exists so keys remain valid. + * Make it safe to delete keys while iterating with the json_object_object_foreach macro. + * Add a json_set_serializer() function to allow the string output of a json_object to be customized. + * Make float parsing locale independent. + * Add a json_tokener_set_flags() function and a JSON_TOKENER_STRICT flag. + * Enable -Werror when building. + * speed improvements to parsing 64-bit integers on systems with working sscanf + * Add a json_object_object_length function. + * Fix a bug (buffer overrun) when expanding arrays to more than 64 entries. + +0.10 + + * Add a json_object_to_json_string_ext() function to allow output to be + formatted in a more human readable form. + * Add json_object_object_get_ex(), a NULL-safe get object method, to be able + to distinguish between a key not present and the value being NULL. + * Add an alternative iterator implementation, see json_object_iterator.h + * Make json_object_iter public to enable external use of the + json_object_object_foreachC macro. + * Add a printbuf_memset() function to provide an effecient way to set and + append things like whitespace indentation. + * Adjust json_object_is_type and json_object_get_type so they return + json_type_null for NULL objects and handle NULL passed to + json_objct_object_get(). + * Rename boolean type to json_bool. + * Fix various compile issues for Visual Studio and MinGW. + * Allow json_tokener_parse_ex() to be re-used to parse multiple object. + Also, fix some parsing issues with capitalized hexadecimal numbers and + number in E notation. + * Add json_tokener_get_error() and json_tokener_error_desc() to better + encapsulate the process of retrieving errors while parsing. + * Various improvements to the documentation of many functions. + * Add new json_object_array_sort() function. + * Fix a bug in json_object_get_int(), which would incorrectly return 0 + when called on a string type object. + Eric Haszlakiewicz + * Add a json_type_to_name() function. + Eric Haszlakiewicz + * Add a json_tokener_parse_verbose() function. + Jehiah Czebotar + * Improve support for null bytes within JSON strings. + Jehiah Czebotar + * Fix file descriptor leak if memory allocation fails in json_util + Zachary Blair, zack_blair at hotmail dot com + * Add int64 support. Two new functions json_object_net_int64 and + json_object_get_int64. Binary compatibility preserved. + Eric Haszlakiewicz, EHASZLA at transunion com + Rui Miguel Silva Seabra, rms at 1407 dot org + * Fix subtle bug in linkhash where lookup could hang after all slots + were filled then successively freed. + Spotted by Jean-Marc Naud, j dash m at newtraxtech dot com + * Make json_object_from_file take const char *filename + Spotted by Vikram Raj V, vsagar at attinteractive dot com + * Add handling of surrogate pairs (json_tokener.c, test4.c, Makefile.am) + Brent Miller, bdmiller at yahoo dash inc dot com + * Correction to comment describing printbuf_memappend in printbuf.h + Brent Miller, bdmiller at yahoo dash inc dot com + +0.9 + * Add README.html README-WIN32.html config.h.win32 to Makefile.am + Michael Clark, + * Add const qualifier to the json_tokener_parse functions + Eric Haszlakiewicz, EHASZLA at transunion dot com + * Rename min and max so we can never clash with C or C++ std library + Ian Atha, thatha at yahoo dash inc dot com + * Fix any noticeable spelling or grammar errors. + * Make sure every va_start has a va_end. + * Check all pointers for validity. + Erik Hovland, erik at hovland dot org + * Fix json_object_get_boolean to return false for empty string + Spotted by Vitaly Kruglikov, Vitaly dot Kruglikov at palm dot com + * optimizations to json_tokener_parse_ex(), printbuf_memappend() + Brent Miller, bdmiller at yahoo dash inc dot com + * Disable REFCOUNT_DEBUG by default in json_object.c + * Don't use this as a variable, so we can compile with a C++ compiler + * Add casts from void* to type of assignment when using malloc + * Add #ifdef __cplusplus guards to all of the headers + * Add typedefs for json_object, json_tokener, array_list, printbuf, lh_table + Michael Clark, + * Null pointer dereference fix. Fix json_object_get_boolean strlen test + to not return TRUE for zero length string. Remove redundant includes. + Erik Hovland, erik at hovland dot org + * Fixed warning reported by adding -Wstrict-prototypes + -Wold-style-definition to the compilatin flags. + Dotan Barak, dotanba at gmail dot com + * Add const correctness to public interfaces + Gerard Krol, g dot c dot krol at student dot tudelft dot nl + +0.8 + * Add va_end for every va_start + Dotan Barak, dotanba at gmail dot com + * Add macros to enable compiling out debug code + Geoffrey Young, geoff at modperlcookbook dot org + * Fix bug with use of capital E in numbers with exponents + Mateusz Loskot, mateusz at loskot dot net + * Add stddef.h include + * Patch allows for json-c compile with -Werror and not fail due to + -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations + Geoffrey Young, geoff at modperlcookbook dot org + +0.7 + * Add escaping of backslash to json output + * Add escaping of foward slash on tokenizing and output + * Changes to internal tokenizer from using recursion to + using a depth state structure to allow incremental parsing + +0.6 + * Fix bug in escaping of control characters + Johan Björklund, johbjo09 at kth dot se + * Remove include "config.h" from headers (should only + be included from .c files) + Michael Clark + +0.5 + * Make headers C++ compatible by change *this to *obj + * Add ifdef C++ extern "C" to headers + * Use simpler definition of min and max in bits.h + Larry Lansing, llansing at fuzzynerd dot com + + * Remove automake 1.6 requirement + * Move autogen commands into autogen.sh. Update README + * Remove error pointer special case for Windows + * Change license from LGPL to MIT + Michael Clark + +0.4 + * Fix additional error case in object parsing + * Add back sign reversal in nested object parse as error pointer + value is negative, while error value is positive. + Michael Clark + +0.3 + * fix pointer arithmetic bug for error pointer check in is_error() macro + * fix type passed to printbuf_memappend in json_tokener + * update autotools bootstrap instructions in README + Michael Clark + +0.2 + * printbuf.c - C. Watford (christopher.watford@gmail.com) + Added a Win32/Win64 compliant implementation of vasprintf + * debug.c - C. Watford (christopher.watford@gmail.com) + Removed usage of vsyslog on Win32/Win64 systems, needs to be handled + by a configure script + * json_object.c - C. Watford (christopher.watford@gmail.com) + Added scope operator to wrap usage of json_object_object_foreach, this + needs to be rethought to be more ANSI C friendly + * json_object.h - C. Watford (christopher.watford@gmail.com) + Added Microsoft C friendly version of json_object_object_foreach + * json_tokener.c - C. Watford (christopher.watford@gmail.com) + Added a Win32/Win64 compliant implementation of strndup + * json_util.c - C. Watford (christopher.watford@gmail.com) + Added cast and mask to suffice size_t v. unsigned int conversion + correctness + * json_tokener.c - sign reversal issue on error info for nested object parse + spotted by Johan Björklund (johbjo09 at kth.se) + * json_object.c - escape " in json_escape_str + * Change to automake and libtool to build shared and static library + Michael Clark + +0.1 + * initial release diff --git a/release/src/router/libjson-c/Doxyfile b/release/src/router/libjson-c/Doxyfile new file mode 100644 index 0000000000..edaffea26b --- /dev/null +++ b/release/src/router/libjson-c/Doxyfile @@ -0,0 +1,1153 @@ +# Doxyfile 1.3.8 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = json-c + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 0.12 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = doc + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of source +# files, where putting all generated files in the same directory would otherwise +# cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, +# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, +# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, +# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, +# Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# This tag can be used to specify the encoding used in the generated output. +# The encoding is not always determined by the language that is chosen, +# but also whether or not the output is meant for Windows or non-Windows users. +# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES +# forces the Windows encoding (this is the default for the Windows binary), +# whereas setting the tag to NO uses a Unix-style encoding (the default for +# all platforms other than Windows). + +USE_WINDOWS_ENCODING = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is used +# as the annotated text. Otherwise, the brief description is used as-is. If left +# blank, the following values are used ("$name" is automatically replaced with the +# name of the entity): "The $name class" "The $name widget" "The $name file" +# "is" "provides" "specifies" "contains" "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited +# members of a class in the documentation of that class as if those members were +# ordinary class members. Constructors, destructors and assignment operators of +# the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = NO + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm + +FILE_PATTERNS = *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories +# that are symbolic links (a Unix filesystem feature) are excluded from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse the +# parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. Note that this +# option is superseded by the HAVE_DOT option below. This is only a fallback. It is +# recommended to install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes that +# lay further from the root node will be omitted. Note that setting this option to +# 1 or 2 may greatly reduce the computation time needed for large code bases. Also +# note that a graph may be further truncated if the graph's image dimensions are +# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). +# If 0 is used for the depth value (the default), the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/release/src/router/libjson-c/Makefile.am b/release/src/router/libjson-c/Makefile.am new file mode 100644 index 0000000000..0001d8a902 --- /dev/null +++ b/release/src/router/libjson-c/Makefile.am @@ -0,0 +1,74 @@ +include Makefile.am.inc + +EXTRA_DIST = README.html README-WIN32.html config.h.win32 doc json-c.vcproj +SUBDIRS = . tests + +lib_LTLIBRARIES = libjson-c.la + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = json-c.pc + +libjson_cincludedir = $(includedir)/json-c +libjson_cinclude_HEADERS = \ + arraylist.h \ + bits.h \ + debug.h \ + json.h \ + json_config.h \ + json_c_version.h \ + json_inttypes.h \ + json_object.h \ + json_object_iterator.h \ + json_object_private.h \ + json_tokener.h \ + json_util.h \ + linkhash.h \ + printbuf.h \ + random_seed.h + +#libjsonx_includedir = $(libdir)/json-c-@VERSION@ +# +#libjsonx_include_HEADERS = \ +# json_config.h + +libjson_c_la_LDFLAGS = -version-info 2:1:0 -no-undefined @JSON_BSYMBOLIC_LDFLAGS@ + +libjson_c_la_SOURCES = \ + arraylist.c \ + debug.c \ + json_c_version.c \ + json_object.c \ + json_object_iterator.c \ + json_tokener.c \ + json_util.c \ + linkhash.c \ + printbuf.c \ + random_seed.c + + +distclean-local: + -rm -rf $(testsubdir) + -rm -rf config.h.in~ Makefile.in aclocal.m4 autom4te.cache/ config.guess config.sub depcomp install-sh ltmain.sh missing + -rm -f INSTALL test-driver tests/Makefile.in compile + +maintainer-clean-local: + -rm -rf configure + +uninstall-local: + rm -rf "$(DESTDIR)@includedir@/json-c" + rm -f "$(DESTDIR)@includedir@/json" + +ANDROID_CFLAGS = -I$(top_srcdir) -DHAVE_CONFIG_H + +Android.mk: Makefile.am + androgenizer -:PROJECT json-c \ + -:SHARED libjson-c \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libjson_c_la_SOURCES) $(nodist_libjson_c_la_SOURCES) \ + -:CFLAGS $(DEFS) $(ANDROID_CFLAGS) $(libjson_c_la_CFLAGS) \ + -:LDFLAGS $(libjson_c_la_LDFLAGS) $(libjson_c_la_LIBADD) \ + -:HEADER_TARGET json-c \ + -:HEADERS $(libjson_cinclude_HEADERS) \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + > $@ diff --git a/release/src/router/libjson-c/Makefile.am.inc b/release/src/router/libjson-c/Makefile.am.inc new file mode 100644 index 0000000000..fec591b6cf --- /dev/null +++ b/release/src/router/libjson-c/Makefile.am.inc @@ -0,0 +1,2 @@ +AM_CFLAGS = -Wall -Werror -Wno-error=deprecated-declarations -Wextra -Wwrite-strings -Wno-unused-parameter -std=gnu99 -D_GNU_SOURCE -D_REENTRANT + diff --git a/release/src/router/libjson-c/NEWS b/release/src/router/libjson-c/NEWS new file mode 100644 index 0000000000..e69de29bb2 diff --git a/release/src/router/libjson-c/README b/release/src/router/libjson-c/README new file mode 100644 index 0000000000..8c7301f042 --- /dev/null +++ b/release/src/router/libjson-c/README @@ -0,0 +1,45 @@ +Building on Unix with git, gcc and autotools + +Home page for json-c: + https://github.com/json-c/json-c/wiki + + Caution: do NOT use sources from svn.metaparadigm.com, they are old. + +Prerequisites: + gcc (or another C compiler) + libtool + + If you're not using a release tarball, you'll also need: + autoconf (autoreconf) + automake + Make sure you have a complete libtool install, including libtoolize + +Github repo for json-c: + https://github.com/json-c/json-c + + $ git clone https://github.com/json-c/json-c.git + $ cd json-c + $ sh autogen.sh + +Then + + $ ./configure + $ make + $ make install + +To build and run the test programs run + + $ make check + +Linking to libjson-c + +If your system has pkgconfig then you can just add this to your makefile + +CFLAGS += $(shell pkg-config --cflags json-c) +LDFLAGS += $(shell pkg-config --libs json-c) + +Without pkgconfig, you would do something like this: + +JSON_C_DIR=/path/to/json_c/install +CFLAGS += -I$(JSON_C_DIR)/include/json-c +LDFLAGS+= -L$(JSON_C_DIR)/lib -ljson-c diff --git a/release/src/router/libjson-c/README-WIN32.html b/release/src/router/libjson-c/README-WIN32.html new file mode 100644 index 0000000000..abdb39e7c5 --- /dev/null +++ b/release/src/router/libjson-c/README-WIN32.html @@ -0,0 +1,50 @@ + + + + JSON-C - A JSON implementation in C - Win32 specific notes + + + +

Windows specific notes for JSON-C

+

Please send Win32 bug reports to christopher.watford@gmail.com

+

Win32 Specific Changes:

+
    +
  • + Various functions have been redefined to their Win32 version (i.e. open + on win32 is _open)
  • +
  • + Implemented missing functions from MS's libc (i.e. vasprintf)
  • +
  • + Added code to allow Win64 support without integer resizing issues, this + probably makes it much nicer on 64bit machines everywhere (i.e. using ptrdiff_t + for pointer math)
  • +
+

Porting Changelog:

+
+
printbuf.c - C. Watford (christopher.watford@gmail.com)
+
+ Added a Win32/Win64 compliant implementation of vasprintf
+
debug.c - C. Watford (christopher.watford@gmail.com)
+
+ Removed usage of vsyslog on Win32/Win64 systems, needs to be handled + by a configure script
+
json_object.c - C. Watford (christopher.watford@gmail.com)
+
+ Added scope operator to wrap usage of json_object_object_foreach, this needs to be + rethought to be more ANSI C friendly
+
json_object.h - C. Watford (christopher.watford@gmail.com)
+
+ Added Microsoft C friendly version of json_object_object_foreach
+
json_tokener.c - C. Watford (christopher.watford@gmail.com)
+
+ Added a Win32/Win64 compliant implementation of strndup
+
json_util.c - C. Watford (christopher.watford@gmail.com)
+
+ Added cast and mask to suffice size_t v. unsigned int + conversion correctness
+
+

This program is free software; you can redistribute it and/or modify it under + the terms of the MIT License. See COPYING for details.

+
+ + diff --git a/release/src/router/libjson-c/README.html b/release/src/router/libjson-c/README.html new file mode 100644 index 0000000000..dc696af37b --- /dev/null +++ b/release/src/router/libjson-c/README.html @@ -0,0 +1,34 @@ + + + + JSON-C - A JSON implementation in C + + + +

JSON-C - A JSON implementation in C

+ +

Overview

+

JSON-C implements a reference counting object model that allows you to easily + construct JSON objects in C, output them as JSON formatted strings and parse + JSON formatted strings back into the C representation of JSON objects.

+ +

Building

+

To setup JSON-C to build on your system please run configure and make.

+

If you are on Win32 and are not using the VS project file, be sure + to rename config.h.win32 to config.h before building.

+ +

Documentation

+

Doxygen generated documentation exists here + and Win32 specific notes can be found here.

+ +

GIT Reposository

+

git clone https://github.com/json-c/json-c.git

+ +

Mailing List

+ Send email to json-c <at> googlegroups <dot> com

+ +

License

+

This program is free software; you can redistribute it and/or modify it under the terms of the MIT License..

+
+ + diff --git a/release/src/router/libjson-c/RELEASE_CHECKLIST.txt b/release/src/router/libjson-c/RELEASE_CHECKLIST.txt new file mode 100644 index 0000000000..0bb2b7785b --- /dev/null +++ b/release/src/router/libjson-c/RELEASE_CHECKLIST.txt @@ -0,0 +1,117 @@ + +Release checklist: + +release=0.12 +git clone https://github.com/json-c/json-c json-c-${release} +cd json-c-${release} + +Check that the compile works on Linux +Check that the compile works on NetBSD +Check that the compile works on Windows +Check ChangeLog to see if anything should be added. +Make any fixes/changes *before* branching. + + git branch json-c-${release} + git checkout json-c-${release} + +------------ + +Update the version in json_c_version.h +Update the version in Doxyfile +Update the version in configure.in + Use ${release}. + +Update the libjson_la_LDFLAGS line in Makefile.am to the new version. + Generally, unless we're doing a major release, change: + -version-info x:y:z + to + -version-info x:y+1:z + +------------ + +Generate the configure script and other files: + sh autogen.sh + git add -f Makefile.in aclocal.m4 config.guess \ + config.sub configure depcomp install-sh \ + ltmain.sh missing tests/Makefile.in \ + INSTALL + + # check for anything else to be added: + git status --ignored + git commit + +------------ + +Generate the doxygen documentation: + doxygen + git add -f doc + git commit doc + +------------ + +cd .. +echo .git > excludes +echo autom4te.cache >> excludes +tar -czf json-c-${release}.tar.gz -X excludes json-c-${release} + +echo doc >> excludes +tar -czf json-c-${release}-nodoc.tar.gz -X excludes json-c-${release} + +------------ + +Tag the branch: +cd json-c-${release} +git tag -a json-c-${release}-$(date +%Y%m%d) -m "Release json-c-${release}" + +git push origin json-c-${release} +git push --tags + +------------ + +Go to Amazon S3 service at: + https://console.aws.amazon.com/s3/ + +Upload the two tarballs in the json-c_releases folder. + When uploading, use "Reduced Redundancy", and make the uploaded files publicly accessible. + +Logout of Amazon S3, and verify that the files are visible. + https://s3.amazonaws.com/json-c_releases/releases/index.html + +=================================== + +Post-release checklist: + +git checkout master +Add new section to ChangeLog +Update the version in json_c_version.h +Update the version in Doxyfile +Update the version in configure.in + Use ${release}.99 to indicate a version "newer" than anything on the branch. + +Leave the libjson_la_LDFLAGS line in Makefile.am alone. + For more details see: + http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html + +------------ + +Update the gh-pages branch with new docs: + +cd json-c-${release} +git checkout json-c-${release} +cd .. + +git clone -b gh-pages https://github.com/json-c/json-c json-c-pages +cd json-c-pages +mkdir json-c-${release} +cp -R ../json-c-${release}/doc json-c-${release}/. +cp ../json-c-${release}/README-WIN32.html json-c-${release}/. +git add json-c-${release} +git commit + +vi index.html + Add/change links to current release. + +------------ + +Send an email to the mailing list. + diff --git a/release/src/router/libjson-c/arraylist.c b/release/src/router/libjson-c/arraylist.c new file mode 100644 index 0000000000..81b6fa2b64 --- /dev/null +++ b/release/src/router/libjson-c/arraylist.c @@ -0,0 +1,101 @@ +/* + * $Id: arraylist.c,v 1.4 2006/01/26 02:16:28 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#include "config.h" + +#ifdef STDC_HEADERS +# include +# include +#endif /* STDC_HEADERS */ + +#if defined(HAVE_STRINGS_H) && !defined(_STRING_H) && !defined(__USE_BSD) +# include +#endif /* HAVE_STRINGS_H */ + +#include "bits.h" +#include "arraylist.h" + +struct array_list* +array_list_new(array_list_free_fn *free_fn) +{ + struct array_list *arr; + + arr = (struct array_list*)calloc(1, sizeof(struct array_list)); + if(!arr) return NULL; + arr->size = ARRAY_LIST_DEFAULT_SIZE; + arr->length = 0; + arr->free_fn = free_fn; + if(!(arr->array = (void**)calloc(sizeof(void*), arr->size))) { + free(arr); + return NULL; + } + return arr; +} + +extern void +array_list_free(struct array_list *arr) +{ + int i; + for(i = 0; i < arr->length; i++) + if(arr->array[i]) arr->free_fn(arr->array[i]); + free(arr->array); + free(arr); +} + +void* +array_list_get_idx(struct array_list *arr, int i) +{ + if(i >= arr->length) return NULL; + return arr->array[i]; +} + +static int array_list_expand_internal(struct array_list *arr, int max) +{ + void *t; + int new_size; + + if(max < arr->size) return 0; + new_size = json_max(arr->size << 1, max); + if(!(t = realloc(arr->array, new_size*sizeof(void*)))) return -1; + arr->array = (void**)t; + (void)memset(arr->array + arr->size, 0, (new_size-arr->size)*sizeof(void*)); + arr->size = new_size; + return 0; +} + +int +array_list_put_idx(struct array_list *arr, int idx, void *data) +{ + if(array_list_expand_internal(arr, idx+1)) return -1; + if(arr->array[idx]) arr->free_fn(arr->array[idx]); + arr->array[idx] = data; + if(arr->length <= idx) arr->length = idx + 1; + return 0; +} + +int +array_list_add(struct array_list *arr, void *data) +{ + return array_list_put_idx(arr, arr->length, data); +} + +void +array_list_sort(struct array_list *arr, int(*sort_fn)(const void *, const void *)) +{ + qsort(arr->array, arr->length, sizeof(arr->array[0]), + (int (*)(const void *, const void *))sort_fn); +} + +int +array_list_length(struct array_list *arr) +{ + return arr->length; +} diff --git a/release/src/router/libjson-c/arraylist.h b/release/src/router/libjson-c/arraylist.h new file mode 100644 index 0000000000..4f3113c094 --- /dev/null +++ b/release/src/router/libjson-c/arraylist.h @@ -0,0 +1,56 @@ +/* + * $Id: arraylist.h,v 1.4 2006/01/26 02:16:28 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef _arraylist_h_ +#define _arraylist_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define ARRAY_LIST_DEFAULT_SIZE 32 + +typedef void (array_list_free_fn) (void *data); + +struct array_list +{ + void **array; + int length; + int size; + array_list_free_fn *free_fn; +}; + +extern struct array_list* +array_list_new(array_list_free_fn *free_fn); + +extern void +array_list_free(struct array_list *al); + +extern void* +array_list_get_idx(struct array_list *al, int i); + +extern int +array_list_put_idx(struct array_list *al, int i, void *data); + +extern int +array_list_add(struct array_list *al, void *data); + +extern int +array_list_length(struct array_list *al); + +extern void +array_list_sort(struct array_list *arr, int(*compar)(const void *, const void *)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/release/src/router/libjson-c/autogen.sh b/release/src/router/libjson-c/autogen.sh new file mode 100755 index 0000000000..69e765a602 --- /dev/null +++ b/release/src/router/libjson-c/autogen.sh @@ -0,0 +1,13 @@ +#!/bin/sh +autoreconf -v --install || exit 1 + +# If there are any options, assume the user wants to run configure. +# To run configure w/o any options, use ./autogen.sh --configure +if [ $# -gt 0 ] ; then + case "$1" in + --conf*) + shift 1 + ;; + esac + exec ./configure "$@" +fi diff --git a/release/src/router/libjson-c/bits.h b/release/src/router/libjson-c/bits.h new file mode 100644 index 0000000000..c8cbbc820d --- /dev/null +++ b/release/src/router/libjson-c/bits.h @@ -0,0 +1,28 @@ +/* + * $Id: bits.h,v 1.10 2006/01/30 23:07:57 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef _bits_h_ +#define _bits_h_ + +#ifndef json_min +#define json_min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef json_max +#define json_max(a,b) ((a) > (b) ? (a) : (b)) +#endif + +#define hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9) +#define error_ptr(error) ((void*)error) +#define error_description(error) (json_tokener_errors[error]) +#define is_error(ptr) (ptr == NULL) + +#endif diff --git a/release/src/router/libjson-c/config.h.in b/release/src/router/libjson-c/config.h.in new file mode 100644 index 0000000000..0dcab1a300 --- /dev/null +++ b/release/src/router/libjson-c/config.h.in @@ -0,0 +1,174 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Enable RDRANR Hardware RNG Hash Seed */ +#undef ENABLE_RDRAND + +/* Define if .gnu.warning accepts long strings. */ +#undef HAS_GNU_WARNING_LONG + +/* Define to 1 if you have the declaration of `INFINITY', and to 0 if you + don't. */ +#undef HAVE_DECL_INFINITY + +/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't. + */ +#undef HAVE_DECL_ISINF + +/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't. + */ +#undef HAVE_DECL_ISNAN + +/* Define to 1 if you have the declaration of `nan', and to 0 if you don't. */ +#undef HAVE_DECL_NAN + +/* Define to 1 if you have the declaration of `_finite', and to 0 if you + don't. */ +#undef HAVE_DECL__FINITE + +/* Define to 1 if you have the declaration of `_isnan', and to 0 if you don't. + */ +#undef HAVE_DECL__ISNAN + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +#undef HAVE_DOPRNT + +/* Define to 1 if you have the header file. */ +#undef HAVE_ENDIAN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LOCALE_H + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `open' function. */ +#undef HAVE_OPEN + +/* Define to 1 if your system has a GNU libc compatible `realloc' function, + and to 0 otherwise. */ +#undef HAVE_REALLOC + +/* Define to 1 if you have the `setlocale' function. */ +#undef HAVE_SETLOCALE + +/* Define to 1 if you have the `snprintf' function. */ +#undef HAVE_SNPRINTF + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDARG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strcasecmp' function. */ +#undef HAVE_STRCASECMP + +/* Define to 1 if you have the `strdup' function. */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strncasecmp' function. */ +#undef HAVE_STRNCASECMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_CDEFS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `vasprintf' function. */ +#undef HAVE_VASPRINTF + +/* Define to 1 if you have the `vprintf' function. */ +#undef HAVE_VPRINTF + +/* Define to 1 if you have the `vsnprintf' function. */ +#undef HAVE_VSNPRINTF + +/* Define to 1 if you have the `vsyslog' function. */ +#undef HAVE_VSYSLOG + +/* Public define for json_inttypes.h */ +#undef JSON_C_HAVE_INTTYPES_H + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to rpl_malloc if the replacement function should be used. */ +#undef malloc + +/* Define to rpl_realloc if the replacement function should be used. */ +#undef realloc + +/* Define to `unsigned int' if does not define. */ +#undef size_t diff --git a/release/src/router/libjson-c/config.h.win32 b/release/src/router/libjson-c/config.h.win32 new file mode 100644 index 0000000000..ec3a84aaf2 --- /dev/null +++ b/release/src/router/libjson-c/config.h.win32 @@ -0,0 +1,94 @@ +/* + * $Id: config.h.win32,v 1.2 2006/01/26 02:16:28 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +/* config.h.win32 Generated by configure. */ + +#define PACKAGE_STRING "JSON C Library 0.2" +#define PACKAGE_BUGREPORT "json-c@googlegroups.com" +#define PACKAGE_NAME "JSON C Library" +#define PACKAGE_TARNAME "json-c" +#define PACKAGE_VERSION "0.2" + +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +/* #undef HAVE_DOPRNT */ + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#define HAVE_MALLOC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `open' function. */ +#undef HAVE_OPEN + +/* Define to 1 if your system has a GNU libc compatible `realloc' function, + and to 0 otherwise. */ +#define HAVE_REALLOC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strdup' function. */ +#undef HAVE_STRNDUP + +/* Define to 1 if you have the header file. */ +#define HAVE_STDARG_H 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `vprintf' function. */ +#undef HAVE_VPRINTF + +/* Define to 1 if you have the `vsyslog' function. */ +#undef HAVE_VSYSLOG + +/* Define to 1 if you have the `strncasecmp' function. */ +#undef HAVE_STRNCASECMP + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 diff --git a/release/src/router/libjson-c/configure.ac b/release/src/router/libjson-c/configure.ac new file mode 100644 index 0000000000..61e8142115 --- /dev/null +++ b/release/src/router/libjson-c/configure.ac @@ -0,0 +1,101 @@ +AC_PREREQ(2.52) + +# Process this file with autoconf to produce a configure script. +AC_INIT([json-c], 0.12, [json-c@googlegroups.com]) + +AM_INIT_AUTOMAKE + +AC_PROG_MAKE_SET + +AC_ARG_ENABLE(rdrand, + AS_HELP_STRING([--enable-rdrand], + [Enable RDRAND Hardware RNG Hash Seed generation on supported x86/x64 platforms.]), +[if test x$enableval = xyes; then + enable_rdrand=yes + AC_DEFINE(ENABLE_RDRAND, 1, [Enable RDRANR Hardware RNG Hash Seed]) +fi]) + +if test "x$enable_rdrand" = "xyes"; then + AC_MSG_RESULT([RDRAND Hardware RNG Hash Seed enabled on supported x86/x64 platforms]) +else + AC_MSG_RESULT([RDRAND Hardware RNG Hash Seed disabled. Use --enable-rdrand to enable]) +fi + +# Checks for programs. + +# Checks for libraries. + +# Checks for header files. +AM_PROG_CC_C_O +AC_CONFIG_HEADER(config.h) +AC_CONFIG_HEADER(json_config.h) +AC_HEADER_STDC +AC_CHECK_HEADERS(fcntl.h limits.h strings.h syslog.h unistd.h [sys/cdefs.h] [sys/param.h] stdarg.h locale.h endian.h) +AC_CHECK_HEADER(inttypes.h,[AC_DEFINE([JSON_C_HAVE_INTTYPES_H],[1],[Public define for json_inttypes.h])]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T + +# Checks for library functions. +AC_FUNC_VPRINTF +AC_FUNC_MEMCMP +AC_FUNC_MALLOC +AC_FUNC_REALLOC +AC_CHECK_FUNCS(strcasecmp strdup strerror snprintf vsnprintf vasprintf open vsyslog strncasecmp setlocale) + +#check if .section.gnu.warning accepts long strings (for __warn_references) +AC_LANG_PUSH([C]) + +AC_MSG_CHECKING([if .gnu.warning accepts long strings]) +AC_LINK_IFELSE([AC_LANG_SOURCE([[ +extern void json_object_get(); +__asm__(".section .gnu.json_object_get,\n\t.ascii \"Please link against libjson-c instead of libjson\"\n\t.text"); + +int main(int c,char* v) {return 0;} +]])], [ + AC_DEFINE(HAS_GNU_WARNING_LONG, 1, [Define if .gnu.warning accepts long strings.]) + AC_MSG_RESULT(yes) +], [ + AC_MSG_RESULT(no) +]) + +AC_LANG_POP([C]) + +AM_PROG_LIBTOOL + +# Check for the -Bsymbolic-functions linker flag +AC_ARG_ENABLE([Bsymbolic], + [AS_HELP_STRING([--disable-Bsymbolic], [Avoid linking with -Bsymbolic-function])], + [], + [enable_Bsymbolic=check]) + +AS_IF([test "x$enable_Bsymbolic" = "xcheck"], + [ + saved_LDFLAGS="${LDFLAGS}" + AC_MSG_CHECKING([for -Bsymbolic-functions linker flag]) + LDFLAGS=-Wl,-Bsymbolic-functions + AC_TRY_LINK([], [int main (void) { return 0; }], + [ + AC_MSG_RESULT([yes]) + enable_Bsymbolic=yes + ], + [ + AC_MSG_RESULT([no]) + enable_Bsymbolic=no + ]) + LDFLAGS="${saved_LDFLAGS}" + ]) + +AS_IF([test "x$enable_Bsymbolic" = "xyes"], [JSON_BSYMBOLIC_LDFLAGS=-Wl[,]-Bsymbolic-functions]) +AC_SUBST(JSON_BSYMBOLIC_LDFLAGS) + +AC_CONFIG_FILES([ +Makefile +json-c.pc +tests/Makefile +json-c-uninstalled.pc +]) + +AC_OUTPUT + diff --git a/release/src/router/libjson-c/debug.c b/release/src/router/libjson-c/debug.c new file mode 100644 index 0000000000..3b64b59052 --- /dev/null +++ b/release/src/router/libjson-c/debug.c @@ -0,0 +1,83 @@ +/* + * $Id: debug.c,v 1.5 2006/01/26 02:16:28 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#include "config.h" + +#include +#include +#include +#include + +#if HAVE_SYSLOG_H +# include +#endif /* HAVE_SYSLOG_H */ + +#if HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ + +#if HAVE_SYS_PARAM_H +#include +#endif /* HAVE_SYS_PARAM_H */ + +#include "debug.h" + +static int _syslog = 0; +static int _debug = 0; + +void mc_set_debug(int debug) { _debug = debug; } +int mc_get_debug(void) { return _debug; } + +extern void mc_set_syslog(int syslog) +{ + _syslog = syslog; +} + +void mc_debug(const char *msg, ...) +{ + va_list ap; + if(_debug) { + va_start(ap, msg); +#if HAVE_VSYSLOG + if(_syslog) { + vsyslog(LOG_DEBUG, msg, ap); + } else +#endif + vprintf(msg, ap); + va_end(ap); + } +} + +void mc_error(const char *msg, ...) +{ + va_list ap; + va_start(ap, msg); +#if HAVE_VSYSLOG + if(_syslog) { + vsyslog(LOG_ERR, msg, ap); + } else +#endif + vfprintf(stderr, msg, ap); + va_end(ap); +} + +void mc_info(const char *msg, ...) +{ + va_list ap; + va_start(ap, msg); +#if HAVE_VSYSLOG + if(_syslog) { + vsyslog(LOG_INFO, msg, ap); + } else +#endif + vfprintf(stderr, msg, ap); + va_end(ap); +} diff --git a/release/src/router/libjson-c/debug.h b/release/src/router/libjson-c/debug.h new file mode 100644 index 0000000000..80ca3e4304 --- /dev/null +++ b/release/src/router/libjson-c/debug.h @@ -0,0 +1,71 @@ +/* + * $Id: debug.h,v 1.5 2006/01/30 23:07:57 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern void mc_set_debug(int debug); +extern int mc_get_debug(void); + +extern void mc_set_syslog(int syslog); + +extern void mc_debug(const char *msg, ...); +extern void mc_error(const char *msg, ...); +extern void mc_info(const char *msg, ...); + +#ifndef __STRING +#define __STRING(x) #x +#endif + +#ifndef PARSER_BROKEN_FIXED + +#define JASSERT(cond) do {} while(0) + +#else + +#define JASSERT(cond) do { \ + if (!(cond)) { \ + mc_error("cjson assert failure %s:%d : cond \"" __STRING(cond) "failed\n", __FILE__, __LINE__); \ + *(int *)0 = 1;\ + abort(); \ + }\ + } while(0) + +#endif + +#define MC_ERROR(x, ...) mc_error(x, ##__VA_ARGS__) + +#ifdef MC_MAINTAINER_MODE +#define MC_SET_DEBUG(x) mc_set_debug(x) +#define MC_GET_DEBUG() mc_get_debug() +#define MC_SET_SYSLOG(x) mc_set_syslog(x) +#define MC_DEBUG(x, ...) mc_debug(x, ##__VA_ARGS__) +#define MC_INFO(x, ...) mc_info(x, ##__VA_ARGS__) +#else +#define MC_SET_DEBUG(x) if (0) mc_set_debug(x) +#define MC_GET_DEBUG() (0) +#define MC_SET_SYSLOG(x) if (0) mc_set_syslog(x) +#define MC_DEBUG(x, ...) if (0) mc_debug(x, ##__VA_ARGS__) +#define MC_INFO(x, ...) if (0) mc_info(x, ##__VA_ARGS__) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/release/src/router/libjson-c/json-c-uninstalled.pc.in b/release/src/router/libjson-c/json-c-uninstalled.pc.in new file mode 100644 index 0000000000..dab2bab5ce --- /dev/null +++ b/release/src/router/libjson-c/json-c-uninstalled.pc.in @@ -0,0 +1,11 @@ +prefix= +exec_prefix= +libdir=@abs_top_builddir@ +includedir=@abs_top_srcdir@ + +Name: json +Description: JSON implementation in C +Version: @VERSION@ +Requires: +Libs: -L@abs_top_builddir@ -ljson-c +Cflags: -I@abs_top_srcdir@ diff --git a/release/src/router/libjson-c/json-c.pc.in b/release/src/router/libjson-c/json-c.pc.in new file mode 100644 index 0000000000..037739d27b --- /dev/null +++ b/release/src/router/libjson-c/json-c.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: json-c +Description: JSON implementation in C +Version: @VERSION@ +Requires: +Libs: -L${libdir} -ljson-c +Cflags: -I${includedir}/json-c diff --git a/release/src/router/libjson-c/json-c.vcproj b/release/src/router/libjson-c/json-c.vcproj new file mode 100644 index 0000000000..0b88754459 --- /dev/null +++ b/release/src/router/libjson-c/json-c.vcproj @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/release/src/router/libjson-c/json.h b/release/src/router/libjson-c/json.h new file mode 100644 index 0000000000..4339b20e90 --- /dev/null +++ b/release/src/router/libjson-c/json.h @@ -0,0 +1,34 @@ +/* + * $Id: json.h,v 1.6 2006/01/26 02:16:28 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef _json_h_ +#define _json_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "bits.h" +#include "debug.h" +#include "linkhash.h" +#include "arraylist.h" +#include "json_util.h" +#include "json_object.h" +#include "json_tokener.h" +#include "json_object_iterator.h" +#include "json_c_version.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/release/src/router/libjson-c/json_c_version.c b/release/src/router/libjson-c/json_c_version.c new file mode 100644 index 0000000000..13eb188554 --- /dev/null +++ b/release/src/router/libjson-c/json_c_version.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2012 Eric Haszlakiewicz + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + */ +#include "config.h" + +#include "json_c_version.h" + +const char *json_c_version(void) +{ + return JSON_C_VERSION; +} + +int json_c_version_num(void) +{ + return JSON_C_VERSION_NUM; +} + diff --git a/release/src/router/libjson-c/json_c_version.h b/release/src/router/libjson-c/json_c_version.h new file mode 100644 index 0000000000..eed98a4975 --- /dev/null +++ b/release/src/router/libjson-c/json_c_version.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2012 Eric Haszlakiewicz + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + */ + +#ifndef _json_c_version_h_ +#define _json_c_version_h_ + +#define JSON_C_MAJOR_VERSION 0 +#define JSON_C_MINOR_VERSION 12 +#define JSON_C_MICRO_VERSION 0 +#define JSON_C_VERSION_NUM ((JSON_C_MAJOR_VERSION << 16) | \ + (JSON_C_MINOR_VERSION << 8) | \ + JSON_C_MICRO_VERSION) +#define JSON_C_VERSION "0.12" + +const char *json_c_version(void); /* Returns JSON_C_VERSION */ +int json_c_version_num(void); /* Returns JSON_C_VERSION_NUM */ + +#endif diff --git a/release/src/router/libjson-c/json_config.h.in b/release/src/router/libjson-c/json_config.h.in new file mode 100644 index 0000000000..7888e02170 --- /dev/null +++ b/release/src/router/libjson-c/json_config.h.in @@ -0,0 +1,3 @@ + +/* Define to 1 if you have the header file. */ +#undef JSON_C_HAVE_INTTYPES_H diff --git a/release/src/router/libjson-c/json_inttypes.h b/release/src/router/libjson-c/json_inttypes.h new file mode 100644 index 0000000000..9de8d246d9 --- /dev/null +++ b/release/src/router/libjson-c/json_inttypes.h @@ -0,0 +1,28 @@ + +#ifndef _json_inttypes_h_ +#define _json_inttypes_h_ + +#include "json_config.h" + +#if defined(_MSC_VER) && _MSC_VER <= 1700 + +/* Anything less than Visual Studio C++ 10 is missing stdint.h and inttypes.h */ +typedef __int32 int32_t; +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX ((int32_t)_I32_MAX) +typedef __int64 int64_t; +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX ((int64_t)_I64_MAX) +#define PRId64 "I64d" +#define SCNd64 "I64d" + +#else + +#ifdef JSON_C_HAVE_INTTYPES_H +#include +#endif +/* inttypes.h includes stdint.h */ + +#endif + +#endif diff --git a/release/src/router/libjson-c/json_object.c b/release/src/router/libjson-c/json_object.c new file mode 100644 index 0000000000..6cc73bce8c --- /dev/null +++ b/release/src/router/libjson-c/json_object.c @@ -0,0 +1,855 @@ +/* + * $Id: json_object.c,v 1.17 2006/07/25 03:24:50 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "printbuf.h" +#include "linkhash.h" +#include "arraylist.h" +#include "json_inttypes.h" +#include "json_object.h" +#include "json_object_private.h" +#include "json_util.h" +#include "math_compat.h" + +#if !defined(HAVE_STRDUP) && defined(_MSC_VER) + /* MSC has the version as _strdup */ +# define strdup _strdup +#elif !defined(HAVE_STRDUP) +# error You do not have strdup on your system. +#endif /* HAVE_STRDUP */ + +#if !defined(HAVE_SNPRINTF) && defined(_MSC_VER) + /* MSC has the version as _snprintf */ +# define snprintf _snprintf +#elif !defined(HAVE_SNPRINTF) +# error You do not have snprintf on your system. +#endif /* HAVE_SNPRINTF */ + +// Don't define this. It's not thread-safe. +/* #define REFCOUNT_DEBUG 1 */ + +const char *json_number_chars = "0123456789.+-eE"; +const char *json_hex_chars = "0123456789abcdefABCDEF"; + +static void json_object_generic_delete(struct json_object* jso); +static struct json_object* json_object_new(enum json_type o_type); + +static json_object_to_json_string_fn json_object_object_to_json_string; +static json_object_to_json_string_fn json_object_boolean_to_json_string; +static json_object_to_json_string_fn json_object_int_to_json_string; +static json_object_to_json_string_fn json_object_double_to_json_string; +static json_object_to_json_string_fn json_object_string_to_json_string; +static json_object_to_json_string_fn json_object_array_to_json_string; + + +/* ref count debugging */ + +#ifdef REFCOUNT_DEBUG + +static struct lh_table *json_object_table; + +static void json_object_init(void) __attribute__ ((constructor)); +static void json_object_init(void) { + MC_DEBUG("json_object_init: creating object table\n"); + json_object_table = lh_kptr_table_new(128, "json_object_table", NULL); +} + +static void json_object_fini(void) __attribute__ ((destructor)); +static void json_object_fini(void) { + struct lh_entry *ent; + if(MC_GET_DEBUG()) { + if (json_object_table->count) { + MC_DEBUG("json_object_fini: %d referenced objects at exit\n", + json_object_table->count); + lh_foreach(json_object_table, ent) { + struct json_object* obj = (struct json_object*)ent->v; + MC_DEBUG("\t%s:%p\n", json_type_to_name(obj->o_type), obj); + } + } + } + MC_DEBUG("json_object_fini: freeing object table\n"); + lh_table_free(json_object_table); +} +#endif /* REFCOUNT_DEBUG */ + + +/* string escaping */ + +static int json_escape_str(struct printbuf *pb, char *str, int len) +{ + int pos = 0, start_offset = 0; + unsigned char c; + while (len--) { + c = str[pos]; + switch(c) { + case '\b': + case '\n': + case '\r': + case '\t': + case '\f': + case '"': + case '\\': + case '/': + if(pos - start_offset > 0) + printbuf_memappend(pb, str + start_offset, pos - start_offset); + if(c == '\b') printbuf_memappend(pb, "\\b", 2); + else if(c == '\n') printbuf_memappend(pb, "\\n", 2); + else if(c == '\r') printbuf_memappend(pb, "\\r", 2); + else if(c == '\t') printbuf_memappend(pb, "\\t", 2); + else if(c == '\f') printbuf_memappend(pb, "\\f", 2); + else if(c == '"') printbuf_memappend(pb, "\\\"", 2); + else if(c == '\\') printbuf_memappend(pb, "\\\\", 2); + else if(c == '/') printbuf_memappend(pb, "\\/", 2); + start_offset = ++pos; + break; + default: + if(c < ' ') { + if(pos - start_offset > 0) + printbuf_memappend(pb, str + start_offset, pos - start_offset); + sprintbuf(pb, "\\u00%c%c", + json_hex_chars[c >> 4], + json_hex_chars[c & 0xf]); + start_offset = ++pos; + } else pos++; + } + } + if(pos - start_offset > 0) + printbuf_memappend(pb, str + start_offset, pos - start_offset); + return 0; +} + + +/* reference counting */ + +extern struct json_object* json_object_get(struct json_object *jso) +{ + if(jso) { + jso->_ref_count++; + } + return jso; +} + +int json_object_put(struct json_object *jso) +{ + if(jso) + { + jso->_ref_count--; + if(!jso->_ref_count) + { + if (jso->_user_delete) + jso->_user_delete(jso, jso->_userdata); + jso->_delete(jso); + return 1; + } + } + return 0; +} + + +/* generic object construction and destruction parts */ + +static void json_object_generic_delete(struct json_object* jso) +{ +#ifdef REFCOUNT_DEBUG + MC_DEBUG("json_object_delete_%s: %p\n", + json_type_to_name(jso->o_type), jso); + lh_table_delete(json_object_table, jso); +#endif /* REFCOUNT_DEBUG */ + printbuf_free(jso->_pb); + free(jso); +} + +static struct json_object* json_object_new(enum json_type o_type) +{ + struct json_object *jso; + + jso = (struct json_object*)calloc(sizeof(struct json_object), 1); + if(!jso) return NULL; + jso->o_type = o_type; + jso->_ref_count = 1; + jso->_delete = &json_object_generic_delete; +#ifdef REFCOUNT_DEBUG + lh_table_insert(json_object_table, jso, jso); + MC_DEBUG("json_object_new_%s: %p\n", json_type_to_name(jso->o_type), jso); +#endif /* REFCOUNT_DEBUG */ + return jso; +} + + +/* type checking functions */ + +int json_object_is_type(struct json_object *jso, enum json_type type) +{ + if (!jso) + return (type == json_type_null); + return (jso->o_type == type); +} + +enum json_type json_object_get_type(struct json_object *jso) +{ + if (!jso) + return json_type_null; + return jso->o_type; +} + +/* set a custom conversion to string */ + +void json_object_set_serializer(json_object *jso, + json_object_to_json_string_fn to_string_func, + void *userdata, + json_object_delete_fn *user_delete) +{ + // First, clean up any previously existing user info + if (jso->_user_delete) + { + jso->_user_delete(jso, jso->_userdata); + } + jso->_userdata = NULL; + jso->_user_delete = NULL; + + if (to_string_func == NULL) + { + // Reset to the standard serialization function + switch(jso->o_type) + { + case json_type_null: + jso->_to_json_string = NULL; + break; + case json_type_boolean: + jso->_to_json_string = &json_object_boolean_to_json_string; + break; + case json_type_double: + jso->_to_json_string = &json_object_double_to_json_string; + break; + case json_type_int: + jso->_to_json_string = &json_object_int_to_json_string; + break; + case json_type_object: + jso->_to_json_string = &json_object_object_to_json_string; + break; + case json_type_array: + jso->_to_json_string = &json_object_array_to_json_string; + break; + case json_type_string: + jso->_to_json_string = &json_object_string_to_json_string; + break; + } + return; + } + + jso->_to_json_string = to_string_func; + jso->_userdata = userdata; + jso->_user_delete = user_delete; +} + + +/* extended conversion to string */ + +const char* json_object_to_json_string_ext(struct json_object *jso, int flags) +{ + if (!jso) + return "null"; + + if ((!jso->_pb) && !(jso->_pb = printbuf_new())) + return NULL; + + printbuf_reset(jso->_pb); + + if(jso->_to_json_string(jso, jso->_pb, 0, flags) < 0) + return NULL; + + return jso->_pb->buf; +} + +/* backwards-compatible conversion to string */ + +const char* json_object_to_json_string(struct json_object *jso) +{ + return json_object_to_json_string_ext(jso, JSON_C_TO_STRING_SPACED); +} + +static void indent(struct printbuf *pb, int level, int flags) +{ + if (flags & JSON_C_TO_STRING_PRETTY) + { + printbuf_memset(pb, -1, ' ', level * 2); + } +} + +/* json_object_object */ + +static int json_object_object_to_json_string(struct json_object* jso, + struct printbuf *pb, + int level, + int flags) +{ + int had_children = 0; + struct json_object_iter iter; + + sprintbuf(pb, "{" /*}*/); + if (flags & JSON_C_TO_STRING_PRETTY) + sprintbuf(pb, "\n"); + json_object_object_foreachC(jso, iter) + { + if (had_children) + { + sprintbuf(pb, ","); + if (flags & JSON_C_TO_STRING_PRETTY) + sprintbuf(pb, "\n"); + } + had_children = 1; + if (flags & JSON_C_TO_STRING_SPACED) + sprintbuf(pb, " "); + indent(pb, level+1, flags); + sprintbuf(pb, "\""); + json_escape_str(pb, iter.key, strlen(iter.key)); + if (flags & JSON_C_TO_STRING_SPACED) + sprintbuf(pb, "\": "); + else + sprintbuf(pb, "\":"); + if(iter.val == NULL) + sprintbuf(pb, "null"); + else + iter.val->_to_json_string(iter.val, pb, level+1,flags); + } + if (flags & JSON_C_TO_STRING_PRETTY) + { + if (had_children) + sprintbuf(pb, "\n"); + indent(pb,level,flags); + } + if (flags & JSON_C_TO_STRING_SPACED) + return sprintbuf(pb, /*{*/ " }"); + else + return sprintbuf(pb, /*{*/ "}"); +} + + +static void json_object_lh_entry_free(struct lh_entry *ent) +{ + free(ent->k); + json_object_put((struct json_object*)ent->v); +} + +static void json_object_object_delete(struct json_object* jso) +{ + lh_table_free(jso->o.c_object); + json_object_generic_delete(jso); +} + +struct json_object* json_object_new_object(void) +{ + struct json_object *jso = json_object_new(json_type_object); + if(!jso) return NULL; + jso->_delete = &json_object_object_delete; + jso->_to_json_string = &json_object_object_to_json_string; + jso->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTRIES, + NULL, &json_object_lh_entry_free); + return jso; +} + +struct lh_table* json_object_get_object(struct json_object *jso) +{ + if(!jso) return NULL; + switch(jso->o_type) { + case json_type_object: + return jso->o.c_object; + default: + return NULL; + } +} + +void json_object_object_add(struct json_object* jso, const char *key, + struct json_object *val) +{ + // We lookup the entry and replace the value, rather than just deleting + // and re-adding it, so the existing key remains valid. + json_object *existing_value = NULL; + struct lh_entry *existing_entry; + existing_entry = lh_table_lookup_entry(jso->o.c_object, (void*)key); + if (!existing_entry) + { + lh_table_insert(jso->o.c_object, strdup(key), val); + return; + } + existing_value = (void *)existing_entry->v; + if (existing_value) + json_object_put(existing_value); + existing_entry->v = val; +} + +int json_object_object_length(struct json_object *jso) +{ + return lh_table_length(jso->o.c_object); +} + +struct json_object* json_object_object_get(struct json_object* jso, const char *key) +{ + struct json_object *result = NULL; + json_object_object_get_ex(jso, key, &result); + return result; +} + +json_bool json_object_object_get_ex(struct json_object* jso, const char *key, struct json_object **value) +{ + if (value != NULL) + *value = NULL; + + if (NULL == jso) + return FALSE; + + switch(jso->o_type) + { + case json_type_object: + return lh_table_lookup_ex(jso->o.c_object, (void*)key, (void**)value); + default: + if (value != NULL) + *value = NULL; + return FALSE; + } +} + +void json_object_object_del(struct json_object* jso, const char *key) +{ + lh_table_delete(jso->o.c_object, key); +} + + +/* json_object_boolean */ + +static int json_object_boolean_to_json_string(struct json_object* jso, + struct printbuf *pb, + int level, + int flags) +{ + if(jso->o.c_boolean) return sprintbuf(pb, "true"); + else return sprintbuf(pb, "false"); +} + +struct json_object* json_object_new_boolean(json_bool b) +{ + struct json_object *jso = json_object_new(json_type_boolean); + if(!jso) return NULL; + jso->_to_json_string = &json_object_boolean_to_json_string; + jso->o.c_boolean = b; + return jso; +} + +json_bool json_object_get_boolean(struct json_object *jso) +{ + if(!jso) return FALSE; + switch(jso->o_type) { + case json_type_boolean: + return jso->o.c_boolean; + case json_type_int: + return (jso->o.c_int64 != 0); + case json_type_double: + return (jso->o.c_double != 0); + case json_type_string: + return (jso->o.c_string.len != 0); + default: + return FALSE; + } +} + + +/* json_object_int */ + +static int json_object_int_to_json_string(struct json_object* jso, + struct printbuf *pb, + int level, + int flags) +{ + return sprintbuf(pb, "%"PRId64, jso->o.c_int64); +} + +struct json_object* json_object_new_int(int32_t i) +{ + struct json_object *jso = json_object_new(json_type_int); + if(!jso) return NULL; + jso->_to_json_string = &json_object_int_to_json_string; + jso->o.c_int64 = i; + return jso; +} + +int32_t json_object_get_int(struct json_object *jso) +{ + int64_t cint64; + enum json_type o_type; + + if(!jso) return 0; + + o_type = jso->o_type; + cint64 = jso->o.c_int64; + + if (o_type == json_type_string) + { + /* + * Parse strings into 64-bit numbers, then use the + * 64-to-32-bit number handling below. + */ + if (json_parse_int64(jso->o.c_string.str, &cint64) != 0) + return 0; /* whoops, it didn't work. */ + o_type = json_type_int; + } + + switch(o_type) { + case json_type_int: + /* Make sure we return the correct values for out of range numbers. */ + if (cint64 <= INT32_MIN) + return INT32_MIN; + else if (cint64 >= INT32_MAX) + return INT32_MAX; + else + return (int32_t)cint64; + case json_type_double: + return (int32_t)jso->o.c_double; + case json_type_boolean: + return jso->o.c_boolean; + default: + return 0; + } +} + +struct json_object* json_object_new_int64(int64_t i) +{ + struct json_object *jso = json_object_new(json_type_int); + if(!jso) return NULL; + jso->_to_json_string = &json_object_int_to_json_string; + jso->o.c_int64 = i; + return jso; +} + +int64_t json_object_get_int64(struct json_object *jso) +{ + int64_t cint; + + if(!jso) return 0; + switch(jso->o_type) { + case json_type_int: + return jso->o.c_int64; + case json_type_double: + return (int64_t)jso->o.c_double; + case json_type_boolean: + return jso->o.c_boolean; + case json_type_string: + if (json_parse_int64(jso->o.c_string.str, &cint) == 0) return cint; + default: + return 0; + } +} + + +/* json_object_double */ + +static int json_object_double_to_json_string(struct json_object* jso, + struct printbuf *pb, + int level, + int flags) +{ + char buf[128], *p, *q; + int size; + /* Although JSON RFC does not support + NaN or Infinity as numeric values + ECMA 262 section 9.8.1 defines + how to handle these cases as strings */ + if(isnan(jso->o.c_double)) + size = snprintf(buf, sizeof(buf), "NaN"); + else if(isinf(jso->o.c_double)) + if(jso->o.c_double > 0) + size = snprintf(buf, sizeof(buf), "Infinity"); + else + size = snprintf(buf, sizeof(buf), "-Infinity"); + else + size = snprintf(buf, sizeof(buf), "%.17g", jso->o.c_double); + + p = strchr(buf, ','); + if (p) { + *p = '.'; + } else { + p = strchr(buf, '.'); + } + if (p && (flags & JSON_C_TO_STRING_NOZERO)) { + /* last useful digit, always keep 1 zero */ + p++; + for (q=p ; *q ; q++) { + if (*q!='0') p=q; + } + /* drop trailing zeroes */ + *(++p) = 0; + size = p-buf; + } + printbuf_memappend(pb, buf, size); + return size; +} + +struct json_object* json_object_new_double(double d) +{ + struct json_object *jso = json_object_new(json_type_double); + if (!jso) + return NULL; + jso->_to_json_string = &json_object_double_to_json_string; + jso->o.c_double = d; + return jso; +} + +struct json_object* json_object_new_double_s(double d, const char *ds) +{ + struct json_object *jso = json_object_new_double(d); + if (!jso) + return NULL; + + json_object_set_serializer(jso, json_object_userdata_to_json_string, + strdup(ds), json_object_free_userdata); + return jso; +} + +int json_object_userdata_to_json_string(struct json_object *jso, + struct printbuf *pb, int level, int flags) +{ + int userdata_len = strlen(jso->_userdata); + printbuf_memappend(pb, jso->_userdata, userdata_len); + return userdata_len; +} + +void json_object_free_userdata(struct json_object *jso, void *userdata) +{ + free(userdata); +} + +double json_object_get_double(struct json_object *jso) +{ + double cdouble; + char *errPtr = NULL; + + if(!jso) return 0.0; + switch(jso->o_type) { + case json_type_double: + return jso->o.c_double; + case json_type_int: + return jso->o.c_int64; + case json_type_boolean: + return jso->o.c_boolean; + case json_type_string: + errno = 0; + cdouble = strtod(jso->o.c_string.str,&errPtr); + + /* if conversion stopped at the first character, return 0.0 */ + if (errPtr == jso->o.c_string.str) + return 0.0; + + /* + * Check that the conversion terminated on something sensible + * + * For example, { "pay" : 123AB } would parse as 123. + */ + if (*errPtr != '\0') + return 0.0; + + /* + * If strtod encounters a string which would exceed the + * capacity of a double, it returns +/- HUGE_VAL and sets + * errno to ERANGE. But +/- HUGE_VAL is also a valid result + * from a conversion, so we need to check errno. + * + * Underflow also sets errno to ERANGE, but it returns 0 in + * that case, which is what we will return anyway. + * + * See CERT guideline ERR30-C + */ + if ((HUGE_VAL == cdouble || -HUGE_VAL == cdouble) && + (ERANGE == errno)) + cdouble = 0.0; + return cdouble; + default: + return 0.0; + } +} + + +/* json_object_string */ + +static int json_object_string_to_json_string(struct json_object* jso, + struct printbuf *pb, + int level, + int flags) +{ + sprintbuf(pb, "\""); + json_escape_str(pb, jso->o.c_string.str, jso->o.c_string.len); + sprintbuf(pb, "\""); + return 0; +} + +static void json_object_string_delete(struct json_object* jso) +{ + free(jso->o.c_string.str); + json_object_generic_delete(jso); +} + +struct json_object* json_object_new_string(const char *s) +{ + struct json_object *jso = json_object_new(json_type_string); + if(!jso) return NULL; + jso->_delete = &json_object_string_delete; + jso->_to_json_string = &json_object_string_to_json_string; + jso->o.c_string.str = strdup(s); + jso->o.c_string.len = strlen(s); + return jso; +} + +struct json_object* json_object_new_string_len(const char *s, int len) +{ + struct json_object *jso = json_object_new(json_type_string); + if(!jso) return NULL; + jso->_delete = &json_object_string_delete; + jso->_to_json_string = &json_object_string_to_json_string; + jso->o.c_string.str = (char*)malloc(len + 1); + memcpy(jso->o.c_string.str, (void *)s, len); + jso->o.c_string.str[len] = '\0'; + jso->o.c_string.len = len; + return jso; +} + +const char* json_object_get_string(struct json_object *jso) +{ + if(!jso) return NULL; + switch(jso->o_type) { + case json_type_string: + return jso->o.c_string.str; + default: + return json_object_to_json_string(jso); + } +} + +int json_object_get_string_len(struct json_object *jso) { + if(!jso) return 0; + switch(jso->o_type) { + case json_type_string: + return jso->o.c_string.len; + default: + return 0; + } +} + + +/* json_object_array */ + +static int json_object_array_to_json_string(struct json_object* jso, + struct printbuf *pb, + int level, + int flags) +{ + int had_children = 0; + int ii; + sprintbuf(pb, "["); + if (flags & JSON_C_TO_STRING_PRETTY) + sprintbuf(pb, "\n"); + for(ii=0; ii < json_object_array_length(jso); ii++) + { + struct json_object *val; + if (had_children) + { + sprintbuf(pb, ","); + if (flags & JSON_C_TO_STRING_PRETTY) + sprintbuf(pb, "\n"); + } + had_children = 1; + if (flags & JSON_C_TO_STRING_SPACED) + sprintbuf(pb, " "); + indent(pb, level + 1, flags); + val = json_object_array_get_idx(jso, ii); + if(val == NULL) + sprintbuf(pb, "null"); + else + val->_to_json_string(val, pb, level+1, flags); + } + if (flags & JSON_C_TO_STRING_PRETTY) + { + if (had_children) + sprintbuf(pb, "\n"); + indent(pb,level,flags); + } + + if (flags & JSON_C_TO_STRING_SPACED) + return sprintbuf(pb, " ]"); + else + return sprintbuf(pb, "]"); +} + +static void json_object_array_entry_free(void *data) +{ + json_object_put((struct json_object*)data); +} + +static void json_object_array_delete(struct json_object* jso) +{ + array_list_free(jso->o.c_array); + json_object_generic_delete(jso); +} + +struct json_object* json_object_new_array(void) +{ + struct json_object *jso = json_object_new(json_type_array); + if(!jso) return NULL; + jso->_delete = &json_object_array_delete; + jso->_to_json_string = &json_object_array_to_json_string; + jso->o.c_array = array_list_new(&json_object_array_entry_free); + return jso; +} + +struct array_list* json_object_get_array(struct json_object *jso) +{ + if(!jso) return NULL; + switch(jso->o_type) { + case json_type_array: + return jso->o.c_array; + default: + return NULL; + } +} + +void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const void *, const void *)) +{ + array_list_sort(jso->o.c_array, sort_fn); +} + +int json_object_array_length(struct json_object *jso) +{ + return array_list_length(jso->o.c_array); +} + +int json_object_array_add(struct json_object *jso,struct json_object *val) +{ + return array_list_add(jso->o.c_array, val); +} + +int json_object_array_put_idx(struct json_object *jso, int idx, + struct json_object *val) +{ + return array_list_put_idx(jso->o.c_array, idx, val); +} + +struct json_object* json_object_array_get_idx(struct json_object *jso, + int idx) +{ + return (struct json_object*)array_list_get_idx(jso->o.c_array, idx); +} + diff --git a/release/src/router/libjson-c/json_object.h b/release/src/router/libjson-c/json_object.h new file mode 100644 index 0000000000..200ac4031d --- /dev/null +++ b/release/src/router/libjson-c/json_object.h @@ -0,0 +1,612 @@ +/* + * $Id: json_object.h,v 1.12 2006/01/30 23:07:57 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef _json_object_h_ +#define _json_object_h_ + +#ifdef __GNUC__ +#define THIS_FUNCTION_IS_DEPRECATED(func) func __attribute__ ((deprecated)) +#elif defined(_MSC_VER) +#define THIS_FUNCTION_IS_DEPRECATED(func) __declspec(deprecated) func +#else +#define THIS_FUNCTION_IS_DEPRECATED(func) func +#endif + +#include "json_inttypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define JSON_OBJECT_DEF_HASH_ENTRIES 16 + +/** + * A flag for the json_object_to_json_string_ext() and + * json_object_to_file_ext() functions which causes the output + * to have no extra whitespace or formatting applied. + */ +#define JSON_C_TO_STRING_PLAIN 0 +/** + * A flag for the json_object_to_json_string_ext() and + * json_object_to_file_ext() functions which causes the output to have + * minimal whitespace inserted to make things slightly more readable. + */ +#define JSON_C_TO_STRING_SPACED (1<<0) +/** + * A flag for the json_object_to_json_string_ext() and + * json_object_to_file_ext() functions which causes + * the output to be formatted. + * + * See the "Two Space Tab" option at http://jsonformatter.curiousconcept.com/ + * for an example of the format. + */ +#define JSON_C_TO_STRING_PRETTY (1<<1) +/** + * A flag to drop trailing zero for float values + */ +#define JSON_C_TO_STRING_NOZERO (1<<2) + +#undef FALSE +#define FALSE ((json_bool)0) + +#undef TRUE +#define TRUE ((json_bool)1) + +extern const char *json_number_chars; +extern const char *json_hex_chars; + +/* CAW: added for ANSI C iteration correctness */ +struct json_object_iter +{ + char *key; + struct json_object *val; + struct lh_entry *entry; +}; + +/* forward structure definitions */ + +typedef int json_bool; +typedef struct printbuf printbuf; +typedef struct lh_table lh_table; +typedef struct array_list array_list; +typedef struct json_object json_object; +typedef struct json_object_iter json_object_iter; +typedef struct json_tokener json_tokener; + +/** + * Type of custom user delete functions. See json_object_set_serializer. + */ +typedef void (json_object_delete_fn)(struct json_object *jso, void *userdata); + +/** + * Type of a custom serialization function. See json_object_set_serializer. + */ +typedef int (json_object_to_json_string_fn)(struct json_object *jso, + struct printbuf *pb, + int level, + int flags); + +/* supported object types */ + +typedef enum json_type { + /* If you change this, be sure to update json_type_to_name() too */ + json_type_null, + json_type_boolean, + json_type_double, + json_type_int, + json_type_object, + json_type_array, + json_type_string, +} json_type; + +/* reference counting functions */ + +/** + * Increment the reference count of json_object, thereby grabbing shared + * ownership of obj. + * + * @param obj the json_object instance + */ +extern struct json_object* json_object_get(struct json_object *obj); + +/** + * Decrement the reference count of json_object and free if it reaches zero. + * You must have ownership of obj prior to doing this or you will cause an + * imbalance in the reference count. + * + * @param obj the json_object instance + * @returns 1 if the object was freed. + */ +int json_object_put(struct json_object *obj); + +/** + * Check if the json_object is of a given type + * @param obj the json_object instance + * @param type one of: + json_type_null (i.e. obj == NULL), + json_type_boolean, + json_type_double, + json_type_int, + json_type_object, + json_type_array, + json_type_string, + */ +extern int json_object_is_type(struct json_object *obj, enum json_type type); + +/** + * Get the type of the json_object. See also json_type_to_name() to turn this + * into a string suitable, for instance, for logging. + * + * @param obj the json_object instance + * @returns type being one of: + json_type_null (i.e. obj == NULL), + json_type_boolean, + json_type_double, + json_type_int, + json_type_object, + json_type_array, + json_type_string, + */ +extern enum json_type json_object_get_type(struct json_object *obj); + + +/** Stringify object to json format. + * Equivalent to json_object_to_json_string_ext(obj, JSON_C_TO_STRING_SPACED) + * @param obj the json_object instance + * @returns a string in JSON format + */ +extern const char* json_object_to_json_string(struct json_object *obj); + +/** Stringify object to json format + * @param obj the json_object instance + * @param flags formatting options, see JSON_C_TO_STRING_PRETTY and other constants + * @returns a string in JSON format + */ +extern const char* json_object_to_json_string_ext(struct json_object *obj, int +flags); + +/** + * Set a custom serialization function to be used when this particular object + * is converted to a string by json_object_to_json_string. + * + * If a custom serializer is already set on this object, any existing + * user_delete function is called before the new one is set. + * + * If to_string_func is NULL, the other parameters are ignored + * and the default behaviour is reset. + * + * The userdata parameter is optional and may be passed as NULL. If provided, + * it is passed to to_string_func as-is. This parameter may be NULL even + * if user_delete is non-NULL. + * + * The user_delete parameter is optional and may be passed as NULL, even if + * the userdata parameter is non-NULL. It will be called just before the + * json_object is deleted, after it's reference count goes to zero + * (see json_object_put()). + * If this is not provided, it is up to the caller to free the userdata at + * an appropriate time. (i.e. after the json_object is deleted) + * + * @param jso the object to customize + * @param to_string_func the custom serialization function + * @param userdata an optional opaque cookie + * @param user_delete an optional function from freeing userdata + */ +extern void json_object_set_serializer(json_object *jso, + json_object_to_json_string_fn to_string_func, + void *userdata, + json_object_delete_fn *user_delete); + +/** + * Simply call free on the userdata pointer. + * Can be used with json_object_set_serializer(). + * + * @param jso unused + * @param userdata the pointer that is passed to free(). + */ +json_object_delete_fn json_object_free_userdata; + +/** + * Copy the jso->_userdata string over to pb as-is. + * Can be used with json_object_set_serializer(). + * + * @param jso The object whose _userdata is used. + * @param pb The destination buffer. + * @param level Ignored. + * @param flags Ignored. + */ +json_object_to_json_string_fn json_object_userdata_to_json_string; + + +/* object type methods */ + +/** Create a new empty object with a reference count of 1. The caller of + * this object initially has sole ownership. Remember, when using + * json_object_object_add or json_object_array_put_idx, ownership will + * transfer to the object/array. Call json_object_get if you want to maintain + * shared ownership or also add this object as a child of multiple objects or + * arrays. Any ownerships you acquired but did not transfer must be released + * through json_object_put. + * + * @returns a json_object of type json_type_object + */ +extern struct json_object* json_object_new_object(void); + +/** Get the hashtable of a json_object of type json_type_object + * @param obj the json_object instance + * @returns a linkhash + */ +extern struct lh_table* json_object_get_object(struct json_object *obj); + +/** Get the size of an object in terms of the number of fields it has. + * @param obj the json_object whose length to return + */ +extern int json_object_object_length(struct json_object* obj); + +/** Add an object field to a json_object of type json_type_object + * + * The reference count will *not* be incremented. This is to make adding + * fields to objects in code more compact. If you want to retain a reference + * to an added object, independent of the lifetime of obj, you must wrap the + * passed object with json_object_get. + * + * Upon calling this, the ownership of val transfers to obj. Thus you must + * make sure that you do in fact have ownership over this object. For instance, + * json_object_new_object will give you ownership until you transfer it, + * whereas json_object_object_get does not. + * + * @param obj the json_object instance + * @param key the object field name (a private copy will be duplicated) + * @param val a json_object or NULL member to associate with the given field + */ +extern void json_object_object_add(struct json_object* obj, const char *key, + struct json_object *val); + +/** Get the json_object associate with a given object field + * + * *No* reference counts will be changed. There is no need to manually adjust + * reference counts through the json_object_put/json_object_get methods unless + * you need to have the child (value) reference maintain a different lifetime + * than the owning parent (obj). Ownership of the returned value is retained + * by obj (do not do json_object_put unless you have done a json_object_get). + * If you delete the value from obj (json_object_object_del) and wish to access + * the returned reference afterwards, make sure you have first gotten shared + * ownership through json_object_get (& don't forget to do a json_object_put + * or transfer ownership to prevent a memory leak). + * + * @param obj the json_object instance + * @param key the object field name + * @returns the json_object associated with the given field name + * @deprecated Please use json_object_object_get_ex + */ +THIS_FUNCTION_IS_DEPRECATED(extern struct json_object* json_object_object_get(struct json_object* obj, + const char *key)); + +/** Get the json_object associated with a given object field. + * + * This returns true if the key is found, false in all other cases (including + * if obj isn't a json_type_object). + * + * *No* reference counts will be changed. There is no need to manually adjust + * reference counts through the json_object_put/json_object_get methods unless + * you need to have the child (value) reference maintain a different lifetime + * than the owning parent (obj). Ownership of value is retained by obj. + * + * @param obj the json_object instance + * @param key the object field name + * @param value a pointer where to store a reference to the json_object + * associated with the given field name. + * + * It is safe to pass a NULL value. + * @returns whether or not the key exists + */ +extern json_bool json_object_object_get_ex(struct json_object* obj, + const char *key, + struct json_object **value); + +/** Delete the given json_object field + * + * The reference count will be decremented for the deleted object. If there + * are no more owners of the value represented by this key, then the value is + * freed. Otherwise, the reference to the value will remain in memory. + * + * @param obj the json_object instance + * @param key the object field name + */ +extern void json_object_object_del(struct json_object* obj, const char *key); + +/** + * Iterate through all keys and values of an object. + * + * Adding keys to the object while iterating is NOT allowed. + * + * Deleting an existing key, or replacing an existing key with a + * new value IS allowed. + * + * @param obj the json_object instance + * @param key the local name for the char* key variable defined in the body + * @param val the local name for the json_object* object variable defined in + * the body + */ +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && __STDC_VERSION__ >= 199901L + +# define json_object_object_foreach(obj,key,val) \ + char *key; \ + struct json_object *val __attribute__((__unused__)); \ + for(struct lh_entry *entry ## key = json_object_get_object(obj)->head, *entry_next ## key = NULL; \ + ({ if(entry ## key) { \ + key = (char*)entry ## key->k; \ + val = (struct json_object*)entry ## key->v; \ + entry_next ## key = entry ## key->next; \ + } ; entry ## key; }); \ + entry ## key = entry_next ## key ) + +#else /* ANSI C or MSC */ + +# define json_object_object_foreach(obj,key,val) \ + char *key;\ + struct json_object *val; \ + struct lh_entry *entry ## key; \ + struct lh_entry *entry_next ## key = NULL; \ + for(entry ## key = json_object_get_object(obj)->head; \ + (entry ## key ? ( \ + key = (char*)entry ## key->k, \ + val = (struct json_object*)entry ## key->v, \ + entry_next ## key = entry ## key->next, \ + entry ## key) : 0); \ + entry ## key = entry_next ## key) + +#endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) && __STDC_VERSION__ >= 199901L */ + +/** Iterate through all keys and values of an object (ANSI C Safe) + * @param obj the json_object instance + * @param iter the object iterator + */ +#define json_object_object_foreachC(obj,iter) \ + for(iter.entry = json_object_get_object(obj)->head; (iter.entry ? (iter.key = (char*)iter.entry->k, iter.val = (struct json_object*)iter.entry->v, iter.entry) : 0); iter.entry = iter.entry->next) + +/* Array type methods */ + +/** Create a new empty json_object of type json_type_array + * @returns a json_object of type json_type_array + */ +extern struct json_object* json_object_new_array(void); + +/** Get the arraylist of a json_object of type json_type_array + * @param obj the json_object instance + * @returns an arraylist + */ +extern struct array_list* json_object_get_array(struct json_object *obj); + +/** Get the length of a json_object of type json_type_array + * @param obj the json_object instance + * @returns an int + */ +extern int json_object_array_length(struct json_object *obj); + +/** Sorts the elements of jso of type json_type_array +* +* Pointers to the json_object pointers will be passed as the two arguments +* to @sort_fn +* +* @param obj the json_object instance +* @param sort_fn a sorting function +*/ +extern void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const void *, const void *)); + +/** Add an element to the end of a json_object of type json_type_array + * + * The reference count will *not* be incremented. This is to make adding + * fields to objects in code more compact. If you want to retain a reference + * to an added object you must wrap the passed object with json_object_get + * + * @param obj the json_object instance + * @param val the json_object to be added + */ +extern int json_object_array_add(struct json_object *obj, + struct json_object *val); + +/** Insert or replace an element at a specified index in an array (a json_object of type json_type_array) + * + * The reference count will *not* be incremented. This is to make adding + * fields to objects in code more compact. If you want to retain a reference + * to an added object you must wrap the passed object with json_object_get + * + * The reference count of a replaced object will be decremented. + * + * The array size will be automatically be expanded to the size of the + * index if the index is larger than the current size. + * + * @param obj the json_object instance + * @param idx the index to insert the element at + * @param val the json_object to be added + */ +extern int json_object_array_put_idx(struct json_object *obj, int idx, + struct json_object *val); + +/** Get the element at specificed index of the array (a json_object of type json_type_array) + * @param obj the json_object instance + * @param idx the index to get the element at + * @returns the json_object at the specified index (or NULL) + */ +extern struct json_object* json_object_array_get_idx(struct json_object *obj, + int idx); + +/* json_bool type methods */ + +/** Create a new empty json_object of type json_type_boolean + * @param b a json_bool TRUE or FALSE (0 or 1) + * @returns a json_object of type json_type_boolean + */ +extern struct json_object* json_object_new_boolean(json_bool b); + +/** Get the json_bool value of a json_object + * + * The type is coerced to a json_bool if the passed object is not a json_bool. + * integer and double objects will return FALSE if there value is zero + * or TRUE otherwise. If the passed object is a string it will return + * TRUE if it has a non zero length. If any other object type is passed + * TRUE will be returned if the object is not NULL. + * + * @param obj the json_object instance + * @returns a json_bool + */ +extern json_bool json_object_get_boolean(struct json_object *obj); + + +/* int type methods */ + +/** Create a new empty json_object of type json_type_int + * Note that values are stored as 64-bit values internally. + * To ensure the full range is maintained, use json_object_new_int64 instead. + * @param i the integer + * @returns a json_object of type json_type_int + */ +extern struct json_object* json_object_new_int(int32_t i); + + +/** Create a new empty json_object of type json_type_int + * @param i the integer + * @returns a json_object of type json_type_int + */ +extern struct json_object* json_object_new_int64(int64_t i); + + +/** Get the int value of a json_object + * + * The type is coerced to a int if the passed object is not a int. + * double objects will return their integer conversion. Strings will be + * parsed as an integer. If no conversion exists then 0 is returned + * and errno is set to EINVAL. null is equivalent to 0 (no error values set) + * + * Note that integers are stored internally as 64-bit values. + * If the value of too big or too small to fit into 32-bit, INT32_MAX or + * INT32_MIN are returned, respectively. + * + * @param obj the json_object instance + * @returns an int + */ +extern int32_t json_object_get_int(struct json_object *obj); + +/** Get the int value of a json_object + * + * The type is coerced to a int64 if the passed object is not a int64. + * double objects will return their int64 conversion. Strings will be + * parsed as an int64. If no conversion exists then 0 is returned. + * + * NOTE: Set errno to 0 directly before a call to this function to determine + * whether or not conversion was successful (it does not clear the value for + * you). + * + * @param obj the json_object instance + * @returns an int64 + */ +extern int64_t json_object_get_int64(struct json_object *obj); + + +/* double type methods */ + +/** Create a new empty json_object of type json_type_double + * @param d the double + * @returns a json_object of type json_type_double + */ +extern struct json_object* json_object_new_double(double d); + +/** + * Create a new json_object of type json_type_double, using + * the exact serialized representation of the value. + * + * This allows for numbers that would otherwise get displayed + * inefficiently (e.g. 12.3 => "12.300000000000001") to be + * serialized with the more convenient form. + * + * Note: this is used by json_tokener_parse_ex() to allow for + * an exact re-serialization of a parsed object. + * + * An equivalent sequence of calls is: + * @code + * jso = json_object_new_double(d); + * json_object_set_serializer(d, json_object_userdata_to_json_string, + * strdup(ds), json_object_free_userdata) + * @endcode + * + * @param d the numeric value of the double. + * @param ds the string representation of the double. This will be copied. + */ +extern struct json_object* json_object_new_double_s(double d, const char *ds); + +/** Get the double floating point value of a json_object + * + * The type is coerced to a double if the passed object is not a double. + * integer objects will return their double conversion. Strings will be + * parsed as a double. If no conversion exists then 0.0 is returned and + * errno is set to EINVAL. null is equivalent to 0 (no error values set) + * + * If the value is too big to fit in a double, then the value is set to + * the closest infinity with errno set to ERANGE. If strings cannot be + * converted to their double value, then EINVAL is set & NaN is returned. + * + * Arrays of length 0 are interpreted as 0 (with no error flags set). + * Arrays of length 1 are effectively cast to the equivalent object and + * converted using the above rules. All other arrays set the error to + * EINVAL & return NaN. + * + * NOTE: Set errno to 0 directly before a call to this function to + * determine whether or not conversion was successful (it does not clear + * the value for you). + * + * @param obj the json_object instance + * @returns a double floating point number + */ +extern double json_object_get_double(struct json_object *obj); + + +/* string type methods */ + +/** Create a new empty json_object of type json_type_string + * + * A copy of the string is made and the memory is managed by the json_object + * + * @param s the string + * @returns a json_object of type json_type_string + */ +extern struct json_object* json_object_new_string(const char *s); + +extern struct json_object* json_object_new_string_len(const char *s, int len); + +/** Get the string value of a json_object + * + * If the passed object is not of type json_type_string then the JSON + * representation of the object is returned. + * + * The returned string memory is managed by the json_object and will + * be freed when the reference count of the json_object drops to zero. + * + * @param obj the json_object instance + * @returns a string + */ +extern const char* json_object_get_string(struct json_object *obj); + +/** Get the string length of a json_object + * + * If the passed object is not of type json_type_string then zero + * will be returned. + * + * @param obj the json_object instance + * @returns int + */ +extern int json_object_get_string_len(struct json_object *obj); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/release/src/router/libjson-c/json_object_iterator.c b/release/src/router/libjson-c/json_object_iterator.c new file mode 100644 index 0000000000..7066649c3b --- /dev/null +++ b/release/src/router/libjson-c/json_object_iterator.c @@ -0,0 +1,168 @@ +/** +******************************************************************************* +* @file json_object_iterator.c +* +* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P. +* +* This library is free software; you can redistribute it and/or modify +* it under the terms of the MIT license. See COPYING for details. +* +* @brief json-c forces clients to use its private data +* structures for JSON Object iteration. This API +* implementation corrects that by abstracting the +* private json-c details. +* +******************************************************************************* +*/ + +#include + +#include "json.h" +#include "json_object_private.h" + +#include "json_object_iterator.h" + +/** + * How It Works + * + * For each JSON Object, json-c maintains a linked list of zero + * or more lh_entry (link-hash entry) structures inside the + * Object's link-hash table (lh_table). + * + * Each lh_entry structure on the JSON Object's linked list + * represents a single name/value pair. The "next" field of the + * last lh_entry in the list is set to NULL, which terminates + * the list. + * + * We represent a valid iterator that refers to an actual + * name/value pair via a pointer to the pair's lh_entry + * structure set as the iterator's opaque_ field. + * + * We follow json-c's current pair list representation by + * representing a valid "end" iterator (one that refers past the + * last pair) with a NULL value in the iterator's opaque_ field. + * + * A JSON Object without any pairs in it will have the "head" + * field of its lh_table structure set to NULL. For such an + * object, json_object_iter_begin will return an iterator with + * the opaque_ field set to NULL, which is equivalent to the + * "end" iterator. + * + * When iterating, we simply update the iterator's opaque_ field + * to point to the next lh_entry structure in the linked list. + * opaque_ will become NULL once we iterate past the last pair + * in the list, which makes the iterator equivalent to the "end" + * iterator. + */ + +/// Our current representation of the "end" iterator; +/// +/// @note May not always be NULL +static const void* kObjectEndIterValue = NULL; + +/** + * **************************************************************************** + */ +struct json_object_iterator +json_object_iter_begin(struct json_object* obj) +{ + struct json_object_iterator iter; + struct lh_table* pTable; + + /// @note json_object_get_object will return NULL if passed NULL + /// or a non-json_type_object instance + pTable = json_object_get_object(obj); + JASSERT(NULL != pTable); + + /// @note For a pair-less Object, head is NULL, which matches our + /// definition of the "end" iterator + iter.opaque_ = pTable->head; + return iter; +} + +/** + * **************************************************************************** + */ +struct json_object_iterator +json_object_iter_end(const struct json_object* obj) +{ + struct json_object_iterator iter; + + JASSERT(NULL != obj); + JASSERT(json_object_is_type(obj, json_type_object)); + + iter.opaque_ = kObjectEndIterValue; + + return iter; +} + +/** + * **************************************************************************** + */ +void +json_object_iter_next(struct json_object_iterator* iter) +{ + JASSERT(NULL != iter); + JASSERT(kObjectEndIterValue != iter->opaque_); + + iter->opaque_ = ((struct lh_entry *)iter->opaque_)->next; +} + + +/** + * **************************************************************************** + */ +const char* +json_object_iter_peek_name(const struct json_object_iterator* iter) +{ + JASSERT(NULL != iter); + JASSERT(kObjectEndIterValue != iter->opaque_); + + return (const char*)(((struct lh_entry *)iter->opaque_)->k); +} + + +/** + * **************************************************************************** + */ +struct json_object* +json_object_iter_peek_value(const struct json_object_iterator* iter) +{ + JASSERT(NULL != iter); + JASSERT(kObjectEndIterValue != iter->opaque_); + + return (struct json_object*)(((struct lh_entry *)iter->opaque_)->v); +} + + +/** + * **************************************************************************** + */ +json_bool +json_object_iter_equal(const struct json_object_iterator* iter1, + const struct json_object_iterator* iter2) +{ + JASSERT(NULL != iter1); + JASSERT(NULL != iter2); + + return (iter1->opaque_ == iter2->opaque_); +} + + +/** + * **************************************************************************** + */ +struct json_object_iterator +json_object_iter_init_default(void) +{ + struct json_object_iterator iter; + + /** + * @note Make this a negative, invalid value, such that + * accidental access to it would likely be trapped by the + * hardware as an invalid address. + */ + iter.opaque_ = NULL; + + return iter; +} diff --git a/release/src/router/libjson-c/json_object_iterator.h b/release/src/router/libjson-c/json_object_iterator.h new file mode 100644 index 0000000000..44c9fb25b6 --- /dev/null +++ b/release/src/router/libjson-c/json_object_iterator.h @@ -0,0 +1,239 @@ +/** +******************************************************************************* +* @file json_object_iterator.h +* +* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P. +* +* This library is free software; you can redistribute it and/or modify +* it under the terms of the MIT license. See COPYING for details. +* +* @brief json-c forces clients to use its private data +* structures for JSON Object iteration. This API +* corrects that by abstracting the private json-c +* details. +* +* API attributes:
+* * Thread-safe: NO
+* * Reentrant: NO +* +******************************************************************************* +*/ + + +#ifndef JSON_OBJECT_ITERATOR_H +#define JSON_OBJECT_ITERATOR_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Forward declaration for the opaque iterator information. + */ +struct json_object_iter_info_; + +/** + * The opaque iterator that references a name/value pair within + * a JSON Object instance or the "end" iterator value. + */ +struct json_object_iterator { + const void* opaque_; +}; + + +/** + * forward declaration of json-c's JSON value instance structure + */ +struct json_object; + + +/** + * Initializes an iterator structure to a "default" value that + * is convenient for initializing an iterator variable to a + * default state (e.g., initialization list in a class' + * constructor). + * + * @code + * struct json_object_iterator iter = json_object_iter_init_default(); + * MyClass() : iter_(json_object_iter_init_default()) + * @endcode + * + * @note The initialized value doesn't reference any specific + * pair, is considered an invalid iterator, and MUST NOT + * be passed to any json-c API that expects a valid + * iterator. + * + * @note User and internal code MUST NOT make any assumptions + * about and dependencies on the value of the "default" + * iterator value. + * + * @return json_object_iterator + */ +struct json_object_iterator +json_object_iter_init_default(void); + +/** Retrieves an iterator to the first pair of the JSON Object. + * + * @warning Any modification of the underlying pair invalidates all + * iterators to that pair. + * + * @param obj JSON Object instance (MUST be of type json_object) + * + * @return json_object_iterator If the JSON Object has at + * least one pair, on return, the iterator refers + * to the first pair. If the JSON Object doesn't + * have any pairs, the returned iterator is + * equivalent to the "end" iterator for the same + * JSON Object instance. + * + * @code + * struct json_object_iterator it; + * struct json_object_iterator itEnd; + * struct json_object* obj; + * + * obj = json_tokener_parse("{'first':'george', 'age':100}"); + * it = json_object_iter_begin(obj); + * itEnd = json_object_iter_end(obj); + * + * while (!json_object_iter_equal(&it, &itEnd)) { + * printf("%s\n", + * json_object_iter_peek_name(&it)); + * json_object_iter_next(&it); + * } + * + * @endcode + */ +struct json_object_iterator +json_object_iter_begin(struct json_object* obj); + +/** Retrieves the iterator that represents the position beyond the + * last pair of the given JSON Object instance. + * + * @warning Do NOT write code that assumes that the "end" + * iterator value is NULL, even if it is so in a + * particular instance of the implementation. + * + * @note The reason we do not (and MUST NOT) provide + * "json_object_iter_is_end(json_object_iterator* iter)" + * type of API is because it would limit the underlying + * representation of name/value containment (or force us + * to add additional, otherwise unnecessary, fields to + * the iterator structure). The "end" iterator and the + * equality test method, on the other hand, permit us to + * cleanly abstract pretty much any reasonable underlying + * representation without burdening the iterator + * structure with unnecessary data. + * + * @note For performance reasons, memorize the "end" iterator prior + * to any loop. + * + * @param obj JSON Object instance (MUST be of type json_object) + * + * @return json_object_iterator On return, the iterator refers + * to the "end" of the Object instance's pairs + * (i.e., NOT the last pair, but "beyond the last + * pair" value) + */ +struct json_object_iterator +json_object_iter_end(const struct json_object* obj); + +/** Returns an iterator to the next pair, if any + * + * @warning Any modification of the underlying pair + * invalidates all iterators to that pair. + * + * @param iter [IN/OUT] Pointer to iterator that references a + * name/value pair; MUST be a valid, non-end iterator. + * WARNING: bad things will happen if invalid or "end" + * iterator is passed. Upon return will contain the + * reference to the next pair if there is one; if there + * are no more pairs, will contain the "end" iterator + * value, which may be compared against the return value + * of json_object_iter_end() for the same JSON Object + * instance. + */ +void +json_object_iter_next(struct json_object_iterator* iter); + + +/** Returns a const pointer to the name of the pair referenced + * by the given iterator. + * + * @param iter pointer to iterator that references a name/value + * pair; MUST be a valid, non-end iterator. + * + * @warning bad things will happen if an invalid or + * "end" iterator is passed. + * + * @return const char* Pointer to the name of the referenced + * name/value pair. The name memory belongs to the + * name/value pair, will be freed when the pair is + * deleted or modified, and MUST NOT be modified or + * freed by the user. + */ +const char* +json_object_iter_peek_name(const struct json_object_iterator* iter); + + +/** Returns a pointer to the json-c instance representing the + * value of the referenced name/value pair, without altering + * the instance's reference count. + * + * @param iter pointer to iterator that references a name/value + * pair; MUST be a valid, non-end iterator. + * + * @warning bad things will happen if invalid or + * "end" iterator is passed. + * + * @return struct json_object* Pointer to the json-c value + * instance of the referenced name/value pair; the + * value's reference count is not changed by this + * function: if you plan to hold on to this json-c node, + * take a look at json_object_get() and + * json_object_put(). IMPORTANT: json-c API represents + * the JSON Null value as a NULL json_object instance + * pointer. + */ +struct json_object* +json_object_iter_peek_value(const struct json_object_iterator* iter); + + +/** Tests two iterators for equality. Typically used to test + * for end of iteration by comparing an iterator to the + * corresponding "end" iterator (that was derived from the same + * JSON Object instance). + * + * @note The reason we do not (and MUST NOT) provide + * "json_object_iter_is_end(json_object_iterator* iter)" + * type of API is because it would limit the underlying + * representation of name/value containment (or force us + * to add additional, otherwise unnecessary, fields to + * the iterator structure). The equality test method, on + * the other hand, permits us to cleanly abstract pretty + * much any reasonable underlying representation. + * + * @param iter1 Pointer to first valid, non-NULL iterator + * @param iter2 POinter to second valid, non-NULL iterator + * + * @warning if a NULL iterator pointer or an uninitialized + * or invalid iterator, or iterators derived from + * different JSON Object instances are passed, bad things + * will happen! + * + * @return json_bool non-zero if iterators are equal (i.e., both + * reference the same name/value pair or are both at + * "end"); zero if they are not equal. + */ +json_bool +json_object_iter_equal(const struct json_object_iterator* iter1, + const struct json_object_iterator* iter2); + + +#ifdef __cplusplus +} +#endif + + +#endif /* JSON_OBJECT_ITERATOR_H */ diff --git a/release/src/router/libjson-c/json_object_private.h b/release/src/router/libjson-c/json_object_private.h new file mode 100644 index 0000000000..5ed791b58b --- /dev/null +++ b/release/src/router/libjson-c/json_object_private.h @@ -0,0 +1,47 @@ +/* + * $Id: json_object_private.h,v 1.4 2006/01/26 02:16:28 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef _json_object_private_h_ +#define _json_object_private_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (json_object_private_delete_fn)(struct json_object *o); + +struct json_object +{ + enum json_type o_type; + json_object_private_delete_fn *_delete; + json_object_to_json_string_fn *_to_json_string; + int _ref_count; + struct printbuf *_pb; + union data { + json_bool c_boolean; + double c_double; + int64_t c_int64; + struct lh_table *c_object; + struct array_list *c_array; + struct { + char *str; + int len; + } c_string; + } o; + json_object_delete_fn *_user_delete; + void *_userdata; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/release/src/router/libjson-c/json_tokener.c b/release/src/router/libjson-c/json_tokener.c new file mode 100644 index 0000000000..9a7629323f --- /dev/null +++ b/release/src/router/libjson-c/json_tokener.c @@ -0,0 +1,886 @@ +/* + * $Id: json_tokener.c,v 1.20 2006/07/25 03:24:50 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + * + * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved. + * The copyrights to the contents of this file are licensed under the MIT License + * (http://www.opensource.org/licenses/mit-license.php) + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "bits.h" +#include "debug.h" +#include "printbuf.h" +#include "arraylist.h" +#include "json_inttypes.h" +#include "json_object.h" +#include "json_tokener.h" +#include "json_util.h" + +#ifdef HAVE_LOCALE_H +#include +#endif /* HAVE_LOCALE_H */ + +#if !HAVE_STRDUP && defined(_MSC_VER) + /* MSC has the version as _strdup */ +# define strdup _strdup +#elif !HAVE_STRDUP +# error You do not have strdup on your system. +#endif /* HAVE_STRDUP */ + +#if !HAVE_STRNCASECMP && defined(_MSC_VER) + /* MSC has the version as _strnicmp */ +# define strncasecmp _strnicmp +#elif !HAVE_STRNCASECMP +# error You do not have strncasecmp on your system. +#endif /* HAVE_STRNCASECMP */ + +/* Use C99 NAN by default; if not available, nan("") should work too. */ +#ifndef NAN +#define NAN nan("") +#endif /* !NAN */ + +static const char json_null_str[] = "null"; +static const int json_null_str_len = sizeof(json_null_str) - 1; +static const char json_inf_str[] = "Infinity"; +static const int json_inf_str_len = sizeof(json_inf_str) - 1; +static const char json_nan_str[] = "NaN"; +static const int json_nan_str_len = sizeof(json_nan_str) - 1; +static const char json_true_str[] = "true"; +static const int json_true_str_len = sizeof(json_true_str) - 1; +static const char json_false_str[] = "false"; +static const int json_false_str_len = sizeof(json_false_str) - 1; + +static const char* json_tokener_errors[] = { + "success", + "continue", + "nesting too deep", + "unexpected end of data", + "unexpected character", + "null expected", + "boolean expected", + "number expected", + "array value separator ',' expected", + "quoted object property name expected", + "object property name separator ':' expected", + "object value separator ',' expected", + "invalid string sequence", + "expected comment", + "buffer size overflow" +}; + +const char *json_tokener_error_desc(enum json_tokener_error jerr) +{ + int jerr_int = (int)jerr; + if (jerr_int < 0 || jerr_int >= (int)(sizeof(json_tokener_errors) / sizeof(json_tokener_errors[0]))) + return "Unknown error, invalid json_tokener_error value passed to json_tokener_error_desc()"; + return json_tokener_errors[jerr]; +} + +enum json_tokener_error json_tokener_get_error(json_tokener *tok) +{ + return tok->err; +} + +/* Stuff for decoding unicode sequences */ +#define IS_HIGH_SURROGATE(uc) (((uc) & 0xFC00) == 0xD800) +#define IS_LOW_SURROGATE(uc) (((uc) & 0xFC00) == 0xDC00) +#define DECODE_SURROGATE_PAIR(hi,lo) ((((hi) & 0x3FF) << 10) + ((lo) & 0x3FF) + 0x10000) +static unsigned char utf8_replacement_char[3] = { 0xEF, 0xBF, 0xBD }; + +struct json_tokener* json_tokener_new_ex(int depth) +{ + struct json_tokener *tok; + + tok = (struct json_tokener*)calloc(1, sizeof(struct json_tokener)); + if (!tok) return NULL; + tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec)); + if (!tok->stack) { + free(tok); + return NULL; + } + tok->pb = printbuf_new(); + tok->max_depth = depth; + json_tokener_reset(tok); + return tok; +} + +struct json_tokener* json_tokener_new(void) +{ + return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH); +} + +void json_tokener_free(struct json_tokener *tok) +{ + json_tokener_reset(tok); + if (tok->pb) printbuf_free(tok->pb); + if (tok->stack) free(tok->stack); + free(tok); +} + +static void json_tokener_reset_level(struct json_tokener *tok, int depth) +{ + tok->stack[depth].state = json_tokener_state_eatws; + tok->stack[depth].saved_state = json_tokener_state_start; + json_object_put(tok->stack[depth].current); + tok->stack[depth].current = NULL; + free(tok->stack[depth].obj_field_name); + tok->stack[depth].obj_field_name = NULL; +} + +void json_tokener_reset(struct json_tokener *tok) +{ + int i; + if (!tok) + return; + + for(i = tok->depth; i >= 0; i--) + json_tokener_reset_level(tok, i); + tok->depth = 0; + tok->err = json_tokener_success; +} + +struct json_object* json_tokener_parse(const char *str) +{ + enum json_tokener_error jerr_ignored; + struct json_object* obj; + obj = json_tokener_parse_verbose(str, &jerr_ignored); + return obj; +} + +struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error) +{ + struct json_tokener* tok; + struct json_object* obj; + + tok = json_tokener_new(); + if (!tok) + return NULL; + obj = json_tokener_parse_ex(tok, str, -1); + *error = tok->err; + if(tok->err != json_tokener_success) { + if (obj != NULL) + json_object_put(obj); + obj = NULL; + } + + json_tokener_free(tok); + return obj; +} + +#define state tok->stack[tok->depth].state +#define saved_state tok->stack[tok->depth].saved_state +#define current tok->stack[tok->depth].current +#define obj_field_name tok->stack[tok->depth].obj_field_name + +/* Optimization: + * json_tokener_parse_ex() consumed a lot of CPU in its main loop, + * iterating character-by character. A large performance boost is + * achieved by using tighter loops to locally handle units such as + * comments and strings. Loops that handle an entire token within + * their scope also gather entire strings and pass them to + * printbuf_memappend() in a single call, rather than calling + * printbuf_memappend() one char at a time. + * + * PEEK_CHAR() and ADVANCE_CHAR() macros are used for code that is + * common to both the main loop and the tighter loops. + */ + +/* PEEK_CHAR(dest, tok) macro: + * Peeks at the current char and stores it in dest. + * Returns 1 on success, sets tok->err and returns 0 if no more chars. + * Implicit inputs: str, len vars + */ +#define PEEK_CHAR(dest, tok) \ + (((tok)->char_offset == len) ? \ + (((tok)->depth == 0 && state == json_tokener_state_eatws && saved_state == json_tokener_state_finish) ? \ + (((tok)->err = json_tokener_success), 0) \ + : \ + (((tok)->err = json_tokener_continue), 0) \ + ) : \ + (((dest) = *str), 1) \ + ) + +/* ADVANCE_CHAR() macro: + * Incrementes str & tok->char_offset. + * For convenience of existing conditionals, returns the old value of c (0 on eof) + * Implicit inputs: c var + */ +#define ADVANCE_CHAR(str, tok) \ + ( ++(str), ((tok)->char_offset)++, c) + + +/* End optimization macro defs */ + + +struct json_object* json_tokener_parse_ex(struct json_tokener *tok, + const char *str, int len) +{ + struct json_object *obj = NULL; + char c = '\1'; +#ifdef HAVE_SETLOCALE + char *oldlocale=NULL, *tmplocale; + + tmplocale = setlocale(LC_NUMERIC, NULL); + if (tmplocale) oldlocale = strdup(tmplocale); + setlocale(LC_NUMERIC, "C"); +#endif + + tok->char_offset = 0; + tok->err = json_tokener_success; + + /* this interface is presently not 64-bit clean due to the int len argument + and the internal printbuf interface that takes 32-bit int len arguments + so the function limits the maximum string size to INT32_MAX (2GB). + If the function is called with len == -1 then strlen is called to check + the string length is less than INT32_MAX (2GB) */ + if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX)) { + tok->err = json_tokener_error_size; + return NULL; + } + + while (PEEK_CHAR(c, tok)) { + + redo_char: + switch(state) { + + case json_tokener_state_eatws: + /* Advance until we change state */ + while (isspace((int)c)) { + if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok))) + goto out; + } + if(c == '/' && !(tok->flags & JSON_TOKENER_STRICT)) { + printbuf_reset(tok->pb); + printbuf_memappend_fast(tok->pb, &c, 1); + state = json_tokener_state_comment_start; + } else { + state = saved_state; + goto redo_char; + } + break; + + case json_tokener_state_start: + switch(c) { + case '{': + state = json_tokener_state_eatws; + saved_state = json_tokener_state_object_field_start; + current = json_object_new_object(); + break; + case '[': + state = json_tokener_state_eatws; + saved_state = json_tokener_state_array; + current = json_object_new_array(); + break; + case 'I': + case 'i': + state = json_tokener_state_inf; + printbuf_reset(tok->pb); + tok->st_pos = 0; + goto redo_char; + case 'N': + case 'n': + state = json_tokener_state_null; // or NaN + printbuf_reset(tok->pb); + tok->st_pos = 0; + goto redo_char; + case '\'': + if (tok->flags & JSON_TOKENER_STRICT) { + /* in STRICT mode only double-quote are allowed */ + tok->err = json_tokener_error_parse_unexpected; + goto out; + } + case '"': + state = json_tokener_state_string; + printbuf_reset(tok->pb); + tok->quote_char = c; + break; + case 'T': + case 't': + case 'F': + case 'f': + state = json_tokener_state_boolean; + printbuf_reset(tok->pb); + tok->st_pos = 0; + goto redo_char; +#if defined(__GNUC__) + case '0' ... '9': +#else + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': +#endif + case '-': + state = json_tokener_state_number; + printbuf_reset(tok->pb); + tok->is_double = 0; + goto redo_char; + default: + tok->err = json_tokener_error_parse_unexpected; + goto out; + } + break; + + case json_tokener_state_finish: + if(tok->depth == 0) goto out; + obj = json_object_get(current); + json_tokener_reset_level(tok, tok->depth); + tok->depth--; + goto redo_char; + + case json_tokener_state_inf: /* aka starts with 'i' */ + { + int size_inf; + int is_negative = 0; + + printbuf_memappend_fast(tok->pb, &c, 1); + size_inf = json_min(tok->st_pos+1, json_inf_str_len); + char *infbuf = tok->pb->buf; + if (*infbuf == '-') + { + infbuf++; + is_negative = 1; + } + if ((!(tok->flags & JSON_TOKENER_STRICT) && + strncasecmp(json_inf_str, infbuf, size_inf) == 0) || + (strncmp(json_inf_str, infbuf, size_inf) == 0) + ) + { + if (tok->st_pos == json_inf_str_len) + { + current = json_object_new_double(is_negative ? -INFINITY : INFINITY); + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; + } + } else { + tok->err = json_tokener_error_parse_unexpected; + goto out; + } + tok->st_pos++; + } + break; + case json_tokener_state_null: /* aka starts with 'n' */ + { + int size; + int size_nan; + printbuf_memappend_fast(tok->pb, &c, 1); + size = json_min(tok->st_pos+1, json_null_str_len); + size_nan = json_min(tok->st_pos+1, json_nan_str_len); + if((!(tok->flags & JSON_TOKENER_STRICT) && + strncasecmp(json_null_str, tok->pb->buf, size) == 0) + || (strncmp(json_null_str, tok->pb->buf, size) == 0) + ) { + if (tok->st_pos == json_null_str_len) { + current = NULL; + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; + } + } + else if ((!(tok->flags & JSON_TOKENER_STRICT) && + strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) || + (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0) + ) + { + if (tok->st_pos == json_nan_str_len) + { + current = json_object_new_double(NAN); + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; + } + } else { + tok->err = json_tokener_error_parse_null; + goto out; + } + tok->st_pos++; + } + break; + + case json_tokener_state_comment_start: + if(c == '*') { + state = json_tokener_state_comment; + } else if(c == '/') { + state = json_tokener_state_comment_eol; + } else { + tok->err = json_tokener_error_parse_comment; + goto out; + } + printbuf_memappend_fast(tok->pb, &c, 1); + break; + + case json_tokener_state_comment: + { + /* Advance until we change state */ + const char *case_start = str; + while(c != '*') { + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { + printbuf_memappend_fast(tok->pb, case_start, str-case_start); + goto out; + } + } + printbuf_memappend_fast(tok->pb, case_start, 1+str-case_start); + state = json_tokener_state_comment_end; + } + break; + + case json_tokener_state_comment_eol: + { + /* Advance until we change state */ + const char *case_start = str; + while(c != '\n') { + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { + printbuf_memappend_fast(tok->pb, case_start, str-case_start); + goto out; + } + } + printbuf_memappend_fast(tok->pb, case_start, str-case_start); + MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf); + state = json_tokener_state_eatws; + } + break; + + case json_tokener_state_comment_end: + printbuf_memappend_fast(tok->pb, &c, 1); + if(c == '/') { + MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf); + state = json_tokener_state_eatws; + } else { + state = json_tokener_state_comment; + } + break; + + case json_tokener_state_string: + { + /* Advance until we change state */ + const char *case_start = str; + while(1) { + if(c == tok->quote_char) { + printbuf_memappend_fast(tok->pb, case_start, str-case_start); + current = json_object_new_string_len(tok->pb->buf, tok->pb->bpos); + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + break; + } else if(c == '\\') { + printbuf_memappend_fast(tok->pb, case_start, str-case_start); + saved_state = json_tokener_state_string; + state = json_tokener_state_string_escape; + break; + } + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { + printbuf_memappend_fast(tok->pb, case_start, str-case_start); + goto out; + } + } + } + break; + + case json_tokener_state_string_escape: + switch(c) { + case '"': + case '\\': + case '/': + printbuf_memappend_fast(tok->pb, &c, 1); + state = saved_state; + break; + case 'b': + case 'n': + case 'r': + case 't': + case 'f': + if(c == 'b') printbuf_memappend_fast(tok->pb, "\b", 1); + else if(c == 'n') printbuf_memappend_fast(tok->pb, "\n", 1); + else if(c == 'r') printbuf_memappend_fast(tok->pb, "\r", 1); + else if(c == 't') printbuf_memappend_fast(tok->pb, "\t", 1); + else if(c == 'f') printbuf_memappend_fast(tok->pb, "\f", 1); + state = saved_state; + break; + case 'u': + tok->ucs_char = 0; + tok->st_pos = 0; + state = json_tokener_state_escape_unicode; + break; + default: + tok->err = json_tokener_error_parse_string; + goto out; + } + break; + + case json_tokener_state_escape_unicode: + { + unsigned int got_hi_surrogate = 0; + + /* Handle a 4-byte sequence, or two sequences if a surrogate pair */ + while(1) { + if(strchr(json_hex_chars, c)) { + tok->ucs_char += ((unsigned int)hexdigit(c) << ((3-tok->st_pos++)*4)); + if(tok->st_pos == 4) { + unsigned char unescaped_utf[4]; + + if (got_hi_surrogate) { + if (IS_LOW_SURROGATE(tok->ucs_char)) { + /* Recalculate the ucs_char, then fall thru to process normally */ + tok->ucs_char = DECODE_SURROGATE_PAIR(got_hi_surrogate, tok->ucs_char); + } else { + /* Hi surrogate was not followed by a low surrogate */ + /* Replace the hi and process the rest normally */ + printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3); + } + got_hi_surrogate = 0; + } + + if (tok->ucs_char < 0x80) { + unescaped_utf[0] = tok->ucs_char; + printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 1); + } else if (tok->ucs_char < 0x800) { + unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6); + unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f); + printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 2); + } else if (IS_HIGH_SURROGATE(tok->ucs_char)) { + /* Got a high surrogate. Remember it and look for the + * the beginning of another sequence, which should be the + * low surrogate. + */ + got_hi_surrogate = tok->ucs_char; + /* Not at end, and the next two chars should be "\u" */ + if ((tok->char_offset+1 != len) && + (tok->char_offset+2 != len) && + (str[1] == '\\') && + (str[2] == 'u')) + { + /* Advance through the 16 bit surrogate, and move on to the + * next sequence. The next step is to process the following + * characters. + */ + if( !ADVANCE_CHAR(str, tok) || !ADVANCE_CHAR(str, tok) ) { + printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3); + } + /* Advance to the first char of the next sequence and + * continue processing with the next sequence. + */ + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { + printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3); + goto out; + } + tok->ucs_char = 0; + tok->st_pos = 0; + continue; /* other json_tokener_state_escape_unicode */ + } else { + /* Got a high surrogate without another sequence following + * it. Put a replacement char in for the hi surrogate + * and pretend we finished. + */ + printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3); + } + } else if (IS_LOW_SURROGATE(tok->ucs_char)) { + /* Got a low surrogate not preceded by a high */ + printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3); + } else if (tok->ucs_char < 0x10000) { + unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12); + unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f); + unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f); + printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 3); + } else if (tok->ucs_char < 0x110000) { + unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07); + unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f); + unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f); + unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f); + printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 4); + } else { + /* Don't know what we got--insert the replacement char */ + printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3); + } + state = saved_state; + break; + } + } else { + tok->err = json_tokener_error_parse_string; + goto out; + } + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { + if (got_hi_surrogate) /* Clean up any pending chars */ + printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3); + goto out; + } + } + } + break; + + case json_tokener_state_boolean: + { + int size1, size2; + printbuf_memappend_fast(tok->pb, &c, 1); + size1 = json_min(tok->st_pos+1, json_true_str_len); + size2 = json_min(tok->st_pos+1, json_false_str_len); + if((!(tok->flags & JSON_TOKENER_STRICT) && + strncasecmp(json_true_str, tok->pb->buf, size1) == 0) + || (strncmp(json_true_str, tok->pb->buf, size1) == 0) + ) { + if(tok->st_pos == json_true_str_len) { + current = json_object_new_boolean(1); + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; + } + } else if((!(tok->flags & JSON_TOKENER_STRICT) && + strncasecmp(json_false_str, tok->pb->buf, size2) == 0) + || (strncmp(json_false_str, tok->pb->buf, size2) == 0)) { + if(tok->st_pos == json_false_str_len) { + current = json_object_new_boolean(0); + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; + } + } else { + tok->err = json_tokener_error_parse_boolean; + goto out; + } + tok->st_pos++; + } + break; + + case json_tokener_state_number: + { + /* Advance until we change state */ + const char *case_start = str; + int case_len=0; + while(c && strchr(json_number_chars, c)) { + ++case_len; + if(c == '.' || c == 'e' || c == 'E') + tok->is_double = 1; + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { + printbuf_memappend_fast(tok->pb, case_start, case_len); + goto out; + } + } + if (case_len>0) + printbuf_memappend_fast(tok->pb, case_start, case_len); + + // Check for -Infinity + if (tok->pb->buf[0] == '-' && case_len == 1 && + (c == 'i' || c == 'I')) + { + state = json_tokener_state_inf; + goto redo_char; + } + } + { + int64_t num64; + double numd; + if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) { + if (num64 && tok->pb->buf[0]=='0' && (tok->flags & JSON_TOKENER_STRICT)) { + /* in strict mode, number must not start with 0 */ + tok->err = json_tokener_error_parse_number; + goto out; + } + current = json_object_new_int64(num64); + } + else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0) + { + current = json_object_new_double_s(numd, tok->pb->buf); + } else { + tok->err = json_tokener_error_parse_number; + goto out; + } + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + goto redo_char; + } + break; + + case json_tokener_state_array_after_sep: + case json_tokener_state_array: + if(c == ']') { + if (state == json_tokener_state_array_after_sep && + (tok->flags & JSON_TOKENER_STRICT)) + { + tok->err = json_tokener_error_parse_unexpected; + goto out; + } + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + } else { + if(tok->depth >= tok->max_depth-1) { + tok->err = json_tokener_error_depth; + goto out; + } + state = json_tokener_state_array_add; + tok->depth++; + json_tokener_reset_level(tok, tok->depth); + goto redo_char; + } + break; + + case json_tokener_state_array_add: + json_object_array_add(current, obj); + saved_state = json_tokener_state_array_sep; + state = json_tokener_state_eatws; + goto redo_char; + + case json_tokener_state_array_sep: + if(c == ']') { + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + } else if(c == ',') { + saved_state = json_tokener_state_array_after_sep; + state = json_tokener_state_eatws; + } else { + tok->err = json_tokener_error_parse_array; + goto out; + } + break; + + case json_tokener_state_object_field_start: + case json_tokener_state_object_field_start_after_sep: + if(c == '}') { + if (state == json_tokener_state_object_field_start_after_sep && + (tok->flags & JSON_TOKENER_STRICT)) + { + tok->err = json_tokener_error_parse_unexpected; + goto out; + } + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + } else if (c == '"' || c == '\'') { + tok->quote_char = c; + printbuf_reset(tok->pb); + state = json_tokener_state_object_field; + } else { + tok->err = json_tokener_error_parse_object_key_name; + goto out; + } + break; + + case json_tokener_state_object_field: + { + /* Advance until we change state */ + const char *case_start = str; + while(1) { + if(c == tok->quote_char) { + printbuf_memappend_fast(tok->pb, case_start, str-case_start); + obj_field_name = strdup(tok->pb->buf); + saved_state = json_tokener_state_object_field_end; + state = json_tokener_state_eatws; + break; + } else if(c == '\\') { + printbuf_memappend_fast(tok->pb, case_start, str-case_start); + saved_state = json_tokener_state_object_field; + state = json_tokener_state_string_escape; + break; + } + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { + printbuf_memappend_fast(tok->pb, case_start, str-case_start); + goto out; + } + } + } + break; + + case json_tokener_state_object_field_end: + if(c == ':') { + saved_state = json_tokener_state_object_value; + state = json_tokener_state_eatws; + } else { + tok->err = json_tokener_error_parse_object_key_sep; + goto out; + } + break; + + case json_tokener_state_object_value: + if(tok->depth >= tok->max_depth-1) { + tok->err = json_tokener_error_depth; + goto out; + } + state = json_tokener_state_object_value_add; + tok->depth++; + json_tokener_reset_level(tok, tok->depth); + goto redo_char; + + case json_tokener_state_object_value_add: + json_object_object_add(current, obj_field_name, obj); + free(obj_field_name); + obj_field_name = NULL; + saved_state = json_tokener_state_object_sep; + state = json_tokener_state_eatws; + goto redo_char; + + case json_tokener_state_object_sep: + if(c == '}') { + saved_state = json_tokener_state_finish; + state = json_tokener_state_eatws; + } else if(c == ',') { + saved_state = json_tokener_state_object_field_start_after_sep; + state = json_tokener_state_eatws; + } else { + tok->err = json_tokener_error_parse_object_value_sep; + goto out; + } + break; + + } + if (!ADVANCE_CHAR(str, tok)) + goto out; + } /* while(POP_CHAR) */ + + out: + if (c && + (state == json_tokener_state_finish) && + (tok->depth == 0) && + (tok->flags & JSON_TOKENER_STRICT)) { + /* unexpected char after JSON data */ + tok->err = json_tokener_error_parse_unexpected; + } + if (!c) { /* We hit an eof char (0) */ + if(state != json_tokener_state_finish && + saved_state != json_tokener_state_finish) + tok->err = json_tokener_error_parse_eof; + } + +#ifdef HAVE_SETLOCALE + setlocale(LC_NUMERIC, oldlocale); + if (oldlocale) free(oldlocale); +#endif + + if (tok->err == json_tokener_success) + { + json_object *ret = json_object_get(current); + int ii; + + /* Partially reset, so we parse additional objects on subsequent calls. */ + for(ii = tok->depth; ii >= 0; ii--) + json_tokener_reset_level(tok, ii); + return ret; + } + + MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n", + json_tokener_errors[tok->err], tok->char_offset); + return NULL; +} + +void json_tokener_set_flags(struct json_tokener *tok, int flags) +{ + tok->flags = flags; +} diff --git a/release/src/router/libjson-c/json_tokener.h b/release/src/router/libjson-c/json_tokener.h new file mode 100644 index 0000000000..a72d2bdefe --- /dev/null +++ b/release/src/router/libjson-c/json_tokener.h @@ -0,0 +1,208 @@ +/* + * $Id: json_tokener.h,v 1.10 2006/07/25 03:24:50 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef _json_tokener_h_ +#define _json_tokener_h_ + +#include +#include "json_object.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum json_tokener_error { + json_tokener_success, + json_tokener_continue, + json_tokener_error_depth, + json_tokener_error_parse_eof, + json_tokener_error_parse_unexpected, + json_tokener_error_parse_null, + json_tokener_error_parse_boolean, + json_tokener_error_parse_number, + json_tokener_error_parse_array, + json_tokener_error_parse_object_key_name, + json_tokener_error_parse_object_key_sep, + json_tokener_error_parse_object_value_sep, + json_tokener_error_parse_string, + json_tokener_error_parse_comment, + json_tokener_error_size +}; + +enum json_tokener_state { + json_tokener_state_eatws, + json_tokener_state_start, + json_tokener_state_finish, + json_tokener_state_null, + json_tokener_state_comment_start, + json_tokener_state_comment, + json_tokener_state_comment_eol, + json_tokener_state_comment_end, + json_tokener_state_string, + json_tokener_state_string_escape, + json_tokener_state_escape_unicode, + json_tokener_state_boolean, + json_tokener_state_number, + json_tokener_state_array, + json_tokener_state_array_add, + json_tokener_state_array_sep, + json_tokener_state_object_field_start, + json_tokener_state_object_field, + json_tokener_state_object_field_end, + json_tokener_state_object_value, + json_tokener_state_object_value_add, + json_tokener_state_object_sep, + json_tokener_state_array_after_sep, + json_tokener_state_object_field_start_after_sep, + json_tokener_state_inf +}; + +struct json_tokener_srec +{ + enum json_tokener_state state, saved_state; + struct json_object *obj; + struct json_object *current; + char *obj_field_name; +}; + +#define JSON_TOKENER_DEFAULT_DEPTH 32 + +struct json_tokener +{ + char *str; + struct printbuf *pb; + int max_depth, depth, is_double, st_pos, char_offset; + enum json_tokener_error err; + unsigned int ucs_char; + char quote_char; + struct json_tokener_srec *stack; + int flags; +}; + +/** + * Be strict when parsing JSON input. Use caution with + * this flag as what is considered valid may become more + * restrictive from one release to the next, causing your + * code to fail on previously working input. + * + * This flag is not set by default. + * + * @see json_tokener_set_flags() + */ +#define JSON_TOKENER_STRICT 0x01 + +/** + * Given an error previously returned by json_tokener_get_error(), + * return a human readable description of the error. + * + * @return a generic error message is returned if an invalid error value is provided. + */ +const char *json_tokener_error_desc(enum json_tokener_error jerr); + +/** + * Retrieve the error caused by the last call to json_tokener_parse_ex(), + * or json_tokener_success if there is no error. + * + * When parsing a JSON string in pieces, if the tokener is in the middle + * of parsing this will return json_tokener_continue. + * + * See also json_tokener_error_desc(). + */ +enum json_tokener_error json_tokener_get_error(struct json_tokener *tok); + +extern struct json_tokener* json_tokener_new(void); +extern struct json_tokener* json_tokener_new_ex(int depth); +extern void json_tokener_free(struct json_tokener *tok); +extern void json_tokener_reset(struct json_tokener *tok); +extern struct json_object* json_tokener_parse(const char *str); +extern struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error); + +/** + * Set flags that control how parsing will be done. + */ +extern void json_tokener_set_flags(struct json_tokener *tok, int flags); + +/** + * Parse a string and return a non-NULL json_object if a valid JSON value + * is found. The string does not need to be a JSON object or array; + * it can also be a string, number or boolean value. + * + * A partial JSON string can be parsed. If the parsing is incomplete, + * NULL will be returned and json_tokener_get_error() will be return + * json_tokener_continue. + * json_tokener_parse_ex() can then be called with additional bytes in str + * to continue the parsing. + * + * If json_tokener_parse_ex() returns NULL and the error anything other than + * json_tokener_continue, a fatal error has occurred and parsing must be + * halted. Then tok object must not be re-used until json_tokener_reset() is + * called. + * + * When a valid JSON value is parsed, a non-NULL json_object will be + * returned. Also, json_tokener_get_error() will return json_tokener_success. + * Be sure to check the type with json_object_is_type() or + * json_object_get_type() before using the object. + * + * @b XXX this shouldn't use internal fields: + * Trailing characters after the parsed value do not automatically cause an + * error. It is up to the caller to decide whether to treat this as an + * error or to handle the additional characters, perhaps by parsing another + * json value starting from that point. + * + * Extra characters can be detected by comparing the tok->char_offset against + * the length of the last len parameter passed in. + * + * The tokener does \b not maintain an internal buffer so the caller is + * responsible for calling json_tokener_parse_ex with an appropriate str + * parameter starting with the extra characters. + * + * This interface is presently not 64-bit clean due to the int len argument + * so the function limits the maximum string size to INT32_MAX (2GB). + * If the function is called with len == -1 then strlen is called to check + * the string length is less than INT32_MAX (2GB) + * + * Example: + * @code +json_object *jobj = NULL; +const char *mystring = NULL; +int stringlen = 0; +enum json_tokener_error jerr; +do { + mystring = ... // get JSON string, e.g. read from file, etc... + stringlen = strlen(mystring); + jobj = json_tokener_parse_ex(tok, mystring, stringlen); +} while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue); +if (jerr != json_tokener_success) +{ + fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr)); + // Handle errors, as appropriate for your application. +} +if (tok->char_offset < stringlen) // XXX shouldn't access internal fields +{ + // Handle extra characters after parsed object as desired. + // e.g. issue an error, parse another object from that point, etc... +} +// Success, use jobj here. + +@endcode + * + * @param tok a json_tokener previously allocated with json_tokener_new() + * @param str an string with any valid JSON expression, or portion of. This does not need to be null terminated. + * @param len the length of str + */ +extern struct json_object* json_tokener_parse_ex(struct json_tokener *tok, + const char *str, int len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/release/src/router/libjson-c/json_util.c b/release/src/router/libjson-c/json_util.c new file mode 100644 index 0000000000..531f9afb3a --- /dev/null +++ b/release/src/router/libjson-c/json_util.c @@ -0,0 +1,300 @@ +/* + * $Id: json_util.c,v 1.4 2006/01/30 23:07:57 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#include "config.h" +#undef realloc + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +#include +#endif /* HAVE_SYS_TYPES_H */ + +#ifdef HAVE_SYS_STAT_H +#include +#endif /* HAVE_SYS_STAT_H */ + +#ifdef HAVE_FCNTL_H +#include +#endif /* HAVE_FCNTL_H */ + +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ + +#ifdef WIN32 +# define WIN32_LEAN_AND_MEAN +# include +# include +#endif /* defined(WIN32) */ + +#if !defined(HAVE_OPEN) && defined(WIN32) +# define open _open +#endif + +#if !defined(HAVE_SNPRINTF) && defined(_MSC_VER) + /* MSC has the version as _snprintf */ +# define snprintf _snprintf +#elif !defined(HAVE_SNPRINTF) +# error You do not have snprintf on your system. +#endif /* HAVE_SNPRINTF */ + +#include "bits.h" +#include "debug.h" +#include "printbuf.h" +#include "json_inttypes.h" +#include "json_object.h" +#include "json_tokener.h" +#include "json_util.h" + +static int sscanf_is_broken = 0; +static int sscanf_is_broken_testdone = 0; +static void sscanf_is_broken_test(void); + +struct json_object* json_object_from_file(const char *filename) +{ + struct printbuf *pb; + struct json_object *obj; + char buf[JSON_FILE_BUF_SIZE]; + int fd, ret; + + if((fd = open(filename, O_RDONLY)) < 0) { + MC_ERROR("json_object_from_file: error opening file %s: %s\n", + filename, strerror(errno)); + return NULL; + } + if(!(pb = printbuf_new())) { + close(fd); + MC_ERROR("json_object_from_file: printbuf_new failed\n"); + return NULL; + } + while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) { + printbuf_memappend(pb, buf, ret); + } + close(fd); + if(ret < 0) { + MC_ERROR("json_object_from_file: error reading file %s: %s\n", + filename, strerror(errno)); + printbuf_free(pb); + return NULL; + } + obj = json_tokener_parse(pb->buf); + printbuf_free(pb); + return obj; +} + +/* extended "format and write to file" function */ + +int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags) +{ + const char *json_str; + int fd, ret; + unsigned int wpos, wsize; + + if(!obj) { + MC_ERROR("json_object_to_file: object is null\n"); + return -1; + } + + if((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) { + MC_ERROR("json_object_to_file: error opening file %s: %s\n", + filename, strerror(errno)); + return -1; + } + + if(!(json_str = json_object_to_json_string_ext(obj,flags))) { + close(fd); + return -1; + } + + wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */ + wpos = 0; + while(wpos < wsize) { + if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) { + close(fd); + MC_ERROR("json_object_to_file: error writing file %s: %s\n", + filename, strerror(errno)); + return -1; + } + + /* because of the above check for ret < 0, we can safely cast and add */ + wpos += (unsigned int)ret; + } + + close(fd); + return 0; +} + +// backwards compatible "format and write to file" function + +int json_object_to_file(const char *filename, struct json_object *obj) +{ + return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN); +} + +int json_parse_double(const char *buf, double *retval) +{ + return (sscanf(buf, "%lf", retval)==1 ? 0 : 1); +} + +/* + * Not all implementations of sscanf actually work properly. + * Check whether the one we're currently using does, and if + * it's broken, enable the workaround code. + */ +static void sscanf_is_broken_test() +{ + int64_t num64; + int ret_errno, is_int64_min, ret_errno2, is_int64_max; + + (void)sscanf(" -01234567890123456789012345", "%" SCNd64, &num64); + ret_errno = errno; + is_int64_min = (num64 == INT64_MIN); + + (void)sscanf(" 01234567890123456789012345", "%" SCNd64, &num64); + ret_errno2 = errno; + is_int64_max = (num64 == INT64_MAX); + + if (ret_errno != ERANGE || !is_int64_min || + ret_errno2 != ERANGE || !is_int64_max) + { + MC_DEBUG("sscanf_is_broken_test failed, enabling workaround code\n"); + sscanf_is_broken = 1; + } +} + +int json_parse_int64(const char *buf, int64_t *retval) +{ + int64_t num64; + const char *buf_sig_digits; + int orig_has_neg; + int saved_errno; + + if (!sscanf_is_broken_testdone) + { + sscanf_is_broken_test(); + sscanf_is_broken_testdone = 1; + } + + // Skip leading spaces + while (isspace((int)*buf) && *buf) + buf++; + + errno = 0; // sscanf won't always set errno, so initialize + if (sscanf(buf, "%" SCNd64, &num64) != 1) + { + MC_DEBUG("Failed to parse, sscanf != 1\n"); + return 1; + } + + saved_errno = errno; + buf_sig_digits = buf; + orig_has_neg = 0; + if (*buf_sig_digits == '-') + { + buf_sig_digits++; + orig_has_neg = 1; + } + + // Not all sscanf implementations actually work + if (sscanf_is_broken && saved_errno != ERANGE) + { + char buf_cmp[100]; + char *buf_cmp_start = buf_cmp; + int recheck_has_neg = 0; + int buf_cmp_len; + + // Skip leading zeros, but keep at least one digit + while (buf_sig_digits[0] == '0' && buf_sig_digits[1] != '\0') + buf_sig_digits++; + if (num64 == 0) // assume all sscanf impl's will parse -0 to 0 + orig_has_neg = 0; // "-0" is the same as just plain "0" + + snprintf(buf_cmp_start, sizeof(buf_cmp), "%" PRId64, num64); + if (*buf_cmp_start == '-') + { + recheck_has_neg = 1; + buf_cmp_start++; + } + // No need to skip leading spaces or zeros here. + + buf_cmp_len = strlen(buf_cmp_start); + /** + * If the sign is different, or + * some of the digits are different, or + * there is another digit present in the original string + * then we have NOT successfully parsed the value. + */ + if (orig_has_neg != recheck_has_neg || + strncmp(buf_sig_digits, buf_cmp_start, strlen(buf_cmp_start)) != 0 || + ((int)strlen(buf_sig_digits) != buf_cmp_len && + isdigit((int)buf_sig_digits[buf_cmp_len]) + ) + ) + { + saved_errno = ERANGE; + } + } + + // Not all sscanf impl's set the value properly when out of range. + // Always do this, even for properly functioning implementations, + // since it shouldn't slow things down much. + if (saved_errno == ERANGE) + { + if (orig_has_neg) + num64 = INT64_MIN; + else + num64 = INT64_MAX; + } + *retval = num64; + return 0; +} + +#ifndef HAVE_REALLOC +void* rpl_realloc(void* p, size_t n) +{ + if (n == 0) + n = 1; + if (p == 0) + return malloc(n); + return realloc(p, n); +} +#endif + +#define NELEM(a) (sizeof(a) / sizeof(a[0])) +static const char* json_type_name[] = { + /* If you change this, be sure to update the enum json_type definition too */ + "null", + "boolean", + "double", + "int", + "object", + "array", + "string", +}; + +const char *json_type_to_name(enum json_type o_type) +{ + int o_type_int = (int)o_type; + if (o_type_int < 0 || o_type_int >= (int)NELEM(json_type_name)) + { + MC_ERROR("json_type_to_name: type %d is out of range [0,%d]\n", o_type, NELEM(json_type_name)); + return NULL; + } + return json_type_name[o_type]; +} + diff --git a/release/src/router/libjson-c/json_util.h b/release/src/router/libjson-c/json_util.h new file mode 100644 index 0000000000..1005e58c5b --- /dev/null +++ b/release/src/router/libjson-c/json_util.h @@ -0,0 +1,41 @@ +/* + * $Id: json_util.h,v 1.4 2006/01/30 23:07:57 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef _json_util_h_ +#define _json_util_h_ + +#include "json_object.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define JSON_FILE_BUF_SIZE 4096 + +/* utility functions */ +extern struct json_object* json_object_from_file(const char *filename); +extern int json_object_to_file(const char *filename, struct json_object *obj); +extern int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags); +extern int json_parse_int64(const char *buf, int64_t *retval); +extern int json_parse_double(const char *buf, double *retval); + + +/** + * Return a string describing the type of the object. + * e.g. "int", or "object", etc... + */ +extern const char *json_type_to_name(enum json_type o_type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/release/src/router/libjson-c/libjson.c b/release/src/router/libjson-c/libjson.c new file mode 100644 index 0000000000..5284fd0e70 --- /dev/null +++ b/release/src/router/libjson-c/libjson.c @@ -0,0 +1,26 @@ + +/* dummy source file for compatibility purposes */ + +#if defined(HAVE_CDEFS_H) +#include +#endif + +#ifndef __warn_references + +#if defined(__GNUC__) && defined (HAS_GNU_WARNING_LONG) + +#define __warn_references(sym,msg) \ + __asm__(".section .gnu" #sym ",\n\t.ascii \"" msg "\"\n\t.text"); + +#else +#define __warn_references(sym,msg) /* nothing */ +#endif + +#endif + +#include "json_object.h" + +__warn_references(json_object_get, "Warning: please link against libjson-c instead of libjson"); + +/* __asm__(".section .gnu.warning." __STRING(sym) \ + " ; .ascii \"" msg "\" ; .text") */ diff --git a/release/src/router/libjson-c/linkhash.c b/release/src/router/libjson-c/linkhash.c new file mode 100644 index 0000000000..712c3879e7 --- /dev/null +++ b/release/src/router/libjson-c/linkhash.c @@ -0,0 +1,602 @@ +/* + * $Id: linkhash.c,v 1.4 2006/01/26 02:16:28 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_ENDIAN_H +# include /* attempt to define endianness */ +#endif + +#include "random_seed.h" +#include "linkhash.h" + +void lh_abort(const char *msg, ...) +{ + va_list ap; + va_start(ap, msg); + vprintf(msg, ap); + va_end(ap); + exit(1); +} + +unsigned long lh_ptr_hash(const void *k) +{ + /* CAW: refactored to be 64bit nice */ + return (unsigned long)((((ptrdiff_t)k * LH_PRIME) >> 4) & ULONG_MAX); +} + +int lh_ptr_equal(const void *k1, const void *k2) +{ + return (k1 == k2); +} + +/* + * hashlittle from lookup3.c, by Bob Jenkins, May 2006, Public Domain. + * http://burtleburtle.net/bob/c/lookup3.c + * minor modifications to make functions static so no symbols are exported + * minor mofifications to compile with -Werror + */ + +/* +------------------------------------------------------------------------------- +lookup3.c, by Bob Jenkins, May 2006, Public Domain. + +These are functions for producing 32-bit hashes for hash table lookup. +hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() +are externally useful functions. Routines to test the hash are included +if SELF_TEST is defined. You can use this free for any purpose. It's in +the public domain. It has no warranty. + +You probably want to use hashlittle(). hashlittle() and hashbig() +hash byte arrays. hashlittle() is is faster than hashbig() on +little-endian machines. Intel and AMD are little-endian machines. +On second thought, you probably want hashlittle2(), which is identical to +hashlittle() except it returns two 32-bit hashes for the price of one. +You could implement hashbig2() if you wanted but I haven't bothered here. + +If you want to find a hash of, say, exactly 7 integers, do + a = i1; b = i2; c = i3; + mix(a,b,c); + a += i4; b += i5; c += i6; + mix(a,b,c); + a += i7; + final(a,b,c); +then use c as the hash value. If you have a variable length array of +4-byte integers to hash, use hashword(). If you have a byte array (like +a character string), use hashlittle(). If you have several byte arrays, or +a mix of things, see the comments above hashlittle(). + +Why is this so big? I read 12 bytes at a time into 3 4-byte integers, +then mix those integers. This is fast (you can do a lot more thorough +mixing with 12*3 instructions on 3 integers than you can with 3 instructions +on 1 byte), but shoehorning those bytes into integers efficiently is messy. +------------------------------------------------------------------------------- +*/ + +/* + * My best guess at if you are big-endian or little-endian. This may + * need adjustment. + */ +#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ + __BYTE_ORDER == __LITTLE_ENDIAN) || \ + (defined(i386) || defined(__i386__) || defined(__i486__) || \ + defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL)) +# define HASH_LITTLE_ENDIAN 1 +# define HASH_BIG_ENDIAN 0 +#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ + __BYTE_ORDER == __BIG_ENDIAN) || \ + (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel)) +# define HASH_LITTLE_ENDIAN 0 +# define HASH_BIG_ENDIAN 1 +#else +# define HASH_LITTLE_ENDIAN 0 +# define HASH_BIG_ENDIAN 0 +#endif + +#define hashsize(n) ((uint32_t)1<<(n)) +#define hashmask(n) (hashsize(n)-1) +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) + +/* +------------------------------------------------------------------------------- +mix -- mix 3 32-bit values reversibly. + +This is reversible, so any information in (a,b,c) before mix() is +still in (a,b,c) after mix(). + +If four pairs of (a,b,c) inputs are run through mix(), or through +mix() in reverse, there are at least 32 bits of the output that +are sometimes the same for one pair and different for another pair. +This was tested for: +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that +satisfy this are + 4 6 8 16 19 4 + 9 15 3 18 27 15 + 14 9 3 7 17 3 +Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing +for "differ" defined as + with a one-bit base and a two-bit delta. I +used http://burtleburtle.net/bob/hash/avalanche.html to choose +the operations, constants, and arrangements of the variables. + +This does not achieve avalanche. There are input bits of (a,b,c) +that fail to affect some output bits of (a,b,c), especially of a. The +most thoroughly mixed value is c, but it doesn't really even achieve +avalanche in c. + +This allows some parallelism. Read-after-writes are good at doubling +the number of bits affected, so the goal of mixing pulls in the opposite +direction as the goal of parallelism. I did what I could. Rotates +seem to cost as much as shifts on every machine I could lay my hands +on, and rotates are much kinder to the top and bottom bits, so I used +rotates. +------------------------------------------------------------------------------- +*/ +#define mix(a,b,c) \ +{ \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ +} + +/* +------------------------------------------------------------------------------- +final -- final mixing of 3 32-bit values (a,b,c) into c + +Pairs of (a,b,c) values differing in only a few bits will usually +produce values of c that look totally different. This was tested for +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +These constants passed: + 14 11 25 16 4 14 24 + 12 14 25 16 4 14 24 +and these came close: + 4 8 15 26 3 22 24 + 10 8 15 26 3 22 24 + 11 8 15 26 3 22 24 +------------------------------------------------------------------------------- +*/ +#define final(a,b,c) \ +{ \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c,4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ +} + + +/* +------------------------------------------------------------------------------- +hashlittle() -- hash a variable-length key into a 32-bit value + k : the key (the unaligned variable-length array of bytes) + length : the length of the key, counting by bytes + initval : can be any 4-byte value +Returns a 32-bit value. Every bit of the key affects every bit of +the return value. Two keys differing by one or two bits will have +totally different hash values. + +The best hash table sizes are powers of 2. There is no need to do +mod a prime (mod is sooo slow!). If you need less than 32 bits, +use a bitmask. For example, if you need only 10 bits, do + h = (h & hashmask(10)); +In which case, the hash table should have hashsize(10) elements. + +If you are hashing n strings (uint8_t **)k, do it like this: + for (i=0, h=0; i 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]&0xffffff" actually reads beyond the end of the string, but + * then masks off the part it's not allowed to read. Because the + * string is aligned, the masked-off tail is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticably faster for short strings (like English words). + */ +#ifndef VALGRIND + + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff; a+=k[0]; break; + case 6 : b+=k[1]&0xffff; a+=k[0]; break; + case 5 : b+=k[1]&0xff; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff; break; + case 2 : a+=k[0]&0xffff; break; + case 1 : a+=k[0]&0xff; break; + case 0 : return c; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + + const uint8_t *k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]; break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ + case 1 : a+=k8[0]; break; + case 0 : return c; + } + +#endif /* !valgrind */ + + } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { + const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ + const uint8_t *k8; + + /*--------------- all but last block: aligned reads and different mixing */ + while (length > 12) + { + a += k[0] + (((uint32_t)k[1])<<16); + b += k[2] + (((uint32_t)k[3])<<16); + c += k[4] + (((uint32_t)k[5])<<16); + mix(a,b,c); + length -= 12; + k += 6; + } + + /*----------------------------- handle the last (probably partial) block */ + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[4]+(((uint32_t)k[5])<<16); + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=k[4]; + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=k[2]; + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=k[0]; + break; + case 1 : a+=k8[0]; + break; + case 0 : return c; /* zero length requires no mixing */ + } + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + a += ((uint32_t)k[1])<<8; + a += ((uint32_t)k[2])<<16; + a += ((uint32_t)k[3])<<24; + b += k[4]; + b += ((uint32_t)k[5])<<8; + b += ((uint32_t)k[6])<<16; + b += ((uint32_t)k[7])<<24; + c += k[8]; + c += ((uint32_t)k[9])<<8; + c += ((uint32_t)k[10])<<16; + c += ((uint32_t)k[11])<<24; + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) /* all the case statements fall through */ + { + case 12: c+=((uint32_t)k[11])<<24; + case 11: c+=((uint32_t)k[10])<<16; + case 10: c+=((uint32_t)k[9])<<8; + case 9 : c+=k[8]; + case 8 : b+=((uint32_t)k[7])<<24; + case 7 : b+=((uint32_t)k[6])<<16; + case 6 : b+=((uint32_t)k[5])<<8; + case 5 : b+=k[4]; + case 4 : a+=((uint32_t)k[3])<<24; + case 3 : a+=((uint32_t)k[2])<<16; + case 2 : a+=((uint32_t)k[1])<<8; + case 1 : a+=k[0]; + break; + case 0 : return c; + } + } + + final(a,b,c); + return c; +} + +unsigned long lh_char_hash(const void *k) +{ + static volatile int random_seed = -1; + + if (random_seed == -1) { + int seed; + /* we can't use -1 as it is the unitialized sentinel */ + while ((seed = json_c_get_random_seed()) == -1); +#if defined __GNUC__ + __sync_val_compare_and_swap(&random_seed, -1, seed); +#elif defined _MSC_VER + InterlockedCompareExchange(&random_seed, seed, -1); +#else +#warning "racy random seed initializtion if used by multiple threads" + random_seed = seed; /* potentially racy */ +#endif + } + + return hashlittle((const char*)k, strlen((const char*)k), random_seed); +} + +int lh_char_equal(const void *k1, const void *k2) +{ + return (strcmp((const char*)k1, (const char*)k2) == 0); +} + +struct lh_table* lh_table_new(int size, const char *name, + lh_entry_free_fn *free_fn, + lh_hash_fn *hash_fn, + lh_equal_fn *equal_fn) +{ + int i; + struct lh_table *t; + + t = (struct lh_table*)calloc(1, sizeof(struct lh_table)); + if(!t) lh_abort("lh_table_new: calloc failed\n"); + t->count = 0; + t->size = size; + t->name = name; + t->table = (struct lh_entry*)calloc(size, sizeof(struct lh_entry)); + if(!t->table) lh_abort("lh_table_new: calloc failed\n"); + t->free_fn = free_fn; + t->hash_fn = hash_fn; + t->equal_fn = equal_fn; + for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY; + return t; +} + +struct lh_table* lh_kchar_table_new(int size, const char *name, + lh_entry_free_fn *free_fn) +{ + return lh_table_new(size, name, free_fn, lh_char_hash, lh_char_equal); +} + +struct lh_table* lh_kptr_table_new(int size, const char *name, + lh_entry_free_fn *free_fn) +{ + return lh_table_new(size, name, free_fn, lh_ptr_hash, lh_ptr_equal); +} + +void lh_table_resize(struct lh_table *t, int new_size) +{ + struct lh_table *new_t; + struct lh_entry *ent; + + new_t = lh_table_new(new_size, t->name, NULL, t->hash_fn, t->equal_fn); + ent = t->head; + while(ent) { + lh_table_insert(new_t, ent->k, ent->v); + ent = ent->next; + } + free(t->table); + t->table = new_t->table; + t->size = new_size; + t->head = new_t->head; + t->tail = new_t->tail; + t->resizes++; + free(new_t); +} + +void lh_table_free(struct lh_table *t) +{ + struct lh_entry *c; + for(c = t->head; c != NULL; c = c->next) { + if(t->free_fn) { + t->free_fn(c); + } + } + free(t->table); + free(t); +} + + +int lh_table_insert(struct lh_table *t, void *k, const void *v) +{ + unsigned long h, n; + + t->inserts++; + if(t->count >= t->size * LH_LOAD_FACTOR) lh_table_resize(t, t->size * 2); + + h = t->hash_fn(k); + n = h % t->size; + + while( 1 ) { + if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) break; + t->collisions++; + if ((int)++n == t->size) n = 0; + } + + t->table[n].k = k; + t->table[n].v = v; + t->count++; + + if(t->head == NULL) { + t->head = t->tail = &t->table[n]; + t->table[n].next = t->table[n].prev = NULL; + } else { + t->tail->next = &t->table[n]; + t->table[n].prev = t->tail; + t->table[n].next = NULL; + t->tail = &t->table[n]; + } + + return 0; +} + + +struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k) +{ + unsigned long h = t->hash_fn(k); + unsigned long n = h % t->size; + int count = 0; + + t->lookups++; + while( count < t->size ) { + if(t->table[n].k == LH_EMPTY) return NULL; + if(t->table[n].k != LH_FREED && + t->equal_fn(t->table[n].k, k)) return &t->table[n]; + if ((int)++n == t->size) n = 0; + count++; + } + return NULL; +} + + +const void* lh_table_lookup(struct lh_table *t, const void *k) +{ + void *result; + lh_table_lookup_ex(t, k, &result); + return result; +} + +json_bool lh_table_lookup_ex(struct lh_table* t, const void* k, void **v) +{ + struct lh_entry *e = lh_table_lookup_entry(t, k); + if (e != NULL) { + if (v != NULL) *v = (void *)e->v; + return TRUE; /* key found */ + } + if (v != NULL) *v = NULL; + return FALSE; /* key not found */ +} + +int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e) +{ + ptrdiff_t n = (ptrdiff_t)(e - t->table); /* CAW: fixed to be 64bit nice, still need the crazy negative case... */ + + /* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */ + if(n < 0) { return -2; } + + if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) return -1; + t->count--; + if(t->free_fn) t->free_fn(e); + t->table[n].v = NULL; + t->table[n].k = LH_FREED; + if(t->tail == &t->table[n] && t->head == &t->table[n]) { + t->head = t->tail = NULL; + } else if (t->head == &t->table[n]) { + t->head->next->prev = NULL; + t->head = t->head->next; + } else if (t->tail == &t->table[n]) { + t->tail->prev->next = NULL; + t->tail = t->tail->prev; + } else { + t->table[n].prev->next = t->table[n].next; + t->table[n].next->prev = t->table[n].prev; + } + t->table[n].next = t->table[n].prev = NULL; + return 0; +} + + +int lh_table_delete(struct lh_table *t, const void *k) +{ + struct lh_entry *e = lh_table_lookup_entry(t, k); + if(!e) return -1; + return lh_table_delete_entry(t, e); +} + +int lh_table_length(struct lh_table *t) +{ + return t->count; +} diff --git a/release/src/router/libjson-c/linkhash.h b/release/src/router/libjson-c/linkhash.h new file mode 100644 index 0000000000..950d09f35d --- /dev/null +++ b/release/src/router/libjson-c/linkhash.h @@ -0,0 +1,292 @@ +/* + * $Id: linkhash.h,v 1.6 2006/01/30 23:07:57 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef _linkhash_h_ +#define _linkhash_h_ + +#include "json_object.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * golden prime used in hash functions + */ +#define LH_PRIME 0x9e370001UL + +/** + * The fraction of filled hash buckets until an insert will cause the table + * to be resized. + * This can range from just above 0 up to 1.0. + */ +#define LH_LOAD_FACTOR 0.66 + +/** + * sentinel pointer value for empty slots + */ +#define LH_EMPTY (void*)-1 + +/** + * sentinel pointer value for freed slots + */ +#define LH_FREED (void*)-2 + +struct lh_entry; + +/** + * callback function prototypes + */ +typedef void (lh_entry_free_fn) (struct lh_entry *e); +/** + * callback function prototypes + */ +typedef unsigned long (lh_hash_fn) (const void *k); +/** + * callback function prototypes + */ +typedef int (lh_equal_fn) (const void *k1, const void *k2); + +/** + * An entry in the hash table + */ +struct lh_entry { + /** + * The key. + */ + void *k; + /** + * The value. + */ + const void *v; + /** + * The next entry + */ + struct lh_entry *next; + /** + * The previous entry. + */ + struct lh_entry *prev; +}; + + +/** + * The hash table structure. + */ +struct lh_table { + /** + * Size of our hash. + */ + int size; + /** + * Numbers of entries. + */ + int count; + + /** + * Number of collisions. + */ + int collisions; + + /** + * Number of resizes. + */ + int resizes; + + /** + * Number of lookups. + */ + int lookups; + + /** + * Number of inserts. + */ + int inserts; + + /** + * Number of deletes. + */ + int deletes; + + /** + * Name of the hash table. + */ + const char *name; + + /** + * The first entry. + */ + struct lh_entry *head; + + /** + * The last entry. + */ + struct lh_entry *tail; + + struct lh_entry *table; + + /** + * A pointer onto the function responsible for freeing an entry. + */ + lh_entry_free_fn *free_fn; + lh_hash_fn *hash_fn; + lh_equal_fn *equal_fn; +}; + + +/** + * Pre-defined hash and equality functions + */ +extern unsigned long lh_ptr_hash(const void *k); +extern int lh_ptr_equal(const void *k1, const void *k2); + +extern unsigned long lh_char_hash(const void *k); +extern int lh_char_equal(const void *k1, const void *k2); + + +/** + * Convenience list iterator. + */ +#define lh_foreach(table, entry) \ +for(entry = table->head; entry; entry = entry->next) + +/** + * lh_foreach_safe allows calling of deletion routine while iterating. + */ +#define lh_foreach_safe(table, entry, tmp) \ +for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp) + + + +/** + * Create a new linkhash table. + * @param size initial table size. The table is automatically resized + * although this incurs a performance penalty. + * @param name the table name. + * @param free_fn callback function used to free memory for entries + * when lh_table_free or lh_table_delete is called. + * If NULL is provided, then memory for keys and values + * must be freed by the caller. + * @param hash_fn function used to hash keys. 2 standard ones are defined: + * lh_ptr_hash and lh_char_hash for hashing pointer values + * and C strings respectively. + * @param equal_fn comparison function to compare keys. 2 standard ones defined: + * lh_ptr_hash and lh_char_hash for comparing pointer values + * and C strings respectively. + * @return a pointer onto the linkhash table. + */ +extern struct lh_table* lh_table_new(int size, const char *name, + lh_entry_free_fn *free_fn, + lh_hash_fn *hash_fn, + lh_equal_fn *equal_fn); + +/** + * Convenience function to create a new linkhash + * table with char keys. + * @param size initial table size. + * @param name table name. + * @param free_fn callback function used to free memory for entries. + * @return a pointer onto the linkhash table. + */ +extern struct lh_table* lh_kchar_table_new(int size, const char *name, + lh_entry_free_fn *free_fn); + + +/** + * Convenience function to create a new linkhash + * table with ptr keys. + * @param size initial table size. + * @param name table name. + * @param free_fn callback function used to free memory for entries. + * @return a pointer onto the linkhash table. + */ +extern struct lh_table* lh_kptr_table_new(int size, const char *name, + lh_entry_free_fn *free_fn); + + +/** + * Free a linkhash table. + * If a callback free function is provided then it is called for all + * entries in the table. + * @param t table to free. + */ +extern void lh_table_free(struct lh_table *t); + + +/** + * Insert a record into the table. + * @param t the table to insert into. + * @param k a pointer to the key to insert. + * @param v a pointer to the value to insert. + */ +extern int lh_table_insert(struct lh_table *t, void *k, const void *v); + + +/** + * Lookup a record into the table. + * @param t the table to lookup + * @param k a pointer to the key to lookup + * @return a pointer to the record structure of the value or NULL if it does not exist. + */ +extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k); + +/** + * Lookup a record into the table + * @param t the table to lookup + * @param k a pointer to the key to lookup + * @return a pointer to the found value or NULL if it does not exist. + * @deprecated Use lh_table_lookup_ex instead. + */ +THIS_FUNCTION_IS_DEPRECATED(extern const void* lh_table_lookup(struct lh_table *t, const void *k)); + +/** + * Lookup a record in the table + * @param t the table to lookup + * @param k a pointer to the key to lookup + * @param v a pointer to a where to store the found value (set to NULL if it doesn't exist). + * @return whether or not the key was found + */ +extern json_bool lh_table_lookup_ex(struct lh_table *t, const void *k, void **v); + +/** + * Delete a record from the table. + * If a callback free function is provided then it is called for the + * for the item being deleted. + * @param t the table to delete from. + * @param e a pointer to the entry to delete. + * @return 0 if the item was deleted. + * @return -1 if it was not found. + */ +extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e); + + +/** + * Delete a record from the table. + * If a callback free function is provided then it is called for the + * for the item being deleted. + * @param t the table to delete from. + * @param k a pointer to the key to delete. + * @return 0 if the item was deleted. + * @return -1 if it was not found. + */ +extern int lh_table_delete(struct lh_table *t, const void *k); + +extern int lh_table_length(struct lh_table *t); + +void lh_abort(const char *msg, ...); +void lh_table_resize(struct lh_table *t, int new_size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/release/src/router/libjson-c/math_compat.h b/release/src/router/libjson-c/math_compat.h new file mode 100644 index 0000000000..47ddd850cc --- /dev/null +++ b/release/src/router/libjson-c/math_compat.h @@ -0,0 +1,9 @@ +#ifndef __math_compat_h +#define __math_compat_h + +#undef isnan +#define isnan(x) __builtin_isnan(x) +#undef isinf +#define isinf(x) __builtin_isinf(x) + +#endif diff --git a/release/src/router/libjson-c/printbuf.c b/release/src/router/libjson-c/printbuf.c new file mode 100644 index 0000000000..9d56522000 --- /dev/null +++ b/release/src/router/libjson-c/printbuf.c @@ -0,0 +1,192 @@ +/* + * $Id: printbuf.c,v 1.5 2006/01/26 02:16:28 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + * + * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved. + * The copyrights to the contents of this file are licensed under the MIT License + * (http://www.opensource.org/licenses/mit-license.php) + */ + +#include "config.h" + +#include +#include +#include + +#ifdef HAVE_STDARG_H +# include +#else /* !HAVE_STDARG_H */ +# error Not enough var arg support! +#endif /* HAVE_STDARG_H */ + +#include "bits.h" +#include "debug.h" +#include "printbuf.h" + +static int printbuf_extend(struct printbuf *p, int min_size); + +struct printbuf* printbuf_new(void) +{ + struct printbuf *p; + + p = (struct printbuf*)calloc(1, sizeof(struct printbuf)); + if(!p) return NULL; + p->size = 32; + p->bpos = 0; + if(!(p->buf = (char*)malloc(p->size))) { + free(p); + return NULL; + } + return p; +} + + +/** + * Extend the buffer p so it has a size of at least min_size. + * + * If the current size is large enough, nothing is changed. + * + * Note: this does not check the available space! The caller + * is responsible for performing those calculations. + */ +static int printbuf_extend(struct printbuf *p, int min_size) +{ + char *t; + int new_size; + + if (p->size >= min_size) + return 0; + + new_size = json_max(p->size * 2, min_size + 8); +#ifdef PRINTBUF_DEBUG + MC_DEBUG("printbuf_memappend: realloc " + "bpos=%d min_size=%d old_size=%d new_size=%d\n", + p->bpos, min_size, p->size, new_size); +#endif /* PRINTBUF_DEBUG */ + if(!(t = (char*)realloc(p->buf, new_size))) + return -1; + p->size = new_size; + p->buf = t; + return 0; +} + +int printbuf_memappend(struct printbuf *p, const char *buf, int size) +{ + if (p->size <= p->bpos + size + 1) { + if (printbuf_extend(p, p->bpos + size + 1) < 0) + return -1; + } + memcpy(p->buf + p->bpos, buf, size); + p->bpos += size; + p->buf[p->bpos]= '\0'; + return size; +} + +int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len) +{ + int size_needed; + + if (offset == -1) + offset = pb->bpos; + size_needed = offset + len; + if (pb->size < size_needed) + { + if (printbuf_extend(pb, size_needed) < 0) + return -1; + } + + memset(pb->buf + offset, charvalue, len); + if (pb->bpos < size_needed) + pb->bpos = size_needed; + + return 0; +} + +#if !defined(HAVE_VSNPRINTF) && defined(_MSC_VER) +# define vsnprintf _vsnprintf +#elif !defined(HAVE_VSNPRINTF) /* !HAVE_VSNPRINTF */ +# error Need vsnprintf! +#endif /* !HAVE_VSNPRINTF && defined(WIN32) */ + +#if !defined(HAVE_VASPRINTF) +/* CAW: compliant version of vasprintf */ +static int vasprintf(char **buf, const char *fmt, va_list ap) +{ +#ifndef WIN32 + static char _T_emptybuffer = '\0'; +#endif /* !defined(WIN32) */ + int chars; + char *b; + + if(!buf) { return -1; } + +#ifdef WIN32 + chars = _vscprintf(fmt, ap)+1; +#else /* !defined(WIN32) */ + /* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite + our buffer like on some 64bit sun systems.... but hey, its time to move on */ + chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1; + if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this problem */ +#endif /* defined(WIN32) */ + + b = (char*)malloc(sizeof(char)*chars); + if(!b) { return -1; } + + if((chars = vsprintf(b, fmt, ap)) < 0) + { + free(b); + } else { + *buf = b; + } + + return chars; +} +#endif /* !HAVE_VASPRINTF */ + +int sprintbuf(struct printbuf *p, const char *msg, ...) +{ + va_list ap; + char *t; + int size; + char buf[128]; + + /* user stack buffer first */ + va_start(ap, msg); + size = vsnprintf(buf, 128, msg, ap); + va_end(ap); + /* if string is greater than stack buffer, then use dynamic string + with vasprintf. Note: some implementation of vsnprintf return -1 + if output is truncated whereas some return the number of bytes that + would have been written - this code handles both cases. */ + if(size == -1 || size > 127) { + va_start(ap, msg); + if((size = vasprintf(&t, msg, ap)) < 0) { va_end(ap); return -1; } + va_end(ap); + printbuf_memappend(p, t, size); + free(t); + return size; + } else { + printbuf_memappend(p, buf, size); + return size; + } +} + +void printbuf_reset(struct printbuf *p) +{ + p->buf[0] = '\0'; + p->bpos = 0; +} + +void printbuf_free(struct printbuf *p) +{ + if(p) { + free(p->buf); + free(p); + } +} diff --git a/release/src/router/libjson-c/printbuf.h b/release/src/router/libjson-c/printbuf.h new file mode 100644 index 0000000000..b1bde7f9f8 --- /dev/null +++ b/release/src/router/libjson-c/printbuf.h @@ -0,0 +1,77 @@ +/* + * $Id: printbuf.h,v 1.4 2006/01/26 02:16:28 mclark Exp $ + * + * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + * + * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved. + * The copyrights to the contents of this file are licensed under the MIT License + * (http://www.opensource.org/licenses/mit-license.php) + */ + +#ifndef _printbuf_h_ +#define _printbuf_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct printbuf { + char *buf; + int bpos; + int size; +}; + +extern struct printbuf* +printbuf_new(void); + +/* As an optimization, printbuf_memappend_fast is defined as a macro + * that handles copying data if the buffer is large enough; otherwise + * it invokes printbuf_memappend_real() which performs the heavy + * lifting of realloc()ing the buffer and copying data. + * Your code should not use printbuf_memappend directly--use + * printbuf_memappend_fast instead. + */ +extern int +printbuf_memappend(struct printbuf *p, const char *buf, int size); + +#define printbuf_memappend_fast(p, bufptr, bufsize) \ +do { \ + if ((p->size - p->bpos) > bufsize) { \ + memcpy(p->buf + p->bpos, (bufptr), bufsize); \ + p->bpos += bufsize; \ + p->buf[p->bpos]= '\0'; \ + } else { printbuf_memappend(p, (bufptr), bufsize); } \ +} while (0) + +#define printbuf_length(p) ((p)->bpos) + +/** + * Set len bytes of the buffer to charvalue, starting at offset offset. + * Similar to calling memset(x, charvalue, len); + * + * The memory allocated for the buffer is extended as necessary. + * + * If offset is -1, this starts at the end of the current data in the buffer. + */ +extern int +printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len); + +extern int +sprintbuf(struct printbuf *p, const char *msg, ...); + +extern void +printbuf_reset(struct printbuf *p); + +extern void +printbuf_free(struct printbuf *p); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/release/src/router/libjson-c/random_seed.c b/release/src/router/libjson-c/random_seed.c new file mode 100644 index 0000000000..3b520d411e --- /dev/null +++ b/release/src/router/libjson-c/random_seed.c @@ -0,0 +1,237 @@ +/* + * random_seed.c + * + * Copyright (c) 2013 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#include +#include "config.h" + +#define DEBUG_SEED(s) + + +#if defined ENABLE_RDRAND + +/* cpuid */ + +#if defined __GNUC__ && (defined __i386__ || defined __x86_64__) +#define HAS_X86_CPUID 1 + +static void do_cpuid(int regs[], int h) +{ + __asm__ __volatile__( +#if defined __x86_64__ + "pushq %%rbx;\n" +#else + "pushl %%ebx;\n" +#endif + "cpuid;\n" +#if defined __x86_64__ + "popq %%rbx;\n" +#else + "popl %%ebx;\n" +#endif + : "=a"(regs[0]), [ebx] "=r"(regs[1]), "=c"(regs[2]), "=d"(regs[3]) + : "a"(h)); +} + +#elif defined _MSC_VER + +#define HAS_X86_CPUID 1 +#define do_cpuid __cpuid + +#endif + +/* has_rdrand */ + +#if HAS_X86_CPUID + +static int has_rdrand() +{ + // CPUID.01H:ECX.RDRAND[bit 30] == 1 + int regs[4]; + do_cpuid(regs, 1); + return (regs[2] & (1 << 30)) != 0; +} + +#endif + +/* get_rdrand_seed - GCC x86 and X64 */ + +#if defined __GNUC__ && (defined __i386__ || defined __x86_64__) + +#define HAVE_RDRAND 1 + +static int get_rdrand_seed() +{ + DEBUG_SEED("get_rdrand_seed"); + int _eax; + // rdrand eax + __asm__ __volatile__("1: .byte 0x0F\n" + " .byte 0xC7\n" + " .byte 0xF0\n" + " jnc 1b;\n" + : "=a" (_eax)); + return _eax; +} + +#endif + +#if defined _MSC_VER + +#if _MSC_VER >= 1700 +#define HAVE_RDRAND 1 + +/* get_rdrand_seed - Visual Studio 2012 and above */ + +static int get_rdrand_seed() +{ + DEBUG_SEED("get_rdrand_seed"); + int r; + while (_rdrand32_step(&r) == 0); + return r; +} + +#elif defined _M_IX86 +#define HAVE_RDRAND 1 + +/* get_rdrand_seed - Visual Studio 2010 and below - x86 only */ + +static int get_rdrand_seed() +{ + DEBUG_SEED("get_rdrand_seed"); + int _eax; +retry: + // rdrand eax + __asm _emit 0x0F __asm _emit 0xC7 __asm _emit 0xF0 + __asm jnc retry + __asm mov _eax, eax + return _eax; +} + +#endif +#endif + +#endif /* defined ENABLE_RDRAND */ + + +/* has_dev_urandom */ + +#if defined (__APPLE__) || defined(__unix__) || defined(__linux__) + +#include +#include +#include +#include +#include +#include + +#define HAVE_DEV_RANDOM 1 + +static const char *dev_random_file = "/dev/urandom"; + +static int has_dev_urandom() +{ + struct stat buf; + if (stat(dev_random_file, &buf)) { + return 0; + } + return ((buf.st_mode & S_IFCHR) != 0); +} + + +/* get_dev_random_seed */ + +static int get_dev_random_seed() +{ + DEBUG_SEED("get_dev_random_seed"); + + int fd = open(dev_random_file, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "error opening %s: %s", dev_random_file, strerror(errno)); + exit(1); + } + + int r; + ssize_t nread = read(fd, &r, sizeof(r)); + if (nread != sizeof(r)) { + fprintf(stderr, "error read %s: %s", dev_random_file, strerror(errno)); + exit(1); + } + else if (nread != sizeof(r)) { + fprintf(stderr, "error short read %s", dev_random_file); + exit(1); + } + close(fd); + return r; +} + +#endif + + +/* get_cryptgenrandom_seed */ + +#ifdef WIN32 + +#define HAVE_CRYPTGENRANDOM 1 + +#include +#pragma comment(lib, "advapi32.lib") + +static int get_cryptgenrandom_seed() +{ + DEBUG_SEED("get_cryptgenrandom_seed"); + + HCRYPTPROV hProvider = 0; + int r; + + if (!CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { + fprintf(stderr, "error CryptAcquireContextW"); + exit(1); + } + + if (!CryptGenRandom(hProvider, sizeof(r), (BYTE*)&r)) { + fprintf(stderr, "error CryptGenRandom"); + exit(1); + } + + CryptReleaseContext(hProvider, 0); + + return r; +} + +#endif + + +/* get_time_seed */ + +#include + +static int get_time_seed() +{ + DEBUG_SEED("get_time_seed"); + + return (int)time(NULL) * 433494437; +} + + +/* json_c_get_random_seed */ + +int json_c_get_random_seed() +{ +#if HAVE_RDRAND + if (has_rdrand()) return get_rdrand_seed(); +#endif +#if HAVE_DEV_RANDOM + if (has_dev_urandom()) return get_dev_random_seed(); +#endif +#if HAVE_CRYPTGENRANDOM + return get_cryptgenrandom_seed(); +#endif + return get_time_seed(); +} diff --git a/release/src/router/libjson-c/random_seed.h b/release/src/router/libjson-c/random_seed.h new file mode 100644 index 0000000000..7362d67d9c --- /dev/null +++ b/release/src/router/libjson-c/random_seed.h @@ -0,0 +1,25 @@ +/* + * random_seed.h + * + * Copyright (c) 2013 Metaparadigm Pte. Ltd. + * Michael Clark + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See COPYING for details. + * + */ + +#ifndef seed_h +#define seed_h + +#ifdef __cplusplus +extern "C" { +#endif + +extern int json_c_get_random_seed(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/release/src/router/libjson-c/tests/Makefile.am b/release/src/router/libjson-c/tests/Makefile.am new file mode 100644 index 0000000000..a388eeb993 --- /dev/null +++ b/release/src/router/libjson-c/tests/Makefile.am @@ -0,0 +1,41 @@ + +include ../Makefile.am.inc +LDADD= $(LIBJSON_LA) + +LIBJSON_LA=$(top_builddir)/libjson-c.la + +TESTS= +TESTS+= test1.test +TESTS+= test2.test +TESTS+= test4.test +TESTS+= testReplaceExisting.test +TESTS+= test_parse_int64.test +TESTS+= test_null.test +TESTS+= test_cast.test +TESTS+= test_parse.test +TESTS+= test_locale.test +TESTS+= test_charcase.test +TESTS+= test_printbuf.test +TESTS+= test_set_serializer.test + +check_PROGRAMS= +check_PROGRAMS += $(TESTS:.test=) + +# Note: handled by test1.test +check_PROGRAMS += test1Formatted +test1Formatted_SOURCES = test1.c parse_flags.c +test1Formatted_CPPFLAGS = -DTEST_FORMATTED + +# Note: handled by test2.test +check_PROGRAMS += test2Formatted +test2Formatted_SOURCES = test2.c parse_flags.c +test2Formatted_CPPFLAGS = -DTEST_FORMATTED + +EXTRA_DIST= +EXTRA_DIST += $(TESTS) + +testsubdir=testSubDir +TESTS_ENVIRONMENT = top_builddir=$(top_builddir) + +distclean-local: + -rm -rf $(testsubdir) diff --git a/release/src/router/libjson-c/tests/parse_flags.c b/release/src/router/libjson-c/tests/parse_flags.c new file mode 100644 index 0000000000..1af61ea418 --- /dev/null +++ b/release/src/router/libjson-c/tests/parse_flags.c @@ -0,0 +1,50 @@ +#include "config.h" + +#include +#include + +#include "json.h" +#include "parse_flags.h" + +#if !defined(HAVE_STRCASECMP) && defined(_MSC_VER) +# define strcasecmp _stricmp +#elif !defined(HAVE_STRCASECMP) +# error You do not have strcasecmp on your system. +#endif /* HAVE_STRNCASECMP */ + +static struct { + const char *arg; + int flag; +} format_args[] = { + { "plain", JSON_C_TO_STRING_PLAIN }, + { "spaced", JSON_C_TO_STRING_SPACED }, + { "pretty", JSON_C_TO_STRING_PRETTY }, +}; + +#ifndef NELEM +#define NELEM(x) (sizeof(x) / sizeof(&x[0])) +#endif + +int parse_flags(int argc, char **argv) +{ + int arg_idx; + int sflags = 0; + for (arg_idx = 1; arg_idx < argc ; arg_idx++) + { + int jj; + for (jj = 0; jj < (int)NELEM(format_args); jj++) + { + if (strcasecmp(argv[arg_idx], format_args[jj].arg) == 0) + { + sflags |= format_args[jj].flag; + break; + } + } + if (jj == NELEM(format_args)) + { + printf("Unknown arg: %s\n", argv[arg_idx]); + exit(1); + } + } + return sflags; +} diff --git a/release/src/router/libjson-c/tests/parse_flags.h b/release/src/router/libjson-c/tests/parse_flags.h new file mode 100644 index 0000000000..c5e2f41035 --- /dev/null +++ b/release/src/router/libjson-c/tests/parse_flags.h @@ -0,0 +1,4 @@ +#ifndef __parse_flags_h +#define __parse_flags_h +int parse_flags(int argc, char **argv); +#endif diff --git a/release/src/router/libjson-c/tests/test-defs.sh b/release/src/router/libjson-c/tests/test-defs.sh new file mode 100755 index 0000000000..658a75d9e4 --- /dev/null +++ b/release/src/router/libjson-c/tests/test-defs.sh @@ -0,0 +1,128 @@ +#!/bin/sh + +# Make sure srcdir is an absolute path. Supply the variable +# if it does not exist. We want to be able to run the tests +# stand-alone!! +# +srcdir=${srcdir-.} +if test ! -d $srcdir ; then + echo "test-defs.sh: installation error" 1>&2 + exit 1 +fi + +# Use absolute paths +case "$srcdir" in + /* | [A-Za-z]:\\*) ;; + *) srcdir=`\cd $srcdir && pwd` ;; +esac + +case "$top_builddir" in + /* | [A-Za-z]:\\*) ;; + *) top_builddir=`\cd ${top_builddir-..} && pwd` ;; +esac + +top_builddir=${top_builddir}/tests + +progname=`echo "$0" | sed 's,^.*/,,'` +testname=`echo "$progname" | sed 's,-.*$,,'` +testsubdir=${testsubdir-testSubDir} +testsubdir=${testsubdir}/${progname} + +# User can set VERBOSE to cause output redirection +case "$VERBOSE" in +[Nn]|[Nn][Oo]|0|"") + VERBOSE=0 + exec > /dev/null + ;; +[Yy]|[Yy][Ee][Ss]) + VERBOSE=1 + ;; +esac + +rm -rf "$testsubdir" > /dev/null 2>&1 +mkdir -p "$testsubdir" +CURDIR=$(pwd) +cd "$testsubdir" \ + || { echo "Cannot make or change into $testsubdir"; exit 1; } + +echo "=== Running test $progname" + +CMP="${CMP-cmp}" + +use_valgrind=${USE_VALGRIND-1} +valgrind_path=$(which valgrind 2> /dev/null) +if [ -z "${valgrind_path}" -o ! -x "${valgrind_path}" ] ; then + use_valgrind=0 +fi + +# +# This is a common function to check the results of a test program +# that is intended to generate consistent output across runs. +# +# ${top_builddir} must be set to the top level build directory. +# +# Output will be written to the current directory. +# +# It must be passed the name of the test command to run, which must be present +# in the ${top_builddir} directory. +# +# It will compare the output of running that against .expected +# +run_output_test() +{ + if [ "$1" = "-o" ] ; then + TEST_OUTPUT="$2" + shift + shift + fi + TEST_COMMAND="$1" + shift + if [ -z "${TEST_OUTPUT}" ] ; then + TEST_OUTPUT=${TEST_COMMAND} + fi + + REDIR_OUTPUT="> \"${TEST_OUTPUT}.out\"" + if [ $VERBOSE -gt 1 ] ; then + REDIR_OUTPUT="| tee \"${TEST_OUTPUT}.out\"" + fi + + if [ $use_valgrind -eq 1 ] ; then + eval valgrind --tool=memcheck \ + --trace-children=yes \ + --demangle=yes \ + --log-file="${TEST_OUTPUT}.vg.out" \ + --leak-check=full \ + --show-reachable=yes \ + --run-libc-freeres=yes \ + "\"${top_builddir}/${TEST_COMMAND}\"" \"\$@\" ${REDIR_OUTPUT} + err=$? + + else + eval "\"${top_builddir}/${TEST_COMMAND}"\" \"\$@\" ${REDIR_OUTPUT} + err=$? + fi + + if [ $err -ne 0 ] ; then + echo "ERROR: \"${TEST_COMMAND} $@\" exited with non-zero exit status: $err" 1>&2 + fi + + if [ $use_valgrind -eq 1 ] ; then + if ! tail -1 "${TEST_OUTPUT}.vg.out" | grep -q "ERROR SUMMARY: 0 errors" ; then + echo "ERROR: valgrind found errors during execution:" 1>&2 + cat "${TEST_OUTPUT}.vg.out" + err=1 + fi + fi + + if ! "$CMP" -s "${top_builddir}/${TEST_OUTPUT}.expected" "${TEST_OUTPUT}.out" ; then + echo "ERROR: \"${TEST_COMMAND} $@\" (${TEST_OUTPUT}) failed (set VERBOSE=1 to see full output):" 1>&2 + (cd "${CURDIR}" ; set -x ; diff "${top_builddir}/${TEST_OUTPUT}.expected" "$testsubdir/${TEST_OUTPUT}.out") + echo "cp \"$testsubdir/${TEST_OUTPUT}.out\" \"${top_builddir}/${TEST_OUTPUT}.expected\"" 1>&2 + + err=1 + fi + + return $err +} + + diff --git a/release/src/router/libjson-c/tests/test1.c b/release/src/router/libjson-c/tests/test1.c new file mode 100644 index 0000000000..7acea62212 --- /dev/null +++ b/release/src/router/libjson-c/tests/test1.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include +#include + +#include "json.h" +#include "parse_flags.h" + +static int sort_fn (const void *j1, const void *j2) +{ + json_object * const *jso1, * const *jso2; + int i1, i2; + + jso1 = (json_object* const*)j1; + jso2 = (json_object* const*)j2; + if (!*jso1 && !*jso2) + return 0; + if (!*jso1) + return -1; + if (!*jso2) + return 1; + + i1 = json_object_get_int(*jso1); + i2 = json_object_get_int(*jso2); + + return i1 - i2; +} + +#ifdef TEST_FORMATTED +#define json_object_to_json_string(obj) json_object_to_json_string_ext(obj,sflags) +#else +/* no special define */ +#endif + +int main(int argc, char **argv) +{ + json_object *my_string, *my_int, *my_object, *my_array; + int i; +#ifdef TEST_FORMATTED + int sflags = 0; +#endif + + MC_SET_DEBUG(1); + +#ifdef TEST_FORMATTED + sflags = parse_flags(argc, argv); +#endif + + my_string = json_object_new_string("\t"); + printf("my_string=%s\n", json_object_get_string(my_string)); + printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string)); + json_object_put(my_string); + + my_string = json_object_new_string("\\"); + printf("my_string=%s\n", json_object_get_string(my_string)); + printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string)); + json_object_put(my_string); + + my_string = json_object_new_string("foo"); + printf("my_string=%s\n", json_object_get_string(my_string)); + printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string)); + + my_int = json_object_new_int(9); + printf("my_int=%d\n", json_object_get_int(my_int)); + printf("my_int.to_string()=%s\n", json_object_to_json_string(my_int)); + + my_array = json_object_new_array(); + json_object_array_add(my_array, json_object_new_int(1)); + json_object_array_add(my_array, json_object_new_int(2)); + json_object_array_add(my_array, json_object_new_int(3)); + json_object_array_put_idx(my_array, 4, json_object_new_int(5)); + printf("my_array=\n"); + for(i=0; i < json_object_array_length(my_array); i++) + { + json_object *obj = json_object_array_get_idx(my_array, i); + printf("\t[%d]=%s\n", i, json_object_to_json_string(obj)); + } + printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array)); + + json_object_put(my_array); + + my_array = json_object_new_array(); + json_object_array_add(my_array, json_object_new_int(3)); + json_object_array_add(my_array, json_object_new_int(1)); + json_object_array_add(my_array, json_object_new_int(2)); + json_object_array_put_idx(my_array, 4, json_object_new_int(0)); + printf("my_array=\n"); + for(i=0; i < json_object_array_length(my_array); i++) + { + json_object *obj = json_object_array_get_idx(my_array, i); + printf("\t[%d]=%s\n", i, json_object_to_json_string(obj)); + } + printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array)); + json_object_array_sort(my_array, sort_fn); + printf("my_array=\n"); + for(i=0; i < json_object_array_length(my_array); i++) + { + json_object *obj = json_object_array_get_idx(my_array, i); + printf("\t[%d]=%s\n", i, json_object_to_json_string(obj)); + } + printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array)); + + my_object = json_object_new_object(); + json_object_object_add(my_object, "abc", json_object_new_int(12)); + json_object_object_add(my_object, "foo", json_object_new_string("bar")); + json_object_object_add(my_object, "bool0", json_object_new_boolean(0)); + json_object_object_add(my_object, "bool1", json_object_new_boolean(1)); + json_object_object_add(my_object, "baz", json_object_new_string("bang")); + + json_object *baz_obj = json_object_new_string("fark"); + json_object_get(baz_obj); + json_object_object_add(my_object, "baz", baz_obj); + json_object_object_del(my_object, "baz"); + + /* baz_obj should still be valid */ + printf("baz_obj.to_string()=%s\n", json_object_to_json_string(baz_obj)); + json_object_put(baz_obj); + + /*json_object_object_add(my_object, "arr", my_array);*/ + printf("my_object=\n"); + json_object_object_foreach(my_object, key, val) + { + printf("\t%s: %s\n", key, json_object_to_json_string(val)); + } + printf("my_object.to_string()=%s\n", json_object_to_json_string(my_object)); + + json_object_put(my_string); + json_object_put(my_int); + json_object_put(my_object); + json_object_put(my_array); + + return 0; +} diff --git a/release/src/router/libjson-c/tests/test1.expected b/release/src/router/libjson-c/tests/test1.expected new file mode 100644 index 0000000000..e36aaa4c4f --- /dev/null +++ b/release/src/router/libjson-c/tests/test1.expected @@ -0,0 +1,36 @@ +my_string= +my_string.to_string()="\t" +my_string=\ +my_string.to_string()="\\" +my_string=foo +my_string.to_string()="foo" +my_int=9 +my_int.to_string()=9 +my_array= + [0]=1 + [1]=2 + [2]=3 + [3]=null + [4]=5 +my_array.to_string()=[ 1, 2, 3, null, 5 ] +my_array= + [0]=3 + [1]=1 + [2]=2 + [3]=null + [4]=0 +my_array.to_string()=[ 3, 1, 2, null, 0 ] +my_array= + [0]=null + [1]=0 + [2]=1 + [3]=2 + [4]=3 +my_array.to_string()=[ null, 0, 1, 2, 3 ] +baz_obj.to_string()="fark" +my_object= + abc: 12 + foo: "bar" + bool0: false + bool1: true +my_object.to_string()={ "abc": 12, "foo": "bar", "bool0": false, "bool1": true } diff --git a/release/src/router/libjson-c/tests/test1.test b/release/src/router/libjson-c/tests/test1.test new file mode 100755 index 0000000000..79d2e09a88 --- /dev/null +++ b/release/src/router/libjson-c/tests/test1.test @@ -0,0 +1,22 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test1 +_err=$? + +for flag in plain spaced pretty ; do + run_output_test -o test1Formatted_${flag} test1Formatted ${flag} + _err2=$? + if [ $_err -eq 0 ] ; then + _err=$_err2 + fi +done + +exit $_err diff --git a/release/src/router/libjson-c/tests/test1Formatted_plain.expected b/release/src/router/libjson-c/tests/test1Formatted_plain.expected new file mode 100644 index 0000000000..edcc1b9328 --- /dev/null +++ b/release/src/router/libjson-c/tests/test1Formatted_plain.expected @@ -0,0 +1,36 @@ +my_string= +my_string.to_string()="\t" +my_string=\ +my_string.to_string()="\\" +my_string=foo +my_string.to_string()="foo" +my_int=9 +my_int.to_string()=9 +my_array= + [0]=1 + [1]=2 + [2]=3 + [3]=null + [4]=5 +my_array.to_string()=[1,2,3,null,5] +my_array= + [0]=3 + [1]=1 + [2]=2 + [3]=null + [4]=0 +my_array.to_string()=[3,1,2,null,0] +my_array= + [0]=null + [1]=0 + [2]=1 + [3]=2 + [4]=3 +my_array.to_string()=[null,0,1,2,3] +baz_obj.to_string()="fark" +my_object= + abc: 12 + foo: "bar" + bool0: false + bool1: true +my_object.to_string()={"abc":12,"foo":"bar","bool0":false,"bool1":true} diff --git a/release/src/router/libjson-c/tests/test1Formatted_pretty.expected b/release/src/router/libjson-c/tests/test1Formatted_pretty.expected new file mode 100644 index 0000000000..95e48ed010 --- /dev/null +++ b/release/src/router/libjson-c/tests/test1Formatted_pretty.expected @@ -0,0 +1,59 @@ +my_string= +my_string.to_string()="\t" +my_string=\ +my_string.to_string()="\\" +my_string=foo +my_string.to_string()="foo" +my_int=9 +my_int.to_string()=9 +my_array= + [0]=1 + [1]=2 + [2]=3 + [3]=null + [4]=5 +my_array.to_string()=[ + 1, + 2, + 3, + null, + 5 +] +my_array= + [0]=3 + [1]=1 + [2]=2 + [3]=null + [4]=0 +my_array.to_string()=[ + 3, + 1, + 2, + null, + 0 +] +my_array= + [0]=null + [1]=0 + [2]=1 + [3]=2 + [4]=3 +my_array.to_string()=[ + null, + 0, + 1, + 2, + 3 +] +baz_obj.to_string()="fark" +my_object= + abc: 12 + foo: "bar" + bool0: false + bool1: true +my_object.to_string()={ + "abc":12, + "foo":"bar", + "bool0":false, + "bool1":true +} diff --git a/release/src/router/libjson-c/tests/test1Formatted_spaced.expected b/release/src/router/libjson-c/tests/test1Formatted_spaced.expected new file mode 100644 index 0000000000..e36aaa4c4f --- /dev/null +++ b/release/src/router/libjson-c/tests/test1Formatted_spaced.expected @@ -0,0 +1,36 @@ +my_string= +my_string.to_string()="\t" +my_string=\ +my_string.to_string()="\\" +my_string=foo +my_string.to_string()="foo" +my_int=9 +my_int.to_string()=9 +my_array= + [0]=1 + [1]=2 + [2]=3 + [3]=null + [4]=5 +my_array.to_string()=[ 1, 2, 3, null, 5 ] +my_array= + [0]=3 + [1]=1 + [2]=2 + [3]=null + [4]=0 +my_array.to_string()=[ 3, 1, 2, null, 0 ] +my_array= + [0]=null + [1]=0 + [2]=1 + [3]=2 + [4]=3 +my_array.to_string()=[ null, 0, 1, 2, 3 ] +baz_obj.to_string()="fark" +my_object= + abc: 12 + foo: "bar" + bool0: false + bool1: true +my_object.to_string()={ "abc": 12, "foo": "bar", "bool0": false, "bool1": true } diff --git a/release/src/router/libjson-c/tests/test2.c b/release/src/router/libjson-c/tests/test2.c new file mode 100644 index 0000000000..ce44e46ffa --- /dev/null +++ b/release/src/router/libjson-c/tests/test2.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include + +#include "json.h" +#include "parse_flags.h" + +#ifdef TEST_FORMATTED +#define json_object_to_json_string(obj) json_object_to_json_string_ext(obj,sflags) +#else +/* no special define */ +#endif + + +int main(int argc, char **argv) +{ + json_object *new_obj; +#ifdef TEST_FORMATTED + int sflags = 0; +#endif + + MC_SET_DEBUG(1); + +#ifdef TEST_FORMATTED + sflags = parse_flags(argc, argv); +#endif + + new_obj = json_tokener_parse("/* more difficult test case */ { \"glossary\": { \"title\": \"example glossary\", \"GlossDiv\": { \"title\": \"S\", \"GlossList\": [ { \"ID\": \"SGML\", \"SortAs\": \"SGML\", \"GlossTerm\": \"Standard Generalized Markup Language\", \"Acronym\": \"SGML\", \"Abbrev\": \"ISO 8879:1986\", \"GlossDef\": \"A meta-markup language, used to create markup languages such as DocBook.\", \"GlossSeeAlso\": [\"GML\", \"XML\", \"markup\"] } ] } } }"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + return 0; +} diff --git a/release/src/router/libjson-c/tests/test2.expected b/release/src/router/libjson-c/tests/test2.expected new file mode 100644 index 0000000000..0b740a9f02 --- /dev/null +++ b/release/src/router/libjson-c/tests/test2.expected @@ -0,0 +1 @@ +new_obj.to_string()={ "glossary": { "title": "example glossary", "GlossDiv": { "title": "S", "GlossList": [ { "ID": "SGML", "SortAs": "SGML", "GlossTerm": "Standard Generalized Markup Language", "Acronym": "SGML", "Abbrev": "ISO 8879:1986", "GlossDef": "A meta-markup language, used to create markup languages such as DocBook.", "GlossSeeAlso": [ "GML", "XML", "markup" ] } ] } } } diff --git a/release/src/router/libjson-c/tests/test2.test b/release/src/router/libjson-c/tests/test2.test new file mode 100755 index 0000000000..d4a4e792b7 --- /dev/null +++ b/release/src/router/libjson-c/tests/test2.test @@ -0,0 +1,22 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test2 +_err=$? + +for flag in plain spaced pretty ; do + run_output_test -o test2Formatted_${flag} test2Formatted ${flag} + _err2=$? + if [ $_err -eq 0 ] ; then + _err=$_err2 + fi +done + +exit $_err diff --git a/release/src/router/libjson-c/tests/test2Formatted_plain.expected b/release/src/router/libjson-c/tests/test2Formatted_plain.expected new file mode 100644 index 0000000000..cc587e9047 --- /dev/null +++ b/release/src/router/libjson-c/tests/test2Formatted_plain.expected @@ -0,0 +1 @@ +new_obj.to_string()={"glossary":{"title":"example glossary","GlossDiv":{"title":"S","GlossList":[{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML","markup"]}]}}} diff --git a/release/src/router/libjson-c/tests/test2Formatted_pretty.expected b/release/src/router/libjson-c/tests/test2Formatted_pretty.expected new file mode 100644 index 0000000000..8d6d740277 --- /dev/null +++ b/release/src/router/libjson-c/tests/test2Formatted_pretty.expected @@ -0,0 +1,23 @@ +new_obj.to_string()={ + "glossary":{ + "title":"example glossary", + "GlossDiv":{ + "title":"S", + "GlossList":[ + { + "ID":"SGML", + "SortAs":"SGML", + "GlossTerm":"Standard Generalized Markup Language", + "Acronym":"SGML", + "Abbrev":"ISO 8879:1986", + "GlossDef":"A meta-markup language, used to create markup languages such as DocBook.", + "GlossSeeAlso":[ + "GML", + "XML", + "markup" + ] + } + ] + } + } +} diff --git a/release/src/router/libjson-c/tests/test2Formatted_spaced.expected b/release/src/router/libjson-c/tests/test2Formatted_spaced.expected new file mode 100644 index 0000000000..0b740a9f02 --- /dev/null +++ b/release/src/router/libjson-c/tests/test2Formatted_spaced.expected @@ -0,0 +1 @@ +new_obj.to_string()={ "glossary": { "title": "example glossary", "GlossDiv": { "title": "S", "GlossList": [ { "ID": "SGML", "SortAs": "SGML", "GlossTerm": "Standard Generalized Markup Language", "Acronym": "SGML", "Abbrev": "ISO 8879:1986", "GlossDef": "A meta-markup language, used to create markup languages such as DocBook.", "GlossSeeAlso": [ "GML", "XML", "markup" ] } ] } } } diff --git a/release/src/router/libjson-c/tests/test4.c b/release/src/router/libjson-c/tests/test4.c new file mode 100644 index 0000000000..23e97dac1b --- /dev/null +++ b/release/src/router/libjson-c/tests/test4.c @@ -0,0 +1,53 @@ +/* + * gcc -o utf8 utf8.c -I/home/y/include -L./.libs -ljson + */ + +#include +#include +#include "config.h" + +#include "json_inttypes.h" +#include "json_object.h" +#include "json_tokener.h" + +void print_hex( const char* s) +{ + const char *iter = s; + unsigned char ch; + while ((ch = *iter++) != 0) + { + if( ',' != ch) + printf("%x ", ch); + else + printf( ","); + } + printf("\n"); +} + +int main() +{ + const char *input = "\"\\ud840\\udd26,\\ud840\\udd27,\\ud800\\udd26,\\ud800\\udd27\""; + const char *expected = "\xF0\xA0\x84\xA6,\xF0\xA0\x84\xA7,\xF0\x90\x84\xA6,\xF0\x90\x84\xA7"; + struct json_object *parse_result = json_tokener_parse((char*)input); + const char *unjson = json_object_get_string(parse_result); + + printf("input: %s\n", input); + + int strings_match = !strcmp( expected, unjson); + int retval = 0; + if (strings_match) + { + printf("JSON parse result is correct: %s\n", unjson); + printf("PASS\n"); + } else { + printf("JSON parse result doesn't match expected string\n"); + printf("expected string bytes: "); + print_hex( expected); + printf("parsed string bytes: "); + print_hex( unjson); + printf("FAIL\n"); + retval = 1; + } + json_object_put(parse_result); + return retval; +} diff --git a/release/src/router/libjson-c/tests/test4.expected b/release/src/router/libjson-c/tests/test4.expected new file mode 100644 index 0000000000..68d4336d90 --- /dev/null +++ b/release/src/router/libjson-c/tests/test4.expected @@ -0,0 +1,3 @@ +input: "\ud840\udd26,\ud840\udd27,\ud800\udd26,\ud800\udd27" +JSON parse result is correct: 𠄦,𠄧,𐄦,𐄧 +PASS diff --git a/release/src/router/libjson-c/tests/test4.test b/release/src/router/libjson-c/tests/test4.test new file mode 100755 index 0000000000..8bcc4609b4 --- /dev/null +++ b/release/src/router/libjson-c/tests/test4.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test4 +exit $? diff --git a/release/src/router/libjson-c/tests/testReplaceExisting.c b/release/src/router/libjson-c/tests/testReplaceExisting.c new file mode 100644 index 0000000000..6db7b98eca --- /dev/null +++ b/release/src/router/libjson-c/tests/testReplaceExisting.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include + +#include "json.h" + +int main(int argc, char **argv) +{ + MC_SET_DEBUG(1); + + /* + * Check that replacing an existing object keeps the key valid, + * and that it keeps the order the same. + */ + json_object *my_object = json_object_new_object(); + json_object_object_add(my_object, "foo1", json_object_new_string("bar1")); + json_object_object_add(my_object, "foo2", json_object_new_string("bar2")); + json_object_object_add(my_object, "deleteme", json_object_new_string("bar2")); + json_object_object_add(my_object, "foo3", json_object_new_string("bar3")); + + printf("==== delete-in-loop test starting ====\n"); + + int orig_count = 0; + json_object_object_foreach(my_object, key0, val0) + { + printf("Key at index %d is [%s]", orig_count, key0); + if (strcmp(key0, "deleteme") == 0) + { + json_object_object_del(my_object, key0); + printf(" (deleted)\n"); + } + else + printf(" (kept)\n"); + orig_count++; + } + + printf("==== replace-value first loop starting ====\n"); + + const char *original_key = NULL; + orig_count = 0; + json_object_object_foreach(my_object, key, val) + { + printf("Key at index %d is [%s]\n", orig_count, key); + orig_count++; + if (strcmp(key, "foo2") != 0) + continue; + printf("replacing value for key [%s]\n", key); + original_key = key; + json_object_object_add(my_object, key, json_object_new_string("zzz")); + } + + printf("==== second loop starting ====\n"); + + int new_count = 0; + int retval = 0; + json_object_object_foreach(my_object, key2, val2) + { + printf("Key at index %d is [%s]\n", new_count, key2); + new_count++; + if (strcmp(key2, "foo2") != 0) + continue; + printf("pointer for key [%s] does %smatch\n", key2, + (key2 == original_key) ? "" : "NOT "); + if (key2 != original_key) + retval = 1; + } + if (new_count != orig_count) + { + printf("mismatch between original count (%d) and new count (%d)\n", + orig_count, new_count); + retval = 1; + } + + json_object_put( my_object ); + + return retval; +} diff --git a/release/src/router/libjson-c/tests/testReplaceExisting.expected b/release/src/router/libjson-c/tests/testReplaceExisting.expected new file mode 100644 index 0000000000..b1d4461b04 --- /dev/null +++ b/release/src/router/libjson-c/tests/testReplaceExisting.expected @@ -0,0 +1,15 @@ +==== delete-in-loop test starting ==== +Key at index 0 is [foo1] (kept) +Key at index 1 is [foo2] (kept) +Key at index 2 is [deleteme] (deleted) +Key at index 3 is [foo3] (kept) +==== replace-value first loop starting ==== +Key at index 0 is [foo1] +Key at index 1 is [foo2] +replacing value for key [foo2] +Key at index 2 is [foo3] +==== second loop starting ==== +Key at index 0 is [foo1] +Key at index 1 is [foo2] +pointer for key [foo2] does match +Key at index 2 is [foo3] diff --git a/release/src/router/libjson-c/tests/testReplaceExisting.test b/release/src/router/libjson-c/tests/testReplaceExisting.test new file mode 100755 index 0000000000..ec5cbf1916 --- /dev/null +++ b/release/src/router/libjson-c/tests/testReplaceExisting.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test testReplaceExisting +exit $? diff --git a/release/src/router/libjson-c/tests/test_cast.c b/release/src/router/libjson-c/tests/test_cast.c new file mode 100644 index 0000000000..72c8cc4a21 --- /dev/null +++ b/release/src/router/libjson-c/tests/test_cast.c @@ -0,0 +1,106 @@ +/* + * Tests if casting within the json_object_get_* functions work correctly. + * Also checks the json_object_get_type and json_object_is_type functions. + */ + +#include +#include +#include +#include "config.h" + +#include "json_inttypes.h" +#include "json_object.h" +#include "json_tokener.h" +#include "json_util.h" + +static void getit(struct json_object *new_obj, const char *field); +static void checktype_header(void); +static void checktype(struct json_object *new_obj, const char *field); + +int main(int argc, char **argv) +{ + const char *input = "{\n\ + \"string_of_digits\": \"123\",\n\ + \"regular_number\": 222,\n\ + \"decimal_number\": 99.55,\n\ + \"boolean_true\": true,\n\ + \"boolean_false\": false,\n\ + \"big_number\": 2147483649,\n\ + \"a_null\": null,\n\ + }"; + /* Note: 2147483649 = INT_MAX + 2 */ + + struct json_object *new_obj; + + new_obj = json_tokener_parse(input); + printf("Parsed input: %s\n", input); + printf("Result is %s\n", (new_obj == NULL) ? "NULL (error!)" : "not NULL"); + if (!new_obj) + return 1; // oops, we failed. + + getit(new_obj, "string_of_digits"); + getit(new_obj, "regular_number"); + getit(new_obj, "decimal_number"); + getit(new_obj, "boolean_true"); + getit(new_obj, "boolean_false"); + getit(new_obj, "big_number"); + getit(new_obj, "a_null"); + + // Now check the behaviour of the json_object_is_type() function. + printf("\n================================\n"); + checktype_header(); + checktype(new_obj, NULL); + checktype(new_obj, "string_of_digits"); + checktype(new_obj, "regular_number"); + checktype(new_obj, "decimal_number"); + checktype(new_obj, "boolean_true"); + checktype(new_obj, "boolean_false"); + checktype(new_obj, "big_number"); + checktype(new_obj, "a_null"); + + json_object_put(new_obj); + + return 0; +} + +static void getit(struct json_object *new_obj, const char *field) +{ + struct json_object *o = json_object_object_get(new_obj, field); + + enum json_type o_type = json_object_get_type(o); + printf("new_obj.%s json_object_get_type()=%s\n", field, + json_type_to_name(o_type)); + printf("new_obj.%s json_object_get_int()=%d\n", field, + json_object_get_int(o)); + printf("new_obj.%s json_object_get_int64()=%" PRId64 "\n", field, + json_object_get_int64(o)); + printf("new_obj.%s json_object_get_boolean()=%d\n", field, + json_object_get_boolean(o)); + printf("new_obj.%s json_object_get_double()=%f\n", field, + json_object_get_double(o)); +} + +static void checktype_header() +{ + printf("json_object_is_type: %s,%s,%s,%s,%s,%s,%s\n", + json_type_to_name(json_type_null), + json_type_to_name(json_type_boolean), + json_type_to_name(json_type_double), + json_type_to_name(json_type_int), + json_type_to_name(json_type_object), + json_type_to_name(json_type_array), + json_type_to_name(json_type_string)); +} +static void checktype(struct json_object *new_obj, const char *field) +{ + struct json_object *o = field ? json_object_object_get(new_obj, field) : new_obj; + printf("new_obj%s%-18s: %d,%d,%d,%d,%d,%d,%d\n", + field ? "." : " ", field ? field : "", + json_object_is_type(o, json_type_null), + json_object_is_type(o, json_type_boolean), + json_object_is_type(o, json_type_double), + json_object_is_type(o, json_type_int), + json_object_is_type(o, json_type_object), + json_object_is_type(o, json_type_array), + json_object_is_type(o, json_type_string)); +} diff --git a/release/src/router/libjson-c/tests/test_cast.expected b/release/src/router/libjson-c/tests/test_cast.expected new file mode 100644 index 0000000000..76ff8231a5 --- /dev/null +++ b/release/src/router/libjson-c/tests/test_cast.expected @@ -0,0 +1,56 @@ +Parsed input: { + "string_of_digits": "123", + "regular_number": 222, + "decimal_number": 99.55, + "boolean_true": true, + "boolean_false": false, + "big_number": 2147483649, + "a_null": null, + } +Result is not NULL +new_obj.string_of_digits json_object_get_type()=string +new_obj.string_of_digits json_object_get_int()=123 +new_obj.string_of_digits json_object_get_int64()=123 +new_obj.string_of_digits json_object_get_boolean()=1 +new_obj.string_of_digits json_object_get_double()=123.000000 +new_obj.regular_number json_object_get_type()=int +new_obj.regular_number json_object_get_int()=222 +new_obj.regular_number json_object_get_int64()=222 +new_obj.regular_number json_object_get_boolean()=1 +new_obj.regular_number json_object_get_double()=222.000000 +new_obj.decimal_number json_object_get_type()=double +new_obj.decimal_number json_object_get_int()=99 +new_obj.decimal_number json_object_get_int64()=99 +new_obj.decimal_number json_object_get_boolean()=1 +new_obj.decimal_number json_object_get_double()=99.550000 +new_obj.boolean_true json_object_get_type()=boolean +new_obj.boolean_true json_object_get_int()=1 +new_obj.boolean_true json_object_get_int64()=1 +new_obj.boolean_true json_object_get_boolean()=1 +new_obj.boolean_true json_object_get_double()=1.000000 +new_obj.boolean_false json_object_get_type()=boolean +new_obj.boolean_false json_object_get_int()=0 +new_obj.boolean_false json_object_get_int64()=0 +new_obj.boolean_false json_object_get_boolean()=0 +new_obj.boolean_false json_object_get_double()=0.000000 +new_obj.big_number json_object_get_type()=int +new_obj.big_number json_object_get_int()=2147483647 +new_obj.big_number json_object_get_int64()=2147483649 +new_obj.big_number json_object_get_boolean()=1 +new_obj.big_number json_object_get_double()=2147483649.000000 +new_obj.a_null json_object_get_type()=null +new_obj.a_null json_object_get_int()=0 +new_obj.a_null json_object_get_int64()=0 +new_obj.a_null json_object_get_boolean()=0 +new_obj.a_null json_object_get_double()=0.000000 + +================================ +json_object_is_type: null,boolean,double,int,object,array,string +new_obj : 0,0,0,0,1,0,0 +new_obj.string_of_digits : 0,0,0,0,0,0,1 +new_obj.regular_number : 0,0,0,1,0,0,0 +new_obj.decimal_number : 0,0,1,0,0,0,0 +new_obj.boolean_true : 0,1,0,0,0,0,0 +new_obj.boolean_false : 0,1,0,0,0,0,0 +new_obj.big_number : 0,0,0,1,0,0,0 +new_obj.a_null : 1,0,0,0,0,0,0 diff --git a/release/src/router/libjson-c/tests/test_cast.test b/release/src/router/libjson-c/tests/test_cast.test new file mode 100755 index 0000000000..210246772f --- /dev/null +++ b/release/src/router/libjson-c/tests/test_cast.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test_cast +exit $? diff --git a/release/src/router/libjson-c/tests/test_charcase.c b/release/src/router/libjson-c/tests/test_charcase.c new file mode 100644 index 0000000000..936afeee83 --- /dev/null +++ b/release/src/router/libjson-c/tests/test_charcase.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include + +#include "json.h" +#include "json_tokener.h" + +static void test_case_parse(void); + +int main(int argc, char **argv) +{ + MC_SET_DEBUG(1); + + test_case_parse(); +} + +/* make sure only lowercase forms are parsed in strict mode */ +static void test_case_parse() +{ + struct json_tokener *tok; + json_object *new_obj; + + tok = json_tokener_new(); + json_tokener_set_flags(tok, JSON_TOKENER_STRICT); + + new_obj = json_tokener_parse_ex(tok, "True", 4); + assert (new_obj == NULL); + + new_obj = json_tokener_parse_ex(tok, "False", 5); + assert (new_obj == NULL); + + new_obj = json_tokener_parse_ex(tok, "Null", 4); + assert (new_obj == NULL); + + printf("OK\n"); + + json_tokener_free(tok); +} diff --git a/release/src/router/libjson-c/tests/test_charcase.expected b/release/src/router/libjson-c/tests/test_charcase.expected new file mode 100644 index 0000000000..d86bac9de5 --- /dev/null +++ b/release/src/router/libjson-c/tests/test_charcase.expected @@ -0,0 +1 @@ +OK diff --git a/release/src/router/libjson-c/tests/test_charcase.test b/release/src/router/libjson-c/tests/test_charcase.test new file mode 100755 index 0000000000..c967475ce4 --- /dev/null +++ b/release/src/router/libjson-c/tests/test_charcase.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test_charcase +exit $? diff --git a/release/src/router/libjson-c/tests/test_locale.c b/release/src/router/libjson-c/tests/test_locale.c new file mode 100644 index 0000000000..da070cf50c --- /dev/null +++ b/release/src/router/libjson-c/tests/test_locale.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include + +#include "config.h" +#include "json.h" +#include "json_tokener.h" + +#ifdef HAVE_LOCALE_H +#include +#endif /* HAVE_LOCALE_H */ + +int main(int argc, char **argv) +{ + json_object *new_obj; +#ifdef HAVE_SETLOCALE + setlocale(LC_NUMERIC, "de_DE"); +#else + printf("No locale\n"); +#endif + + MC_SET_DEBUG(1); + + new_obj = json_tokener_parse("[1.2,3.4,123456.78,5.0,2.3e10]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + printf("new_obj.to_string()=%s\n", json_object_to_json_string_ext(new_obj,JSON_C_TO_STRING_NOZERO)); + json_object_put(new_obj); +} + diff --git a/release/src/router/libjson-c/tests/test_locale.expected b/release/src/router/libjson-c/tests/test_locale.expected new file mode 100644 index 0000000000..0068be4aae --- /dev/null +++ b/release/src/router/libjson-c/tests/test_locale.expected @@ -0,0 +1,2 @@ +new_obj.to_string()=[ 1.2, 3.4, 123456.78, 5.0, 2.3e10 ] +new_obj.to_string()=[1.2,3.4,123456.78,5.0,2.3e10] diff --git a/release/src/router/libjson-c/tests/test_locale.test b/release/src/router/libjson-c/tests/test_locale.test new file mode 100755 index 0000000000..e4b6c6dcc6 --- /dev/null +++ b/release/src/router/libjson-c/tests/test_locale.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test_locale +exit $? diff --git a/release/src/router/libjson-c/tests/test_null.c b/release/src/router/libjson-c/tests/test_null.c new file mode 100644 index 0000000000..1f07910ee1 --- /dev/null +++ b/release/src/router/libjson-c/tests/test_null.c @@ -0,0 +1,57 @@ +/* +* Tests if binary strings are supported. +*/ + +#include +#include +#include "config.h" + +#include "json_inttypes.h" +#include "json_object.h" +#include "json_tokener.h" + +int main() +{ + // this test has a space after the null character. check that it's still included + const char *input = " \0 "; + const char *expected = "\" \\u0000 \""; + struct json_object *string = json_object_new_string_len(input, 3); + const char *json = json_object_to_json_string(string); + + int strings_match = !strcmp( expected, json); + int retval = 0; + if (strings_match) + { + printf("JSON write result is correct: %s\n", json); + printf("PASS\n"); + } else { + printf("JSON write result doesn't match expected string\n"); + printf("expected string: "); + printf("%s\n", expected); + printf("parsed string: "); + printf("%s\n", json); + printf("FAIL\n"); + retval=1; + } + json_object_put(string); + + struct json_object *parsed_str = json_tokener_parse(expected); + if (parsed_str) + { + int parsed_len = json_object_get_string_len(parsed_str); + const char *parsed_cstr = json_object_get_string(parsed_str); + int ii; + printf("Re-parsed object string len=%d, chars=[", parsed_len); + for (ii = 0; ii < parsed_len ; ii++) + { + printf("%s%d", (ii ? ", " : ""), (int)parsed_cstr[ii]); + } + printf("]\n"); + json_object_put(parsed_str); + } + else + { + printf("ERROR: failed to parse\n"); + } + return retval; +} diff --git a/release/src/router/libjson-c/tests/test_null.expected b/release/src/router/libjson-c/tests/test_null.expected new file mode 100644 index 0000000000..52d2890091 --- /dev/null +++ b/release/src/router/libjson-c/tests/test_null.expected @@ -0,0 +1,3 @@ +JSON write result is correct: " \u0000 " +PASS +Re-parsed object string len=3, chars=[32, 0, 32] diff --git a/release/src/router/libjson-c/tests/test_null.test b/release/src/router/libjson-c/tests/test_null.test new file mode 100755 index 0000000000..469ec64a7e --- /dev/null +++ b/release/src/router/libjson-c/tests/test_null.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test_null +exit $? diff --git a/release/src/router/libjson-c/tests/test_parse.c b/release/src/router/libjson-c/tests/test_parse.c new file mode 100644 index 0000000000..8808d0fa61 --- /dev/null +++ b/release/src/router/libjson-c/tests/test_parse.c @@ -0,0 +1,322 @@ +#include +#include +#include +#include +#include + +#include "json.h" +#include "json_tokener.h" + +static void test_basic_parse(void); +static void test_verbose_parse(void); +static void test_incremental_parse(void); + +int main(int argc, char **argv) +{ + MC_SET_DEBUG(1); + + test_basic_parse(); + printf("==================================\n"); + test_verbose_parse(); + printf("==================================\n"); + test_incremental_parse(); + printf("==================================\n"); +} + +static void test_basic_parse() +{ + json_object *new_obj; + + new_obj = json_tokener_parse("\"\003\""); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("/* hello */\"foo\""); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("// hello\n\"foo\""); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("\"\\u0041\\u0042\\u0043\""); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("null"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("NaN"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("-NaN"); /* non-sensical, returns null */ + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("Inf"); /* must use full string, returns null */ + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("inf"); /* must use full string, returns null */ + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("Infinity"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("infinity"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("-Infinity"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("-infinity"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("True"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("12"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("12.3"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("[\"\\n\"]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("[\"\\nabc\\n\"]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("[null]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("[]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("[false]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("[\"abc\",null,\"def\",12]"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{}"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{ \"foo\": \"bar\" }"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{ \"foo\": \"bar\", \"baz\": null, \"bool0\": true }"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{ \"foo\": [null, \"foo\"] }"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{ \"abc\": 12, \"foo\": \"bar\", \"bool0\": false, \"bool1\": true, \"arr\": [ 1, 2, 3, null, 5 ] }"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); +} + +static void test_verbose_parse() +{ + json_object *new_obj; + enum json_tokener_error error = json_tokener_success; + + new_obj = json_tokener_parse_verbose("{ foo }", &error); + assert (error == json_tokener_error_parse_object_key_name); + assert (new_obj == NULL); + + new_obj = json_tokener_parse("{ foo }"); + assert (new_obj == NULL); + + new_obj = json_tokener_parse("foo"); + assert (new_obj == NULL); + new_obj = json_tokener_parse_verbose("foo", &error); + assert (new_obj == NULL); + + /* b/c the string starts with 'f' parsing return a boolean error */ + assert (error == json_tokener_error_parse_boolean); + + printf("json_tokener_parse_versbose() OK\n"); +} + +struct incremental_step { + const char *string_to_parse; + int length; + int char_offset; + enum json_tokener_error expected_error; + int reset_tokener; +} incremental_steps[] = { + + /* Check that full json messages can be parsed, both w/ and w/o a reset */ + { "{ \"foo\": 123 }", -1, -1, json_tokener_success, 0 }, + { "{ \"foo\": 456 }", -1, -1, json_tokener_success, 1 }, + { "{ \"foo\": 789 }", -1, -1, json_tokener_success, 1 }, + + /* Check a basic incremental parse */ + { "{ \"foo", -1, -1, json_tokener_continue, 0 }, + { "\": {\"bar", -1, -1, json_tokener_continue, 0 }, + { "\":13}}", -1, -1, json_tokener_success, 1 }, + + /* Check that json_tokener_reset actually resets */ + { "{ \"foo", -1, -1, json_tokener_continue, 1 }, + { ": \"bar\"}", -1, 0, json_tokener_error_parse_unexpected, 1 }, + + /* Check incremental parsing with trailing characters */ + { "{ \"foo", -1, -1, json_tokener_continue, 0 }, + { "\": {\"bar", -1, -1, json_tokener_continue, 0 }, + { "\":13}}XXXX", 10, 6, json_tokener_success, 0 }, + { "XXXX", 4, 0, json_tokener_error_parse_unexpected, 1 }, + + /* Check that trailing characters can change w/o a reset */ + { "{\"x\": 123 }\"X\"", -1, 11, json_tokener_success, 0 }, + { "\"Y\"", -1, -1, json_tokener_success, 1 }, + + /* To stop parsing a number we need to reach a non-digit, e.g. a \0 */ + { "1", 1, 1, json_tokener_continue, 0 }, + { "2", 2, 1, json_tokener_success, 0 }, + + /* Strings have a well defined end point, so we can stop at the quote */ + { "\"blue\"", -1, -1, json_tokener_success, 0 }, + + /* Check each of the escape sequences defined by the spec */ + { "\"\\\"\"", -1, -1, json_tokener_success, 0 }, + { "\"\\\\\"", -1, -1, json_tokener_success, 0 }, + { "\"\\b\"", -1, -1, json_tokener_success, 0 }, + { "\"\\f\"", -1, -1, json_tokener_success, 0 }, + { "\"\\n\"", -1, -1, json_tokener_success, 0 }, + { "\"\\r\"", -1, -1, json_tokener_success, 0 }, + { "\"\\t\"", -1, -1, json_tokener_success, 0 }, + + { "[1,2,3]", -1, -1, json_tokener_success, 0 }, + + /* This behaviour doesn't entirely follow the json spec, but until we have + a way to specify how strict to be we follow Postel's Law and be liberal + in what we accept (up to a point). */ + { "[1,2,3,]", -1, -1, json_tokener_success, 0 }, + { "[1,2,,3,]", -1, 5, json_tokener_error_parse_unexpected, 0 }, + + { "[1,2,3,]", -1, 7, json_tokener_error_parse_unexpected, 3 }, + { "{\"a\":1,}", -1, 7, json_tokener_error_parse_unexpected, 3 }, + + { NULL, -1, -1, json_tokener_success, 0 }, +}; + +static void test_incremental_parse() +{ + json_object *new_obj; + enum json_tokener_error jerr; + json_tokener *tok; + const char *string_to_parse; + int ii; + int num_ok, num_error; + + num_ok = 0; + num_error = 0; + + printf("Starting incremental tests.\n"); + printf("Note: quotes and backslashes seen in the output here are literal values passed\n"); + printf(" to the parse functions. e.g. this is 4 characters: \"\\f\"\n"); + + string_to_parse = "{ \"foo"; /* } */ + printf("json_tokener_parse(%s) ... ", string_to_parse); + new_obj = json_tokener_parse(string_to_parse); + if (new_obj == NULL) printf("got error as expected\n"); + + /* test incremental parsing in various forms */ + tok = json_tokener_new(); + for (ii = 0; incremental_steps[ii].string_to_parse != NULL; ii++) + { + int this_step_ok = 0; + struct incremental_step *step = &incremental_steps[ii]; + int length = step->length; + int expected_char_offset = step->char_offset; + + if (step->reset_tokener & 2) + json_tokener_set_flags(tok, JSON_TOKENER_STRICT); + else + json_tokener_set_flags(tok, 0); + + if (length == -1) + length = strlen(step->string_to_parse); + if (expected_char_offset == -1) + expected_char_offset = length; + + printf("json_tokener_parse_ex(tok, %-12s, %3d) ... ", + step->string_to_parse, length); + new_obj = json_tokener_parse_ex(tok, step->string_to_parse, length); + + jerr = json_tokener_get_error(tok); + if (step->expected_error != json_tokener_success) + { + if (new_obj != NULL) + printf("ERROR: invalid object returned: %s\n", + json_object_to_json_string(new_obj)); + else if (jerr != step->expected_error) + printf("ERROR: got wrong error: %s\n", + json_tokener_error_desc(jerr)); + else if (tok->char_offset != expected_char_offset) + printf("ERROR: wrong char_offset %d != expected %d\n", + tok->char_offset, + expected_char_offset); + else + { + printf("OK: got correct error: %s\n", json_tokener_error_desc(jerr)); + this_step_ok = 1; + } + } + else + { + if (new_obj == NULL) + printf("ERROR: expected valid object, instead: %s\n", + json_tokener_error_desc(jerr)); + else if (tok->char_offset != expected_char_offset) + printf("ERROR: wrong char_offset %d != expected %d\n", + tok->char_offset, + expected_char_offset); + else + { + printf("OK: got object of type [%s]: %s\n", + json_type_to_name(json_object_get_type(new_obj)), + json_object_to_json_string(new_obj)); + this_step_ok = 1; + } + } + + if (new_obj) + json_object_put(new_obj); + + if (step->reset_tokener & 1) + json_tokener_reset(tok); + + if (this_step_ok) + num_ok++; + else + num_error++; + } + + json_tokener_free(tok); + + printf("End Incremental Tests OK=%d ERROR=%d\n", num_ok, num_error); + + return; +} diff --git a/release/src/router/libjson-c/tests/test_parse.expected b/release/src/router/libjson-c/tests/test_parse.expected new file mode 100644 index 0000000000..d49cbbb18e --- /dev/null +++ b/release/src/router/libjson-c/tests/test_parse.expected @@ -0,0 +1,65 @@ +new_obj.to_string()="\u0003" +new_obj.to_string()="foo" +new_obj.to_string()="foo" +new_obj.to_string()="ABC" +new_obj.to_string()=null +new_obj.to_string()=NaN +new_obj.to_string()=null +new_obj.to_string()=null +new_obj.to_string()=null +new_obj.to_string()=Infinity +new_obj.to_string()=Infinity +new_obj.to_string()=-Infinity +new_obj.to_string()=-Infinity +new_obj.to_string()=true +new_obj.to_string()=12 +new_obj.to_string()=12.3 +new_obj.to_string()=[ "\n" ] +new_obj.to_string()=[ "\nabc\n" ] +new_obj.to_string()=[ null ] +new_obj.to_string()=[ ] +new_obj.to_string()=[ false ] +new_obj.to_string()=[ "abc", null, "def", 12 ] +new_obj.to_string()={ } +new_obj.to_string()={ "foo": "bar" } +new_obj.to_string()={ "foo": "bar", "baz": null, "bool0": true } +new_obj.to_string()={ "foo": [ null, "foo" ] } +new_obj.to_string()={ "abc": 12, "foo": "bar", "bool0": false, "bool1": true, "arr": [ 1, 2, 3, null, 5 ] } +================================== +json_tokener_parse_versbose() OK +================================== +Starting incremental tests. +Note: quotes and backslashes seen in the output here are literal values passed + to the parse functions. e.g. this is 4 characters: "\f" +json_tokener_parse({ "foo) ... got error as expected +json_tokener_parse_ex(tok, { "foo": 123 }, 14) ... OK: got object of type [object]: { "foo": 123 } +json_tokener_parse_ex(tok, { "foo": 456 }, 14) ... OK: got object of type [object]: { "foo": 456 } +json_tokener_parse_ex(tok, { "foo": 789 }, 14) ... OK: got object of type [object]: { "foo": 789 } +json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue +json_tokener_parse_ex(tok, ": {"bar , 8) ... OK: got correct error: continue +json_tokener_parse_ex(tok, ":13}} , 6) ... OK: got object of type [object]: { "foo": { "bar": 13 } } +json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue +json_tokener_parse_ex(tok, : "bar"} , 8) ... OK: got correct error: unexpected character +json_tokener_parse_ex(tok, { "foo , 6) ... OK: got correct error: continue +json_tokener_parse_ex(tok, ": {"bar , 8) ... OK: got correct error: continue +json_tokener_parse_ex(tok, ":13}}XXXX , 10) ... OK: got object of type [object]: { "foo": { "bar": 13 } } +json_tokener_parse_ex(tok, XXXX , 4) ... OK: got correct error: unexpected character +json_tokener_parse_ex(tok, {"x": 123 }"X", 14) ... OK: got object of type [object]: { "x": 123 } +json_tokener_parse_ex(tok, "Y" , 3) ... OK: got object of type [string]: "Y" +json_tokener_parse_ex(tok, 1 , 1) ... OK: got correct error: continue +json_tokener_parse_ex(tok, 2 , 2) ... OK: got object of type [int]: 12 +json_tokener_parse_ex(tok, "blue" , 6) ... OK: got object of type [string]: "blue" +json_tokener_parse_ex(tok, "\"" , 4) ... OK: got object of type [string]: "\"" +json_tokener_parse_ex(tok, "\\" , 4) ... OK: got object of type [string]: "\\" +json_tokener_parse_ex(tok, "\b" , 4) ... OK: got object of type [string]: "\b" +json_tokener_parse_ex(tok, "\f" , 4) ... OK: got object of type [string]: "\f" +json_tokener_parse_ex(tok, "\n" , 4) ... OK: got object of type [string]: "\n" +json_tokener_parse_ex(tok, "\r" , 4) ... OK: got object of type [string]: "\r" +json_tokener_parse_ex(tok, "\t" , 4) ... OK: got object of type [string]: "\t" +json_tokener_parse_ex(tok, [1,2,3] , 7) ... OK: got object of type [array]: [ 1, 2, 3 ] +json_tokener_parse_ex(tok, [1,2,3,] , 8) ... OK: got object of type [array]: [ 1, 2, 3 ] +json_tokener_parse_ex(tok, [1,2,,3,] , 9) ... OK: got correct error: unexpected character +json_tokener_parse_ex(tok, [1,2,3,] , 8) ... OK: got correct error: unexpected character +json_tokener_parse_ex(tok, {"a":1,} , 8) ... OK: got correct error: unexpected character +End Incremental Tests OK=29 ERROR=0 +================================== diff --git a/release/src/router/libjson-c/tests/test_parse.test b/release/src/router/libjson-c/tests/test_parse.test new file mode 100755 index 0000000000..70d1c82e4a --- /dev/null +++ b/release/src/router/libjson-c/tests/test_parse.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test_parse +exit $? diff --git a/release/src/router/libjson-c/tests/test_parse_int64.c b/release/src/router/libjson-c/tests/test_parse_int64.c new file mode 100644 index 0000000000..c251e01348 --- /dev/null +++ b/release/src/router/libjson-c/tests/test_parse_int64.c @@ -0,0 +1,115 @@ + +#include +#include + +#include "config.h" + +#include "json_inttypes.h" +#include "json_util.h" + +void checkit(const char *buf) +{ + int64_t cint64 = -666; + + int retval = json_parse_int64(buf, &cint64); + printf("buf=%s parseit=%d, value=%" PRId64 " \n", buf, retval, cint64); +} + +/** + * This test calls json_parse_int64 with a variety of different strings. + * It's purpose is to ensure that the results are consistent across all + * different environments that it might be executed in. + * + * This always exits with a 0 exit value. The output should be compared + * against previously saved expected output. + */ +int main() +{ + char buf[100]; + + checkit("x"); + + checkit("0"); + checkit("-0"); + + checkit("00000000"); + checkit("-00000000"); + + checkit("1"); + + strcpy(buf, "2147483647"); // aka INT32_MAX + checkit(buf); + + strcpy(buf, "-1"); + checkit(buf); + + strcpy(buf, " -1"); + checkit(buf); + + strcpy(buf, "00001234"); + checkit(buf); + + strcpy(buf, "0001234x"); + checkit(buf); + + strcpy(buf, "-00001234"); + checkit(buf); + + strcpy(buf, "-00001234x"); + checkit(buf); + + strcpy(buf, "4294967295"); // aka UINT32_MAX + + sprintf(buf, "4294967296"); // aka UINT32_MAX + 1 + + strcpy(buf, "21474836470"); // INT32_MAX * 10 + checkit(buf); + + strcpy(buf, "31474836470"); // INT32_MAX * 10 + a bunch + checkit(buf); + + strcpy(buf, "-2147483647"); // INT32_MIN + 1 + checkit(buf); + + strcpy(buf, "-2147483648"); // INT32_MIN + checkit(buf); + + strcpy(buf, "-2147483649"); // INT32_MIN - 1 + checkit(buf); + + strcpy(buf, "-21474836480"); // INT32_MIN * 10 + checkit(buf); + + strcpy(buf, "9223372036854775806"); // INT64_MAX - 1 + checkit(buf); + + strcpy(buf, "9223372036854775807"); // INT64_MAX + checkit(buf); + + strcpy(buf, "9223372036854775808"); // INT64_MAX + 1 + checkit(buf); + + strcpy(buf, "-9223372036854775808"); // INT64_MIN + checkit(buf); + + strcpy(buf, "-9223372036854775809"); // INT64_MIN - 1 + checkit(buf); + + strcpy(buf, "18446744073709551614"); // UINT64_MAX - 1 + checkit(buf); + + strcpy(buf, "18446744073709551615"); // UINT64_MAX + checkit(buf); + + strcpy(buf, "18446744073709551616"); // UINT64_MAX + 1 + checkit(buf); + + strcpy(buf, "-18446744073709551616"); // -UINT64_MAX + checkit(buf); + + // Ensure we can still parse valid numbers after parsing out of range ones. + strcpy(buf, "123"); + checkit(buf); + + return 0; +} diff --git a/release/src/router/libjson-c/tests/test_parse_int64.expected b/release/src/router/libjson-c/tests/test_parse_int64.expected new file mode 100644 index 0000000000..d9cdf5acee --- /dev/null +++ b/release/src/router/libjson-c/tests/test_parse_int64.expected @@ -0,0 +1,29 @@ +buf=x parseit=1, value=-666 +buf=0 parseit=0, value=0 +buf=-0 parseit=0, value=0 +buf=00000000 parseit=0, value=0 +buf=-00000000 parseit=0, value=0 +buf=1 parseit=0, value=1 +buf=2147483647 parseit=0, value=2147483647 +buf=-1 parseit=0, value=-1 +buf= -1 parseit=0, value=-1 +buf=00001234 parseit=0, value=1234 +buf=0001234x parseit=0, value=1234 +buf=-00001234 parseit=0, value=-1234 +buf=-00001234x parseit=0, value=-1234 +buf=21474836470 parseit=0, value=21474836470 +buf=31474836470 parseit=0, value=31474836470 +buf=-2147483647 parseit=0, value=-2147483647 +buf=-2147483648 parseit=0, value=-2147483648 +buf=-2147483649 parseit=0, value=-2147483649 +buf=-21474836480 parseit=0, value=-21474836480 +buf=9223372036854775806 parseit=0, value=9223372036854775806 +buf=9223372036854775807 parseit=0, value=9223372036854775807 +buf=9223372036854775808 parseit=0, value=9223372036854775807 +buf=-9223372036854775808 parseit=0, value=-9223372036854775808 +buf=-9223372036854775809 parseit=0, value=-9223372036854775808 +buf=18446744073709551614 parseit=0, value=9223372036854775807 +buf=18446744073709551615 parseit=0, value=9223372036854775807 +buf=18446744073709551616 parseit=0, value=9223372036854775807 +buf=-18446744073709551616 parseit=0, value=-9223372036854775808 +buf=123 parseit=0, value=123 diff --git a/release/src/router/libjson-c/tests/test_parse_int64.test b/release/src/router/libjson-c/tests/test_parse_int64.test new file mode 100755 index 0000000000..2b7fbfb6f5 --- /dev/null +++ b/release/src/router/libjson-c/tests/test_parse_int64.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test_parse_int64 +exit $? diff --git a/release/src/router/libjson-c/tests/test_printbuf.c b/release/src/router/libjson-c/tests/test_printbuf.c new file mode 100644 index 0000000000..c8b8ad036b --- /dev/null +++ b/release/src/router/libjson-c/tests/test_printbuf.c @@ -0,0 +1,166 @@ +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "printbuf.h" + +static void test_basic_printbuf_memset(void); +static void test_printbuf_memset_length(void); + +static void test_basic_printbuf_memset() +{ + struct printbuf *pb; + + printf("%s: starting test\n", __func__); + pb = printbuf_new(); + sprintbuf(pb, "blue:%d", 1); + printbuf_memset(pb, -1, 'x', 52); + printf("Buffer contents:%.*s\n", printbuf_length(pb), pb->buf); + printbuf_free(pb); + printf("%s: end test\n", __func__); +} + +static void test_printbuf_memset_length() +{ + struct printbuf *pb; + + printf("%s: starting test\n", __func__); + pb = printbuf_new(); + printbuf_memset(pb, -1, ' ', 0); + printbuf_memset(pb, -1, ' ', 0); + printbuf_memset(pb, -1, ' ', 0); + printbuf_memset(pb, -1, ' ', 0); + printbuf_memset(pb, -1, ' ', 0); + printf("Buffer length: %d\n", printbuf_length(pb)); + printbuf_memset(pb, -1, ' ', 2); + printbuf_memset(pb, -1, ' ', 4); + printbuf_memset(pb, -1, ' ', 6); + printf("Buffer length: %d\n", printbuf_length(pb)); + printbuf_memset(pb, -1, ' ', 6); + printf("Buffer length: %d\n", printbuf_length(pb)); + printbuf_memset(pb, -1, ' ', 8); + printbuf_memset(pb, -1, ' ', 10); + printbuf_memset(pb, -1, ' ', 10); + printbuf_memset(pb, -1, ' ', 10); + printbuf_memset(pb, -1, ' ', 20); + printf("Buffer length: %d\n", printbuf_length(pb)); + + // No length change should occur + printbuf_memset(pb, 0, 'x', 30); + printf("Buffer length: %d\n", printbuf_length(pb)); + + // This should extend it by one. + printbuf_memset(pb, 0, 'x', printbuf_length(pb) + 1); + printf("Buffer length: %d\n", printbuf_length(pb)); + + printbuf_free(pb); + printf("%s: end test\n", __func__); +} + +static void test_printbuf_memappend(int *before_resize); +static void test_printbuf_memappend(int *before_resize) +{ + struct printbuf *pb; + int initial_size; + + printf("%s: starting test\n", __func__); + pb = printbuf_new(); + printf("Buffer length: %d\n", printbuf_length(pb)); + + initial_size = pb->size; + + while(pb->size == initial_size) + { + printbuf_memappend_fast(pb, "x", 1); + } + *before_resize = printbuf_length(pb) - 1; + printf("Appended %d bytes for resize: [%s]\n", *before_resize + 1, pb->buf); + + printbuf_reset(pb); + printbuf_memappend_fast(pb, "bluexyz123", 3); + printf("Partial append: %d, [%s]\n", printbuf_length(pb), pb->buf); + + char with_nulls[] = { 'a', 'b', '\0', 'c' }; + printbuf_reset(pb); + printbuf_memappend_fast(pb, with_nulls, (int)sizeof(with_nulls)); + printf("With embedded \\0 character: %d, [%s]\n", printbuf_length(pb), pb->buf); + + printbuf_free(pb); + pb = printbuf_new(); + char *data = malloc(*before_resize); + memset(data, 'X', *before_resize); + printbuf_memappend_fast(pb, data, *before_resize); + printf("Append to just before resize: %d, [%s]\n", printbuf_length(pb), pb->buf); + + free(data); + printbuf_free(pb); + + pb = printbuf_new(); + data = malloc(*before_resize + 1); + memset(data, 'X', *before_resize + 1); + printbuf_memappend_fast(pb, data, *before_resize + 1); + printf("Append to just after resize: %d, [%s]\n", printbuf_length(pb), pb->buf); + + free(data); + + printbuf_free(pb); + printf("%s: end test\n", __func__); +} + +static void test_sprintbuf(int before_resize); +static void test_sprintbuf(int before_resize) +{ + struct printbuf *pb; + + printf("%s: starting test\n", __func__); + pb = printbuf_new(); + printf("Buffer length: %d\n", printbuf_length(pb)); + + char *data = malloc(before_resize + 1 + 1); + memset(data, 'X', before_resize + 1 + 1); + data[before_resize + 1] = '\0'; + sprintbuf(pb, "%s", data); + free(data); + printf("sprintbuf to just after resize(%d+1): %d, [%s], strlen(buf)=%d\n", before_resize, printbuf_length(pb), pb->buf, (int)strlen(pb->buf)); + + printbuf_reset(pb); + sprintbuf(pb, "plain"); + printf("%d, [%s]\n", printbuf_length(pb), pb->buf); + + sprintbuf(pb, "%d", 1); + printf("%d, [%s]\n", printbuf_length(pb), pb->buf); + + sprintbuf(pb, "%d", INT_MAX); + printf("%d, [%s]\n", printbuf_length(pb), pb->buf); + + sprintbuf(pb, "%d", INT_MIN); + printf("%d, [%s]\n", printbuf_length(pb), pb->buf); + + sprintbuf(pb, "%s", "%s"); + printf("%d, [%s]\n", printbuf_length(pb), pb->buf); + + printbuf_free(pb); + printf("%s: end test\n", __func__); +} + +int main(int argc, char **argv) +{ + int before_resize = 0; + + mc_set_debug(1); + + test_basic_printbuf_memset(); + printf("========================================\n"); + test_printbuf_memset_length(); + printf("========================================\n"); + test_printbuf_memappend(&before_resize); + printf("========================================\n"); + test_sprintbuf(before_resize); + printf("========================================\n"); + + return 0; +} diff --git a/release/src/router/libjson-c/tests/test_printbuf.expected b/release/src/router/libjson-c/tests/test_printbuf.expected new file mode 100644 index 0000000000..142db0babd --- /dev/null +++ b/release/src/router/libjson-c/tests/test_printbuf.expected @@ -0,0 +1,32 @@ +test_basic_printbuf_memset: starting test +Buffer contents:blue:1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +test_basic_printbuf_memset: end test +======================================== +test_printbuf_memset_length: starting test +Buffer length: 0 +Buffer length: 12 +Buffer length: 18 +Buffer length: 76 +Buffer length: 76 +Buffer length: 77 +test_printbuf_memset_length: end test +======================================== +test_printbuf_memappend: starting test +Buffer length: 0 +Appended 32 bytes for resize: [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx] +Partial append: 3, [blu] +With embedded \0 character: 4, [ab] +Append to just before resize: 31, [XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX] +Append to just after resize: 32, [XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX] +test_printbuf_memappend: end test +======================================== +test_sprintbuf: starting test +Buffer length: 0 +sprintbuf to just after resize(31+1): 32, [XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX], strlen(buf)=32 +5, [plain] +6, [plain1] +16, [plain12147483647] +27, [plain12147483647-2147483648] +29, [plain12147483647-2147483648%s] +test_sprintbuf: end test +======================================== diff --git a/release/src/router/libjson-c/tests/test_printbuf.test b/release/src/router/libjson-c/tests/test_printbuf.test new file mode 100755 index 0000000000..09d27c23af --- /dev/null +++ b/release/src/router/libjson-c/tests/test_printbuf.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test_printbuf +exit $? diff --git a/release/src/router/libjson-c/tests/test_set_serializer.c b/release/src/router/libjson-c/tests/test_set_serializer.c new file mode 100644 index 0000000000..0f122af237 --- /dev/null +++ b/release/src/router/libjson-c/tests/test_set_serializer.c @@ -0,0 +1,71 @@ +#include +#include +#include + +#include "json.h" +#include "printbuf.h" + +struct myinfo { + int value; +}; + +static int freeit_was_called = 0; +static void freeit(json_object *jso, void *userdata) +{ + struct myinfo *info = userdata; + printf("freeit, value=%d\n", info->value); + // Don't actually free anything here, the userdata is stack allocated. + freeit_was_called = 1; +} +static int custom_serializer(struct json_object *o, + struct printbuf *pb, + int level, + int flags) +{ + sprintbuf(pb, "Custom Output"); + return 0; +} + +int main(int argc, char **argv) +{ + json_object *my_object; + + MC_SET_DEBUG(1); + + printf("Test setting, then resetting a custom serializer:\n"); + my_object = json_object_new_object(); + json_object_object_add(my_object, "abc", json_object_new_int(12)); + json_object_object_add(my_object, "foo", json_object_new_string("bar")); + + printf("my_object.to_string(standard)=%s\n", json_object_to_json_string(my_object)); + + struct myinfo userdata = { .value = 123 }; + json_object_set_serializer(my_object, custom_serializer, &userdata, freeit); + + printf("my_object.to_string(custom serializer)=%s\n", json_object_to_json_string(my_object)); + + printf("Next line of output should be from the custom freeit function:\n"); + freeit_was_called = 0; + json_object_set_serializer(my_object, NULL, NULL, NULL); + assert(freeit_was_called); + + printf("my_object.to_string(standard)=%s\n", json_object_to_json_string(my_object)); + + json_object_put(my_object); + + // ============================================ + + my_object = json_object_new_object(); + printf("Check that the custom serializer isn't free'd until the last json_object_put:\n"); + json_object_set_serializer(my_object, custom_serializer, &userdata, freeit); + json_object_get(my_object); + json_object_put(my_object); + printf("my_object.to_string(custom serializer)=%s\n", json_object_to_json_string(my_object)); + printf("Next line of output should be from the custom freeit function:\n"); + + freeit_was_called = 0; + json_object_put(my_object); + assert(freeit_was_called); + + return 0; +} diff --git a/release/src/router/libjson-c/tests/test_set_serializer.expected b/release/src/router/libjson-c/tests/test_set_serializer.expected new file mode 100644 index 0000000000..ad44a9053b --- /dev/null +++ b/release/src/router/libjson-c/tests/test_set_serializer.expected @@ -0,0 +1,10 @@ +Test setting, then resetting a custom serializer: +my_object.to_string(standard)={ "abc": 12, "foo": "bar" } +my_object.to_string(custom serializer)=Custom Output +Next line of output should be from the custom freeit function: +freeit, value=123 +my_object.to_string(standard)={ "abc": 12, "foo": "bar" } +Check that the custom serializer isn't free'd until the last json_object_put: +my_object.to_string(custom serializer)=Custom Output +Next line of output should be from the custom freeit function: +freeit, value=123 diff --git a/release/src/router/libjson-c/tests/test_set_serializer.test b/release/src/router/libjson-c/tests/test_set_serializer.test new file mode 100755 index 0000000000..728dfedf16 --- /dev/null +++ b/release/src/router/libjson-c/tests/test_set_serializer.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test_set_serializer +exit $? diff --git a/release/src/router/uqmi/CMakeLists.txt b/release/src/router/uqmi/CMakeLists.txt new file mode 100644 index 0000000000..d7872980c1 --- /dev/null +++ b/release/src/router/uqmi/CMakeLists.txt @@ -0,0 +1,66 @@ +cmake_minimum_required(VERSION 2.6) + +PROJECT(uqmi C) + +OPTION(BUILD_STATIC ON) + +ADD_DEFINITIONS(-Os -ggdb -Wall -Werror --std=gnu99 -Wmissing-declarations -Wno-enum-conversion) + +SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") + +SET(SOURCES main.c dev.c commands.c qmi-message.c) + +IF(BUILD_STATIC) + FIND_LIBRARY(json NAMES libjson.a libjson-c.a) + FIND_LIBRARY(blobmsg_json NAMES libblobmsg_json.a) + FIND_LIBRARY(ubox NAMES libubox.a) +ELSE(BUILD_STATIC) + FIND_LIBRARY(json NAMES json-c json) + FIND_LIBRARY(blobmsg_json NAMES blobmsg_json) + FIND_LIBRARY(ubox NAMES ubox) +ENDIF(BUILD_STATIC) + +SET(LIBS ${ubox} ${blobmsg_json} ${json}) + +IF(DEBUG_PACKET) + ADD_DEFINITIONS(-DDEBUG_PACKET) +ENDIF() + +IF(DEBUG) + ADD_DEFINITIONS(-DDEBUG -g3) +ENDIF() + +SET(service_headers) +SET(service_sources) +FOREACH(service ctl dms nas pds wds wms wda) + ADD_CUSTOM_COMMAND( + OUTPUT qmi-message-${service}.h + COMMAND ./data/gen-header.pl ${service}_ ./data/qmi-service-${service}.json > qmi-message-${service}.h + DEPENDS ./data/gen-header.pl ./data/qmi-service-${service}.json ./data/gen-common.pm + ) + SET(service_headers ${service_headers} qmi-message-${service}.h) + ADD_CUSTOM_COMMAND( + OUTPUT qmi-message-${service}.c + COMMAND ./data/gen-code.pl ${service}_ ./data/qmi-service-${service}.json > qmi-message-${service}.c + DEPENDS ./data/gen-code.pl ./data/qmi-service-${service}.json ./data/gen-common.pm + ) + SET(service_sources ${service_sources} qmi-message-${service}.c) + set_property(SOURCE qmi-message-${service}.c PROPERTY COMPILE_FLAGS "-Wno-unused") +ENDFOREACH() + +ADD_CUSTOM_COMMAND( + OUTPUT qmi-errors.c + COMMAND ./data/gen-error-list.pl ./qmi-errors.h > qmi-errors.c + DEPENDS ./data/gen-error-list.pl ./qmi-errors.h +) +ADD_CUSTOM_TARGET(gen-errors DEPENDS qmi-errors.c) +ADD_CUSTOM_TARGET(gen-headers DEPENDS ${service_headers}) + +ADD_EXECUTABLE(uqmi ${SOURCES} ${service_sources}) +ADD_DEPENDENCIES(uqmi gen-headers gen-errors) + +TARGET_LINK_LIBRARIES(uqmi ${LIBS}) + +INSTALL(TARGETS uqmi + RUNTIME DESTINATION sbin +) diff --git a/release/src/router/uqmi/commands-dms.c b/release/src/router/uqmi/commands-dms.c new file mode 100644 index 0000000000..dad2b86072 --- /dev/null +++ b/release/src/router/uqmi/commands-dms.c @@ -0,0 +1,410 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2014-2015 Felix Fietkau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ +#include "qmi-message.h" + +static struct { + QmiDmsUimPinId pin_id; + char* pin; + char* new_pin; + char* puk; +} dms_req_data; + +static void cmd_dms_get_capabilities_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + void *t, *networks; + int i; + struct qmi_dms_get_capabilities_response res; + const char *radio_cap[] = { + [QMI_DMS_RADIO_INTERFACE_CDMA20001X] = "cdma1x", + [QMI_DMS_RADIO_INTERFACE_EVDO] = "cdma1xevdo", + [QMI_DMS_RADIO_INTERFACE_GSM] = "gsm", + [QMI_DMS_RADIO_INTERFACE_UMTS] = "umts", + [QMI_DMS_RADIO_INTERFACE_LTE] = "lte", + }; + const char *service_cap[] = { + [QMI_DMS_DATA_SERVICE_CAPABILITY_NONE] = "none", + [QMI_DMS_DATA_SERVICE_CAPABILITY_CS] = "cs", + [QMI_DMS_DATA_SERVICE_CAPABILITY_PS] = "ps", + [QMI_DMS_DATA_SERVICE_CAPABILITY_SIMULTANEOUS_CS_PS] = "simultaneous_cs_ps", + [QMI_DMS_DATA_SERVICE_CAPABILITY_NON_SIMULTANEOUS_CS_PS] = "non_simultaneous_cs_ps", + }; + + qmi_parse_dms_get_capabilities_response(msg, &res); + + t = blobmsg_open_table(&status, NULL); + + blobmsg_add_u32(&status, "max_tx_channel_rate", (int32_t) res.data.info.max_tx_channel_rate); + blobmsg_add_u32(&status, "max_rx_channel_rate", (int32_t) res.data.info.max_rx_channel_rate); + if ((int)res.data.info.data_service_capability >= 0 && res.data.info.data_service_capability < ARRAY_SIZE(service_cap)) + blobmsg_add_string(&status, "data_service", service_cap[res.data.info.data_service_capability]); + + if(res.data.info.sim_capability == QMI_DMS_SIM_CAPABILITY_NOT_SUPPORTED) + blobmsg_add_string(&status, "sim", "not supported"); + else if(res.data.info.sim_capability == QMI_DMS_SIM_CAPABILITY_SUPPORTED) + blobmsg_add_string(&status, "sim", "supported"); + + networks = blobmsg_open_array(&status, "networks"); + for (i = 0; i < res.data.info.radio_interface_list_n; i++) { + if ((int)res.data.info.radio_interface_list[i] >= 0 && res.data.info.radio_interface_list[i] < ARRAY_SIZE(radio_cap)) + blobmsg_add_string(&status, NULL, radio_cap[res.data.info.radio_interface_list[i]]); + else + blobmsg_add_string(&status, NULL, "unknown"); + } + blobmsg_close_array(&status, networks); + + blobmsg_close_table(&status, t); +} + +static enum qmi_cmd_result +cmd_dms_get_capabilities_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + qmi_set_dms_get_capabilities_request(msg); + return QMI_CMD_REQUEST; +} + +static const char *get_pin_status(int status) +{ + static const char *pin_status[] = { + [QMI_DMS_UIM_PIN_STATUS_NOT_INITIALIZED] = "not_initialized", + [QMI_DMS_UIM_PIN_STATUS_ENABLED_NOT_VERIFIED] = "not_verified", + [QMI_DMS_UIM_PIN_STATUS_ENABLED_VERIFIED] = "verified", + [QMI_DMS_UIM_PIN_STATUS_DISABLED] = "disabled", + [QMI_DMS_UIM_PIN_STATUS_BLOCKED] = "blocked", + [QMI_DMS_UIM_PIN_STATUS_PERMANENTLY_BLOCKED] = "permanently_blocked", + [QMI_DMS_UIM_PIN_STATUS_UNBLOCKED] = "unblocked", + [QMI_DMS_UIM_PIN_STATUS_CHANGED] = "changed", + }; + const char *res = "Unknown"; + + if (status < ARRAY_SIZE(pin_status) && pin_status[status]) + res = pin_status[status]; + + return res; +} + +static void cmd_dms_get_pin_status_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + struct qmi_dms_uim_get_pin_status_response res; + void *c; + + qmi_parse_dms_uim_get_pin_status_response(msg, &res); + c = blobmsg_open_table(&status, NULL); + if (res.set.pin1_status) { + blobmsg_add_string(&status, "pin1_status", get_pin_status(res.data.pin1_status.current_status)); + blobmsg_add_u32(&status, "pin1_verify_tries", (int32_t) res.data.pin1_status.verify_retries_left); + blobmsg_add_u32(&status, "pin1_unblock_tries", (int32_t) res.data.pin1_status.unblock_retries_left); + } + if (res.set.pin2_status) { + blobmsg_add_string(&status, "pin2_status", get_pin_status(res.data.pin2_status.current_status)); + blobmsg_add_u32(&status, "pin2_verify_tries", (int32_t) res.data.pin2_status.verify_retries_left); + blobmsg_add_u32(&status, "pin2_unblock_tries", (int32_t) res.data.pin2_status.unblock_retries_left); + } + blobmsg_close_table(&status, c); +} + +static enum qmi_cmd_result +cmd_dms_get_pin_status_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + qmi_set_dms_uim_get_pin_status_request(msg); + return QMI_CMD_REQUEST; +} + +#define cmd_dms_verify_pin1_cb no_cb +static enum qmi_cmd_result +cmd_dms_verify_pin1_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + struct qmi_dms_uim_verify_pin_request data = { + QMI_INIT_SEQUENCE(info, + .pin_id = QMI_DMS_UIM_PIN_ID_PIN, + .pin = arg + ) + }; + qmi_set_dms_uim_verify_pin_request(msg, &data); + return QMI_CMD_REQUEST; +} + +#define cmd_dms_verify_pin2_cb no_cb +static enum qmi_cmd_result +cmd_dms_verify_pin2_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + struct qmi_dms_uim_verify_pin_request data = { + QMI_INIT_SEQUENCE(info, + .pin_id = QMI_DMS_UIM_PIN_ID_PIN2, + .pin = arg + ) + }; + qmi_set_dms_uim_verify_pin_request(msg, &data); + return QMI_CMD_REQUEST; +} + +#define cmd_dms_set_pin_cb no_cb +static enum qmi_cmd_result +cmd_dms_set_pin_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + dms_req_data.pin = arg; + return QMI_CMD_DONE; +} + +static enum qmi_cmd_result +cmd_dms_set_pin_protection_prepare(struct qmi_msg *msg, char *arg) +{ + if (!dms_req_data.pin) { + uqmi_add_error("Missing argument"); + return QMI_CMD_EXIT; + } + + int is_enabled; + if (strcasecmp(arg, "disabled") == 0) + is_enabled = false; + else if (strcasecmp(arg, "enabled") == 0) + is_enabled = true; + else { + uqmi_add_error("Invalid value (valid: disabled, enabled)"); + return QMI_CMD_EXIT; + } + + struct qmi_dms_uim_set_pin_protection_request dms_pin_protection_req = { + QMI_INIT_SEQUENCE(info, + .pin_id = dms_req_data.pin_id + ), + QMI_INIT_PTR(info.pin, dms_req_data.pin), + QMI_INIT_PTR(info.protection_enabled, is_enabled) + }; + + qmi_set_dms_uim_set_pin_protection_request(msg, &dms_pin_protection_req); + return QMI_CMD_REQUEST; +} + +#define cmd_dms_set_pin1_protection_cb no_cb +static enum qmi_cmd_result +cmd_dms_set_pin1_protection_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + dms_req_data.pin_id = QMI_DMS_UIM_PIN_ID_PIN; + return cmd_dms_set_pin_protection_prepare(msg, arg); +} + +#define cmd_dms_set_pin2_protection_cb no_cb +static enum qmi_cmd_result +cmd_dms_set_pin2_protection_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + dms_req_data.pin_id = QMI_DMS_UIM_PIN_ID_PIN2; + return cmd_dms_set_pin_protection_prepare(msg, arg); +} + +static enum qmi_cmd_result +cmd_dms_change_pin_prepare(struct qmi_msg *msg, char *arg) +{ + if (!dms_req_data.pin || !dms_req_data.new_pin) { + uqmi_add_error("Missing argument"); + return QMI_CMD_EXIT; + } + + struct qmi_dms_uim_change_pin_request dms_change_pin_req = { + QMI_INIT_SEQUENCE(info, + .pin_id = dms_req_data.pin_id + ), + QMI_INIT_PTR(info.old_pin, dms_req_data.pin), + QMI_INIT_PTR(info.new_pin, dms_req_data.new_pin) + }; + + qmi_set_dms_uim_change_pin_request(msg, &dms_change_pin_req); + return QMI_CMD_REQUEST; +} + +#define cmd_dms_change_pin1_cb no_cb +static enum qmi_cmd_result +cmd_dms_change_pin1_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + dms_req_data.pin_id = QMI_DMS_UIM_PIN_ID_PIN; + return cmd_dms_change_pin_prepare(msg, arg); +} + +#define cmd_dms_change_pin2_cb no_cb +static enum qmi_cmd_result +cmd_dms_change_pin2_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + dms_req_data.pin_id = QMI_DMS_UIM_PIN_ID_PIN2; + return cmd_dms_change_pin_prepare(msg, arg); +} + +#define cmd_dms_set_new_pin_cb no_cb +static enum qmi_cmd_result +cmd_dms_set_new_pin_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + dms_req_data.new_pin = arg; + return QMI_CMD_DONE; +} + +#define cmd_dms_set_puk_cb no_cb +static enum qmi_cmd_result +cmd_dms_set_puk_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + dms_req_data.puk = arg; + return QMI_CMD_DONE; +} + +#define cmd_dms_unblock_pin1_cb no_cb +static enum qmi_cmd_result +cmd_dms_unblock_pin1_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + if (!dms_req_data.puk || !dms_req_data.new_pin) { + uqmi_add_error("Missing argument"); + return QMI_CMD_EXIT; + } + + struct qmi_dms_uim_unblock_pin_request dms_unlock_pin_req = { + QMI_INIT_SEQUENCE(info, + .pin_id = QMI_DMS_UIM_PIN_ID_PIN + ), + QMI_INIT_PTR(info.puk, dms_req_data.puk), + QMI_INIT_PTR(info.new_pin, dms_req_data.new_pin) + }; + + qmi_set_dms_uim_unblock_pin_request(msg, &dms_unlock_pin_req); + return QMI_CMD_REQUEST; +} + +#define cmd_dms_unblock_pin2_cb no_cb +static enum qmi_cmd_result +cmd_dms_unblock_pin2_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + if (!dms_req_data.puk || !dms_req_data.new_pin) { + uqmi_add_error("Missing argument"); + return QMI_CMD_EXIT; + } + + struct qmi_dms_uim_unblock_pin_request dms_unlock_pin_req = { + QMI_INIT_SEQUENCE(info, + .pin_id = QMI_DMS_UIM_PIN_ID_PIN2 + ), + QMI_INIT_PTR(info.puk, dms_req_data.puk), + QMI_INIT_PTR(info.new_pin, dms_req_data.new_pin) + }; + + qmi_set_dms_uim_unblock_pin_request(msg, &dms_unlock_pin_req); + return QMI_CMD_REQUEST; +} + +static void cmd_dms_get_iccid_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + struct qmi_dms_uim_get_iccid_response res; + + qmi_parse_dms_uim_get_iccid_response(msg, &res); + if (res.data.iccid) + blobmsg_add_string(&status, NULL, res.data.iccid); +} + +static enum qmi_cmd_result +cmd_dms_get_iccid_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + qmi_set_dms_uim_get_iccid_request(msg); + return QMI_CMD_REQUEST; +} + +static void cmd_dms_get_imsi_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + struct qmi_dms_uim_get_imsi_response res; + + qmi_parse_dms_uim_get_imsi_response(msg, &res); + if (res.data.imsi) + blobmsg_add_string(&status, NULL, res.data.imsi); +} + +static enum qmi_cmd_result +cmd_dms_get_imsi_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + qmi_set_dms_uim_get_imsi_request(msg); + return QMI_CMD_REQUEST; +} + +static void cmd_dms_get_msisdn_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + struct qmi_dms_get_msisdn_response res; + + qmi_parse_dms_get_msisdn_response(msg, &res); + if (res.data.msisdn) + blobmsg_add_string(&status, NULL, res.data.msisdn); +} + +static enum qmi_cmd_result +cmd_dms_get_msisdn_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + qmi_set_dms_get_msisdn_request(msg); + return QMI_CMD_REQUEST; +} + +static void cmd_dms_get_imei_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + struct qmi_dms_get_ids_response res; + + qmi_parse_dms_get_ids_response(msg, &res); + if (res.data.imei) + blobmsg_add_string(&status, NULL, res.data.imei); +} + +static enum qmi_cmd_result +cmd_dms_get_imei_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + qmi_set_dms_get_ids_request(msg); + return QMI_CMD_REQUEST; +} + +#define cmd_dms_reset_cb no_cb +static enum qmi_cmd_result +cmd_dms_reset_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + qmi_set_dms_reset_request(msg); + return QMI_CMD_REQUEST; +} + +#define cmd_dms_set_operating_mode_cb no_cb +static enum qmi_cmd_result +cmd_dms_set_operating_mode_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + static const char *modes[] = { + [QMI_DMS_OPERATING_MODE_ONLINE] = "online", + [QMI_DMS_OPERATING_MODE_LOW_POWER] = "low_power", + [QMI_DMS_OPERATING_MODE_FACTORY_TEST] = "factory_test", + [QMI_DMS_OPERATING_MODE_OFFLINE] = "offline", + [QMI_DMS_OPERATING_MODE_RESET] = "reset", + [QMI_DMS_OPERATING_MODE_SHUTTING_DOWN] = "shutting_down", + [QMI_DMS_OPERATING_MODE_PERSISTENT_LOW_POWER] = "persistent_low_power", + [QMI_DMS_OPERATING_MODE_MODE_ONLY_LOW_POWER] = "mode_only_low_power", + }; + static struct qmi_dms_set_operating_mode_request sreq = { + QMI_INIT(mode, QMI_DMS_OPERATING_MODE_ONLINE), + }; + int i; + + for (i = 0; i < ARRAY_SIZE(modes); i++) { + if (!modes[i]) + continue; + + if (strcmp(arg, modes[i]) != 0) + continue; + + sreq.data.mode = i; + qmi_set_dms_set_operating_mode_request(msg, &sreq); + return QMI_CMD_REQUEST; + } + + return uqmi_add_error("Invalid argument"); +} diff --git a/release/src/router/uqmi/commands-dms.h b/release/src/router/uqmi/commands-dms.h new file mode 100644 index 0000000000..ccafbb12de --- /dev/null +++ b/release/src/router/uqmi/commands-dms.h @@ -0,0 +1,73 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2014-2015 Felix Fietkau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#define __uqmi_dms_commands \ + __uqmi_command(dms_get_capabilities, get-capabilities, no, QMI_SERVICE_DMS), \ + __uqmi_command(dms_get_pin_status, get-pin-status, no, QMI_SERVICE_DMS), \ + __uqmi_command(dms_verify_pin1, verify-pin1, required, QMI_SERVICE_DMS), \ + __uqmi_command(dms_verify_pin2, verify-pin2, required, QMI_SERVICE_DMS), \ + __uqmi_command(dms_set_pin1_protection, set-pin1-protection, required, QMI_SERVICE_DMS), \ + __uqmi_command(dms_set_pin2_protection, set-pin2-protection, required, QMI_SERVICE_DMS), \ + __uqmi_command(dms_set_pin, pin, required, CMD_TYPE_OPTION), \ + __uqmi_command(dms_change_pin1, change-pin1, no, QMI_SERVICE_DMS), \ + __uqmi_command(dms_change_pin2, change-pin2, no, QMI_SERVICE_DMS), \ + __uqmi_command(dms_unblock_pin1, unblock-pin1, no, QMI_SERVICE_DMS), \ + __uqmi_command(dms_unblock_pin2, unblock-pin2, no, QMI_SERVICE_DMS), \ + __uqmi_command(dms_set_puk, puk, required, CMD_TYPE_OPTION), \ + __uqmi_command(dms_set_new_pin, new-pin, required, CMD_TYPE_OPTION), \ + __uqmi_command(dms_get_iccid, get-iccid, no, QMI_SERVICE_DMS), \ + __uqmi_command(dms_get_imsi, get-imsi, no, QMI_SERVICE_DMS), \ + __uqmi_command(dms_get_imei, get-imei, no, QMI_SERVICE_DMS), \ + __uqmi_command(dms_get_msisdn, get-msisdn, no, QMI_SERVICE_DMS), \ + __uqmi_command(dms_set_operating_mode, set-device-operating-mode, required, QMI_SERVICE_DMS), \ + __uqmi_command(dms_reset, reset-dms, no, QMI_SERVICE_DMS) \ + +#define dms_helptext \ + " --get-capabilities: List device capabilities\n" \ + " --get-pin-status: Get PIN verification status\n" \ + " --verify-pin1 : Verify PIN1\n" \ + " --verify-pin2 : Verify PIN2\n" \ + " --set-pin1-protection : Set PIN1 protection state (disabled, enabled)\n" \ + " --pin : PIN1 needed to change state\n" \ + " --set-pin2-protection : Set PIN2 protection state (disabled, enabled)\n" \ + " --pin : PIN2 needed to change state\n" \ + " --change-pin1: Change PIN1\n" \ + " --pin : Current PIN1\n" \ + " --new-pin : New pin\n" \ + " --change-pin2: Change PIN2\n" \ + " --pin : Current PIN2\n" \ + " --new-pin : New pin\n" \ + " --unblock-pin1: Unblock PIN1\n" \ + " --puk : PUK needed to unblock\n" \ + " --new-pin : New pin\n" \ + " --unblock-pin2: Unblock PIN2\n" \ + " --puk : PUK needed to unblock\n" \ + " --new-pin : New pin\n" \ + " --get-iccid: Get the ICCID\n" \ + " --get-imsi: Get International Mobile Subscriber ID\n" \ + " --get-imei: Get International Mobile Equipment ID\n" \ + " --get-msisdn: Get the MSISDN (telephone number)\n" \ + " --reset-dms: Reset the DMS service\n" \ + " --set-device-operating-mode Set the device operating mode\n" \ + " (modes: online, low_power, factory_test, offline\n" \ + " reset, shutting_down, persistent_low_power,\n" \ + " mode_only_low_power)\n" \ + diff --git a/release/src/router/uqmi/commands-nas.c b/release/src/router/uqmi/commands-nas.c new file mode 100644 index 0000000000..fd51a132c1 --- /dev/null +++ b/release/src/router/uqmi/commands-nas.c @@ -0,0 +1,371 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2014-2015 Felix Fietkau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include "qmi-message.h" + +static struct qmi_nas_set_system_selection_preference_request sel_req; +static struct { + bool mcc_is_set; + bool mnc_is_set; +} plmn_code_flag; + +#define cmd_nas_do_set_system_selection_cb no_cb +static enum qmi_cmd_result +cmd_nas_do_set_system_selection_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + qmi_set_nas_set_system_selection_preference_request(msg, &sel_req); + return QMI_CMD_REQUEST; +} + +static enum qmi_cmd_result +do_sel_network(void) +{ + static bool use_sel_req = false; + + if (!use_sel_req) { + use_sel_req = true; + uqmi_add_command(NULL, __UQMI_COMMAND_nas_do_set_system_selection); + } + + return QMI_CMD_DONE; +} + +#define cmd_nas_set_network_modes_cb no_cb +static enum qmi_cmd_result +cmd_nas_set_network_modes_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + static const struct { + const char *name; + QmiNasRatModePreference val; + } modes[] = { + { "cdma", QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1X | QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1XEVDO }, + { "td-scdma", QMI_NAS_RAT_MODE_PREFERENCE_TD_SCDMA }, + { "gsm", QMI_NAS_RAT_MODE_PREFERENCE_GSM }, + { "umts", QMI_NAS_RAT_MODE_PREFERENCE_UMTS }, + { "lte", QMI_NAS_RAT_MODE_PREFERENCE_LTE }, + }; + QmiNasRatModePreference val = 0; + char *word; + int i; + + for (word = strtok(arg, ","); + word; + word = strtok(NULL, ",")) { + bool found = false; + + for (i = 0; i < ARRAY_SIZE(modes); i++) { + if (strcmp(word, modes[i].name) != 0 && + strcmp(word, "all") != 0) + continue; + + val |= modes[i].val; + found = true; + } + + if (!found) { + uqmi_add_error("Invalid network mode"); + return QMI_CMD_EXIT; + } + } + + qmi_set(&sel_req, mode_preference, val); + return do_sel_network(); +} + +#define cmd_nas_set_network_preference_cb no_cb +static enum qmi_cmd_result +cmd_nas_set_network_preference_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + QmiNasGsmWcdmaAcquisitionOrderPreference pref = QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_AUTOMATIC; + + if (!strcmp(arg, "gsm")) + pref = QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_GSM; + else if (!strcmp(arg, "wcdma")) + pref = QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_WCDMA; + + qmi_set(&sel_req, gsm_wcdma_acquisition_order_preference, pref); + return do_sel_network(); +} + +#define cmd_nas_set_roaming_cb no_cb +static enum qmi_cmd_result +cmd_nas_set_roaming_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + QmiNasRoamingPreference pref; + + if (!strcmp(arg, "any")) + pref = QMI_NAS_ROAMING_PREFERENCE_ANY; + else if (!strcmp(arg, "only")) + pref = QMI_NAS_ROAMING_PREFERENCE_NOT_OFF; + else if (!strcmp(arg, "off")) + pref = QMI_NAS_ROAMING_PREFERENCE_OFF; + else + return uqmi_add_error("Invalid argument"); + + qmi_set(&sel_req, roaming_preference, pref); + return do_sel_network(); +} + +#define cmd_nas_set_mcc_cb no_cb +static enum qmi_cmd_result +cmd_nas_set_mcc_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + char *err; + int value = strtoul(arg, &err, 10); + if (err && *err) { + uqmi_add_error("Invalid MCC value"); + return QMI_CMD_EXIT; + } + + sel_req.data.network_selection_preference.mcc = value; + plmn_code_flag.mcc_is_set = true; + return QMI_CMD_DONE; +} + +#define cmd_nas_set_mnc_cb no_cb +static enum qmi_cmd_result +cmd_nas_set_mnc_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + char *err; + int value = strtoul(arg, &err, 10); + if (err && *err) { + uqmi_add_error("Invalid MNC value"); + return QMI_CMD_EXIT; + } + + sel_req.data.network_selection_preference.mnc = value; + plmn_code_flag.mnc_is_set = true; + return QMI_CMD_DONE; +} + +#define cmd_nas_set_plmn_cb no_cb +static enum qmi_cmd_result +cmd_nas_set_plmn_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + sel_req.set.network_selection_preference = 1; + sel_req.data.network_selection_preference.mode = QMI_NAS_NETWORK_SELECTION_PREFERENCE_AUTOMATIC; + + if (!plmn_code_flag.mcc_is_set && plmn_code_flag.mnc_is_set) { + uqmi_add_error("No MCC value"); + return QMI_CMD_EXIT; + } + + if (plmn_code_flag.mcc_is_set && sel_req.data.network_selection_preference.mcc) { + if (!plmn_code_flag.mnc_is_set) { + uqmi_add_error("No MNC value"); + return QMI_CMD_EXIT; + } else { + sel_req.data.network_selection_preference.mode = QMI_NAS_NETWORK_SELECTION_PREFERENCE_MANUAL; + } + } + + return do_sel_network(); +} + +#define cmd_nas_initiate_network_register_cb no_cb +static enum qmi_cmd_result +cmd_nas_initiate_network_register_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + static struct qmi_nas_initiate_network_register_request register_req = { + QMI_INIT(action, QMI_NAS_NETWORK_REGISTER_TYPE_AUTOMATIC) + }; + + qmi_set_nas_initiate_network_register_request(msg, ®ister_req); + return QMI_CMD_REQUEST; +} + +static void +cmd_nas_get_signal_info_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + struct qmi_nas_get_signal_info_response res; + void *c; + + qmi_parse_nas_get_signal_info_response(msg, &res); + + c = blobmsg_open_table(&status, NULL); + if (res.set.cdma_signal_strength) { + blobmsg_add_string(&status, "type", "cdma"); + blobmsg_add_u32(&status, "rssi", (int32_t) res.data.cdma_signal_strength.rssi); + blobmsg_add_u32(&status, "ecio", (int32_t) res.data.cdma_signal_strength.ecio); + } + + if (res.set.hdr_signal_strength) { + blobmsg_add_string(&status, "type", "hdr"); + blobmsg_add_u32(&status, "rssi", (int32_t) res.data.hdr_signal_strength.rssi); + blobmsg_add_u32(&status, "ecio", (int32_t) res.data.hdr_signal_strength.ecio); + blobmsg_add_u32(&status, "io", res.data.hdr_signal_strength.io); + } + + if (res.set.gsm_signal_strength) { + blobmsg_add_string(&status, "type", "gsm"); + blobmsg_add_u32(&status, "signal", (int32_t) res.data.gsm_signal_strength); + } + + if (res.set.wcdma_signal_strength) { + blobmsg_add_string(&status, "type", "wcdma"); + blobmsg_add_u32(&status, "rssi", (int32_t) res.data.wcdma_signal_strength.rssi); + blobmsg_add_u32(&status, "ecio", (int32_t) res.data.wcdma_signal_strength.ecio); + } + + if (res.set.lte_signal_strength) { + blobmsg_add_string(&status, "type", "lte"); + blobmsg_add_u32(&status, "rssi", (int32_t) res.data.lte_signal_strength.rssi); + blobmsg_add_u32(&status, "rsrq", (int32_t) res.data.lte_signal_strength.rsrq); + blobmsg_add_u32(&status, "rsrp", (int32_t) res.data.lte_signal_strength.rsrp); + blobmsg_add_u32(&status, "snr", (int32_t) res.data.lte_signal_strength.snr); + } + + if (res.set.tdma_signal_strength) { + blobmsg_add_string(&status, "type", "tdma"); + blobmsg_add_u32(&status, "signal", (int32_t) res.data.tdma_signal_strength); + } + + blobmsg_close_table(&status, c); +} + +static enum qmi_cmd_result +cmd_nas_get_signal_info_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + qmi_set_nas_get_signal_info_request(msg); + return QMI_CMD_REQUEST; +} + +static void +cmd_nas_get_serving_system_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + struct qmi_nas_get_serving_system_response res; + static const char *reg_states[] = { + [QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED] = "not_registered", + [QMI_NAS_REGISTRATION_STATE_REGISTERED] = "registered", + [QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED_SEARCHING] = "searching", + [QMI_NAS_REGISTRATION_STATE_REGISTRATION_DENIED] = "registering_denied", + [QMI_NAS_REGISTRATION_STATE_UNKNOWN] = "unknown", + }; + void *c; + + qmi_parse_nas_get_serving_system_response(msg, &res); + + c = blobmsg_open_table(&status, NULL); + if (res.set.serving_system) { + int state = res.data.serving_system.registration_state; + + if (state > QMI_NAS_REGISTRATION_STATE_UNKNOWN) + state = QMI_NAS_REGISTRATION_STATE_UNKNOWN; + + blobmsg_add_string(&status, "registration", reg_states[state]); + } + if (res.set.current_plmn) { + blobmsg_add_u32(&status, "plmn_mcc", res.data.current_plmn.mcc); + blobmsg_add_u32(&status, "plmn_mnc", res.data.current_plmn.mnc); + if (res.data.current_plmn.description) + blobmsg_add_string(&status, "plmn_description", res.data.current_plmn.description); + } + + if (res.set.roaming_indicator) + blobmsg_add_u8(&status, "roaming", !res.data.roaming_indicator); + + blobmsg_close_table(&status, c); +} + +static enum qmi_cmd_result +cmd_nas_get_serving_system_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + qmi_set_nas_get_serving_system_request(msg); + return QMI_CMD_REQUEST; +} + +static void +cmd_nas_network_scan_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + static struct qmi_nas_network_scan_response res; + const char *network_status[] = { + "current_serving", + "available", + "home", + "roaming", + "forbidden", + "not_forbidden", + "preferred", + "not_preferred", + }; + const char *radio[] = { + [QMI_NAS_RADIO_INTERFACE_NONE] = "none", + [QMI_NAS_RADIO_INTERFACE_CDMA_1X] = "cdma-1x", + [QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO] = "cdma-1x_evdo", + [QMI_NAS_RADIO_INTERFACE_AMPS] = "amps", + [QMI_NAS_RADIO_INTERFACE_GSM] = "gsm", + [QMI_NAS_RADIO_INTERFACE_UMTS] = "umts", + [QMI_NAS_RADIO_INTERFACE_LTE] = "lte", + [QMI_NAS_RADIO_INTERFACE_TD_SCDMA] = "td-scdma", + }; + void *t, *c, *info, *stat; + int i, j; + + qmi_parse_nas_network_scan_response(msg, &res); + + t = blobmsg_open_table(&status, NULL); + + c = blobmsg_open_array(&status, "network_info"); + for (i = 0; i < res.data.network_information_n; i++) { + info = blobmsg_open_table(&status, NULL); + blobmsg_add_u32(&status, "mcc", res.data.network_information[i].mcc); + blobmsg_add_u32(&status, "mnc", res.data.network_information[i].mnc); + if (res.data.network_information[i].description) + blobmsg_add_string(&status, "description", res.data.network_information[i].description); + stat = blobmsg_open_array(&status, "status"); + for (j = 0; j < ARRAY_SIZE(network_status); j++) { + if (!(res.data.network_information[i].network_status & (1 << j))) + continue; + + blobmsg_add_string(&status, NULL, network_status[j]); + } + blobmsg_close_array(&status, stat); + blobmsg_close_table(&status, info); + } + blobmsg_close_array(&status, c); + + c = blobmsg_open_array(&status, "radio_access_technology"); + for (i = 0; i < res.data.radio_access_technology_n; i++) { + const char *r = "unknown"; + int r_i = res.data.radio_access_technology[i].radio_interface; + + info = blobmsg_open_table(&status, NULL); + blobmsg_add_u32(&status, "mcc", res.data.radio_access_technology[i].mcc); + blobmsg_add_u32(&status, "mnc", res.data.radio_access_technology[i].mnc); + if (r_i >= 0 && r_i < ARRAY_SIZE(radio)) + r = radio[r_i]; + + blobmsg_add_string(&status, "radio", r); + blobmsg_close_table(&status, info); + } + blobmsg_close_array(&status, c); + + blobmsg_close_table(&status, t); +} + +static enum qmi_cmd_result +cmd_nas_network_scan_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + struct qmi_nas_network_scan_request sreq = {}; + + qmi_set_nas_network_scan_request(msg, &sreq); + return QMI_CMD_REQUEST; +} diff --git a/release/src/router/uqmi/commands-nas.h b/release/src/router/uqmi/commands-nas.h new file mode 100644 index 0000000000..9ebfa00346 --- /dev/null +++ b/release/src/router/uqmi/commands-nas.h @@ -0,0 +1,49 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2014-2015 Felix Fietkau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#define __uqmi_nas_commands \ + __uqmi_command(nas_do_set_system_selection, __set-system-selection, no, QMI_SERVICE_NAS), \ + __uqmi_command(nas_set_network_modes, set-network-modes, required, CMD_TYPE_OPTION), \ + __uqmi_command(nas_initiate_network_register, network-register, no, QMI_SERVICE_NAS), \ + __uqmi_command(nas_set_plmn, set-plmn, no, QMI_SERVICE_NAS), \ + __uqmi_command(nas_set_mcc, mcc, required, CMD_TYPE_OPTION), \ + __uqmi_command(nas_set_mnc, mnc, required, CMD_TYPE_OPTION), \ + __uqmi_command(nas_network_scan, network-scan, no, QMI_SERVICE_NAS), \ + __uqmi_command(nas_get_signal_info, get-signal-info, no, QMI_SERVICE_NAS), \ + __uqmi_command(nas_get_serving_system, get-serving-system, no, QMI_SERVICE_NAS), \ + __uqmi_command(nas_set_network_preference, set-network-preference, required, CMD_TYPE_OPTION), \ + __uqmi_command(nas_set_roaming, set-network-roaming, required, CMD_TYPE_OPTION) \ + +#define nas_helptext \ + " --set-network-modes : Set usable network modes (Syntax: [,,...])\n" \ + " Available modes: all, lte, umts, gsm, cdma, td-scdma\n" \ + " --set-network-preference : Set preferred network mode to \n" \ + " Available modes: auto, gsm, wcdma\n" \ + " --set-network-roaming : Set roaming preference:\n" \ + " Available modes: any, off, only\n" \ + " --network-scan: Initiate network scan\n" \ + " --network-register: Initiate network register\n" \ + " --set-plmn: Register at specified network\n" \ + " --mcc : Mobile Country Code (0 - auto)\n" \ + " --mnc : Mobile Network Code\n" \ + " --get-signal-info: Get signal strength info\n" \ + " --get-serving-system: Get serving system info\n" \ + diff --git a/release/src/router/uqmi/commands-wda.c b/release/src/router/uqmi/commands-wda.c new file mode 100644 index 0000000000..3b2530ad05 --- /dev/null +++ b/release/src/router/uqmi/commands-wda.c @@ -0,0 +1,79 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2014-2015 Felix Fietkau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include + +#include "qmi-message.h" + +static const struct { + const char *name; + QmiWdaLinkLayerProtocol val; +} link_modes[] = { + { "802.3", QMI_WDA_LINK_LAYER_PROTOCOL_802_3 }, + { "raw-ip", QMI_WDA_LINK_LAYER_PROTOCOL_RAW_IP }, +}; + +#define cmd_wda_set_data_format_cb no_cb + +static enum qmi_cmd_result +cmd_wda_set_data_format_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + struct qmi_wda_set_data_format_request data_req = {}; + int i; + + for (i = 0; i < ARRAY_SIZE(link_modes); i++) { + if (strcasecmp(link_modes[i].name, arg) != 0) + continue; + + qmi_set(&data_req, link_layer_protocol, link_modes[i].val); + qmi_set_wda_set_data_format_request(msg, &data_req); + return QMI_CMD_REQUEST; + } + + uqmi_add_error("Invalid auth mode (valid: 802.3, raw-ip)"); + return QMI_CMD_EXIT; +} + +static void +cmd_wda_get_data_format_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + struct qmi_wda_get_data_format_response res; + const char *name = "unknown"; + int i; + + qmi_parse_wda_get_data_format_response(msg, &res); + for (i = 0; i < ARRAY_SIZE(link_modes); i++) { + if (link_modes[i].val != res.data.link_layer_protocol) + continue; + + name = link_modes[i].name; + break; + } + + blobmsg_add_string(&status, NULL, name); +} + +static enum qmi_cmd_result +cmd_wda_get_data_format_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + qmi_set_wda_get_data_format_request(msg); + return QMI_CMD_REQUEST; +} diff --git a/release/src/router/uqmi/commands-wda.h b/release/src/router/uqmi/commands-wda.h new file mode 100644 index 0000000000..3ae7b7f5ad --- /dev/null +++ b/release/src/router/uqmi/commands-wda.h @@ -0,0 +1,30 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2014-2015 Felix Fietkau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#define __uqmi_wda_commands \ + __uqmi_command(wda_set_data_format, wda-set-data-format, required, QMI_SERVICE_WDA), \ + __uqmi_command(wda_get_data_format, wda-get-data-format, no, QMI_SERVICE_WDA) + + +#define wda_helptext \ + " --wda-set-data-format : Set data format (type: 802.3|raw-ip)\n" \ + " --wda-get-data-format: Get data format\n" \ + diff --git a/release/src/router/uqmi/commands-wds.c b/release/src/router/uqmi/commands-wds.c new file mode 100644 index 0000000000..fabb5f4c6e --- /dev/null +++ b/release/src/router/uqmi/commands-wds.c @@ -0,0 +1,323 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2014-2015 Felix Fietkau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include +#include + +#include "qmi-message.h" + +static struct qmi_wds_start_network_request wds_sn_req = { + QMI_INIT(authentication_preference, + QMI_WDS_AUTHENTICATION_PAP | QMI_WDS_AUTHENTICATION_CHAP), +}; +static struct qmi_wds_stop_network_request wds_stn_req; + +#define cmd_wds_set_auth_cb no_cb +static enum qmi_cmd_result +cmd_wds_set_auth_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + static const struct { + const char *name; + QmiWdsAuthentication auth; + } modes[] = { + { "pap", QMI_WDS_AUTHENTICATION_PAP }, + { "chap", QMI_WDS_AUTHENTICATION_CHAP }, + { "both", QMI_WDS_AUTHENTICATION_PAP | QMI_WDS_AUTHENTICATION_CHAP }, + { "none", QMI_WDS_AUTHENTICATION_NONE }, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(modes); i++) { + if (strcasecmp(modes[i].name, arg) != 0) + continue; + + qmi_set(&wds_sn_req, authentication_preference, modes[i].auth); + return QMI_CMD_DONE; + } + + uqmi_add_error("Invalid auth mode (valid: pap, chap, both, none)"); + return QMI_CMD_EXIT; +} + +#define cmd_wds_set_username_cb no_cb +static enum qmi_cmd_result +cmd_wds_set_username_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + qmi_set_ptr(&wds_sn_req, username, arg); + return QMI_CMD_DONE; +} + +#define cmd_wds_set_password_cb no_cb +static enum qmi_cmd_result +cmd_wds_set_password_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + qmi_set_ptr(&wds_sn_req, password, arg); + return QMI_CMD_DONE; +} + +#define cmd_wds_set_autoconnect_cb no_cb +static enum qmi_cmd_result +cmd_wds_set_autoconnect_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + qmi_set(&wds_sn_req, enable_autoconnect, true); + qmi_set(&wds_stn_req, disable_autoconnect, true); + return QMI_CMD_DONE; +} + +static void +cmd_wds_start_network_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + struct qmi_wds_start_network_response res; + + qmi_parse_wds_start_network_response(msg, &res); + if (res.set.packet_data_handle) + blobmsg_add_u32(&status, NULL, res.data.packet_data_handle); +} + +static enum qmi_cmd_result +cmd_wds_start_network_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + qmi_set_ptr(&wds_sn_req, apn, arg); + qmi_set_wds_start_network_request(msg, &wds_sn_req); + return QMI_CMD_REQUEST; +} + +#define cmd_wds_stop_network_cb no_cb +static enum qmi_cmd_result +cmd_wds_stop_network_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + uint32_t pdh = strtoul(arg, NULL, 0); + + qmi_set(&wds_stn_req, packet_data_handle, pdh); + qmi_set_wds_stop_network_request(msg, &wds_stn_req); + return QMI_CMD_REQUEST; +} + +static void +cmd_wds_get_packet_service_status_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + struct qmi_wds_get_packet_service_status_response res; + const char *data_status[] = { + [QMI_WDS_CONNECTION_STATUS_UNKNOWN] = "unknown", + [QMI_WDS_CONNECTION_STATUS_DISCONNECTED] = "disconnected", + [QMI_WDS_CONNECTION_STATUS_CONNECTED] = "connected", + [QMI_WDS_CONNECTION_STATUS_SUSPENDED] = "suspended", + [QMI_WDS_CONNECTION_STATUS_AUTHENTICATING] = "authenticating", + }; + int s = 0; + + qmi_parse_wds_get_packet_service_status_response(msg, &res); + if (res.set.connection_status && + res.data.connection_status < ARRAY_SIZE(data_status)) + s = res.data.connection_status; + + blobmsg_add_string(&status, NULL, data_status[s]); +} + +static enum qmi_cmd_result +cmd_wds_get_packet_service_status_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + qmi_set_wds_get_packet_service_status_request(msg); + return QMI_CMD_REQUEST; +} + +#define cmd_wds_set_autoconnect_setting_cb no_cb +static enum qmi_cmd_result +cmd_wds_set_autoconnect_setting_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + struct qmi_wds_set_autoconnect_setting_request ac_req; + const char *modes[] = { + [QMI_WDS_AUTOCONNECT_DISABLED] = "disabled", + [QMI_WDS_AUTOCONNECT_ENABLED] = "enabled", + [QMI_WDS_AUTOCONNECT_PAUSED] = "paused", + }; + int i; + + for (i = 0; i < ARRAY_SIZE(modes); i++) { + if (strcasecmp(modes[i], arg) != 0) + continue; + + qmi_set(&ac_req, setting, i); + qmi_set_wds_set_autoconnect_setting_request(msg, &ac_req); + return QMI_CMD_DONE; + } + + uqmi_add_error("Invalid value (valid: disabled, enabled, paused)"); + return QMI_CMD_EXIT; +} + +#define cmd_wds_reset_cb no_cb +static enum qmi_cmd_result +cmd_wds_reset_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + qmi_set_wds_reset_request(msg); + return QMI_CMD_REQUEST; +} + +#define cmd_wds_set_ip_family_cb no_cb +static enum qmi_cmd_result +cmd_wds_set_ip_family_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + struct qmi_wds_set_ip_family_request ipf_req; + const struct ip_modes { + const char *name; + const QmiWdsIpFamily mode; + } modes[] = { + { "ipv4", QMI_WDS_IP_FAMILY_IPV4 }, + { "ipv6", QMI_WDS_IP_FAMILY_IPV6 }, + { "unspecified", QMI_WDS_IP_FAMILY_UNSPECIFIED }, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(modes); i++) { + if (strcasecmp(modes[i].name, arg) != 0) + continue; + + qmi_set(&ipf_req, preference, modes[i].mode); + qmi_set_wds_set_ip_family_request(msg, &ipf_req); + return QMI_CMD_REQUEST; + } + + uqmi_add_error("Invalid value (valid: ipv4, ipv6, unspecified)"); + return QMI_CMD_EXIT; +} + +static void wds_to_ipv4(const char *name, const uint32_t addr) +{ + struct in_addr ip_addr; + char buf[INET_ADDRSTRLEN]; + + ip_addr.s_addr = htonl(addr); + blobmsg_add_string(&status, name, inet_ntop(AF_INET, &ip_addr, buf, sizeof(buf))); +} + +static void wds_to_ipv6(const char *name, const uint16_t *addr) +{ + int i; + struct in6_addr ip_addr; + char buf[INET6_ADDRSTRLEN]; + + for (i = 0; i < ARRAY_SIZE(ip_addr.s6_addr16); i++) { + ip_addr.s6_addr16[i] = htons(addr[i]); + } + + blobmsg_add_string(&status, name, inet_ntop(AF_INET6, &ip_addr, buf, sizeof(buf))); +} + +static void +cmd_wds_get_current_settings_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + void *v4, *v6, *d, *t; + struct qmi_wds_get_current_settings_response res; + const char *pdptypes[] = { + [QMI_WDS_PDP_TYPE_IPV4] = "ipv4", + [QMI_WDS_PDP_TYPE_PPP] = "ppp", + [QMI_WDS_PDP_TYPE_IPV6] = "ipv6", + [QMI_WDS_PDP_TYPE_IPV4_OR_IPV6] = "ipv4-or-ipv6", + }; + const struct ip_modes { + const char *name; + const QmiWdsIpFamily mode; + } modes[] = { + { "ipv4", QMI_WDS_IP_FAMILY_IPV4 }, + { "ipv6", QMI_WDS_IP_FAMILY_IPV6 }, + { "unspecified", QMI_WDS_IP_FAMILY_UNSPECIFIED }, + }; + int i; + + qmi_parse_wds_get_current_settings_response(msg, &res); + + t = blobmsg_open_table(&status, NULL); + + if (res.set.pdp_type && res.data.pdp_type < ARRAY_SIZE(pdptypes)) + blobmsg_add_string(&status, "pdp-type", pdptypes[res.data.pdp_type]); + + if (res.set.ip_family) { + for (i = 0; i < ARRAY_SIZE(modes); i++) { + if (modes[i].mode != res.data.ip_family) + continue; + blobmsg_add_string(&status, "ip-family", modes[i].name); + break; + } + } + + if (res.set.mtu) + blobmsg_add_u32(&status, "mtu", res.data.mtu); + + /* IPV4 */ + v4 = blobmsg_open_table(&status, "ipv4"); + + if (res.set.ipv4_address) + wds_to_ipv4("ip", res.data.ipv4_address); + if (res.set.primary_ipv4_dns_address) + wds_to_ipv4("dns1", res.data.primary_ipv4_dns_address); + if (res.set.secondary_ipv4_dns_address) + wds_to_ipv4("dns2", res.data.secondary_ipv4_dns_address); + if (res.set.ipv4_gateway_address) + wds_to_ipv4("gateway", res.data.ipv4_gateway_address); + if (res.set.ipv4_gateway_subnet_mask) + wds_to_ipv4("subnet", res.data.ipv4_gateway_subnet_mask); + blobmsg_close_table(&status, v4); + + /* IPV6 */ + v6 = blobmsg_open_table(&status, "ipv6"); + + if (res.set.ipv6_address) { + wds_to_ipv6("ip", res.data.ipv6_address.address); + blobmsg_add_u32(&status, "ip-prefix-length", res.data.ipv6_address.prefix_length); + } + if (res.set.ipv6_gateway_address) { + wds_to_ipv6("gateway", res.data.ipv6_gateway_address.address); + blobmsg_add_u32(&status, "gw-prefix-length", res.data.ipv6_gateway_address.prefix_length); + } + if (res.set.ipv6_primary_dns_address) + wds_to_ipv6("dns1", res.data.ipv6_primary_dns_address); + if (res.set.ipv6_secondary_dns_address) + wds_to_ipv6("dns2", res.data.ipv6_secondary_dns_address); + + blobmsg_close_table(&status, v6); + + d = blobmsg_open_table(&status, "domain-names"); + for (i = 0; i < res.data.domain_name_list_n; i++) { + blobmsg_add_string(&status, NULL, res.data.domain_name_list[i]); + } + blobmsg_close_table(&status, d); + + blobmsg_close_table(&status, t); +} + +static enum qmi_cmd_result +cmd_wds_get_current_settings_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + struct qmi_wds_get_current_settings_request gcs_req; + memset(&gcs_req, '\0', sizeof(struct qmi_wds_get_current_settings_request)); + qmi_set(&gcs_req, requested_settings, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PDP_TYPE | + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DNS_ADDRESS | + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GRANTED_QOS | + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_ADDRESS | + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GATEWAY_INFO | + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_MTU | + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DOMAIN_NAME_LIST | + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_FAMILY); + qmi_set_wds_get_current_settings_request(msg, &gcs_req); + return QMI_CMD_REQUEST; +} diff --git a/release/src/router/uqmi/commands-wds.h b/release/src/router/uqmi/commands-wds.h new file mode 100644 index 0000000000..8cb72896bf --- /dev/null +++ b/release/src/router/uqmi/commands-wds.h @@ -0,0 +1,48 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2014-2015 Felix Fietkau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#define __uqmi_wds_commands \ + __uqmi_command(wds_start_network, start-network, required, QMI_SERVICE_WDS), \ + __uqmi_command(wds_set_auth, auth-type, required, CMD_TYPE_OPTION), \ + __uqmi_command(wds_set_username, username, required, CMD_TYPE_OPTION), \ + __uqmi_command(wds_set_password, password, required, CMD_TYPE_OPTION), \ + __uqmi_command(wds_set_ip_family, ip-family, required, CMD_TYPE_OPTION), \ + __uqmi_command(wds_set_autoconnect, autoconnect, no, CMD_TYPE_OPTION), \ + __uqmi_command(wds_stop_network, stop-network, required, QMI_SERVICE_WDS), \ + __uqmi_command(wds_get_packet_service_status, get-data-status, no, QMI_SERVICE_WDS), \ + __uqmi_command(wds_set_autoconnect_setting, set-autoconnect, required, QMI_SERVICE_WDS), \ + __uqmi_command(wds_reset, reset-wds, no, QMI_SERVICE_WDS), \ + __uqmi_command(wds_get_current_settings, get-current-settings, no, QMI_SERVICE_WDS) \ + + +#define wds_helptext \ + " --start-network : Start network connection (use with options below)\n" \ + " --auth-type pap|chap|both|none: Use network authentication type\n" \ + " --username : Use network username\n" \ + " --password : Use network password\n" \ + " --ip-family : Use ip-family for the connection (ipv4, ipv6, unspecified)\n" \ + " --autoconnect: Enable automatic connect/reconnect\n" \ + " --stop-network : Stop network connection (use with option below)\n" \ + " --autoconnect: Disable automatic connect/reconnect\n" \ + " --get-data-status: Get current data access status\n" \ + " --set-autoconnect : Get current data access status (disabled, enabled, paused)\n" \ + " --get-current-settings: Get current connection settings\n" \ + diff --git a/release/src/router/uqmi/commands-wms.c b/release/src/router/uqmi/commands-wms.c new file mode 100644 index 0000000000..700d79ff96 --- /dev/null +++ b/release/src/router/uqmi/commands-wms.c @@ -0,0 +1,668 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2014-2015 Felix Fietkau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include "qmi-message.h" + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define CEILDIV(x,y) (((x) + (y) - 1) / (y)) + +static void cmd_wms_list_messages_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + struct qmi_wms_list_messages_response res; + void *c; + int i; + + qmi_parse_wms_list_messages_response(msg, &res); + c = blobmsg_open_array(&status, NULL); + for (i = 0; i < res.data.message_list_n; i++) + blobmsg_add_u32(&status, NULL, res.data.message_list[i].memory_index); + + blobmsg_close_array(&status, c); +} + +static enum qmi_cmd_result +cmd_wms_list_messages_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + static struct qmi_wms_list_messages_request mreq = { + QMI_INIT(storage_type, QMI_WMS_STORAGE_TYPE_UIM), + QMI_INIT(message_tag, QMI_WMS_MESSAGE_TAG_TYPE_MT_NOT_READ), + }; + + qmi_set_wms_list_messages_request(msg, &mreq); + + return QMI_CMD_REQUEST; +} + +static int +put_unicode_char(char *dest, uint16_t c) +{ + if (c < 0x80) { + *dest = c; + return 1; + } else if (c < 0x800) { + *(dest++) = 0xc0 | ((c >> 6) & 0x1f); + *dest = 0x80 | (c & 0x3f); + return 2; + } else { + *(dest++) = 0xe0 | ((c >> 12) & 0xf); + *(dest++) = 0x80 | ((c >> 6) & 0x3f); + *dest = 0x80 | (c & 0x3f); + return 3; + } +} + + +static int +pdu_decode_7bit_char(char *dest, int len, unsigned char c, bool *escape) +{ + uint16_t conv_0x20[] = { + 0x0040, 0x00A3, 0x0024, 0x00A5, 0x00E8, 0x00E9, 0x00F9, 0x00EC, + 0x00F2, 0x00E7, 0x000A, 0x00D8, 0x00F8, 0x000D, 0x00C5, 0x00E5, + 0x0394, 0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0, 0x03A8, + 0x03A3, 0x0398, 0x039E, 0x00A0, 0x00C6, 0x00E6, 0x00DF, 0x00C9, + }; + uint16_t conv_0x5b[] = { + 0x00C4, 0x00D6, 0x00D1, 0x00DC, 0x00A7, 0x00BF, + }; + uint16_t conv_0x7b[] = { + 0x00E4, 0x00F6, 0x00F1, 0x00FC, 0x00E0 + }; + int cur_len = 0; + uint16_t outc; + + fprintf(stderr, " %02x", c); + dest += len; + if (*escape) { + *escape = false; + switch(c) { + case 0x0A: + *dest = 0x0C; + return 1; + case 0x14: + *dest = 0x5E; + return 1; + case 0x28: + *dest = 0x7B; + return 1; + case 0x29: + *dest = 0x7D; + return 1; + case 0x2F: + *dest = 0x5C; + return 1; + case 0x3C: + *dest = 0x5B; + return 1; + case 0x3D: + *dest = 0x7E; + return 1; + case 0x3E: + *dest = 0x5D; + return 1; + case 0x40: + *dest = 0x7C; + return 1; + case 0x65: + outc = 0x20AC; + goto out; + case 0x1B: + goto normal; + default: + /* invalid */ + *(dest++) = conv_0x20[0x1B]; + cur_len++; + goto normal; + } + } + + if (c == 0x1b) { + *escape = true; + return 0; + } + +normal: + if (c < 0x20) + outc = conv_0x20[(int) c]; + else if (c == 0x40) + outc = 0x00A1; + else if (c >= 0x5b && c <= 0x60) + outc = conv_0x5b[c - 0x5b]; + else if (c >= 0x7b && c <= 0x7f) + outc = conv_0x7b[c - 0x7b]; + else + outc = c; + +out: + return cur_len + put_unicode_char(dest, outc); +} + +static int +pdu_decode_7bit_str(char *dest, const unsigned char *data, int data_len, int bit_offset) +{ + bool escape = false; + int len = 0; + int i; + + fprintf(stderr, "Raw text:"); + for (i = 0; i < data_len; i++) { + int pos = (i + bit_offset) % 7; + + if (pos == 0) { + len += pdu_decode_7bit_char(dest, len, data[i] & 0x7f, &escape); + } else { + if (i) + len += pdu_decode_7bit_char(dest, len, + (data[i - 1] >> (7 + 1 - pos)) | + ((data[i] << pos) & 0x7f), &escape); + + if (pos == 6) + len += pdu_decode_7bit_char(dest, len, (data[i] >> 1) & 0x7f, + &escape); + } + } + dest[len] = 0; + fprintf(stderr, "\n"); + return len; +} + +static int decode_udh(const unsigned char *data) +{ + const unsigned char *end; + unsigned int type, len, udh_len; + + udh_len = *(data++); + end = data + udh_len; + while (data < end) { + const unsigned char *val; + + type = data[0]; + len = data[1]; + val = &data[2]; + data += 2 + len; + if (data > end) + break; + + switch (type) { + case 0x00: + blobmsg_add_u32(&status, "concat_ref", (uint32_t) val[0]); + blobmsg_add_u32(&status, "concat_part", (uint32_t) val[2]); + blobmsg_add_u32(&status, "concat_parts", (uint32_t) val[1]); + break; + case 0x08: + blobmsg_add_u32(&status, "concat_ref", (uint32_t) (val[0] << 8 | val[1])); + blobmsg_add_u32(&status, "concat_part", (uint32_t) val[3]); + blobmsg_add_u32(&status, "concat_parts", (uint32_t) val[2]); + break; + default: + break; + } + } + + return udh_len + 1; +} + +static void decode_7bit_field(char *name, const unsigned char *data, int data_len, int bit_offset) +{ + char *dest = blobmsg_alloc_string_buffer(&status, name, 3 * data_len + 2); + pdu_decode_7bit_str(dest, data, CEILDIV(data_len * 7, 8), bit_offset); + dest[data_len] = 0; + blobmsg_add_string_buffer(&status); +} + +static char *pdu_add_semioctet(char *str, char val) +{ + *str = '0' + (val & 0xf); + if (*str <= '9') + str++; + + *str = '0' + ((val >> 4) & 0xf); + if (*str <= '9') + str++; + + return str; +} + +static void +pdu_decode_address(char *str, unsigned char *data, int len) +{ + unsigned char toa; + + toa = *(data++); + switch (toa & 0x70) { + case 0x50: + pdu_decode_7bit_str(str, data, len, 0); + return; + case 0x10: + *(str++) = '+'; + /* fall through */ + default: + while (len--) { + str = pdu_add_semioctet(str, *data); + data++; + } + } + + *str = 0; +} + +static void wms_decode_address(char *name, unsigned char *data, int len) +{ + char *str = blobmsg_alloc_string_buffer(&status, name, len * 2 + 2); + pdu_decode_address(str, data, len); + blobmsg_add_string_buffer(&status); +} + +static void blobmsg_add_hex(struct blob_buf *buf, const char *name, unsigned const char *data, int len) +{ + char* str = blobmsg_alloc_string_buffer(buf, name, len * 2 + 1); + for (int i = 0; i < len; i++) { + str += sprintf(str, "%02x", data[i]); + } + blobmsg_add_string_buffer(buf); +} + +#define cmd_wms_delete_message_cb no_cb +static enum qmi_cmd_result +cmd_wms_delete_message_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + char *err; + int id; + + id = strtoul(arg, &err, 10); + if (err && *err) { + uqmi_add_error("Invalid message ID"); + return QMI_CMD_EXIT; + } + + static struct qmi_wms_delete_request mreq = { + QMI_INIT(memory_storage, QMI_WMS_STORAGE_TYPE_UIM), + QMI_INIT(message_mode, QMI_WMS_MESSAGE_MODE_GSM_WCDMA), + }; + + mreq.set.memory_index = 1; + mreq.data.memory_index = id; + + qmi_set_wms_delete_request(msg, &mreq); + + return QMI_CMD_REQUEST; +} + + +static void cmd_wms_get_message_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + struct qmi_wms_raw_read_response res; + unsigned char *data, *end; + char *str; + int cur_len; + bool sent; + unsigned char first, dcs; + void *c; + + qmi_parse_wms_raw_read_response(msg, &res); + c = blobmsg_open_table(&status, NULL); + data = (unsigned char *) res.data.raw_message_data.raw_data; + end = data + res.data.raw_message_data.raw_data_n; + + cur_len = *(data++); + if (data + cur_len >= end) + goto error; + + if (cur_len) { + wms_decode_address("smsc", data, cur_len - 1); + data += cur_len; + } + + if (data + 3 >= end) + goto error; + + first = *(data++); + sent = (first & 0x3) == 1; + if (sent) + data++; + + cur_len = *(data++); + if (data + cur_len >= end) + goto error; + + if (cur_len) { + cur_len = (cur_len + 1) / 2; + wms_decode_address(sent ? "receiver" : "sender", data, cur_len); + data += cur_len + 1; + } + + if (data + 3 >= end) + goto error; + + /* Protocol ID */ + if (*(data++) != 0) + goto error; + + /* Data Encoding */ + dcs = *(data++); + + if (dcs & 0x10) + blobmsg_add_u32(&status, "class", (dcs & 3)); + + if (sent) { + /* Message validity */ + data++; + } else { + if (data + 6 >= end) + goto error; + + str = blobmsg_alloc_string_buffer(&status, "timestamp", 32); + + /* year */ + *(str++) = '2'; + *(str++) = '0'; + str = pdu_add_semioctet(str, data[0]); + /* month */ + *(str++) = '-'; + str = pdu_add_semioctet(str, data[1]); + /* day */ + *(str++) = '-'; + str = pdu_add_semioctet(str, data[2]); + + /* hour */ + *(str++) = ' '; + str = pdu_add_semioctet(str, data[3]); + /* minute */ + *(str++) = ':'; + str = pdu_add_semioctet(str, data[4]); + /* second */ + *(str++) = ':'; + str = pdu_add_semioctet(str, data[5]); + *str = 0; + + blobmsg_add_string_buffer(&status); + + data += 7; + } + + int message_len = *(data++); + int udh_len = 0; + int bit_offset = 0; + + /* User Data Header */ + if (first & 0x40) { + udh_len = decode_udh(data); + data += udh_len; + bit_offset = udh_len % 7; + } + + if (data >= end) + goto error; + + switch(dcs & 0x0c) { + case 0x00: + /* 7 bit GSM alphabet */ + message_len = message_len - CEILDIV(udh_len * 8, 7); + message_len = MIN(message_len, CEILDIV((end - data) * 8, 7)); + decode_7bit_field("text", data, message_len, bit_offset); + break; + case 0x04: + /* 8 bit data */ + message_len = MIN(message_len - udh_len, end - data); + blobmsg_add_hex(&status, "data", data, message_len); + break; + case 0x08: + /* 16 bit UCS-2 string */ + message_len = MIN(message_len - udh_len, end - data); + blobmsg_add_hex(&status, "ucs-2", data, message_len); + break; + default: + goto error; + } + + blobmsg_close_table(&status, c); + return; + +error: + blobmsg_close_table(&status, c); + fprintf(stderr, "There was an error reading message.\n"); +} + +static enum qmi_cmd_result +cmd_wms_get_message_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + static struct qmi_wms_raw_read_request mreq = { + QMI_INIT_SEQUENCE(message_memory_storage_id, + .storage_type = QMI_WMS_STORAGE_TYPE_UIM, + ), + QMI_INIT(message_mode, QMI_WMS_MESSAGE_MODE_GSM_WCDMA), + }; + char *err; + int id; + + id = strtoul(arg, &err, 10); + if (err && *err) { + uqmi_add_error("Invalid message ID"); + return QMI_CMD_EXIT; + } + + mreq.data.message_memory_storage_id.memory_index = id; + qmi_set_wms_raw_read_request(msg, &mreq); + + return QMI_CMD_REQUEST; +} + + +static void cmd_wms_get_raw_message_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + struct qmi_wms_raw_read_response res; + unsigned char *data; + char *str; + int i; + + qmi_parse_wms_raw_read_response(msg, &res); + data = (unsigned char *) res.data.raw_message_data.raw_data; + str = blobmsg_alloc_string_buffer(&status, NULL, res.data.raw_message_data.raw_data_n * 3); + for (i = 0; i < res.data.raw_message_data.raw_data_n; i++) { + str += sprintf(str, &" %02x"[i ? 0 : 1], data[i]); + } + blobmsg_add_string_buffer(&status); +} + +#define cmd_wms_get_raw_message_prepare cmd_wms_get_message_prepare + + +static struct { + const char *smsc; + const char *target; + bool flash; +} _send; + + +#define cmd_wms_send_message_smsc_cb no_cb +static enum qmi_cmd_result +cmd_wms_send_message_smsc_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + _send.smsc = arg; + return QMI_CMD_DONE; +} + +#define cmd_wms_send_message_target_cb no_cb +static enum qmi_cmd_result +cmd_wms_send_message_target_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + _send.target = arg; + return QMI_CMD_DONE; +} + +#define cmd_wms_send_message_flash_cb no_cb +static enum qmi_cmd_result +cmd_wms_send_message_flash_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + _send.flash = true; + return QMI_CMD_DONE; +} + +static int +pdu_encode_semioctet(unsigned char *dest, const char *str) +{ + int len = 0; + bool lower = true; + + while (*str) { + char digit = *str - '0'; + + if (lower) + dest[len] = 0xf0 | digit; + else + dest[len++] &= (digit << 4) | 0xf; + + lower = !lower; + str++; + } + + return lower ? len : (len + 1); +} + +static int +pdu_encode_7bit_str(unsigned char *data, const char *str) +{ + unsigned char c; + int len = 0; + int ofs = 0; + + while(1) { + c = *(str++) & 0x7f; + if (!c) + break; + + switch(ofs) { + case 0: + data[len] = c; + break; + default: + data[len++] |= c << (8 - ofs); + data[len] = c >> ofs; + break; + } + + ofs = (ofs + 1) % 8; + } + + return len + 1; +} + +static int +pdu_encode_number(unsigned char *dest, const char *str, bool smsc) +{ + unsigned char format; + bool ascii = false; + int len = 0; + int i; + + dest[len++] = 0; + if (*str == '+') { + str++; + format = 0x91; + } else { + format = 0x81; + } + + for (i = 0; str[i]; i++) { + if (str[i] >= '0' && str[i] <= '9') + continue; + + ascii = true; + break; + } + + if (ascii) + format |= 0x40; + + dest[len++] = format; + if (!ascii) + len += pdu_encode_semioctet(&dest[len], str); + else + len += pdu_encode_7bit_str(&dest[len], str); + + if (smsc) + dest[0] = len - 1; + else + dest[0] = strlen(str); + + return len; +} + +static int +pdu_encode_data(unsigned char *dest, const char *str) +{ + int len = 0; + + dest[len++] = 0; + len += pdu_encode_7bit_str(&dest[len], str); + dest[0] = strlen(str); + + return len; +} + +#define cmd_wms_send_message_cb no_cb +static enum qmi_cmd_result +cmd_wms_send_message_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + static unsigned char buf[512]; + static struct qmi_wms_raw_send_request mreq = { + QMI_INIT_SEQUENCE(raw_message_data, + .format = QMI_WMS_MESSAGE_FORMAT_GSM_WCDMA_POINT_TO_POINT, + .raw_data = buf, + ), + }; + unsigned char *cur = buf; + unsigned char first_octet = 0x11; + unsigned char protocol_id = 0x00; + unsigned char dcs = 0x00; + + if (!_send.target || !*_send.target) { + uqmi_add_error("Missing argument"); + return QMI_CMD_EXIT; + } + + if ((_send.smsc && strlen(_send.smsc) > 16) || strlen(_send.target) > 16 || strlen(arg) > 160) { + uqmi_add_error("Argument too long"); + return QMI_CMD_EXIT; + } + + if (_send.flash) + dcs |= 0x10; + + if (!_send.smsc || !*_send.smsc) + *(cur++) = 0; + else + cur += pdu_encode_number(cur, _send.smsc, true); + + *(cur++) = first_octet; + *(cur++) = 0; /* reference */ + + cur += pdu_encode_number(cur, _send.target, false); + *(cur++) = protocol_id; + *(cur++) = dcs; + + *(cur++) = 0xff; /* validity */ + cur += pdu_encode_data(cur, arg); + + mreq.data.raw_message_data.raw_data_n = cur - buf; + qmi_set_wms_raw_send_request(msg, &mreq); + + return QMI_CMD_REQUEST; +} diff --git a/release/src/router/uqmi/commands-wms.h b/release/src/router/uqmi/commands-wms.h new file mode 100644 index 0000000000..e28b97bcd8 --- /dev/null +++ b/release/src/router/uqmi/commands-wms.h @@ -0,0 +1,41 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2014-2015 Felix Fietkau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#define __uqmi_wms_commands \ + __uqmi_command(wms_list_messages, list-messages, no, QMI_SERVICE_WMS), \ + __uqmi_command(wms_delete_message, delete-message, required, QMI_SERVICE_WMS), \ + __uqmi_command(wms_get_message, get-message, required, QMI_SERVICE_WMS), \ + __uqmi_command(wms_get_raw_message, get-raw-message, required, QMI_SERVICE_WMS), \ + __uqmi_command(wms_send_message_smsc, send-message-smsc, required, CMD_TYPE_OPTION), \ + __uqmi_command(wms_send_message_target, send-message-target, required, CMD_TYPE_OPTION), \ + __uqmi_command(wms_send_message_flash, send-message-flash, no, CMD_TYPE_OPTION), \ + __uqmi_command(wms_send_message, send-message, required, QMI_SERVICE_WMS) + +#define wms_helptext \ + " --list-messages: List SMS messages\n" \ + " --delete-message : Delete SMS message at index \n" \ + " --get-message : Get SMS message at index \n" \ + " --get-raw-message : Get SMS raw message contents at index \n" \ + " --send-message : Send SMS message (use options below)\n" \ + " --send-message-smsc : SMSC number\n" \ + " --send-message-target : Destination number (required)\n" \ + " --send-message-flash: Send as Flash SMS\n" \ + diff --git a/release/src/router/uqmi/commands.c b/release/src/router/uqmi/commands.c new file mode 100644 index 0000000000..b1b54d70b8 --- /dev/null +++ b/release/src/router/uqmi/commands.c @@ -0,0 +1,264 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2014-2015 Felix Fietkau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "uqmi.h" +#include "commands.h" + +static struct blob_buf status; +bool single_line = false; + +static void no_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ +} + +static void cmd_version_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + struct qmi_ctl_get_version_info_response res; + void *c; + char name_buf[16]; + int i; + + qmi_parse_ctl_get_version_info_response(msg, &res); + + c = blobmsg_open_table(&status, NULL); + for (i = 0; i < res.data.service_list_n; i++) { + sprintf(name_buf, "service_%d", res.data.service_list[i].service); + blobmsg_printf(&status, name_buf, "%d,%d", + res.data.service_list[i].major_version, + res.data.service_list[i].minor_version); + } + blobmsg_close_table(&status, c); +} + +static enum qmi_cmd_result +cmd_version_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + qmi_set_ctl_get_version_info_request(msg); + return QMI_CMD_REQUEST; +} + +#define cmd_get_client_id_cb no_cb +static enum qmi_cmd_result +cmd_get_client_id_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + QmiService svc = qmi_service_get_by_name(arg); + + if (svc < 0) { + fprintf(stderr, "Invalid service name '%s'\n", arg); + return QMI_CMD_EXIT; + } + + if (qmi_service_connect(qmi, svc, -1)) { + fprintf(stderr, "Failed to connect to service\n"); + return QMI_CMD_EXIT; + } + + printf("%d\n", qmi_service_get_client_id(qmi, svc)); + return QMI_CMD_DONE; +} + +#define cmd_set_client_id_cb no_cb +static enum qmi_cmd_result +cmd_set_client_id_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + QmiService svc; + int id; + char *s; + + s = strchr(arg, ','); + if (!s) { + fprintf(stderr, "Invalid argument\n"); + return QMI_CMD_EXIT; + } + *s = 0; + s++; + + id = strtoul(s, &s, 0); + if (s && *s) { + fprintf(stderr, "Invalid argument\n"); + return QMI_CMD_EXIT; + } + + svc = qmi_service_get_by_name(arg); + if (svc < 0) { + fprintf(stderr, "Invalid service name '%s'\n", arg); + return QMI_CMD_EXIT; + } + + if (qmi_service_connect(qmi, svc, id)) { + fprintf(stderr, "Failed to connect to service\n"); + return QMI_CMD_EXIT; + } + + return QMI_CMD_DONE; +} + +static int +qmi_get_array_idx(const char **array, int size, const char *str) +{ + int i; + + for (i = 0; i < size; i++) { + if (!array[i]) + continue; + + if (!strcmp(array[i], str)) + return i; + } + + return -1; +} + +#define cmd_ctl_set_data_format_cb no_cb +static enum qmi_cmd_result +cmd_ctl_set_data_format_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) +{ + struct qmi_ctl_set_data_format_request sreq = {}; + const char *modes[] = { + [QMI_CTL_DATA_LINK_PROTOCOL_802_3] = "802.3", + [QMI_CTL_DATA_LINK_PROTOCOL_RAW_IP] = "raw-ip", + }; + int mode = qmi_get_array_idx(modes, ARRAY_SIZE(modes), arg); + + if (mode < 0) { + uqmi_add_error("Invalid mode (modes: 802.3, raw-ip)"); + return QMI_CMD_EXIT; + } + + qmi_set_ctl_set_data_format_request(msg, &sreq); + return QMI_CMD_DONE; +} + +#include "commands-wds.c" +#include "commands-dms.c" +#include "commands-nas.c" +#include "commands-wms.c" +#include "commands-wda.c" + +#define __uqmi_command(_name, _optname, _arg, _type) \ + [__UQMI_COMMAND_##_name] = { \ + .name = #_optname, \ + .type = _type, \ + .prepare = cmd_##_name##_prepare, \ + .cb = cmd_##_name##_cb, \ + } + +const struct uqmi_cmd_handler uqmi_cmd_handler[__UQMI_COMMAND_LAST] = { + __uqmi_commands +}; +#undef __uqmi_command + +static struct uqmi_cmd *cmds; +static int n_cmds; + +void uqmi_add_command(char *arg, int cmd) +{ + int idx = n_cmds++; + + cmds = realloc(cmds, n_cmds * sizeof(*cmds)); + cmds[idx].handler = &uqmi_cmd_handler[cmd]; + cmds[idx].arg = optarg; +} + +static void uqmi_print_result(struct blob_attr *data) +{ + char *str; + + if (!blob_len(data)) + return; + + str = blobmsg_format_json_indent(blob_data(data), false, single_line ? -1 : 0); + if (!str) + return; + + printf("%s\n", str); + free(str); +} + +static bool __uqmi_run_commands(struct qmi_dev *qmi, bool option) +{ + static char buf[2048]; + static struct qmi_request req; + int i; + + for (i = 0; i < n_cmds; i++) { + enum qmi_cmd_result res; + bool cmd_option = cmds[i].handler->type == CMD_TYPE_OPTION; + bool do_break = false; + + if (cmd_option != option) + continue; + + blob_buf_init(&status, 0); + if (cmds[i].handler->type > QMI_SERVICE_CTL && + qmi_service_connect(qmi, cmds[i].handler->type, -1)) { + uqmi_add_error("Failed to connect to service"); + res = QMI_CMD_EXIT; + } else { + res = cmds[i].handler->prepare(qmi, &req, (void *) buf, cmds[i].arg); + } + + if (res == QMI_CMD_REQUEST) { + qmi_request_start(qmi, &req, (void *) buf, cmds[i].handler->cb); + req.no_error_cb = true; + if (qmi_request_wait(qmi, &req)) { + uqmi_add_error(qmi_get_error_str(req.ret)); + do_break = true; + } + } else if (res == QMI_CMD_EXIT) { + do_break = true; + } + + uqmi_print_result(status.head); + if (do_break) + return false; + } + return true; +} + +int uqmi_add_error(const char *msg) +{ + blobmsg_add_string(&status, NULL, msg); + return QMI_CMD_EXIT; +} + +bool uqmi_run_commands(struct qmi_dev *qmi) +{ + bool ret; + + ret = __uqmi_run_commands(qmi, true) && + __uqmi_run_commands(qmi, false); + + free(cmds); + cmds = NULL; + n_cmds = 0; + + return ret; +} diff --git a/release/src/router/uqmi/commands.h b/release/src/router/uqmi/commands.h new file mode 100644 index 0000000000..1c9b5d613b --- /dev/null +++ b/release/src/router/uqmi/commands.h @@ -0,0 +1,79 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2014-2015 Felix Fietkau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#ifndef __UQMI_COMMANDS_H +#define __UQMI_COMMANDS_H + +#include +#include "commands-wds.h" +#include "commands-dms.h" +#include "commands-nas.h" +#include "commands-wms.h" +#include "commands-wda.h" + +enum qmi_cmd_result { + QMI_CMD_DONE, + QMI_CMD_REQUEST, + QMI_CMD_EXIT, +}; + +enum { + CMD_TYPE_OPTION = -1, +}; + +struct uqmi_cmd_handler { + const char *name; + int type; + + enum qmi_cmd_result (*prepare)(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg); + void (*cb)(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg); +}; + +struct uqmi_cmd { + const struct uqmi_cmd_handler *handler; + char *arg; +}; + +#define __uqmi_commands \ + __uqmi_command(version, get-versions, no, QMI_SERVICE_CTL), \ + __uqmi_command(set_client_id, set-client-id, required, CMD_TYPE_OPTION), \ + __uqmi_command(get_client_id, get-client-id, required, QMI_SERVICE_CTL), \ + __uqmi_command(ctl_set_data_format, set-data-format, required, QMI_SERVICE_CTL), \ + __uqmi_wds_commands, \ + __uqmi_dms_commands, \ + __uqmi_nas_commands, \ + __uqmi_wms_commands, \ + __uqmi_wda_commands + +#define __uqmi_command(_name, _optname, _arg, _option) __UQMI_COMMAND_##_name +enum uqmi_command { + __uqmi_commands, + __UQMI_COMMAND_LAST +}; +#undef __uqmi_command + +extern bool single_line; +extern const struct uqmi_cmd_handler uqmi_cmd_handler[]; +void uqmi_add_command(char *arg, int longidx); +bool uqmi_run_commands(struct qmi_dev *qmi); +int uqmi_add_error(const char *msg); + +#endif diff --git a/release/src/router/uqmi/data/gen-code.pl b/release/src/router/uqmi/data/gen-code.pl new file mode 100755 index 0000000000..f45d28a053 --- /dev/null +++ b/release/src/router/uqmi/data/gen-code.pl @@ -0,0 +1,450 @@ +#!/usr/bin/env perl +use strict; + +use FindBin '$Bin'; +require "$Bin/gen-common.pm"; + +our %tlv_types; +our $ctl; + +my $data = get_json(); +my $varsize_field; + +my %tlv_get = ( + gint8 => "*(int8_t *) get_next(1)", + guint8 => "*(uint8_t *) get_next(1)", + gint16 => "le16_to_cpu(*(uint16_t *) get_next(2))", + guint16 => "le16_to_cpu(*(uint16_t *) get_next(2))", + gint32 => "le32_to_cpu(*(uint32_t *) get_next(4))", + guint32 => "le32_to_cpu(*(uint32_t *) get_next(4))", + gint64 => "le64_to_cpu(*(uint64_t *) get_next(8))", + guint64 => "le64_to_cpu(*(uint64_t *) get_next(8))", + gfloat => "({ uint32_t data = le32_to_cpu(*(uint32_t *) get_next(4)); float _val; memcpy(&_val, &data, sizeof(_val)); _val; })" +); + +my %tlv_get_be = ( + gint16 => "be16_to_cpu(*(uint16_t *) get_next(2))", + guint16 => "be16_to_cpu(*(uint16_t *) get_next(2))", + gint32 => "be32_to_cpu(*(uint32_t *) get_next(4))", + guint32 => "be32_to_cpu(*(uint32_t *) get_next(4))", + gint64 => "be64_to_cpu(*(uint64_t *) get_next(8))", + guint64 => "be64_to_cpu(*(uint64_t *) get_next(8))", +); + +sub gen_tlv_parse_field($$$$) { + my $var = shift; + my $elem = shift; + my $n_indent = shift; + my $iterator = shift; + my $data = ""; + + my $indent = "\t" x ($n_indent + 3); + my $use_iterator = 0; + my $field = 0; + + my $type = $elem->{"format"}; + + $varsize_field and die "Cannot place fields after a variable-sized field (var: $var, field: $varsize_field)\n"; + + my $val; + if ($elem->{endian} eq 'network') { + $val = $tlv_get_be{$type}; + } else { + $val = $tlv_get{$type}; + } + + if ($val) { + return $indent."$var = $val;\n"; + } elsif ($type eq "array") { + my $size; + my $cur_varsize_field; + my $var_data; + my $var_iterator; + + if ($elem->{"fixed-size"}) { + $size = $elem->{"fixed-size"}; + $data .= $indent."for ($iterator = 0; $iterator < $size; $iterator\++) {\n"; + + ($var_data, $var_iterator) = + gen_tlv_parse_field($var."[$iterator]", $elem->{"array-element"}, $n_indent + 1, "i$iterator"); + + } else { + my $prefix = $elem->{"size-prefix-format"}; + $prefix or $prefix = 'guint8'; + + $size = $tlv_get{$prefix}; + die "Unknown size element type '$prefix'" if not defined $size; + + ($var_data, $var_iterator) = + gen_tlv_parse_field($var."[$var\_n]", $elem->{"array-element"}, $n_indent + 1, "i$iterator"); + + $var_data .= $indent."\t$var\_n++;\n"; + $data .= $indent."$iterator = $size;\n"; + $data .= $indent."$var = __qmi_alloc_static($iterator * sizeof($var\[0]));\n"; + $data .= $indent."while($iterator\-- > 0) {\n"; + } + + $var_iterator and $data .= $indent."\tunsigned int i$iterator;\n"; + $data .= $var_data; + $data .= $indent."}\n"; + + $varsize_field = $cur_varsize_field; + + return $data, 1; + } elsif ($type eq "struct" or $type eq "sequence") { + foreach my $field (@{$elem->{contents}}) { + my $field_cname = gen_cname($field->{name}); + my ($var_data, $var_iterator) = + gen_tlv_parse_field("$var.$field_cname", $field, $n_indent, $iterator); + + $data .= $var_data; + $var_iterator and $use_iterator = 1; + } + return $data, $use_iterator; + } elsif ($type eq "string") { + my $size = $elem->{"fixed-size"}; + $size or do { + my $prefix = $elem->{"size-prefix-format"}; + $prefix or do { + $elem->{type} eq 'TLV' or $prefix = 'guint8'; + }; + + if ($prefix) { + $size = $tlv_get{$prefix}; + } else { + $size = "cur_tlv_len - ofs"; + $varsize_field = $var; + } + }; + + $data .= $indent."$iterator = $size;\n"; + my $maxsize = $elem->{"max-size"}; + $maxsize and do { + $data .= $indent."if ($iterator > $maxsize)\n"; + $data .= $indent."\t$iterator = $maxsize;\n"; + }; + $data .= $indent.$var." = __qmi_copy_string(get_next($iterator), $iterator);\n"; + return $data, 1; + } elsif ($type eq "guint-sized") { + my $size = $elem->{"guint-size"}; + return $indent."$var = ({ uint64_t var; memcpy(&var, get_next($size), $size); le64_to_cpu(var); });\n"; + } else { + die "Invalid type $type for variable $var"; + } +} + +sub gen_tlv_type($$$) { + my $cname = shift; + my $elem = shift; + my $idx = shift; + my $idx_word = "found[".int($idx / 32)."]"; + my $idx_bit = "(1 << ".($idx % 32).")"; + + my $type = $elem->{"format"}; + my $id = $elem->{"id"}; + my $data = ""; + undef $varsize_field; + my $indent = "\t\t\t"; + + $type or return undef; + + print <data.$cname", $elem, 0, "i"); + print "$var_data"; + } elsif ($type eq "array") { + $elem->{"fixed-size"} and $data = $indent."res->set.$cname = 1;\n"; + my ($var_data, $var_iterator) = + gen_tlv_parse_field("res->data.$cname", $elem, 0, "i"); + print "$data$var_data\n"; + } elsif ($type eq "sequence" or $type eq "struct") { + my ($var_data, $var_iterator) = + gen_tlv_parse_field("res->data.$cname", $elem, 0, "i"); + + print $indent."res->set.$cname = 1;\n".$var_data; + } + print <$type.tlv; + unsigned int tlv_len = le16_to_cpu(msg->$type.tlv_len); +EOF + + if (gen_has_types($data)) { + my $n_bits = scalar @$data; + my $n_words = int(($n_bits + 31) / 32); + my $i = 0; + + print <len); + unsigned int ofs = 0; + + switch(tlv->type) { +EOF + foreach my $field (@$data) { + my $cname = gen_cname($field->{name}); + gen_tlv_type($cname, $field, $i++); + } + + print <type, le16_to_cpu(tlv->len)); + return QMI_ERROR_INVALID_DATA; +EOF + } else { + print < sub { my $a = shift; my $b = shift; print "*(uint8_t *) $a = $b;\n" }, + guint16 => sub { my $a = shift; my $b = shift; print "*(uint16_t *) $a = cpu_to_le16($b);\n" }, + guint32 => sub { my $a = shift; my $b = shift; print "*(uint32_t *) $a = cpu_to_le32($b);\n" }, +); + +my %tlv_put = ( + gint8 => sub { my $a = shift; "put_tlv_var(uint8_t, $a, 1);\n" }, + guint8 => sub { my $a = shift; "put_tlv_var(uint8_t, $a, 1);\n" }, + gint16 => sub { my $a = shift; "put_tlv_var(uint16_t, cpu_to_le16($a), 2);\n" }, + guint16 => sub { my $a = shift; "put_tlv_var(uint16_t, cpu_to_le16($a), 2);\n" }, + gint32 => sub { my $a = shift; "put_tlv_var(uint32_t, cpu_to_le32($a), 4);\n" }, + guint32 => sub { my $a = shift; "put_tlv_var(uint32_t, cpu_to_le32($a), 4);\n" }, + gint64 => sub { my $a = shift; "put_tlv_var(uint64_t, cpu_to_le64($a), 8);\n" }, + guint64 => sub { my $a = shift; "put_tlv_var(uint64_t, cpu_to_le64($a), 8);\n" }, +); + +my %tlv_put_be = ( + gint16 => sub { my $a = shift; "put_tlv_var(uint16_t, cpu_to_be16($a), 2);\n" }, + guint16 => sub { my $a = shift; "put_tlv_var(uint16_t, cpu_to_be16($a), 2);\n" }, + gint32 => sub { my $a = shift; "put_tlv_var(uint32_t, cpu_to_be32($a), 4);\n" }, + guint32 => sub { my $a = shift; "put_tlv_var(uint32_t, cpu_to_be32($a), 4);\n" }, + gint64 => sub { my $a = shift; "put_tlv_var(uint64_t, cpu_to_be64($a), 8);\n" }, + guint64 => sub { my $a = shift; "put_tlv_var(uint64_t, cpu_to_be64($a), 8);\n" }, +); + +sub gen_tlv_val_set($$$$$) +{ + my $cname = shift; + my $elem = shift; + my $indent = shift; + my $iterator = shift; + my $cond = shift; + my $prev_cond; + + my $type = $elem->{format}; + my $data = ""; + + my $put; + if ($elem->{endian} eq 'network') { + $put = $tlv_put_be{$type}; + } else { + $put = $tlv_put{$type}; + } + $put and return $indent.&$put($cname); + + $type eq 'array' and do { + my $size = $elem->{"fixed-size"}; + + $size or do { + $cond and $$cond = $cname; + $size = $cname."_n"; + + my $prefix = $elem->{"size-prefix-format"}; + $prefix or $prefix = 'gint8'; + + $put = $tlv_put{$prefix}; + $put or die "Unknown size prefix type $prefix\n"; + + $data .= $indent.&$put($size); + }; + + $data .= $indent."for ($iterator = 0; $iterator < $size; $iterator++) {\n"; + my ($var_data, $var_iterator) = + gen_tlv_val_set($cname."[$iterator]", $elem->{"array-element"}, "$indent\t", "i$iterator", undef); + + $var_iterator and $data .= $indent."\tunsigned int i$iterator;\n"; + $data .= $var_data; + $data .= $indent."}\n"; + + return $data, 1; + }; + + $type eq 'string' and do { + $cond and $$cond = $cname; + + my $len = $elem->{"fixed-size"}; + $len or $len = "strlen($cname)"; + + $data .= $indent."$iterator = $len;\n"; + + $len = $elem->{"max-size"}; + $len and do { + $data .= $indent."if ($iterator > $len)\n"; + $data .= $indent."\t$iterator = $len;\n"; + }; + + my $prefix = $elem->{"size-prefix-format"}; + $prefix or do { + $elem->{"type"} eq 'TLV' or $prefix = 'guint8'; + }; + + $prefix and do { + my $put = $tlv_put{$prefix} or die "Unknown size prefix format $prefix"; + $data .= $indent.&$put("$iterator"); + }; + + $data .= $indent."strncpy(__qmi_alloc_static($iterator), $cname, $iterator);\n"; + + return $data, 1; + }; + + ($type eq 'sequence' or $type eq 'struct') and do { + my $use_iterator; + + foreach my $field (@{$elem->{contents}}) { + my $field_cname = gen_cname($field->{name}); + my ($var_data, $var_iterator) = + gen_tlv_val_set("$cname.$field_cname", $field, $indent, $iterator, undef); + + $var_iterator and $use_iterator = 1; + $data .= $var_data; + } + return $data, $use_iterator; + }; + + die "Unknown type $type"; +} + +sub gen_tlv_attr_set($$) +{ + my $cname = shift; + my $elem = shift; + my $indent = "\t"; + my $data = ""; + my $iterator = ""; + my $size_var = ""; + my $id = $elem->{id}; + + my $cond = "req->set.$cname"; + my ($var_data, $use_iterator) = + gen_tlv_val_set("req->data.$cname", $elem, "\t\t", "i", \$cond); + $use_iterator and $iterator = "\t\tunsigned int i;\n"; + + $data = <{service}; + my $id = $data->{id}; + + $service eq 'CTL' and $type = 'ctl'; + + print gen_tlv_set_func($name, $fields)."\n"; + print <$type.message = cpu_to_le16($id); + +EOF + foreach my $field (@$fields) { + my $cname = gen_cname($field->{name}); + gen_tlv_attr_set($cname, $field); + } + + print < +#include +#include "qmi-message.h" + +#define get_next(_size) ({ void *_buf = &tlv->data[ofs]; ofs += _size; if (ofs > cur_tlv_len) goto error_len; _buf; }) +#define copy_tlv(_val, _size) \\ + do { \\ + unsigned int __size = _size; \\ + if (__size > 0) \\ + memcpy(__qmi_alloc_static(__size), _val, __size); \\ + } while (0); + +#define put_tlv_var(_type, _val, _size) \\ + do { \\ + _type __var = _val; \\ + copy_tlv(&__var, _size); \\ + } while(0) + +EOF + +gen_foreach_message_type($data, \&gen_set_func, \&gen_parse_func); diff --git a/release/src/router/uqmi/data/gen-common.pm b/release/src/router/uqmi/data/gen-common.pm new file mode 100644 index 0000000000..6c3492f25a --- /dev/null +++ b/release/src/router/uqmi/data/gen-common.pm @@ -0,0 +1,89 @@ +use lib "$Bin/lib"; +use JSON; + +@ARGV < 2 and die "Usage: $0 \n"; +my $prefix = shift @ARGV; + +our $ctl; +our %tlv_types = ( + gint8 => "int8_t", + guint8 => "uint8_t", + gint16 => "int16_t", + guint16 => "uint16_t", + gint32 => "int32_t", + guint32 => "uint32_t", + gint64 => "int64_t", + guint64 => "uint64_t", + gfloat => "float", + gboolean => "bool", +); + +$prefix eq 'ctl_' and $ctl = 1; + +sub get_json() { + local $/; + my $json = <>; + $json =~ s/^\s*\/\/.*$//mg; + return decode_json($json); +} + +sub gen_cname($) { + my $name = shift; + + $name =~ s/[^a-zA-Z0-9_]/_/g; + return lc($name); +} + +sub gen_has_types($) { + my $data = shift; + + foreach my $field (@$data) { + my $type = $field->{"format"}; + $type and return 1; + } + return undef +} + +sub gen_tlv_set_func($$) { + my $name = shift; + my $data = shift; + + $name = gen_cname($name); + if (gen_has_types($data)) { + return "int qmi_set_$name(struct qmi_msg *msg, struct qmi_$name *req)" + } else { + return "int qmi_set_$name(struct qmi_msg *msg)" + } +} + +sub gen_tlv_parse_func($$) { + my $name = shift; + my $data = shift; + + $name = gen_cname($name); + if (gen_has_types($data)) { + return "int qmi_parse_$name(struct qmi_msg *msg, struct qmi_$name *res)" + } else { + return "int qmi_parse_$name(struct qmi_msg *msg)" + } +} + +sub gen_foreach_message_type($$$) +{ + my $data = shift; + my $req_sub = shift; + my $res_sub = shift; + + foreach my $entry (@$data) { + my $args = []; + my $fields = []; + + next if $entry->{type} ne 'Message'; + next if not defined $entry->{input} and not defined $entry->{output}; + + &$req_sub($prefix.$entry->{name}." Request", $entry->{input}, $entry); + &$res_sub($prefix.$entry->{name}." Response", $entry->{output}, $entry); + } +} + +1; diff --git a/release/src/router/uqmi/data/gen-error-list.pl b/release/src/router/uqmi/data/gen-error-list.pl new file mode 100755 index 0000000000..770c162522 --- /dev/null +++ b/release/src/router/uqmi/data/gen-error-list.pl @@ -0,0 +1,41 @@ +#!/usr/bin/env perl +use strict; +my $doc_start; +my $error_data; +my $line; +my @errors; + +while ($line = <>) { + chomp $line; + + $line =~ /^\/\*\*/ and do { + $doc_start = 1; + next; + }; + + $line =~ /^\s*\*\// and undef $error_data; + + $doc_start and $line =~ /^\s*\*\s*QmiProtocolError:/ and do { + $error_data = 1; + undef $doc_start; + next; + }; + undef $doc_start; + + $line =~ /^\s*\*\s*@(.+): (.+)\./ and push @errors, [ $1, $2 ]; +} + +@errors > 0 or die "No data found\n"; + +print <[0].", \"".$error->[1]."\" },\n"; +} +print <{"format"}; + my $ptype = $elem->{"public-format"}; + my $data; + + $type or return undef; + $ptype or $ptype = $type; + + if ($type eq "guint-sized") { + my $size = $elem->{"guint-size"}; + + if ($size > 4 and $size < 8) { + $ptype = "guint64"; + } elsif ($size > 2) { + $ptype = "guint32"; + } else { + die "Invalid size for guint-sized"; + } + } + + if ($tlv_types{$ptype}) { + return $indent.$tlv_types{$ptype}." $cname;"; + } elsif ($tlv_types{$type}) { + return $indent."$ptype $cname;"; + } elsif ($type eq "string") { + return $indent."char *$cname;", 1; + } elsif ($type eq "array") { + if ($elem->{"fixed-size"}) { + my $len_f = '['.$elem->{"fixed-size"}.']'; + return gen_tlv_type("$cname$len_f", $elem->{"array-element"}, $indent); + } + my ($type, $no_set_field) = gen_tlv_type("*$cname", $elem->{"array-element"}, $indent); + return undef if not defined $type; + return $indent."unsigned int $cname\_n;$type", 1; + } elsif ($type eq "sequence" or $type eq "struct") { + my $contents = $elem->{"contents"}; + my $data = "struct {"; + + foreach my $field (@$contents) { + my $_cname = gen_cname($field->{name}); + my ($_data, $no_set_field) = gen_tlv_type($_cname, $field, "$indent\t"); + $data .= $_data; + } + return $indent.$data.$indent."} $cname;"; + } else { + die "Unknown type: $ptype\n"; + } +} + +sub gen_tlv_struct($$) { + my $name = shift; + my $data = shift; + my $_set = ""; + my $_data = ""; + + foreach my $field (@$data) { + my $cname = gen_cname($field->{name}); + my ($data, $no_set_field) = gen_tlv_type($cname, $field, "\n\t\t"); + + next if not defined $data; + $_data .= $data; + + next if $no_set_field; + $_set .= "\n\t\tunsigned int $cname : 1;"; + } + + $name = gen_cname($name); + + $_data or return; + + $_set .= "\n\t"; + $_data .= "\n\t"; + + print <support_by_pp(@PPOnlyMethods) if ($JSON::Backend eq $Module_XS); + } + next; + } + elsif ($tag eq '-no_export') { + $no_export++, next; + } + elsif ( $tag eq '-convert_blessed_universally' ) { + eval q| + require B; + *UNIVERSAL::TO_JSON = sub { + my $b_obj = B::svref_2object( $_[0] ); + return $b_obj->isa('B::HV') ? { %{ $_[0] } } + : $b_obj->isa('B::AV') ? [ @{ $_[0] } ] + : undef + ; + } + | if ( !$_UNIV_CONV_BLESSED++ ); + next; + } + push @what_to_export, $tag; + } + + return if ($no_export); + + __PACKAGE__->export_to_level(1, $pkg, @what_to_export); +} + + +# OBSOLETED + +sub jsonToObj { + my $alternative = 'from_json'; + if (defined $_[0] and UNIVERSAL::isa($_[0], 'JSON')) { + shift @_; $alternative = 'decode'; + } + Carp::carp "'jsonToObj' will be obsoleted. Please use '$alternative' instead."; + return JSON::from_json(@_); +}; + +sub objToJson { + my $alternative = 'to_json'; + if (defined $_[0] and UNIVERSAL::isa($_[0], 'JSON')) { + shift @_; $alternative = 'encode'; + } + Carp::carp "'objToJson' will be obsoleted. Please use '$alternative' instead."; + JSON::to_json(@_); +}; + + +# INTERFACES + +sub to_json ($@) { + if ( + ref($_[0]) eq 'JSON' + or (@_ > 2 and $_[0] eq 'JSON') + ) { + Carp::croak "to_json should not be called as a method."; + } + my $json = new JSON; + + if (@_ == 2 and ref $_[1] eq 'HASH') { + my $opt = $_[1]; + for my $method (keys %$opt) { + $json->$method( $opt->{$method} ); + } + } + + $json->encode($_[0]); +} + + +sub from_json ($@) { + if ( ref($_[0]) eq 'JSON' or $_[0] eq 'JSON' ) { + Carp::croak "from_json should not be called as a method."; + } + my $json = new JSON; + + if (@_ == 2 and ref $_[1] eq 'HASH') { + my $opt = $_[1]; + for my $method (keys %$opt) { + $json->$method( $opt->{$method} ); + } + } + + return $json->decode( $_[0] ); +} + + +sub true { $JSON::true } + +sub false { $JSON::false } + +sub null { undef; } + + +sub require_xs_version { $XS_Version; } + +sub backend { + my $proto = shift; + $JSON::Backend; +} + +#*module = *backend; + + +sub is_xs { + return $_[0]->module eq $Module_XS; +} + + +sub is_pp { + return not $_[0]->xs; +} + + +sub pureperl_only_methods { @PPOnlyMethods; } + + +sub property { + my ($self, $name, $value) = @_; + + if (@_ == 1) { + my %props; + for $name (@Properties) { + my $method = 'get_' . $name; + if ($name eq 'max_size') { + my $value = $self->$method(); + $props{$name} = $value == 1 ? 0 : $value; + next; + } + $props{$name} = $self->$method(); + } + return \%props; + } + elsif (@_ > 3) { + Carp::croak('property() can take only the option within 2 arguments.'); + } + elsif (@_ == 2) { + if ( my $method = $self->can('get_' . $name) ) { + if ($name eq 'max_size') { + my $value = $self->$method(); + return $value == 1 ? 0 : $value; + } + $self->$method(); + } + } + else { + $self->$name($value); + } + +} + + + +# INTERNAL + +sub _load_xs { + my $opt = shift; + + $JSON::DEBUG and Carp::carp "Load $Module_XS."; + + # if called after install module, overload is disable.... why? + JSON::Boolean::_overrride_overload($Module_XS); + JSON::Boolean::_overrride_overload($Module_PP); + + eval qq| + use $Module_XS $XS_Version (); + |; + + if ($@) { + if (defined $opt and $opt & $_INSTALL_DONT_DIE) { + $JSON::DEBUG and Carp::carp "Can't load $Module_XS...($@)"; + return 0; + } + Carp::croak $@; + } + + unless (defined $opt and $opt & $_INSTALL_ONLY) { + _set_module( $JSON::Backend = $Module_XS ); + my $data = join("", ); # this code is from Jcode 2.xx. + close(DATA); + eval $data; + JSON::Backend::XS->init; + } + + return 1; +}; + + +sub _load_pp { + my $opt = shift; + my $backend = $_USSING_bpPP ? $Module_bp : $Module_PP; + + $JSON::DEBUG and Carp::carp "Load $backend."; + + # if called after install module, overload is disable.... why? + JSON::Boolean::_overrride_overload($Module_XS); + JSON::Boolean::_overrride_overload($backend); + + if ( $_USSING_bpPP ) { + eval qq| require $backend |; + } + else { + eval qq| use $backend $PP_Version () |; + } + + if ($@) { + if ( $backend eq $Module_PP ) { + $JSON::DEBUG and Carp::carp "Can't load $Module_PP ($@), so try to load $Module_bp"; + $_USSING_bpPP++; + $backend = $Module_bp; + JSON::Boolean::_overrride_overload($backend); + local $^W; # if PP installed but invalid version, backportPP redifines methods. + eval qq| require $Module_bp |; + } + Carp::croak $@ if $@; + } + + unless (defined $opt and $opt & $_INSTALL_ONLY) { + _set_module( $JSON::Backend = $Module_PP ); # even if backportPP, set $Backend with 'JSON::PP' + JSON::Backend::PP->init; + } +}; + + +sub _set_module { + return if defined $JSON::true; + + my $module = shift; + + local $^W; + no strict qw(refs); + + $JSON::true = ${"$module\::true"}; + $JSON::false = ${"$module\::false"}; + + push @JSON::ISA, $module; + push @{"$module\::Boolean::ISA"}, qw(JSON::Boolean); + + *{"JSON::is_bool"} = \&{"$module\::is_bool"}; + + for my $method ($module eq $Module_XS ? @PPOnlyMethods : @XSOnlyMethods) { + *{"JSON::$method"} = sub { + Carp::carp("$method is not supported in $module."); + $_[0]; + }; + } + + return 1; +} + + + +# +# JSON Boolean +# + +package JSON::Boolean; + +my %Installed; + +sub _overrride_overload { + return if ($Installed{ $_[0] }++); + + my $boolean = $_[0] . '::Boolean'; + + eval sprintf(q| + package %s; + use overload ( + '""' => sub { ${$_[0]} == 1 ? 'true' : 'false' }, + 'eq' => sub { + my ($obj, $op) = ref ($_[0]) ? ($_[0], $_[1]) : ($_[1], $_[0]); + if ($op eq 'true' or $op eq 'false') { + return "$obj" eq 'true' ? 'true' eq $op : 'false' eq $op; + } + else { + return $obj ? 1 == $op : 0 == $op; + } + }, + ); + |, $boolean); + + if ($@) { Carp::croak $@; } + + return 1; +} + + +# +# Helper classes for Backend Module (PP) +# + +package JSON::Backend::PP; + +sub init { + local $^W; + no strict qw(refs); # this routine may be called after JSON::Backend::XS init was called. + *{"JSON::decode_json"} = \&{"JSON::PP::decode_json"}; + *{"JSON::encode_json"} = \&{"JSON::PP::encode_json"}; + *{"JSON::PP::is_xs"} = sub { 0 }; + *{"JSON::PP::is_pp"} = sub { 1 }; + return 1; +} + +# +# To save memory, the below lines are read only when XS backend is used. +# + +package JSON; + +1; +__DATA__ + + +# +# Helper classes for Backend Module (XS) +# + +package JSON::Backend::XS; + +use constant INDENT_LENGTH_FLAG => 15 << 12; + +use constant UNSUPPORTED_ENCODE_FLAG => { + ESCAPE_SLASH => 0x00000010, + ALLOW_BIGNUM => 0x00000020, + AS_NONBLESSED => 0x00000040, + EXPANDED => 0x10000000, # for developer's +}; + +use constant UNSUPPORTED_DECODE_FLAG => { + LOOSE => 0x00000001, + ALLOW_BIGNUM => 0x00000002, + ALLOW_BAREKEY => 0x00000004, + ALLOW_SINGLEQUOTE => 0x00000008, + EXPANDED => 0x20000000, # for developer's +}; + + +sub init { + local $^W; + no strict qw(refs); + *{"JSON::decode_json"} = \&{"JSON::XS::decode_json"}; + *{"JSON::encode_json"} = \&{"JSON::XS::encode_json"}; + *{"JSON::XS::is_xs"} = sub { 1 }; + *{"JSON::XS::is_pp"} = sub { 0 }; + return 1; +} + + +sub support_by_pp { + my ($class, @methods) = @_; + + local $^W; + no strict qw(refs); + + my $JSON_XS_encode_orignal = \&JSON::XS::encode; + my $JSON_XS_decode_orignal = \&JSON::XS::decode; + my $JSON_XS_incr_parse_orignal = \&JSON::XS::incr_parse; + + *JSON::XS::decode = \&JSON::Backend::XS::Supportable::_decode; + *JSON::XS::encode = \&JSON::Backend::XS::Supportable::_encode; + *JSON::XS::incr_parse = \&JSON::Backend::XS::Supportable::_incr_parse; + + *{JSON::XS::_original_decode} = $JSON_XS_decode_orignal; + *{JSON::XS::_original_encode} = $JSON_XS_encode_orignal; + *{JSON::XS::_original_incr_parse} = $JSON_XS_incr_parse_orignal; + + push @JSON::Backend::XS::Supportable::ISA, 'JSON'; + + my $pkg = 'JSON::Backend::XS::Supportable'; + + *{JSON::new} = sub { + my $proto = new JSON::XS; $$proto = 0; + bless $proto, $pkg; + }; + + + for my $method (@methods) { + my $flag = uc($method); + my $type |= (UNSUPPORTED_ENCODE_FLAG->{$flag} || 0); + $type |= (UNSUPPORTED_DECODE_FLAG->{$flag} || 0); + + next unless($type); + + $pkg->_make_unsupported_method($method => $type); + } + + push @{"JSON::XS::Boolean::ISA"}, qw(JSON::PP::Boolean); + push @{"JSON::PP::Boolean::ISA"}, qw(JSON::Boolean); + + $JSON::DEBUG and Carp::carp("set -support_by_pp mode."); + + return 1; +} + + + + +# +# Helper classes for XS +# + +package JSON::Backend::XS::Supportable; + +$Carp::Internal{'JSON::Backend::XS::Supportable'} = 1; + +sub _make_unsupported_method { + my ($pkg, $method, $type) = @_; + + local $^W; + no strict qw(refs); + + *{"$pkg\::$method"} = sub { + local $^W; + if (defined $_[1] ? $_[1] : 1) { + ${$_[0]} |= $type; + } + else { + ${$_[0]} &= ~$type; + } + $_[0]; + }; + + *{"$pkg\::get_$method"} = sub { + ${$_[0]} & $type ? 1 : ''; + }; + +} + + +sub _set_for_pp { + JSON::_load_pp( $_INSTALL_ONLY ); + + my $type = shift; + my $pp = new JSON::PP; + my $prop = $_[0]->property; + + for my $name (keys %$prop) { + $pp->$name( $prop->{$name} ? $prop->{$name} : 0 ); + } + + my $unsupported = $type eq 'encode' ? JSON::Backend::XS::UNSUPPORTED_ENCODE_FLAG + : JSON::Backend::XS::UNSUPPORTED_DECODE_FLAG; + my $flags = ${$_[0]} || 0; + + for my $name (keys %$unsupported) { + next if ($name eq 'EXPANDED'); # for developer's + my $enable = ($flags & $unsupported->{$name}) ? 1 : 0; + my $method = lc $name; + $pp->$method($enable); + } + + $pp->indent_length( $_[0]->get_indent_length ); + + return $pp; +} + +sub _encode { # using with PP encod + if (${$_[0]}) { + _set_for_pp('encode' => @_)->encode($_[1]); + } + else { + $_[0]->_original_encode( $_[1] ); + } +} + + +sub _decode { # if unsupported-flag is set, use PP + if (${$_[0]}) { + _set_for_pp('decode' => @_)->decode($_[1]); + } + else { + $_[0]->_original_decode( $_[1] ); + } +} + + +sub decode_prefix { # if unsupported-flag is set, use PP + _set_for_pp('decode' => @_)->decode_prefix($_[1]); +} + + +sub _incr_parse { + if (${$_[0]}) { + _set_for_pp('decode' => @_)->incr_parse($_[1]); + } + else { + $_[0]->_original_incr_parse( $_[1] ); + } +} + + +sub get_indent_length { + ${$_[0]} << 4 >> 16; +} + + +sub indent_length { + my $length = $_[1]; + + if (!defined $length or $length > 15 or $length < 0) { + Carp::carp "The acceptable range of indent_length() is 0 to 15."; + } + else { + local $^W; + $length <<= 12; + ${$_[0]} &= ~ JSON::Backend::XS::INDENT_LENGTH_FLAG; + ${$_[0]} |= $length; + *JSON::XS::encode = \&JSON::Backend::XS::Supportable::_encode; + } + + $_[0]; +} + + +1; +__END__ + +=head1 NAME + +JSON - JSON (JavaScript Object Notation) encoder/decoder + +=head1 SYNOPSIS + + use JSON; # imports encode_json, decode_json, to_json and from_json. + + # simple and fast interfaces (expect/generate UTF-8) + + $utf8_encoded_json_text = encode_json $perl_hash_or_arrayref; + $perl_hash_or_arrayref = decode_json $utf8_encoded_json_text; + + # OO-interface + + $json = JSON->new->allow_nonref; + + $json_text = $json->encode( $perl_scalar ); + $perl_scalar = $json->decode( $json_text ); + + $pretty_printed = $json->pretty->encode( $perl_scalar ); # pretty-printing + + # If you want to use PP only support features, call with '-support_by_pp' + # When XS unsupported feature is enable, using PP (de|en)code instead of XS ones. + + use JSON -support_by_pp; + + # option-acceptable interfaces (expect/generate UNICODE by default) + + $json_text = to_json( $perl_scalar, { ascii => 1, pretty => 1 } ); + $perl_scalar = from_json( $json_text, { utf8 => 1 } ); + + # Between (en|de)code_json and (to|from)_json, if you want to write + # a code which communicates to an outer world (encoded in UTF-8), + # recommend to use (en|de)code_json. + +=head1 VERSION + + 2.53 + +This version is compatible with JSON::XS B<2.27> and later. + + +=head1 NOTE + +JSON::PP was inculded in C distribution. +It comes to be a perl core module in Perl 5.14. +And L will be split away it. + +C distribution will inculde yet another JSON::PP modules. +They are JSNO::backportPP and so on. JSON.pm should work as it did at all. + +=head1 DESCRIPTION + + ************************** CAUTION ******************************** + * This is 'JSON module version 2' and there are many differences * + * to version 1.xx * + * Please check your applications useing old version. * + * See to 'INCOMPATIBLE CHANGES TO OLD VERSION' * + ******************************************************************* + +JSON (JavaScript Object Notation) is a simple data format. +See to L and C(L). + +This module converts Perl data structures to JSON and vice versa using either +L or L. + +JSON::XS is the fastest and most proper JSON module on CPAN which must be +compiled and installed in your environment. +JSON::PP is a pure-Perl module which is bundled in this distribution and +has a strong compatibility to JSON::XS. + +This module try to use JSON::XS by default and fail to it, use JSON::PP instead. +So its features completely depend on JSON::XS or JSON::PP. + +See to L. + +To distinguish the module name 'JSON' and the format type JSON, +the former is quoted by CEE (its results vary with your using media), +and the latter is left just as it is. + +Module name : C + +Format type : JSON + +=head2 FEATURES + +=over + +=item * correct unicode handling + +This module (i.e. backend modules) knows how to handle Unicode, documents +how and when it does so, and even documents what "correct" means. + +Even though there are limitations, this feature is available since Perl version 5.6. + +JSON::XS requires Perl 5.8.2 (but works correctly in 5.8.8 or later), so in older versions +C sholud call JSON::PP as the backend which can be used since Perl 5.005. + +With Perl 5.8.x JSON::PP works, but from 5.8.0 to 5.8.2, because of a Perl side problem, +JSON::PP works slower in the versions. And in 5.005, the Unicode handling is not available. +See to L for more information. + +See also to L +and L. + + +=item * round-trip integrity + +When you serialise a perl data structure using only data types supported +by JSON and Perl, the deserialised data structure is identical on the Perl +level. (e.g. the string "2.0" doesn't suddenly become "2" just because +it looks like a number). There I minor exceptions to this, read the +L section below to learn about those. + + +=item * strict checking of JSON correctness + +There is no guessing, no generating of illegal JSON texts by default, +and only JSON is accepted as input by default (the latter is a security +feature). + +See to L and L. + +=item * fast + +This module returns a JSON::XS object itself if available. +Compared to other JSON modules and other serialisers such as Storable, +JSON::XS usually compares favourably in terms of speed, too. + +If not available, C returns a JSON::PP object instead of JSON::XS and +it is very slow as pure-Perl. + +=item * simple to use + +This module has both a simple functional interface as well as an +object oriented interface interface. + +=item * reasonably versatile output formats + +You can choose between the most compact guaranteed-single-line format possible +(nice for simple line-based protocols), a pure-ASCII format (for when your transport +is not 8-bit clean, still supports the whole Unicode range), or a pretty-printed +format (for when you want to read that stuff). Or you can combine those features +in whatever way you like. + +=back + +=head1 FUNCTIONAL INTERFACE + +Some documents are copied and modified from L. +C and C are additional functions. + +=head2 encode_json + + $json_text = encode_json $perl_scalar + +Converts the given Perl data structure to a UTF-8 encoded, binary string. + +This function call is functionally identical to: + + $json_text = JSON->new->utf8->encode($perl_scalar) + +=head2 decode_json + + $perl_scalar = decode_json $json_text + +The opposite of C: expects an UTF-8 (binary) string and tries +to parse that as an UTF-8 encoded JSON text, returning the resulting +reference. + +This function call is functionally identical to: + + $perl_scalar = JSON->new->utf8->decode($json_text) + + +=head2 to_json + + $json_text = to_json($perl_scalar) + +Converts the given Perl data structure to a json string. + +This function call is functionally identical to: + + $json_text = JSON->new->encode($perl_scalar) + +Takes a hash reference as the second. + + $json_text = to_json($perl_scalar, $flag_hashref) + +So, + + $json_text = to_json($perl_scalar, {utf8 => 1, pretty => 1}) + +equivalent to: + + $json_text = JSON->new->utf8(1)->pretty(1)->encode($perl_scalar) + +If you want to write a modern perl code which communicates to outer world, +you should use C (supposed that JSON data are encoded in UTF-8). + +=head2 from_json + + $perl_scalar = from_json($json_text) + +The opposite of C: expects a json string and tries +to parse it, returning the resulting reference. + +This function call is functionally identical to: + + $perl_scalar = JSON->decode($json_text) + +Takes a hash reference as the second. + + $perl_scalar = from_json($json_text, $flag_hashref) + +So, + + $perl_scalar = from_json($json_text, {utf8 => 1}) + +equivalent to: + + $perl_scalar = JSON->new->utf8(1)->decode($json_text) + +If you want to write a modern perl code which communicates to outer world, +you should use C (supposed that JSON data are encoded in UTF-8). + +=head2 JSON::is_bool + + $is_boolean = JSON::is_bool($scalar) + +Returns true if the passed scalar represents either JSON::true or +JSON::false, two constants that act like C<1> and C<0> respectively +and are also used to represent JSON C and C in Perl strings. + +=head2 JSON::true + +Returns JSON true value which is blessed object. +It C JSON::Boolean object. + +=head2 JSON::false + +Returns JSON false value which is blessed object. +It C JSON::Boolean object. + +=head2 JSON::null + +Returns C. + +See L, below, for more information on how JSON values are mapped to +Perl. + +=head1 HOW DO I DECODE A DATA FROM OUTER AND ENCODE TO OUTER + +This section supposes that your perl vresion is 5.8 or later. + +If you know a JSON text from an outer world - a network, a file content, and so on, +is encoded in UTF-8, you should use C or C module object +with C enable. And the decoded result will contain UNICODE characters. + + # from network + my $json = JSON->new->utf8; + my $json_text = CGI->new->param( 'json_data' ); + my $perl_scalar = $json->decode( $json_text ); + + # from file content + local $/; + open( my $fh, '<', 'json.data' ); + $json_text = <$fh>; + $perl_scalar = decode_json( $json_text ); + +If an outer data is not encoded in UTF-8, firstly you should C it. + + use Encode; + local $/; + open( my $fh, '<', 'json.data' ); + my $encoding = 'cp932'; + my $unicode_json_text = decode( $encoding, <$fh> ); # UNICODE + + # or you can write the below code. + # + # open( my $fh, "<:encoding($encoding)", 'json.data' ); + # $unicode_json_text = <$fh>; + +In this case, C<$unicode_json_text> is of course UNICODE string. +So you B use C nor C module object with C enable. +Instead of them, you use C module object with C disable or C. + + $perl_scalar = $json->utf8(0)->decode( $unicode_json_text ); + # or + $perl_scalar = from_json( $unicode_json_text ); + +Or C and C: + + $perl_scalar = decode_json( encode( 'utf8', $unicode_json_text ) ); + # this way is not efficient. + +And now, you want to convert your C<$perl_scalar> into JSON data and +send it to an outer world - a network or a file content, and so on. + +Your data usually contains UNICODE strings and you want the converted data to be encoded +in UTF-8, you should use C or C module object with C enable. + + print encode_json( $perl_scalar ); # to a network? file? or display? + # or + print $json->utf8->encode( $perl_scalar ); + +If C<$perl_scalar> does not contain UNICODE but C<$encoding>-encoded strings +for some reason, then its characters are regarded as B for perl +(because it does not concern with your $encoding). +You B use C nor C module object with C enable. +Instead of them, you use C module object with C disable or C. +Note that the resulted text is a UNICODE string but no problem to print it. + + # $perl_scalar contains $encoding encoded string values + $unicode_json_text = $json->utf8(0)->encode( $perl_scalar ); + # or + $unicode_json_text = to_json( $perl_scalar ); + # $unicode_json_text consists of characters less than 0x100 + print $unicode_json_text; + +Or C all string values and C: + + $perl_scalar->{ foo } = decode( $encoding, $perl_scalar->{ foo } ); + # ... do it to each string values, then encode_json + $json_text = encode_json( $perl_scalar ); + +This method is a proper way but probably not efficient. + +See to L, L. + + +=head1 COMMON OBJECT-ORIENTED INTERFACE + +=head2 new + + $json = new JSON + +Returns a new C object inherited from either JSON::XS or JSON::PP +that can be used to de/encode JSON strings. + +All boolean flags described below are by default I. + +The mutators for flags all return the JSON object again and thus calls can +be chained: + + my $json = JSON->new->utf8->space_after->encode({a => [1,2]}) + => {"a": [1, 2]} + +=head2 ascii + + $json = $json->ascii([$enable]) + + $enabled = $json->get_ascii + +If $enable is true (or missing), then the encode method will not generate characters outside +the code range 0..127. Any Unicode characters outside that range will be escaped using either +a single \uXXXX or a double \uHHHH\uLLLLL escape sequence, as per RFC4627. + +If $enable is false, then the encode method will not escape Unicode characters unless +required by the JSON syntax or other flags. This results in a faster and more compact format. + +This feature depends on the used Perl version and environment. + +See to L if the backend is PP. + + JSON->new->ascii(1)->encode([chr 0x10401]) + => ["\ud801\udc01"] + +=head2 latin1 + + $json = $json->latin1([$enable]) + + $enabled = $json->get_latin1 + +If $enable is true (or missing), then the encode method will encode the resulting JSON +text as latin1 (or iso-8859-1), escaping any characters outside the code range 0..255. + +If $enable is false, then the encode method will not escape Unicode characters +unless required by the JSON syntax or other flags. + + JSON->new->latin1->encode (["\x{89}\x{abc}"] + => ["\x{89}\\u0abc"] # (perl syntax, U+abc escaped, U+89 not) + +=head2 utf8 + + $json = $json->utf8([$enable]) + + $enabled = $json->get_utf8 + +If $enable is true (or missing), then the encode method will encode the JSON result +into UTF-8, as required by many protocols, while the decode method expects to be handled +an UTF-8-encoded string. Please note that UTF-8-encoded strings do not contain any +characters outside the range 0..255, they are thus useful for bytewise/binary I/O. + +In future versions, enabling this option might enable autodetection of the UTF-16 and UTF-32 +encoding families, as described in RFC4627. + +If $enable is false, then the encode method will return the JSON string as a (non-encoded) +Unicode string, while decode expects thus a Unicode string. Any decoding or encoding +(e.g. to UTF-8 or UTF-16) needs to be done yourself, e.g. using the Encode module. + + +Example, output UTF-16BE-encoded JSON: + + use Encode; + $jsontext = encode "UTF-16BE", JSON::XS->new->encode ($object); + +Example, decode UTF-32LE-encoded JSON: + + use Encode; + $object = JSON::XS->new->decode (decode "UTF-32LE", $jsontext); + +See to L if the backend is PP. + + +=head2 pretty + + $json = $json->pretty([$enable]) + +This enables (or disables) all of the C, C and +C (and in the future possibly more) flags in one call to +generate the most readable (or most compact) form possible. + +Equivalent to: + + $json->indent->space_before->space_after + +The indent space length is three and JSON::XS cannot change the indent +space length. + +=head2 indent + + $json = $json->indent([$enable]) + + $enabled = $json->get_indent + +If C<$enable> is true (or missing), then the C method will use a multiline +format as output, putting every array member or object/hash key-value pair +into its own line, identing them properly. + +If C<$enable> is false, no newlines or indenting will be produced, and the +resulting JSON text is guarenteed not to contain any C. + +This setting has no effect when decoding JSON texts. + +The indent space length is three. +With JSON::PP, you can also access C to change indent space length. + + +=head2 space_before + + $json = $json->space_before([$enable]) + + $enabled = $json->get_space_before + +If C<$enable> is true (or missing), then the C method will add an extra +optional space before the C<:> separating keys from values in JSON objects. + +If C<$enable> is false, then the C method will not add any extra +space at those places. + +This setting has no effect when decoding JSON texts. + +Example, space_before enabled, space_after and indent disabled: + + {"key" :"value"} + + +=head2 space_after + + $json = $json->space_after([$enable]) + + $enabled = $json->get_space_after + +If C<$enable> is true (or missing), then the C method will add an extra +optional space after the C<:> separating keys from values in JSON objects +and extra whitespace after the C<,> separating key-value pairs and array +members. + +If C<$enable> is false, then the C method will not add any extra +space at those places. + +This setting has no effect when decoding JSON texts. + +Example, space_before and indent disabled, space_after enabled: + + {"key": "value"} + + +=head2 relaxed + + $json = $json->relaxed([$enable]) + + $enabled = $json->get_relaxed + +If C<$enable> is true (or missing), then C will accept some +extensions to normal JSON syntax (see below). C will not be +affected in anyway. I. I suggest only to use this option to +parse application-specific files written by humans (configuration files, +resource files etc.) + +If C<$enable> is false (the default), then C will only accept +valid JSON texts. + +Currently accepted extensions are: + +=over 4 + +=item * list items can have an end-comma + +JSON I array elements and key-value pairs with commas. This +can be annoying if you write JSON texts manually and want to be able to +quickly append elements, so this extension accepts comma at the end of +such items not just between them: + + [ + 1, + 2, <- this comma not normally allowed + ] + { + "k1": "v1", + "k2": "v2", <- this comma not normally allowed + } + +=item * shell-style '#'-comments + +Whenever JSON allows whitespace, shell-style comments are additionally +allowed. They are terminated by the first carriage-return or line-feed +character, after which more white-space and comments are allowed. + + [ + 1, # this comment not allowed in JSON + # neither this one... + ] + +=back + + +=head2 canonical + + $json = $json->canonical([$enable]) + + $enabled = $json->get_canonical + +If C<$enable> is true (or missing), then the C method will output JSON objects +by sorting their keys. This is adding a comparatively high overhead. + +If C<$enable> is false, then the C method will output key-value +pairs in the order Perl stores them (which will likely change between runs +of the same script). + +This option is useful if you want the same data structure to be encoded as +the same JSON text (given the same overall settings). If it is disabled, +the same hash might be encoded differently even if contains the same data, +as key-value pairs have no inherent ordering in Perl. + +This setting has no effect when decoding JSON texts. + +=head2 allow_nonref + + $json = $json->allow_nonref([$enable]) + + $enabled = $json->get_allow_nonref + +If C<$enable> is true (or missing), then the C method can convert a +non-reference into its corresponding string, number or null JSON value, +which is an extension to RFC4627. Likewise, C will accept those JSON +values instead of croaking. + +If C<$enable> is false, then the C method will croak if it isn't +passed an arrayref or hashref, as JSON texts must either be an object +or array. Likewise, C will croak if given something that is not a +JSON object or array. + + JSON->new->allow_nonref->encode ("Hello, World!") + => "Hello, World!" + +=head2 allow_unknown + + $json = $json->allow_unknown ([$enable]) + + $enabled = $json->get_allow_unknown + +If $enable is true (or missing), then "encode" will *not* throw an +exception when it encounters values it cannot represent in JSON (for +example, filehandles) but instead will encode a JSON "null" value. +Note that blessed objects are not included here and are handled +separately by c. + +If $enable is false (the default), then "encode" will throw an +exception when it encounters anything it cannot encode as JSON. + +This option does not affect "decode" in any way, and it is +recommended to leave it off unless you know your communications +partner. + +=head2 allow_blessed + + $json = $json->allow_blessed([$enable]) + + $enabled = $json->get_allow_blessed + +If C<$enable> is true (or missing), then the C method will not +barf when it encounters a blessed reference. Instead, the value of the +B option will decide whether C (C +disabled or no C method found) or a representation of the +object (C enabled and C method found) is being +encoded. Has no effect on C. + +If C<$enable> is false (the default), then C will throw an +exception when it encounters a blessed object. + + +=head2 convert_blessed + + $json = $json->convert_blessed([$enable]) + + $enabled = $json->get_convert_blessed + +If C<$enable> is true (or missing), then C, upon encountering a +blessed object, will check for the availability of the C method +on the object's class. If found, it will be called in scalar context +and the resulting scalar will be encoded instead of the object. If no +C method is found, the value of C will decide what +to do. + +The C method may safely call die if it wants. If C +returns other blessed objects, those will be handled in the same +way. C must take care of not causing an endless recursion cycle +(== crash) in this case. The name of C was chosen because other +methods called by the Perl core (== not by the user of the object) are +usually in upper case letters and to avoid collisions with the C +function or method. + +This setting does not yet influence C in any way. + +If C<$enable> is false, then the C setting will decide what +to do when a blessed object is found. + +=over + +=item convert_blessed_universally mode + +If use C with C<-convert_blessed_universally>, the C +subroutine is defined as the below code: + + *UNIVERSAL::TO_JSON = sub { + my $b_obj = B::svref_2object( $_[0] ); + return $b_obj->isa('B::HV') ? { %{ $_[0] } } + : $b_obj->isa('B::AV') ? [ @{ $_[0] } ] + : undef + ; + } + +This will cause that C method converts simple blessed objects into +JSON objects as non-blessed object. + + JSON -convert_blessed_universally; + $json->allow_blessed->convert_blessed->encode( $blessed_object ) + +This feature is experimental and may be removed in the future. + +=back + +=head2 filter_json_object + + $json = $json->filter_json_object([$coderef]) + +When C<$coderef> is specified, it will be called from C each +time it decodes a JSON object. The only argument passed to the coderef +is a reference to the newly-created hash. If the code references returns +a single scalar (which need not be a reference), this value +(i.e. a copy of that scalar to avoid aliasing) is inserted into the +deserialised data structure. If it returns an empty list +(NOTE: I C, which is a valid scalar), the original deserialised +hash will be inserted. This setting can slow down decoding considerably. + +When C<$coderef> is omitted or undefined, any existing callback will +be removed and C will not change the deserialised hash in any +way. + +Example, convert all JSON objects into the integer 5: + + my $js = JSON->new->filter_json_object (sub { 5 }); + # returns [5] + $js->decode ('[{}]'); # the given subroutine takes a hash reference. + # throw an exception because allow_nonref is not enabled + # so a lone 5 is not allowed. + $js->decode ('{"a":1, "b":2}'); + + +=head2 filter_json_single_key_object + + $json = $json->filter_json_single_key_object($key [=> $coderef]) + +Works remotely similar to C, but is only called for +JSON objects having a single key named C<$key>. + +This C<$coderef> is called before the one specified via +C, if any. It gets passed the single value in the JSON +object. If it returns a single value, it will be inserted into the data +structure. If it returns nothing (not even C but the empty list), +the callback from C will be called next, as if no +single-key callback were specified. + +If C<$coderef> is omitted or undefined, the corresponding callback will be +disabled. There can only ever be one callback for a given key. + +As this callback gets called less often then the C +one, decoding speed will not usually suffer as much. Therefore, single-key +objects make excellent targets to serialise Perl objects into, especially +as single-key JSON objects are as close to the type-tagged value concept +as JSON gets (it's basically an ID/VALUE tuple). Of course, JSON does not +support this in any way, so you need to make sure your data never looks +like a serialised Perl hash. + +Typical names for the single object key are C<__class_whatever__>, or +C<$__dollars_are_rarely_used__$> or C<}ugly_brace_placement>, or even +things like C<__class_md5sum(classname)__>, to reduce the risk of clashing +with real hashes. + +Example, decode JSON objects of the form C<< { "__widget__" => } >> +into the corresponding C<< $WIDGET{} >> object: + + # return whatever is in $WIDGET{5}: + JSON + ->new + ->filter_json_single_key_object (__widget__ => sub { + $WIDGET{ $_[0] } + }) + ->decode ('{"__widget__": 5') + + # this can be used with a TO_JSON method in some "widget" class + # for serialisation to json: + sub WidgetBase::TO_JSON { + my ($self) = @_; + + unless ($self->{id}) { + $self->{id} = ..get..some..id..; + $WIDGET{$self->{id}} = $self; + } + + { __widget__ => $self->{id} } + } + + +=head2 shrink + + $json = $json->shrink([$enable]) + + $enabled = $json->get_shrink + +With JSON::XS, this flag resizes strings generated by either +C or C to their minimum size possible. This can save +memory when your JSON texts are either very very long or you have many +short strings. It will also try to downgrade any strings to octet-form +if possible: perl stores strings internally either in an encoding called +UTF-X or in octet-form. The latter cannot store everything but uses less +space in general (and some buggy Perl or C code might even rely on that +internal representation being used). + +With JSON::PP, it is noop about resizing strings but tries +C to the returned string by C. See to L. + +See to L and L. + +=head2 max_depth + + $json = $json->max_depth([$maximum_nesting_depth]) + + $max_depth = $json->get_max_depth + +Sets the maximum nesting level (default C<512>) accepted while encoding +or decoding. If a higher nesting level is detected in JSON text or a Perl +data structure, then the encoder and decoder will stop and croak at that +point. + +Nesting level is defined by number of hash- or arrayrefs that the encoder +needs to traverse to reach a given point or the number of C<{> or C<[> +characters without their matching closing parenthesis crossed to reach a +given character in a string. + +If no argument is given, the highest possible setting will be used, which +is rarely useful. + +Note that nesting is implemented by recursion in C. The default value has +been chosen to be as large as typical operating systems allow without +crashing. (JSON::XS) + +With JSON::PP as the backend, when a large value (100 or more) was set and +it de/encodes a deep nested object/text, it may raise a warning +'Deep recursion on subroutin' at the perl runtime phase. + +See L for more info on why this is useful. + +=head2 max_size + + $json = $json->max_size([$maximum_string_size]) + + $max_size = $json->get_max_size + +Set the maximum length a JSON text may have (in bytes) where decoding is +being attempted. The default is C<0>, meaning no limit. When C +is called on a string that is longer then this many bytes, it will not +attempt to decode the string but throw an exception. This setting has no +effect on C (yet). + +If no argument is given, the limit check will be deactivated (same as when +C<0> is specified). + +See L, below, for more info on why this is useful. + +=head2 encode + + $json_text = $json->encode($perl_scalar) + +Converts the given Perl data structure (a simple scalar or a reference +to a hash or array) to its JSON representation. Simple scalars will be +converted into JSON string or number sequences, while references to arrays +become JSON arrays and references to hashes become JSON objects. Undefined +Perl values (e.g. C) become JSON C values. +References to the integers C<0> and C<1> are converted into C and C. + +=head2 decode + + $perl_scalar = $json->decode($json_text) + +The opposite of C: expects a JSON text and tries to parse it, +returning the resulting simple scalar or reference. Croaks on error. + +JSON numbers and strings become simple Perl scalars. JSON arrays become +Perl arrayrefs and JSON objects become Perl hashrefs. C becomes +C<1> (C), C becomes C<0> (C) and +C becomes C. + +=head2 decode_prefix + + ($perl_scalar, $characters) = $json->decode_prefix($json_text) + +This works like the C method, but instead of raising an exception +when there is trailing garbage after the first JSON object, it will +silently stop parsing there and return the number of characters consumed +so far. + + JSON->new->decode_prefix ("[1] the tail") + => ([], 3) + +See to L + +=head2 property + + $boolean = $json->property($property_name) + +Returns a boolean value about above some properties. + +The available properties are C, C, C, +C,C, C, C, C, +C, C, C, C, +C, C and C. + + $boolean = $json->property('utf8'); + => 0 + $json->utf8; + $boolean = $json->property('utf8'); + => 1 + +Sets the property with a given boolean value. + + $json = $json->property($property_name => $boolean); + +With no argumnt, it returns all the above properties as a hash reference. + + $flag_hashref = $json->property(); + +=head1 INCREMENTAL PARSING + +Most of this section are copied and modified from L. + +In some cases, there is the need for incremental parsing of JSON texts. +This module does allow you to parse a JSON stream incrementally. +It does so by accumulating text until it has a full JSON object, which +it then can decode. This process is similar to using C +to see if a full JSON object is available, but is much more efficient +(and can be implemented with a minimum of method calls). + +The backend module will only attempt to parse the JSON text once it is sure it +has enough text to get a decisive result, using a very simple but +truly incremental parser. This means that it sometimes won't stop as +early as the full parser, for example, it doesn't detect parenthese +mismatches. The only thing it guarantees is that it starts decoding as +soon as a syntactically valid JSON text has been seen. This means you need +to set resource limits (e.g. C) to ensure the parser will stop +parsing in the presence if syntax errors. + +The following methods implement this incremental parser. + +=head2 incr_parse + + $json->incr_parse( [$string] ) # void context + + $obj_or_undef = $json->incr_parse( [$string] ) # scalar context + + @obj_or_empty = $json->incr_parse( [$string] ) # list context + +This is the central parsing function. It can both append new text and +extract objects from the stream accumulated so far (both of these +functions are optional). + +If C<$string> is given, then this string is appended to the already +existing JSON fragment stored in the C<$json> object. + +After that, if the function is called in void context, it will simply +return without doing anything further. This can be used to add more text +in as many chunks as you want. + +If the method is called in scalar context, then it will try to extract +exactly I JSON object. If that is successful, it will return this +object, otherwise it will return C. If there is a parse error, +this method will croak just as C would do (one can then use +C to skip the errornous part). This is the most common way of +using the method. + +And finally, in list context, it will try to extract as many objects +from the stream as it can find and return them, or the empty list +otherwise. For this to work, there must be no separators between the JSON +objects or arrays, instead they must be concatenated back-to-back. If +an error occurs, an exception will be raised as in the scalar context +case. Note that in this case, any previously-parsed JSON texts will be +lost. + +Example: Parse some JSON arrays/objects in a given string and return them. + + my @objs = JSON->new->incr_parse ("[5][7][1,2]"); + +=head2 incr_text + + $lvalue_string = $json->incr_text + +This method returns the currently stored JSON fragment as an lvalue, that +is, you can manipulate it. This I works when a preceding call to +C in I successfully returned an object. Under +all other circumstances you must not call this function (I mean it. +although in simple tests it might actually work, it I fail under +real world conditions). As a special exception, you can also call this +method before having parsed anything. + +This function is useful in two cases: a) finding the trailing text after a +JSON object or b) parsing multiple JSON objects separated by non-JSON text +(such as commas). + + $json->incr_text =~ s/\s*,\s*//; + +In Perl 5.005, C attribute is not available. +You must write codes like the below: + + $string = $json->incr_text; + $string =~ s/\s*,\s*//; + $json->incr_text( $string ); + +=head2 incr_skip + + $json->incr_skip + +This will reset the state of the incremental parser and will remove the +parsed text from the input buffer. This is useful after C +died, in which case the input buffer and incremental parser state is left +unchanged, to skip the text parsed so far and to reset the parse state. + +=head2 incr_reset + + $json->incr_reset + +This completely resets the incremental parser, that is, after this call, +it will be as if the parser had never parsed anything. + +This is useful if you want ot repeatedly parse JSON objects and want to +ignore any trailing data, which means you have to reset the parser after +each successful decode. + +See to L for examples. + + +=head1 JSON::PP SUPPORT METHODS + +The below methods are JSON::PP own methods, so when C works +with JSON::PP (i.e. the created object is a JSON::PP object), available. +See to L in detail. + +If you use C with additonal C<-support_by_pp>, some methods +are available even with JSON::XS. See to L. + + BEING { $ENV{PERL_JSON_BACKEND} = 'JSON::XS' } + + use JSON -support_by_pp; + + my $json = new JSON; + $json->allow_nonref->escape_slash->encode("/"); + + # functional interfaces too. + print to_json(["/"], {escape_slash => 1}); + print from_json('["foo"]', {utf8 => 1}); + +If you do not want to all functions but C<-support_by_pp>, +use C<-no_export>. + + use JSON -support_by_pp, -no_export; + # functional interfaces are not exported. + +=head2 allow_singlequote + + $json = $json->allow_singlequote([$enable]) + +If C<$enable> is true (or missing), then C will accept +any JSON strings quoted by single quotations that are invalid JSON +format. + + $json->allow_singlequote->decode({"foo":'bar'}); + $json->allow_singlequote->decode({'foo':"bar"}); + $json->allow_singlequote->decode({'foo':'bar'}); + +As same as the C option, this option may be used to parse +application-specific files written by humans. + +=head2 allow_barekey + + $json = $json->allow_barekey([$enable]) + +If C<$enable> is true (or missing), then C will accept +bare keys of JSON object that are invalid JSON format. + +As same as the C option, this option may be used to parse +application-specific files written by humans. + + $json->allow_barekey->decode('{foo:"bar"}'); + +=head2 allow_bignum + + $json = $json->allow_bignum([$enable]) + +If C<$enable> is true (or missing), then C will convert +the big integer Perl cannot handle as integer into a L +object and convert a floating number (any) into a L. + +On the contary, C converts C objects and C +objects into JSON numbers with C enable. + + $json->allow_nonref->allow_blessed->allow_bignum; + $bigfloat = $json->decode('2.000000000000000000000000001'); + print $json->encode($bigfloat); + # => 2.000000000000000000000000001 + +See to L aboout the conversion of JSON number. + +=head2 loose + + $json = $json->loose([$enable]) + +The unescaped [\x00-\x1f\x22\x2f\x5c] strings are invalid in JSON strings +and the module doesn't allow to C to these (except for \x2f). +If C<$enable> is true (or missing), then C will accept these +unescaped strings. + + $json->loose->decode(qq|["abc + def"]|); + +See to L. + +=head2 escape_slash + + $json = $json->escape_slash([$enable]) + +According to JSON Grammar, I (U+002F) is escaped. But by default +JSON backend modules encode strings without escaping slash. + +If C<$enable> is true (or missing), then C will escape slashes. + +=head2 indent_length + + $json = $json->indent_length($length) + +With JSON::XS, The indent space length is 3 and cannot be changed. +With JSON::PP, it sets the indent space length with the given $length. +The default is 3. The acceptable range is 0 to 15. + +=head2 sort_by + + $json = $json->sort_by($function_name) + $json = $json->sort_by($subroutine_ref) + +If $function_name or $subroutine_ref are set, its sort routine are used. + + $js = $pc->sort_by(sub { $JSON::PP::a cmp $JSON::PP::b })->encode($obj); + # is($js, q|{"a":1,"b":2,"c":3,"d":4,"e":5,"f":6,"g":7,"h":8,"i":9}|); + + $js = $pc->sort_by('own_sort')->encode($obj); + # is($js, q|{"a":1,"b":2,"c":3,"d":4,"e":5,"f":6,"g":7,"h":8,"i":9}|); + + sub JSON::PP::own_sort { $JSON::PP::a cmp $JSON::PP::b } + +As the sorting routine runs in the JSON::PP scope, the given +subroutine name and the special variables C<$a>, C<$b> will begin +with 'JSON::PP::'. + +If $integer is set, then the effect is same as C on. + +See to L. + +=head1 MAPPING + +This section is copied from JSON::XS and modified to C. +JSON::XS and JSON::PP mapping mechanisms are almost equivalent. + +See to L. + +=head2 JSON -> PERL + +=over 4 + +=item object + +A JSON object becomes a reference to a hash in Perl. No ordering of object +keys is preserved (JSON does not preserver object key ordering itself). + +=item array + +A JSON array becomes a reference to an array in Perl. + +=item string + +A JSON string becomes a string scalar in Perl - Unicode codepoints in JSON +are represented by the same codepoints in the Perl string, so no manual +decoding is necessary. + +=item number + +A JSON number becomes either an integer, numeric (floating point) or +string scalar in perl, depending on its range and any fractional parts. On +the Perl level, there is no difference between those as Perl handles all +the conversion details, but an integer may take slightly less memory and +might represent more values exactly than floating point numbers. + +If the number consists of digits only, C will try to represent +it as an integer value. If that fails, it will try to represent it as +a numeric (floating point) value if that is possible without loss of +precision. Otherwise it will preserve the number as a string value (in +which case you lose roundtripping ability, as the JSON number will be +re-encoded toa JSON string). + +Numbers containing a fractional or exponential part will always be +represented as numeric (floating point) values, possibly at a loss of +precision (in which case you might lose perfect roundtripping ability, but +the JSON number will still be re-encoded as a JSON number). + +Note that precision is not accuracy - binary floating point values cannot +represent most decimal fractions exactly, and when converting from and to +floating point, C only guarantees precision up to but not including +the leats significant bit. + +If the backend is JSON::PP and C is enable, the big integers +and the numeric can be optionally converted into L and +L objects. + +=item true, false + +These JSON atoms become C and C, +respectively. They are overloaded to act almost exactly like the numbers +C<1> and C<0>. You can check wether a scalar is a JSON boolean by using +the C function. + +If C and C are used as strings or compared as strings, +they represent as C and C respectively. + + print JSON::true . "\n"; + => true + print JSON::true + 1; + => 1 + + ok(JSON::true eq 'true'); + ok(JSON::true eq '1'); + ok(JSON::true == 1); + +C will install these missing overloading features to the backend modules. + + +=item null + +A JSON null atom becomes C in Perl. + +C returns C. + +=back + + +=head2 PERL -> JSON + +The mapping from Perl to JSON is slightly more difficult, as Perl is a +truly typeless language, so we can only guess which JSON type is meant by +a Perl value. + +=over 4 + +=item hash references + +Perl hash references become JSON objects. As there is no inherent ordering +in hash keys (or JSON objects), they will usually be encoded in a +pseudo-random order that can change between runs of the same program but +stays generally the same within a single run of a program. C +optionally sort the hash keys (determined by the I flag), so +the same datastructure will serialise to the same JSON text (given same +settings and version of JSON::XS), but this incurs a runtime overhead +and is only rarely useful, e.g. when you want to compare some JSON text +against another for equality. + +In future, the ordered object feature will be added to JSON::PP using C mechanism. + + +=item array references + +Perl array references become JSON arrays. + +=item other references + +Other unblessed references are generally not allowed and will cause an +exception to be thrown, except for references to the integers C<0> and +C<1>, which get turned into C and C atoms in JSON. You can +also use C and C to improve readability. + + to_json [\0,JSON::true] # yields [false,true] + +=item JSON::true, JSON::false, JSON::null + +These special values become JSON true and JSON false values, +respectively. You can also use C<\1> and C<\0> directly if you want. + +JSON::null returns C. + +=item blessed objects + +Blessed objects are not directly representable in JSON. See the +C and C methods on various options on +how to deal with this: basically, you can choose between throwing an +exception, encoding the reference as if it weren't blessed, or provide +your own serialiser method. + +With C mode, C converts blessed +hash references or blessed array references (contains other blessed references) +into JSON members and arrays. + + use JSON -convert_blessed_universally; + JSON->new->allow_blessed->convert_blessed->encode( $blessed_object ); + +See to L. + +=item simple scalars + +Simple Perl scalars (any scalar that is not a reference) are the most +difficult objects to encode: JSON::XS and JSON::PP will encode undefined scalars as +JSON C values, scalars that have last been used in a string context +before encoding as JSON strings, and anything else as number value: + + # dump as number + encode_json [2] # yields [2] + encode_json [-3.0e17] # yields [-3e+17] + my $value = 5; encode_json [$value] # yields [5] + + # used as string, so dump as string + print $value; + encode_json [$value] # yields ["5"] + + # undef becomes null + encode_json [undef] # yields [null] + +You can force the type to be a string by stringifying it: + + my $x = 3.1; # some variable containing a number + "$x"; # stringified + $x .= ""; # another, more awkward way to stringify + print $x; # perl does it for you, too, quite often + +You can force the type to be a number by numifying it: + + my $x = "3"; # some variable containing a string + $x += 0; # numify it, ensuring it will be dumped as a number + $x *= 1; # same thing, the choise is yours. + +You can not currently force the type in other, less obscure, ways. + +Note that numerical precision has the same meaning as under Perl (so +binary to decimal conversion follows the same rules as in Perl, which +can differ to other languages). Also, your perl interpreter might expose +extensions to the floating point numbers of your platform, such as +infinities or NaN's - these cannot be represented in JSON, and it is an +error to pass those in. + +=item Big Number + +If the backend is JSON::PP and C is enable, +C converts C objects and C +objects into JSON numbers. + + +=back + +=head1 JSON and ECMAscript + +See to L. + +=head1 JSON and YAML + +JSON is not a subset of YAML. +See to L. + + +=head1 BACKEND MODULE DECISION + +When you use C, C tries to C JSON::XS. If this call failed, it will +C JSON::PP. The required JSON::XS version is I<2.2> or later. + +The C constructor method returns an object inherited from the backend module, +and JSON::XS object is a blessed scaler reference while JSON::PP is a blessed hash +reference. + +So, your program should not depend on the backend module, especially +returned objects should not be modified. + + my $json = JSON->new; # XS or PP? + $json->{stash} = 'this is xs object'; # this code may raise an error! + +To check the backend module, there are some methods - C, C and C. + + JSON->backend; # 'JSON::XS' or 'JSON::PP' + + JSON->backend->is_pp: # 0 or 1 + + JSON->backend->is_xs: # 1 or 0 + + $json->is_xs; # 1 or 0 + + $json->is_pp; # 0 or 1 + + +If you set an enviornment variable C, The calling action will be changed. + +=over + +=item PERL_JSON_BACKEND = 0 or PERL_JSON_BACKEND = 'JSON::PP' + +Always use JSON::PP + +=item PERL_JSON_BACKEND == 1 or PERL_JSON_BACKEND = 'JSON::XS,JSON::PP' + +(The default) Use compiled JSON::XS if it is properly compiled & installed, +otherwise use JSON::PP. + +=item PERL_JSON_BACKEND == 2 or PERL_JSON_BACKEND = 'JSON::XS' + +Always use compiled JSON::XS, die if it isn't properly compiled & installed. + +=item PERL_JSON_BACKEND = 'JSON::backportPP' + +Always use JSON::backportPP. +JSON::backportPP is JSON::PP back port module. +C includs JSON::backportPP instead of JSON::PP. + +=back + +These ideas come from L mechanism. + +example: + + BEGIN { $ENV{PERL_JSON_BACKEND} = 'JSON::PP' } + use JSON; # always uses JSON::PP + +In future, it may be able to specify another module. + +=head1 USE PP FEATURES EVEN THOUGH XS BACKEND + +Many methods are available with either JSON::XS or JSON::PP and +when the backend module is JSON::XS, if any JSON::PP specific (i.e. JSON::XS unspported) +method is called, it will C and be noop. + +But If you C C passing the optional string C<-support_by_pp>, +it makes a part of those unupported methods available. +This feature is achieved by using JSON::PP in C. + + BEGIN { $ENV{PERL_JSON_BACKEND} = 2 } # with JSON::XS + use JSON -support_by_pp; + my $json = new JSON; + $json->allow_nonref->escape_slash->encode("/"); + +At this time, the returned object is a C +object (re-blessed XS object), and by checking JSON::XS unsupported flags +in de/encoding, can support some unsupported methods - C, C, +C, C, C and C. + +When any unsupported methods are not enable, C will be +used as is. The switch is achieved by changing the symbolic tables. + +C<-support_by_pp> is effective only when the backend module is JSON::XS +and it makes the de/encoding speed down a bit. + +See to L. + +=head1 INCOMPATIBLE CHANGES TO OLD VERSION + +There are big incompatibility between new version (2.00) and old (1.xx). +If you use old C 1.xx in your code, please check it. + +See to L + +=over + +=item jsonToObj and objToJson are obsoleted. + +Non Perl-style name C and C are obsoleted +(but not yet deleted from the source). +If you use these functions in your code, please replace them +with C and C. + + +=item Global variables are no longer available. + +C class variables - C<$JSON::AUTOCONVERT>, C<$JSON::BareKey>, etc... +- are not available any longer. +Instead, various features can be used through object methods. + + +=item Package JSON::Converter and JSON::Parser are deleted. + +Now C bundles with JSON::PP which can handle JSON more properly than them. + +=item Package JSON::NotString is deleted. + +There was C class which represents JSON value C, C, C +and numbers. It was deleted and replaced by C. + +C represents C and C. + +C does not represent C. + +C returns C. + +C makes L and L is-a relation +to L. + +=item function JSON::Number is obsoleted. + +C is now needless because JSON::XS and JSON::PP have +round-trip integrity. + +=item JSONRPC modules are deleted. + +Perl implementation of JSON-RPC protocol - C, C +and C are deleted in this distribution. +Instead of them, there is L which supports JSON-RPC protocol version 1.1. + +=back + +=head2 Transition ways from 1.xx to 2.xx. + +You should set C mode firstly, because +it is always successful for the below codes even with JSON::XS. + + use JSON -support_by_pp; + +=over + +=item Exported jsonToObj (simple) + + from_json($json_text); + +=item Exported objToJson (simple) + + to_json($perl_scalar); + +=item Exported jsonToObj (advanced) + + $flags = {allow_barekey => 1, allow_singlequote => 1}; + from_json($json_text, $flags); + +equivalent to: + + $JSON::BareKey = 1; + $JSON::QuotApos = 1; + jsonToObj($json_text); + +=item Exported objToJson (advanced) + + $flags = {allow_blessed => 1, allow_barekey => 1}; + to_json($perl_scalar, $flags); + +equivalent to: + + $JSON::BareKey = 1; + objToJson($perl_scalar); + +=item jsonToObj as object method + + $json->decode($json_text); + +=item objToJson as object method + + $json->encode($perl_scalar); + +=item new method with parameters + +The C method in 2.x takes any parameters no longer. +You can set parameters instead; + + $json = JSON->new->pretty; + +=item $JSON::Pretty, $JSON::Indent, $JSON::Delimiter + +If C is enable, that means C<$JSON::Pretty> flag set. And +C<$JSON::Delimiter> was substituted by C and C. +In conclusion: + + $json->indent->space_before->space_after; + +Equivalent to: + + $json->pretty; + +To change indent length, use C. + +(Only with JSON::PP, if C<-support_by_pp> is not used.) + + $json->pretty->indent_length(2)->encode($perl_scalar); + +=item $JSON::BareKey + +(Only with JSON::PP, if C<-support_by_pp> is not used.) + + $json->allow_barekey->decode($json_text) + +=item $JSON::ConvBlessed + +use C<-convert_blessed_universally>. See to L. + +=item $JSON::QuotApos + +(Only with JSON::PP, if C<-support_by_pp> is not used.) + + $json->allow_singlequote->decode($json_text) + +=item $JSON::SingleQuote + +Disable. C does not make such a invalid JSON string any longer. + +=item $JSON::KeySort + + $json->canonical->encode($perl_scalar) + +This is the ascii sort. + +If you want to use with your own sort routine, check the C method. + +(Only with JSON::PP, even if C<-support_by_pp> is used currently.) + + $json->sort_by($sort_routine_ref)->encode($perl_scalar) + + $json->sort_by(sub { $JSON::PP::a <=> $JSON::PP::b })->encode($perl_scalar) + +Can't access C<$a> and C<$b> but C<$JSON::PP::a> and C<$JSON::PP::b>. + +=item $JSON::SkipInvalid + + $json->allow_unknown + +=item $JSON::AUTOCONVERT + +Needless. C backend modules have the round-trip integrity. + +=item $JSON::UTF8 + +Needless because C (JSON::XS/JSON::PP) sets +the UTF8 flag on properly. + + # With UTF8-flagged strings + + $json->allow_nonref; + $str = chr(1000); # UTF8-flagged + + $json_text = $json->utf8(0)->encode($str); + utf8::is_utf8($json_text); + # true + $json_text = $json->utf8(1)->encode($str); + utf8::is_utf8($json_text); + # false + + $str = '"' . chr(1000) . '"'; # UTF8-flagged + + $perl_scalar = $json->utf8(0)->decode($str); + utf8::is_utf8($perl_scalar); + # true + $perl_scalar = $json->utf8(1)->decode($str); + # died because of 'Wide character in subroutine' + +See to L. + +=item $JSON::UnMapping + +Disable. See to L. + +=item $JSON::SelfConvert + +This option was deleted. +Instead of it, if a givien blessed object has the C method, +C will be executed with C. + + $json->convert_blessed->encode($bleesed_hashref_or_arrayref) + # if need, call allow_blessed + +Note that it was C in old version, but now not C but C. + +=back + +=head1 TODO + +=over + +=item example programs + +=back + +=head1 THREADS + +No test with JSON::PP. If with JSON::XS, See to L. + + +=head1 BUGS + +Please report bugs relevant to C to Emakamaka[at]cpan.orgE. + + +=head1 SEE ALSO + +Most of the document is copied and modified from JSON::XS doc. + +L, L + +C(L) + +=head1 AUTHOR + +Makamaka Hannyaharamitu, Emakamaka[at]cpan.orgE + +JSON::XS was written by Marc Lehmann + +The relese of this new version owes to the courtesy of Marc Lehmann. + + +=head1 COPYRIGHT AND LICENSE + +Copyright 2005-2011 by Makamaka Hannyaharamitu + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut + diff --git a/release/src/router/uqmi/data/lib/JSON/backportPP.pm b/release/src/router/uqmi/data/lib/JSON/backportPP.pm new file mode 100644 index 0000000000..ab374162d8 --- /dev/null +++ b/release/src/router/uqmi/data/lib/JSON/backportPP.pm @@ -0,0 +1,2797 @@ +package # This is JSON::backportPP + JSON::PP; + +# JSON-2.0 + +use 5.005; +use strict; +use base qw(Exporter); +use overload (); + +use Carp (); +use B (); +#use Devel::Peek; + +$JSON::PP::VERSION = '2.27200'; + +@JSON::PP::EXPORT = qw(encode_json decode_json from_json to_json); + +# instead of hash-access, i tried index-access for speed. +# but this method is not faster than what i expected. so it will be changed. + +use constant P_ASCII => 0; +use constant P_LATIN1 => 1; +use constant P_UTF8 => 2; +use constant P_INDENT => 3; +use constant P_CANONICAL => 4; +use constant P_SPACE_BEFORE => 5; +use constant P_SPACE_AFTER => 6; +use constant P_ALLOW_NONREF => 7; +use constant P_SHRINK => 8; +use constant P_ALLOW_BLESSED => 9; +use constant P_CONVERT_BLESSED => 10; +use constant P_RELAXED => 11; + +use constant P_LOOSE => 12; +use constant P_ALLOW_BIGNUM => 13; +use constant P_ALLOW_BAREKEY => 14; +use constant P_ALLOW_SINGLEQUOTE => 15; +use constant P_ESCAPE_SLASH => 16; +use constant P_AS_NONBLESSED => 17; + +use constant P_ALLOW_UNKNOWN => 18; + +use constant OLD_PERL => $] < 5.008 ? 1 : 0; + +BEGIN { + my @xs_compati_bit_properties = qw( + latin1 ascii utf8 indent canonical space_before space_after allow_nonref shrink + allow_blessed convert_blessed relaxed allow_unknown + ); + my @pp_bit_properties = qw( + allow_singlequote allow_bignum loose + allow_barekey escape_slash as_nonblessed + ); + + # Perl version check, Unicode handling is enable? + # Helper module sets @JSON::PP::_properties. + if ($] < 5.008 ) { + my $helper = $] >= 5.006 ? 'JSON::backportPP::Compat5006' : 'JSON::backportPP::Compat5005'; + eval qq| require $helper |; + if ($@) { Carp::croak $@; } + } + + for my $name (@xs_compati_bit_properties, @pp_bit_properties) { + my $flag_name = 'P_' . uc($name); + + eval qq/ + sub $name { + my \$enable = defined \$_[1] ? \$_[1] : 1; + + if (\$enable) { + \$_[0]->{PROPS}->[$flag_name] = 1; + } + else { + \$_[0]->{PROPS}->[$flag_name] = 0; + } + + \$_[0]; + } + + sub get_$name { + \$_[0]->{PROPS}->[$flag_name] ? 1 : ''; + } + /; + } + +} + + + +# Functions + +my %encode_allow_method + = map {($_ => 1)} qw/utf8 pretty allow_nonref latin1 self_encode escape_slash + allow_blessed convert_blessed indent indent_length allow_bignum + as_nonblessed + /; +my %decode_allow_method + = map {($_ => 1)} qw/utf8 allow_nonref loose allow_singlequote allow_bignum + allow_barekey max_size relaxed/; + + +my $JSON; # cache + +sub encode_json ($) { # encode + ($JSON ||= __PACKAGE__->new->utf8)->encode(@_); +} + + +sub decode_json { # decode + ($JSON ||= __PACKAGE__->new->utf8)->decode(@_); +} + +# Obsoleted + +sub to_json($) { + Carp::croak ("JSON::PP::to_json has been renamed to encode_json."); +} + + +sub from_json($) { + Carp::croak ("JSON::PP::from_json has been renamed to decode_json."); +} + + +# Methods + +sub new { + my $class = shift; + my $self = { + max_depth => 512, + max_size => 0, + indent => 0, + FLAGS => 0, + fallback => sub { encode_error('Invalid value. JSON can only reference.') }, + indent_length => 3, + }; + + bless $self, $class; +} + + +sub encode { + return $_[0]->PP_encode_json($_[1]); +} + + +sub decode { + return $_[0]->PP_decode_json($_[1], 0x00000000); +} + + +sub decode_prefix { + return $_[0]->PP_decode_json($_[1], 0x00000001); +} + + +# accessor + + +# pretty printing + +sub pretty { + my ($self, $v) = @_; + my $enable = defined $v ? $v : 1; + + if ($enable) { # indent_length(3) for JSON::XS compatibility + $self->indent(1)->indent_length(3)->space_before(1)->space_after(1); + } + else { + $self->indent(0)->space_before(0)->space_after(0); + } + + $self; +} + +# etc + +sub max_depth { + my $max = defined $_[1] ? $_[1] : 0x80000000; + $_[0]->{max_depth} = $max; + $_[0]; +} + + +sub get_max_depth { $_[0]->{max_depth}; } + + +sub max_size { + my $max = defined $_[1] ? $_[1] : 0; + $_[0]->{max_size} = $max; + $_[0]; +} + + +sub get_max_size { $_[0]->{max_size}; } + + +sub filter_json_object { + $_[0]->{cb_object} = defined $_[1] ? $_[1] : 0; + $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0; + $_[0]; +} + +sub filter_json_single_key_object { + if (@_ > 1) { + $_[0]->{cb_sk_object}->{$_[1]} = $_[2]; + } + $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0; + $_[0]; +} + +sub indent_length { + if (!defined $_[1] or $_[1] > 15 or $_[1] < 0) { + Carp::carp "The acceptable range of indent_length() is 0 to 15."; + } + else { + $_[0]->{indent_length} = $_[1]; + } + $_[0]; +} + +sub get_indent_length { + $_[0]->{indent_length}; +} + +sub sort_by { + $_[0]->{sort_by} = defined $_[1] ? $_[1] : 1; + $_[0]; +} + +sub allow_bigint { + Carp::carp("allow_bigint() is obsoleted. use allow_bignum() insted."); +} + +############################### + +### +### Perl => JSON +### + + +{ # Convert + + my $max_depth; + my $indent; + my $ascii; + my $latin1; + my $utf8; + my $space_before; + my $space_after; + my $canonical; + my $allow_blessed; + my $convert_blessed; + + my $indent_length; + my $escape_slash; + my $bignum; + my $as_nonblessed; + + my $depth; + my $indent_count; + my $keysort; + + + sub PP_encode_json { + my $self = shift; + my $obj = shift; + + $indent_count = 0; + $depth = 0; + + my $idx = $self->{PROPS}; + + ($ascii, $latin1, $utf8, $indent, $canonical, $space_before, $space_after, $allow_blessed, + $convert_blessed, $escape_slash, $bignum, $as_nonblessed) + = @{$idx}[P_ASCII .. P_SPACE_AFTER, P_ALLOW_BLESSED, P_CONVERT_BLESSED, + P_ESCAPE_SLASH, P_ALLOW_BIGNUM, P_AS_NONBLESSED]; + + ($max_depth, $indent_length) = @{$self}{qw/max_depth indent_length/}; + + $keysort = $canonical ? sub { $a cmp $b } : undef; + + if ($self->{sort_by}) { + $keysort = ref($self->{sort_by}) eq 'CODE' ? $self->{sort_by} + : $self->{sort_by} =~ /\D+/ ? $self->{sort_by} + : sub { $a cmp $b }; + } + + encode_error("hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)") + if(!ref $obj and !$idx->[ P_ALLOW_NONREF ]); + + my $str = $self->object_to_json($obj); + + $str .= "\n" if ( $indent ); # JSON::XS 2.26 compatible + + unless ($ascii or $latin1 or $utf8) { + utf8::upgrade($str); + } + + if ($idx->[ P_SHRINK ]) { + utf8::downgrade($str, 1); + } + + return $str; + } + + + sub object_to_json { + my ($self, $obj) = @_; + my $type = ref($obj); + + if($type eq 'HASH'){ + return $self->hash_to_json($obj); + } + elsif($type eq 'ARRAY'){ + return $self->array_to_json($obj); + } + elsif ($type) { # blessed object? + if (blessed($obj)) { + + return $self->value_to_json($obj) if ( $obj->isa('JSON::PP::Boolean') ); + + if ( $convert_blessed and $obj->can('TO_JSON') ) { + my $result = $obj->TO_JSON(); + if ( defined $result and ref( $result ) ) { + if ( refaddr( $obj ) eq refaddr( $result ) ) { + encode_error( sprintf( + "%s::TO_JSON method returned same object as was passed instead of a new one", + ref $obj + ) ); + } + } + + return $self->object_to_json( $result ); + } + + return "$obj" if ( $bignum and _is_bignum($obj) ); + return $self->blessed_to_json($obj) if ($allow_blessed and $as_nonblessed); # will be removed. + + encode_error( sprintf("encountered object '%s', but neither allow_blessed " + . "nor convert_blessed settings are enabled", $obj) + ) unless ($allow_blessed); + + return 'null'; + } + else { + return $self->value_to_json($obj); + } + } + else{ + return $self->value_to_json($obj); + } + } + + + sub hash_to_json { + my ($self, $obj) = @_; + my @res; + + encode_error("json text or perl structure exceeds maximum nesting level (max_depth set too low?)") + if (++$depth > $max_depth); + + my ($pre, $post) = $indent ? $self->_up_indent() : ('', ''); + my $del = ($space_before ? ' ' : '') . ':' . ($space_after ? ' ' : ''); + + for my $k ( _sort( $obj ) ) { + if ( OLD_PERL ) { utf8::decode($k) } # key for Perl 5.6 / be optimized + push @res, string_to_json( $self, $k ) + . $del + . ( $self->object_to_json( $obj->{$k} ) || $self->value_to_json( $obj->{$k} ) ); + } + + --$depth; + $self->_down_indent() if ($indent); + + return '{' . ( @res ? $pre : '' ) . ( @res ? join( ",$pre", @res ) . $post : '' ) . '}'; + } + + + sub array_to_json { + my ($self, $obj) = @_; + my @res; + + encode_error("json text or perl structure exceeds maximum nesting level (max_depth set too low?)") + if (++$depth > $max_depth); + + my ($pre, $post) = $indent ? $self->_up_indent() : ('', ''); + + for my $v (@$obj){ + push @res, $self->object_to_json($v) || $self->value_to_json($v); + } + + --$depth; + $self->_down_indent() if ($indent); + + return '[' . ( @res ? $pre : '' ) . ( @res ? join( ",$pre", @res ) . $post : '' ) . ']'; + } + + + sub value_to_json { + my ($self, $value) = @_; + + return 'null' if(!defined $value); + + my $b_obj = B::svref_2object(\$value); # for round trip problem + my $flags = $b_obj->FLAGS; + + return $value # as is + if $flags & ( B::SVp_IOK | B::SVp_NOK ) and !( $flags & B::SVp_POK ); # SvTYPE is IV or NV? + + my $type = ref($value); + + if(!$type){ + return string_to_json($self, $value); + } + elsif( blessed($value) and $value->isa('JSON::PP::Boolean') ){ + return $$value == 1 ? 'true' : 'false'; + } + elsif ($type) { + if ((overload::StrVal($value) =~ /=(\w+)/)[0]) { + return $self->value_to_json("$value"); + } + + if ($type eq 'SCALAR' and defined $$value) { + return $$value eq '1' ? 'true' + : $$value eq '0' ? 'false' + : $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ? 'null' + : encode_error("cannot encode reference to scalar"); + } + + if ( $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ) { + return 'null'; + } + else { + if ( $type eq 'SCALAR' or $type eq 'REF' ) { + encode_error("cannot encode reference to scalar"); + } + else { + encode_error("encountered $value, but JSON can only represent references to arrays or hashes"); + } + } + + } + else { + return $self->{fallback}->($value) + if ($self->{fallback} and ref($self->{fallback}) eq 'CODE'); + return 'null'; + } + + } + + + my %esc = ( + "\n" => '\n', + "\r" => '\r', + "\t" => '\t', + "\f" => '\f', + "\b" => '\b', + "\"" => '\"', + "\\" => '\\\\', + "\'" => '\\\'', + ); + + + sub string_to_json { + my ($self, $arg) = @_; + + $arg =~ s/([\x22\x5c\n\r\t\f\b])/$esc{$1}/g; + $arg =~ s/\//\\\//g if ($escape_slash); + $arg =~ s/([\x00-\x08\x0b\x0e-\x1f])/'\\u00' . unpack('H2', $1)/eg; + + if ($ascii) { + $arg = JSON_PP_encode_ascii($arg); + } + + if ($latin1) { + $arg = JSON_PP_encode_latin1($arg); + } + + if ($utf8) { + utf8::encode($arg); + } + + return '"' . $arg . '"'; + } + + + sub blessed_to_json { + my $reftype = reftype($_[1]) || ''; + if ($reftype eq 'HASH') { + return $_[0]->hash_to_json($_[1]); + } + elsif ($reftype eq 'ARRAY') { + return $_[0]->array_to_json($_[1]); + } + else { + return 'null'; + } + } + + + sub encode_error { + my $error = shift; + Carp::croak "$error"; + } + + + sub _sort { + defined $keysort ? (sort $keysort (keys %{$_[0]})) : keys %{$_[0]}; + } + + + sub _up_indent { + my $self = shift; + my $space = ' ' x $indent_length; + + my ($pre,$post) = ('',''); + + $post = "\n" . $space x $indent_count; + + $indent_count++; + + $pre = "\n" . $space x $indent_count; + + return ($pre,$post); + } + + + sub _down_indent { $indent_count--; } + + + sub PP_encode_box { + { + depth => $depth, + indent_count => $indent_count, + }; + } + +} # Convert + + +sub _encode_ascii { + join('', + map { + $_ <= 127 ? + chr($_) : + $_ <= 65535 ? + sprintf('\u%04x', $_) : sprintf('\u%x\u%x', _encode_surrogates($_)); + } unpack('U*', $_[0]) + ); +} + + +sub _encode_latin1 { + join('', + map { + $_ <= 255 ? + chr($_) : + $_ <= 65535 ? + sprintf('\u%04x', $_) : sprintf('\u%x\u%x', _encode_surrogates($_)); + } unpack('U*', $_[0]) + ); +} + + +sub _encode_surrogates { # from perlunicode + my $uni = $_[0] - 0x10000; + return ($uni / 0x400 + 0xD800, $uni % 0x400 + 0xDC00); +} + + +sub _is_bignum { + $_[0]->isa('Math::BigInt') or $_[0]->isa('Math::BigFloat'); +} + + + +# +# JSON => Perl +# + +my $max_intsize; + +BEGIN { + my $checkint = 1111; + for my $d (5..64) { + $checkint .= 1; + my $int = eval qq| $checkint |; + if ($int =~ /[eE]/) { + $max_intsize = $d - 1; + last; + } + } +} + +{ # PARSE + + my %escapes = ( # by Jeremy Muhlich + b => "\x8", + t => "\x9", + n => "\xA", + f => "\xC", + r => "\xD", + '\\' => '\\', + '"' => '"', + '/' => '/', + ); + + my $text; # json data + my $at; # offset + my $ch; # 1chracter + my $len; # text length (changed according to UTF8 or NON UTF8) + # INTERNAL + my $depth; # nest counter + my $encoding; # json text encoding + my $is_valid_utf8; # temp variable + my $utf8_len; # utf8 byte length + # FLAGS + my $utf8; # must be utf8 + my $max_depth; # max nest nubmer of objects and arrays + my $max_size; + my $relaxed; + my $cb_object; + my $cb_sk_object; + + my $F_HOOK; + + my $allow_bigint; # using Math::BigInt + my $singlequote; # loosely quoting + my $loose; # + my $allow_barekey; # bareKey + + # $opt flag + # 0x00000001 .... decode_prefix + # 0x10000000 .... incr_parse + + sub PP_decode_json { + my ($self, $opt); # $opt is an effective flag during this decode_json. + + ($self, $text, $opt) = @_; + + ($at, $ch, $depth) = (0, '', 0); + + if ( !defined $text or ref $text ) { + decode_error("malformed JSON string, neither array, object, number, string or atom"); + } + + my $idx = $self->{PROPS}; + + ($utf8, $relaxed, $loose, $allow_bigint, $allow_barekey, $singlequote) + = @{$idx}[P_UTF8, P_RELAXED, P_LOOSE .. P_ALLOW_SINGLEQUOTE]; + + if ( $utf8 ) { + utf8::downgrade( $text, 1 ) or Carp::croak("Wide character in subroutine entry"); + } + else { + utf8::upgrade( $text ); + } + + $len = length $text; + + ($max_depth, $max_size, $cb_object, $cb_sk_object, $F_HOOK) + = @{$self}{qw/max_depth max_size cb_object cb_sk_object F_HOOK/}; + + if ($max_size > 1) { + use bytes; + my $bytes = length $text; + decode_error( + sprintf("attempted decode of JSON text of %s bytes size, but max_size is set to %s" + , $bytes, $max_size), 1 + ) if ($bytes > $max_size); + } + + # Currently no effect + # should use regexp + my @octets = unpack('C4', $text); + $encoding = ( $octets[0] and $octets[1]) ? 'UTF-8' + : (!$octets[0] and $octets[1]) ? 'UTF-16BE' + : (!$octets[0] and !$octets[1]) ? 'UTF-32BE' + : ( $octets[2] ) ? 'UTF-16LE' + : (!$octets[2] ) ? 'UTF-32LE' + : 'unknown'; + + white(); # remove head white space + + my $valid_start = defined $ch; # Is there a first character for JSON structure? + + my $result = value(); + + return undef if ( !$result && ( $opt & 0x10000000 ) ); # for incr_parse + + decode_error("malformed JSON string, neither array, object, number, string or atom") unless $valid_start; + + if ( !$idx->[ P_ALLOW_NONREF ] and !ref $result ) { + decode_error( + 'JSON text must be an object or array (but found number, string, true, false or null,' + . ' use allow_nonref to allow this)', 1); + } + + Carp::croak('something wrong.') if $len < $at; # we won't arrive here. + + my $consumed = defined $ch ? $at - 1 : $at; # consumed JSON text length + + white(); # remove tail white space + + if ( $ch ) { + return ( $result, $consumed ) if ($opt & 0x00000001); # all right if decode_prefix + decode_error("garbage after JSON object"); + } + + ( $opt & 0x00000001 ) ? ( $result, $consumed ) : $result; + } + + + sub next_chr { + return $ch = undef if($at >= $len); + $ch = substr($text, $at++, 1); + } + + + sub value { + white(); + return if(!defined $ch); + return object() if($ch eq '{'); + return array() if($ch eq '['); + return string() if($ch eq '"' or ($singlequote and $ch eq "'")); + return number() if($ch =~ /[0-9]/ or $ch eq '-'); + return word(); + } + + sub string { + my ($i, $s, $t, $u); + my $utf16; + my $is_utf8; + + ($is_valid_utf8, $utf8_len) = ('', 0); + + $s = ''; # basically UTF8 flag on + + if($ch eq '"' or ($singlequote and $ch eq "'")){ + my $boundChar = $ch; + + OUTER: while( defined(next_chr()) ){ + + if($ch eq $boundChar){ + next_chr(); + + if ($utf16) { + decode_error("missing low surrogate character in surrogate pair"); + } + + utf8::decode($s) if($is_utf8); + + return $s; + } + elsif($ch eq '\\'){ + next_chr(); + if(exists $escapes{$ch}){ + $s .= $escapes{$ch}; + } + elsif($ch eq 'u'){ # UNICODE handling + my $u = ''; + + for(1..4){ + $ch = next_chr(); + last OUTER if($ch !~ /[0-9a-fA-F]/); + $u .= $ch; + } + + # U+D800 - U+DBFF + if ($u =~ /^[dD][89abAB][0-9a-fA-F]{2}/) { # UTF-16 high surrogate? + $utf16 = $u; + } + # U+DC00 - U+DFFF + elsif ($u =~ /^[dD][c-fC-F][0-9a-fA-F]{2}/) { # UTF-16 low surrogate? + unless (defined $utf16) { + decode_error("missing high surrogate character in surrogate pair"); + } + $is_utf8 = 1; + $s .= JSON_PP_decode_surrogates($utf16, $u) || next; + $utf16 = undef; + } + else { + if (defined $utf16) { + decode_error("surrogate pair expected"); + } + + if ( ( my $hex = hex( $u ) ) > 127 ) { + $is_utf8 = 1; + $s .= JSON_PP_decode_unicode($u) || next; + } + else { + $s .= chr $hex; + } + } + + } + else{ + unless ($loose) { + $at -= 2; + decode_error('illegal backslash escape sequence in string'); + } + $s .= $ch; + } + } + else{ + + if ( ord $ch > 127 ) { + if ( $utf8 ) { + unless( $ch = is_valid_utf8($ch) ) { + $at -= 1; + decode_error("malformed UTF-8 character in JSON string"); + } + else { + $at += $utf8_len - 1; + } + } + else { + utf8::encode( $ch ); + } + + $is_utf8 = 1; + } + + if (!$loose) { + if ($ch =~ /[\x00-\x1f\x22\x5c]/) { # '/' ok + $at--; + decode_error('invalid character encountered while parsing JSON string'); + } + } + + $s .= $ch; + } + } + } + + decode_error("unexpected end of string while parsing JSON string"); + } + + + sub white { + while( defined $ch ){ + if($ch le ' '){ + next_chr(); + } + elsif($ch eq '/'){ + next_chr(); + if(defined $ch and $ch eq '/'){ + 1 while(defined(next_chr()) and $ch ne "\n" and $ch ne "\r"); + } + elsif(defined $ch and $ch eq '*'){ + next_chr(); + while(1){ + if(defined $ch){ + if($ch eq '*'){ + if(defined(next_chr()) and $ch eq '/'){ + next_chr(); + last; + } + } + else{ + next_chr(); + } + } + else{ + decode_error("Unterminated comment"); + } + } + next; + } + else{ + $at--; + decode_error("malformed JSON string, neither array, object, number, string or atom"); + } + } + else{ + if ($relaxed and $ch eq '#') { # correctly? + pos($text) = $at; + $text =~ /\G([^\n]*(?:\r\n|\r|\n|$))/g; + $at = pos($text); + next_chr; + next; + } + + last; + } + } + } + + + sub array { + my $a = $_[0] || []; # you can use this code to use another array ref object. + + decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)') + if (++$depth > $max_depth); + + next_chr(); + white(); + + if(defined $ch and $ch eq ']'){ + --$depth; + next_chr(); + return $a; + } + else { + while(defined($ch)){ + push @$a, value(); + + white(); + + if (!defined $ch) { + last; + } + + if($ch eq ']'){ + --$depth; + next_chr(); + return $a; + } + + if($ch ne ','){ + last; + } + + next_chr(); + white(); + + if ($relaxed and $ch eq ']') { + --$depth; + next_chr(); + return $a; + } + + } + } + + decode_error(", or ] expected while parsing array"); + } + + + sub object { + my $o = $_[0] || {}; # you can use this code to use another hash ref object. + my $k; + + decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)') + if (++$depth > $max_depth); + next_chr(); + white(); + + if(defined $ch and $ch eq '}'){ + --$depth; + next_chr(); + if ($F_HOOK) { + return _json_object_hook($o); + } + return $o; + } + else { + while (defined $ch) { + $k = ($allow_barekey and $ch ne '"' and $ch ne "'") ? bareKey() : string(); + white(); + + if(!defined $ch or $ch ne ':'){ + $at--; + decode_error("':' expected"); + } + + next_chr(); + $o->{$k} = value(); + white(); + + last if (!defined $ch); + + if($ch eq '}'){ + --$depth; + next_chr(); + if ($F_HOOK) { + return _json_object_hook($o); + } + return $o; + } + + if($ch ne ','){ + last; + } + + next_chr(); + white(); + + if ($relaxed and $ch eq '}') { + --$depth; + next_chr(); + if ($F_HOOK) { + return _json_object_hook($o); + } + return $o; + } + + } + + } + + $at--; + decode_error(", or } expected while parsing object/hash"); + } + + + sub bareKey { # doesn't strictly follow Standard ECMA-262 3rd Edition + my $key; + while($ch =~ /[^\x00-\x23\x25-\x2F\x3A-\x40\x5B-\x5E\x60\x7B-\x7F]/){ + $key .= $ch; + next_chr(); + } + return $key; + } + + + sub word { + my $word = substr($text,$at-1,4); + + if($word eq 'true'){ + $at += 3; + next_chr; + return $JSON::PP::true; + } + elsif($word eq 'null'){ + $at += 3; + next_chr; + return undef; + } + elsif($word eq 'fals'){ + $at += 3; + if(substr($text,$at,1) eq 'e'){ + $at++; + next_chr; + return $JSON::PP::false; + } + } + + $at--; # for decode_error report + + decode_error("'null' expected") if ($word =~ /^n/); + decode_error("'true' expected") if ($word =~ /^t/); + decode_error("'false' expected") if ($word =~ /^f/); + decode_error("malformed JSON string, neither array, object, number, string or atom"); + } + + + sub number { + my $n = ''; + my $v; + + # According to RFC4627, hex or oct digts are invalid. + if($ch eq '0'){ + my $peek = substr($text,$at,1); + my $hex = $peek =~ /[xX]/; # 0 or 1 + + if($hex){ + decode_error("malformed number (leading zero must not be followed by another digit)"); + ($n) = ( substr($text, $at+1) =~ /^([0-9a-fA-F]+)/); + } + else{ # oct + ($n) = ( substr($text, $at) =~ /^([0-7]+)/); + if (defined $n and length $n > 1) { + decode_error("malformed number (leading zero must not be followed by another digit)"); + } + } + + if(defined $n and length($n)){ + if (!$hex and length($n) == 1) { + decode_error("malformed number (leading zero must not be followed by another digit)"); + } + $at += length($n) + $hex; + next_chr; + return $hex ? hex($n) : oct($n); + } + } + + if($ch eq '-'){ + $n = '-'; + next_chr; + if (!defined $ch or $ch !~ /\d/) { + decode_error("malformed number (no digits after initial minus)"); + } + } + + while(defined $ch and $ch =~ /\d/){ + $n .= $ch; + next_chr; + } + + if(defined $ch and $ch eq '.'){ + $n .= '.'; + + next_chr; + if (!defined $ch or $ch !~ /\d/) { + decode_error("malformed number (no digits after decimal point)"); + } + else { + $n .= $ch; + } + + while(defined(next_chr) and $ch =~ /\d/){ + $n .= $ch; + } + } + + if(defined $ch and ($ch eq 'e' or $ch eq 'E')){ + $n .= $ch; + next_chr; + + if(defined($ch) and ($ch eq '+' or $ch eq '-')){ + $n .= $ch; + next_chr; + if (!defined $ch or $ch =~ /\D/) { + decode_error("malformed number (no digits after exp sign)"); + } + $n .= $ch; + } + elsif(defined($ch) and $ch =~ /\d/){ + $n .= $ch; + } + else { + decode_error("malformed number (no digits after exp sign)"); + } + + while(defined(next_chr) and $ch =~ /\d/){ + $n .= $ch; + } + + } + + $v .= $n; + + if ($v !~ /[.eE]/ and length $v > $max_intsize) { + if ($allow_bigint) { # from Adam Sussman + require Math::BigInt; + return Math::BigInt->new($v); + } + else { + return "$v"; + } + } + elsif ($allow_bigint) { + require Math::BigFloat; + return Math::BigFloat->new($v); + } + + return 0+$v; + } + + + sub is_valid_utf8 { + + $utf8_len = $_[0] =~ /[\x00-\x7F]/ ? 1 + : $_[0] =~ /[\xC2-\xDF]/ ? 2 + : $_[0] =~ /[\xE0-\xEF]/ ? 3 + : $_[0] =~ /[\xF0-\xF4]/ ? 4 + : 0 + ; + + return unless $utf8_len; + + my $is_valid_utf8 = substr($text, $at - 1, $utf8_len); + + return ( $is_valid_utf8 =~ /^(?: + [\x00-\x7F] + |[\xC2-\xDF][\x80-\xBF] + |[\xE0][\xA0-\xBF][\x80-\xBF] + |[\xE1-\xEC][\x80-\xBF][\x80-\xBF] + |[\xED][\x80-\x9F][\x80-\xBF] + |[\xEE-\xEF][\x80-\xBF][\x80-\xBF] + |[\xF0][\x90-\xBF][\x80-\xBF][\x80-\xBF] + |[\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF] + |[\xF4][\x80-\x8F][\x80-\xBF][\x80-\xBF] + )$/x ) ? $is_valid_utf8 : ''; + } + + + sub decode_error { + my $error = shift; + my $no_rep = shift; + my $str = defined $text ? substr($text, $at) : ''; + my $mess = ''; + my $type = $] >= 5.008 ? 'U*' + : $] < 5.006 ? 'C*' + : utf8::is_utf8( $str ) ? 'U*' # 5.6 + : 'C*' + ; + + for my $c ( unpack( $type, $str ) ) { # emulate pv_uni_display() ? + $mess .= $c == 0x07 ? '\a' + : $c == 0x09 ? '\t' + : $c == 0x0a ? '\n' + : $c == 0x0d ? '\r' + : $c == 0x0c ? '\f' + : $c < 0x20 ? sprintf('\x{%x}', $c) + : $c == 0x5c ? '\\\\' + : $c < 0x80 ? chr($c) + : sprintf('\x{%x}', $c) + ; + if ( length $mess >= 20 ) { + $mess .= '...'; + last; + } + } + + unless ( length $mess ) { + $mess = '(end of string)'; + } + + Carp::croak ( + $no_rep ? "$error" : "$error, at character offset $at (before \"$mess\")" + ); + + } + + + sub _json_object_hook { + my $o = $_[0]; + my @ks = keys %{$o}; + + if ( $cb_sk_object and @ks == 1 and exists $cb_sk_object->{ $ks[0] } and ref $cb_sk_object->{ $ks[0] } ) { + my @val = $cb_sk_object->{ $ks[0] }->( $o->{$ks[0]} ); + if (@val == 1) { + return $val[0]; + } + } + + my @val = $cb_object->($o) if ($cb_object); + if (@val == 0 or @val > 1) { + return $o; + } + else { + return $val[0]; + } + } + + + sub PP_decode_box { + { + text => $text, + at => $at, + ch => $ch, + len => $len, + depth => $depth, + encoding => $encoding, + is_valid_utf8 => $is_valid_utf8, + }; + } + +} # PARSE + + +sub _decode_surrogates { # from perlunicode + my $uni = 0x10000 + (hex($_[0]) - 0xD800) * 0x400 + (hex($_[1]) - 0xDC00); + my $un = pack('U*', $uni); + utf8::encode( $un ); + return $un; +} + + +sub _decode_unicode { + my $un = pack('U', hex shift); + utf8::encode( $un ); + return $un; +} + +# +# Setup for various Perl versions (the code from JSON::PP58) +# + +BEGIN { + + unless ( defined &utf8::is_utf8 ) { + require Encode; + *utf8::is_utf8 = *Encode::is_utf8; + } + + if ( $] >= 5.008 ) { + *JSON::PP::JSON_PP_encode_ascii = \&_encode_ascii; + *JSON::PP::JSON_PP_encode_latin1 = \&_encode_latin1; + *JSON::PP::JSON_PP_decode_surrogates = \&_decode_surrogates; + *JSON::PP::JSON_PP_decode_unicode = \&_decode_unicode; + } + + if ($] >= 5.008 and $] < 5.008003) { # join() in 5.8.0 - 5.8.2 is broken. + package JSON::PP; + require subs; + subs->import('join'); + eval q| + sub join { + return '' if (@_ < 2); + my $j = shift; + my $str = shift; + for (@_) { $str .= $j . $_; } + return $str; + } + |; + } + + + sub JSON::PP::incr_parse { + local $Carp::CarpLevel = 1; + ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_parse( @_ ); + } + + + sub JSON::PP::incr_skip { + ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_skip; + } + + + sub JSON::PP::incr_reset { + ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_reset; + } + + eval q{ + sub JSON::PP::incr_text : lvalue { + $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new; + + if ( $_[0]->{_incr_parser}->{incr_parsing} ) { + Carp::croak("incr_text can not be called when the incremental parser already started parsing"); + } + $_[0]->{_incr_parser}->{incr_text}; + } + } if ( $] >= 5.006 ); + +} # Setup for various Perl versions (the code from JSON::PP58) + + +############################### +# Utilities +# + +BEGIN { + eval 'require Scalar::Util'; + unless($@){ + *JSON::PP::blessed = \&Scalar::Util::blessed; + *JSON::PP::reftype = \&Scalar::Util::reftype; + *JSON::PP::refaddr = \&Scalar::Util::refaddr; + } + else{ # This code is from Sclar::Util. + # warn $@; + eval 'sub UNIVERSAL::a_sub_not_likely_to_be_here { ref($_[0]) }'; + *JSON::PP::blessed = sub { + local($@, $SIG{__DIE__}, $SIG{__WARN__}); + ref($_[0]) ? eval { $_[0]->a_sub_not_likely_to_be_here } : undef; + }; + my %tmap = qw( + B::NULL SCALAR + B::HV HASH + B::AV ARRAY + B::CV CODE + B::IO IO + B::GV GLOB + B::REGEXP REGEXP + ); + *JSON::PP::reftype = sub { + my $r = shift; + + return undef unless length(ref($r)); + + my $t = ref(B::svref_2object($r)); + + return + exists $tmap{$t} ? $tmap{$t} + : length(ref($$r)) ? 'REF' + : 'SCALAR'; + }; + *JSON::PP::refaddr = sub { + return undef unless length(ref($_[0])); + + my $addr; + if(defined(my $pkg = blessed($_[0]))) { + $addr .= bless $_[0], 'Scalar::Util::Fake'; + bless $_[0], $pkg; + } + else { + $addr .= $_[0] + } + + $addr =~ /0x(\w+)/; + local $^W; + #no warnings 'portable'; + hex($1); + } + } +} + + +# shamely copied and modified from JSON::XS code. + +$JSON::PP::true = do { bless \(my $dummy = 1), "JSON::backportPP::Boolean" }; +$JSON::PP::false = do { bless \(my $dummy = 0), "JSON::backportPP::Boolean" }; + +sub is_bool { defined $_[0] and UNIVERSAL::isa($_[0], "JSON::PP::Boolean"); } + +sub true { $JSON::PP::true } +sub false { $JSON::PP::false } +sub null { undef; } + +############################### + +package JSON::backportPP::Boolean; + +@JSON::backportPP::Boolean::ISA = ('JSON::PP::Boolean'); +use overload ( + "0+" => sub { ${$_[0]} }, + "++" => sub { $_[0] = ${$_[0]} + 1 }, + "--" => sub { $_[0] = ${$_[0]} - 1 }, + fallback => 1, +); + + +############################### + +package + JSON::PP::IncrParser; + +use strict; + +use constant INCR_M_WS => 0; # initial whitespace skipping +use constant INCR_M_STR => 1; # inside string +use constant INCR_M_BS => 2; # inside backslash +use constant INCR_M_JSON => 3; # outside anything, count nesting +use constant INCR_M_C0 => 4; +use constant INCR_M_C1 => 5; + +$JSON::PP::IncrParser::VERSION = '1.01'; + +my $unpack_format = $] < 5.006 ? 'C*' : 'U*'; + +sub new { + my ( $class ) = @_; + + bless { + incr_nest => 0, + incr_text => undef, + incr_parsing => 0, + incr_p => 0, + }, $class; +} + + +sub incr_parse { + my ( $self, $coder, $text ) = @_; + + $self->{incr_text} = '' unless ( defined $self->{incr_text} ); + + if ( defined $text ) { + if ( utf8::is_utf8( $text ) and !utf8::is_utf8( $self->{incr_text} ) ) { + utf8::upgrade( $self->{incr_text} ) ; + utf8::decode( $self->{incr_text} ) ; + } + $self->{incr_text} .= $text; + } + + + my $max_size = $coder->get_max_size; + + if ( defined wantarray ) { + + $self->{incr_mode} = INCR_M_WS unless defined $self->{incr_mode}; + + if ( wantarray ) { + my @ret; + + $self->{incr_parsing} = 1; + + do { + push @ret, $self->_incr_parse( $coder, $self->{incr_text} ); + + unless ( !$self->{incr_nest} and $self->{incr_mode} == INCR_M_JSON ) { + $self->{incr_mode} = INCR_M_WS if $self->{incr_mode} != INCR_M_STR; + } + + } until ( length $self->{incr_text} >= $self->{incr_p} ); + + $self->{incr_parsing} = 0; + + return @ret; + } + else { # in scalar context + $self->{incr_parsing} = 1; + my $obj = $self->_incr_parse( $coder, $self->{incr_text} ); + $self->{incr_parsing} = 0 if defined $obj; # pointed by Martin J. Evans + return $obj ? $obj : undef; # $obj is an empty string, parsing was completed. + } + + } + +} + + +sub _incr_parse { + my ( $self, $coder, $text, $skip ) = @_; + my $p = $self->{incr_p}; + my $restore = $p; + + my @obj; + my $len = length $text; + + if ( $self->{incr_mode} == INCR_M_WS ) { + while ( $len > $p ) { + my $s = substr( $text, $p, 1 ); + $p++ and next if ( 0x20 >= unpack($unpack_format, $s) ); + $self->{incr_mode} = INCR_M_JSON; + last; + } + } + + while ( $len > $p ) { + my $s = substr( $text, $p++, 1 ); + + if ( $s eq '"' ) { + if (substr( $text, $p - 2, 1 ) eq '\\' ) { + next; + } + + if ( $self->{incr_mode} != INCR_M_STR ) { + $self->{incr_mode} = INCR_M_STR; + } + else { + $self->{incr_mode} = INCR_M_JSON; + unless ( $self->{incr_nest} ) { + last; + } + } + } + + if ( $self->{incr_mode} == INCR_M_JSON ) { + + if ( $s eq '[' or $s eq '{' ) { + if ( ++$self->{incr_nest} > $coder->get_max_depth ) { + Carp::croak('json text or perl structure exceeds maximum nesting level (max_depth set too low?)'); + } + } + elsif ( $s eq ']' or $s eq '}' ) { + last if ( --$self->{incr_nest} <= 0 ); + } + elsif ( $s eq '#' ) { + while ( $len > $p ) { + last if substr( $text, $p++, 1 ) eq "\n"; + } + } + + } + + } + + $self->{incr_p} = $p; + + return if ( $self->{incr_mode} == INCR_M_STR and not $self->{incr_nest} ); + return if ( $self->{incr_mode} == INCR_M_JSON and $self->{incr_nest} > 0 ); + + return '' unless ( length substr( $self->{incr_text}, 0, $p ) ); + + local $Carp::CarpLevel = 2; + + $self->{incr_p} = $restore; + $self->{incr_c} = $p; + + my ( $obj, $tail ) = $coder->PP_decode_json( substr( $self->{incr_text}, 0, $p ), 0x10000001 ); + + $self->{incr_text} = substr( $self->{incr_text}, $p ); + $self->{incr_p} = 0; + + return $obj or ''; +} + + +sub incr_text { + if ( $_[0]->{incr_parsing} ) { + Carp::croak("incr_text can not be called when the incremental parser already started parsing"); + } + $_[0]->{incr_text}; +} + + +sub incr_skip { + my $self = shift; + $self->{incr_text} = substr( $self->{incr_text}, $self->{incr_c} ); + $self->{incr_p} = 0; +} + + +sub incr_reset { + my $self = shift; + $self->{incr_text} = undef; + $self->{incr_p} = 0; + $self->{incr_mode} = 0; + $self->{incr_nest} = 0; + $self->{incr_parsing} = 0; +} + +############################### + + +1; +__END__ +=pod + +=head1 NAME + +JSON::PP - JSON::XS compatible pure-Perl module. + +=head1 SYNOPSIS + + use JSON::PP; + + # exported functions, they croak on error + # and expect/generate UTF-8 + + $utf8_encoded_json_text = encode_json $perl_hash_or_arrayref; + $perl_hash_or_arrayref = decode_json $utf8_encoded_json_text; + + # OO-interface + + $coder = JSON::PP->new->ascii->pretty->allow_nonref; + + $json_text = $json->encode( $perl_scalar ); + $perl_scalar = $json->decode( $json_text ); + + $pretty_printed = $json->pretty->encode( $perl_scalar ); # pretty-printing + + # Note that JSON version 2.0 and above will automatically use + # JSON::XS or JSON::PP, so you should be able to just: + + use JSON; + + +=head1 VERSION + + 2.27200 + +L 2.27 (~2.30) compatible. + +=head1 DESCRIPTION + +This module is L compatible pure Perl module. +(Perl 5.8 or later is recommended) + +JSON::XS is the fastest and most proper JSON module on CPAN. +It is written by Marc Lehmann in C, so must be compiled and +installed in the used environment. + +JSON::PP is a pure-Perl module and has compatibility to JSON::XS. + + +=head2 FEATURES + +=over + +=item * correct unicode handling + +This module knows how to handle Unicode (depending on Perl version). + +See to L and L. + + +=item * round-trip integrity + +When you serialise a perl data structure using only data types supported +by JSON and Perl, the deserialised data structure is identical on the Perl +level. (e.g. the string "2.0" doesn't suddenly become "2" just because +it looks like a number). There I minor exceptions to this, read the +MAPPING section below to learn about those. + + +=item * strict checking of JSON correctness + +There is no guessing, no generating of illegal JSON texts by default, +and only JSON is accepted as input by default (the latter is a security feature). +But when some options are set, loose chcking features are available. + +=back + +=head1 FUNCTIONAL INTERFACE + +Some documents are copied and modified from L. + +=head2 encode_json + + $json_text = encode_json $perl_scalar + +Converts the given Perl data structure to a UTF-8 encoded, binary string. + +This function call is functionally identical to: + + $json_text = JSON::PP->new->utf8->encode($perl_scalar) + +=head2 decode_json + + $perl_scalar = decode_json $json_text + +The opposite of C: expects an UTF-8 (binary) string and tries +to parse that as an UTF-8 encoded JSON text, returning the resulting +reference. + +This function call is functionally identical to: + + $perl_scalar = JSON::PP->new->utf8->decode($json_text) + +=head2 JSON::PP::is_bool + + $is_boolean = JSON::PP::is_bool($scalar) + +Returns true if the passed scalar represents either JSON::PP::true or +JSON::PP::false, two constants that act like C<1> and C<0> respectively +and are also used to represent JSON C and C in Perl strings. + +=head2 JSON::PP::true + +Returns JSON true value which is blessed object. +It C JSON::PP::Boolean object. + +=head2 JSON::PP::false + +Returns JSON false value which is blessed object. +It C JSON::PP::Boolean object. + +=head2 JSON::PP::null + +Returns C. + +See L, below, for more information on how JSON values are mapped to +Perl. + + +=head1 HOW DO I DECODE A DATA FROM OUTER AND ENCODE TO OUTER + +This section supposes that your perl vresion is 5.8 or later. + +If you know a JSON text from an outer world - a network, a file content, and so on, +is encoded in UTF-8, you should use C or C module object +with C enable. And the decoded result will contain UNICODE characters. + + # from network + my $json = JSON::PP->new->utf8; + my $json_text = CGI->new->param( 'json_data' ); + my $perl_scalar = $json->decode( $json_text ); + + # from file content + local $/; + open( my $fh, '<', 'json.data' ); + $json_text = <$fh>; + $perl_scalar = decode_json( $json_text ); + +If an outer data is not encoded in UTF-8, firstly you should C it. + + use Encode; + local $/; + open( my $fh, '<', 'json.data' ); + my $encoding = 'cp932'; + my $unicode_json_text = decode( $encoding, <$fh> ); # UNICODE + + # or you can write the below code. + # + # open( my $fh, "<:encoding($encoding)", 'json.data' ); + # $unicode_json_text = <$fh>; + +In this case, C<$unicode_json_text> is of course UNICODE string. +So you B use C nor C module object with C enable. +Instead of them, you use C module object with C disable. + + $perl_scalar = $json->utf8(0)->decode( $unicode_json_text ); + +Or C and C: + + $perl_scalar = decode_json( encode( 'utf8', $unicode_json_text ) ); + # this way is not efficient. + +And now, you want to convert your C<$perl_scalar> into JSON data and +send it to an outer world - a network or a file content, and so on. + +Your data usually contains UNICODE strings and you want the converted data to be encoded +in UTF-8, you should use C or C module object with C enable. + + print encode_json( $perl_scalar ); # to a network? file? or display? + # or + print $json->utf8->encode( $perl_scalar ); + +If C<$perl_scalar> does not contain UNICODE but C<$encoding>-encoded strings +for some reason, then its characters are regarded as B for perl +(because it does not concern with your $encoding). +You B use C nor C module object with C enable. +Instead of them, you use C module object with C disable. +Note that the resulted text is a UNICODE string but no problem to print it. + + # $perl_scalar contains $encoding encoded string values + $unicode_json_text = $json->utf8(0)->encode( $perl_scalar ); + # $unicode_json_text consists of characters less than 0x100 + print $unicode_json_text; + +Or C all string values and C: + + $perl_scalar->{ foo } = decode( $encoding, $perl_scalar->{ foo } ); + # ... do it to each string values, then encode_json + $json_text = encode_json( $perl_scalar ); + +This method is a proper way but probably not efficient. + +See to L, L. + + +=head1 METHODS + +Basically, check to L or L. + +=head2 new + + $json = JSON::PP->new + +Rturns a new JSON::PP object that can be used to de/encode JSON +strings. + +All boolean flags described below are by default I. + +The mutators for flags all return the JSON object again and thus calls can +be chained: + + my $json = JSON::PP->new->utf8->space_after->encode({a => [1,2]}) + => {"a": [1, 2]} + +=head2 ascii + + $json = $json->ascii([$enable]) + + $enabled = $json->get_ascii + +If $enable is true (or missing), then the encode method will not generate characters outside +the code range 0..127. Any Unicode characters outside that range will be escaped using either +a single \uXXXX or a double \uHHHH\uLLLLL escape sequence, as per RFC4627. +(See to L). + +In Perl 5.005, there is no character having high value (more than 255). +See to L. + +If $enable is false, then the encode method will not escape Unicode characters unless +required by the JSON syntax or other flags. This results in a faster and more compact format. + + JSON::PP->new->ascii(1)->encode([chr 0x10401]) + => ["\ud801\udc01"] + +=head2 latin1 + + $json = $json->latin1([$enable]) + + $enabled = $json->get_latin1 + +If $enable is true (or missing), then the encode method will encode the resulting JSON +text as latin1 (or iso-8859-1), escaping any characters outside the code range 0..255. + +If $enable is false, then the encode method will not escape Unicode characters +unless required by the JSON syntax or other flags. + + JSON::XS->new->latin1->encode (["\x{89}\x{abc}"] + => ["\x{89}\\u0abc"] # (perl syntax, U+abc escaped, U+89 not) + +See to L. + +=head2 utf8 + + $json = $json->utf8([$enable]) + + $enabled = $json->get_utf8 + +If $enable is true (or missing), then the encode method will encode the JSON result +into UTF-8, as required by many protocols, while the decode method expects to be handled +an UTF-8-encoded string. Please note that UTF-8-encoded strings do not contain any +characters outside the range 0..255, they are thus useful for bytewise/binary I/O. + +(In Perl 5.005, any character outside the range 0..255 does not exist. +See to L.) + +In future versions, enabling this option might enable autodetection of the UTF-16 and UTF-32 +encoding families, as described in RFC4627. + +If $enable is false, then the encode method will return the JSON string as a (non-encoded) +Unicode string, while decode expects thus a Unicode string. Any decoding or encoding +(e.g. to UTF-8 or UTF-16) needs to be done yourself, e.g. using the Encode module. + +Example, output UTF-16BE-encoded JSON: + + use Encode; + $jsontext = encode "UTF-16BE", JSON::PP->new->encode ($object); + +Example, decode UTF-32LE-encoded JSON: + + use Encode; + $object = JSON::PP->new->decode (decode "UTF-32LE", $jsontext); + + +=head2 pretty + + $json = $json->pretty([$enable]) + +This enables (or disables) all of the C, C and +C flags in one call to generate the most readable +(or most compact) form possible. + +Equivalent to: + + $json->indent->space_before->space_after + +=head2 indent + + $json = $json->indent([$enable]) + + $enabled = $json->get_indent + +The default indent space length is three. +You can use C to change the length. + +=head2 space_before + + $json = $json->space_before([$enable]) + + $enabled = $json->get_space_before + +If C<$enable> is true (or missing), then the C method will add an extra +optional space before the C<:> separating keys from values in JSON objects. + +If C<$enable> is false, then the C method will not add any extra +space at those places. + +This setting has no effect when decoding JSON texts. + +Example, space_before enabled, space_after and indent disabled: + + {"key" :"value"} + +=head2 space_after + + $json = $json->space_after([$enable]) + + $enabled = $json->get_space_after + +If C<$enable> is true (or missing), then the C method will add an extra +optional space after the C<:> separating keys from values in JSON objects +and extra whitespace after the C<,> separating key-value pairs and array +members. + +If C<$enable> is false, then the C method will not add any extra +space at those places. + +This setting has no effect when decoding JSON texts. + +Example, space_before and indent disabled, space_after enabled: + + {"key": "value"} + +=head2 relaxed + + $json = $json->relaxed([$enable]) + + $enabled = $json->get_relaxed + +If C<$enable> is true (or missing), then C will accept some +extensions to normal JSON syntax (see below). C will not be +affected in anyway. I. I suggest only to use this option to +parse application-specific files written by humans (configuration files, +resource files etc.) + +If C<$enable> is false (the default), then C will only accept +valid JSON texts. + +Currently accepted extensions are: + +=over 4 + +=item * list items can have an end-comma + +JSON I array elements and key-value pairs with commas. This +can be annoying if you write JSON texts manually and want to be able to +quickly append elements, so this extension accepts comma at the end of +such items not just between them: + + [ + 1, + 2, <- this comma not normally allowed + ] + { + "k1": "v1", + "k2": "v2", <- this comma not normally allowed + } + +=item * shell-style '#'-comments + +Whenever JSON allows whitespace, shell-style comments are additionally +allowed. They are terminated by the first carriage-return or line-feed +character, after which more white-space and comments are allowed. + + [ + 1, # this comment not allowed in JSON + # neither this one... + ] + +=back + +=head2 canonical + + $json = $json->canonical([$enable]) + + $enabled = $json->get_canonical + +If C<$enable> is true (or missing), then the C method will output JSON objects +by sorting their keys. This is adding a comparatively high overhead. + +If C<$enable> is false, then the C method will output key-value +pairs in the order Perl stores them (which will likely change between runs +of the same script). + +This option is useful if you want the same data structure to be encoded as +the same JSON text (given the same overall settings). If it is disabled, +the same hash might be encoded differently even if contains the same data, +as key-value pairs have no inherent ordering in Perl. + +This setting has no effect when decoding JSON texts. + +If you want your own sorting routine, you can give a code referece +or a subroutine name to C. See to C. + +=head2 allow_nonref + + $json = $json->allow_nonref([$enable]) + + $enabled = $json->get_allow_nonref + +If C<$enable> is true (or missing), then the C method can convert a +non-reference into its corresponding string, number or null JSON value, +which is an extension to RFC4627. Likewise, C will accept those JSON +values instead of croaking. + +If C<$enable> is false, then the C method will croak if it isn't +passed an arrayref or hashref, as JSON texts must either be an object +or array. Likewise, C will croak if given something that is not a +JSON object or array. + + JSON::PP->new->allow_nonref->encode ("Hello, World!") + => "Hello, World!" + +=head2 allow_unknown + + $json = $json->allow_unknown ([$enable]) + + $enabled = $json->get_allow_unknown + +If $enable is true (or missing), then "encode" will *not* throw an +exception when it encounters values it cannot represent in JSON (for +example, filehandles) but instead will encode a JSON "null" value. +Note that blessed objects are not included here and are handled +separately by c. + +If $enable is false (the default), then "encode" will throw an +exception when it encounters anything it cannot encode as JSON. + +This option does not affect "decode" in any way, and it is +recommended to leave it off unless you know your communications +partner. + +=head2 allow_blessed + + $json = $json->allow_blessed([$enable]) + + $enabled = $json->get_allow_blessed + +If C<$enable> is true (or missing), then the C method will not +barf when it encounters a blessed reference. Instead, the value of the +B option will decide whether C (C +disabled or no C method found) or a representation of the +object (C enabled and C method found) is being +encoded. Has no effect on C. + +If C<$enable> is false (the default), then C will throw an +exception when it encounters a blessed object. + +=head2 convert_blessed + + $json = $json->convert_blessed([$enable]) + + $enabled = $json->get_convert_blessed + +If C<$enable> is true (or missing), then C, upon encountering a +blessed object, will check for the availability of the C method +on the object's class. If found, it will be called in scalar context +and the resulting scalar will be encoded instead of the object. If no +C method is found, the value of C will decide what +to do. + +The C method may safely call die if it wants. If C +returns other blessed objects, those will be handled in the same +way. C must take care of not causing an endless recursion cycle +(== crash) in this case. The name of C was chosen because other +methods called by the Perl core (== not by the user of the object) are +usually in upper case letters and to avoid collisions with the C +function or method. + +This setting does not yet influence C in any way. + +If C<$enable> is false, then the C setting will decide what +to do when a blessed object is found. + +=head2 filter_json_object + + $json = $json->filter_json_object([$coderef]) + +When C<$coderef> is specified, it will be called from C each +time it decodes a JSON object. The only argument passed to the coderef +is a reference to the newly-created hash. If the code references returns +a single scalar (which need not be a reference), this value +(i.e. a copy of that scalar to avoid aliasing) is inserted into the +deserialised data structure. If it returns an empty list +(NOTE: I C, which is a valid scalar), the original deserialised +hash will be inserted. This setting can slow down decoding considerably. + +When C<$coderef> is omitted or undefined, any existing callback will +be removed and C will not change the deserialised hash in any +way. + +Example, convert all JSON objects into the integer 5: + + my $js = JSON::PP->new->filter_json_object (sub { 5 }); + # returns [5] + $js->decode ('[{}]'); # the given subroutine takes a hash reference. + # throw an exception because allow_nonref is not enabled + # so a lone 5 is not allowed. + $js->decode ('{"a":1, "b":2}'); + +=head2 filter_json_single_key_object + + $json = $json->filter_json_single_key_object($key [=> $coderef]) + +Works remotely similar to C, but is only called for +JSON objects having a single key named C<$key>. + +This C<$coderef> is called before the one specified via +C, if any. It gets passed the single value in the JSON +object. If it returns a single value, it will be inserted into the data +structure. If it returns nothing (not even C but the empty list), +the callback from C will be called next, as if no +single-key callback were specified. + +If C<$coderef> is omitted or undefined, the corresponding callback will be +disabled. There can only ever be one callback for a given key. + +As this callback gets called less often then the C +one, decoding speed will not usually suffer as much. Therefore, single-key +objects make excellent targets to serialise Perl objects into, especially +as single-key JSON objects are as close to the type-tagged value concept +as JSON gets (it's basically an ID/VALUE tuple). Of course, JSON does not +support this in any way, so you need to make sure your data never looks +like a serialised Perl hash. + +Typical names for the single object key are C<__class_whatever__>, or +C<$__dollars_are_rarely_used__$> or C<}ugly_brace_placement>, or even +things like C<__class_md5sum(classname)__>, to reduce the risk of clashing +with real hashes. + +Example, decode JSON objects of the form C<< { "__widget__" => } >> +into the corresponding C<< $WIDGET{} >> object: + + # return whatever is in $WIDGET{5}: + JSON::PP + ->new + ->filter_json_single_key_object (__widget__ => sub { + $WIDGET{ $_[0] } + }) + ->decode ('{"__widget__": 5') + + # this can be used with a TO_JSON method in some "widget" class + # for serialisation to json: + sub WidgetBase::TO_JSON { + my ($self) = @_; + + unless ($self->{id}) { + $self->{id} = ..get..some..id..; + $WIDGET{$self->{id}} = $self; + } + + { __widget__ => $self->{id} } + } + +=head2 shrink + + $json = $json->shrink([$enable]) + + $enabled = $json->get_shrink + +In JSON::XS, this flag resizes strings generated by either +C or C to their minimum size possible. +It will also try to downgrade any strings to octet-form if possible. + +In JSON::PP, it is noop about resizing strings but tries +C to the returned string by C. +See to L. + +See to L + +=head2 max_depth + + $json = $json->max_depth([$maximum_nesting_depth]) + + $max_depth = $json->get_max_depth + +Sets the maximum nesting level (default C<512>) accepted while encoding +or decoding. If a higher nesting level is detected in JSON text or a Perl +data structure, then the encoder and decoder will stop and croak at that +point. + +Nesting level is defined by number of hash- or arrayrefs that the encoder +needs to traverse to reach a given point or the number of C<{> or C<[> +characters without their matching closing parenthesis crossed to reach a +given character in a string. + +If no argument is given, the highest possible setting will be used, which +is rarely useful. + +See L for more info on why this is useful. + +When a large value (100 or more) was set and it de/encodes a deep nested object/text, +it may raise a warning 'Deep recursion on subroutin' at the perl runtime phase. + +=head2 max_size + + $json = $json->max_size([$maximum_string_size]) + + $max_size = $json->get_max_size + +Set the maximum length a JSON text may have (in bytes) where decoding is +being attempted. The default is C<0>, meaning no limit. When C +is called on a string that is longer then this many bytes, it will not +attempt to decode the string but throw an exception. This setting has no +effect on C (yet). + +If no argument is given, the limit check will be deactivated (same as when +C<0> is specified). + +See L for more info on why this is useful. + +=head2 encode + + $json_text = $json->encode($perl_scalar) + +Converts the given Perl data structure (a simple scalar or a reference +to a hash or array) to its JSON representation. Simple scalars will be +converted into JSON string or number sequences, while references to arrays +become JSON arrays and references to hashes become JSON objects. Undefined +Perl values (e.g. C) become JSON C values. +References to the integers C<0> and C<1> are converted into C and C. + +=head2 decode + + $perl_scalar = $json->decode($json_text) + +The opposite of C: expects a JSON text and tries to parse it, +returning the resulting simple scalar or reference. Croaks on error. + +JSON numbers and strings become simple Perl scalars. JSON arrays become +Perl arrayrefs and JSON objects become Perl hashrefs. C becomes +C<1> (C), C becomes C<0> (C) and +C becomes C. + +=head2 decode_prefix + + ($perl_scalar, $characters) = $json->decode_prefix($json_text) + +This works like the C method, but instead of raising an exception +when there is trailing garbage after the first JSON object, it will +silently stop parsing there and return the number of characters consumed +so far. + + JSON->new->decode_prefix ("[1] the tail") + => ([], 3) + +=head1 INCREMENTAL PARSING + +Most of this section are copied and modified from L. + +In some cases, there is the need for incremental parsing of JSON texts. +This module does allow you to parse a JSON stream incrementally. +It does so by accumulating text until it has a full JSON object, which +it then can decode. This process is similar to using C +to see if a full JSON object is available, but is much more efficient +(and can be implemented with a minimum of method calls). + +This module will only attempt to parse the JSON text once it is sure it +has enough text to get a decisive result, using a very simple but +truly incremental parser. This means that it sometimes won't stop as +early as the full parser, for example, it doesn't detect parenthese +mismatches. The only thing it guarantees is that it starts decoding as +soon as a syntactically valid JSON text has been seen. This means you need +to set resource limits (e.g. C) to ensure the parser will stop +parsing in the presence if syntax errors. + +The following methods implement this incremental parser. + +=head2 incr_parse + + $json->incr_parse( [$string] ) # void context + + $obj_or_undef = $json->incr_parse( [$string] ) # scalar context + + @obj_or_empty = $json->incr_parse( [$string] ) # list context + +This is the central parsing function. It can both append new text and +extract objects from the stream accumulated so far (both of these +functions are optional). + +If C<$string> is given, then this string is appended to the already +existing JSON fragment stored in the C<$json> object. + +After that, if the function is called in void context, it will simply +return without doing anything further. This can be used to add more text +in as many chunks as you want. + +If the method is called in scalar context, then it will try to extract +exactly I JSON object. If that is successful, it will return this +object, otherwise it will return C. If there is a parse error, +this method will croak just as C would do (one can then use +C to skip the errornous part). This is the most common way of +using the method. + +And finally, in list context, it will try to extract as many objects +from the stream as it can find and return them, or the empty list +otherwise. For this to work, there must be no separators between the JSON +objects or arrays, instead they must be concatenated back-to-back. If +an error occurs, an exception will be raised as in the scalar context +case. Note that in this case, any previously-parsed JSON texts will be +lost. + +Example: Parse some JSON arrays/objects in a given string and return them. + + my @objs = JSON->new->incr_parse ("[5][7][1,2]"); + +=head2 incr_text + + $lvalue_string = $json->incr_text + +This method returns the currently stored JSON fragment as an lvalue, that +is, you can manipulate it. This I works when a preceding call to +C in I successfully returned an object. Under +all other circumstances you must not call this function (I mean it. +although in simple tests it might actually work, it I fail under +real world conditions). As a special exception, you can also call this +method before having parsed anything. + +This function is useful in two cases: a) finding the trailing text after a +JSON object or b) parsing multiple JSON objects separated by non-JSON text +(such as commas). + + $json->incr_text =~ s/\s*,\s*//; + +In Perl 5.005, C attribute is not available. +You must write codes like the below: + + $string = $json->incr_text; + $string =~ s/\s*,\s*//; + $json->incr_text( $string ); + +=head2 incr_skip + + $json->incr_skip + +This will reset the state of the incremental parser and will remove the +parsed text from the input buffer. This is useful after C +died, in which case the input buffer and incremental parser state is left +unchanged, to skip the text parsed so far and to reset the parse state. + +=head2 incr_reset + + $json->incr_reset + +This completely resets the incremental parser, that is, after this call, +it will be as if the parser had never parsed anything. + +This is useful if you want ot repeatedly parse JSON objects and want to +ignore any trailing data, which means you have to reset the parser after +each successful decode. + +See to L for examples. + + +=head1 JSON::PP OWN METHODS + +=head2 allow_singlequote + + $json = $json->allow_singlequote([$enable]) + +If C<$enable> is true (or missing), then C will accept +JSON strings quoted by single quotations that are invalid JSON +format. + + $json->allow_singlequote->decode({"foo":'bar'}); + $json->allow_singlequote->decode({'foo':"bar"}); + $json->allow_singlequote->decode({'foo':'bar'}); + +As same as the C option, this option may be used to parse +application-specific files written by humans. + + +=head2 allow_barekey + + $json = $json->allow_barekey([$enable]) + +If C<$enable> is true (or missing), then C will accept +bare keys of JSON object that are invalid JSON format. + +As same as the C option, this option may be used to parse +application-specific files written by humans. + + $json->allow_barekey->decode('{foo:"bar"}'); + +=head2 allow_bignum + + $json = $json->allow_bignum([$enable]) + +If C<$enable> is true (or missing), then C will convert +the big integer Perl cannot handle as integer into a L +object and convert a floating number (any) into a L. + +On the contary, C converts C objects and C +objects into JSON numbers with C enable. + + $json->allow_nonref->allow_blessed->allow_bignum; + $bigfloat = $json->decode('2.000000000000000000000000001'); + print $json->encode($bigfloat); + # => 2.000000000000000000000000001 + +See to L aboout the normal conversion of JSON number. + +=head2 loose + + $json = $json->loose([$enable]) + +The unescaped [\x00-\x1f\x22\x2f\x5c] strings are invalid in JSON strings +and the module doesn't allow to C to these (except for \x2f). +If C<$enable> is true (or missing), then C will accept these +unescaped strings. + + $json->loose->decode(qq|["abc + def"]|); + +See L. + +=head2 escape_slash + + $json = $json->escape_slash([$enable]) + +According to JSON Grammar, I (U+002F) is escaped. But default +JSON::PP (as same as JSON::XS) encodes strings without escaping slash. + +If C<$enable> is true (or missing), then C will escape slashes. + +=head2 indent_length + + $json = $json->indent_length($length) + +JSON::XS indent space length is 3 and cannot be changed. +JSON::PP set the indent space length with the given $length. +The default is 3. The acceptable range is 0 to 15. + +=head2 sort_by + + $json = $json->sort_by($function_name) + $json = $json->sort_by($subroutine_ref) + +If $function_name or $subroutine_ref are set, its sort routine are used +in encoding JSON objects. + + $js = $pc->sort_by(sub { $JSON::PP::a cmp $JSON::PP::b })->encode($obj); + # is($js, q|{"a":1,"b":2,"c":3,"d":4,"e":5,"f":6,"g":7,"h":8,"i":9}|); + + $js = $pc->sort_by('own_sort')->encode($obj); + # is($js, q|{"a":1,"b":2,"c":3,"d":4,"e":5,"f":6,"g":7,"h":8,"i":9}|); + + sub JSON::PP::own_sort { $JSON::PP::a cmp $JSON::PP::b } + +As the sorting routine runs in the JSON::PP scope, the given +subroutine name and the special variables C<$a>, C<$b> will begin +'JSON::PP::'. + +If $integer is set, then the effect is same as C on. + +=head1 INTERNAL + +For developers. + +=over + +=item PP_encode_box + +Returns + + { + depth => $depth, + indent_count => $indent_count, + } + + +=item PP_decode_box + +Returns + + { + text => $text, + at => $at, + ch => $ch, + len => $len, + depth => $depth, + encoding => $encoding, + is_valid_utf8 => $is_valid_utf8, + }; + +=back + +=head1 MAPPING + +This section is copied from JSON::XS and modified to C. +JSON::XS and JSON::PP mapping mechanisms are almost equivalent. + +See to L. + +=head2 JSON -> PERL + +=over 4 + +=item object + +A JSON object becomes a reference to a hash in Perl. No ordering of object +keys is preserved (JSON does not preserver object key ordering itself). + +=item array + +A JSON array becomes a reference to an array in Perl. + +=item string + +A JSON string becomes a string scalar in Perl - Unicode codepoints in JSON +are represented by the same codepoints in the Perl string, so no manual +decoding is necessary. + +=item number + +A JSON number becomes either an integer, numeric (floating point) or +string scalar in perl, depending on its range and any fractional parts. On +the Perl level, there is no difference between those as Perl handles all +the conversion details, but an integer may take slightly less memory and +might represent more values exactly than floating point numbers. + +If the number consists of digits only, C will try to represent +it as an integer value. If that fails, it will try to represent it as +a numeric (floating point) value if that is possible without loss of +precision. Otherwise it will preserve the number as a string value (in +which case you lose roundtripping ability, as the JSON number will be +re-encoded toa JSON string). + +Numbers containing a fractional or exponential part will always be +represented as numeric (floating point) values, possibly at a loss of +precision (in which case you might lose perfect roundtripping ability, but +the JSON number will still be re-encoded as a JSON number). + +Note that precision is not accuracy - binary floating point values cannot +represent most decimal fractions exactly, and when converting from and to +floating point, C only guarantees precision up to but not including +the leats significant bit. + +When C is enable, the big integers +and the numeric can be optionally converted into L and +L objects. + +=item true, false + +These JSON atoms become C and C, +respectively. They are overloaded to act almost exactly like the numbers +C<1> and C<0>. You can check wether a scalar is a JSON boolean by using +the C function. + + print JSON::PP::true . "\n"; + => true + print JSON::PP::true + 1; + => 1 + + ok(JSON::true eq '1'); + ok(JSON::true == 1); + +C will install these missing overloading features to the backend modules. + + +=item null + +A JSON null atom becomes C in Perl. + +C returns C. + +=back + + +=head2 PERL -> JSON + +The mapping from Perl to JSON is slightly more difficult, as Perl is a +truly typeless language, so we can only guess which JSON type is meant by +a Perl value. + +=over 4 + +=item hash references + +Perl hash references become JSON objects. As there is no inherent ordering +in hash keys (or JSON objects), they will usually be encoded in a +pseudo-random order that can change between runs of the same program but +stays generally the same within a single run of a program. C +optionally sort the hash keys (determined by the I flag), so +the same datastructure will serialise to the same JSON text (given same +settings and version of JSON::XS), but this incurs a runtime overhead +and is only rarely useful, e.g. when you want to compare some JSON text +against another for equality. + + +=item array references + +Perl array references become JSON arrays. + +=item other references + +Other unblessed references are generally not allowed and will cause an +exception to be thrown, except for references to the integers C<0> and +C<1>, which get turned into C and C atoms in JSON. You can +also use C and C to improve readability. + + to_json [\0,JSON::PP::true] # yields [false,true] + +=item JSON::PP::true, JSON::PP::false, JSON::PP::null + +These special values become JSON true and JSON false values, +respectively. You can also use C<\1> and C<\0> directly if you want. + +JSON::PP::null returns C. + +=item blessed objects + +Blessed objects are not directly representable in JSON. See the +C and C methods on various options on +how to deal with this: basically, you can choose between throwing an +exception, encoding the reference as if it weren't blessed, or provide +your own serialiser method. + +See to L. + +=item simple scalars + +Simple Perl scalars (any scalar that is not a reference) are the most +difficult objects to encode: JSON::XS and JSON::PP will encode undefined scalars as +JSON C values, scalars that have last been used in a string context +before encoding as JSON strings, and anything else as number value: + + # dump as number + encode_json [2] # yields [2] + encode_json [-3.0e17] # yields [-3e+17] + my $value = 5; encode_json [$value] # yields [5] + + # used as string, so dump as string + print $value; + encode_json [$value] # yields ["5"] + + # undef becomes null + encode_json [undef] # yields [null] + +You can force the type to be a string by stringifying it: + + my $x = 3.1; # some variable containing a number + "$x"; # stringified + $x .= ""; # another, more awkward way to stringify + print $x; # perl does it for you, too, quite often + +You can force the type to be a number by numifying it: + + my $x = "3"; # some variable containing a string + $x += 0; # numify it, ensuring it will be dumped as a number + $x *= 1; # same thing, the choise is yours. + +You can not currently force the type in other, less obscure, ways. + +Note that numerical precision has the same meaning as under Perl (so +binary to decimal conversion follows the same rules as in Perl, which +can differ to other languages). Also, your perl interpreter might expose +extensions to the floating point numbers of your platform, such as +infinities or NaN's - these cannot be represented in JSON, and it is an +error to pass those in. + +=item Big Number + +When C is enable, +C converts C objects and C +objects into JSON numbers. + + +=back + +=head1 UNICODE HANDLING ON PERLS + +If you do not know about Unicode on Perl well, +please check L. + +=head2 Perl 5.8 and later + +Perl can handle Unicode and the JSON::PP de/encode methods also work properly. + + $json->allow_nonref->encode(chr hex 3042); + $json->allow_nonref->encode(chr hex 12345); + +Reuturns C<"\u3042"> and C<"\ud808\udf45"> respectively. + + $json->allow_nonref->decode('"\u3042"'); + $json->allow_nonref->decode('"\ud808\udf45"'); + +Returns UTF-8 encoded strings with UTF8 flag, regarded as C and C. + +Note that the versions from Perl 5.8.0 to 5.8.2, Perl built-in C was broken, +so JSON::PP wraps the C with a subroutine. Thus JSON::PP works slow in the versions. + + +=head2 Perl 5.6 + +Perl can handle Unicode and the JSON::PP de/encode methods also work. + +=head2 Perl 5.005 + +Perl 5.005 is a byte sementics world -- all strings are sequences of bytes. +That means the unicode handling is not available. + +In encoding, + + $json->allow_nonref->encode(chr hex 3042); # hex 3042 is 12354. + $json->allow_nonref->encode(chr hex 12345); # hex 12345 is 74565. + +Returns C and C, as C takes a value more than 255, it treats +as C<$value % 256>, so the above codes are equivalent to : + + $json->allow_nonref->encode(chr 66); + $json->allow_nonref->encode(chr 69); + +In decoding, + + $json->decode('"\u00e3\u0081\u0082"'); + +The returned is a byte sequence C<0xE3 0x81 0x82> for UTF-8 encoded +japanese character (C). +And if it is represented in Unicode code point, C. + +Next, + + $json->decode('"\u3042"'); + +We ordinary expect the returned value is a Unicode character C. +But here is 5.005 world. This is C<0xE3 0x81 0x82>. + + $json->decode('"\ud808\udf45"'); + +This is not a character C but bytes - C<0xf0 0x92 0x8d 0x85>. + + +=head1 TODO + +=over + +=item speed + +=item memory saving + +=back + + +=head1 SEE ALSO + +Most of the document are copied and modified from JSON::XS doc. + +L + +RFC4627 (L) + +=head1 AUTHOR + +Makamaka Hannyaharamitu, Emakamaka[at]cpan.orgE + + +=head1 COPYRIGHT AND LICENSE + +Copyright 2007-2011 by Makamaka Hannyaharamitu + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/release/src/router/uqmi/data/lib/JSON/backportPP/Boolean.pm b/release/src/router/uqmi/data/lib/JSON/backportPP/Boolean.pm new file mode 100644 index 0000000000..2646b8e3a0 --- /dev/null +++ b/release/src/router/uqmi/data/lib/JSON/backportPP/Boolean.pm @@ -0,0 +1,26 @@ +=head1 NAME + +JSON::PP::Boolean - dummy module providing JSON::PP::Boolean + +=head1 SYNOPSIS + + # do not "use" yourself + +=head1 DESCRIPTION + +This module exists only to provide overload resolution for Storable and similar modules. See +L for more info about this class. + +=cut + +use JSON::backportPP (); +use strict; + +1; + +=head1 AUTHOR + +This idea is from L written by Marc Lehmann + +=cut + diff --git a/release/src/router/uqmi/data/lib/JSON/backportPP/Compat5005.pm b/release/src/router/uqmi/data/lib/JSON/backportPP/Compat5005.pm new file mode 100644 index 0000000000..f51741c3a8 --- /dev/null +++ b/release/src/router/uqmi/data/lib/JSON/backportPP/Compat5005.pm @@ -0,0 +1,131 @@ +package # This is JSON::backportPP + JSON::backportPP5005; + +use 5.005; +use strict; + +my @properties; + +$JSON::PP5005::VERSION = '1.10'; + +BEGIN { + + sub utf8::is_utf8 { + 0; # It is considered that UTF8 flag off for Perl 5.005. + } + + sub utf8::upgrade { + } + + sub utf8::downgrade { + 1; # must always return true. + } + + sub utf8::encode { + } + + sub utf8::decode { + } + + *JSON::PP::JSON_PP_encode_ascii = \&_encode_ascii; + *JSON::PP::JSON_PP_encode_latin1 = \&_encode_latin1; + *JSON::PP::JSON_PP_decode_surrogates = \&_decode_surrogates; + *JSON::PP::JSON_PP_decode_unicode = \&_decode_unicode; + + # missing in B module. + sub B::SVp_IOK () { 0x01000000; } + sub B::SVp_NOK () { 0x02000000; } + sub B::SVp_POK () { 0x04000000; } + + $INC{'bytes.pm'} = 1; # dummy +} + + + +sub _encode_ascii { + join('', map { $_ <= 127 ? chr($_) : sprintf('\u%04x', $_) } unpack('C*', $_[0]) ); +} + + +sub _encode_latin1 { + join('', map { chr($_) } unpack('C*', $_[0]) ); +} + + +sub _decode_surrogates { # from http://homepage1.nifty.com/nomenclator/unicode/ucs_utf.htm + my $uni = 0x10000 + (hex($_[0]) - 0xD800) * 0x400 + (hex($_[1]) - 0xDC00); # from perlunicode + my $bit = unpack('B32', pack('N', $uni)); + + if ( $bit =~ /^00000000000(...)(......)(......)(......)$/ ) { + my ($w, $x, $y, $z) = ($1, $2, $3, $4); + return pack('B*', sprintf('11110%s10%s10%s10%s', $w, $x, $y, $z)); + } + else { + Carp::croak("Invalid surrogate pair"); + } +} + + +sub _decode_unicode { + my ($u) = @_; + my ($utf8bit); + + if ( $u =~ /^00([89a-f][0-9a-f])$/i ) { # 0x80-0xff + return pack( 'H2', $1 ); + } + + my $bit = unpack("B*", pack("H*", $u)); + + if ( $bit =~ /^00000(.....)(......)$/ ) { + $utf8bit = sprintf('110%s10%s', $1, $2); + } + elsif ( $bit =~ /^(....)(......)(......)$/ ) { + $utf8bit = sprintf('1110%s10%s10%s', $1, $2, $3); + } + else { + Carp::croak("Invalid escaped unicode"); + } + + return pack('B*', $utf8bit); +} + + +sub JSON::PP::incr_text { + $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new; + + if ( $_[0]->{_incr_parser}->{incr_parsing} ) { + Carp::croak("incr_text can not be called when the incremental parser already started parsing"); + } + + $_[0]->{_incr_parser}->{incr_text} = $_[1] if ( @_ > 1 ); + $_[0]->{_incr_parser}->{incr_text}; +} + + +1; +__END__ + +=pod + +=head1 NAME + +JSON::PP5005 - Helper module in using JSON::PP in Perl 5.005 + +=head1 DESCRIPTION + +JSON::PP calls internally. + +=head1 AUTHOR + +Makamaka Hannyaharamitu, Emakamaka[at]cpan.orgE + + +=head1 COPYRIGHT AND LICENSE + +Copyright 2007-2010 by Makamaka Hannyaharamitu + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut + diff --git a/release/src/router/uqmi/data/lib/JSON/backportPP/Compat5006.pm b/release/src/router/uqmi/data/lib/JSON/backportPP/Compat5006.pm new file mode 100644 index 0000000000..820dc938f7 --- /dev/null +++ b/release/src/router/uqmi/data/lib/JSON/backportPP/Compat5006.pm @@ -0,0 +1,173 @@ +package # This is JSON::backportPP + JSON::backportPP56; + +use 5.006; +use strict; + +my @properties; + +$JSON::PP56::VERSION = '1.08'; + +BEGIN { + + sub utf8::is_utf8 { + my $len = length $_[0]; # char length + { + use bytes; # byte length; + return $len != length $_[0]; # if !=, UTF8-flagged on. + } + } + + + sub utf8::upgrade { + ; # noop; + } + + + sub utf8::downgrade ($;$) { + return 1 unless ( utf8::is_utf8( $_[0] ) ); + + if ( _is_valid_utf8( $_[0] ) ) { + my $downgrade; + for my $c ( unpack( "U*", $_[0] ) ) { + if ( $c < 256 ) { + $downgrade .= pack("C", $c); + } + else { + $downgrade .= pack("U", $c); + } + } + $_[0] = $downgrade; + return 1; + } + else { + Carp::croak("Wide character in subroutine entry") unless ( $_[1] ); + 0; + } + } + + + sub utf8::encode ($) { # UTF8 flag off + if ( utf8::is_utf8( $_[0] ) ) { + $_[0] = pack( "C*", unpack( "C*", $_[0] ) ); + } + else { + $_[0] = pack( "U*", unpack( "C*", $_[0] ) ); + $_[0] = pack( "C*", unpack( "C*", $_[0] ) ); + } + } + + + sub utf8::decode ($) { # UTF8 flag on + if ( _is_valid_utf8( $_[0] ) ) { + utf8::downgrade( $_[0] ); + $_[0] = pack( "U*", unpack( "U*", $_[0] ) ); + } + } + + + *JSON::PP::JSON_PP_encode_ascii = \&_encode_ascii; + *JSON::PP::JSON_PP_encode_latin1 = \&_encode_latin1; + *JSON::PP::JSON_PP_decode_surrogates = \&JSON::PP::_decode_surrogates; + *JSON::PP::JSON_PP_decode_unicode = \&JSON::PP::_decode_unicode; + + unless ( defined &B::SVp_NOK ) { # missing in B module. + eval q{ sub B::SVp_NOK () { 0x02000000; } }; + } + +} + + + +sub _encode_ascii { + join('', + map { + $_ <= 127 ? + chr($_) : + $_ <= 65535 ? + sprintf('\u%04x', $_) : sprintf('\u%x\u%x', JSON::PP::_encode_surrogates($_)); + } _unpack_emu($_[0]) + ); +} + + +sub _encode_latin1 { + join('', + map { + $_ <= 255 ? + chr($_) : + $_ <= 65535 ? + sprintf('\u%04x', $_) : sprintf('\u%x\u%x', JSON::PP::_encode_surrogates($_)); + } _unpack_emu($_[0]) + ); +} + + +sub _unpack_emu { # for Perl 5.6 unpack warnings + return !utf8::is_utf8($_[0]) ? unpack('C*', $_[0]) + : _is_valid_utf8($_[0]) ? unpack('U*', $_[0]) + : unpack('C*', $_[0]); +} + + +sub _is_valid_utf8 { + my $str = $_[0]; + my $is_utf8; + + while ($str =~ /(?: + ( + [\x00-\x7F] + |[\xC2-\xDF][\x80-\xBF] + |[\xE0][\xA0-\xBF][\x80-\xBF] + |[\xE1-\xEC][\x80-\xBF][\x80-\xBF] + |[\xED][\x80-\x9F][\x80-\xBF] + |[\xEE-\xEF][\x80-\xBF][\x80-\xBF] + |[\xF0][\x90-\xBF][\x80-\xBF][\x80-\xBF] + |[\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF] + |[\xF4][\x80-\x8F][\x80-\xBF][\x80-\xBF] + ) + | (.) + )/xg) + { + if (defined $1) { + $is_utf8 = 1 if (!defined $is_utf8); + } + else { + $is_utf8 = 0 if (!defined $is_utf8); + if ($is_utf8) { # eventually, not utf8 + return; + } + } + } + + return $is_utf8; +} + + +1; +__END__ + +=pod + +=head1 NAME + +JSON::PP56 - Helper module in using JSON::PP in Perl 5.6 + +=head1 DESCRIPTION + +JSON::PP calls internally. + +=head1 AUTHOR + +Makamaka Hannyaharamitu, Emakamaka[at]cpan.orgE + + +=head1 COPYRIGHT AND LICENSE + +Copyright 2007-2009 by Makamaka Hannyaharamitu + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut + diff --git a/release/src/router/uqmi/data/qmi-service-ctl.json b/release/src/router/uqmi/data/qmi-service-ctl.json new file mode 100644 index 0000000000..1e293f7c97 --- /dev/null +++ b/release/src/router/uqmi/data/qmi-service-ctl.json @@ -0,0 +1,162 @@ + +[ + // ********************************************************************************* + { "name" : "CTL", + "type" : "Service" }, + + // ********************************************************************************* + { "name" : "QMI Client CTL", + "type" : "Client" }, + + // ********************************************************************************* + { "name" : "QMI Message CTL", + "type" : "Message-ID-Enum" }, + + // ********************************************************************************* + { "name" : "QMI Indication CTL", + "type" : "Indication-ID-Enum" }, + + // ********************************************************************************* + { "name" : "Set Instance ID", + "type" : "Message", + "service" : "CTL", + "id" : "0x0020", + "input" : [ { "name" : "ID", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint8" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Link ID", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint16", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Version Info", + "type" : "Message", + "service" : "CTL", + "id" : "0x0021", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Service list", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "array", + "array-element" : { "name" : "Service", + "format" : "struct", + "contents" : [ { "name" : "Service", + "format" : "guint8", + "public-format" : "QmiService" }, + { "name" : "Major version", + "format" : "guint16" }, + { "name" : "Minor version", + "format" : "guint16" } ] }, + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Allocate CID", + "type" : "Message", + "service" : "CTL", + "id" : "0x0022", + "input" : [ { "name" : "Service", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint8" , + "public-format" : "QmiService" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Allocation Info", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Service", + "format" : "guint8", + "public-format" : "QmiService" }, + { "name" : "Cid", + "format" : "guint8" } ], + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Release CID", + "type" : "Message", + "service" : "CTL", + "id" : "0x0023", + "input" : [ { "name" : "Release Info", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Service", + "format" : "guint8", + "public-format" : "QmiService" }, + { "name" : "Cid", + "format" : "guint8" } ] } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Release Info", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Service", + "format" : "guint8", + "public-format" : "QmiService" }, + { "name" : "Cid", + "format" : "guint8" } ], + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Set Data Format", + "type" : "Message", + "service" : "CTL", + "id" : "0x0026", + "input" : [ { "name" : "Format", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiCtlDataFormat" }, + { "name" : "Protocol", + "id" : "0x10", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiCtlDataLinkProtocol" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Protocol", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiCtlDataLinkProtocol" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] }, + + // ********************************************************************************* + { "name" : "Sync", + "type" : "Message", + "service" : "CTL", + "id" : "0x0027", + "output" : [ { "common-ref" : "Operation Result" } ] }, + + { "name" : "Sync", + "type" : "Indication", + "service" : "CTL", + "id" : "0x0027" }, + + // ********************************************************************************* + // Internal + { "name" : "Internal Proxy Open", + "type" : "Message", + "service" : "CTL", + "id" : "0xFF00", + "input" : [ { "name" : "Device Path", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "string" } ], + "output" : [ { "common-ref" : "Operation Result" } ] } + +] diff --git a/release/src/router/uqmi/data/qmi-service-dms.json b/release/src/router/uqmi/data/qmi-service-dms.json new file mode 100644 index 0000000000..1e48455bf2 --- /dev/null +++ b/release/src/router/uqmi/data/qmi-service-dms.json @@ -0,0 +1,1174 @@ + +[ + // ********************************************************************************* + { "name" : "DMS", + "type" : "Service" }, + + // ********************************************************************************* + { "name" : "QMI Client DMS", + "type" : "Client" }, + + // ********************************************************************************* + { "name" : "QMI Message DMS", + "type" : "Message-ID-Enum" }, + + // ********************************************************************************* + { "name" : "QMI Indication DMS", + "type" : "Indication-ID-Enum" }, + + // ********************************************************************************* + { "name" : "Reset", + "type" : "Message", + "service" : "DMS", + "id" : "0x0000", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Set Event Report", + "type" : "Message", + "service" : "DMS", + "id" : "0x0001", + "version" : "1.0", + "input" : [ { "name" : "Power State Reporting", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Battery Level Report Limits", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Lower Limit", + "format" : "guint8" }, + { "name" : "Upper Limit", + "format" : "guint8" } ] }, + { "name" : "PIN State Reporting", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Activation State Reporting", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Operating Mode Reporting", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "UIM State Reporting", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Wireless Disable State Reporting", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "PRL Init Reporting", + "id" : "0x17", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + { "name" : "Event Report", + "type" : "Indication", + "service" : "DMS", + "id" : "0x0001", + "output" : [ { "name" : "Power State", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Power State Flags", + "format" : "guint8" }, + { "name" : "Battery Level", + "format" : "guint8" } ] }, + { "name" : "PIN1 Status", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Current Status", + "format" : "guint8", + "public-format" : "QmiDmsUimPinStatus" }, + { "name" : "Verify Retries Left", + "format" : "guint8" }, + { "name" : "Unblock Retries Left", + "format" : "guint8" } ] }, + { "name" : "PIN2 Status", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Current Status", + "format" : "guint8", + "public-format" : "QmiDmsUimPinStatus" }, + { "name" : "Verify Retries Left", + "format" : "guint8" }, + { "name" : "Unblock Retries Left", + "format" : "guint8" } ] }, + { "name" : "Activation State", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiDmsActivationState" }, + { "name" : "Operating Mode", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiDmsOperatingMode" }, + { "name" : "UIM State", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiDmsUimState" }, + { "name" : "Wireless Disable State", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "PRL Init Notification", + "id" : "0x17", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + + // ********************************************************************************* + { "name" : "Get Capabilities", + "type" : "Message", + "service" : "DMS", + "id" : "0x0020", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Info", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Max Tx Channel Rate", + "format" : "guint32" }, + { "name" : "Max Rx Channel Rate", + "format" : "guint32" }, + { "name" : "Data Service Capability", + "format" : "guint8", + "public-format" : "QmiDmsDataServiceCapability" }, + { "name" : "SIM Capability", + "format" : "guint8", + "public-format" : "QmiDmsSimCapability" }, + { "name" : "Radio Interface List", + "format" : "array", + "array-element" : { "format" : "guint8", + "public-format" : "QmiDmsRadioInterface" } } ], + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Manufacturer", + "type" : "Message", + "service" : "DMS", + "id" : "0x0021", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Manufacturer", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "string", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Model", + "type" : "Message", + "service" : "DMS", + "id" : "0x0022", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Model", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "string", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Revision", + "type" : "Message", + "service" : "DMS", + "id" : "0x0023", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Revision", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "string", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get MSISDN", + "type" : "Message", + "service" : "DMS", + "id" : "0x0024", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "MSISDN", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "string", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get IDs", + "type" : "Message", + "service" : "DMS", + "id" : "0x0025", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Esn", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "string", + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "Imei", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "string", + "max-size" : "15", + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "Meid", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "string", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Power State", + "type" : "Message", + "service" : "DMS", + "id" : "0x0026", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Info", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Power State Flags", + "format" : "guint8" }, + { "name" : "Battery Level", + "format" : "guint8" } ], + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "UIM Set PIN Protection", + "type" : "Message", + "service" : "DMS", + "id" : "0x0027", + "version" : "1.1", + "input" : [ { "name" : "Info", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Pin ID", + "format" : "guint8", + "public-format" : "QmiDmsUimPinId" }, + { "name" : "Protection Enabled", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "PIN", + "format" : "string" } ] } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Pin Retries Status", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Verify Retries Left", + "format" : "guint8" }, + { "name" : "Unblock Retries Left", + "format" : "guint8" } ], + "prerequisites": [ { "common-ref" : "No Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "UIM Verify PIN", + "type" : "Message", + "service" : "DMS", + "id" : "0x0028", + "version" : "1.1", + "input" : [ { "name" : "Info", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Pin ID", + "format" : "guint8", + "public-format" : "QmiDmsUimPinId" }, + { "name" : "PIN", + "format" : "string" } ] } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Pin Retries Status", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Verify Retries Left", + "format" : "guint8" }, + { "name" : "Unblock Retries Left", + "format" : "guint8" } ], + "prerequisites": [ { "common-ref" : "No Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "UIM Unblock PIN", + "type" : "Message", + "service" : "DMS", + "id" : "0x0029", + "version" : "1.1", + "input" : [ { "name" : "Info", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Pin ID", + "format" : "guint8", + "public-format" : "QmiDmsUimPinId" }, + { "name" : "PUK", + "format" : "string" }, + { "name" : "New PIN", + "format" : "string" } ] } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Pin Retries Status", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Verify Retries Left", + "format" : "guint8" }, + { "name" : "Unblock Retries Left", + "format" : "guint8" } ], + "prerequisites": [ { "common-ref" : "No Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "UIM Change PIN", + "type" : "Message", + "service" : "DMS", + "id" : "0x002A", + "version" : "1.1", + "input" : [ { "name" : "Info", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Pin ID", + "format" : "guint8", + "public-format" : "QmiDmsUimPinId" }, + { "name" : "Old PIN", + "format" : "string" }, + { "name" : "New PIN", + "format" : "string" } ] } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Pin Retries Status", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Verify Retries Left", + "format" : "guint8" }, + { "name" : "Unblock Retries Left", + "format" : "guint8" } ], + "prerequisites": [ { "common-ref" : "No Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "UIM Get PIN Status", + "type" : "Message", + "service" : "DMS", + "id" : "0x002B", + "version" : "1.1", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "PIN1 Status", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Current Status", + "format" : "guint8", + "public-format" : "QmiDmsUimPinStatus" }, + { "name" : "Verify Retries Left", + "format" : "guint8" }, + { "name" : "Unblock Retries Left", + "format" : "guint8" } ] }, + { "name" : "PIN2 Status", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Current Status", + "format" : "guint8", + "public-format" : "QmiDmsUimPinStatus" }, + { "name" : "Verify Retries Left", + "format" : "guint8" }, + { "name" : "Unblock Retries Left", + "format" : "guint8" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Hardware Revision", + "type" : "Message", + "service" : "DMS", + "id" : "0x002C", + "version" : "1.2", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Revision", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "string", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Operating Mode", + "type" : "Message", + "service" : "DMS", + "id" : "0x002D", + "version" : "1.1", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Mode", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiDmsOperatingMode", + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "Offline Reason", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiDmsOfflineReason", + "prerequisites": [ { "field" : "Mode", + "operation" : "==", + "value" : "QMI_DMS_OPERATING_MODE_OFFLINE" } ] }, + { "name" : "Hardware Restricted Mode", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Set Operating Mode", + "type" : "Message", + "service" : "DMS", + "id" : "0x002E", + "version" : "1.1", + "input" : [ { "name" : "Mode", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiDmsOperatingMode" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Get Time", + "type" : "Message", + "service" : "DMS", + "id" : "0x002F", + "version" : "1.3", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Device Time", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Time Count", + "format" : "guint-sized", + "guint-size" : "6" }, + { "name" : "Time Source", + "format" : "guint16", + "public-format" : "QmiDmsTimeSource" } ], + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "System Time", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint64", + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "User Time", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint64", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get PRL Version", + "type" : "Message", + "service" : "DMS", + "id" : "0x0030", + "version" : "1.3", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Version", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint16", + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "PRL Only Preference", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Activation State", + "type" : "Message", + "service" : "DMS", + "id" : "0x0031", + "version" : "1.3", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Info", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiDmsActivationState", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Activate Automatic", + "type" : "Message", + "service" : "DMS", + "id" : "0x0032", + "version" : "1.3", + "input" : [ { "name" : "Activation Code", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "string", + "size-prefix-format" : "guint8" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Activate Manual", + "type" : "Message", + "service" : "DMS", + "id" : "0x0033", + "version" : "1.3", + "input" : [ { "name" : "Info", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Service Programming Code", + "format" : "string", + "fixed-size" : "6" }, + { "name" : "System Identification Number", + "format" : "guint16" }, + { "name" : "Mobile Directory Number", + "format" : "string", + "max-size" : "15" }, + { "name" : "Mobile Identification Number", + "format" : "string", + "max-size" : "15" } ] }, + { "name" : "MN HA key", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "string", + "max-size" : "16", + "size-prefix-format" : "guint8" }, + { "name" : "MN AAA key", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "string", + "max-size" : "16", + "size-prefix-format" : "guint8" }, + { "name" : "PRL", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "PRL total length", + "format" : "guint16" }, + { "name" : "PRL segment", + "format" : "array", + "size-prefix-format" : "guint16", + "sequence-prefix-format" : "guint8", + "array-element" : { "format" : "guint8" } } ] } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Get User Lock State", + "type" : "Message", + "service" : "DMS", + "id" : "0x0034", + "version" : "1.3", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Enabled", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean", + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Set User Lock State", + "type" : "Message", + "service" : "DMS", + "id" : "0x0035", + "version" : "1.3", + "input" : [ { "name" : "Info", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Enabled", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Lock Code", + "format" : "string", + "fixed-size" : "4" } ] } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Set User Lock Code", + "type" : "Message", + "service" : "DMS", + "id" : "0x0036", + "version" : "1.3", + "input" : [ { "name" : "Info", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Old Code", + "format" : "string", + "fixed-size" : "4" }, + { "name" : "New Code", + "format" : "string", + "fixed-size" : "4" } ] } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Read User Data", + "type" : "Message", + "service" : "DMS", + "id" : "0x0037", + "version" : "1.6", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "User Data", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "format" : "guint8" }, + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Write User Data", + "type" : "Message", + "service" : "DMS", + "id" : "0x0038", + "version" : "1.6", + "input" : [ { "name" : "User Data", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "format" : "guint8" } } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Read ERI File", + "type" : "Message", + "service" : "DMS", + "id" : "0x0039", + "version" : "1.6", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "ERI File", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "format" : "guint8" }, + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Restore Factory Defaults", + "type" : "Message", + "service" : "DMS", + "id" : "0x003A", + "version" : "1.6", + "input" : [ { "name" : "Service Programming Code", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "string", + "fixed-size" : "6" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Validate Service Programming Code", + "type" : "Message", + "service" : "DMS", + "id" : "0x003B", + "version" : "1.3", + "input" : [ { "name" : "Service Programming Code", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "string", + "fixed-size" : "6" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "UIM Get ICCID", + "type" : "Message", + "service" : "DMS", + "id" : "0x003C", + "version" : "1.3", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "ICCID", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "string", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "UIM Get CK Status", + "type" : "Message", + "service" : "DMS", + "id" : "0x0040", + "version" : "1.3", + "input" : [ { "name" : "Facility", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiDmsUimFacility" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "CK Status", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Facility State", + "format" : "guint8", + "public-format" : "QmiDmsUimFacilityState" }, + { "name" : "Verify Retries Left", + "format" : "guint8" }, + { "name" : "Unblock Retries Left", + "format" : "guint8" } ], + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "Operation Blocking Facility", + "id" : "0x10", + "mandatory" : "false", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "UIM Set CK Protection", + "type" : "Message", + "service" : "DMS", + "id" : "0x0041", + "version" : "1.3", + "input" : [ { "name" : "Facility", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Facility", + "format" : "guint8", + "public-format" : "QmiDmsUimFacility" }, + { "name" : "Facility State", + "format" : "guint8", + "public-format" : "QmiDmsUimFacilityState" }, + { "name" : "Facility Depersonalization Control Key", + "format" : "string" } ] } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Verify Retries Left", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8" } ] }, + + // ********************************************************************************* + { "name" : "UIM Unblock CK", + "type" : "Message", + "service" : "DMS", + "id" : "0x0042", + "version" : "1.3", + "input" : [ { "name" : "Facility", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Facility", + "format" : "guint8", + "public-format" : "QmiDmsUimFacility" }, + { "name" : "Facility Control Key", + "format" : "string" } ] } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Unblock Retries Left", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8" } ] }, + + // ********************************************************************************* + { "name" : "UIM Get IMSI", + "type" : "Message", + "service" : "DMS", + "id" : "0x0043", + "version" : "1.3", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "IMSI", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "string", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "UIM Get State", + "type" : "Message", + "service" : "DMS", + "id" : "0x0044", + "version" : "1.3", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "State", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiDmsUimState", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Band Capabilities", + "type" : "Message", + "service" : "DMS", + "id" : "0x0045", + "version" : "1.3", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Band Capability", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint64", + "public-format" : "QmiDmsBandCapability", + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "LTE Band Capability", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint64", + "public-format" : "QmiDmsLteBandCapability", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Factory SKU", + "type" : "Message", + "service" : "DMS", + "id" : "0x0046", + "version" : "1.6", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "SKU", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "string", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Firmware Preference", + "type" : "Message", + "service" : "DMS", + "id" : "0x0047", + "version" : "1.3", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "List", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "array", + "array-element" : { "name" : "Image", + "format" : "struct", + "contents" : [ { "name" : "Type", + "format" : "guint8", + "public-format" : "QmiDmsFirmwareImageType" }, + { "name" : "Unique ID", + "format" : "array", + "fixed-size" : "16", + "array-element" : { "format": "guint8" } }, + { "name" : "Build ID", + "format" : "string" } ] }, + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Set Firmware Preference", + "type" : "Message", + "service" : "DMS", + "id" : "0x0048", + "version" : "1.3", + "input" : [ { "name" : "List", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "array", + "array-element" : { "name" : "Image", + "format" : "struct", + "contents" : [ { "name" : "Type", + "format" : "guint8", + "public-format" : "QmiDmsFirmwareImageType" }, + { "name" : "Unique ID", + "format" : "array", + "fixed-size" : "16", + "array-element" : { "format": "guint8" } }, + { "name" : "Build ID", + "format" : "string" } ] } }, + { "name" : "Download Override", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Modem Storage Index", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Image Download List", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "array", + "array-element" : { "name" : "Image Type", + "format" : "guint8", + "public-format" : "QmiDmsFirmwareImageType" }, + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "List Stored Images", + "type" : "Message", + "service" : "DMS", + "id" : "0x0049", + "version" : "1.3", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "List", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "array", + "array-element" : { "name" : "Image", + "format" : "struct", + "contents" : [ { "name" : "Type", + "format" : "guint8", + "public-format" : "QmiDmsFirmwareImageType" }, + { "name" : "Maximum Images", + "format" : "guint8" }, + { "name" : "Index Of Running Image", + "format" : "guint8" }, + { "name" : "Sublist", + "format" : "array", + "array-element" : { "name" : "Sublist Element", + "format" : "struct", + "contents" : [ { "name" : "Storage Index", + "format" : "guint8" }, + { "name" : "Failure Count", + "format" : "guint8" }, + { "name" : "Unique ID", + "format" : "array", + "fixed-size" : "16", + "array-element" : { "format": "guint8" } }, + { "name" : "Build ID", + "format" : "string" } ] } } ] }, + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Delete Stored Image", + "type" : "Message", + "service" : "DMS", + "id" : "0x004A", + "version" : "1.3", + "input" : [ { "name" : "Image", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "struct", + "contents" : [ { "name" : "Type", + "format" : "guint8", + "public-format" : "QmiDmsFirmwareImageType" }, + { "name" : "Unique ID", + "format" : "array", + "fixed-size" : "16", + "array-element" : { "format": "guint8" } }, + { "name" : "Build ID", + "format" : "string" } ] } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Set Time", + "type" : "Message", + "service" : "DMS", + "id" : "0x004B", + "version" : "1.4", + "input" : [ { "name" : "Time Value", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint64" }, + { "name" : "Time Reference Type", + "id" : "0x10", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiDmsTimeReferenceType" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Get Stored Image Info", + "type" : "Message", + "service" : "DMS", + "id" : "0x004C", + "version" : "1.3", + "input" : [ { "name" : "Image", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "struct", + "contents" : [ { "name" : "Type", + "format" : "guint8", + "public-format" : "QmiDmsFirmwareImageType" }, + { "name" : "Unique ID", + "format" : "array", + "fixed-size" : "16", + "array-element" : { "format": "guint8" } }, + { "name" : "Build ID", + "format" : "string" } ] } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Boot Version", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Major Version", + "format" : "guint16" }, + { "name" : "Minor Version", + "format" : "guint16" } ], + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "PRI Version", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "PRI Version", + "format" : "guint32" }, + { "name" : "PRI Info", + "format" : "string", + "fixed-size" : "32" } ], + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "OEM Lock ID", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Alt Net Config", + "type" : "Message", + "service" : "DMS", + "id" : "0x004D", + "version" : "1.6", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Config", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Set Alt Net Config", + "type" : "Message", + "service" : "DMS", + "id" : "0x004E", + "version" : "1.6", + "input" : [ { "name" : "Config", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Get Software Version", + "type" : "Message", + "service" : "DMS", + "id" : "0x0051", + "version" : "1.5", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Version", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "string", + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Set Service Programming Code", + "type" : "Message", + "service" : "DMS", + "id" : "0x0052", + "version" : "1.5", + "input" : [ { "name" : "Current", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "string", + "fixed-size" : "6" }, + { "name" : "New", + "id" : "0x02", + "mandatory" : "yes", + "type" : "TLV", + "format" : "string", + "fixed-size" : "6" } ], + "output" : [ { "common-ref" : "Operation Result" } ] } + +] diff --git a/release/src/router/uqmi/data/qmi-service-nas.json b/release/src/router/uqmi/data/qmi-service-nas.json new file mode 100644 index 0000000000..f5a3930a6d --- /dev/null +++ b/release/src/router/uqmi/data/qmi-service-nas.json @@ -0,0 +1,3159 @@ + +[ + // ********************************************************************************* + { "name" : "NAS", + "type" : "Service" }, + + // ********************************************************************************* + { "name" : "QMI Client NAS", + "type" : "Client" }, + + // ********************************************************************************* + { "name" : "QMI Message NAS", + "type" : "Message-ID-Enum" }, + + // ********************************************************************************* + { "name" : "QMI Indication NAS", + "type" : "Indication-ID-Enum" }, + + // ********************************************************************************* + { "name" : "Reset", + "type" : "Message", + "service" : "NAS", + "id" : "0x0000", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Abort", + "type" : "Message", + "service" : "NAS", + "id" : "0x0001", + "version" : "1.0", + // This magic tag allows us to avoid creating a method in the client + "scope" : "library-only", + "input" : [ { "name" : "Transaction ID", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint16" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Set Event Report", + "type" : "Message", + "service" : "NAS", + "id" : "0x0002", + "version" : "1.0", + "input" : [ { "name" : "Signal Strength Indicator", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Report", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Thresholds", + "format" : "array", + "array-element" : { "format" : "gint8" } } ] }, + { "name" : "RF Band Information", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Registration Reject Reason", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "RSSI Indicator", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Report", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "RSSI Delta", + "format" : "guint8" } ] }, + { "name" : "ECIO Indicator", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Report", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "ECIO Delta", + "format" : "guint8" } ] }, + { "name" : "IO Indicator", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Report", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "IO Delta", + "format" : "guint8" } ] }, + { "name" : "SINR Indicator", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Report", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "SINR Delta", + "format" : "guint8" } ] }, + { "name" : "Error Rate Indicator", + "id" : "0x17", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "ECIO Threshold", + "id" : "0x19", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Report", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Thresholds", + "format" : "array", + "array-element" : { "format" : "gint16" } } ] }, + { "name" : "SINR Threshold", + "id" : "0x1A", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Report", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Thresholds", + "format" : "array", + "array-element" : { "format" : "guint8" } } ] }, + { "name" : "LTE SNR Delta", + "id" : "0x1B", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Report", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "SNR Delta", + "format" : "guint8" } ] }, + { "name" : "LTE RSRP Delta", + "id" : "0x1C", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Report", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "RSRP Delta", + "format" : "guint8" } ] } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + { "name" : "Event Report", + "type" : "Indication", + "service" : "NAS", + "id" : "0x0002", + "output" : [ { "name" : "Signal Strength", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Strength", + "format" : "gint8" }, + { "name" : "Radio Interface", + "format" : "gint8", + "public-format" : "QmiNasRadioInterface" } ] }, + { "name" : "RF Band Information", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Radio Interface", + "format" : "gint8", + "public-format" : "QmiNasRadioInterface" }, + { "name" : "Active Band Class", + "format" : "guint16", + "public-format" : "QmiNasActiveBand" }, + { "name" : "Active Channel", + "format" : "guint16" } ] } }, + { "name" : "Registration Reject Reason", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Service Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Reject Cause", + "format" : "guint16" } ] }, + { "name" : "RSSI", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "RSSI", + "format" : "guint8" }, + { "name" : "Radio Interface", + "format" : "gint8", + "public-format" : "QmiNasRadioInterface" } ] }, + { "name" : "ECIO", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "ECIO", + "format" : "gint8" }, + { "name" : "Radio Interface", + "format" : "gint8", + "public-format" : "QmiNasRadioInterface" } ] }, + { "name" : "IO", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "gint32" }, + { "name" : "SINR", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiNasEvdoSinrLevel" }, + { "name" : "Error Rate", + "id" : "0x17", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Rate", + "format" : "guint16" }, + { "name" : "Radio Interface", + "format" : "gint8", + "public-format" : "QmiNasRadioInterface" } ] }, + { "name" : "RSRQ", + "id" : "0x18", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "RSRQ", + "format" : "gint8" }, + { "name" : "Radio Interface", + "format" : "gint8", + "public-format" : "QmiNasRadioInterface" } ] }, + { "name" : "LTE SNR", + "id" : "0x19", + "mandatory" : "no", + "type" : "TLV", + "format" : "gint16" }, + { "name" : "LTE RSRP", + "id" : "0x1A", + "mandatory" : "no", + "type" : "TLV", + "format" : "gint16" } ] }, + + // ********************************************************************************* + { "name" : "Register Indications", + "type" : "Message", + "service" : "NAS", + "id" : "0x0003", + "version" : "1.1", + "input" : [ { "name" : "System Selection Preference", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "DDTM Events", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Serving System Events", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Dual Standby Preference", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Subscription Info", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Network Time", + "id" : "0x17", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "System Info", + "id" : "0x18", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Signal Info", + "id" : "0x19", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Error Rate", + "id" : "0x1A", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "HDR New UATI Assigned", + "id" : "0x1B", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "HDR Session Closed", + "id" : "0x1C", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Managed Roaming", + "id" : "0x1D", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Current PLMN Name", + "id" : "0x1E", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "eMBMS Status", + "id" : "0x1F", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "RF Band Information", + "id" : "0x20", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Get Signal Strength", + "type" : "Message", + "service" : "NAS", + "id" : "0x0020", + "version" : "1.0", + "input" : [ { "name" : "Request Mask", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiNasSignalStrengthRequest" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Signal Strength", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Strength", + "format" : "gint8" }, + { "name" : "Radio Interface", + "format" : "gint8", + "public-format" : "QmiNasRadioInterface" } ], + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "Strength List", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Strength", + "format" : "gint8" }, + { "name" : "Radio Interface", + "format" : "gint8", + "public-format" : "QmiNasRadioInterface" } ] } }, + { "name" : "RSSI List", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "RSSI", + "format" : "guint8" }, + { "name" : "Radio Interface", + "format" : "gint8", + "public-format" : "QmiNasRadioInterface" } ] } }, + { "name" : "ECIO List", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "ECIO", + "format" : "gint8" }, + { "name" : "Radio Interface", + "format" : "gint8", + "public-format" : "QmiNasRadioInterface" } ] } }, + { "name" : "IO", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "gint32" }, + { "name" : "SINR", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiNasEvdoSinrLevel" }, + { "name" : "Error Rate List", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Rate", + "format" : "guint16" }, + { "name" : "Radio Interface", + "format" : "gint8", + "public-format" : "QmiNasRadioInterface" } ] } }, + { "name" : "RSRQ", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "RSRQ", + "format" : "gint8" }, + { "name" : "Radio Interface", + "format" : "gint8", + "public-format" : "QmiNasRadioInterface" } ] }, + { "name" : "LTE SNR", + "id" : "0x17", + "mandatory" : "no", + "type" : "TLV", + "format" : "gint16" }, + { "name" : "LTE RSRP", + "id" : "0x18", + "mandatory" : "no", + "type" : "TLV", + "format" : "gint16" } ] }, + + // ********************************************************************************* + { "name" : "Network Scan", + "type" : "Message", + "service" : "NAS", + "id" : "0x0021", + "version" : "1.0", + // This method may be aborted + "abort" : "yes", + "input" : [ { "name" : "Network Type", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiNasNetworkScanType" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Network Information", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "MCC", + "format" : "guint16" }, + { "name" : "MNC", + "format" : "guint16" }, + { "name" : "Network Status", + "format" : "guint8", + "public-format" : "QmiNasNetworkStatus" }, + { "name" : "Description", + "format" : "string" } ] } }, + { "name" : "Radio Access Technology", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "MCC", + "format" : "guint16" }, + { "name" : "MNC", + "format" : "guint16" }, + { "name" : "Radio Interface", + "format" : "gint8", + "public-format" : "QmiNasRadioInterface" } ] } }, + { "name" : "MNC PCS Digit Include Status", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "MCC", + "format" : "guint16" }, + { "name" : "MNC", + "format" : "guint16" }, + { "name" : "Includes PCS Digit", + "format" : "guint8", + "public-format" : "gboolean" } ] } } ] }, + + // ********************************************************************************* + { "name" : "Initiate Network Register", + "type" : "Message", + "service" : "NAS", + "id" : "0x0022", + "version" : "1.0", + "input" : [ { "name" : "Action", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiNasNetworkRegisterType" }, + { "name" : "Manual Registration Info 3GPP", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "MCC", + "format" : "guint16" }, + { "name" : "MNC", + "format" : "guint16" }, + { "name" : "Radio Interface", + "format" : "gint8", + "public-format" : "QmiNasRadioInterface" } ] }, + { "name" : "Change Duration", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiNasChangeDuration" }, + { "name" : "MNC PCS Digit Include Status", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Get Serving System", + "type" : "Message", + "service" : "NAS", + "id" : "0x0024", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Serving System", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Registration State", + "format" : "guint8", + "public-format" : "QmiNasRegistrationState" }, + { "name" : "CS Attach State", + "format" : "guint8", + "public-format" : "QmiNasAttachState" }, + { "name" : "PS Attach State", + "format" : "guint8", + "public-format" : "QmiNasAttachState" }, + { "name" : "Selected Network", + "format" : "guint8", + "public-format" : "QmiNasNetworkType" }, + { "name" : "Radio Interfaces", + "format" : "array", + "array-element" : { "format" : "gint8", + "public-format" : "QmiNasRadioInterface" } } ], + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "Roaming Indicator", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiNasRoamingIndicatorStatus" }, + { "name" : "Data Service Capability", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "array-element" : { "format" : "guint8", + "public-format" : "QmiNasDataCapability" } }, + { "name" : "Current PLMN", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "MCC", + "format" : "guint16" }, + { "name" : "MNC", + "format" : "guint16" }, + { "name" : "Description", + "format" : "string" } ] }, + { "name" : "CDMA System ID", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "SID", + "format" : "guint16" }, + { "name" : "NID", + "format" : "guint16" } ] }, + { "name" : "CDMA Base Station Info", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Base Station ID", + "format" : "guint16" }, + { "name" : "Base Station Latitude", + "format" : "gint32" }, + { "name" : "Base Station Longitude", + "format" : "gint32" } ] }, + { "name" : "Roaming Indicator List", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Radio Interface", + "format" : "guint8", + "public-format" : "QmiNasRadioInterface" }, + { "name" : "Roaming Indicator", + "format" : "guint8", + "public-format" : "QmiNasRoamingIndicatorStatus" } ] } }, + { "name" : "Default Roaming Indicator", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiNasRoamingIndicatorStatus" }, + { "name" : "Time Zone 3GPP2", + "id" : "0x17", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Leap Seconds", + "format" : "guint8" }, + { "name" : "Local Time Offset", + "format" : "gint8" }, + { "name" : "Daylight Saving Time", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "CDMA P Rev", + "id" : "0x18", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8" }, + { "name" : "Time Zone 3GPP", + "id" : "0x1A", + "mandatory" : "no", + "type" : "TLV", + "format" : "gint8" }, + { "name" : "Daylight Saving Time Adjustment 3GPP", + "id" : "0x1B", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8" }, + { "name" : "LAC 3GPP", + "id" : "0x1C", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16" }, + { "name" : "CID 3GPP", + "id" : "0x1D", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32" }, + { "name" : "Concurrent Service Info 3GPP2", + "id" : "0x1E", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean"}, + { "name" : "PRL Indicator 3GPP2", + "id" : "0x1F", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean"}, + { "name" : "DTM Support", + "id" : "0x20", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean"}, + { "name" : "Detailed Service Status", + "id" : "0x21", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "Capability", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "HDR Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "HDR Hybrid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Forbidden", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "CDMA System Info", + "id" : "0x22", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "MCC", + "format" : "guint16" }, + { "name" : "IMSI_11_12", + "format" : "guint8" } ] }, + { "name" : "HDR Personality", + "id" : "0x23", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiNasHdrPersonality"}, + { "name" : "LTE TAC", + "id" : "0x24", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16" }, + { "name" : "Call Barring Status", + "id" : "0x25", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "CS Status", + "format" : "gint32", + "public-format" : "QmiNasCallBarringStatus" }, + { "name" : "PS Status", + "format" : "gint32", + "public-format" : "QmiNasCallBarringStatus" } ] }, + { "name" : "UMTS Primary Scrambling Code", + "id" : "0x26", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16" }, + { "name" : "MNC PCS Digit Include Status", + "id" : "0x27", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "MCC", + "format" : "guint16" }, + { "name" : "MNC", + "format" : "guint16" }, + { "name" : "Includes PCS Digit", + "format" : "guint8", + "public-format" : "gboolean" } ] } ] }, + + { "name" : "Serving System", + "type" : "Indication", + "service" : "NAS", + "id" : "0x0024", + "version" : "1.0", + "output" : [ { "name" : "Serving System", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Registration State", + "format" : "guint8", + "public-format" : "QmiNasRegistrationState" }, + { "name" : "CS Attach State", + "format" : "guint8", + "public-format" : "QmiNasAttachState" }, + { "name" : "PS Attach State", + "format" : "guint8", + "public-format" : "QmiNasAttachState" }, + { "name" : "Selected Network", + "format" : "guint8", + "public-format" : "QmiNasNetworkType" }, + { "name" : "Radio Interfaces", + "format" : "array", + "array-element" : { "format" : "gint8", + "public-format" : "QmiNasRadioInterface" } } ] }, + { "name" : "Roaming Indicator", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiNasRoamingIndicatorStatus" }, + { "name" : "Data Service Capability", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "array-element" : { "format" : "guint8", + "public-format" : "QmiNasDataCapability" } }, + { "name" : "Current PLMN", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "MCC", + "format" : "guint16" }, + { "name" : "MNC", + "format" : "guint16" }, + { "name" : "Description", + "format" : "string" } ] }, + { "name" : "CDMA System ID", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "SID", + "format" : "guint16" }, + { "name" : "NID", + "format" : "guint16" } ] }, + { "name" : "CDMA Base Station Info", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Base Station ID", + "format" : "guint16" }, + { "name" : "Base Station Latitude", + "format" : "gint32" }, + { "name" : "Base Station Longitude", + "format" : "gint32" } ] }, + { "name" : "Roaming Indicator List", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Radio Interface", + "format" : "guint8", + "public-format" : "QmiNasRadioInterface" }, + { "name" : "Roaming Indicator", + "format" : "guint8", + "public-format" : "QmiNasRoamingIndicatorStatus" } ] } }, + { "name" : "Default Roaming Indicator", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiNasRoamingIndicatorStatus" }, + { "name" : "Time Zone 3GPP2", + "id" : "0x17", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Leap Seconds", + "format" : "guint8" }, + { "name" : "Local Time Offset", + "format" : "gint8" }, + { "name" : "Daylight Saving Time", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "CDMA P Rev", + "id" : "0x18", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8" }, + { "name" : "PLMN Name Flag 3GPP", + "id" : "0x19", + "mandatory" : "no", + "type" : "TLV", + "format" : "gint8", + "public-format" : "gboolean" }, + { "name" : "Time Zone 3GPP", + "id" : "0x1A", + "mandatory" : "no", + "type" : "TLV", + "format" : "gint8" }, + { "name" : "Daylight Saving Time Adjustment 3GPP", + "id" : "0x1B", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8" }, + { "name" : "Universal Time and Local Time Zone 3GPP", + "id" : "0x1C", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Year", + "format" : "guint16" }, + { "name" : "Month", + "format" : "guint8" }, + { "name" : "Day", + "format" : "guint8" }, + { "name" : "Hour", + "format" : "guint8" }, + { "name" : "Minute", + "format" : "guint8" }, + { "name" : "Second", + "format" : "guint8" }, + { "name" : "Time Zone", + "format" : "guint8" } ] }, + { "name" : "LAC 3GPP", + "id" : "0x1D", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16" }, + { "name" : "CID 3GPP", + "id" : "0x1E", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32" }, + { "name" : "Concurrent Service Info 3GPP2", + "id" : "0x1F", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean"}, + { "name" : "PRL Indicator 3GPP2", + "id" : "0x20", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean"}, + { "name" : "DTM Support", + "id" : "0x21", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean"}, + { "name" : "Detailed Service Status", + "id" : "0x22", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "Capability", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "HDR Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "HDR Hybrid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Forbidden", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "CDMA System Info", + "id" : "0x23", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "MCC", + "format" : "guint16" }, + { "name" : "IMSI_11_12", + "format" : "guint8" } ] }, + { "name" : "HDR Personality", + "id" : "0x24", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiNasHdrPersonality"}, + { "name" : "LTE TAC", + "id" : "0x25", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16" }, + { "name" : "Call Barring Status", + "id" : "0x26", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "CS Status", + "format" : "gint32", + "public-format" : "QmiNasCallBarringStatus" }, + { "name" : "PS Status", + "format" : "gint32", + "public-format" : "QmiNasCallBarringStatus" } ] }, + { "name" : "PLMN Not Changed Indication", + "id" : "0x27", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "UMTS Primary Scrambling Code", + "id" : "0x28", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16" }, + { "name" : "MNC PCS Digit Include Status", + "id" : "0x29", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "MCC", + "format" : "guint16" }, + { "name" : "MNC", + "format" : "guint16" }, + { "name" : "Includes PCS Digit", + "format" : "guint8", + "public-format" : "gboolean" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Home Network", + "type" : "Message", + "service" : "NAS", + "id" : "0x0025", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Home Network", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "MCC", + "format" : "guint16" }, + { "name" : "MNC", + "format" : "guint16" }, + { "name" : "Description", + "format" : "string" } ], + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "Home System ID", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "SID", + "format" : "guint16" }, + { "name" : "NID", + "format" : "guint16" } ] }, + { "name" : "Home Network 3GPP2", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "MCC", + "format" : "guint16" }, + { "name" : "MNC", + "format" : "guint16" }, + { "name" : "Display Description", + "format" : "guint8", + "public-format" : "QmiNasNetworkDescriptionDisplay" }, + { "name" : "Description Encoding", + "format" : "guint8", + "public-format" : "QmiNasNetworkDescriptionEncoding" }, + { "name" : "Description", + "format" : "string" } ] } ] }, + + // ********************************************************************************* + { "name" : "Set Technology Preference", + "type" : "Message", + "service" : "NAS", + "id" : "0x002A", + "version" : "1.0", + "input" : [ { "name" : "Current", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Technology Preference", + "format" : "guint16", + "public-format" : "QmiNasRadioTechnologyPreference" }, + { "name" : "Technology Preference Duration", + "format" : "guint8", + "public-format" : "QmiNasPreferenceDuration" } ] } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Get Technology Preference", + "type" : "Message", + "service" : "NAS", + "id" : "0x002B", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Active", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Technology Preference", + "format" : "guint16", + "public-format" : "QmiNasRadioTechnologyPreference" }, + { "name" : "Technology Preference Duration", + "format" : "guint8", + "public-format" : "QmiNasPreferenceDuration" } ], + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "Persistent", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiNasRadioTechnologyPreference" } ] }, + + // ********************************************************************************* + { "name" : "Get RF Band Information", + "type" : "Message", + "service" : "NAS", + "id" : "0x0031", + "version" : "1.1", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "List", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Radio Interface", + "format" : "gint8", + "public-format" : "QmiNasRadioInterface" }, + { "name" : "Active Band Class", + "format" : "guint16", + "public-format" : "QmiNasActiveBand" }, + { "name" : "Active Channel", + "format" : "guint16" } ] } } ] }, + + // ********************************************************************************* + { "name" : "Set System Selection Preference", + "type" : "Message", + "service" : "NAS", + "id" : "0x0033", + "version" : "1.1", + "input" : [ { "name" : "Emergency mode", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Mode Preference", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiNasRatModePreference" }, + { "name" : "Band Preference", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint64", + "public-format" : "QmiNasBandPreference" }, + { "name" : "CDMA PRL Preference", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiNasCdmaPrlPreference" }, + { "name" : "Roaming Preference", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiNasRoamingPreference" }, + { "name" : "LTE Band Preference", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint64", + "public-format" : "QmiNasLteBandPreference" }, + { "name" : "Network Selection Preference", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Mode", + "format" : "guint8", + "public-format" : "QmiNasNetworkSelectionPreference" }, + { "name" : "MCC", + "format" : "guint16" }, + { "name" : "MNC", + "format" : "guint16" } ] }, + { "name" : "Change Duration", + "id" : "0x17", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiNasChangeDuration" }, + { "name" : "Service Domain Preference", + "id" : "0x18", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiNasServiceDomainPreference" }, + { "name" : "GSM WCDMA Acquisition Order Preference", + "id" : "0x19", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiNasGsmWcdmaAcquisitionOrderPreference" }, + { "name" : "MNC PDS Digit Include Status", + "id" : "0x1A", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "TD SCDMA Band Preference", + "id" : "0x1D", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint64", + "public-format" : "QmiNasTdScdmaBandPreference" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Get System Selection Preference", + "type" : "Message", + "service" : "NAS", + "id" : "0x0034", + "version" : "1.1", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Emergency mode", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Mode Preference", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiNasRatModePreference" }, + { "name" : "Band Preference", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint64", + "public-format" : "QmiNasBandPreference" }, + { "name" : "CDMA PRL Preference", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiNasCdmaPrlPreference" }, + { "name" : "Roaming Preference", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiNasRoamingPreference" }, + { "name" : "LTE Band Preference", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint64", + "public-format" : "QmiNasLteBandPreference" }, + { "name" : "Network Selection Preference", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiNasNetworkSelectionPreference" }, + { "name" : "Service Domain Preference", + "id" : "0x18", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiNasServiceDomainPreference" }, + { "name" : "GSM WCDMA Acquisition Order Preference", + "id" : "0x19", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiNasGsmWcdmaAcquisitionOrderPreference" }, + { "name" : "TD SCDMA Band Preference", + "id" : "0x1A", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint64", + "public-format" : "QmiNasTdScdmaBandPreference" }, + { "name" : "Manual Network Selection", + "id" : "0x1B", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "MCC", + "format" : "guint16" }, + { "name" : "MNC", + "format" : "guint16" }, + { "name" : "Includes PCS Digit", + "format" : "guint8", + "public-format" : "gboolean" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Cell Location Info", + "type" : "Message", + "service" : "NAS", + "id" : "0x0043", + "version" : "1.4", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "GERAN Info", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Cell ID", + "format" : "guint32" }, + { "name" : "PLMN", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "LAC", + "format" : "guint16" }, + { "name" : "GERAN Absolute RF Channel Number", + "format" : "guint16" }, + { "name" : "Base Station Identity Code", + "format" : "guint8" }, + { "name" : "Timing Advance", + "format" : "guint32" }, + { "name" : "RX Level", + "format" : "guint16" }, + { "name" : "Cell", + "format" : "array", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Cell ID", + "format" : "guint32" }, + { "name" : "PLMN", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "LAC", + "format" : "guint16" }, + { "name" : "GERAN Absolute RF Channel Number", + "format" : "guint16" }, + { "name" : "Base Station Identity Code", + "format" : "guint8" }, + { "name" : "RX Level", + "format" : "guint16" } ] } } ] }, + { "name" : "UMTS Info", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Cell ID", + "format" : "guint16" }, + { "name" : "PLMN", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "LAC", + "format" : "guint16" }, + { "name" : "UTRA Absolute RF Channel Number", + "format" : "guint16" }, + { "name" : "Primary Scrambling Code", + "format" : "guint16" }, + { "name" : "RSCP", + "format" : "gint16" }, + { "name" : "ECIO", + "format" : "gint16" }, + { "name" : "Cell", + "format" : "array", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "UTRA Absolute RF Channel Number", + "format" : "guint16" }, + { "name" : "Primary Scrambling Code", + "format" : "guint16" }, + { "name" : "RSCP", + "format" : "gint16" }, + { "name" : "ECIO", + "format" : "gint16" } ] } }, + { "name" : "Neighboring GERAN", + "format" : "array", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "GERAN Absolute RF Channel Number", + "format" : "guint16" }, + { "name" : "Network Color Code", + "format" : "guint8" }, + { "name" : "Base Station Color Code", + "format" : "guint8" }, + { "name" : "RSSI", + "format" : "gint16" } ] } } ] }, + { "name" : "CDMA Info", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "System ID", + "format" : "guint16" }, + { "name" : "Network ID", + "format" : "guint16" }, + { "name" : "Base Station ID", + "format" : "guint16" }, + { "name" : "Reference PN", + "format" : "guint16" }, + { "name" : "Latitude", + "format" : "guint32" }, + { "name" : "Longitude", + "format" : "guint32" } ] }, + { "name" : "Intrafrequency LTE Info", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "UE In Idle", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "PLMN", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "Tracking Area Code", + "format" : "guint16" }, + { "name" : "Global Cell ID", + "format" : "guint32" }, + { "name" : "EUTRA Absolute RF Channel Number", + "format" : "guint16" }, + { "name" : "Serving Cell ID", + "format" : "guint16" }, + { "name" : "Cell Reselection Priority", + "format" : "guint8" }, + { "name" : "S Non Intra Search Threshold", + "format" : "guint8" }, + { "name" : "Serving Cell Low Threshold", + "format" : "guint8" }, + { "name" : "S Intra Search Threshold", + "format" : "guint8" }, + { "name" : "Cell", + "format" : "array", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Physical Cell ID", + "format" : "guint16" }, + { "name" : "RSRQ", + "format" : "gint16" }, + { "name" : "RSRP", + "format" : "gint16" }, + { "name" : "RSSI", + "format" : "gint16" }, + { "name" : "Cell Selection RX Level", + "format" : "gint16" } ] } } ] }, + { "name" : "Interfrequency LTE Info", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "UE In Idle", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Frequency", + "format" : "array", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "EUTRA Absolute RF Channel Number", + "format" : "guint16" }, + { "name" : "Cell Selection RX Level Low Threshold", + "format" : "guint8" }, + { "name" : "Cell Selection RX Level High Threshold", + "format" : "guint8" }, + { "name" : "Cell Reselection Priority", + "format" : "guint8" }, + { "name" : "Cell", + "format" : "array", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Physical Cell ID", + "format" : "guint16" }, + { "name" : "RSRQ", + "format" : "gint16" }, + { "name" : "RSRP", + "format" : "gint16" }, + { "name" : "RSSI", + "format" : "gint16" }, + { "name" : "Cell Selection RX Level", + "format" : "gint16" } ] } } ] } } ] }, + { "name" : "LTE Info Neighboring GSM", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "UE In Idle", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Frequency", + "format" : "array", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Cell Reselection Priority", + "format" : "guint8" }, + { "name" : "Cell Reselection High Threshold", + "format" : "guint8" }, + { "name" : "Cell Reselection Low Threshold", + "format" : "guint8" }, + { "name" : "NCC Permitted", + "format" : "guint8" }, + { "name" : "Cell", + "format" : "array", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "GERAN Absolute RF Channel Number", + "format" : "guint16" }, + { "name" : "Band Is 1900", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Cell ID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Base Station Identity Code", + "format" : "guint8" }, + { "name" : "RSSI", + "format" : "gint16" }, + { "name" : "Cell Selection RX Level", + "format" : "gint16" } ] } } ] } } ] }, + { "name" : "LTE Info Neighboring WCDMA", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "UE In Idle", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Frequency", + "format" : "array", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "UTRA Absolute RF Channel Number", + "format" : "guint16" }, + { "name" : "Cell Reselection Priority", + "format" : "guint8" }, + { "name" : "Cell Reselection High Threshold", + "format" : "guint16" }, + { "name" : "Cell Reselection Low Threshold", + "format" : "guint16" }, + { "name" : "Cell", + "format" : "array", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Primary Scrambling Code", + "format" : "guint16" }, + { "name" : "CPICH RSCP", + "format" : "gint16" }, + { "name" : "CPICH EcNo", + "format" : "gint16" }, + { "name" : "Cell Selection RX Level", + "format" : "gint16" } ] } } ] } } ] }, + { "name" : "UMTS Cell ID", + "id" : "0x17", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32" }, + { "name" : "UMTS Info Neighboring LTE", + "id" : "0x18", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "RRC state", + "format" : "guint32", + "public-format" : "QmiNasWcdmaRrcState" }, + { "name" : "Frequency", + "format" : "array", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "EUTRA Absolute RF Channel Number", + "format" : "guint16" }, + { "name" : "Physical Cell ID", + "format" : "guint16" }, + { "name" : "RSRP", + "format" : "gfloat" }, + { "name" : "RSRQ", + "format" : "gfloat" }, + { "name" : "Cell Selection RX Level", + "format" : "gint16" }, + { "name" : "Is TDD", + "format" : "guint8", + "public-format" : "gboolean" } ] } } ] } ] }, + + // ********************************************************************************* + { "name" : "Network Time", + "type" : "Indication", + "service" : "NAS", + "id" : "0x004C", + "version" : "1.1", + "output" : [ { "name" : "Universal Time", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Year", + "format" : "guint16" }, + { "name" : "Month", + "format" : "guint8" }, + { "name" : "Day", + "format" : "guint8" }, + { "name" : "Hour", + "format" : "guint8" }, + { "name" : "Minute", + "format" : "guint8" }, + { "name" : "Second", + "format" : "guint8" }, + { "name" : "Day Of Week", + "format" : "guint8", + "public-format" : "QmiNasDayOfWeek" } ] }, + { "name" : "Timezone Offset", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "gint8" }, + { "name" : "Daylight Savings Adjustment", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiNasDaylightSavingsAdjustment" }, + { "name" : "Radio Interface", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "gint8", + "public-format" : "QmiNasRadioInterface" } ] }, + + // ********************************************************************************* + { "name" : "Get System Info", + "type" : "Message", + "service" : "NAS", + "id" : "0x004D", + "version" : "1.8", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "CDMA Service Status", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "Preferred Data Path", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "HDR Service Status", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "Preferred Data Path", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "GSM Service Status", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "True Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "Preferred Data Path", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "WCDMA Service Status", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "True Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "Preferred Data Path", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "LTE Service Status", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "True Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "Preferred Data Path", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "CDMA System Info", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Domain Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Service Capability Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Service Capability", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Roaming Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Roaming Status", + "format" : "guint8", + "public-format" : "QmiNasRoamingStatus" }, + { "name" : "Forbidden Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Forbidden", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "PRL Match Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "PRL Match", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "P Rev Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "P Rev", + "format" : "guint8" }, + { "name" : "Base Station P Rev Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Base Station P Rev", + "format" : "guint8" }, + { "name" : "Concurrent Service Support Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Concurrent Service Support", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "CDMA System ID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "SID", + "format" : "guint16" }, + { "name" : "NID", + "format" : "guint16" }, + { "name" : "Base Station Info Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Base Station ID", + "format" : "guint16" }, + { "name" : "Base Station Latitude", + "format" : "gint32" }, + { "name" : "Base Station Longitude", + "format" : "gint32" }, + { "name" : "Packet Zone Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Packet Zone", + "format" : "guint16" }, + { "name" : "Network ID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "MCC", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "MNC", + "format" : "string", + "fixed-size" : "3" } ] }, + { "name" : "HDR System Info", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Domain Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Service Capability Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Service Capability", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Roaming Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Roaming Status", + "format" : "guint8", + "public-format" : "QmiNasRoamingStatus" }, + { "name" : "Forbidden Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Forbidden", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "PRL Match Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "PRL Match", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Personality Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Personality", + "format" : "guint8", + "public-format" : "QmiNasHdrPersonality" }, + { "name" : "Protocol Revision Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Protocol Revision", + "format" : "guint8", + "public-format" : "QmiNasHdrProtocolRevision" }, + { "name" : "IS 856 System ID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "IS 856 System ID", + "format" : "string", + "fixed-size" : "16" } ] }, + { "name" : "GSM System Info", + "id" : "0x17", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Domain Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Service Capability Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Service Capability", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Roaming Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Roaming Status", + "format" : "guint8", + "public-format" : "QmiNasRoamingStatus" }, + { "name" : "Forbidden Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Forbidden", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "LAC Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "LAC", + "format" : "guint16" }, + { "name" : "CID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "CID", + "format" : "guint32" }, + { "name" : "Registration Reject Info Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Registration Reject Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Registration Reject Cause", + "format" : "guint8" }, + { "name" : "Network ID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "MCC", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "MNC", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "EGPRS Support Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "EGPRS Support", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "DTM Support Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "DTM Support", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "WCDMA System Info", + "id" : "0x18", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Domain Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Service Capability Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Service Capability", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Roaming Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Roaming Status", + "format" : "guint8", + "public-format" : "QmiNasRoamingStatus" }, + { "name" : "Forbidden Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Forbidden", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "LAC Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "LAC", + "format" : "guint16" }, + { "name" : "CID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "CID", + "format" : "guint32" }, + { "name" : "Registration Reject Info Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Registration Reject Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Registration Reject Cause", + "format" : "guint8" }, + { "name" : "Network ID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "MCC", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "MNC", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "HS Call Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "HS Call Status", + "format" : "guint8", + "public-format" : "QmiNasWcdmaHsService" }, + { "name" : "HS Service Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "HS Service", + "format" : "guint8", + "public-format" : "QmiNasWcdmaHsService" }, + { "name" : "Primary Scrambling Code Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Primary Scrambling Code", + "format" : "guint16" } ] }, + { "name" : "LTE System Info", + "id" : "0x19", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Domain Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Service Capability Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Service Capability", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Roaming Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Roaming Status", + "format" : "guint8", + "public-format" : "QmiNasRoamingStatus" }, + { "name" : "Forbidden Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Forbidden", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "LAC Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "LAC", + "format" : "guint16" }, + { "name" : "CID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "CID", + "format" : "guint32" }, + { "name" : "Registration Reject Info Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Registration Reject Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Registration Reject Cause", + "format" : "guint8" }, + { "name" : "Network ID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "MCC", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "MNC", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "TAC Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "TAC", + "format" : "guint16" } ] }, + { "name" : "Additional CDMA System Info", + "id" : "0x1A", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Geo System Index", + "format" : "guint16" }, + { "name" : "Registration Period", + "format" : "guint16" } ] }, + { "name" : "Additional HDR System Info", + "id" : "0x1B", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Geo System Index", + "format" : "guint16" } ] }, + { "name" : "Additional GSM System Info", + "id" : "0x1C", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Geo System Index", + "format" : "guint16" }, + { "name" : "Cell Broadcast Support", + "format" : "guint32", + "public-format" : "QmiNasCellBroadcastCapability" } ] }, + { "name" : "Additional WCDMA System Info", + "id" : "0x1D", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Geo System Index", + "format" : "guint16" }, + { "name" : "Cell Broadcast Support", + "format" : "guint32", + "public-format" : "QmiNasCellBroadcastCapability" } ] }, + { "name" : "Additional LTE System Info", + "id" : "0x1E", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Geo System Index", + "format" : "guint16" } ] }, + { "name" : "GSM Call Barring Status", + "id" : "0x1F", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "CS Status", + "format" : "gint32", + "public-format" : "QmiNasCallBarringStatus" }, + { "name" : "PS Status", + "format" : "gint32", + "public-format" : "QmiNasCallBarringStatus" } ] }, + { "name" : "WCDMA Call Barring Status", + "id" : "0x20", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "CS Status", + "format" : "gint32", + "public-format" : "QmiNasCallBarringStatus" }, + { "name" : "PS Status", + "format" : "gint32", + "public-format" : "QmiNasCallBarringStatus" } ] }, + { "name" : "LTE Voice Support", + "id" : "0x21", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "GSM Cipher Domain", + "id" : "0x22", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "WCDMA Cipher Domain", + "id" : "0x23", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "TD SCDMA Service Status", + "id" : "0x24", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "True Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "Preferred Data Path", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "TD SCDMA System Info", + "id" : "0x25", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Domain Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Service Capability Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Service Capability", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Roaming Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Roaming Status", + "format" : "guint8", + "public-format" : "QmiNasRoamingStatus" }, + { "name" : "Forbidden Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Forbidden", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "LAC Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "LAC", + "format" : "guint16" }, + { "name" : "CID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "CID", + "format" : "guint32" }, + { "name" : "Registration Reject Info Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Registration Reject Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Registration Reject Cause", + "format" : "guint8" }, + { "name" : "Network ID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "MCC", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "MNC", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "HS Call Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "HS Call Status", + "format" : "guint8", + "public-format" : "QmiNasWcdmaHsService" }, + { "name" : "HS Service Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "HS Service", + "format" : "guint8", + "public-format" : "QmiNasWcdmaHsService" }, + { "name" : "Cell Parameter ID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Cell Parameter ID", + "format" : "guint16" }, + { "name" : "Cell Broadcast Support Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Cell Broadcast Support", + "format" : "guint32", + "public-format" : "QmiNasCellBroadcastCapability" }, + { "name" : "CS Call Barring Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "CS Call Barring Status", + "format" : "gint32", + "public-format" : "QmiNasCallBarringStatus" }, + { "name" : "PS Call Barring Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "PS Call Barring Status", + "format" : "gint32", + "public-format" : "QmiNasCallBarringStatus" }, + { "name" : "Cipher Domain Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Cipher Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" } ] }, + { "name" : "LTE eMBMS Coverage Info Support", + "id" : "0x26", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "SIM Reject Info", + "id" : "0x27", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiNasSimRejectState" } ] }, + + // ********************************************************************************* + { "name" : "System Info", + "type" : "Indication", + "service" : "NAS", + "id" : "0x004E", + "version" : "1.8", + "output" : [ { "name" : "CDMA Service Status", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "Preferred Data Path", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "HDR Service Status", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "Preferred Data Path", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "GSM Service Status", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "True Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "Preferred Data Path", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "WCDMA Service Status", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "True Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "Preferred Data Path", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "LTE Service Status", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "True Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "Preferred Data Path", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "CDMA System Info", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Domain Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Service Capability Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Service Capability", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Roaming Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Roaming Status", + "format" : "guint8", + "public-format" : "QmiNasRoamingStatus" }, + { "name" : "Forbidden Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Forbidden", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "PRL Match Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "PRL Match", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "P Rev Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "P Rev", + "format" : "guint8" }, + { "name" : "Base Station P Rev Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Base Station P Rev", + "format" : "guint8" }, + { "name" : "Concurrent Service Support Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Concurrent Service Support", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "CDMA System ID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "SID", + "format" : "guint16" }, + { "name" : "NID", + "format" : "guint16" }, + { "name" : "Base Station Info Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Base Station ID", + "format" : "guint16" }, + { "name" : "Base Station Latitude", + "format" : "gint32" }, + { "name" : "Base Station Longitude", + "format" : "gint32" }, + { "name" : "Packet Zone Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Packet Zone", + "format" : "guint16" }, + { "name" : "Network ID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "MCC", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "MNC", + "format" : "string", + "fixed-size" : "3" } ] }, + { "name" : "HDR System Info", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Domain Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Service Capability Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Service Capability", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Roaming Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Roaming Status", + "format" : "guint8", + "public-format" : "QmiNasRoamingStatus" }, + { "name" : "Forbidden Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Forbidden", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "PRL Match Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "PRL Match", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Personality Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Personality", + "format" : "guint8", + "public-format" : "QmiNasHdrPersonality" }, + { "name" : "Protocol Revision Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Protocol Revision", + "format" : "guint8", + "public-format" : "QmiNasHdrProtocolRevision" }, + { "name" : "IS 856 System ID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "IS 856 System ID", + "format" : "string", + "fixed-size" : "16" } ] }, + { "name" : "GSM System Info", + "id" : "0x17", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Domain Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Service Capability Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Service Capability", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Roaming Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Roaming Status", + "format" : "guint8", + "public-format" : "QmiNasRoamingStatus" }, + { "name" : "Forbidden Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Forbidden", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "LAC Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "LAC", + "format" : "guint16" }, + { "name" : "CID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "CID", + "format" : "guint32" }, + { "name" : "Registration Reject Info Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Registration Reject Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Registration Reject Cause", + "format" : "guint8" }, + { "name" : "Network ID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "MCC", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "MNC", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "EGPRS Support Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "EGPRS Support", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "DTM Support Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "DTM Support", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "WCDMA System Info", + "id" : "0x18", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Domain Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Service Capability Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Service Capability", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Roaming Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Roaming Status", + "format" : "guint8", + "public-format" : "QmiNasRoamingStatus" }, + { "name" : "Forbidden Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Forbidden", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "LAC Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "LAC", + "format" : "guint16" }, + { "name" : "CID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "CID", + "format" : "guint32" }, + { "name" : "Registration Reject Info Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Registration Reject Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Registration Reject Cause", + "format" : "guint8" }, + { "name" : "Network ID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "MCC", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "MNC", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "HS Call Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "HS Call Status", + "format" : "guint8", + "public-format" : "QmiNasWcdmaHsService" }, + { "name" : "HS Service Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "HS Service", + "format" : "guint8", + "public-format" : "QmiNasWcdmaHsService" }, + { "name" : "Primary Scrambling Code Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Primary Scrambling Code", + "format" : "guint16" } ] }, + { "name" : "LTE System Info", + "id" : "0x19", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Domain Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Service Capability Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Service Capability", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Roaming Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Roaming Status", + "format" : "guint8", + "public-format" : "QmiNasRoamingStatus" }, + { "name" : "Forbidden Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Forbidden", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "LAC Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "LAC", + "format" : "guint16" }, + { "name" : "CID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "CID", + "format" : "guint32" }, + { "name" : "Registration Reject Info Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Registration Reject Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Registration Reject Cause", + "format" : "guint8" }, + { "name" : "Network ID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "MCC", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "MNC", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "TAC Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "TAC", + "format" : "guint16" } ] }, + { "name" : "Additional CDMA System Info", + "id" : "0x1A", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Geo System Index", + "format" : "guint16" }, + { "name" : "Registration Period", + "format" : "guint16" } ] }, + { "name" : "Additional HDR System Info", + "id" : "0x1B", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Geo System Index", + "format" : "guint16" } ] }, + { "name" : "Additional GSM System Info", + "id" : "0x1C", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Geo System Index", + "format" : "guint16" }, + { "name" : "Cell Broadcast Support", + "format" : "guint32", + "public-format" : "QmiNasCellBroadcastCapability" } ] }, + { "name" : "Additional WCDMA System Info", + "id" : "0x1D", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Geo System Index", + "format" : "guint16" }, + { "name" : "Cell Broadcast Support", + "format" : "guint32", + "public-format" : "QmiNasCellBroadcastCapability" } ] }, + { "name" : "Additional LTE System Info", + "id" : "0x1E", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Geo System Index", + "format" : "guint16" } ] }, + { "name" : "GSM Call Barring Status", + "id" : "0x1F", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "CS Status", + "format" : "gint32", + "public-format" : "QmiNasCallBarringStatus" }, + { "name" : "PS Status", + "format" : "gint32", + "public-format" : "QmiNasCallBarringStatus" } ] }, + { "name" : "WCDMA Call Barring Status", + "id" : "0x20", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "CS Status", + "format" : "gint32", + "public-format" : "QmiNasCallBarringStatus" }, + { "name" : "PS Status", + "format" : "gint32", + "public-format" : "QmiNasCallBarringStatus" } ] }, + { "name" : "LTE Voice Support", + "id" : "0x21", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "GSM Cipher Domain", + "id" : "0x22", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "WCDMA Cipher Domain", + "id" : "0x23", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "PLMN Not Changed Indication", + "id" : "0x24", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "TD SCDMA Service Status", + "id" : "0x25", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "True Service Status", + "format" : "guint8", + "public-format" : "QmiNasServiceStatus" }, + { "name" : "Preferred Data Path", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "TD SCMA System Info", + "id" : "0x26", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Domain Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Service Capability Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Service Capability", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Roaming Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Roaming Status", + "format" : "guint8", + "public-format" : "QmiNasRoamingStatus" }, + { "name" : "Forbidden Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Forbidden", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "LAC Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "LAC", + "format" : "guint16" }, + { "name" : "CID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "CID", + "format" : "guint32" }, + { "name" : "Registration Reject Info Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Registration Reject Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" }, + { "name" : "Registration Reject Cause", + "format" : "guint8" }, + { "name" : "Network ID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "MCC", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "MNC", + "format" : "string", + "fixed-size" : "3" }, + { "name" : "HS Call Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "HS Call Status", + "format" : "guint8", + "public-format" : "QmiNasWcdmaHsService" }, + { "name" : "HS Service Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "HS Service", + "format" : "guint8", + "public-format" : "QmiNasWcdmaHsService" }, + { "name" : "Cell Parameter ID Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Cell Parameter ID", + "format" : "guint16" }, + { "name" : "Cell Broadcast Support Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Cell Broadcast Support", + "format" : "guint32", + "public-format" : "QmiNasCellBroadcastCapability" }, + { "name" : "CS Call Barring Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "CS Call Barring Status", + "format" : "gint32", + "public-format" : "QmiNasCallBarringStatus" }, + { "name" : "PS Call Barring Status Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "PS Call Barring Status", + "format" : "gint32", + "public-format" : "QmiNasCallBarringStatus" }, + { "name" : "Cipher Domain Valid", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Cipher Domain", + "format" : "guint8", + "public-format" : "QmiNasNetworkServiceDomain" } ] }, + { "name" : "LTE eMBMS Coverage Info Support", + "id" : "0x27", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "SIM Reject Info", + "id" : "0x28", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiNasSimRejectState" } ] }, + + // ********************************************************************************* + { "name" : "Get Signal Info", + "type" : "Message", + "service" : "NAS", + "id" : "0x004F", + "version" : "1.8", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "CDMA Signal Strength", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "RSSI", + "format" : "gint8" }, + { "name" : "ECIO", + "format" : "gint16" } ] }, + { "name" : "HDR Signal Strength", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "RSSI", + "format" : "gint8" }, + { "name" : "ECIO", + "format" : "gint16" }, + { "name" : "SINR", + "format" : "guint8", + "public-format" : "QmiNasEvdoSinrLevel" }, + { "name" : "IO", + "format" : "gint32" } ] }, + { "name" : "GSM Signal Strength", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "gint8" }, + { "name" : "WCDMA Signal Strength", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "RSSI", + "format" : "gint8" }, + { "name" : "ECIO", + "format" : "gint16" } ] }, + { "name" : "LTE Signal Strength", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "RSSI", + "format" : "gint8" }, + { "name" : "RSRQ", + "format" : "gint8" }, + { "name" : "RSRP", + "format" : "gint16" }, + { "name" : "SNR", + "format" : "gint16" } ] }, + { "name" : "TDMA Signal Strength", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "gint8" } ] }, + + // ********************************************************************************* + { "name" : "Config Signal Info", + "type" : "Message", + "service" : "NAS", + "id" : "0x0050", + "version" : "1.8", + "input" : [ { "name" : "RSSI Threshold", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "array-element" : { "format" : "gint8" } }, + { "name" : "ECIO Threshold", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "array-element" : { "format" : "gint16" } }, + { "name" : "SINR Threshold", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "array-element" : { "format" : "guint8" } }, + { "name" : "LTE SNR Threshold", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "array-element" : { "format" : "gint16" } }, + { "name" : "IO Threshold", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "array-element" : { "format" : "gint32" } }, + { "name" : "RSRQ Threshold", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "array-element" : { "format" : "gint8" } }, + { "name" : "RSRP Threshold", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "array-element" : { "format" : "gint16" } }, + { "name" : "LTE Report", + "id" : "0x17", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Rate", + "format" : "guint8" }, + { "name" : "Average Period", + "format" : "guint8" } ] }, + { "name" : "RSCP Threshold", + "id" : "0x18", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "array-element" : { "format" : "gint8" } } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Signal Info", + "type" : "Indication", + "service" : "NAS", + "id" : "0x0051", + "version" : "1.8", + "output" : [ { "name" : "CDMA Signal Strength", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "RSSI", + "format" : "gint8" }, + { "name" : "ECIO", + "format" : "gint16" } ] }, + { "name" : "HDR Signal Strength", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "RSSI", + "format" : "gint8" }, + { "name" : "ECIO", + "format" : "gint16" }, + { "name" : "SINR", + "format" : "guint8", + "public-format" : "QmiNasEvdoSinrLevel" }, + { "name" : "IO", + "format" : "gint32" } ] }, + { "name" : "GSM Signal Strength", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "gint8" }, + { "name" : "WCDMA Signal Strength", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "RSSI", + "format" : "gint8" }, + { "name" : "ECIO", + "format" : "gint16" } ] }, + { "name" : "LTE Signal Strength", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "RSSI", + "format" : "gint8" }, + { "name" : "RSRQ", + "format" : "gint8" }, + { "name" : "RSRP", + "format" : "gint16" }, + { "name" : "SNR", + "format" : "gint16" } ] }, + { "name" : "TDMA Signal Strength", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "gint8" } ] }, + + // ********************************************************************************* + { "name" : "Get Tx Rx Info", + "type" : "Message", + "service" : "NAS", + "id" : "0x005A", + "version" : "1.9", + "input" : [ { "name" : "Radio Interface", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "gint8", + "public-format" : "QmiNasRadioInterface" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Rx Chain 0 Info", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Is Radio Tuned", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Rx Power", + "format" : "gint32" }, + { "name" : "ECIO", + "format" : "gint32" }, + { "name" : "RSCP", + "format" : "gint32" }, + { "name" : "RSRP", + "format" : "gint32" }, + { "name" : "Phase", + "format" : "guint32" } ], + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "Rx Chain 1 Info", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Is Radio Tuned", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Rx Power", + "format" : "gint32" }, + { "name" : "ECIO", + "format" : "gint32" }, + { "name" : "RSCP", + "format" : "gint32" }, + { "name" : "RSRP", + "format" : "gint32" }, + { "name" : "Phase", + "format" : "guint32" } ], + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "Tx Info", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Is In Traffic", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Tx Power", + "format" : "gint32" } ], + "prerequisites": [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get CDMA Position Info", + "type" : "Message", + "service" : "NAS", + "id" : "0x0065", + "version" : "1.3", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "CDMA Position Info", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "UI In Idle Mode", + "format" : "gint8" }, + { "name" : "BaseStations", + "format" : "array", + "size-prefix-format" : "guint8", + "array-element" : { "name" : "BaseStation", + "format" : "struct", + "contents" : [ { "name" : "Pilot Type", + "format" : "guint32", + "public-format" : "QmiNasCdmaPilotType" }, + { "name" : "System ID", + "format" : "guint16" }, + { "name" : "Network ID", + "format" : "guint16" }, + { "name" : "Base Station ID", + "format" : "guint16" }, + { "name" : "Pilot PN", + "format" : "guint16" }, + { "name" : "Pilot Strength", + "format" : "guint16" }, + { "name" : "Latitude", + "format" : "gint32" }, + { "name" : "Longitude", + "format" : "gint32" }, + { "name" : "GPS Time In Milliseconds", + "format" : "guint64" } ] } } ], + "prerequisites": [ { "common-ref" : "Success" } ] } ] } +] diff --git a/release/src/router/uqmi/data/qmi-service-oma.json b/release/src/router/uqmi/data/qmi-service-oma.json new file mode 100644 index 0000000000..bdd8c26aef --- /dev/null +++ b/release/src/router/uqmi/data/qmi-service-oma.json @@ -0,0 +1,223 @@ + +[ + // ********************************************************************************* + { "name" : "OMA", + "type" : "Service" }, + + // ********************************************************************************* + { "name" : "QMI Client OMA", + "type" : "Client" }, + + // ********************************************************************************* + { "name" : "QMI Message OMA", + "type" : "Message-ID-Enum" }, + + // ********************************************************************************* + { "name" : "QMI Indication OMA", + "type" : "Indication-ID-Enum" }, + + // ********************************************************************************* + { "name" : "Reset", + "type" : "Message", + "service" : "OMA", + "id" : "0x0000", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Set Event Report", + "type" : "Message", + "service" : "OMA", + "id" : "0x0001", + "version" : "1.0", + "input" : [ { "name" : "Network Initiated Alert Reporting", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Session State Reporting", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + { "name" : "Event Report", + "type" : "Indication", + "service" : "OMA", + "id" : "0x0001", + "output" : [ { "name" : "Network Initiated Alert", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Session Type", + "format" : "guint8", + "public-format" : "QmiOmaSessionType" }, + { "name" : "Session ID", + "format" : "guint16" } ] }, + { "name" : "Session State", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiOmaSessionState" }, + { "name" : "Session Fail Reason", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiOmaSessionFailedReason" } ] }, + + // ********************************************************************************* + { "name" : "Start Session", + "type" : "Message", + "service" : "OMA", + "id" : "0x0020", + "version" : "1.0", + "input" : [ { "name" : "Session Type", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiOmaSessionType" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Cancel Session", + "type" : "Message", + "service" : "OMA", + "id" : "0x0021", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Get Session Info", + "type" : "Message", + "service" : "OMA", + "id" : "0x0022", + "output" : [ { "name" : "Session Info", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Session State", + "format" : "guint8", + "public-format" : "QmiOmaSessionState" }, + { "name" : "Session Type", + "format" : "guint8", + "public-format" : "QmiOmaSessionType" } ], + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "Session Failed Reason", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiOmaSessionFailedReason", + "prerequisites" : [ { "field" : "Session Info Session State", + "operation" : "==", + "value" : "QMI_OMA_SESSION_STATE_FAILED" } ] }, + { "name" : "Retry Info", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Retry Count", + "format" : "guint8" }, + { "name" : "Retry Pause Timer", + "format" : "guint16" }, + { "name" : "Retry Pause Timer Remaining", + "format" : "guint16" } ], + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "Network Initiated Alert", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Session Type", + "format" : "guint8", + "public-format" : "QmiOmaSessionType" }, + { "name" : "Session ID", + "format" : "guint16" } ], + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Send Selection", + "type" : "Message", + "service" : "OMA", + "id" : "0x0023", + "input" : [ { "name" : "Network Initiated Alert Selection", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Control Point Selection Accept", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Session ID", + "format" : "guint16" } ] } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Get Feature Setting", + "type" : "Message", + "service" : "OMA", + "id" : "0x0024", + "output" : [ { "name" : "Device Provisioning Service Update Config", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "PRL Update Service Config", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "HFA Feature Config", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "HFA Feature Done State", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiOmaHfaFeatureDoneState", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Set Feature Setting", + "type" : "Message", + "service" : "OMA", + "id" : "0x0025", + "input" : [ { "name" : "Device Provisioning Service Update Config", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "PRL Update Service Config", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "HFA Feature Config", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" } ], + "output" : [ { "common-ref" : "Operation Result" } ] } +] diff --git a/release/src/router/uqmi/data/qmi-service-pbm.json b/release/src/router/uqmi/data/qmi-service-pbm.json new file mode 100644 index 0000000000..9296aeaee8 --- /dev/null +++ b/release/src/router/uqmi/data/qmi-service-pbm.json @@ -0,0 +1,298 @@ + +[ + // ********************************************************************************* + { "name" : "PBM", + "type" : "Service" }, + + // ********************************************************************************* + { "name" : "QMI Client PBM", + "type" : "Client" }, + + // ********************************************************************************* + { "name" : "QMI Message PBM", + "type" : "Message-ID-Enum" }, + + // ********************************************************************************* + { "name" : "Indication Register", + "type" : "Message", + "service" : "PBM", + "id" : "0x0001", + "version" : "1.0", + "input" : [ { "name" : "Event Registration Mask", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiPbmEventRegistrationFlag" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Event Registration Mask", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiPbmEventRegistrationFlag", + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Capabilities", + "type" : "Message", + "service" : "PBM", + "id" : "0x0002", + "version" : "1.0", + "input" : [ { "name" : "Phonebook Information", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Session Type", + "format" : "guint8", + "public-format" : "QmiPbmSessionType" }, + { "name" : "Phonebook Type", + "format" : "guint16", + "public-format" : "QmiPbmPhonebookType" } ] } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Capability Basic Information", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Session Type", + "format" : "guint8", + "public-format" : "QmiPbmSessionType" }, + { "name" : "Phonebook Type", + "format" : "guint16", + "public-format" : "QmiPbmPhonebookType" }, + { "name" : "Used Records", + "format" : "guint16" }, + { "name" : "Maximum Records", + "format" : "guint16" }, + { "name" : "Maximum Number Length", + "format" : "guint8" }, + { "name" : "Maximum Name Length", + "format" : "guint8" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Group Capability", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Maximum Groups", + "format" : "guint8" }, + { "name" : "Maximum Group Tag Length", + "format" : "guint8" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Additional Number Capability", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Maximum Additional Numbers", + "format" : "guint8" }, + { "name" : "Maximum Additional Number Length", + "format" : "guint8" }, + { "name" : "Maximum Additional Number Tag Length", + "format" : "guint8" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Email Capability", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Maximum Emails", + "format" : "guint8" }, + { "name" : "Maximum Email Address Length", + "format" : "guint8" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Second Name Capability", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Maximum Second Name Length", + "format" : "guint8" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Hidden Records Capability", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Supported", + "format" : "guint8", + "public-format" : "gboolean" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Grouping Information Alpha String Capability", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Maximum Records", + "format" : "guint8" }, + { "name" : "Used Records", + "format" : "guint8" }, + { "name" : "Maximum String Length", + "format" : "guint8" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Additional Number Alpha String Capability", + "id" : "0x17", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Maximum Records", + "format" : "guint8" }, + { "name" : "Used Records", + "format" : "guint8" }, + { "name" : "Maximum String Length", + "format" : "guint8" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get All Capabilities", + "type" : "Message", + "service" : "PBM", + "id" : "0x0003", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Capability Basic Information", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint8", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Session Type", + "format" : "guint8", + "public-format" : "QmiPbmSessionType" }, + { "name" : "Phonebooks", + "format" : "array", + "size-prefix-format" : "guint8", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Phonebook Type", + "format" : "guint16", + "public-format" : "QmiPbmPhonebookType" }, + { "name" : "Used Records", + "format" : "guint16" }, + { "name" : "Maximum Records", + "format" : "guint16" }, + { "name" : "Maximum Number Length", + "format" : "guint8" }, + { "name" : "Maximum Name Length", + "format" : "guint8" } ] } } ] }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Group Capability", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint8", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Session Type", + "format" : "guint8", + "public-format" : "QmiPbmSessionType" }, + { "name" : "Maximum Groups", + "format" : "guint8" }, + { "name" : "Maximum Group Tag Length", + "format" : "guint8" } ] }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Additional Number Capability", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint8", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Session Type", + "format" : "guint8", + "public-format" : "QmiPbmSessionType" }, + { "name" : "Maximum Additional Numbers", + "format" : "guint8" }, + { "name" : "Maximum Additional Number Length", + "format" : "guint8" }, + { "name" : "Maximum Additional Number Tag Length", + "format" : "guint8" } ] }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Email Capability", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint8", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Session Type", + "format" : "guint8", + "public-format" : "QmiPbmSessionType" }, + { "name" : "Maximum Emails", + "format" : "guint8" }, + { "name" : "Maximum Email Address Length", + "format" : "guint8" } ] }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Second Name Capability", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint8", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Session Type", + "format" : "guint8", + "public-format" : "QmiPbmSessionType" }, + { "name" : "Maximum Second Name Length", + "format" : "guint8" } ] }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Hidden Records Capability", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint8", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Session Type", + "format" : "guint8", + "public-format" : "QmiPbmSessionType" }, + { "name" : "Supported", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Grouping Information Alpha String Capability", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint8", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Session Type", + "format" : "guint8", + "public-format" : "QmiPbmSessionType" }, + { "name" : "Maximum Records", + "format" : "guint8" }, + { "name" : "Used Records", + "format" : "guint8" }, + { "name" : "Maximum String Length", + "format" : "guint8" } ] }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Additional Number Alpha String Capability", + "id" : "0x17", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint8", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Session Type", + "format" : "guint8", + "public-format" : "QmiPbmSessionType" }, + { "name" : "Maximum Records", + "format" : "guint8" }, + { "name" : "Used Records", + "format" : "guint8" }, + { "name" : "Maximum String Length", + "format" : "guint8" } ] }, + "prerequisites" : [ { "common-ref" : "Success" } ] } ] } +] diff --git a/release/src/router/uqmi/data/qmi-service-pds.json b/release/src/router/uqmi/data/qmi-service-pds.json new file mode 100644 index 0000000000..b2e3cb8a67 --- /dev/null +++ b/release/src/router/uqmi/data/qmi-service-pds.json @@ -0,0 +1,439 @@ + +[ + // ********************************************************************************* + { "name" : "PDS", + "type" : "Service" }, + + // ********************************************************************************* + { "name" : "QMI Client PDS", + "type" : "Client" }, + + // ********************************************************************************* + { "name" : "QMI Message PDS", + "type" : "Message-ID-Enum" }, + + // ********************************************************************************* + { "name" : "QMI Indication PDS", + "type" : "Indication-ID-Enum" }, + + // ********************************************************************************* + { "name" : "Reset", + "type" : "Message", + "service" : "PDS", + "id" : "0x0000", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Set Event Report", + "type" : "Message", + "service" : "PDS", + "id" : "0x0001", + "version" : "1.0", + "input" : [ { "name" : "NMEA Position Reporting", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Extended NMEA Position Reporting", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Parsed Position Reporting", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "External XTRA Data Request Reporting", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "External Time Injection Request Reporting", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "External WIFI Position Request Reporting", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Satellite Information Reporting", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "VX Network Initiated Request Reporting", + "id" : "0x17", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "SUPL Network Initiated Prompt Reporting", + "id" : "0x18", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "UMTS CP Network Initiated Prompt Reporting", + "id" : "0x19", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "PDS Comm Event Reporting", + "id" : "0x1A", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Accelerometer Data Streaming Ready Reporting", + "id" : "0x1B", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Gyro Data Streaming Ready Reporting", + "id" : "0x1C", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Time Sync Request Reporting", + "id" : "0x1D", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Position Reliability Indicator Reporting", + "id" : "0x1E", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Sensor Data Usage Indicator Reporting", + "id" : "0x1F", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Time Source Information Reporting", + "id" : "0x20", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Heading Uncertainty Reporting", + "id" : "0x21", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "NMEA Debug Strings Reporting", + "id" : "0x22", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Extended External XTRA Data Request Reporting", + "id" : "0x23", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + { "name" : "Event Report", + "type" : "Indication", + "service" : "PDS", + "id" : "0x0001", + "output" : [ { "name" : "NMEA Position", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "string", + "max-size" : "200" }, + { "name" : "Extended NMEA Position", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Operation Mode", + "format" : "gint8", + "public-format" : "QmiPdsOperationMode" }, + { "name" : "NMEA", + "format" : "string", + // This was supposed to be only 1 byte for length, but it seems it's not + "size-prefix-format" : "guint16", + "max-size" : "200" } ] }, + { "name" : "Position Session Status", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiPdsPositionSessionStatus" } ] }, + + // TODO: parse all TLVs of this indication + // Reading gfloat/gdouble is still missing + //{ "name" : "Parsed Position", + // "id" : "0x13", + // "mandatory" : "no", + // "type" : "TLV", + // "format" : "sequence", + // "contents" : [ { "name" : "Valid Mask", + // "format" : "gint8" }, + // { "name" : "Timestamp Calendar", + // "format" : "struct", + // "contents" : [ { "name" : "Year", + // "format" : "guint16" }, + // { "name" : "Month", + // "format" : "guint8" }, + // { "name" : "Day Of Week", + // "format" : "guint8" }, + // { "name" : "Day of Month", + // "format" : "guint8" }, + // { "name" : "Hour", + // "format" : "guint8" }, + // { "name" : "Minute", + // "format" : "guint8" }, + // { "name" : "Second", + // "format" : "guint8" }, + // { "name" : "Millisecond", + // "format" : "guint16" } ] }, + // { "name" : "Leap Seconds", + // "format" : "guint8" }, + // { "name" : "Timestamp UTC", + // "format" : "guint64" }, + // { "name" : "Time Uncertainty", + // "format" : "guint32" }, + // { "name" : "Latitude", + // "format" : "gdouble" }, + // { "name" : "Longitude", + // "format" : "gdouble" }, + // { "name" : "Altitude Ellipsoid", + // "format" : "gfloat" }, + // { "name" : "Altitude Sea Level", + // "format" : "gfloat" }, + // { "name" : "Horizontal Speed", + // "format" : "gfloat" }, + // { "name" : "Vertical Speed", + // "format" : "gfloat" }, + // { "name" : "Heading", + // "format" : "gfloat" }, + // { "name" : "Horizontal Uncertainty Circular", + // "format" : "gfloat" }, + // { "name" : "Horizontal Uncertainty Ellipse Semi Major", + // "format" : "gfloat" }, + // { "name" : "Horizontal Uncertainty Ellipse Semi Minor", + // "format" : "gfloat" }, + // { "name" : "Horizontal Uncertainty Ellipse Orient Azimuth", + // "format" : "gfloat" }, + // { "name" : "Vertical Uncertainty", + // "format" : "gfloat" }, + // { "name" : "Horizontal Velocity Uncertainty", + // "format" : "gfloat" }, + // { "name" : "Vertical Velocity Uncertainty", + // "format" : "gfloat" }, + // { "name" : "Horizontal confidence", + // "format" : "guint8" }, + // { "name" : "Position DOP", + // "format" : "gfloat" }, + // { "name" : "Horizontal DOP", + // "format" : "gfloat" }, + // { "name" : "Vertical DOP", + // "format" : "gfloat" }, + // { "name" : "Operation Mode", + // "format" : "gint8", + // "public-format" : "QmiPdsOperationMode" } ], + // "prerequisites": [ { "field" : "Position Session Status", + // "operation" : "<=", + // "value" : "QMI_PDS_POSITION_SESSION_STATUS_IN_PROGRESS" } ] } ] } + + // ********************************************************************************* + { "name" : "Get GPS Service State", + "type" : "Message", + "service" : "PDS", + "id" : "0x0020", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "State", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "GPS Service State", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Tracking Session State", + "format" : "guint8", + "public-format" : "QmiPdsTrackingSessionState" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Set GPS Service State", + "type" : "Message", + "service" : "PDS", + "id" : "0x0021", + "version" : "1.0", + "input" : [ { "name" : "State", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "GPS Service State", + "format" : "guint8", + "public-format" : "gboolean" } ] } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Get Default Tracking Session", + "type" : "Message", + "service" : "PDS", + "id" : "0x0029", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Info", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Session Operation", + "format" : "guint8", + "public-format" : "QmiPdsOperatingMode" }, + { "name" : "Position Data Timeout", + "format" : "guint8" }, + { "name" : "Interval", + "format" : "guint32" }, + { "name" : "Accuracy Threshold", + "format" : "guint32" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Set Default Tracking Session", + "type" : "Message", + "service" : "PDS", + "id" : "0x002A", + "version" : "1.0", + "input" : [ { "name" : "Info", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Session Operation", + "format" : "guint8", + "public-format" : "QmiPdsOperatingMode" }, + { "name" : "Position Data Timeout", + "format" : "guint8" }, + { "name" : "Interval", + "format" : "guint32" }, + { "name" : "Accuracy Threshold", + "format" : "guint32" } ] } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Get AGPS Config", + "type" : "Message", + "service" : "PDS", + "id" : "0x002E", + "version" : "1.0", + "input" : [ { "name" : "Network Mode", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiPdsNetworkMode" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Location Server Address", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "IP", + "format" : "guint32", + "endian" : "little" }, + { "name" : "Port", + "format" : "guint32" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Location Server URL", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint8", + "array-element" : { "format" : "guint8" }, + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Set AGPS Config", + "type" : "Message", + "service" : "PDS", + "id" : "0x002F", + "version" : "1.0", + "input" : [ { "name" : "Location Server Address", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "IP", + "format" : "guint32", + "format" : "guint32" }, + { "name" : "Port", + "format" : "guint32" } ] }, + { "name" : "Location Server URL", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint8", + "array-element" : { "format" : "guint8" } }, + { "name" : "Network Mode", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiPdsNetworkMode" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Get Auto Tracking State", + "type" : "Message", + "service" : "PDS", + "id" : "0x0030", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "State", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Auto Tracking State", + "format" : "guint8", + "public-format" : "gboolean" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Set Auto Tracking State", + "type" : "Message", + "service" : "PDS", + "id" : "0x0031", + "version" : "1.0", + "input" : [ { "name" : "State", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Auto Tracking State", + "format" : "guint8", + "public-format" : "gboolean" } ] } ], + "output" : [ { "common-ref" : "Operation Result" } ] } + +] diff --git a/release/src/router/uqmi/data/qmi-service-uim.json b/release/src/router/uqmi/data/qmi-service-uim.json new file mode 100644 index 0000000000..596ed3e993 --- /dev/null +++ b/release/src/router/uqmi/data/qmi-service-uim.json @@ -0,0 +1,359 @@ + +[ + // ********************************************************************************* + { "name" : "UIM", + "type" : "Service" }, + + // ********************************************************************************* + { "name" : "QMI Client UIM", + "type" : "Client" }, + + // ********************************************************************************* + { "name" : "QMI Message UIM", + "type" : "Message-ID-Enum" }, + + // ********************************************************************************* + { "name" : "Reset", + "type" : "Message", + "service" : "UIM", + "id" : "0x0000", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Read Transparent", + "type" : "Message", + "service" : "UIM", + "id" : "0x0020", + "version" : "1.0", + "input" : [ { "name" : "Session Information", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Session Type", + "format" : "guint8", + "public-format" : "QmiUimSessionType" }, + { "name" : "Application Identifier", + "format" : "string" } ] }, + { "name" : "File", + "id" : "0x02", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "File ID", + "format" : "guint16" }, + { "name" : "File Path", + "format" : "array", + "array-element" : { "format" : "guint8" } } ] }, + { "name" : "Read Information", + "id" : "0x03", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Offset", + "format" : "guint16" }, + { "name" : "Length", + "format" : "guint16" } ] }, + { "name" : "Response In Indication Token", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32" }, + { "name" : "Encrypt Data", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Card result", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "SW1", + "format" : "guint8" }, + { "name" : "SW2", + "format" : "guint8" } ] }, + { "name" : "Read result", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "format" : "guint8" }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Response In Indication Token", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Encrypted Data", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean", + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Read Record", + "type" : "Message", + "service" : "UIM", + "id" : "0x0021", + "version" : "1.0", + "input" : [ { "name" : "Session Information", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Session Type", + "format" : "guint8", + "public-format" : "QmiUimSessionType" }, + { "name" : "Application Identifier", + "format" : "string" } ] }, + { "name" : "File", + "id" : "0x02", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "File ID", + "format" : "guint16" }, + { "name" : "File Path", + "format" : "array", + "array-element" : { "format" : "guint8" } } ] }, + { "name" : "Record", + "id" : "0x03", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Record Number", + "format" : "guint16" }, + { "name" : "Record Length", + "format" : "guint16" } ] }, + { "name" : "Last Record", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16" }, + { "name" : "Response In Indication Token", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Card result", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "SW1", + "format" : "guint8" }, + { "name" : "SW2", + "format" : "guint8" } ] }, + { "name" : "Read Result", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "format" : "guint8" }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Additional Read Result", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "format" : "guint8" }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Response In Indication Token", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get File Attributes", + "type" : "Message", + "service" : "UIM", + "id" : "0x0024", + "version" : "1.0", + "input" : [ { "name" : "Session Information", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Session Type", + "format" : "guint8", + "public-format" : "QmiUimSessionType" }, + { "name" : "Application Identifier", + "format" : "string" } ] }, + { "name" : "File", + "id" : "0x02", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "File ID", + "format" : "guint16" }, + { "name" : "File Path", + "format" : "array", + "array-element" : { "format" : "guint8" } } ] }, + { "name" : "Response In Indication Token", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Card result", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "SW1", + "format" : "guint8" }, + { "name" : "SW2", + "format" : "guint8" } ] }, + { "name" : "File Attributes", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "File Size", + "format" : "guint16" }, + { "name" : "File ID", + "format" : "guint16" }, + { "name" : "File Type", + "format" : "guint8", + "public-format" : "QmiUimFileType" }, + { "name" : "Record Size", + "format" : "guint16" }, + { "name" : "Record Count", + "format" : "guint16" }, + { "name" : "Read Security Attributes Logic", + "format" : "guint8", + "public-format" : "QmiUimSecurityAttributeLogic" }, + { "name" : "Read Security Attributes", + "format" : "guint16", + "public-format" : "QmiUimSecurityAttribute" }, + { "name" : "Write Security Attributes Logic", + "format" : "guint8", + "public-format" : "QmiUimSecurityAttributeLogic" }, + { "name" : "Write Security Attributes", + "format" : "guint16", + "public-format" : "QmiUimSecurityAttribute" }, + { "name" : "Increase Security Attributes Logic", + "format" : "guint8", + "public-format" : "QmiUimSecurityAttributeLogic" }, + { "name" : "Increase Security Attributes", + "format" : "guint16", + "public-format" : "QmiUimSecurityAttribute" }, + { "name" : "Deactivate Security Attributes Logic", + "format" : "guint8", + "public-format" : "QmiUimSecurityAttributeLogic" }, + { "name" : "Deactivate Security Attributes", + "format" : "guint16", + "public-format" : "QmiUimSecurityAttribute" }, + { "name" : "Activate Security Attributes Logic", + "format" : "guint8", + "public-format" : "QmiUimSecurityAttributeLogic" }, + { "name" : "Activate Security Attributes", + "format" : "guint16", + "public-format" : "QmiUimSecurityAttribute" }, + { "name" : "Raw Data", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "format" : "guint8" } } ], + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Response In Indication Token", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Card Status", + "type" : "Message", + "service" : "UIM", + "id" : "0x002F", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Card Status", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Index GW Primary", + "format" : "guint16" }, + { "name" : "Index 1x Primary", + "format" : "guint16" }, + { "name" : "Index GW Secondary ", + "format" : "guint16" }, + { "name" : "Index 1x Secondary", + "format" : "guint16" }, + { "name" : "Cards", + "format" : "array", + "size-prefix-format" : "guint8", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Card State", + "format" : "guint8", + "public-format" : "QmiUimCardState" }, + { "name" : "UPIN State", + "format" : "guint8", + "public-format" : "QmiUimPinState" }, + { "name" : "UPIN Retries", + "format" : "guint8" }, + { "name" : "UPUK Retries", + "format" : "guint8" }, + { "name" : "Error code", + "format" : "guint8", + "public-format" : "QmiUimCardError" }, + { "name" : "Applications", + "format" : "array", + "size-prefix-format" : "guint8", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Type", + "format" : "guint8", + "public-format" : "QmiUimCardApplicationType" }, + { "name" : "State", + "format" : "guint8", + "public-format" : "QmiUimCardApplicationState" }, + { "name" : "Personalization State", + "format" : "guint8", + "public-format" : "QmiUimCardApplicationPersonalizationState" }, + { "name" : "Personalization Feature", + "format" : "guint8", + "public-format" : "QmiUimCardApplicationPersonalizationFeature" }, + { "name" : "Personalization Retries", + "format" : "guint8" }, + { "name" : "Personalization Unblock Retries", + "format" : "guint8" }, + { "name" : "Application Identifier Value", + "format" : "array", + "size-prefix-format" : "guint8", + "array-element" : { "format" : "guint8" } }, + { "name" : "UPIN replaces PIN1", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "PIN1 State", + "format" : "guint8", + "public-format" : "QmiUimPinState" }, + { "name" : "PIN1 Retries", + "format" : "guint8" }, + { "name" : "PUK1 Retries", + "format" : "guint8" }, + { "name" : "PIN2 State", + "format" : "guint8", + "public-format" : "QmiUimPinState" }, + { "name" : "PIN2 Retries", + "format" : "guint8" }, + { "name" : "PUK2 Retries", + "format" : "guint8" } ] } } ] } } ] } ] } + +] diff --git a/release/src/router/uqmi/data/qmi-service-wda.json b/release/src/router/uqmi/data/qmi-service-wda.json new file mode 100644 index 0000000000..3a9b797189 --- /dev/null +++ b/release/src/router/uqmi/data/qmi-service-wda.json @@ -0,0 +1,162 @@ + +[ + // ********************************************************************************* + { "name" : "WDA", + "type" : "Service" }, + + // ********************************************************************************* + { "name" : "QMI Client WDA", + "type" : "Client" }, + + // ********************************************************************************* + { "name" : "QMI Message WDA", + "type" : "Message-ID-Enum" }, + + // ********************************************************************************* + { "name" : "Set Data Format", + "type" : "Message", + "service" : "WDA", + "id" : "0x0020", + "version" : "1.0", + "input" : [ { "name" : "QoS Format", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Link Layer Protocol", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiWdaLinkLayerProtocol" }, + { "name" : "Uplink Data Aggregation Protocol", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiWdaDataAggregationProtocol" }, + { "name" : "Downlink Data Aggregation Protocol", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiWdaDataAggregationProtocol" }, + { "name" : "NDP Signature", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32" }, + { "name" : "Downlink Data Aggregation Max Datagrams", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32" }, + { "name" : "Downlink Data Aggregation Max Size", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "QoS Format", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean", + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "Link Layer Protocol", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiWdaLinkLayerProtocol", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Uplink Data Aggregation Protocol", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiWdaDataAggregationProtocol", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Downlink Data Aggregation Protocol", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiWdaDataAggregationProtocol", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "NDP Signature", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Downlink Data Aggregation Max Datagrams", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Downlink Data Aggregation Max Size", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Data Format", + "type" : "Message", + "service" : "WDA", + "id" : "0x0021", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "QoS Format", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean", + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "Link Layer Protocol", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiWdaLinkLayerProtocol", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Uplink Data Aggregation Protocol", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiWdaDataAggregationProtocol", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Downlink Data Aggregation Protocol", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiWdaDataAggregationProtocol", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "NDP Signature", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Uplink Data Aggregation Max Size", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Downlink Data Aggregation Max Size", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] } ] } + +] diff --git a/release/src/router/uqmi/data/qmi-service-wds.json b/release/src/router/uqmi/data/qmi-service-wds.json new file mode 100644 index 0000000000..ab48e8a6ab --- /dev/null +++ b/release/src/router/uqmi/data/qmi-service-wds.json @@ -0,0 +1,1069 @@ + +[ + // ********************************************************************************* + { "name" : "WDS", + "type" : "Service" }, + + // ********************************************************************************* + { "name" : "QMI Client WDS", + "type" : "Client" }, + + // ********************************************************************************* + { "name" : "QMI Message WDS", + "type" : "Message-ID-Enum" }, + + // ********************************************************************************* + { "name" : "Reset", + "type" : "Message", + "service" : "WDS", + "id" : "0x0000", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Abort", + "type" : "Message", + "service" : "WDS", + "id" : "0x0002", + "version" : "1.0", + // This magic tag allows us to avoid creating a method in the client + "scope" : "library-only", + "input" : [ { "name" : "Transaction ID", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint16" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Start Network", + "type" : "Message", + "service" : "WDS", + "id" : "0x0020", + "version" : "1.0", + // This method may be aborted + "abort" : "yes", + "input" : [ { "name" : "Primary DNS Address Preference", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32" }, + { "name" : "Secondary DNS Address Preference", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32" }, + { "name" : "Primary NBNS Address Preference", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32" }, + { "name" : "Secondary NBNS Address Preference", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32" }, + { "name" : "APN", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "string" }, + { "name" : "IPv4 Address Preference", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32" }, + { "name" : "Authentication Preference", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWdsAuthentication" }, + { "name" : "Username", + "id" : "0x17", + "mandatory" : "no", + "type" : "TLV", + "format" : "string" }, + { "name" : "Password", + "id" : "0x18", + "mandatory" : "no", + "type" : "TLV", + "format" : "string" }, + { "name" : "IP Family Preference", + "id" : "0x19", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWdsIpFamily" }, + { "name" : "Technology Preference", + "id" : "0x30", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWdsTechnologyPreference" }, + { "name" : "Profile Index 3GPP", + "id" : "0x31", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8" }, + { "name" : "Profile Index 3GPP2", + "id" : "0x32", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8" }, + { "name" : "Enable Autoconnect", + "id" : "0x33", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Extended Technology Preference", + "id" : "0x34", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiWdsExtendedTechnologyPreference" }, + { "name" : "Call Type", + "id" : "0x35", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWdsCallType" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Packet Data Handle", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint32", + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "Call End Reason", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiWdsCallEndReason", + "prerequisites" : [ { "field" : "Result.Error Status", + "operation" : "!=", + "value" : "QMI_STATUS_SUCCESS" }, + { "field" : "Result.Error Code", + "operation" : "==", + "value" : "QMI_PROTOCOL_ERROR_CALL_FAILED" } ] }, + { "name" : "Verbose Call End Reason", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Type", + "format" : "guint16", + "public-format" : "QmiWdsVerboseCallEndReasonType" }, + { "name" : "Reason", + "format" : "gint16" } ], + "prerequisites": [ { "field" : "Result.Error Status", + "operation" : "!=", + "value" : "QMI_STATUS_SUCCESS" }, + { "field" : "Result.Error Code", + "operation" : "==", + "value" : "QMI_PROTOCOL_ERROR_CALL_FAILED" } ] } ] }, + + // ********************************************************************************* + { "name" : "Stop Network", + "type" : "Message", + "service" : "WDS", + "id" : "0x0021", + "version" : "1.0", + "input" : [ { "name" : "Packet Data Handle", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint32" }, + { "name" : "Disable Autoconnect", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Get Packet Service Status", + "type" : "Message", + "service" : "WDS", + "id" : "0x0022", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Connection Status", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWdsConnectionStatus", + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Packet Statistics", + "type" : "Message", + "service" : "WDS", + "id" : "0x0024", + "version" : "1.0", + "input" : [ { "name" : "Mask", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiWdsPacketStatisticsMaskFlag" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Tx Packets Ok", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Rx Packets Ok", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Tx Packets Error", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Rx Packets Error", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Tx Overflows", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Rx Overflows", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Tx Bytes Ok", + "id" : "0x19", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint64", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Rx Bytes Ok", + "id" : "0x1A", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint64", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Last Call Tx Bytes Ok", + "id" : "0x1B", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint64", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Last Call Rx Bytes Ok", + "id" : "0x1C", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint64", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Tx Packets Dropped", + "id" : "0x1D", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Rx Packets Dropped", + "id" : "0x1E", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Profile List", + "type" : "Message", + "service" : "WDS", + "id" : "0x002A", + "version" : "1.1", + "input" : [ { "name" : "Profile Type", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWdsProfileType" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Profile List", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "array", + "array-element" : { "name" : "Profile", + "format" : "struct", + "contents" : [ { "name" : "Profile Type", + "format" : "guint8", + "public-format" : "QmiWdsProfileType" }, + { "name" : "Profile Index", + "format" : "guint8" }, + { "name" : "Profile Name", + "format" : "string" } ] }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Extended Error Code", + "id" : "0xE0", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiWdsDsProfileError", + "prerequisites" : [ { "field" : "Result.Error Status", + "operation" : "!=", + "value" : "QMI_STATUS_SUCCESS" }, + { "field" : "Result.Error Code", + "operation" : "==", + "value" : "QMI_PROTOCOL_ERROR_EXTENDED_INTERNAL" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Profile Settings", + "type" : "Message", + "service" : "WDS", + "id" : "0x002B", + "version" : "1.1", + "input" : [ { "name" : "Profile ID", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Profile Type", + "format" : "guint8", + "public-format" : "QmiWdsProfileType" }, + { "name" : "Profile Index", + "format" : "guint8" } ] } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Profile Name", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "string", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "PDP Type", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWdsPdpType", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "APN Name", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "string", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Primary IPv4 DNS Address", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "endian" : "little", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Secondary IPv4 DNS Address", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "endian" : "little", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + // 0x17 UMTS Requested QoS + // 0x18 UMTS Minimum QoS + { "name" : "GPRS Requested QoS", + "id" : "0x19", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Precedence Class", + "format" : "guint32" }, + { "name" : "Delay Class", + "format" : "guint32" }, + { "name" : "Reliability Class", + "format" : "guint32" }, + { "name" : "Peak Throughput Class", + "format" : "guint32" }, + { "name" : "Mean Throughput Class", + "format" : "guint32" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "GPRS Minimum QoS", + "id" : "0x1A", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Precedence Class", + "format" : "guint32" }, + { "name" : "Delay Class", + "format" : "guint32" }, + { "name" : "Reliability Class", + "format" : "guint32" }, + { "name" : "Peak Throughput Class", + "format" : "guint32" }, + { "name" : "Mean Throughput Class", + "format" : "guint32" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Username", + "id" : "0x1B", + "mandatory" : "no", + "type" : "TLV", + "format" : "string", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Password", + "id" : "0x1C", + "mandatory" : "no", + "type" : "TLV", + "format" : "string", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Authentication", + "id" : "0x1D", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWdsAuthentication", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "IPv4 Address Preference", + "id" : "0x1E", + "mandatory" : "no", + "type" : "TLV", + "endian" : "little", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "PCSCF Address Using PCO", + "id" : "0x1F", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + // 0x20, PDP access control flag + { "name" : "PCSCF Address Using DHCP", + "id" : "0x21", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "IMCN Flag", + "id" : "0x22", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + // 0x23, TFT ID1 Parameters + // 0x24, TFT ID2 Parameters + // 0x25, PDP context number + // 0x26, PDP context secondary flag + // 0x27, PDP context primary id + { "name" : "IPv6 Address Preference", + "id" : "0x28", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Address", + "format" : "array", + "fixed-size" : "8", + "array-element" : { "format": "guint16", "endian": "network" } } ] }, + // 0x29, UMTS requested QoS with Signaling Indication Flag + // 0x2A, UMTS minimum QoS with Signaling Indication Flag + { "name" : "IPv6 Primary DNS Address Preference", + "id" : "0x2B", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "fixed-size": "8", + "array-element" : { "format": "guint16", "endian": "network" }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "IPv6 Secondary DNS Address Preference", + "id" : "0x2C", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "fixed-size": "8", + "array-element" : { "format": "guint16", "endian": "network" }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + // 0x2D, DHCP/NAS Preference + // 0x2E, 3GPP LTE QoS Parameters + // 0x2F, APN disabled flag + // 0x30, PDN inactivity timeout + // 0x31, APN class + // 0x90, Negotiate DNS server preference + // 0x91, PPP session close timer for DO + // 0x92, PPP session close timer for 1X + // 0x93, Allow/disallow lingering of interface + // 0x94, LCP ACK timeout + // 0x95, IPCP ACK timeout + // 0x96, AUTH timeout + // 0x97, LCP configuration request retry count value + // 0x98, IPCP configuration request retry count value + // 0x99, Authentication retry + // 0x9A, Authentication protocol, + // 0x9B, User ID + // 0x9C, Authentication password + // 0x9D, Data rate + // 0x9E, Application type + // 0x9F, Data mode + // 0xA0, Application priority + // 0xA1, APN string + // 0xA2, PDN type + // 0xA3, Is PCSCF address needed + // 0xA4, IPv4 Primary DNS address + // 0xA5, IPv4 Secondary DNS address + // 0xA6, IPv6 Primary DNS address + // 0xA7, IPv6 Secondary DNS address + // 0xA8, RAT type + // 0xA9, APN enabled + // 0xAA, PDN inactivity timeout + // 0xAB, APN class + { "name" : "Extended Error Code", + "id" : "0xE0", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiWdsDsProfileError", + "prerequisites" : [ { "field" : "Result.Error Status", + "operation" : "!=", + "value" : "QMI_STATUS_SUCCESS" }, + { "field" : "Result.Error Code", + "operation" : "==", + "value" : "QMI_PROTOCOL_ERROR_EXTENDED_INTERNAL" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Default Settings", + "type" : "Message", + "service" : "WDS", + "id" : "0x002C", + "version" : "1.1", + "input" : [ { "name" : "Profile Type", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWdsProfileType" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Profile Name", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "string", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "PDP Type", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWdsPdpType", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "APN Name", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "string", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Primary IPv4 DNS Address", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "endian" : "little", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Secondary IPv4 DNS Address", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "endian" : "little", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + // 0x17 UMTS Requested QoS + // 0x18 UMTS Minimum QoS + { "name" : "GPRS Requested QoS", + "id" : "0x19", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Precedence Class", + "format" : "guint32" }, + { "name" : "Delay Class", + "format" : "guint32" }, + { "name" : "Reliability Class", + "format" : "guint32" }, + { "name" : "Peak Throughput Class", + "format" : "guint32" }, + { "name" : "Mean Throughput Class", + "format" : "guint32" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "GPRS Minimum QoS", + "id" : "0x1A", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Precedence Class", + "format" : "guint32" }, + { "name" : "Delay Class", + "format" : "guint32" }, + { "name" : "Reliability Class", + "format" : "guint32" }, + { "name" : "Peak Throughput Class", + "format" : "guint32" }, + { "name" : "Mean Throughput Class", + "format" : "guint32" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Username", + "id" : "0x1B", + "mandatory" : "no", + "type" : "TLV", + "format" : "string", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Password", + "id" : "0x1C", + "mandatory" : "no", + "type" : "TLV", + "format" : "string", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Authentication", + "id" : "0x1D", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWdsAuthentication", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "IPv4 Address Preference", + "id" : "0x1E", + "mandatory" : "no", + "type" : "TLV", + "endian" : "little", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "PCSCF Address Using PCO", + "id" : "0x1F", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + // 0x20, PDP access control flag + { "name" : "PCSCF Address Using DHCP", + "id" : "0x21", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "IMCN Flag", + "id" : "0x22", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + // 0x23, TFT ID1 Parameters + // 0x24, TFT ID2 Parameters + // 0x25, PDP context number + // 0x26, PDP context secondary flag + // 0x27, PDP context primary id + { "name" : "IPv6 Address Preference", + "id" : "0x28", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Address", + "format" : "array", + "fixed-size" : "8", + "array-element" : { "format": "guint16", "endian": "network" } } ] }, + // 0x29, UMTS requested QoS with Signaling Indication Flag + // 0x2A, UMTS minimum QoS with Signaling Indication Flag + { "name" : "IPv6 Primary DNS Address Preference", + "id" : "0x2B", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "fixed-size": "8", + "array-element" : { "format": "guint16", "endian": "network" }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "IPv6 Secondary DNS Address Preference", + "id" : "0x2C", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "fixed-size": "8", + "array-element" : { "format": "guint16", "endian": "network" }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + // 0x2D, DHCP/NAS Preference + // 0x2E, 3GPP LTE QoS Parameters + // 0x2F, APN disabled flag + // 0x30, PDN inactivity timeout + // 0x31, APN class + // 0x90, Negotiate DNS server preference + // 0x91, PPP session close timer for DO + // 0x92, PPP session close timer for 1X + // 0x93, Allow/disallow lingering of interface + // 0x94, LCP ACK timeout + // 0x95, IPCP ACK timeout + // 0x96, AUTH timeout + // 0x97, LCP configuration request retry count value + // 0x98, IPCP configuration request retry count value + // 0x99, Authentication retry + // 0x9A, Authentication protocol, + // 0x9B, User ID + // 0x9C, Authentication password + // 0x9D, Data rate + // 0x9E, Application type + // 0x9F, Data mode + // 0xA0, Application priority + // 0xA1, APN string + // 0xA2, PDN type + // 0xA3, Is PCSCF address needed + // 0xA4, IPv4 Primary DNS address + // 0xA5, IPv4 Secondary DNS address + // 0xA6, IPv6 Primary DNS address + // 0xA7, IPv6 Secondary DNS address + // 0xA8, RAT type + // 0xA9, APN enabled + // 0xAA, PDN inactivity timeout + // 0xAB, APN class + { "name" : "Extended Error Code", + "id" : "0xE0", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiWdsDsProfileError", + "prerequisites" : [ { "field" : "Result.Error Status", + "operation" : "!=", + "value" : "QMI_STATUS_SUCCESS" }, + { "field" : "Result.Error Code", + "operation" : "==", + "value" : "QMI_PROTOCOL_ERROR_EXTENDED_INTERNAL" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Current Settings", + "type" : "Message", + "service" : "WDS", + "id" : "0x002D", + "version" : "1.2", + "input" : [ { "name" : "Requested Settings", + "id" : "0x10", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint32", + "public-format" : "QmiWdsGetCurrentSettingsRequestedSettings" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Profile Name", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "string", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "PDP Type", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWdsPdpType", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "APN Name", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "string", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Primary IPv4 DNS Address", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "endian" : "little", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Secondary IPv4 DNS Address", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "endian" : "little", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "GPRS Granted QoS", + "id" : "0x19", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Precedence Class", + "format" : "guint32" }, + { "name" : "Delay Class", + "format" : "guint32" }, + { "name" : "Reliability Class", + "format" : "guint32" }, + { "name" : "Peak Throughput Class", + "format" : "guint32" }, + { "name" : "Mean Throughput Class", + "format" : "guint32" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Username", + "id" : "0x1B", + "mandatory" : "no", + "type" : "TLV", + "format" : "string", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Authentication", + "id" : "0x1D", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWdsAuthentication", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "IPv4 Address", + "id" : "0x1E", + "mandatory" : "no", + "type" : "TLV", + "endian" : "little", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Profile ID", + "id" : "0x1F", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Profile Type", + "format" : "guint8", + "public-format" : "QmiWdsProfileType" }, + { "name" : "Profile Index", + "format" : "guint8" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "IPv4 Gateway Address", + "id" : "0x20", + "mandatory" : "no", + "type" : "TLV", + "endian" : "little", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "IPv4 Gateway Subnet Mask", + "id" : "0x21", + "mandatory" : "no", + "type" : "TLV", + "endian" : "little", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "PCSCF Address Using PCO", + "id" : "0x22", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "PCSCF Server Address List", + "id" : "0x23", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "array-element" : { "name" : "IPv4 Address", + "endian" : "little", + "format" : "guint32" }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "PCSCF Domain Name List", + "id" : "0x24", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "array-element" : { "name" : "FQDN", + "format" : "string", + "size-prefix-format" : "guint16" }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "IPv6 Address", + "id" : "0x25", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Address", + "format" : "array", + "fixed-size" : "8", + "array-element" : { "format": "guint16", "endian": "network" } }, + { "name" : "Prefix Length", + "format" : "guint8" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "IPv6 Gateway Address", + "id" : "0x26", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Address", + "format" : "array", + "fixed-size" : "8", + "array-element" : { "format": "guint16", "endian": "network" } }, + { "name" : "Prefix Length", + "format" : "guint8" } ], + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "IPv6 Primary DNS Address", + "id" : "0x27", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "fixed-size": "8", + "array-element" : { "format": "guint16", "endian": "network" }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "IPv6 Secondary DNS Address", + "id" : "0x28", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "fixed-size": "8", + "array-element" : { "format": "guint16", "endian": "network" }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "MTU", + "id" : "0x29", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Domain Name List", + "id" : "0x2A", + "mandatory" : "no", + "type" : "TLV", + "format" : "array", + "array-element" : { "name" : "Domain Name", + "format" : "string", + "size-prefix-format" : "guint16" }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "IP Family", + "id" : "0x2B", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWdsIpFamily", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "IMCN Flag", + "id" : "0x2C", + "mandatory" : "no", + "type" : "TLV", + "format" : "gint8", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Extended Technology Preference", + "id" : "0x2D", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiWdsExtendedTechnologyPreference", + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Autoconnect Setting", + "type" : "Message", + "service" : "WDS", + "id" : "0x0034", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Setting", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "gint8", + "public-format" : "QmiWdsAutoconnectSetting", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Roaming", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "gint8", + "public-format" : "gboolean", + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Data Bearer Technology", + "type" : "Message", + "service" : "WDS", + "id" : "0x0037", + "version" : "1.12", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Current", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "gint8", + "public-format" : "QmiWdsDataBearerTechnology", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Last", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "gint8", + "public-format" : "QmiWdsDataBearerTechnology", + "prerequisites" : [ { "field" : "Result.Error Status", + "operation" : "!=", + "value" : "QMI_STATUS_SUCCESS" }, + { "field" : "Result.Error Code", + "operation" : "==", + "value" : "QMI_PROTOCOL_ERROR_OUT_OF_CALL" } ] } ] }, + + // ********************************************************************************* + { "name" : "Get Current Data Bearer Technology", + "type" : "Message", + "service" : "WDS", + "id" : "0x0044", + "version" : "1.4", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Current", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Network Type", + "format" : "guint8", + "public-format" : "QmiWdsNetworkType" }, + { "name" : "RAT Mask", + "format" : "guint32" }, + { "name" : "SO Mask", + "format" : "guint32" } ], + "prerequisites": [ { "common-ref" : "Success" } ] }, + { "name" : "Last", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Network Type", + "format" : "guint8", + "public-format" : "QmiWdsNetworkType" }, + { "name" : "RAT Mask", + "format" : "guint32" }, + { "name" : "SO Mask", + "format" : "guint32" } ] } ] }, + + // ********************************************************************************* + { "name" : "Set IP Family", + "type" : "Message", + "service" : "WDS", + "id" : "0x004D", + "version" : "1.9", + "input" : [ { "name" : "Preference", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWdsIpFamily" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + + // ********************************************************************************* + { "name" : "Set Autoconnect Setting", + "type" : "Message", + "service" : "WDS", + "id" : "0x0051", + "version" : "1.0", + "input" : [ { "name" : "Setting", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWdsAutoconnectSetting" }, + { "name" : "Roaming", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" } ], + "output" : [ { "common-ref" : "Operation Result" } ] } + +] diff --git a/release/src/router/uqmi/data/qmi-service-wms.json b/release/src/router/uqmi/data/qmi-service-wms.json new file mode 100644 index 0000000000..75accd44a0 --- /dev/null +++ b/release/src/router/uqmi/data/qmi-service-wms.json @@ -0,0 +1,567 @@ + +[ + // ********************************************************************************* + { "name" : "WMS", + "type" : "Service" }, + + // ********************************************************************************* + { "name" : "QMI Client WMS", + "type" : "Client" }, + + // ********************************************************************************* + { "name" : "QMI Message WMS", + "type" : "Message-ID-Enum" }, + + // ********************************************************************************* + { "name" : "QMI Indication WMS", + "type" : "Indication-ID-Enum" }, + + // ********************************************************************************* + { "name" : "Reset", + "type" : "Message", + "service" : "WMS", + "id" : "0x0000", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Set Event Report", + "type" : "Message", + "service" : "WMS", + "id" : "0x0001", + "version" : "1.0", + "input" : [ { "name" : "New MT Message Indicator", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Report", + "format" : "guint8", + "public-format" : "gboolean" } ] } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + { "name" : "Event Report", + "type" : "Indication", + "service" : "WMS", + "id" : "0x0001", + "output" : [ { "name" : "MT Message", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Storage Type", + "format" : "guint8", + "public-format" : "QmiWmsStorageType" }, + { "name" : "Memory Index", + "format" : "guint32" } ] }, + { "name" : "Transfer Route MT Message", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Ack Indicator", + "format" : "guint8", + "public-format" : "QmiWmsAckIndicator" }, + { "name" : "Transaction ID", + "format" : "guint32" }, + { "name" : "Format", + "format" : "guint8", + "public-format" : "QmiWmsMessageFormat" }, + { "name" : "Raw Data", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "format" : "guint8" } } ] }, + { "name" : "Message Mode", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWmsMessageMode" }, + { "name" : "ETWS Message", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Notification Type", + "format" : "guint8", + "public-format" : "QmiWmsNotificationType" }, + { "name" : "Raw Data", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "format" : "guint8" } } ] }, + { "name" : "ETWS PLMN Information", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "MCC", + "format" : "guint16" }, + { "name" : "MNC", + "format" : "guint16" } ] }, + { "name" : "SMSC Address", + "id" : "0x15", + "mandatory" : "no", + "type" : "TLV", + "format" : "string" }, + { "name" : "SMS on IMS", + "id" : "0x16", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + + // ********************************************************************************* + { "name" : "Raw Send", + "type" : "Message", + "service" : "WMS", + "id" : "0x0020", + "version" : "1.0", + "input" : [ { "name" : "Raw Message Data", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Format", + "format" : "guint8", + "public-format" : "QmiWmsMessageFormat" }, + { "name" : "Raw Data", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "format" : "guint8" } } ] }, + { "name" : "CDMA Force On DC", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Force", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "Service Option", + "format" : "guint8", + "public-format" : "QmiWmsCdmaServiceOption" } ] }, + { "name" : "CDMA Follow On DC", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Follow", + "format" : "guint8", + "public-format" : "gboolean" } ] }, + { "name" : "GSM WCDMA Link Timer", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8" }, + { "name" : "SMS on IMS", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Message ID", + "id" : "0x01", + // Even if we have this TLV as mandatory, it seems it really isn't + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "CDMA Cause Code", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiWmsCdmaCauseCode", + "prerequisites" : [ { "field" : "Result.Error Status", + "operation" : "!=", + "value" : "QMI_STATUS_SUCCESS" }, + { "field" : "Result.Error Code", + "operation" : "==", + "value" : "QMI_PROTOCOL_ERROR_WMS_CAUSE_CODE" } ] }, + { "name" : "CDMA Error Class", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWmsCdmaErrorClass", + "prerequisites" : [ { "field" : "Result.Error Status", + "operation" : "!=", + "value" : "QMI_STATUS_SUCCESS" }, + { "field" : "Result.Error Code", + "operation" : "==", + "value" : "QMI_PROTOCOL_ERROR_WMS_CAUSE_CODE" } ] }, + { "name" : "GSM WCDMA Cause Info", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "RP Cause", + "format" : "guint16", + "public-format" : "QmiWmsGsmUmtsRpCause" }, + { "name" : "TP Cause", + "format" : "guint8", + "public-format" : "QmiWmsGsmUmtsTpCause" } ], + "prerequisites" : [ { "field" : "Result.Error Status", + "operation" : "!=", + "value" : "QMI_STATUS_SUCCESS" }, + { "field" : "Result.Error Code", + "operation" : "==", + "value" : "QMI_PROTOCOL_ERROR_WMS_CAUSE_CODE" } ] }, + { "name" : "Message Delivery Failure Type", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWmsMessageDeliveryFailureType", + "prerequisites" : [ { "field" : "Result.Error Status", + "operation" : "!=", + "value" : "QMI_STATUS_SUCCESS" }, + { "field" : "Result.Error Code", + "operation" : "==", + "value" : "QMI_PROTOCOL_ERROR_WMS_CAUSE_CODE" } ] } ] }, + + // ********************************************************************************* + { "name" : "Raw Write", + "type" : "Message", + "service" : "WMS", + "id" : "0x0021", + "version" : "1.0", + "input" : [ { "name" : "Raw Message Data", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Storage Type", + "format" : "guint8", + "public-format" : "QmiWmsStorageType" }, + { "name" : "Format", + "format" : "guint8", + "public-format" : "QmiWmsMessageFormat" }, + { "name" : "Raw Data", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "format" : "guint8" } } ] } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Memory Index", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Raw Read", + "type" : "Message", + "service" : "WMS", + "id" : "0x0022", + "version" : "1.0", + "input" : [ { "name" : "Message Memory Storage ID", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Storage Type", + "format" : "guint8", + "public-format" : "QmiWmsStorageType" }, + { "name" : "Memory Index", + "format" : "guint32" } ] }, + { "name" : "Message Mode", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWmsMessageMode" }, + { "name" : "SMS on IMS", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Raw Message Data", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Message Tag", + "format" : "guint8", + "public-format" : "QmiWmsMessageTagType" }, + { "name" : "Format", + "format" : "guint8", + "public-format" : "QmiWmsMessageFormat" }, + { "name" : "Raw Data", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "format" : "guint8" } } ], + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Modify Tag", + "type" : "Message", + "service" : "WMS", + "id" : "0x0023", + "version" : "1.0", + "input" : [ { "name" : "Message Tag", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Storage Type", + "format" : "guint8", + "public-format" : "QmiWmsStorageType" }, + { "name" : "Memory Index", + "format" : "guint32" }, + { "name" : "Message Tag", + "format" : "guint8", + "public-format" : "QmiWmsMessageTagType" } ] }, + { "name" : "Message Mode", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWmsMessageMode" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Delete", + "type" : "Message", + "service" : "WMS", + "id" : "0x0024", + "version" : "1.0", + "input" : [ { "name" : "Memory Storage", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWmsStorageType" }, + { "name" : "Memory Index", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32" }, + { "name" : "Message Tag", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWmsMessageTagType" }, + { "name" : "Message Mode", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWmsMessageMode" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Get Message Protocol", + "type" : "Message", + "service" : "WMS", + "id" : "0x0030", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Message Protocol", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWmsMessageProtocol", + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "List Messages", + "type" : "Message", + "service" : "WMS", + "id" : "0x0031", + "version" : "1.0", + "input" : [ { "name" : "Storage Type", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWmsStorageType" }, + { "name" : "Message Tag", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWmsMessageTagType" }, + { "name" : "Message Mode", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWmsMessageMode" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Message List", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint32" , + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Memory Index", + "format" : "guint32" }, + { "name" : "Message Tag", + "format" : "guint8", + "public-format" : "QmiWmsMessageTagType" } ] }, + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Set Routes", + "type" : "Message", + "service" : "WMS", + "id" : "0x0032", + "version" : "1.0", + "input" : [ { "name" : "Route List", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Message Type", + "format" : "guint8", + "public-format" : "QmiWmsMessageType" }, + { "name" : "Message Class", + "format" : "guint8", + "public-format" : "QmiWmsMessageClass" }, + { "name" : "Storage", + "format" : "guint8", + "public-format" : "QmiWmsStorageType" }, + { "name" : "Receipt Action", + "format" : "guint8", + "public-format" : "QmiWmsReceiptAction" } ] } }, + { "name" : "Transfer Status Report", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWmsTransferIndication" } ], + "output" : [ { "common-ref" : "Operation Result" } ] }, + + // ********************************************************************************* + { "name" : "Get Routes", + "type" : "Message", + "service" : "WMS", + "id" : "0x0033", + "version" : "1.0", + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Route List", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "array", + "size-prefix-format" : "guint16", + "array-element" : { "name" : "Element", + "format" : "struct", + "contents" : [ { "name" : "Message Type", + "format" : "guint8", + "public-format" : "QmiWmsMessageType" }, + { "name" : "Message Class", + "format" : "guint8", + "public-format" : "QmiWmsMessageClass" }, + { "name" : "Storage", + "format" : "guint8", + "public-format" : "QmiWmsStorageType" }, + { "name" : "Receipt Action", + "format" : "guint8", + "public-format" : "QmiWmsReceiptAction" } ] }, + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Transfer Status Report", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWmsTransferIndication", + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* + { "name" : "Send From Memory Storage", + "type" : "Message", + "service" : "WMS", + "id" : "0x0042", + "version" : "1.2", + "input" : [ { "name" : "Information", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Storage Type", + "format" : "guint8", + "public-format" : "QmiWmsStorageType" }, + { "name" : "Memory Index", + "format" : "guint32" }, + { "name" : "Message Mode", + "format" : "guint8", + "public-format" : "QmiWmsMessageMode" } ] }, + { "name" : "SMS on IMS", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "gboolean" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Message ID", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "CDMA Cause Code", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint16", + "public-format" : "QmiWmsCdmaCauseCode", + "prerequisites" : [ { "field" : "Result.Error Status", + "operation" : "!=", + "value" : "QMI_STATUS_SUCCESS" }, + { "field" : "Result.Error Code", + "operation" : "==", + "value" : "QMI_PROTOCOL_ERROR_WMS_CAUSE_CODE" } ] }, + { "name" : "CDMA Error Class", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWmsCdmaErrorClass", + "prerequisites" : [ { "field" : "Result.Error Status", + "operation" : "!=", + "value" : "QMI_STATUS_SUCCESS" }, + { "field" : "Result.Error Code", + "operation" : "==", + "value" : "QMI_PROTOCOL_ERROR_WMS_CAUSE_CODE" } ] }, + { "name" : "GSM WCDMA Cause Info", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "RP Cause", + "format" : "guint16", + "public-format" : "QmiWmsGsmUmtsRpCause" }, + { "name" : "TP Cause", + "format" : "guint8", + "public-format" : "QmiWmsGsmUmtsTpCause" } ], + "prerequisites" : [ { "field" : "Result.Error Status", + "operation" : "!=", + "value" : "QMI_STATUS_SUCCESS" }, + { "field" : "Result.Error Code", + "operation" : "==", + "value" : "QMI_PROTOCOL_ERROR_WMS_CAUSE_CODE" } ] }, + { "name" : "Message Delivery Failure Type", + "id" : "0x14", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint8", + "public-format" : "QmiWmsMessageDeliveryFailureType", + "prerequisites" : [ { "field" : "Result.Error Status", + "operation" : "!=", + "value" : "QMI_STATUS_SUCCESS" }, + { "field" : "Result.Error Code", + "operation" : "==", + "value" : "QMI_PROTOCOL_ERROR_WMS_CAUSE_CODE" } ] } ] } + +] diff --git a/release/src/router/uqmi/dev.c b/release/src/router/uqmi/dev.c new file mode 100644 index 0000000000..c25900bb9f --- /dev/null +++ b/release/src/router/uqmi/dev.c @@ -0,0 +1,388 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2014-2015 Felix Fietkau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include "uqmi.h" +#include "qmi-errors.h" +#include "qmi-errors.c" + +bool cancel_all_requests = false; + +#define __qmi_service(_n) [__##_n] = _n +static const uint8_t qmi_services[__QMI_SERVICE_LAST] = { + __qmi_services +}; +#undef __qmi_service + +static union { + char buf[512]; + struct qmi_msg msg; +} msgbuf; + +#ifdef DEBUG_PACKET +void dump_packet(const char *prefix, void *ptr, int len) +{ + unsigned char *data = ptr; + int i; + + fprintf(stderr, "%s:", prefix); + for (i = 0; i < len; i++) + fprintf(stderr, " %02x", data[i]); + fprintf(stderr, "\n"); +} +#endif + +static int +qmi_get_service_idx(QmiService svc) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(qmi_services); i++) + if (qmi_services[i] == svc) + return i; + + return -1; +} + +static void __qmi_request_complete(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + void *tlv_buf; + int tlv_len; + + if (!req->pending) + return; + + req->pending = false; + list_del(&req->list); + + if (msg) { + tlv_buf = qmi_msg_get_tlv_buf(msg, &tlv_len); + req->ret = qmi_check_message_status(tlv_buf, tlv_len); + if (req->ret) + msg = NULL; + } else { + req->ret = QMI_ERROR_CANCELLED; + } + + if (req->cb && (msg || !req->no_error_cb)) + req->cb(qmi, req, msg); + + if (req->complete) { + *req->complete = true; + uloop_cancelled = true; + } +} + +static void qmi_process_msg(struct qmi_dev *qmi, struct qmi_msg *msg) +{ + struct qmi_request *req; + uint16_t tid; + + if (msg->qmux.service == QMI_SERVICE_CTL) + tid = msg->ctl.transaction; + else + tid = le16_to_cpu(msg->svc.transaction); + + list_for_each_entry(req, &qmi->req, list) { + if (req->service != msg->qmux.service) + continue; + + if (req->tid != tid) + continue; + + __qmi_request_complete(qmi, req, msg); + return; + } +} + +static void qmi_notify_read(struct ustream *us, int bytes) +{ + struct qmi_dev *qmi = container_of(us, struct qmi_dev, sf.stream); + struct qmi_msg *msg; + char *buf; + int len, msg_len; + + while (1) { + buf = ustream_get_read_buf(us, &len); + if (!buf || !len) + return; + + if (len < offsetof(struct qmi_msg, flags)) + return; + + msg = (struct qmi_msg *) buf; + msg_len = le16_to_cpu(msg->qmux.len) + 1; + if (len < msg_len) + return; + + dump_packet("Received packet", msg, msg_len); + qmi_process_msg(qmi, msg); + ustream_consume(us, msg_len); + } +} + +int qmi_request_start(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, request_cb cb) +{ + int len = qmi_complete_request_message(msg); + uint16_t tid; + + memset(req, 0, sizeof(*req)); + req->ret = -1; + req->service = msg->qmux.service; + if (req->service == QMI_SERVICE_CTL) { + tid = qmi->ctl_tid++; + msg->ctl.transaction = tid; + } else { + int idx = qmi_get_service_idx(req->service); + + if (idx < 0) + return -1; + + tid = qmi->service_data[idx].tid++; + msg->svc.transaction = cpu_to_le16(tid); + msg->qmux.client = qmi->service_data[idx].client_id; + } + + req->tid = tid; + req->cb = cb; + req->pending = true; + list_add(&req->list, &qmi->req); + + dump_packet("Send packet", msg, len); + ustream_write(&qmi->sf.stream, (void *) msg, len, false); + return 0; +} + +void qmi_request_cancel(struct qmi_dev *qmi, struct qmi_request *req) +{ + req->cb = NULL; + __qmi_request_complete(qmi, req, NULL); +} + +int qmi_request_wait(struct qmi_dev *qmi, struct qmi_request *req) +{ + bool complete = false; + bool cancelled; + + if (!req->pending) + return req->ret; + + if (req->complete) + *req->complete = true; + + req->complete = &complete; + while (!complete) { + cancelled = uloop_cancelled; + uloop_cancelled = false; + uloop_run(); + + if (cancel_all_requests) + qmi_request_cancel(qmi, req); + + uloop_cancelled = cancelled; + } + + if (req->complete == &complete) + req->complete = NULL; + + return req->ret; +} + +struct qmi_connect_request { + struct qmi_request req; + int cid; +}; + +static void qmi_connect_service_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) +{ + struct qmi_ctl_allocate_cid_response res; + struct qmi_connect_request *creq = container_of(req, struct qmi_connect_request, req); + + if (!msg) + return; + + qmi_parse_ctl_allocate_cid_response(msg, &res); + creq->cid = res.data.allocation_info.cid; +} + +int qmi_service_connect(struct qmi_dev *qmi, QmiService svc, int client_id) +{ + struct qmi_ctl_allocate_cid_request creq = { + QMI_INIT(service, svc) + }; + struct qmi_connect_request req; + int idx = qmi_get_service_idx(svc); + struct qmi_msg *msg = &msgbuf.msg; + + if (idx < 0) + return -1; + + if (qmi->service_connected & (1 << idx)) + return 0; + + if (client_id < 0) { + qmi_set_ctl_allocate_cid_request(msg, &creq); + qmi_request_start(qmi, &req.req, msg, qmi_connect_service_cb); + qmi_request_wait(qmi, &req.req); + + if (req.req.ret) + return req.req.ret; + + client_id = req.cid; + } else { + qmi->service_keep_cid |= (1 << idx); + } + + qmi->service_data[idx].connected = true; + qmi->service_data[idx].client_id = client_id; + qmi->service_data[idx].tid = 1; + qmi->service_connected |= (1 << idx); + + return 0; +} + +static void __qmi_service_disconnect(struct qmi_dev *qmi, int idx) +{ + int client_id = qmi->service_data[idx].client_id; + struct qmi_ctl_release_cid_request creq = { + QMI_INIT_SEQUENCE(release_info, + .service = qmi_services[idx], + .cid = client_id, + ) + }; + struct qmi_request req; + struct qmi_msg *msg = &msgbuf.msg; + + qmi->service_connected &= ~(1 << idx); + qmi->service_data[idx].client_id = -1; + qmi->service_data[idx].tid = 0; + + qmi_set_ctl_release_cid_request(msg, &creq); + qmi_request_start(qmi, &req, msg, NULL); + qmi_request_wait(qmi, &req); +} + +int qmi_service_release_client_id(struct qmi_dev *qmi, QmiService svc) +{ + int idx = qmi_get_service_idx(svc); + qmi->service_release_cid |= 1 << idx; + return 0; +} + +static void qmi_close_all_services(struct qmi_dev *qmi) +{ + uint32_t connected = qmi->service_connected; + int idx; + + qmi->service_keep_cid &= ~qmi->service_release_cid; + for (idx = 0; connected; idx++, connected >>= 1) { + if (!(connected & 1)) + continue; + + if (qmi->service_keep_cid & (1 << idx)) + continue; + + __qmi_service_disconnect(qmi, idx); + } +} + +int qmi_service_get_client_id(struct qmi_dev *qmi, QmiService svc) +{ + int idx = qmi_get_service_idx(svc); + + if (idx < 0) + return -1; + + qmi->service_keep_cid |= (1 << idx); + return qmi->service_data[idx].client_id; +} + +int qmi_device_open(struct qmi_dev *qmi, const char *path) +{ + struct ustream *us = &qmi->sf.stream; + int fd; + + uloop_init(); + + fd = open(path, O_RDWR | O_EXCL | O_NONBLOCK | O_NOCTTY); + if (fd < 0) + return -1; + + us->notify_read = qmi_notify_read; + ustream_fd_init(&qmi->sf, fd); + INIT_LIST_HEAD(&qmi->req); + qmi->ctl_tid = 1; + + return 0; +} + +void qmi_device_close(struct qmi_dev *qmi) +{ + struct qmi_request *req; + + qmi_close_all_services(qmi); + ustream_free(&qmi->sf.stream); + close(qmi->sf.fd.fd); + + while (!list_empty(&qmi->req)) { + req = list_first_entry(&qmi->req, struct qmi_request, list); + qmi_request_cancel(qmi, req); + } +} + +QmiService qmi_service_get_by_name(const char *str) +{ + static const struct { + const char *name; + QmiService svc; + } services[] = { + { "dms", QMI_SERVICE_DMS }, + { "nas", QMI_SERVICE_NAS }, + { "pds", QMI_SERVICE_PDS }, + { "wds", QMI_SERVICE_WDS }, + { "wms", QMI_SERVICE_WMS }, + { "wda", QMI_SERVICE_WDA }, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(services); i++) { + if (!strcasecmp(str, services[i].name)) + return services[i].svc; + } + + return -1; +} + +const char *qmi_get_error_str(int code) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(qmi_errors); i++) { + if (qmi_errors[i].code == code) + return qmi_errors[i].text; + } + + return "Unknown error"; +} diff --git a/release/src/router/uqmi/libubox/CMakeLists.txt b/release/src/router/uqmi/libubox/CMakeLists.txt new file mode 100644 index 0000000000..f24fee9b6d --- /dev/null +++ b/release/src/router/uqmi/libubox/CMakeLists.txt @@ -0,0 +1,69 @@ +cmake_minimum_required(VERSION 2.6) +INCLUDE(CheckLibraryExists) +INCLUDE(CheckFunctionExists) + +PROJECT(ubox C) +ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu99 -g3 -Wmissing-declarations) + +OPTION(BUILD_LUA "build Lua plugin" ON) + +IF(APPLE) + INCLUDE_DIRECTORIES(/opt/local/include) + LINK_DIRECTORIES(/opt/local/lib) +ENDIF() + +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(JSONC json-c json) +IF(JSONC_FOUND) + ADD_DEFINITIONS(-DJSONC) + INCLUDE_DIRECTORIES(${JSONC_INCLUDE_DIRS}) +ENDIF() + +SET(SOURCES avl.c avl-cmp.c blob.c blobmsg.c uloop.c usock.c ustream.c ustream-fd.c vlist.c utils.c safe_list.c runqueue.c md5.c kvlist.c) + +ADD_LIBRARY(ubox SHARED ${SOURCES}) +ADD_LIBRARY(ubox-static STATIC ${SOURCES}) +SET_TARGET_PROPERTIES(ubox-static PROPERTIES OUTPUT_NAME ubox) + +SET(LIBS) +CHECK_FUNCTION_EXISTS(clock_gettime HAVE_GETTIME) +IF(NOT HAVE_GETTIME) + CHECK_LIBRARY_EXISTS(rt clock_gettime "" NEED_GETTIME) + IF(NEED_GETTIME) + TARGET_LINK_LIBRARIES(ubox rt) + ENDIF() +ENDIF() + +FILE(GLOB headers *.h) +INSTALL(FILES ${headers} + DESTINATION include/libubox +) +INSTALL(TARGETS ubox ubox-static + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib +) + +ADD_SUBDIRECTORY(lua) + +find_library(json NAMES json-c json) +IF(EXISTS ${json}) + ADD_LIBRARY(blobmsg_json SHARED blobmsg_json.c) + TARGET_LINK_LIBRARIES(blobmsg_json ubox ${json}) + + ADD_EXECUTABLE(jshn jshn.c) + TARGET_LINK_LIBRARIES(jshn blobmsg_json ${json}) + + ADD_LIBRARY(json_script SHARED json_script.c) + TARGET_LINK_LIBRARIES(json_script ubox) + + INSTALL(TARGETS blobmsg_json jshn json_script + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin + ) + + FILE(GLOB scripts sh/*.sh) + INSTALL(FILES ${scripts} + DESTINATION share/libubox + ) + +ENDIF() diff --git a/release/src/router/uqmi/libubox/avl-cmp.c b/release/src/router/uqmi/libubox/avl-cmp.c new file mode 100644 index 0000000000..2d0acecd9d --- /dev/null +++ b/release/src/router/uqmi/libubox/avl-cmp.c @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include "avl-cmp.h" + +int +avl_strcmp(const void *k1, const void *k2, void *ptr) +{ + return strcmp(k1, k2); +} + diff --git a/release/src/router/uqmi/libubox/avl-cmp.h b/release/src/router/uqmi/libubox/avl-cmp.h new file mode 100644 index 0000000000..5adb495c02 --- /dev/null +++ b/release/src/router/uqmi/libubox/avl-cmp.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __AVL_CMP_H +#define __AVL_CMP_H + +int avl_strcmp(const void *k1, const void *k2, void *ptr); + +#endif diff --git a/release/src/router/uqmi/libubox/avl.c b/release/src/router/uqmi/libubox/avl.c new file mode 100644 index 0000000000..8d0bf65aaa --- /dev/null +++ b/release/src/router/uqmi/libubox/avl.c @@ -0,0 +1,735 @@ +/* + * PacketBB handler library (see RFC 5444) + * Copyright (c) 2010 Henning Rogge + * Original OLSRd implementation by Hannes Gredler + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of olsr.org, olsrd nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Visit http://www.olsr.org/git for more information. + * + * If you find this software useful feel free to make a donation + * to the project. For more information see the website or contact + * the copyright holders. + */ + +#include +#include +#include +#include +#include + +#include "avl.h" +#include "list.h" + +/** + * internal type save inline function to calculate the maximum of + * to integers without macro implementation. + * + * @param x first parameter of maximum function + * @param y second parameter of maximum function + * @return largest integer of both parameters + */ +static inline int avl_max(int x, int y) { + return x > y ? x : y; +} + +/** + * internal type save inline function to calculate the minimum of + * to integers without macro implementation. + * + * @param x first parameter of minimum function + * @param y second parameter of minimum function + * @return smallest integer of both parameters + */ +static inline int avl_min(int x, int y) { + return x < y ? x : y; +} + +static struct avl_node * +avl_find_rec(struct avl_node *node, const void *key, avl_tree_comp comp, void *ptr, int *cmp_result); +static void avl_insert_before(struct avl_tree *tree, struct avl_node *pos_node, struct avl_node *node); +static void avl_insert_after(struct avl_tree *tree, struct avl_node *pos_node, struct avl_node *node); +static void post_insert(struct avl_tree *tree, struct avl_node *node); +static void avl_delete_worker(struct avl_tree *tree, struct avl_node *node); +static void avl_remove(struct avl_tree *tree, struct avl_node *node); + +/** + * Initialize a new avl_tree struct + * @param tree pointer to avl-tree + * @param comp pointer to comparator for the tree + * @param allow_dups true if the tree allows multiple + * elements with the same + * @param ptr custom parameter for comparator + */ +void +avl_init(struct avl_tree *tree, avl_tree_comp comp, bool allow_dups, void *ptr) +{ + INIT_LIST_HEAD(&tree->list_head); + tree->root = NULL; + tree->count = 0; + tree->comp = comp; + tree->allow_dups = allow_dups; + tree->cmp_ptr = ptr; +} + +static inline struct avl_node *avl_next(struct avl_node *node) +{ + return list_entry(node->list.next, struct avl_node, list); +} + +/** + * Finds a node in an avl-tree with a certain key + * @param tree pointer to avl-tree + * @param key pointer to key + * @return pointer to avl-node with key, NULL if no node with + * this key exists. + */ +struct avl_node * +avl_find(const struct avl_tree *tree, const void *key) +{ + struct avl_node *node; + int diff; + + if (tree->root == NULL) + return NULL; + + node = avl_find_rec(tree->root, key, tree->comp, tree->cmp_ptr, &diff); + + return diff == 0 ? node : NULL; +} + +/** + * Finds the last node in an avl-tree with a key less or equal + * than the specified key + * @param tree pointer to avl-tree + * @param key pointer to specified key + * @return pointer to avl-node, NULL if no node with + * key less or equal specified key exists. + */ +struct avl_node * +avl_find_lessequal(const struct avl_tree *tree, const void *key) { + struct avl_node *node, *next; + int diff; + + if (tree->root == NULL) + return NULL; + + node = avl_find_rec(tree->root, key, tree->comp, tree->cmp_ptr, &diff); + + /* go left as long as keylist, &tree->list_head)) { + return NULL; + } + + node = (struct avl_node *)node->list.prev; + diff = (*tree->comp) (key, node->key, tree->cmp_ptr); + } + + /* go right as long as key>=next_node.key */ + next = node; + while (diff >= 0) { + node = next; + if (list_is_last(&node->list, &tree->list_head)) { + break; + } + + next = (struct avl_node *)node->list.next; + diff = (*tree->comp) (key, next->key, tree->cmp_ptr); + } + return node; +} + +/** + * Finds the first node in an avl-tree with a key greater or equal + * than the specified key + * @param tree pointer to avl-tree + * @param key pointer to specified key + * @return pointer to avl-node, NULL if no node with + * key greater or equal specified key exists. + */ +struct avl_node * +avl_find_greaterequal(const struct avl_tree *tree, const void *key) { + struct avl_node *node, *next; + int diff; + + if (tree->root == NULL) + return NULL; + + node = avl_find_rec(tree->root, key, tree->comp, tree->cmp_ptr, &diff); + + /* go right as long as key>node.key */ + while (diff > 0) { + if (list_is_last(&node->list, &tree->list_head)) { + return NULL; + } + + node = (struct avl_node *)node->list.next; + diff = (*tree->comp) (key, node->key, tree->cmp_ptr); + } + + /* go left as long as key<=next_node.key */ + next = node; + while (diff <= 0) { + node = next; + if (list_is_first(&node->list, &tree->list_head)) { + break; + } + + next = (struct avl_node *)node->list.prev; + diff = (*tree->comp) (key, next->key, tree->cmp_ptr); + } + return node; +} + +/** + * Inserts an avl_node into a tree + * @param tree pointer to tree + * @param new pointer to node + * @return 0 if node was inserted successfully, -1 if it was not inserted + * because of a key collision + */ +int +avl_insert(struct avl_tree *tree, struct avl_node *new) +{ + struct avl_node *node, *next, *last; + int diff; + + new->parent = NULL; + + new->left = NULL; + new->right = NULL; + + new->balance = 0; + new->leader = true; + + if (tree->root == NULL) { + list_add(&new->list, &tree->list_head); + tree->root = new; + tree->count = 1; + return 0; + } + + node = avl_find_rec(tree->root, new->key, tree->comp, tree->cmp_ptr, &diff); + + last = node; + + while (!list_is_last(&last->list, &tree->list_head)) { + next = avl_next(last); + if (next->leader) { + break; + } + last = next; + } + + diff = (*tree->comp) (new->key, node->key, tree->cmp_ptr); + + if (diff == 0) { + if (!tree->allow_dups) + return -1; + + new->leader = 0; + + avl_insert_after(tree, last, new); + return 0; + } + + if (node->balance == 1) { + avl_insert_before(tree, node, new); + + node->balance = 0; + new->parent = node; + node->left = new; + return 0; + } + + if (node->balance == -1) { + avl_insert_after(tree, last, new); + + node->balance = 0; + new->parent = node; + node->right = new; + return 0; + } + + if (diff < 0) { + avl_insert_before(tree, node, new); + + node->balance = -1; + new->parent = node; + node->left = new; + post_insert(tree, node); + return 0; + } + + avl_insert_after(tree, last, new); + + node->balance = 1; + new->parent = node; + node->right = new; + post_insert(tree, node); + return 0; +} + +/** + * Remove a node from an avl tree + * @param tree pointer to tree + * @param node pointer to node + */ +void +avl_delete(struct avl_tree *tree, struct avl_node *node) +{ + struct avl_node *next; + struct avl_node *parent; + struct avl_node *left; + struct avl_node *right; + if (node->leader) { + if (tree->allow_dups + && !list_is_last(&node->list, &tree->list_head) + && !(next = avl_next(node))->leader) { + next->leader = true; + next->balance = node->balance; + + parent = node->parent; + left = node->left; + right = node->right; + + next->parent = parent; + next->left = left; + next->right = right; + + if (parent == NULL) + tree->root = next; + + else { + if (node == parent->left) + parent->left = next; + + else + parent->right = next; + } + + if (left != NULL) + left->parent = next; + + if (right != NULL) + right->parent = next; + } + + else + avl_delete_worker(tree, node); + } + + avl_remove(tree, node); +} + +static struct avl_node * +avl_find_rec(struct avl_node *node, const void *key, avl_tree_comp comp, void *cmp_ptr, int *cmp_result) +{ + int diff; + + diff = (*comp) (key, node->key, cmp_ptr); + *cmp_result = diff; + + if (diff < 0) { + if (node->left != NULL) + return avl_find_rec(node->left, key, comp, cmp_ptr, cmp_result); + + return node; + } + + if (diff > 0) { + if (node->right != NULL) + return avl_find_rec(node->right, key, comp, cmp_ptr, cmp_result); + + return node; + } + + return node; +} + +static void +avl_rotate_right(struct avl_tree *tree, struct avl_node *node) +{ + struct avl_node *left, *parent; + + left = node->left; + parent = node->parent; + + left->parent = parent; + node->parent = left; + + if (parent == NULL) + tree->root = left; + + else { + if (parent->left == node) + parent->left = left; + + else + parent->right = left; + } + + node->left = left->right; + left->right = node; + + if (node->left != NULL) + node->left->parent = node; + + node->balance += 1 - avl_min(left->balance, 0); + left->balance += 1 + avl_max(node->balance, 0); +} + +static void +avl_rotate_left(struct avl_tree *tree, struct avl_node *node) +{ + struct avl_node *right, *parent; + + right = node->right; + parent = node->parent; + + right->parent = parent; + node->parent = right; + + if (parent == NULL) + tree->root = right; + + else { + if (parent->left == node) + parent->left = right; + + else + parent->right = right; + } + + node->right = right->left; + right->left = node; + + if (node->right != NULL) + node->right->parent = node; + + node->balance -= 1 + avl_max(right->balance, 0); + right->balance -= 1 - avl_min(node->balance, 0); +} + +static void +post_insert(struct avl_tree *tree, struct avl_node *node) +{ + struct avl_node *parent = node->parent; + + if (parent == NULL) + return; + + if (node == parent->left) { + parent->balance--; + + if (parent->balance == 0) + return; + + if (parent->balance == -1) { + post_insert(tree, parent); + return; + } + + if (node->balance == -1) { + avl_rotate_right(tree, parent); + return; + } + + avl_rotate_left(tree, node); + avl_rotate_right(tree, node->parent->parent); + return; + } + + parent->balance++; + + if (parent->balance == 0) + return; + + if (parent->balance == 1) { + post_insert(tree, parent); + return; + } + + if (node->balance == 1) { + avl_rotate_left(tree, parent); + return; + } + + avl_rotate_right(tree, node); + avl_rotate_left(tree, node->parent->parent); +} + +static void +avl_insert_before(struct avl_tree *tree, struct avl_node *pos_node, struct avl_node *node) +{ + list_add_tail(&node->list, &pos_node->list); + tree->count++; +} + +static void +avl_insert_after(struct avl_tree *tree, struct avl_node *pos_node, struct avl_node *node) +{ + list_add(&node->list, &pos_node->list); + tree->count++; +} + +static void +avl_remove(struct avl_tree *tree, struct avl_node *node) +{ + list_del(&node->list); + tree->count--; +} + +static void +avl_post_delete(struct avl_tree *tree, struct avl_node *node) +{ + struct avl_node *parent; + + if ((parent = node->parent) == NULL) + return; + + if (node == parent->left) { + parent->balance++; + + if (parent->balance == 0) { + avl_post_delete(tree, parent); + return; + } + + if (parent->balance == 1) + return; + + if (parent->right->balance == 0) { + avl_rotate_left(tree, parent); + return; + } + + if (parent->right->balance == 1) { + avl_rotate_left(tree, parent); + avl_post_delete(tree, parent->parent); + return; + } + + avl_rotate_right(tree, parent->right); + avl_rotate_left(tree, parent); + avl_post_delete(tree, parent->parent); + return; + } + + parent->balance--; + + if (parent->balance == 0) { + avl_post_delete(tree, parent); + return; + } + + if (parent->balance == -1) + return; + + if (parent->left->balance == 0) { + avl_rotate_right(tree, parent); + return; + } + + if (parent->left->balance == -1) { + avl_rotate_right(tree, parent); + avl_post_delete(tree, parent->parent); + return; + } + + avl_rotate_left(tree, parent->left); + avl_rotate_right(tree, parent); + avl_post_delete(tree, parent->parent); +} + +static struct avl_node * +avl_local_min(struct avl_node *node) +{ + while (node->left != NULL) + node = node->left; + + return node; +} + +#if 0 +static struct avl_node * +avl_local_max(struct avl_node *node) +{ + while (node->right != NULL) + node = node->right; + + return node; +} +#endif + +static void +avl_delete_worker(struct avl_tree *tree, struct avl_node *node) +{ + struct avl_node *parent, *min; + + parent = node->parent; + + if (node->left == NULL && node->right == NULL) { + if (parent == NULL) { + tree->root = NULL; + return; + } + + if (parent->left == node) { + parent->left = NULL; + parent->balance++; + + if (parent->balance == 1) + return; + + if (parent->balance == 0) { + avl_post_delete(tree, parent); + return; + } + + if (parent->right->balance == 0) { + avl_rotate_left(tree, parent); + return; + } + + if (parent->right->balance == 1) { + avl_rotate_left(tree, parent); + avl_post_delete(tree, parent->parent); + return; + } + + avl_rotate_right(tree, parent->right); + avl_rotate_left(tree, parent); + avl_post_delete(tree, parent->parent); + return; + } + + if (parent->right == node) { + parent->right = NULL; + parent->balance--; + + if (parent->balance == -1) + return; + + if (parent->balance == 0) { + avl_post_delete(tree, parent); + return; + } + + if (parent->left->balance == 0) { + avl_rotate_right(tree, parent); + return; + } + + if (parent->left->balance == -1) { + avl_rotate_right(tree, parent); + avl_post_delete(tree, parent->parent); + return; + } + + avl_rotate_left(tree, parent->left); + avl_rotate_right(tree, parent); + avl_post_delete(tree, parent->parent); + return; + } + } + + if (node->left == NULL) { + if (parent == NULL) { + tree->root = node->right; + node->right->parent = NULL; + return; + } + + node->right->parent = parent; + + if (parent->left == node) + parent->left = node->right; + + else + parent->right = node->right; + + avl_post_delete(tree, node->right); + return; + } + + if (node->right == NULL) { + if (parent == NULL) { + tree->root = node->left; + node->left->parent = NULL; + return; + } + + node->left->parent = parent; + + if (parent->left == node) + parent->left = node->left; + + else + parent->right = node->left; + + avl_post_delete(tree, node->left); + return; + } + + min = avl_local_min(node->right); + avl_delete_worker(tree, min); + parent = node->parent; + + min->balance = node->balance; + min->parent = parent; + min->left = node->left; + min->right = node->right; + + if (min->left != NULL) + min->left->parent = min; + + if (min->right != NULL) + min->right->parent = min; + + if (parent == NULL) { + tree->root = min; + return; + } + + if (parent->left == node) { + parent->left = min; + return; + } + + parent->right = min; +} + +/* + * Local Variables: + * c-basic-offset: 2 + * indent-tabs-mode: nil + * End: + */ diff --git a/release/src/router/uqmi/libubox/avl.h b/release/src/router/uqmi/libubox/avl.h new file mode 100644 index 0000000000..c46859723f --- /dev/null +++ b/release/src/router/uqmi/libubox/avl.h @@ -0,0 +1,560 @@ +/* + * PacketBB handler library (see RFC 5444) + * Copyright (c) 2010 Henning Rogge + * Original OLSRd implementation by Hannes Gredler + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of olsr.org, olsrd nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Visit http://www.olsr.org/git for more information. + * + * If you find this software useful feel free to make a donation + * to the project. For more information see the website or contact + * the copyright holders. + */ + +#ifndef _AVL_H +#define _AVL_H + +#include +#include + +#include "list.h" + +/* Support for OLSR.org linker symbol export */ +#define EXPORT(sym) sym + +/** + * This element is a member of a avl-tree. It must be contained in all + * larger structs that should be put into a tree. + */ +struct avl_node { + /** + * Linked list node for supporting easy iteration and multiple + * elments with the same key. + * + * this must be the first element of an avl_node to + * make casting for lists easier + */ + struct list_head list; + + /** + * Pointer to parent node in tree, NULL if root node + */ + struct avl_node *parent; + + /** + * Pointer to left child + */ + struct avl_node *left; + + /** + * Pointer to right child + */ + struct avl_node *right; + + /** + * pointer to key of node + */ + const void *key; + + /** + * balance state of AVL tree (0,-1,+1) + */ + signed char balance; + + /** + * true if first of a series of nodes with same key + */ + bool leader; +}; + +/** + * Prototype for avl comparators + * @param k1 first key + * @param k2 second key + * @param ptr custom data for tree comparator + * @return +1 if k1>k2, -1 if k1list_head.next == &node->list; +} + +/** + * @param tree pointer to avl-tree + * @param node pointer to node of the tree + * @return true if node is the last one of the tree, false otherwise + */ +static inline bool +avl_is_last(struct avl_tree *tree, struct avl_node *node) { + return tree->list_head.prev == &node->list; +} + +/** + * @param tree pointer to avl-tree + * @return true if the tree is empty, false otherwise + */ +static inline bool +avl_is_empty(struct avl_tree *tree) { + return tree->count == 0; +} + +/** + * Internal function to support returning the element from a avl tree query + * @param tree pointer to avl tree + * @param key pointer to key + * @param offset offset of node inside the embedded struct + * @param mode mode of lookup operation (less equal, equal or greater equal) + * @param pointer to elemen, NULL if no fitting one was found + */ +static inline void * +__avl_find_element(const struct avl_tree *tree, const void *key, size_t offset, enum avl_find_mode mode) { + void *node = NULL; + + switch (mode) { + case AVL_FIND_EQUAL: + node = avl_find(tree, key); + break; + case AVL_FIND_LESSEQUAL: + node = avl_find_lessequal(tree, key); + break; + case AVL_FIND_GREATEREQUAL: + node = avl_find_greaterequal(tree, key); + break; + } + return node == NULL ? NULL : (((char *)node) - offset); +} + +/** + * @param tree pointer to avl-tree + * @param key pointer to key + * @param element pointer to a node element + * (don't need to be initialized) + * @param node_element name of the avl_node element inside the + * larger struct + * @return pointer to tree element with the specified key, + * NULL if no element was found + */ +#define avl_find_element(tree, key, element, node_element) \ + ((typeof(*(element)) *)__avl_find_element(tree, key, offsetof(typeof(*(element)), node_element), AVL_FIND_EQUAL)) + +/** + * @param tree pointer to avl-tree + * @param key pointer to specified key + * @param element pointer to a node element + * (don't need to be initialized) + * @param node_element name of the avl_node element inside the + * larger struct + * return pointer to last tree element with less or equal key than specified key, + * NULL if no element was found + */ +#define avl_find_le_element(tree, key, element, node_element) \ + ((typeof(*(element)) *)__avl_find_element(tree, key, offsetof(typeof(*(element)), node_element), AVL_FIND_LESSEQUAL)) + +/** + * @param tree pointer to avl-tree + * @param key pointer to specified key + * @param element pointer to a node element + * (don't need to be initialized) + * @param node_element name of the avl_node element inside the + * larger struct + * return pointer to first tree element with greater or equal key than specified key, + * NULL if no element was found + */ +#define avl_find_ge_element(tree, key, element, node_element) \ + ((typeof(*(element)) *)__avl_find_element(tree, key, offsetof(typeof(*(element)), node_element), AVL_FIND_GREATEREQUAL)) + +/** + * This function must not be called for an empty tree + * + * @param tree pointer to avl-tree + * @param element pointer to a node element + * (don't need to be initialized) + * @param node_member name of the avl_node element inside the + * larger struct + * @return pointer to the first element of the avl_tree + * (automatically converted to type 'element') + */ +#define avl_first_element(tree, element, node_member) \ + container_of((tree)->list_head.next, typeof(*(element)), node_member.list) + +/** + * @param tree pointer to tree + * @param element pointer to a node struct that contains the avl_node + * (don't need to be initialized) + * @param node_member name of the avl_node element inside the + * larger struct + * @return pointer to the last element of the avl_tree + * (automatically converted to type 'element') + */ +#define avl_last_element(tree, element, node_member) \ + container_of((tree)->list_head.prev, typeof(*(element)), node_member.list) + +/** + * This function must not be called for the last element of + * an avl tree + * + * @param element pointer to a node of the tree + * @param node_member name of the avl_node element inside the + * larger struct + * @return pointer to the node after 'element' + * (automatically converted to type 'element') + */ +#define avl_next_element(element, node_member) \ + container_of((&(element)->node_member.list)->next, typeof(*(element)), node_member.list) + +/** + * This function must not be called for the first element of + * an avl tree + * + * @param element pointer to a node of the tree + * @param node_member name of the avl_node element inside the + * larger struct + * @return pointer to the node before 'element' + * (automatically converted to type 'element') + */ +#define avl_prev_element(element, node_member) \ + container_of((&(element)->node_member.list)->prev, typeof(*(element)), node_member.list) + +/** + * Loop over a block of elements of a tree, used similar to a for() command. + * This loop should not be used if elements are removed from the tree during + * the loop. + * + * @param first pointer to first element of loop + * @param last pointer to last element of loop + * @param element pointer to a node of the tree, this element will + * contain the current node of the list during the loop + * @param node_member name of the avl_node element inside the + * larger struct + */ +#define avl_for_element_range(first, last, element, node_member) \ + for (element = (first); \ + element->node_member.list.prev != &(last)->node_member.list; \ + element = avl_next_element(element, node_member)) + +/** + * Loop over a block of elements of a tree backwards, used similar to a for() command. + * This loop should not be used if elements are removed from the tree during + * the loop. + * + * @param first pointer to first element of loop + * @param last pointer to last element of loop + * @param element pointer to a node of the tree, this element will + * contain the current node of the list during the loop + * @param node_member name of the avl_node element inside the + * larger struct + */ +#define avl_for_element_range_reverse(first, last, element, node_member) \ + for (element = (last); \ + element->node_member.list.next != &(first)->node_member.list; \ + element = avl_prev_element(element, node_member)) + +/** + * Loop over all elements of an avl_tree, used similar to a for() command. + * This loop should not be used if elements are removed from the tree during + * the loop. + * + * @param tree pointer to avl-tree + * @param element pointer to a node of the tree, this element will + * contain the current node of the tree during the loop + * @param node_member name of the avl_node element inside the + * larger struct + */ +#define avl_for_each_element(tree, element, node_member) \ + avl_for_element_range(avl_first_element(tree, element, node_member), \ + avl_last_element(tree, element, node_member), \ + element, node_member) + +/** + * Loop over all elements of an avl_tree backwards, used similar to a for() command. + * This loop should not be used if elements are removed from the tree during + * the loop. + * + * @param tree pointer to avl-tree + * @param element pointer to a node of the tree, this element will + * contain the current node of the tree during the loop + * @param node_member name of the avl_node element inside the + * larger struct + */ +#define avl_for_each_element_reverse(tree, element, node_member) \ + avl_for_element_range_reverse(avl_first_element(tree, element, node_member), \ + avl_last_element(tree, element, node_member), \ + element, node_member) + +/** + * Loop over a block of elements of a tree, used similar to a for() command. + * This loop should not be used if elements are removed from the tree during + * the loop. + * The loop runs from the element 'first' to the end of the tree. + * + * @param tree pointer to avl-tree + * @param first pointer to first element of loop + * @param element pointer to a node of the tree, this element will + * contain the current node of the list during the loop + * @param node_member name of the avl_node element inside the + * larger struct + */ +#define avl_for_element_to_last(tree, first, element, node_member) \ + avl_for_element_range(first, avl_last_element(tree, element, node_member), element, node_member) + + +/** + * Loop over a block of elements of a tree backwards, used similar to a for() command. + * This loop should not be used if elements are removed from the tree during + * the loop. + * The loop runs from the element 'first' to the end of the tree. + * + * @param tree pointer to avl-tree + * @param first pointer to first element of loop + * @param element pointer to a node of the tree, this element will + * contain the current node of the list during the loop + * @param node_member name of the avl_node element inside the + * larger struct + */ +#define avl_for_element_to_last_reverse(tree, first, element, node_member) \ + avl_for_element_range_reverse(first, avl_last_element(tree, element, node_member), element, node_member) + +/** + * Loop over a block of elements of a tree, used similar to a for() command. + * This loop should not be used if elements are removed from the tree during + * the loop. + * The loop runs from the start of the tree to the element 'last'. + * + * @param tree pointer to avl-tree + * @param last pointer to last element of loop + * @param element pointer to a node of the tree, this element will + * contain the current node of the list during the loop + * @param node_member name of the avl_node element inside the + * larger struct + */ +#define avl_for_first_to_element(tree, last, element, node_member) \ + avl_for_element_range(avl_first_element(tree, element, node_member), last, element, node_member) + + +/** + * Loop over a block of elements of a tree backwards, used similar to a for() command. + * This loop should not be used if elements are removed from the tree during + * the loop. + * The loop runs from the start of the tree to the element 'last'. + * + * @param tree pointer to avl-tree + * @param last pointer to last element of loop + * @param element pointer to a node of the tree, this element will + * contain the current node of the list during the loop + * @param node_member name of the avl_node element inside the + * larger struct + */ +#define avl_for_first_to_element_reverse(tree, last, element, node_member) \ + avl_for_element_range_reverse(avl_first_element(tree, element, node_member), last, element, node_member) + +/** + * Loop over a block of nodes of a tree, used similar to a for() command. + * This loop can be used if the current element might be removed from + * the tree during the loop. Other elements should not be removed during + * the loop. + * + * @param first_element first element of loop + * @param last_element last element of loop + * @param element iterator pointer to tree element struct + * @param node_member name of avl_node within tree element struct + * @param ptr pointer to tree element struct which is used to store + * the next node during the loop + */ +#define avl_for_element_range_safe(first_element, last_element, element, node_member, ptr) \ + for (element = (first_element), ptr = avl_next_element(first_element, node_member); \ + element->node_member.list.prev != &(last_element)->node_member.list; \ + element = ptr, ptr = avl_next_element(ptr, node_member)) + +/** + * Loop over a block of elements of a tree backwards, used similar to a for() command. + * This loop can be used if the current element might be removed from + * the tree during the loop. Other elements should not be removed during + * the loop. + * + * @param first_element first element of range (will be last returned by the loop) + * @param last_element last element of range (will be first returned by the loop) + * @param element iterator pointer to node element struct + * @param node_member name of avl_node within node element struct + * @param ptr pointer to node element struct which is used to store + * the previous node during the loop + */ +#define avl_for_element_range_reverse_safe(first_element, last_element, element, node_member, ptr) \ + for (element = (last_element), ptr = avl_prev_element(last_element, node_member); \ + element->node_member.list.next != &(first_element)->node_member.list; \ + element = ptr, ptr = avl_prev_element(ptr, node_member)) + +/** + * Loop over all elements of an avl_tree, used similar to a for() command. + * This loop can be used if the current element might be removed from + * the tree during the loop. Other elements should not be removed during + * the loop. + * + * @param tree pointer to avl-tree + * @param element pointer to a node of the tree, this element will + * contain the current node of the tree during the loop + * @param node_member name of the avl_node element inside the + * larger struct + * @param ptr pointer to a tree element which is used to store + * the next node during the loop + */ +#define avl_for_each_element_safe(tree, element, node_member, ptr) \ + avl_for_element_range_safe(avl_first_element(tree, element, node_member), \ + avl_last_element(tree, element, node_member), \ + element, node_member, ptr) + +/** + * Loop over all elements of an avl_tree backwards, used similar to a for() command. + * This loop can be used if the current element might be removed from + * the tree during the loop. Other elements should not be removed during + * the loop. + * + * @param tree pointer to avl-tree + * @param element pointer to a node of the tree, this element will + * contain the current node of the tree during the loop + * @param node_member name of the avl_node element inside the + * larger struct + * @param ptr pointer to a tree element which is used to store + * the next node during the loop + */ +#define avl_for_each_element_reverse_safe(tree, element, node_member, ptr) \ + avl_for_element_range_reverse_safe(avl_first_element(tree, element, node_member), \ + avl_last_element(tree, element, node_member), \ + element, node_member, ptr) + +/** + * A special loop that removes all elements of the tree and cleans up the tree + * root. The loop body is responsible to free the node elements of the tree. + * + * This loop is much faster than a normal one for clearing the tree because it + * does not rebalance the tree after each removal. Do NOT use a break command + * inside. + * You can free the memory of the elements within the loop. + * Do NOT call avl_delete() on the elements within the loop, + * + * @param tree pointer to avl-tree + * @param element pointer to a node of the tree, this element will + * contain the current node of the tree during the loop + * @param node_member name of the avl_node element inside the + * larger struct + * @param ptr pointer to a tree element which is used to store + * the next node during the loop + */ +#define avl_remove_all_elements(tree, element, node_member, ptr) \ + for (element = avl_first_element(tree, element, node_member), \ + ptr = avl_next_element(element, node_member), \ + INIT_LIST_HEAD(&(tree)->list_head), \ + (tree)->root = NULL; \ + (tree)->count > 0; \ + element = ptr, ptr = avl_next_element(ptr, node_member), (tree)->count--) + +#endif /* _AVL_H */ + +/* + * Local Variables: + * c-basic-offset: 2 + * indent-tabs-mode: nil + * End: + */ diff --git a/release/src/router/uqmi/libubox/blob.c b/release/src/router/uqmi/libubox/blob.c new file mode 100644 index 0000000000..ec8617bef8 --- /dev/null +++ b/release/src/router/uqmi/libubox/blob.c @@ -0,0 +1,287 @@ +/* + * blob - library for generating/parsing tagged binary data + * + * Copyright (C) 2010 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "blob.h" + +static bool +blob_buffer_grow(struct blob_buf *buf, int minlen) +{ + struct blob_buf *new; + int delta = ((minlen / 256) + 1) * 256; + new = realloc(buf->buf, buf->buflen + delta); + if (new) { + buf->buf = new; + memset(buf->buf + buf->buflen, 0, delta); + buf->buflen += delta; + } + return !!new; +} + +static void +blob_init(struct blob_attr *attr, int id, unsigned int len) +{ + len &= BLOB_ATTR_LEN_MASK; + len |= (id << BLOB_ATTR_ID_SHIFT) & BLOB_ATTR_ID_MASK; + attr->id_len = cpu_to_be32(len); +} + +static inline struct blob_attr * +offset_to_attr(struct blob_buf *buf, int offset) +{ + void *ptr = (char *)buf->buf + offset - BLOB_COOKIE; + return ptr; +} + +static inline int +attr_to_offset(struct blob_buf *buf, struct blob_attr *attr) +{ + return (char *)attr - (char *) buf->buf + BLOB_COOKIE; +} + +bool +blob_buf_grow(struct blob_buf *buf, int required) +{ + int offset_head = attr_to_offset(buf, buf->head); + + if (!buf->grow || !buf->grow(buf, required)) + return false; + + buf->head = offset_to_attr(buf, offset_head); + return true; +} + +static struct blob_attr * +blob_add(struct blob_buf *buf, struct blob_attr *pos, int id, int payload) +{ + int offset = attr_to_offset(buf, pos); + int required = (offset - BLOB_COOKIE + sizeof(struct blob_attr) + payload) - buf->buflen; + struct blob_attr *attr; + + if (required > 0) { + if (!blob_buf_grow(buf, required)) + return NULL; + attr = offset_to_attr(buf, offset); + } else { + attr = pos; + } + + blob_init(attr, id, payload + sizeof(struct blob_attr)); + blob_fill_pad(attr); + return attr; +} + +int +blob_buf_init(struct blob_buf *buf, int id) +{ + if (!buf->grow) + buf->grow = blob_buffer_grow; + + buf->head = buf->buf; + if (blob_add(buf, buf->buf, id, 0) == NULL) + return -ENOMEM; + + return 0; +} + +void +blob_buf_free(struct blob_buf *buf) +{ + free(buf->buf); + buf->buf = NULL; + buf->buflen = 0; +} + +void +blob_fill_pad(struct blob_attr *attr) +{ + char *buf = (char *) attr; + int len = blob_pad_len(attr); + int delta = len - blob_raw_len(attr); + + if (delta > 0) + memset(buf + len - delta, 0, delta); +} + +void +blob_set_raw_len(struct blob_attr *attr, unsigned int len) +{ + len &= BLOB_ATTR_LEN_MASK; + attr->id_len &= ~cpu_to_be32(BLOB_ATTR_LEN_MASK); + attr->id_len |= cpu_to_be32(len); +} + +struct blob_attr * +blob_new(struct blob_buf *buf, int id, int payload) +{ + struct blob_attr *attr; + + attr = blob_add(buf, blob_next(buf->head), id, payload); + if (!attr) + return NULL; + + blob_set_raw_len(buf->head, blob_pad_len(buf->head) + blob_pad_len(attr)); + return attr; +} + +struct blob_attr * +blob_put_raw(struct blob_buf *buf, const void *ptr, unsigned int len) +{ + struct blob_attr *attr; + + if (len < sizeof(struct blob_attr) || !ptr) + return NULL; + + attr = blob_add(buf, blob_next(buf->head), 0, len - sizeof(struct blob_attr)); + if (!attr) + return NULL; + blob_set_raw_len(buf->head, blob_pad_len(buf->head) + len); + memcpy(attr, ptr, len); + return attr; +} + +struct blob_attr * +blob_put(struct blob_buf *buf, int id, const void *ptr, unsigned int len) +{ + struct blob_attr *attr; + + attr = blob_new(buf, id, len); + if (!attr) + return NULL; + + if (ptr) + memcpy(blob_data(attr), ptr, len); + return attr; +} + +void * +blob_nest_start(struct blob_buf *buf, int id) +{ + unsigned long offset = attr_to_offset(buf, buf->head); + buf->head = blob_new(buf, id, 0); + if (!buf->head) + return NULL; + return (void *) offset; +} + +void +blob_nest_end(struct blob_buf *buf, void *cookie) +{ + struct blob_attr *attr = offset_to_attr(buf, (unsigned long) cookie); + blob_set_raw_len(attr, blob_pad_len(attr) + blob_len(buf->head)); + buf->head = attr; +} + +static const int blob_type_minlen[BLOB_ATTR_LAST] = { + [BLOB_ATTR_STRING] = 1, + [BLOB_ATTR_INT8] = sizeof(uint8_t), + [BLOB_ATTR_INT16] = sizeof(uint16_t), + [BLOB_ATTR_INT32] = sizeof(uint32_t), + [BLOB_ATTR_INT64] = sizeof(uint64_t), +}; + +bool +blob_check_type(const void *ptr, unsigned int len, int type) +{ + const char *data = ptr; + + if (type >= BLOB_ATTR_LAST) + return false; + + if (type >= BLOB_ATTR_INT8 && type <= BLOB_ATTR_INT64) { + if (len != blob_type_minlen[type]) + return false; + } else { + if (len < blob_type_minlen[type]) + return false; + } + + if (type == BLOB_ATTR_STRING && data[len - 1] != 0) + return false; + + return true; +} + +int +blob_parse(struct blob_attr *attr, struct blob_attr **data, const struct blob_attr_info *info, int max) +{ + struct blob_attr *pos; + int found = 0; + int rem; + + memset(data, 0, sizeof(struct blob_attr *) * max); + blob_for_each_attr(pos, attr, rem) { + int id = blob_id(pos); + int len = blob_len(pos); + + if (id >= max) + continue; + + if (info) { + int type = info[id].type; + + if (type < BLOB_ATTR_LAST) { + if (!blob_check_type(blob_data(pos), len, type)) + continue; + } + + if (info[id].minlen && len < info[id].minlen) + continue; + + if (info[id].maxlen && len > info[id].maxlen) + continue; + + if (info[id].validate && !info[id].validate(&info[id], pos)) + continue; + } + + if (!data[id]) + found++; + + data[id] = pos; + } + return found; +} + +bool +blob_attr_equal(const struct blob_attr *a1, const struct blob_attr *a2) +{ + if (!a1 && !a2) + return true; + + if (!a1 || !a2) + return false; + + if (blob_pad_len(a1) != blob_pad_len(a2)) + return false; + + return !memcmp(a1, a2, blob_pad_len(a1)); +} + +struct blob_attr * +blob_memdup(struct blob_attr *attr) +{ + struct blob_attr *ret; + int size = blob_pad_len(attr); + + ret = malloc(size); + if (!ret) + return NULL; + + memcpy(ret, attr, size); + return ret; +} diff --git a/release/src/router/uqmi/libubox/blob.h b/release/src/router/uqmi/libubox/blob.h new file mode 100644 index 0000000000..ab077eab0d --- /dev/null +++ b/release/src/router/uqmi/libubox/blob.h @@ -0,0 +1,257 @@ +/* + * blob - library for generating/parsing tagged binary data + * + * Copyright (C) 2010 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _BLOB_H__ +#define _BLOB_H__ + +#include +#include +#include +#include +#include +#include + +#include "utils.h" + +#define BLOB_COOKIE 0x01234567 + +enum { + BLOB_ATTR_UNSPEC, + BLOB_ATTR_NESTED, + BLOB_ATTR_BINARY, + BLOB_ATTR_STRING, + BLOB_ATTR_INT8, + BLOB_ATTR_INT16, + BLOB_ATTR_INT32, + BLOB_ATTR_INT64, + BLOB_ATTR_LAST +}; + +#define BLOB_ATTR_ID_MASK 0x7f000000 +#define BLOB_ATTR_ID_SHIFT 24 +#define BLOB_ATTR_LEN_MASK 0x00ffffff +#define BLOB_ATTR_ALIGN 4 +#define BLOB_ATTR_EXTENDED 0x80000000 + +struct blob_attr { + uint32_t id_len; + char data[]; +} __packed; + +struct blob_attr_info { + unsigned int type; + unsigned int minlen; + unsigned int maxlen; + bool (*validate)(const struct blob_attr_info *, struct blob_attr *); +}; + +struct blob_buf { + struct blob_attr *head; + bool (*grow)(struct blob_buf *buf, int minlen); + int buflen; + void *buf; +}; + +/* + * blob_data: returns the data pointer for an attribute + */ +static inline void * +blob_data(const struct blob_attr *attr) +{ + return (void *) attr->data; +} + +/* + * blob_id: returns the id of an attribute + */ +static inline unsigned int +blob_id(const struct blob_attr *attr) +{ + int id = (be32_to_cpu(attr->id_len) & BLOB_ATTR_ID_MASK) >> BLOB_ATTR_ID_SHIFT; + return id; +} + +static inline bool +blob_is_extended(const struct blob_attr *attr) +{ + return !!(attr->id_len & cpu_to_be32(BLOB_ATTR_EXTENDED)); +} + +/* + * blob_len: returns the length of the attribute's payload + */ +static inline unsigned int +blob_len(const struct blob_attr *attr) +{ + return (be32_to_cpu(attr->id_len) & BLOB_ATTR_LEN_MASK) - sizeof(struct blob_attr); +} + +/* + * blob_raw_len: returns the complete length of an attribute (including the header) + */ +static inline unsigned int +blob_raw_len(const struct blob_attr *attr) +{ + return blob_len(attr) + sizeof(struct blob_attr); +} + +/* + * blob_pad_len: returns the padded length of an attribute (including the header) + */ +static inline unsigned int +blob_pad_len(const struct blob_attr *attr) +{ + unsigned int len = blob_raw_len(attr); + len = (len + BLOB_ATTR_ALIGN - 1) & ~(BLOB_ATTR_ALIGN - 1); + return len; +} + +static inline uint8_t +blob_get_u8(const struct blob_attr *attr) +{ + return *((uint8_t *) attr->data); +} + +static inline uint16_t +blob_get_u16(const struct blob_attr *attr) +{ + uint16_t *tmp = (uint16_t*)attr->data; + return be16_to_cpu(*tmp); +} + +static inline uint32_t +blob_get_u32(const struct blob_attr *attr) +{ + uint32_t *tmp = (uint32_t*)attr->data; + return be32_to_cpu(*tmp); +} + +static inline uint64_t +blob_get_u64(const struct blob_attr *attr) +{ + uint32_t *ptr = (uint32_t *) blob_data(attr); + uint64_t tmp = ((uint64_t) be32_to_cpu(ptr[0])) << 32; + tmp |= be32_to_cpu(ptr[1]); + return tmp; +} + +static inline int8_t +blob_get_int8(const struct blob_attr *attr) +{ + return blob_get_u8(attr); +} + +static inline int16_t +blob_get_int16(const struct blob_attr *attr) +{ + return blob_get_u16(attr); +} + +static inline int32_t +blob_get_int32(const struct blob_attr *attr) +{ + return blob_get_u32(attr); +} + +static inline int64_t +blob_get_int64(const struct blob_attr *attr) +{ + return blob_get_u64(attr); +} + +static inline const char * +blob_get_string(const struct blob_attr *attr) +{ + return attr->data; +} + +static inline struct blob_attr * +blob_next(const struct blob_attr *attr) +{ + return (struct blob_attr *) ((char *) attr + blob_pad_len(attr)); +} + +extern void blob_fill_pad(struct blob_attr *attr); +extern void blob_set_raw_len(struct blob_attr *attr, unsigned int len); +extern bool blob_attr_equal(const struct blob_attr *a1, const struct blob_attr *a2); +extern int blob_buf_init(struct blob_buf *buf, int id); +extern void blob_buf_free(struct blob_buf *buf); +extern bool blob_buf_grow(struct blob_buf *buf, int required); +extern struct blob_attr *blob_new(struct blob_buf *buf, int id, int payload); +extern void *blob_nest_start(struct blob_buf *buf, int id); +extern void blob_nest_end(struct blob_buf *buf, void *cookie); +extern struct blob_attr *blob_put(struct blob_buf *buf, int id, const void *ptr, unsigned int len); +extern bool blob_check_type(const void *ptr, unsigned int len, int type); +extern int blob_parse(struct blob_attr *attr, struct blob_attr **data, const struct blob_attr_info *info, int max); +extern struct blob_attr *blob_memdup(struct blob_attr *attr); +extern struct blob_attr *blob_put_raw(struct blob_buf *buf, const void *ptr, unsigned int len); + +static inline struct blob_attr * +blob_put_string(struct blob_buf *buf, int id, const char *str) +{ + return blob_put(buf, id, str, strlen(str) + 1); +} + +static inline struct blob_attr * +blob_put_u8(struct blob_buf *buf, int id, uint8_t val) +{ + return blob_put(buf, id, &val, sizeof(val)); +} + +static inline struct blob_attr * +blob_put_u16(struct blob_buf *buf, int id, uint16_t val) +{ + val = cpu_to_be16(val); + return blob_put(buf, id, &val, sizeof(val)); +} + +static inline struct blob_attr * +blob_put_u32(struct blob_buf *buf, int id, uint32_t val) +{ + val = cpu_to_be32(val); + return blob_put(buf, id, &val, sizeof(val)); +} + +static inline struct blob_attr * +blob_put_u64(struct blob_buf *buf, int id, uint64_t val) +{ + val = cpu_to_be64(val); + return blob_put(buf, id, &val, sizeof(val)); +} + +#define blob_put_int8 blob_put_u8 +#define blob_put_int16 blob_put_u16 +#define blob_put_int32 blob_put_u32 +#define blob_put_int64 blob_put_u64 + +#define __blob_for_each_attr(pos, attr, rem) \ + for (pos = (void *) attr; \ + rem > 0 && (blob_pad_len(pos) <= rem) && \ + (blob_pad_len(pos) >= sizeof(struct blob_attr)); \ + rem -= blob_pad_len(pos), pos = blob_next(pos)) + + +#define blob_for_each_attr(pos, attr, rem) \ + for (rem = attr ? blob_len(attr) : 0, \ + pos = attr ? blob_data(attr) : 0; \ + rem > 0 && (blob_pad_len(pos) <= rem) && \ + (blob_pad_len(pos) >= sizeof(struct blob_attr)); \ + rem -= blob_pad_len(pos), pos = blob_next(pos)) + + +#endif diff --git a/release/src/router/uqmi/libubox/blobmsg.c b/release/src/router/uqmi/libubox/blobmsg.c new file mode 100644 index 0000000000..9fe96e44c8 --- /dev/null +++ b/release/src/router/uqmi/libubox/blobmsg.c @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2010-2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "blobmsg.h" + +static const int blob_type[__BLOBMSG_TYPE_LAST] = { + [BLOBMSG_TYPE_INT8] = BLOB_ATTR_INT8, + [BLOBMSG_TYPE_INT16] = BLOB_ATTR_INT16, + [BLOBMSG_TYPE_INT32] = BLOB_ATTR_INT32, + [BLOBMSG_TYPE_INT64] = BLOB_ATTR_INT64, + [BLOBMSG_TYPE_STRING] = BLOB_ATTR_STRING, + [BLOBMSG_TYPE_UNSPEC] = BLOB_ATTR_BINARY, +}; + +static uint16_t +blobmsg_namelen(const struct blobmsg_hdr *hdr) +{ + return be16_to_cpu(hdr->namelen); +} + +bool blobmsg_check_attr(const struct blob_attr *attr, bool name) +{ + const struct blobmsg_hdr *hdr; + const char *data; + int id, len; + + if (blob_len(attr) < sizeof(struct blobmsg_hdr)) + return false; + + hdr = (void *) attr->data; + if (!hdr->namelen && name) + return false; + + if (blobmsg_namelen(hdr) > blob_len(attr) - sizeof(struct blobmsg_hdr)) + return false; + + if (hdr->name[blobmsg_namelen(hdr)] != 0) + return false; + + id = blob_id(attr); + len = blobmsg_data_len(attr); + data = blobmsg_data(attr); + + if (id > BLOBMSG_TYPE_LAST) + return false; + + if (!blob_type[id]) + return true; + + return blob_check_type(data, len, blob_type[id]); +} + +int blobmsg_check_array(const struct blob_attr *attr, int type) +{ + struct blob_attr *cur; + bool name; + int rem; + int size = 0; + + switch (blobmsg_type(attr)) { + case BLOBMSG_TYPE_TABLE: + name = true; + break; + case BLOBMSG_TYPE_ARRAY: + name = false; + break; + default: + return -1; + } + + blobmsg_for_each_attr(cur, attr, rem) { + if (type != BLOBMSG_TYPE_UNSPEC && blobmsg_type(cur) != type) + return -1; + + if (!blobmsg_check_attr(cur, name)) + return -1; + + size++; + } + + return size; +} + +bool blobmsg_check_attr_list(const struct blob_attr *attr, int type) +{ + return blobmsg_check_array(attr, type) >= 0; +} + +int blobmsg_parse_array(const struct blobmsg_policy *policy, int policy_len, + struct blob_attr **tb, void *data, unsigned int len) +{ + struct blob_attr *attr; + int i = 0; + + memset(tb, 0, policy_len * sizeof(*tb)); + __blob_for_each_attr(attr, data, len) { + if (policy[i].type != BLOBMSG_TYPE_UNSPEC && + blob_id(attr) != policy[i].type) + continue; + + if (!blobmsg_check_attr(attr, false)) + return -1; + + if (tb[i]) + continue; + + tb[i++] = attr; + if (i == policy_len) + break; + } + + return 0; +} + + +int blobmsg_parse(const struct blobmsg_policy *policy, int policy_len, + struct blob_attr **tb, void *data, unsigned int len) +{ + struct blobmsg_hdr *hdr; + struct blob_attr *attr; + uint8_t *pslen; + int i; + + memset(tb, 0, policy_len * sizeof(*tb)); + pslen = alloca(policy_len); + for (i = 0; i < policy_len; i++) { + if (!policy[i].name) + continue; + + pslen[i] = strlen(policy[i].name); + } + + __blob_for_each_attr(attr, data, len) { + hdr = blob_data(attr); + for (i = 0; i < policy_len; i++) { + if (!policy[i].name) + continue; + + if (policy[i].type != BLOBMSG_TYPE_UNSPEC && + blob_id(attr) != policy[i].type) + continue; + + if (blobmsg_namelen(hdr) != pslen[i]) + continue; + + if (!blobmsg_check_attr(attr, true)) + return -1; + + if (tb[i]) + continue; + + if (strcmp(policy[i].name, (char *) hdr->name) != 0) + continue; + + tb[i] = attr; + } + } + + return 0; +} + + +static struct blob_attr * +blobmsg_new(struct blob_buf *buf, int type, const char *name, int payload_len, void **data) +{ + struct blob_attr *attr; + struct blobmsg_hdr *hdr; + int attrlen, namelen; + char *pad_start, *pad_end; + + if (!name) + name = ""; + + namelen = strlen(name); + attrlen = blobmsg_hdrlen(namelen) + payload_len; + attr = blob_new(buf, type, attrlen); + if (!attr) + return NULL; + + attr->id_len |= be32_to_cpu(BLOB_ATTR_EXTENDED); + hdr = blob_data(attr); + hdr->namelen = cpu_to_be16(namelen); + strcpy((char *) hdr->name, (const char *)name); + pad_end = *data = blobmsg_data(attr); + pad_start = (char *) &hdr->name[namelen]; + if (pad_start < pad_end) + memset(pad_start, 0, pad_end - pad_start); + + return attr; +} + +static inline int +attr_to_offset(struct blob_buf *buf, struct blob_attr *attr) +{ + return (char *)attr - (char *) buf->buf + BLOB_COOKIE; +} + + +void * +blobmsg_open_nested(struct blob_buf *buf, const char *name, bool array) +{ + struct blob_attr *head; + int type = array ? BLOBMSG_TYPE_ARRAY : BLOBMSG_TYPE_TABLE; + unsigned long offset = attr_to_offset(buf, buf->head); + void *data; + + if (!name) + name = ""; + + head = blobmsg_new(buf, type, name, 0, &data); + if (!head) + return NULL; + blob_set_raw_len(buf->head, blob_pad_len(buf->head) - blobmsg_hdrlen(strlen(name))); + buf->head = head; + return (void *)offset; +} + +void +blobmsg_vprintf(struct blob_buf *buf, const char *name, const char *format, va_list arg) +{ + va_list arg2; + char cbuf; + int len; + + va_copy(arg2, arg); + len = vsnprintf(&cbuf, sizeof(cbuf), format, arg2); + va_end(arg2); + + vsprintf(blobmsg_alloc_string_buffer(buf, name, len + 1), format, arg); + blobmsg_add_string_buffer(buf); +} + +void +blobmsg_printf(struct blob_buf *buf, const char *name, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + blobmsg_vprintf(buf, name, format, ap); + va_end(ap); +} + +void * +blobmsg_alloc_string_buffer(struct blob_buf *buf, const char *name, unsigned int maxlen) +{ + struct blob_attr *attr; + void *data_dest; + + attr = blobmsg_new(buf, BLOBMSG_TYPE_STRING, name, maxlen, &data_dest); + if (!attr) + return NULL; + + data_dest = blobmsg_data(attr); + blob_set_raw_len(buf->head, blob_pad_len(buf->head) - blob_pad_len(attr)); + blob_set_raw_len(attr, blob_raw_len(attr) - maxlen); + + return data_dest; +} + +void * +blobmsg_realloc_string_buffer(struct blob_buf *buf, unsigned int maxlen) +{ + struct blob_attr *attr = blob_next(buf->head); + int offset = attr_to_offset(buf, blob_next(buf->head)) + blob_pad_len(attr) - BLOB_COOKIE; + int required = maxlen - (buf->buflen - offset); + + if (required <= 0) + goto out; + + blob_buf_grow(buf, required); + attr = blob_next(buf->head); + +out: + return blobmsg_data(attr); +} + +void +blobmsg_add_string_buffer(struct blob_buf *buf) +{ + struct blob_attr *attr; + int len, attrlen; + + attr = blob_next(buf->head); + len = strlen(blobmsg_data(attr)) + 1; + + attrlen = blob_raw_len(attr) + len; + blob_set_raw_len(attr, attrlen); + blob_fill_pad(attr); + + blob_set_raw_len(buf->head, blob_raw_len(buf->head) + blob_pad_len(attr)); +} + +int +blobmsg_add_field(struct blob_buf *buf, int type, const char *name, + const void *data, unsigned int len) +{ + struct blob_attr *attr; + void *data_dest; + + attr = blobmsg_new(buf, type, name, len, &data_dest); + if (!attr) + return -1; + + if (len > 0) + memcpy(data_dest, data, len); + + return 0; +} diff --git a/release/src/router/uqmi/libubox/blobmsg.h b/release/src/router/uqmi/libubox/blobmsg.h new file mode 100644 index 0000000000..e58f95deb6 --- /dev/null +++ b/release/src/router/uqmi/libubox/blobmsg.h @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2010-2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __BLOBMSG_H +#define __BLOBMSG_H + +#include +#include "blob.h" + +#define BLOBMSG_ALIGN 2 +#define BLOBMSG_PADDING(len) (((len) + (1 << BLOBMSG_ALIGN) - 1) & ~((1 << BLOBMSG_ALIGN) - 1)) + +enum blobmsg_type { + BLOBMSG_TYPE_UNSPEC, + BLOBMSG_TYPE_ARRAY, + BLOBMSG_TYPE_TABLE, + BLOBMSG_TYPE_STRING, + BLOBMSG_TYPE_INT64, + BLOBMSG_TYPE_INT32, + BLOBMSG_TYPE_INT16, + BLOBMSG_TYPE_INT8, + __BLOBMSG_TYPE_LAST, + BLOBMSG_TYPE_LAST = __BLOBMSG_TYPE_LAST - 1, + BLOBMSG_TYPE_BOOL = BLOBMSG_TYPE_INT8, +}; + +struct blobmsg_hdr { + uint16_t namelen; + uint8_t name[]; +} __packed; + +struct blobmsg_policy { + const char *name; + enum blobmsg_type type; +}; + +static inline int blobmsg_hdrlen(unsigned int namelen) +{ + return BLOBMSG_PADDING(sizeof(struct blobmsg_hdr) + namelen + 1); +} + +static inline void blobmsg_clear_name(struct blob_attr *attr) +{ + struct blobmsg_hdr *hdr = (struct blobmsg_hdr *) blob_data(attr); + hdr->name[0] = 0; +} + +static inline const char *blobmsg_name(const struct blob_attr *attr) +{ + struct blobmsg_hdr *hdr = (struct blobmsg_hdr *) blob_data(attr); + return (const char *) hdr->name; +} + +static inline int blobmsg_type(const struct blob_attr *attr) +{ + return blob_id(attr); +} + +static inline void *blobmsg_data(const struct blob_attr *attr) +{ + struct blobmsg_hdr *hdr = (struct blobmsg_hdr *) blob_data(attr); + char *data = (char *) blob_data(attr); + + if (blob_is_extended(attr)) + data += blobmsg_hdrlen(be16_to_cpu(hdr->namelen)); + + return data; +} + +static inline int blobmsg_data_len(const struct blob_attr *attr) +{ + uint8_t *start, *end; + + start = (uint8_t *) blob_data(attr); + end = (uint8_t *) blobmsg_data(attr); + + return blob_len(attr) - (end - start); +} + +static inline int blobmsg_len(const struct blob_attr *attr) +{ + return blobmsg_data_len(attr); +} + +bool blobmsg_check_attr(const struct blob_attr *attr, bool name); +bool blobmsg_check_attr_list(const struct blob_attr *attr, int type); + +/* + * blobmsg_check_array: validate array/table and return size + * + * Checks if all elements of an array or table are valid and have + * the specified type. Returns the number of elements in the array + */ +int blobmsg_check_array(const struct blob_attr *attr, int type); + +int blobmsg_parse(const struct blobmsg_policy *policy, int policy_len, + struct blob_attr **tb, void *data, unsigned int len); +int blobmsg_parse_array(const struct blobmsg_policy *policy, int policy_len, + struct blob_attr **tb, void *data, unsigned int len); + +int blobmsg_add_field(struct blob_buf *buf, int type, const char *name, + const void *data, unsigned int len); + +static inline int +blobmsg_add_u8(struct blob_buf *buf, const char *name, uint8_t val) +{ + return blobmsg_add_field(buf, BLOBMSG_TYPE_INT8, name, &val, 1); +} + +static inline int +blobmsg_add_u16(struct blob_buf *buf, const char *name, uint16_t val) +{ + val = cpu_to_be16(val); + return blobmsg_add_field(buf, BLOBMSG_TYPE_INT16, name, &val, 2); +} + +static inline int +blobmsg_add_u32(struct blob_buf *buf, const char *name, uint32_t val) +{ + val = cpu_to_be32(val); + return blobmsg_add_field(buf, BLOBMSG_TYPE_INT32, name, &val, 4); +} + +static inline int +blobmsg_add_u64(struct blob_buf *buf, const char *name, uint64_t val) +{ + val = cpu_to_be64(val); + return blobmsg_add_field(buf, BLOBMSG_TYPE_INT64, name, &val, 8); +} + +static inline int +blobmsg_add_string(struct blob_buf *buf, const char *name, const char *string) +{ + return blobmsg_add_field(buf, BLOBMSG_TYPE_STRING, name, string, strlen(string) + 1); +} + +static inline int +blobmsg_add_blob(struct blob_buf *buf, struct blob_attr *attr) +{ + return blobmsg_add_field(buf, blobmsg_type(attr), blobmsg_name(attr), + blobmsg_data(attr), blobmsg_data_len(attr)); +} + +void *blobmsg_open_nested(struct blob_buf *buf, const char *name, bool array); + +static inline void * +blobmsg_open_array(struct blob_buf *buf, const char *name) +{ + return blobmsg_open_nested(buf, name, true); +} + +static inline void * +blobmsg_open_table(struct blob_buf *buf, const char *name) +{ + return blobmsg_open_nested(buf, name, false); +} + +static inline void +blobmsg_close_array(struct blob_buf *buf, void *cookie) +{ + blob_nest_end(buf, cookie); +} + +static inline void +blobmsg_close_table(struct blob_buf *buf, void *cookie) +{ + blob_nest_end(buf, cookie); +} + +static inline int blobmsg_buf_init(struct blob_buf *buf) +{ + return blob_buf_init(buf, BLOBMSG_TYPE_TABLE); +} + +static inline uint8_t blobmsg_get_u8(struct blob_attr *attr) +{ + return *(uint8_t *) blobmsg_data(attr); +} + +static inline bool blobmsg_get_bool(struct blob_attr *attr) +{ + return *(uint8_t *) blobmsg_data(attr); +} + +static inline uint16_t blobmsg_get_u16(struct blob_attr *attr) +{ + return be16_to_cpu(*(uint16_t *) blobmsg_data(attr)); +} + +static inline uint32_t blobmsg_get_u32(struct blob_attr *attr) +{ + return be32_to_cpu(*(uint32_t *) blobmsg_data(attr)); +} + +static inline uint64_t blobmsg_get_u64(struct blob_attr *attr) +{ + uint32_t *ptr = (uint32_t *) blobmsg_data(attr); + uint64_t tmp = ((uint64_t) be32_to_cpu(ptr[0])) << 32; + tmp |= be32_to_cpu(ptr[1]); + return tmp; +} + +static inline char *blobmsg_get_string(struct blob_attr *attr) +{ + if (!attr) + return NULL; + + return (char *) blobmsg_data(attr); +} + +void *blobmsg_alloc_string_buffer(struct blob_buf *buf, const char *name, unsigned int maxlen); +void *blobmsg_realloc_string_buffer(struct blob_buf *buf, unsigned int maxlen); +void blobmsg_add_string_buffer(struct blob_buf *buf); + +void blobmsg_vprintf(struct blob_buf *buf, const char *name, const char *format, va_list arg); +void blobmsg_printf(struct blob_buf *buf, const char *name, const char *format, ...) + __attribute__((format(printf, 3, 4))); + + +/* blobmsg to json formatting */ + +#define blobmsg_for_each_attr(pos, attr, rem) \ + for (rem = attr ? blobmsg_data_len(attr) : 0, \ + pos = attr ? blobmsg_data(attr) : 0; \ + rem > 0 && (blob_pad_len(pos) <= rem) && \ + (blob_pad_len(pos) >= sizeof(struct blob_attr)); \ + rem -= blob_pad_len(pos), pos = blob_next(pos)) + +#endif diff --git a/release/src/router/uqmi/libubox/blobmsg_json.c b/release/src/router/uqmi/libubox/blobmsg_json.c new file mode 100644 index 0000000000..ad9247e835 --- /dev/null +++ b/release/src/router/uqmi/libubox/blobmsg_json.c @@ -0,0 +1,329 @@ +/* + * Copyright (C) 2010-2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include "blobmsg.h" +#include "blobmsg_json.h" + +#define JSONC + +#ifdef JSONC + #include +#else + #include +#endif + +bool blobmsg_add_object(struct blob_buf *b, json_object *obj) +{ + json_object_object_foreach(obj, key, val) { + if (!blobmsg_add_json_element(b, key, val)) + return false; + } + return true; +} + +static bool blobmsg_add_array(struct blob_buf *b, struct array_list *a) +{ + int i, len; + + for (i = 0, len = array_list_length(a); i < len; i++) { + if (!blobmsg_add_json_element(b, NULL, array_list_get_idx(a, i))) + return false; + } + + return true; +} + +bool blobmsg_add_json_element(struct blob_buf *b, const char *name, json_object *obj) +{ + bool ret = true; + void *c; + + if (!obj) + return false; + + switch (json_object_get_type(obj)) { + case json_type_object: + c = blobmsg_open_table(b, name); + ret = blobmsg_add_object(b, obj); + blobmsg_close_table(b, c); + break; + case json_type_array: + c = blobmsg_open_array(b, name); + ret = blobmsg_add_array(b, json_object_get_array(obj)); + blobmsg_close_array(b, c); + break; + case json_type_string: + blobmsg_add_string(b, name, json_object_get_string(obj)); + break; + case json_type_boolean: + blobmsg_add_u8(b, name, json_object_get_boolean(obj)); + break; + case json_type_int: + blobmsg_add_u32(b, name, json_object_get_int(obj)); + break; + default: + return false; + } + return ret; +} + +static bool __blobmsg_add_json(struct blob_buf *b, json_object *obj) +{ + bool ret = false; + + if (!obj) + return false; + + if (json_object_get_type(obj) != json_type_object) + goto out; + + ret = blobmsg_add_object(b, obj); + +out: + json_object_put(obj); + return ret; +} + +bool blobmsg_add_json_from_file(struct blob_buf *b, const char *file) +{ + return __blobmsg_add_json(b, json_object_from_file(file)); +} + +bool blobmsg_add_json_from_string(struct blob_buf *b, const char *str) +{ + return __blobmsg_add_json(b, json_tokener_parse(str)); +} + + +struct strbuf { + int len; + int pos; + char *buf; + + blobmsg_json_format_t custom_format; + void *priv; + bool indent; + int indent_level; +}; + +static bool blobmsg_puts(struct strbuf *s, const char *c, int len) +{ + if (len <= 0) + return true; + + if (s->pos + len >= s->len) { + s->len += 16 + len; + s->buf = realloc(s->buf, s->len); + if (!s->buf) + return false; + } + memcpy(s->buf + s->pos, c, len); + s->pos += len; + return true; +} + +static void add_separator(struct strbuf *s) +{ + static char indent_chars[17] = "\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; + int indent; + char *start; + + if (!s->indent) + return; + + indent = s->indent_level; + if (indent > 16) + indent = 16; + + start = &indent_chars[sizeof(indent_chars) - indent - 1]; + *start = '\n'; + blobmsg_puts(s, start, indent + 1); + *start = '\t'; +} + + +static void blobmsg_format_string(struct strbuf *s, const char *str) +{ + const unsigned char *p, *last, *end; + char buf[8] = "\\u00"; + + end = (unsigned char *) str + strlen(str); + blobmsg_puts(s, "\"", 1); + for (p = (unsigned char *) str, last = p; *p; p++) { + char escape = '\0'; + int len; + + switch(*p) { + case '\b': + escape = 'b'; + break; + case '\n': + escape = 'n'; + break; + case '\t': + escape = 't'; + break; + case '\r': + escape = 'r'; + break; + case '"': + case '\\': + case '/': + escape = *p; + break; + default: + if (*p < ' ') + escape = 'u'; + break; + } + + if (!escape) + continue; + + if (p > last) + blobmsg_puts(s, (char *) last, p - last); + last = p + 1; + buf[1] = escape; + + if (escape == 'u') { + sprintf(buf + 4, "%02x", (unsigned char) *p); + len = 6; + } else { + len = 2; + } + blobmsg_puts(s, buf, len); + } + + blobmsg_puts(s, (char *) last, end - last); + blobmsg_puts(s, "\"", 1); +} + +static void blobmsg_format_json_list(struct strbuf *s, struct blob_attr *attr, int len, bool array); + +static void blobmsg_format_element(struct strbuf *s, struct blob_attr *attr, bool array, bool head) +{ + const char *data_str; + char buf[32]; + void *data; + int len; + + if (!blobmsg_check_attr(attr, false)) + return; + + if (!array && blobmsg_name(attr)[0]) { + blobmsg_format_string(s, blobmsg_name(attr)); + blobmsg_puts(s, ": ", s->indent ? 2 : 1); + } + + data = blobmsg_data(attr); + len = blobmsg_data_len(attr); + + if (!head && s->custom_format) { + data_str = s->custom_format(s->priv, attr); + if (data_str) + goto out; + } + + data_str = buf; + switch(blob_id(attr)) { + case BLOBMSG_TYPE_UNSPEC: + sprintf(buf, "null"); + break; + case BLOBMSG_TYPE_BOOL: + sprintf(buf, "%s", *(uint8_t *)data ? "true" : "false"); + break; + case BLOBMSG_TYPE_INT16: + sprintf(buf, "%d", be16_to_cpu(*(uint16_t *)data)); + break; + case BLOBMSG_TYPE_INT32: + sprintf(buf, "%d", (int32_t) be32_to_cpu(*(uint32_t *)data)); + break; + case BLOBMSG_TYPE_INT64: + sprintf(buf, "%" PRId64, (int64_t) be64_to_cpu(*(uint64_t *)data)); + break; + case BLOBMSG_TYPE_STRING: + blobmsg_format_string(s, data); + return; + case BLOBMSG_TYPE_ARRAY: + blobmsg_format_json_list(s, data, len, true); + return; + case BLOBMSG_TYPE_TABLE: + blobmsg_format_json_list(s, data, len, false); + return; + } + +out: + blobmsg_puts(s, data_str, strlen(data_str)); +} + +static void blobmsg_format_json_list(struct strbuf *s, struct blob_attr *attr, int len, bool array) +{ + struct blob_attr *pos; + bool first = true; + int rem = len; + + blobmsg_puts(s, (array ? "[" : "{" ), 1); + s->indent_level++; + add_separator(s); + __blob_for_each_attr(pos, attr, rem) { + if (!first) { + blobmsg_puts(s, ",", 1); + add_separator(s); + } + + blobmsg_format_element(s, pos, array, false); + first = false; + } + s->indent_level--; + add_separator(s); + blobmsg_puts(s, (array ? "]" : "}"), 1); +} + +char *blobmsg_format_json_with_cb(struct blob_attr *attr, bool list, blobmsg_json_format_t cb, void *priv, int indent) +{ + struct strbuf s; + bool array; + + s.len = blob_len(attr); + s.buf = malloc(s.len); + s.pos = 0; + s.custom_format = cb; + s.priv = priv; + s.indent = false; + + if (indent >= 0) { + s.indent = true; + s.indent_level = indent; + } + + array = blob_is_extended(attr) && + blobmsg_type(attr) == BLOBMSG_TYPE_ARRAY; + + if (list) + blobmsg_format_json_list(&s, blobmsg_data(attr), blobmsg_data_len(attr), array); + else + blobmsg_format_element(&s, attr, false, false); + + if (!s.len) { + free(s.buf); + return NULL; + } + + s.buf = realloc(s.buf, s.pos + 1); + s.buf[s.pos] = 0; + + return s.buf; +} diff --git a/release/src/router/uqmi/libubox/blobmsg_json.h b/release/src/router/uqmi/libubox/blobmsg_json.h new file mode 100644 index 0000000000..cd9ed33e4c --- /dev/null +++ b/release/src/router/uqmi/libubox/blobmsg_json.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2010-2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __BLOBMSG_JSON_H +#define __BLOBMSG_JSON_H + +struct json_object; + +#include +#include "blobmsg.h" + +bool blobmsg_add_object(struct blob_buf *b, struct json_object *obj); +bool blobmsg_add_json_element(struct blob_buf *b, const char *name, struct json_object *obj); +bool blobmsg_add_json_from_string(struct blob_buf *b, const char *str); +bool blobmsg_add_json_from_file(struct blob_buf *b, const char *file); + +typedef const char *(*blobmsg_json_format_t)(void *priv, struct blob_attr *attr); + +char *blobmsg_format_json_with_cb(struct blob_attr *attr, bool list, + blobmsg_json_format_t cb, void *priv, + int indent); + +static inline char *blobmsg_format_json(struct blob_attr *attr, bool list) +{ + return blobmsg_format_json_with_cb(attr, list, NULL, NULL, -1); +} + +static inline char *blobmsg_format_json_indent(struct blob_attr *attr, bool list, int indent) +{ + return blobmsg_format_json_with_cb(attr, list, NULL, NULL, indent); +} + +#endif diff --git a/release/src/router/uqmi/libubox/examples/CMakeLists.txt b/release/src/router/uqmi/libubox/examples/CMakeLists.txt new file mode 100644 index 0000000000..2126d29842 --- /dev/null +++ b/release/src/router/uqmi/libubox/examples/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 2.6) + +PROJECT(ubox-examples C) +ADD_DEFINITIONS(-O1 -Wall -Werror --std=gnu99 -g3) + +IF(APPLE) + INCLUDE_DIRECTORIES(/opt/local/include) + LINK_DIRECTORIES(/opt/local/lib) +ENDIF() + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/..) +LINK_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/..) + +FIND_LIBRARY(json NAMES json-c json) + +ADD_EXECUTABLE(blobmsg-example blobmsg-example.c) +TARGET_LINK_LIBRARIES(blobmsg-example ubox blobmsg_json ${json}) + +ADD_EXECUTABLE(ustream-example ustream-example.c) +TARGET_LINK_LIBRARIES(ustream-example ubox) + +ADD_EXECUTABLE(runqueue-example runqueue-example.c) +TARGET_LINK_LIBRARIES(runqueue-example ubox) + diff --git a/release/src/router/uqmi/libubox/examples/blobmsg-example.c b/release/src/router/uqmi/libubox/examples/blobmsg-example.c new file mode 100644 index 0000000000..69ddce8960 --- /dev/null +++ b/release/src/router/uqmi/libubox/examples/blobmsg-example.c @@ -0,0 +1,139 @@ +#include + +#include "blobmsg.h" +#include "blobmsg_json.h" + +static const char *indent_str = "\t\t\t\t\t\t\t\t\t\t\t\t\t"; + +#define indent_printf(indent, ...) do { \ + if (indent > 0) \ + fwrite(indent_str, indent, 1, stderr); \ + fprintf(stderr, __VA_ARGS__); \ +} while(0) + +static void dump_attr_data(struct blob_attr *data, int indent, int next_indent); + +static void +dump_table(struct blob_attr *head, int len, int indent, bool array) +{ + struct blob_attr *attr; + struct blobmsg_hdr *hdr; + + indent_printf(indent, "{\n"); + __blob_for_each_attr(attr, head, len) { + hdr = blob_data(attr); + if (!array) + indent_printf(indent + 1, "%s : ", hdr->name); + dump_attr_data(attr, 0, indent + 1); + } + indent_printf(indent, "}\n"); +} + +static void dump_attr_data(struct blob_attr *data, int indent, int next_indent) +{ + int type = blobmsg_type(data); + switch(type) { + case BLOBMSG_TYPE_STRING: + indent_printf(indent, "%s\n", blobmsg_get_string(data)); + break; + case BLOBMSG_TYPE_INT8: + indent_printf(indent, "%d\n", blobmsg_get_u8(data)); + break; + case BLOBMSG_TYPE_INT16: + indent_printf(indent, "%d\n", blobmsg_get_u16(data)); + break; + case BLOBMSG_TYPE_INT32: + indent_printf(indent, "%d\n", blobmsg_get_u32(data)); + break; + case BLOBMSG_TYPE_INT64: + indent_printf(indent, "%"PRIu64"\n", blobmsg_get_u64(data)); + break; + case BLOBMSG_TYPE_TABLE: + case BLOBMSG_TYPE_ARRAY: + if (!indent) + indent_printf(indent, "\n"); + dump_table(blobmsg_data(data), blobmsg_data_len(data), + next_indent, type == BLOBMSG_TYPE_ARRAY); + break; + } +} + +enum { + FOO_MESSAGE, + FOO_LIST, + FOO_TESTDATA +}; + +static const struct blobmsg_policy pol[] = { + [FOO_MESSAGE] = { + .name = "message", + .type = BLOBMSG_TYPE_STRING, + }, + [FOO_LIST] = { + .name = "list", + .type = BLOBMSG_TYPE_ARRAY, + }, + [FOO_TESTDATA] = { + .name = "testdata", + .type = BLOBMSG_TYPE_TABLE, + }, +}; + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +static void dump_message(struct blob_buf *buf) +{ + struct blob_attr *tb[ARRAY_SIZE(pol)]; + + if (blobmsg_parse(pol, ARRAY_SIZE(pol), tb, blob_data(buf->head), blob_len(buf->head)) != 0) { + fprintf(stderr, "Parse failed\n"); + return; + } + if (tb[FOO_MESSAGE]) + fprintf(stderr, "Message: %s\n", (char *) blobmsg_data(tb[FOO_MESSAGE])); + + if (tb[FOO_LIST]) { + fprintf(stderr, "List: "); + dump_table(blobmsg_data(tb[FOO_LIST]), blobmsg_data_len(tb[FOO_LIST]), 0, true); + } + if (tb[FOO_TESTDATA]) { + fprintf(stderr, "Testdata: "); + dump_table(blobmsg_data(tb[FOO_TESTDATA]), blobmsg_data_len(tb[FOO_TESTDATA]), 0, false); + } +} + +static void +fill_message(struct blob_buf *buf) +{ + void *tbl; + + blobmsg_add_string(buf, "message", "Hello, world!"); + + tbl = blobmsg_open_table(buf, "testdata"); + blobmsg_add_u32(buf, "hello", 1); + blobmsg_add_string(buf, "world", "2"); + blobmsg_close_table(buf, tbl); + + tbl = blobmsg_open_array(buf, "list"); + blobmsg_add_u32(buf, NULL, 0); + blobmsg_add_u32(buf, NULL, 1); + blobmsg_add_u32(buf, NULL, 2); + blobmsg_close_table(buf, tbl); +} + +int main(int argc, char **argv) +{ + static struct blob_buf buf; + + blobmsg_buf_init(&buf); + fill_message(&buf); + dump_message(&buf); + fprintf(stderr, "json: %s\n", blobmsg_format_json(buf.head, true)); + + if (buf.buf) + free(buf.buf); + + return 0; +} diff --git a/release/src/router/uqmi/libubox/examples/runqueue-example.c b/release/src/router/uqmi/libubox/examples/runqueue-example.c new file mode 100644 index 0000000000..1ae184a9b0 --- /dev/null +++ b/release/src/router/uqmi/libubox/examples/runqueue-example.c @@ -0,0 +1,112 @@ +/* + * runqueue-example.c + * + * Copyright (C) 2013 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include "runqueue.h" + +static struct runqueue q; + +struct sleeper { + struct runqueue_process proc; + int val; +}; + +static void q_empty(struct runqueue *q) +{ + fprintf(stderr, "All done!\n"); + uloop_end(); +} + +static void q_sleep_run(struct runqueue *q, struct runqueue_task *t) +{ + struct sleeper *s = container_of(t, struct sleeper, proc.task); + char str[32]; + pid_t pid; + + fprintf(stderr, "[%d/%d] start 'sleep %d'\n", q->running_tasks, q->max_running_tasks, s->val); + + pid = fork(); + if (pid < 0) + return; + + if (pid) { + runqueue_process_add(q, &s->proc, pid); + return; + } + + sprintf(str, "%d", s->val); + execlp("sleep", "sleep", str, NULL); + exit(1); +} + +static void q_sleep_cancel(struct runqueue *q, struct runqueue_task *t, int type) +{ + struct sleeper *s = container_of(t, struct sleeper, proc.task); + + fprintf(stderr, "[%d/%d] cancel 'sleep %d'\n", q->running_tasks, q->max_running_tasks, s->val); + runqueue_process_cancel_cb(q, t, type); +} + +static void q_sleep_complete(struct runqueue *q, struct runqueue_task *p) +{ + struct sleeper *s = container_of(p, struct sleeper, proc.task); + + fprintf(stderr, "[%d/%d] finish 'sleep %d'\n", q->running_tasks, q->max_running_tasks, s->val); + free(s); +} + +static void add_sleeper(int val) +{ + static const struct runqueue_task_type sleeper_type = { + .run = q_sleep_run, + .cancel = q_sleep_cancel, + .kill = runqueue_process_kill_cb, + }; + struct sleeper *s; + + s = calloc(1, sizeof(*s)); + s->proc.task.type = &sleeper_type; + s->proc.task.run_timeout = 500; + s->proc.task.complete = q_sleep_complete; + s->val = val; + runqueue_task_add(&q, &s->proc.task, false); +} + +int main(int argc, char **argv) +{ + uloop_init(); + + runqueue_init(&q); + q.empty_cb = q_empty; + q.max_running_tasks = 1; + + if (argc > 1) + q.max_running_tasks = atoi(argv[1]); + + add_sleeper(1); + add_sleeper(1); + add_sleeper(1); + uloop_run(); + uloop_done(); + + return 0; +} diff --git a/release/src/router/uqmi/libubox/examples/uloop-example.lua b/release/src/router/uqmi/libubox/examples/uloop-example.lua new file mode 100755 index 0000000000..9b0684e648 --- /dev/null +++ b/release/src/router/uqmi/libubox/examples/uloop-example.lua @@ -0,0 +1,78 @@ +#!/usr/bin/env lua + +local socket = require "socket" + +local uloop = require("uloop") +uloop.init() + +local udp = socket.udp() +udp:settimeout(0) +udp:setsockname('*', 8080) + +-- timer example 1 +local timer +function t() + print("1000 ms timer run"); + timer:set(1000) +end +timer = uloop.timer(t) +timer:set(1000) + +-- timer example 2 +uloop.timer(function() print("2000 ms timer run"); end, 2000) + +-- timer example 3 +uloop.timer(function() print("3000 ms timer run"); end, 3000):cancel() + +-- process +function p1(r) + print("Process 1 completed") + print(r) +end + +function p2(r) + print("Process 2 completed") + print(r) +end + +uloop.timer( + function() + uloop.process("uloop_pid_test.sh", {"foo", "bar"}, {"PROCESS=1"}, p1) + end, 1000 +) +uloop.timer( + function() + uloop.process("uloop_pid_test.sh", {"foo", "bar"}, {"PROCESS=2"}, p2) + end, 2000 +) + +udp_ev = uloop.fd_add(udp, function(ufd, events) + local words, msg_or_ip, port_or_nil = ufd:receivefrom() + print('Recv UDP packet from '..msg_or_ip..':'..port_or_nil..' : '..words) + if words == "Stop!" then + udp_ev:delete() + end +end, uloop.ULOOP_READ) + +udp_count = 0 +udp_send_timer = uloop.timer( + function() + local s = socket.udp() + local words + if udp_count > 3 then + words = "Stop!" + udp_send_timer:cancel() + else + words = 'Hello!' + udp_send_timer:set(1000) + end + print('Send UDP packet to 127.0.0.1:8080 :'..words) + s:sendto(words, '127.0.0.1', 8080) + s:close() + + udp_count = udp_count + 1 + end, 3000 +) + +uloop.run() + diff --git a/release/src/router/uqmi/libubox/examples/uloop_pid_test.sh b/release/src/router/uqmi/libubox/examples/uloop_pid_test.sh new file mode 100755 index 0000000000..c622064f1f --- /dev/null +++ b/release/src/router/uqmi/libubox/examples/uloop_pid_test.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +echo $0 $* +echo Environment: +env + +sleep 2 + +echo "stopping child" + +exit 5 diff --git a/release/src/router/uqmi/libubox/examples/ustream-example.c b/release/src/router/uqmi/libubox/examples/ustream-example.c new file mode 100644 index 0000000000..3db56c443e --- /dev/null +++ b/release/src/router/uqmi/libubox/examples/ustream-example.c @@ -0,0 +1,148 @@ +#include +#include + +#include +#include +#include +#include +#include + +#include "ustream.h" +#include "uloop.h" +#include "usock.h" + +static struct uloop_fd server; +static const char *port = "10000"; +struct client *next_client = NULL; + +struct client { + struct sockaddr_in sin; + + struct ustream_fd s; + int ctr; +}; + +static void client_read_cb(struct ustream *s, int bytes) +{ + struct client *cl = container_of(s, struct client, s.stream); + struct ustream_buf *buf = s->r.head; + char *newline, *str; + + do { + str = ustream_get_read_buf(s, NULL); + if (!str) + break; + + newline = strchr(buf->data, '\n'); + if (!newline) + break; + + *newline = 0; + ustream_printf(s, "%s\n", str); + ustream_consume(s, newline + 1 - str); + cl->ctr += newline + 1 - str; + } while(1); + + if (s->w.data_bytes > 256 && !ustream_read_blocked(s)) { + fprintf(stderr, "Block read, bytes: %d\n", s->w.data_bytes); + ustream_set_read_blocked(s, true); + } +} + +static void client_close(struct ustream *s) +{ + struct client *cl = container_of(s, struct client, s.stream); + + fprintf(stderr, "Connection closed\n"); + ustream_free(s); + close(cl->s.fd.fd); + free(cl); +} + +static void client_notify_write(struct ustream *s, int bytes) +{ + fprintf(stderr, "Wrote %d bytes, pending: %d\n", bytes, s->w.data_bytes); + + if (s->w.data_bytes < 128 && ustream_read_blocked(s)) { + fprintf(stderr, "Unblock read\n"); + ustream_set_read_blocked(s, false); + } +} + +static void client_notify_state(struct ustream *s) +{ + struct client *cl = container_of(s, struct client, s.stream); + + if (!s->eof) + return; + + fprintf(stderr, "eof!, pending: %d, total: %d\n", s->w.data_bytes, cl->ctr); + if (!s->w.data_bytes) + return client_close(s); + +} + +static void server_cb(struct uloop_fd *fd, unsigned int events) +{ + struct client *cl; + unsigned int sl = sizeof(struct sockaddr_in); + int sfd; + + if (!next_client) + next_client = calloc(1, sizeof(*next_client)); + + cl = next_client; + sfd = accept(server.fd, (struct sockaddr *) &cl->sin, &sl); + if (sfd < 0) { + fprintf(stderr, "Accept failed\n"); + return; + } + + cl->s.stream.string_data = true; + cl->s.stream.notify_read = client_read_cb; + cl->s.stream.notify_state = client_notify_state; + cl->s.stream.notify_write = client_notify_write; + ustream_fd_init(&cl->s, sfd); + next_client = NULL; + fprintf(stderr, "New connection\n"); +} + +static int run_server(void) +{ + + server.cb = server_cb; + server.fd = usock(USOCK_TCP | USOCK_SERVER | USOCK_IPV4ONLY | USOCK_NUMERIC, "127.0.0.1", port); + if (server.fd < 0) { + perror("usock"); + return 1; + } + + uloop_init(); + uloop_fd_add(&server, ULOOP_READ); + uloop_run(); + + return 0; +} + +static int usage(const char *name) +{ + fprintf(stderr, "Usage: %s -p \n", name); + return 1; +} + +int main(int argc, char **argv) +{ + int ch; + + while ((ch = getopt(argc, argv, "p:")) != -1) { + switch(ch) { + case 'p': + port = optarg; + break; + default: + return usage(argv[0]); + } + } + + return run_server(); +} diff --git a/release/src/router/uqmi/libubox/jshn.c b/release/src/router/uqmi/libubox/jshn.c new file mode 100644 index 0000000000..431e1b3eb5 --- /dev/null +++ b/release/src/router/uqmi/libubox/jshn.c @@ -0,0 +1,308 @@ +/* + * Copyright (C) 2011-2013 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifdef JSONC + #include +#else + #include +#endif + +#include +#include +#include +#include +#include +#include +#include "list.h" + +#include "blob.h" +#include "blobmsg_json.h" + +#define MAX_VARLEN 256 + +static struct blob_buf b = { 0 }; + +static const char *var_prefix = ""; +static int var_prefix_len = 0; + +static int add_json_element(const char *key, json_object *obj); + +static int add_json_object(json_object *obj) +{ + int ret = 0; + + json_object_object_foreach(obj, key, val) { + ret = add_json_element(key, val); + if (ret) + break; + } + return ret; +} + +static int add_json_array(struct array_list *a) +{ + char seq[12]; + int i, len; + int ret; + + for (i = 0, len = array_list_length(a); i < len; i++) { + sprintf(seq, "%d", i); + ret = add_json_element(seq, array_list_get_idx(a, i)); + if (ret) + return ret; + } + + return 0; +} + +static void add_json_string(const char *str) +{ + char *ptr = (char *) str; + int len; + char *c; + + while ((c = strchr(ptr, '\'')) != NULL) { + len = c - ptr; + if (len > 0) + fwrite(ptr, len, 1, stdout); + ptr = c + 1; + c = "'\\''"; + fwrite(c, strlen(c), 1, stdout); + } + len = strlen(ptr); + if (len > 0) + fwrite(ptr, len, 1, stdout); +} + +static void write_key_string(const char *key) +{ + while (*key) { + putc(isalnum(*key) ? *key : '_', stdout); + key++; + } +} + +static int add_json_element(const char *key, json_object *obj) +{ + char *type; + + if (!obj) + return -1; + + switch (json_object_get_type(obj)) { + case json_type_object: + type = "object"; + break; + case json_type_array: + type = "array"; + break; + case json_type_string: + type = "string"; + break; + case json_type_boolean: + type = "boolean"; + break; + case json_type_int: + type = "int"; + break; + case json_type_double: + type = "double"; + break; + default: + return -1; + } + + fprintf(stdout, "json_add_%s '", type); + write_key_string(key); + + switch (json_object_get_type(obj)) { + case json_type_object: + fprintf(stdout, "';\n"); + add_json_object(obj); + fprintf(stdout, "json_close_object;\n"); + break; + case json_type_array: + fprintf(stdout, "';\n"); + add_json_array(json_object_get_array(obj)); + fprintf(stdout, "json_close_array;\n"); + break; + case json_type_string: + fprintf(stdout, "' '"); + add_json_string(json_object_get_string(obj)); + fprintf(stdout, "';\n"); + break; + case json_type_boolean: + fprintf(stdout, "' %d;\n", json_object_get_boolean(obj)); + break; + case json_type_int: + fprintf(stdout, "' %d;\n", json_object_get_int(obj)); + break; + case json_type_double: + fprintf(stdout, "' %lf;\n", json_object_get_double(obj)); + break; + default: + return -1; + } + + return 0; +} + +static int jshn_parse(const char *str) +{ + json_object *obj; + + obj = json_tokener_parse(str); + if (!obj || json_object_get_type(obj) != json_type_object) { + fprintf(stderr, "Failed to parse message data\n"); + return 1; + } + fprintf(stdout, "json_init;\n"); + add_json_object(obj); + fflush(stdout); + + return 0; +} + +static char *get_keys(const char *prefix) +{ + char *keys; + + keys = alloca(var_prefix_len + strlen(prefix) + sizeof("K_") + 1); + sprintf(keys, "%sK_%s", var_prefix, prefix); + return getenv(keys); +} + +static void get_var(const char *prefix, const char **name, char **var, char **type) +{ + char *tmpname, *varname; + + tmpname = alloca(var_prefix_len + strlen(prefix) + 1 + strlen(*name) + 1 + sizeof("T_")); + + sprintf(tmpname, "%s%s_%s", var_prefix, prefix, *name); + *var = getenv(tmpname); + + sprintf(tmpname, "%sT_%s_%s", var_prefix, prefix, *name); + *type = getenv(tmpname); + + sprintf(tmpname, "%sN_%s_%s", var_prefix, prefix, *name); + varname = getenv(tmpname); + if (varname) + *name = varname; +} + +static json_object *jshn_add_objects(json_object *obj, const char *prefix, bool array); + +static void jshn_add_object_var(json_object *obj, bool array, const char *prefix, const char *name) +{ + json_object *new; + char *var, *type; + + get_var(prefix, &name, &var, &type); + if (!var || !type) + return; + + if (!strcmp(type, "array")) { + new = json_object_new_array(); + jshn_add_objects(new, var, true); + } else if (!strcmp(type, "object")) { + new = json_object_new_object(); + jshn_add_objects(new, var, false); + } else if (!strcmp(type, "string")) { + new = json_object_new_string(var); + } else if (!strcmp(type, "int")) { + new = json_object_new_int(atoi(var)); + } else if (!strcmp(type, "double")) { + new = json_object_new_double(strtod(var, NULL)); + } else if (!strcmp(type, "boolean")) { + new = json_object_new_boolean(!!atoi(var)); + } else { + return; + } + + if (array) + json_object_array_add(obj, new); + else + json_object_object_add(obj, name, new); +} + +static json_object *jshn_add_objects(json_object *obj, const char *prefix, bool array) +{ + char *keys, *key, *brk; + + keys = get_keys(prefix); + if (!keys || !obj) + goto out; + + for (key = strtok_r(keys, " ", &brk); key; + key = strtok_r(NULL, " ", &brk)) { + jshn_add_object_var(obj, array, prefix, key); + } + +out: + return obj; +} + +static int jshn_format(bool no_newline, bool indent) +{ + json_object *obj; + const char *output; + + obj = json_object_new_object(); + jshn_add_objects(obj, "J_V", false); + output = json_object_to_json_string(obj); + if (indent) { + blob_buf_init(&b, 0); + blobmsg_add_json_from_string(&b, output); + output = blobmsg_format_json_indent(b.head, 1, 0); + } + fprintf(stdout, "%s%s", output, no_newline ? "" : "\n"); + json_object_put(obj); + return 0; +} + +static int usage(const char *progname) +{ + fprintf(stderr, "Usage: %s [-n] [-i] -r |-w\n", progname); + return 2; +} + +int main(int argc, char **argv) +{ + bool no_newline = false; + bool indent = false; + int ch; + + while ((ch = getopt(argc, argv, "p:nir:w")) != -1) { + switch(ch) { + case 'p': + var_prefix = optarg; + var_prefix_len = strlen(var_prefix); + break; + case 'r': + return jshn_parse(optarg); + case 'w': + return jshn_format(no_newline, indent); + case 'n': + no_newline = true; + break; + case 'i': + indent = true; + break; + default: + return usage(argv[0]); + } + } + return usage(argv[0]); +} diff --git a/release/src/router/uqmi/libubox/json_script.c b/release/src/router/uqmi/libubox/json_script.c new file mode 100644 index 0000000000..0ec7b382ad --- /dev/null +++ b/release/src/router/uqmi/libubox/json_script.c @@ -0,0 +1,651 @@ +/* + * Copyright (C) 2013 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include + +#include "avl-cmp.h" +#include "json_script.h" + +struct json_call { + struct json_script_ctx *ctx; + struct blob_attr *vars; + unsigned int seq; +}; + +struct json_handler { + const char *name; + int (*cb)(struct json_call *call, struct blob_attr *cur); +}; + +static int json_process_expr(struct json_call *call, struct blob_attr *cur); +static int json_process_cmd(struct json_call *call, struct blob_attr *cur); + +struct json_script_file * +json_script_file_from_blobmsg(const char *name, void *data, int len) +{ + struct json_script_file *f; + char *new_name; + int name_len = 0; + + if (name) + name_len = strlen(name) + 1; + + f = calloc_a(sizeof(*f) + len, &new_name, name_len); + memcpy(f->data, data, len); + if (name) + f->avl.key = strcpy(new_name, name); + + return f; +} + +static struct json_script_file * +json_script_get_file(struct json_script_ctx *ctx, const char *filename) +{ + struct json_script_file *f; + + f = avl_find_element(&ctx->files, filename, f, avl); + if (f) + return f; + + f = ctx->handle_file(ctx, filename); + if (!f) + return NULL; + + avl_insert(&ctx->files, &f->avl); + return f; +} + +static void __json_script_run(struct json_call *call, struct json_script_file *file, + struct blob_attr *context) +{ + struct json_script_ctx *ctx = call->ctx; + + if (file->seq == call->seq) { + if (context) + ctx->handle_error(ctx, "Recursive include", context); + + return; + } + + file->seq = call->seq; + while (file) { + json_process_cmd(call, file->data); + file = file->next; + } +} + +const char *json_script_find_var(struct json_script_ctx *ctx, struct blob_attr *vars, + const char *name) +{ + struct blob_attr *cur; + int rem; + + blobmsg_for_each_attr(cur, vars, rem) { + if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) + continue; + + if (strcmp(blobmsg_name(cur), name) != 0) + continue; + + return blobmsg_data(cur); + } + + return ctx->handle_var(ctx, name, vars); +} + +static const char * +msg_find_var(struct json_call *call, const char *name) +{ + return json_script_find_var(call->ctx, call->vars, name); +} + +static void +json_get_tuple(struct blob_attr *cur, struct blob_attr **tb, int t1, int t2) +{ + static struct blobmsg_policy expr_tuple[3] = { + { .type = BLOBMSG_TYPE_STRING }, + {}, + {}, + }; + + expr_tuple[1].type = t1; + expr_tuple[2].type = t2; + blobmsg_parse_array(expr_tuple, 3, tb, blobmsg_data(cur), blobmsg_data_len(cur)); +} + +static int handle_if(struct json_call *call, struct blob_attr *expr) +{ + struct blob_attr *tb[4]; + int ret; + + static const struct blobmsg_policy if_tuple[4] = { + { .type = BLOBMSG_TYPE_STRING }, + { .type = BLOBMSG_TYPE_ARRAY }, + { .type = BLOBMSG_TYPE_ARRAY }, + { .type = BLOBMSG_TYPE_ARRAY }, + }; + + blobmsg_parse_array(if_tuple, 4, tb, blobmsg_data(expr), blobmsg_data_len(expr)); + + if (!tb[1] || !tb[2]) + return 0; + + ret = json_process_expr(call, tb[1]); + if (ret < 0) + return 0; + + if (ret) + return json_process_cmd(call, tb[2]); + + if (!tb[3]) + return 0; + + return json_process_cmd(call, tb[3]); +} + +static int handle_case(struct json_call *call, struct blob_attr *expr) +{ + struct blob_attr *tb[3], *cur; + const char *var; + int rem; + + json_get_tuple(expr, tb, BLOBMSG_TYPE_STRING, BLOBMSG_TYPE_TABLE); + if (!tb[1] || !tb[2]) + return 0; + + var = msg_find_var(call, blobmsg_data(tb[1])); + if (!var) + return 0; + + blobmsg_for_each_attr(cur, tb[2], rem) { + if (!strcmp(var, blobmsg_name(cur))) + return json_process_cmd(call, cur); + } + + return 0; +} + +static int handle_return(struct json_call *call, struct blob_attr *expr) +{ + return -2; +} + +static int handle_include(struct json_call *call, struct blob_attr *expr) +{ + struct blob_attr *tb[3]; + struct json_script_file *f; + + json_get_tuple(expr, tb, BLOBMSG_TYPE_STRING, 0); + if (!tb[1]) + return 0; + + f = json_script_get_file(call->ctx, blobmsg_data(tb[1])); + if (!f) + return 0; + + __json_script_run(call, f, expr); + return 0; +} + +static const struct json_handler cmd[] = { + { "if", handle_if }, + { "case", handle_case }, + { "return", handle_return }, + { "include", handle_include }, +}; + +static int eq_regex_cmp(const char *str, const char *pattern, bool regex) +{ + regex_t reg; + int ret; + + if (!regex) + return !strcmp(str, pattern); + + if (regcomp(®, pattern, REG_EXTENDED | REG_NOSUB)) + return 0; + + ret = !regexec(®, str, 0, NULL, 0); + regfree(®); + + return ret; +} + +static int expr_eq_regex(struct json_call *call, struct blob_attr *expr, bool regex) +{ + struct json_script_ctx *ctx = call->ctx; + struct blob_attr *tb[3], *cur; + const char *var; + int rem; + + json_get_tuple(expr, tb, BLOBMSG_TYPE_STRING, 0); + if (!tb[1] || !tb[2]) + return -1; + + var = msg_find_var(call, blobmsg_data(tb[1])); + if (!var) + return 0; + + switch(blobmsg_type(tb[2])) { + case BLOBMSG_TYPE_STRING: + return eq_regex_cmp(var, blobmsg_data(tb[2]), regex); + case BLOBMSG_TYPE_ARRAY: + blobmsg_for_each_attr(cur, tb[2], rem) { + if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) { + ctx->handle_error(ctx, "Unexpected element type", cur); + return -1; + } + + if (eq_regex_cmp(var, blobmsg_data(cur), regex)) + return 1; + } + return 0; + default: + ctx->handle_error(ctx, "Unexpected element type", tb[2]); + return -1; + } +} + +static int handle_expr_eq(struct json_call *call, struct blob_attr *expr) +{ + return expr_eq_regex(call, expr, false); +} + +static int handle_expr_regex(struct json_call *call, struct blob_attr *expr) +{ + return expr_eq_regex(call, expr, true); +} + +static int handle_expr_has(struct json_call *call, struct blob_attr *expr) +{ + struct json_script_ctx *ctx = call->ctx; + struct blob_attr *tb[3], *cur; + int rem; + + json_get_tuple(expr, tb, 0, 0); + if (!tb[1]) + return -1; + + switch(blobmsg_type(tb[1])) { + case BLOBMSG_TYPE_STRING: + return !!msg_find_var(call, blobmsg_data(tb[1])); + case BLOBMSG_TYPE_ARRAY: + blobmsg_for_each_attr(cur, tb[1], rem) { + if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) { + ctx->handle_error(ctx, "Unexpected element type", cur); + return -1; + } + + if (msg_find_var(call, blobmsg_data(cur))) + return 1; + } + return 0; + default: + ctx->handle_error(ctx, "Unexpected element type", tb[1]); + return -1; + } +} + +static int expr_and_or(struct json_call *call, struct blob_attr *expr, bool and) +{ + struct blob_attr *cur; + int ret, rem; + int i = 0; + + blobmsg_for_each_attr(cur, expr, rem) { + if (i++ < 1) + continue; + + ret = json_process_expr(call, cur); + if (ret < 0) + return ret; + + if (ret != and) + return ret; + } + + return and; +} + +static int handle_expr_and(struct json_call *call, struct blob_attr *expr) +{ + return expr_and_or(call, expr, 1); +} + +static int handle_expr_or(struct json_call *call, struct blob_attr *expr) +{ + return expr_and_or(call, expr, 0); +} + +static int handle_expr_not(struct json_call *call, struct blob_attr *expr) +{ + struct blob_attr *tb[3]; + + json_get_tuple(expr, tb, BLOBMSG_TYPE_ARRAY, 0); + if (!tb[1]) + return -1; + + return json_process_expr(call, tb[1]); +} + +static const struct json_handler expr[] = { + { "eq", handle_expr_eq }, + { "regex", handle_expr_regex }, + { "has", handle_expr_has }, + { "and", handle_expr_and }, + { "or", handle_expr_or }, + { "not", handle_expr_not }, +}; + +static int +__json_process_type(struct json_call *call, struct blob_attr *cur, + const struct json_handler *h, int n, bool *found) +{ + const char *name = blobmsg_data(blobmsg_data(cur)); + int i; + + for (i = 0; i < n; i++) { + if (strcmp(name, h[i].name) != 0) + continue; + + *found = true; + return h[i].cb(call, cur); + } + + *found = false; + return -1; +} + +static int json_process_expr(struct json_call *call, struct blob_attr *cur) +{ + struct json_script_ctx *ctx = call->ctx; + bool found; + int ret; + + if (blobmsg_type(cur) != BLOBMSG_TYPE_ARRAY || + blobmsg_type(blobmsg_data(cur)) != BLOBMSG_TYPE_STRING) { + ctx->handle_error(ctx, "Unexpected element type", cur); + return -1; + } + + ret = __json_process_type(call, cur, expr, ARRAY_SIZE(expr), &found); + if (!found) + ctx->handle_error(ctx, "Unknown expression type", cur); + + return ret; +} + +static int eval_string(struct json_call *call, struct blob_buf *buf, const char *name, const char *pattern) +{ + char *dest, *next, *str; + int len = 0; + bool var = false; + char c = '%'; + + dest = blobmsg_alloc_string_buffer(buf, name, 1); + next = alloca(strlen(pattern) + 1); + strcpy(next, pattern); + + for (str = next; str; str = next) { + const char *cur; + char *end; + int cur_len = 0; + bool cur_var = var; + + end = strchr(str, '%'); + if (end) { + *end = 0; + next = end + 1; + var = !var; + } else { + end = str + strlen(str); + next = NULL; + } + + if (cur_var) { + if (next > str) { + cur = msg_find_var(call, str); + if (!cur) + continue; + + cur_len = strlen(cur); + } else { + cur = &c; + cur_len = 1; + } + } else { + if (str == end) + continue; + + cur = str; + cur_len = end - str; + } + + dest = blobmsg_realloc_string_buffer(buf, cur_len + 1); + memcpy(dest + len, cur, cur_len); + len += cur_len; + } + + dest[len] = 0; + blobmsg_add_string_buffer(buf); + + if (var) + return -1; + + return 0; +} + +static int cmd_add_string(struct json_call *call, const char *pattern) +{ + return eval_string(call, &call->ctx->buf, NULL, pattern); +} + +int json_script_eval_string(struct json_script_ctx *ctx, struct blob_attr *vars, + struct blob_buf *buf, const char *name, + const char *pattern) +{ + struct json_call call = { + .ctx = ctx, + .vars = vars, + }; + + return eval_string(&call, buf, name, pattern); +} + +static int cmd_process_strings(struct json_call *call, struct blob_attr *attr) +{ + struct json_script_ctx *ctx = call->ctx; + struct blob_attr *cur; + int args = -1; + int rem, ret; + void *c; + + blob_buf_init(&ctx->buf, 0); + c = blobmsg_open_array(&ctx->buf, NULL); + blobmsg_for_each_attr(cur, attr, rem) { + if (args++ < 0) + continue; + + if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) { + ctx->handle_error(ctx, "Invalid argument in command", attr); + return -1; + } + + ret = cmd_add_string(call, blobmsg_data(cur)); + if (ret) { + ctx->handle_error(ctx, "Unterminated variable reference in string", attr); + return ret; + } + } + + blobmsg_close_array(&ctx->buf, c); + + return 0; +} + +static int __json_process_cmd(struct json_call *call, struct blob_attr *cur) +{ + struct json_script_ctx *ctx = call->ctx; + const char *name; + bool found; + int ret; + + if (blobmsg_type(cur) != BLOBMSG_TYPE_ARRAY || + blobmsg_type(blobmsg_data(cur)) != BLOBMSG_TYPE_STRING) { + ctx->handle_error(ctx, "Unexpected element type", cur); + return -1; + } + + ret = __json_process_type(call, cur, cmd, ARRAY_SIZE(cmd), &found); + if (found) + return ret; + + name = blobmsg_data(blobmsg_data(cur)); + ret = cmd_process_strings(call, cur); + if (ret) + return ret; + + ctx->handle_command(ctx, name, blob_data(ctx->buf.head), call->vars); + + return 0; +} + +static int json_process_cmd(struct json_call *call, struct blob_attr *block) +{ + struct json_script_ctx *ctx = call->ctx; + struct blob_attr *cur; + int rem; + int ret; + int i = 0; + + if (blobmsg_type(block) != BLOBMSG_TYPE_ARRAY) { + ctx->handle_error(ctx, "Unexpected element type", block); + return -1; + } + + blobmsg_for_each_attr(cur, block, rem) { + switch(blobmsg_type(cur)) { + case BLOBMSG_TYPE_STRING: + if (!i) + return __json_process_cmd(call, block); + default: + ret = json_process_cmd(call, cur); + if (ret < -1) + return ret; + break; + } + i++; + } + + return 0; +} + +void json_script_run_file(struct json_script_ctx *ctx, struct json_script_file *file, + struct blob_attr *vars) +{ + static unsigned int _seq = 0; + struct json_call call = { + .ctx = ctx, + .vars = vars, + .seq = ++_seq, + }; + + /* overflow */ + if (!call.seq) + call.seq = ++_seq; + + __json_script_run(&call, file, NULL); +} + +void json_script_run(struct json_script_ctx *ctx, const char *name, + struct blob_attr *vars) +{ + struct json_script_file *file; + + file = json_script_get_file(ctx, name); + if (!file) + return; + + json_script_run_file(ctx, file, vars); +} + +static void __json_script_file_free(struct json_script_file *f) +{ + struct json_script_file *next; + + if (!f) + return; + + next = f->next; + free(f); + + if (next) + return __json_script_file_free(next); +} + +void +json_script_free(struct json_script_ctx *ctx) +{ + struct json_script_file *f, *next; + + avl_remove_all_elements(&ctx->files, f, avl, next) + __json_script_file_free(f); + + blob_buf_free(&ctx->buf); +} + +static void +__default_handle_error(struct json_script_ctx *ctx, const char *msg, + struct blob_attr *context) +{ +} + +static const char * +__default_handle_var(struct json_script_ctx *ctx, const char *name, + struct blob_attr *vars) +{ + return NULL; +} + +static int +__default_handle_expr(struct json_script_ctx *ctx, const char *name, + struct blob_attr *expr, struct blob_attr *vars) +{ + return -1; +} + +static struct json_script_file * +__default_handle_file(struct json_script_ctx *ctx, const char *name) +{ + return NULL; +} + +void json_script_init(struct json_script_ctx *ctx) +{ + avl_init(&ctx->files, avl_strcmp, false, NULL); + + if (!ctx->handle_error) + ctx->handle_error = __default_handle_error; + + if (!ctx->handle_var) + ctx->handle_var = __default_handle_var; + + if (!ctx->handle_expr) + ctx->handle_expr = __default_handle_expr; + + if (!ctx->handle_file) + ctx->handle_file = __default_handle_file; +} diff --git a/release/src/router/uqmi/libubox/json_script.h b/release/src/router/uqmi/libubox/json_script.h new file mode 100644 index 0000000000..9475baa595 --- /dev/null +++ b/release/src/router/uqmi/libubox/json_script.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2013 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __JSON_SCRIPT_H +#define __JSON_SCRIPT_H + +#include "avl.h" +#include "blob.h" +#include "blobmsg.h" +#include "utils.h" + +struct json_script_file; + +struct json_script_ctx { + struct avl_tree files; + struct blob_buf buf; + + uint32_t run_seq; + + /* + * handle_command: handle a command that was not recognized by the + * json_script core (required) + * + * @cmd: blobmsg container of the processed command + * @vars: blobmsg container of current run variables + */ + void (*handle_command)(struct json_script_ctx *ctx, const char *name, + struct blob_attr *cmd, struct blob_attr *vars); + + /* + * handle_expr: handle an expression that was not recognized by the + * json_script core (optional) + * + * @expr: blobmsg container of the processed expression + * @vars: blobmsg container of current runtime variables + */ + int (*handle_expr)(struct json_script_ctx *ctx, const char *name, + struct blob_attr *expr, struct blob_attr *vars); + + /* + * handle_var - look up a variable that's not part of the runtime + * variable set (optional) + */ + const char *(*handle_var)(struct json_script_ctx *ctx, const char *name, + struct blob_attr *vars); + + /* + * handle_file - load a file by filename (optional) + * + * in case of wildcards, it can return a chain of json_script files + * linked via the ::next pointer. Only the first json_script file is + * added to the tree. + */ + struct json_script_file *(*handle_file)(struct json_script_ctx *ctx, + const char *name); + + /* + * handle_error - handle a processing error in a command or expression + * (optional) + * + * @msg: error message + * @context: source file context of the error (blobmsg container) + */ + void (*handle_error)(struct json_script_ctx *ctx, const char *msg, + struct blob_attr *context); +}; + +struct json_script_file { + struct avl_node avl; + struct json_script_file *next; + + unsigned int seq; + struct blob_attr data[]; +}; + +void json_script_init(struct json_script_ctx *ctx); +void json_script_free(struct json_script_ctx *ctx); + +/* + * json_script_run - run a json script with a set of runtime variables + * + * @filename: initial filename to run + * @vars: blobmsg container of the current runtime variables + */ +void json_script_run(struct json_script_ctx *ctx, const char *filename, + struct blob_attr *vars); + +void json_script_run_file(struct json_script_ctx *ctx, struct json_script_file *file, + struct blob_attr *vars); +/* + * json_script_eval_string - evaluate a string and store the result + * + * Can be used to process variable references outside of a script + * in a same way that they would be interpreted in the script context. + */ +int json_script_eval_string(struct json_script_ctx *ctx, struct blob_attr *vars, + struct blob_buf *buf, const char *name, + const char *pattern); + +struct json_script_file * +json_script_file_from_blobmsg(const char *name, void *data, int len); + +/* + * json_script_find_var - helper function to find a runtime variable from + * the list passed by json_script user. + * It is intended to be used by the .handle_var callback + */ +const char *json_script_find_var(struct json_script_ctx *ctx, struct blob_attr *vars, + const char *name); + +#endif diff --git a/release/src/router/uqmi/libubox/kvlist.c b/release/src/router/uqmi/libubox/kvlist.c new file mode 100644 index 0000000000..e0a8acb002 --- /dev/null +++ b/release/src/router/uqmi/libubox/kvlist.c @@ -0,0 +1,96 @@ +/* + * kvlist - simple key/value store + * + * Copyright (C) 2014 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include + +#include "utils.h" +#include "avl-cmp.h" +#include "blob.h" + +#include "kvlist.h" + +int kvlist_strlen(struct kvlist *kv, const void *data) +{ + return strlen(data) + 1; +} + +int kvlist_blob_len(struct kvlist *kv, const void *data) +{ + return blob_pad_len(data); +} + +void kvlist_init(struct kvlist *kv, int (*get_len)(struct kvlist *kv, const void *data)) +{ + avl_init(&kv->avl, avl_strcmp, false, NULL); + kv->get_len = get_len; +} + +static struct kvlist_node *__kvlist_get(struct kvlist *kv, const char *name) +{ + struct kvlist_node *node; + + return avl_find_element(&kv->avl, name, node, avl); +} + +void *kvlist_get(struct kvlist *kv, const char *name) +{ + struct kvlist_node *node; + + node = __kvlist_get(kv, name); + if (!node) + return NULL; + + return node->data; +} + +bool kvlist_delete(struct kvlist *kv, const char *name) +{ + struct kvlist_node *node; + + node = __kvlist_get(kv, name); + if (node) { + avl_delete(&kv->avl, &node->avl); + free(node); + } + + return !!node; +} + +void kvlist_set(struct kvlist *kv, const char *name, const void *data) +{ + struct kvlist_node *node; + char *name_buf; + int len = kv->get_len(kv, data); + + kvlist_delete(kv, name); + + node = calloc_a(sizeof(struct kvlist_node) + len, + &name_buf, strlen(name) + 1); + memcpy(node->data, data, len); + + node->avl.key = strcpy(name_buf, name); + avl_insert(&kv->avl, &node->avl); +} + +void kvlist_free(struct kvlist *kv) +{ + struct kvlist_node *node, *tmp; + + avl_remove_all_elements(&kv->avl, node, avl, tmp) + free(node); +} diff --git a/release/src/router/uqmi/libubox/kvlist.h b/release/src/router/uqmi/libubox/kvlist.h new file mode 100644 index 0000000000..0d35b46a5f --- /dev/null +++ b/release/src/router/uqmi/libubox/kvlist.h @@ -0,0 +1,54 @@ +/* + * kvlist - simple key/value store + * + * Copyright (C) 2014 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __LIBUBOX_KVLIST_H +#define __LIBUBOX_KVLIST_H + +#include "avl.h" + +struct kvlist { + struct avl_tree avl; + + int (*get_len)(struct kvlist *kv, const void *data); +}; + +struct kvlist_node { + struct avl_node avl; + + char data[0] __attribute__((aligned(4))); +}; + +#define __ptr_to_kv(_ptr) container_of(((char *) (_ptr)), struct kvlist_node, data[0]) +#define __avl_list_to_kv(_l) container_of(_l, struct kvlist_node, avl.list) + +#define kvlist_for_each(kv, name, value) \ + for (value = (void *) __avl_list_to_kv((kv)->avl.list_head.next)->data, \ + name = (const char *) __ptr_to_kv(value)->avl.key, (void) name; \ + &__ptr_to_kv(value)->avl.list != &(kv)->avl.list_head; \ + value = (void *) (__avl_list_to_kv(__ptr_to_kv(value)->avl.list.next))->data, \ + name = (const char *) __ptr_to_kv(value)->avl.key) + +void kvlist_init(struct kvlist *kv, int (*get_len)(struct kvlist *kv, const void *data)); +void kvlist_free(struct kvlist *kv); +void *kvlist_get(struct kvlist *kv, const char *name); +void kvlist_set(struct kvlist *kv, const char *name, const void *data); +bool kvlist_delete(struct kvlist *kv, const char *name); + +int kvlist_strlen(struct kvlist *kv, const void *data); +int kvlist_blob_len(struct kvlist *kv, const void *data); + +#endif diff --git a/release/src/router/uqmi/libubox/list.h b/release/src/router/uqmi/libubox/list.h new file mode 100644 index 0000000000..ab52acff2f --- /dev/null +++ b/release/src/router/uqmi/libubox/list.h @@ -0,0 +1,208 @@ +/*- + * Copyright (c) 2011 Felix Fietkau + * Copyright (c) 2010 Isilon Systems, Inc. + * Copyright (c) 2010 iX Systems, Inc. + * Copyright (c) 2010 Panasas, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _LINUX_LIST_H_ +#define _LINUX_LIST_H_ + +#include +#include + +#define prefetch(x) + +#ifndef container_of +#define container_of(ptr, type, member) \ + ({ \ + const typeof(((type *) NULL)->member) *__mptr = (ptr); \ + (type *) ((char *) __mptr - offsetof(type, member)); \ + }) +#endif + +struct list_head { + struct list_head *next; + struct list_head *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } +#undef LIST_HEAD +#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name) + +static inline void +INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list->prev = list; +} + +static inline bool +list_empty(const struct list_head *head) +{ + return (head->next == head); +} + +static inline bool +list_is_first(const struct list_head *list, + const struct list_head *head) +{ + return list->prev == head; +} + +static inline bool +list_is_last(const struct list_head *list, + const struct list_head *head) +{ + return list->next == head; +} + +static inline void +_list_del(struct list_head *entry) +{ + entry->next->prev = entry->prev; + entry->prev->next = entry->next; +} + +static inline void +list_del(struct list_head *entry) +{ + _list_del(entry); + entry->next = entry->prev = NULL; +} + +static inline void +_list_add(struct list_head *_new, struct list_head *prev, + struct list_head *next) +{ + + next->prev = _new; + _new->next = next; + _new->prev = prev; + prev->next = _new; +} + +static inline void +list_del_init(struct list_head *entry) +{ + _list_del(entry); + INIT_LIST_HEAD(entry); +} + +#define list_entry(ptr, type, field) container_of(ptr, type, field) +#define list_first_entry(ptr, type, field) list_entry((ptr)->next, type, field) +#define list_last_entry(ptr, type, field) list_entry((ptr)->prev, type, field) + +#define list_for_each(p, head) \ + for (p = (head)->next; p != (head); p = p->next) + +#define list_for_each_safe(p, n, head) \ + for (p = (head)->next, n = p->next; p != (head); p = n, n = p->next) + +#define list_for_each_entry(p, h, field) \ + for (p = list_first_entry(h, typeof(*p), field); &p->field != (h); \ + p = list_entry(p->field.next, typeof(*p), field)) + +#define list_for_each_entry_safe(p, n, h, field) \ + for (p = list_first_entry(h, typeof(*p), field), \ + n = list_entry(p->field.next, typeof(*p), field); &p->field != (h);\ + p = n, n = list_entry(n->field.next, typeof(*n), field)) + +#define list_for_each_entry_reverse(p, h, field) \ + for (p = list_last_entry(h, typeof(*p), field); &p->field != (h); \ + p = list_entry(p->field.prev, typeof(*p), field)) + +#define list_for_each_prev(p, h) for (p = (h)->prev; p != (h); p = p->prev) +#define list_for_each_prev_safe(p, n, h) for (p = (h)->prev, n = p->prev; p != (h); p = n, n = p->prev) + +static inline void +list_add(struct list_head *_new, struct list_head *head) +{ + _list_add(_new, head, head->next); +} + +static inline void +list_add_tail(struct list_head *_new, struct list_head *head) +{ + _list_add(_new, head->prev, head); +} + +static inline void +list_move(struct list_head *list, struct list_head *head) +{ + _list_del(list); + list_add(list, head); +} + +static inline void +list_move_tail(struct list_head *entry, struct list_head *head) +{ + _list_del(entry); + list_add_tail(entry, head); +} + +static inline void +_list_splice(const struct list_head *list, struct list_head *prev, + struct list_head *next) +{ + struct list_head *first; + struct list_head *last; + + if (list_empty(list)) + return; + + first = list->next; + last = list->prev; + first->prev = prev; + prev->next = first; + last->next = next; + next->prev = last; +} + +static inline void +list_splice(const struct list_head *list, struct list_head *head) +{ + _list_splice(list, head, head->next); +} + +static inline void +list_splice_tail(struct list_head *list, struct list_head *head) +{ + _list_splice(list, head->prev, head); +} + +static inline void +list_splice_init(struct list_head *list, struct list_head *head) +{ + _list_splice(list, head, head->next); + INIT_LIST_HEAD(list); +} + +static inline void +list_splice_tail_init(struct list_head *list, struct list_head *head) +{ + _list_splice(list, head->prev, head); + INIT_LIST_HEAD(list); +} + +#endif /* _LINUX_LIST_H_ */ diff --git a/release/src/router/uqmi/libubox/lua/CMakeLists.txt b/release/src/router/uqmi/libubox/lua/CMakeLists.txt new file mode 100644 index 0000000000..04abe0caa0 --- /dev/null +++ b/release/src/router/uqmi/libubox/lua/CMakeLists.txt @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 2.6) + +PROJECT(uloop C) + +SET(CMAKE_INSTALL_PREFIX /) + +IF(NOT LUA_CFLAGS) + FIND_PROGRAM(PKG_CONFIG pkg-config) + IF(PKG_CONFIG) + EXECUTE_PROCESS( + COMMAND pkg-config --silence-errors --cflags lua5.1 + OUTPUT_VARIABLE LUA_CFLAGS + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + ENDIF() +ENDIF() + +ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu99 -g3 -I.. ${LUA_CFLAGS}) +LINK_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/..) + +IF(APPLE) + ADD_DEFINITIONS(-I/opt/local/include) + SET(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -undefined dynamic_lookup") +ENDIF(APPLE) + +IF(NOT LUAPATH) + EXECUTE_PROCESS( + COMMAND lua -e "for k in string.gmatch(package.cpath .. \";\", \"([^;]+)/..so;\") do if k:sub(1,1) == \"/\" then print(k) break end end" + OUTPUT_VARIABLE LUAPATH + RESULT_VARIABLE LUA_CHECK_RES + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + IF(BUILD_LUA) + IF(NOT ${LUA_CHECK_RES} EQUAL 0 OR "${LUAPATH}" EQUAL "") + MESSAGE(SEND_ERROR "Lua was not found on your system") + ENDIF() + ENDIF() +ENDIF() + +IF(BUILD_LUA) + ADD_LIBRARY(uloop_lua MODULE uloop.c) + SET_TARGET_PROPERTIES(uloop_lua PROPERTIES + OUTPUT_NAME uloop + PREFIX "" + ) + TARGET_LINK_LIBRARIES(uloop_lua ubox) + + INSTALL(TARGETS uloop_lua + LIBRARY DESTINATION ${LUAPATH} + ) +ENDIF() diff --git a/release/src/router/uqmi/libubox/lua/uloop.c b/release/src/router/uqmi/libubox/lua/uloop.c new file mode 100644 index 0000000000..2a0a516b5e --- /dev/null +++ b/release/src/router/uqmi/libubox/lua/uloop.c @@ -0,0 +1,419 @@ +/* + * Copyright (C) 2012 John Crispin + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include +#include +#include + +#include +#include +#include + +#include "../uloop.h" +#include "../list.h" + +struct lua_uloop_fd { + struct uloop_fd fd; + int r; + int fd_r; +}; + +struct lua_uloop_timeout { + struct uloop_timeout t; + int r; +}; + +struct lua_uloop_process { + struct uloop_process p; + int r; +}; + +static lua_State *state; + +static void ul_timer_cb(struct uloop_timeout *t) +{ + struct lua_uloop_timeout *tout = container_of(t, struct lua_uloop_timeout, t); + + lua_getglobal(state, "__uloop_cb"); + lua_rawgeti(state, -1, tout->r); + lua_remove(state, -2); + + lua_call(state, 0, 0); + +} + +static int ul_timer_set(lua_State *L) +{ + struct lua_uloop_timeout *tout; + double set; + + if (!lua_isnumber(L, -1)) { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + + return 0; + } + + set = lua_tointeger(L, -1); + tout = lua_touserdata(L, 1); + uloop_timeout_set(&tout->t, set); + + return 1; +} + +static int ul_timer_free(lua_State *L) +{ + struct lua_uloop_timeout *tout = lua_touserdata(L, 1); + + uloop_timeout_cancel(&tout->t); + + /* obj.__index.__gc = nil , make sure executing only once*/ + lua_getfield(L, -1, "__index"); + lua_pushstring(L, "__gc"); + lua_pushnil(L); + lua_settable(L, -3); + + lua_getglobal(state, "__uloop_cb"); + luaL_unref(state, -1, tout->r); + + return 1; +} + +static const luaL_Reg timer_m[] = { + { "set", ul_timer_set }, + { "cancel", ul_timer_free }, + { NULL, NULL } +}; + +static int ul_timer(lua_State *L) +{ + struct lua_uloop_timeout *tout; + int set = 0; + int ref; + + if (lua_isnumber(L, -1)) { + set = lua_tointeger(L, -1); + lua_pop(L, 1); + } + + if (!lua_isfunction(L, -1)) { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + + return 0; + } + + lua_getglobal(L, "__uloop_cb"); + lua_pushvalue(L, -2); + ref = luaL_ref(L, -2); + + tout = lua_newuserdata(L, sizeof(*tout)); + lua_createtable(L, 0, 2); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + lua_pushcfunction(L, ul_timer_free); + lua_setfield(L, -2, "__gc"); + lua_pushvalue(L, -1); + lua_setmetatable(L, -3); + lua_pushvalue(L, -2); + luaI_openlib(L, NULL, timer_m, 1); + lua_pushvalue(L, -2); + + memset(tout, 0, sizeof(*tout)); + + tout->r = ref; + tout->t.cb = ul_timer_cb; + if (set) + uloop_timeout_set(&tout->t, set); + + return 1; +} + +static void ul_ufd_cb(struct uloop_fd *fd, unsigned int events) +{ + struct lua_uloop_fd *ufd = container_of(fd, struct lua_uloop_fd, fd); + + lua_getglobal(state, "__uloop_cb"); + lua_rawgeti(state, -1, ufd->r); + lua_remove(state, -2); + + /* push fd object */ + lua_getglobal(state, "__uloop_fds"); + lua_rawgeti(state, -1, ufd->fd_r); + lua_remove(state, -2); + + /* push events */ + lua_pushinteger(state, events); + lua_call(state, 2, 0); +} + + +static int get_sock_fd(lua_State* L, int idx) { + int fd; + if(lua_isnumber(L, idx)) { + fd = lua_tonumber(L, idx); + } else { + luaL_checktype(L, idx, LUA_TUSERDATA); + lua_getfield(L, idx, "getfd"); + if(lua_isnil(L, -1)) + return luaL_error(L, "socket type missing 'getfd' method"); + lua_pushvalue(L, idx - 1); + lua_call(L, 1, 1); + fd = lua_tointeger(L, -1); + lua_pop(L, 1); + } + return fd; +} + +static int ul_ufd_delete(lua_State *L) +{ + struct lua_uloop_fd *ufd = lua_touserdata(L, 1); + + uloop_fd_delete(&ufd->fd); + + /* obj.__index.__gc = nil , make sure executing only once*/ + lua_getfield(L, -1, "__index"); + lua_pushstring(L, "__gc"); + lua_pushnil(L); + lua_settable(L, -3); + + lua_getglobal(state, "__uloop_cb"); + luaL_unref(state, -1, ufd->r); + lua_remove(state, -1); + + lua_getglobal(state, "__uloop_fds"); + luaL_unref(state, -1, ufd->fd_r); + lua_remove(state, -1); + + return 1; +} + +static const luaL_Reg ufd_m[] = { + { "delete", ul_ufd_delete }, + { NULL, NULL } +}; + +static int ul_ufd_add(lua_State *L) +{ + struct lua_uloop_fd *ufd; + int fd = 0; + unsigned int flags = 0; + int ref; + int fd_ref; + + if (lua_isnumber(L, -1)) { + flags = lua_tointeger(L, -1); + lua_pop(L, 1); + } + + if (!lua_isfunction(L, -1)) { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + + return 0; + } + + fd = get_sock_fd(L, -2); + + lua_getglobal(L, "__uloop_cb"); + lua_pushvalue(L, -2); + ref = luaL_ref(L, -2); + lua_pop(L, 1); + + lua_getglobal(L, "__uloop_fds"); + lua_pushvalue(L, -3); + fd_ref = luaL_ref(L, -2); + lua_pop(L, 1); + + ufd = lua_newuserdata(L, sizeof(*ufd)); + + lua_createtable(L, 0, 2); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + lua_pushcfunction(L, ul_ufd_delete); + lua_setfield(L, -2, "__gc"); + lua_pushvalue(L, -1); + lua_setmetatable(L, -3); + lua_pushvalue(L, -2); + luaI_openlib(L, NULL, ufd_m, 1); + lua_pushvalue(L, -2); + + memset(ufd, 0, sizeof(*ufd)); + + ufd->r = ref; + ufd->fd.fd = fd; + ufd->fd_r = fd_ref; + ufd->fd.cb = ul_ufd_cb; + if (flags) + uloop_fd_add(&ufd->fd, flags); + + return 1; +} + +static void ul_process_cb(struct uloop_process *p, int ret) +{ + struct lua_uloop_process *proc = container_of(p, struct lua_uloop_process, p); + + lua_getglobal(state, "__uloop_cb"); + lua_rawgeti(state, -1, proc->r); + + luaL_unref(state, -2, proc->r); + lua_remove(state, -2); + lua_pushinteger(state, ret >> 8); + lua_call(state, 1, 0); +} + +static int ul_process(lua_State *L) +{ + struct lua_uloop_process *proc; + pid_t pid; + int ref; + + if (!lua_isfunction(L, -1) || !lua_istable(L, -2) || + !lua_istable(L, -3) || !lua_isstring(L, -4)) { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + + return 0; + } + + pid = fork(); + + if (pid == -1) { + lua_pushstring(L, "failed to fork"); + lua_error(L); + + return 0; + } + + if (pid == 0) { + /* child */ + int argn = lua_objlen(L, -3); + int envn = lua_objlen(L, -2); + char** argp = malloc(sizeof(char*) * (argn + 2)); + char** envp = malloc(sizeof(char*) * envn + 1); + int i = 1; + + argp[0] = (char*) lua_tostring(L, -4); + for (i = 1; i <= argn; i++) { + lua_rawgeti(L, -3, i); + argp[i] = (char*) lua_tostring(L, -1); + lua_pop(L, 1); + } + argp[i] = NULL; + + for (i = 1; i <= envn; i++) { + lua_rawgeti(L, -2, i); + envp[i - 1] = (char*) lua_tostring(L, -1); + lua_pop(L, 1); + } + envp[i - 1] = NULL; + + execve(*argp, argp, envp); + exit(-1); + } + + lua_getglobal(L, "__uloop_cb"); + lua_pushvalue(L, -2); + ref = luaL_ref(L, -2); + + proc = lua_newuserdata(L, sizeof(*proc)); + memset(proc, 0, sizeof(*proc)); + + proc->r = ref; + proc->p.pid = pid; + proc->p.cb = ul_process_cb; + uloop_process_add(&proc->p); + + return 1; +} + +static int ul_init(lua_State *L) +{ + uloop_init(); + lua_pushboolean(L, 1); + + return 1; +} + +static int ul_run(lua_State *L) +{ + uloop_run(); + lua_pushboolean(L, 1); + + return 1; +} + +static int ul_end(lua_State *L) +{ + uloop_end(); + return 1; +} + +static luaL_reg uloop_func[] = { + {"init", ul_init}, + {"run", ul_run}, + {"timer", ul_timer}, + {"process", ul_process}, + {"fd_add", ul_ufd_add}, + {"cancel", ul_end}, + {NULL, NULL}, +}; + +/* avoid warnings about missing declarations */ +int luaopen_uloop(lua_State *L); +int luaclose_uloop(lua_State *L); + +int luaopen_uloop(lua_State *L) +{ + state = L; + + lua_createtable(L, 1, 0); + lua_setglobal(L, "__uloop_cb"); + + lua_createtable(L, 1, 0); + lua_setglobal(L, "__uloop_fds"); + + luaL_openlib(L, "uloop", uloop_func, 0); + lua_pushstring(L, "_VERSION"); + lua_pushstring(L, "1.0"); + lua_rawset(L, -3); + + lua_pushstring(L, "ULOOP_READ"); + lua_pushinteger(L, ULOOP_READ); + lua_rawset(L, -3); + + lua_pushstring(L, "ULOOP_WRITE"); + lua_pushinteger(L, ULOOP_WRITE); + lua_rawset(L, -3); + + lua_pushstring(L, "ULOOP_EDGE_TRIGGER"); + lua_pushinteger(L, ULOOP_EDGE_TRIGGER); + lua_rawset(L, -3); + + lua_pushstring(L, "ULOOP_BLOCKING"); + lua_pushinteger(L, ULOOP_BLOCKING); + lua_rawset(L, -3); + + return 1; +} + +int luaclose_uloop(lua_State *L) +{ + lua_pushstring(L, "Called"); + + return 1; +} diff --git a/release/src/router/uqmi/libubox/md5.c b/release/src/router/uqmi/libubox/md5.c new file mode 100644 index 0000000000..13f84552b3 --- /dev/null +++ b/release/src/router/uqmi/libubox/md5.c @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2014 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD5 Message-Digest Algorithm (RFC 1321). + * + * Homepage: + * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * (This is a heavily cut-down "BSD license".) + * + * This differs from Colin Plumb's older public domain implementation in that + * no exactly 32-bit integer data type is required (any 32-bit or wider + * unsigned integer data type will do), there's no compile-time endianness + * configuration, and the function prototypes match OpenSSL's. No code from + * Colin Plumb's implementation has been reused; this comment merely compares + * the properties of the two independent implementations. + * + * The primary goals of this implementation are portability and ease of use. + * It is meant to be fast, but not as fast as possible. Some known + * optimizations are not included to reduce source code size and avoid + * compile-time configuration. + */ + +#include +#include + +#include "md5.h" + +/* + * The basic MD5 functions. + * + * F and G are optimized compared to their RFC 1321 definitions for + * architectures that lack an AND-NOT instruction, just like in Colin Plumb's + * implementation. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) +#define H(x, y, z) (((x) ^ (y)) ^ (z)) +#define H2(x, y, z) ((x) ^ ((y) ^ (z))) +#define I(x, y, z) ((y) ^ ((x) | ~(z))) + +/* + * The MD5 transformation for all four rounds. + */ +#define STEP(f, a, b, c, d, x, t, s) \ + (a) += f((b), (c), (d)) + (x) + (t); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ + (a) += (b); + +/* + * SET reads 4 input bytes in little-endian byte order and stores them + * in a properly aligned word in host byte order. + */ +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define SET(n) \ + (*(uint32_t *)&ptr[(n) * 4]) +#define GET(n) \ + SET(n) +#else +#define SET(n) \ + (block[(n)] = \ + (uint32_t)ptr[(n) * 4] | \ + ((uint32_t)ptr[(n) * 4 + 1] << 8) | \ + ((uint32_t)ptr[(n) * 4 + 2] << 16) | \ + ((uint32_t)ptr[(n) * 4 + 3] << 24)) +#define GET(n) \ + (block[(n)]) +#endif + +/* + * This processes one or more 64-byte data blocks, but does NOT update + * the bit counters. There are no alignment requirements. + */ +static const void *body(md5_ctx_t *ctx, const void *data, unsigned long size) +{ + const unsigned char *ptr; + uint32_t a, b, c, d; + uint32_t saved_a, saved_b, saved_c, saved_d; +#if __BYTE_ORDER != __LITTLE_ENDIAN + uint32_t block[16]; +#endif + + ptr = (const unsigned char *)data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + do { + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + +/* Round 1 */ + STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) + STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) + STEP(F, c, d, a, b, SET(2), 0x242070db, 17) + STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) + STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) + STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) + STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) + STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) + STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) + STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) + STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) + STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) + STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) + STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) + STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) + STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) + +/* Round 2 */ + STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) + STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) + STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) + STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) + STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) + STEP(G, d, a, b, c, GET(10), 0x02441453, 9) + STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) + STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) + STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) + STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) + STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) + STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) + STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) + STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) + STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) + STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) + +/* Round 3 */ + STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) + STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11) + STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) + STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23) + STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) + STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11) + STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) + STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23) + STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) + STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11) + STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) + STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23) + STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) + STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11) + STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) + STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23) + +/* Round 4 */ + STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) + STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) + STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) + STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) + STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) + STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) + STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) + STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) + STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) + STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) + STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) + STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) + STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) + STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) + STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) + STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } while (size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + + return ptr; +} + +void md5_begin(md5_ctx_t *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + + ctx->lo = 0; + ctx->hi = 0; +} + +void md5_hash(const void *data, size_t size, md5_ctx_t *ctx) +{ + uint32_t saved_lo; + unsigned long used, available; + + saved_lo = ctx->lo; + if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + ctx->hi++; + ctx->hi += size >> 29; + + used = saved_lo & 0x3f; + + if (used) { + available = 64 - used; + + if (size < available) { + memcpy(&ctx->buffer[used], data, size); + return; + } + + memcpy(&ctx->buffer[used], data, available); + data = (const unsigned char *)data + available; + size -= available; + body(ctx, ctx->buffer, 64); + } + + if (size >= 64) { + data = body(ctx, data, size & ~((size_t) 0x3f)); + size &= 0x3f; + } + + memcpy(ctx->buffer, data, size); +} + +void md5_end(void *resbuf, md5_ctx_t *ctx) +{ + unsigned char *result = resbuf; + unsigned long used, available; + + used = ctx->lo & 0x3f; + + ctx->buffer[used++] = 0x80; + + available = 64 - used; + + if (available < 8) { + memset(&ctx->buffer[used], 0, available); + body(ctx, ctx->buffer, 64); + used = 0; + available = 64; + } + + memset(&ctx->buffer[used], 0, available - 8); + + ctx->lo <<= 3; + ctx->buffer[56] = ctx->lo; + ctx->buffer[57] = ctx->lo >> 8; + ctx->buffer[58] = ctx->lo >> 16; + ctx->buffer[59] = ctx->lo >> 24; + ctx->buffer[60] = ctx->hi; + ctx->buffer[61] = ctx->hi >> 8; + ctx->buffer[62] = ctx->hi >> 16; + ctx->buffer[63] = ctx->hi >> 24; + + body(ctx, ctx->buffer, 64); + + result[0] = ctx->a; + result[1] = ctx->a >> 8; + result[2] = ctx->a >> 16; + result[3] = ctx->a >> 24; + result[4] = ctx->b; + result[5] = ctx->b >> 8; + result[6] = ctx->b >> 16; + result[7] = ctx->b >> 24; + result[8] = ctx->c; + result[9] = ctx->c >> 8; + result[10] = ctx->c >> 16; + result[11] = ctx->c >> 24; + result[12] = ctx->d; + result[13] = ctx->d >> 8; + result[14] = ctx->d >> 16; + result[15] = ctx->d >> 24; + + memset(ctx, 0, sizeof(*ctx)); +} + +int md5sum(char *file, void *md5_buf) +{ + char buf[256]; + md5_ctx_t ctx; + int ret = 0; + FILE *f; + + f = fopen(file, "r"); + if (!f) + return -1; + + md5_begin(&ctx); + do { + int len = fread(buf, 1, sizeof(buf), f); + if (!len) + break; + + md5_hash(buf, len, &ctx); + ret += len; + } while(1); + + md5_end(md5_buf, &ctx); + fclose(f); + + return ret; +} diff --git a/release/src/router/uqmi/libubox/md5.h b/release/src/router/uqmi/libubox/md5.h new file mode 100644 index 0000000000..b2f1b80c4c --- /dev/null +++ b/release/src/router/uqmi/libubox/md5.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2014 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD5 Message-Digest Algorithm (RFC 1321). + * + * Homepage: + * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * See md5.c for more information. + */ + +#ifndef _LIBUBOX_MD5_H +#define _LIBUBOX_MD5_H + +#include +#include + +typedef struct md5_ctx { + uint32_t lo, hi; + uint32_t a, b, c, d; + unsigned char buffer[64]; +} md5_ctx_t; + +extern void md5_begin(md5_ctx_t *ctx); +extern void md5_hash(const void *data, size_t length, md5_ctx_t *ctx); +extern void md5_end(void *resbuf, md5_ctx_t *ctx); +int md5sum(char *file, void *md5_buf); + +#endif diff --git a/release/src/router/uqmi/libubox/runqueue.c b/release/src/router/uqmi/libubox/runqueue.c new file mode 100644 index 0000000000..1d9fa4b3a1 --- /dev/null +++ b/release/src/router/uqmi/libubox/runqueue.c @@ -0,0 +1,282 @@ +/* + * runqueue.c - a simple task queueing/completion tracking helper + * + * Copyright (C) 2013 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include "runqueue.h" + +static void +__runqueue_empty_cb(struct uloop_timeout *timeout) +{ + struct runqueue *q = container_of(timeout, struct runqueue, timeout); + + q->empty_cb(q); +} + +void runqueue_init(struct runqueue *q) +{ + INIT_SAFE_LIST(&q->tasks_active); + INIT_SAFE_LIST(&q->tasks_inactive); +} + +static void __runqueue_start_next(struct uloop_timeout *timeout) +{ + struct runqueue *q = container_of(timeout, struct runqueue, timeout); + struct runqueue_task *t; + + do { + if (q->stopped) + break; + + if (list_empty(&q->tasks_inactive.list)) + break; + + if (q->max_running_tasks && q->running_tasks >= q->max_running_tasks) + break; + + t = list_first_entry(&q->tasks_inactive.list, struct runqueue_task, list.list); + safe_list_del(&t->list); + safe_list_add(&t->list, &q->tasks_active); + t->running = true; + q->running_tasks++; + if (t->run_timeout) + uloop_timeout_set(&t->timeout, t->run_timeout); + t->type->run(q, t); + } while (1); + + if (!q->empty && + list_empty(&q->tasks_active.list) && + list_empty(&q->tasks_inactive.list)) { + q->empty = true; + if (q->empty_cb) { + q->timeout.cb = __runqueue_empty_cb; + uloop_timeout_set(&q->timeout, 1); + } + } +} + +static void runqueue_start_next(struct runqueue *q) +{ + if (q->empty) + return; + + q->timeout.cb = __runqueue_start_next; + uloop_timeout_set(&q->timeout, 1); +} + +static int __runqueue_cancel(void *ctx, struct safe_list *list) +{ + struct runqueue_task *t; + + t = container_of(list, struct runqueue_task, list); + runqueue_task_cancel(t, 0); + + return 0; +} + +void runqueue_cancel_active(struct runqueue *q) +{ + safe_list_for_each(&q->tasks_active, __runqueue_cancel, NULL); +} + +void runqueue_cancel_pending(struct runqueue *q) +{ + safe_list_for_each(&q->tasks_inactive, __runqueue_cancel, NULL); +} + +void runqueue_cancel(struct runqueue *q) +{ + runqueue_cancel_pending(q); + runqueue_cancel_active(q); +} + +void runqueue_kill(struct runqueue *q) +{ + struct runqueue_task *t; + + while (!list_empty(&q->tasks_active.list)) { + t = list_first_entry(&q->tasks_active.list, struct runqueue_task, list.list); + runqueue_task_kill(t); + } + runqueue_cancel_pending(q); + uloop_timeout_cancel(&q->timeout); +} + +void runqueue_task_cancel(struct runqueue_task *t, int type) +{ + if (!t->queued) + return; + + if (!t->running) { + runqueue_task_complete(t); + return; + } + + t->cancelled = true; + if (t->cancel_timeout) + uloop_timeout_set(&t->timeout, t->cancel_timeout); + if (t->type->cancel) + t->type->cancel(t->q, t, type); +} + +static void +__runqueue_task_timeout(struct uloop_timeout *timeout) +{ + struct runqueue_task *t = container_of(timeout, struct runqueue_task, timeout); + + if (t->cancelled) + runqueue_task_kill(t); + else + runqueue_task_cancel(t, t->cancel_type); +} + +static void _runqueue_task_add(struct runqueue *q, struct runqueue_task *t, bool running, bool first) +{ + struct safe_list *head; + + if (t->queued) + return; + + if (!t->type->run && !running) { + fprintf(stderr, "BUG: inactive task added without run() callback\n"); + return; + } + + if (running) { + q->running_tasks++; + head = &q->tasks_active; + } else { + head = &q->tasks_inactive; + } + + t->timeout.cb = __runqueue_task_timeout; + t->q = q; + if (first) + safe_list_add_first(&t->list, head); + else + safe_list_add(&t->list, head); + t->cancelled = false; + t->queued = true; + t->running = running; + q->empty = false; + + runqueue_start_next(q); +} + +void runqueue_task_add(struct runqueue *q, struct runqueue_task *t, bool running) +{ + _runqueue_task_add(q, t, running, 0); +} + +void runqueue_task_add_first(struct runqueue *q, struct runqueue_task *t, bool running) +{ + _runqueue_task_add(q, t, running, 1); +} + +void runqueue_task_kill(struct runqueue_task *t) +{ + struct runqueue *q = t->q; + bool running = t->running; + + if (!t->queued) + return; + + runqueue_task_complete(t); + if (running && t->type->kill) + t->type->kill(q, t); + + runqueue_start_next(q); +} + +void runqueue_stop(struct runqueue *q) +{ + q->stopped = true; +} + +void runqueue_resume(struct runqueue *q) +{ + q->stopped = false; + runqueue_start_next(q); +} + +void runqueue_task_complete(struct runqueue_task *t) +{ + struct runqueue *q = t->q; + + if (!t->queued) + return; + + if (t->running) + t->q->running_tasks--; + + uloop_timeout_cancel(&t->timeout); + + safe_list_del(&t->list); + t->queued = false; + t->running = false; + t->cancelled = false; + if (t->complete) + t->complete(q, t); + runqueue_start_next(t->q); +} + +static void +__runqueue_proc_cb(struct uloop_process *p, int ret) +{ + struct runqueue_process *t = container_of(p, struct runqueue_process, proc); + + runqueue_task_complete(&t->task); +} + +void runqueue_process_cancel_cb(struct runqueue *q, struct runqueue_task *t, int type) +{ + struct runqueue_process *p = container_of(t, struct runqueue_process, task); + + if (!type) + type = SIGTERM; + + kill(p->proc.pid, type); +} + +void runqueue_process_kill_cb(struct runqueue *q, struct runqueue_task *t) +{ + struct runqueue_process *p = container_of(t, struct runqueue_process, task); + + uloop_process_delete(&p->proc); + kill(p->proc.pid, SIGKILL); +} + +static const struct runqueue_task_type runqueue_proc_type = { + .name = "process", + .cancel = runqueue_process_cancel_cb, + .kill = runqueue_process_kill_cb, +}; + +void runqueue_process_add(struct runqueue *q, struct runqueue_process *p, pid_t pid) +{ + if (p->proc.pending) + return; + + p->proc.pid = pid; + p->proc.cb = __runqueue_proc_cb; + if (!p->task.type) + p->task.type = &runqueue_proc_type; + uloop_process_add(&p->proc); + if (!p->task.running) + runqueue_task_add(q, &p->task, true); +} diff --git a/release/src/router/uqmi/libubox/runqueue.h b/release/src/router/uqmi/libubox/runqueue.h new file mode 100644 index 0000000000..0d4173dbf5 --- /dev/null +++ b/release/src/router/uqmi/libubox/runqueue.h @@ -0,0 +1,115 @@ +/* + * runqueue.c - a simple task queueing/completion tracking helper + * + * Copyright (C) 2013 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __LIBUBOX_RUNQUEUE_H +#define __LIBUBOX_RUNQUEUE_H + +#include "list.h" +#include "safe_list.h" +#include "uloop.h" + +struct runqueue; +struct runqueue_task; +struct runqueue_task_type; + +struct runqueue { + struct safe_list tasks_active; + struct safe_list tasks_inactive; + struct uloop_timeout timeout; + + int running_tasks; + int max_running_tasks; + bool stopped; + bool empty; + + /* called when the runqueue is emptied */ + void (*empty_cb)(struct runqueue *q); +}; + +struct runqueue_task_type { + const char *name; + + /* + * called when a task is requested to run + * + * The task is removed from the list before this callback is run. It + * can re-arm itself using runqueue_task_add. + */ + void (*run)(struct runqueue *q, struct runqueue_task *t); + + /* + * called to request cancelling a task + * + * int type is used as an optional hint for the method to be used when + * cancelling the task, e.g. a signal number for processes. Calls + * runqueue_task_complete when done. + */ + void (*cancel)(struct runqueue *q, struct runqueue_task *t, int type); + + /* + * called to kill a task. must not make any calls to runqueue_task_complete, + * it has already been removed from the list. + */ + void (*kill)(struct runqueue *q, struct runqueue_task *t); +}; + +struct runqueue_task { + struct safe_list list; + const struct runqueue_task_type *type; + struct runqueue *q; + + void (*complete)(struct runqueue *q, struct runqueue_task *t); + + struct uloop_timeout timeout; + int run_timeout; + int cancel_timeout; + int cancel_type; + + bool queued; + bool running; + bool cancelled; +}; + +struct runqueue_process { + struct runqueue_task task; + struct uloop_process proc; +}; + +void runqueue_init(struct runqueue *q); +void runqueue_cancel(struct runqueue *q); +void runqueue_cancel_active(struct runqueue *q); +void runqueue_cancel_pending(struct runqueue *q); +void runqueue_kill(struct runqueue *q); + +void runqueue_stop(struct runqueue *q); +void runqueue_resume(struct runqueue *q); + +void runqueue_task_add(struct runqueue *q, struct runqueue_task *t, bool running); +void runqueue_task_add_first(struct runqueue *q, struct runqueue_task *t, bool running); +void runqueue_task_complete(struct runqueue_task *t); + +void runqueue_task_cancel(struct runqueue_task *t, int type); +void runqueue_task_kill(struct runqueue_task *t); + +void runqueue_process_add(struct runqueue *q, struct runqueue_process *p, pid_t pid); + +/* to be used only from runqueue_process callbacks */ +void runqueue_process_cancel_cb(struct runqueue *q, struct runqueue_task *t, int type); +void runqueue_process_kill_cb(struct runqueue *q, struct runqueue_task *t); + +#endif diff --git a/release/src/router/uqmi/libubox/safe_list.c b/release/src/router/uqmi/libubox/safe_list.c new file mode 100644 index 0000000000..16f57e084f --- /dev/null +++ b/release/src/router/uqmi/libubox/safe_list.c @@ -0,0 +1,121 @@ +/* + * safe_list - linked list protected against recursive iteration with deletes + * + * Copyright (C) 2013 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "safe_list.h" + +struct safe_list_iterator { + struct safe_list_iterator **head; + struct safe_list_iterator *next_i; + struct safe_list *next; +}; + +static void +__safe_list_set_iterator(struct safe_list *list, + struct safe_list_iterator *i) +{ + struct safe_list_iterator *next_i; + struct safe_list *next; + + next = list_entry(list->list.next, struct safe_list, list); + next_i = next->i; + + next->i = i; + i->next = next; + i->head = &next->i; + + i->next_i = next_i; + if (next_i) + next_i->head = &i->next_i; +} + +static void +__safe_list_del_iterator(struct safe_list_iterator *i) +{ + *i->head = i->next_i; + if (i->next_i) + i->next_i->head = i->head; +} + +static void +__safe_list_move_iterator(struct safe_list *list, + struct safe_list_iterator *i) +{ + __safe_list_del_iterator(i); + __safe_list_set_iterator(list, i); +} + +int safe_list_for_each(struct safe_list *head, + int (*cb)(void *ctx, struct safe_list *list), + void *ctx) +{ + struct safe_list_iterator i; + struct safe_list *cur; + int ret = 0; + + for (cur = list_entry(head->list.next, struct safe_list, list), + __safe_list_set_iterator(cur, &i); + cur != head; + cur = i.next, __safe_list_move_iterator(cur, &i)) { + ret = cb(ctx, cur); + if (ret) + break; + } + + __safe_list_del_iterator(&i); + return ret; +} + +void safe_list_add(struct safe_list *list, struct safe_list *head) +{ + list->i = NULL; + list_add_tail(&list->list, &head->list); +} + +void safe_list_add_first(struct safe_list *list, struct safe_list *head) +{ + list->i = NULL; + list_add(&list->list, &head->list); +} + +void safe_list_del(struct safe_list *list) +{ + struct safe_list_iterator *i, *next_i, **tail; + struct safe_list *next; + + next = list_entry(list->list.next, struct safe_list, list); + list_del(&list->list); + + if (!list->i) + return; + + next_i = next->i; + tail = &next->i; + + for (i = list->i; i; i = i->next_i) { + tail = &i->next_i; + i->next = next; + } + + next->i = list->i; + list->i->head = &next->i; + *tail = next_i; + if (next_i) + next_i->head = tail; + + list->i = NULL; +} diff --git a/release/src/router/uqmi/libubox/safe_list.h b/release/src/router/uqmi/libubox/safe_list.h new file mode 100644 index 0000000000..67b673d9db --- /dev/null +++ b/release/src/router/uqmi/libubox/safe_list.h @@ -0,0 +1,62 @@ +/* + * safe_list - linked list protected against recursive iteration with deletes + * + * Copyright (C) 2013 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Use this linked list implementation as a replacement for list.h if you + * want to allow deleting arbitrary list entries from within one or more + * recursive iterator calling context + */ + +#ifndef __LIBUBOX_SAFE_LIST_H +#define __LIBUBOX_SAFE_LIST_H + +#include +#include "list.h" +#include "utils.h" + +struct safe_list; +struct safe_list_iterator; + +struct safe_list { + struct list_head list; + struct safe_list_iterator *i; +}; + +int safe_list_for_each(struct safe_list *list, + int (*cb)(void *ctx, struct safe_list *list), + void *ctx); + +void safe_list_add(struct safe_list *list, struct safe_list *head); +void safe_list_add_first(struct safe_list *list, struct safe_list *head); +void safe_list_del(struct safe_list *list); + +#define INIT_SAFE_LIST(_head) \ + do { \ + INIT_LIST_HEAD(_head.list); \ + (_head)->i = NULL; \ + } while (0) + +#define SAFE_LIST_INIT(_name) { LIST_HEAD_INIT(_name.list), NULL } +#define SAFE_LIST(_name) struct safe_list _name = SAFE_LIST_INIT(_name) + +static inline bool safe_list_empty(struct safe_list *head) +{ + return list_empty(&head->list); +} + +#endif diff --git a/release/src/router/uqmi/libubox/sh/jshn.sh b/release/src/router/uqmi/libubox/sh/jshn.sh new file mode 100644 index 0000000000..bf76edbeed --- /dev/null +++ b/release/src/router/uqmi/libubox/sh/jshn.sh @@ -0,0 +1,280 @@ +# functions for parsing and generating json + +_json_get_var() { + # dest=$1 + # var=$2 + eval "$1=\"\$${JSON_PREFIX}$2\"" +} + +_json_set_var() { + # var=$1 + local ___val="$2" + eval "${JSON_PREFIX}$1=\"\$___val\"" +} + +__jshn_raw_append() { + # var=$1 + local value="$2" + local sep="${3:- }" + + eval "export -- \"$1=\${$1:+\${$1}\${value:+\$sep}}\$value\"" +} + +_jshn_append() { + # var=$1 + local _a_value="$2" + eval "${JSON_PREFIX}$1=\"\${${JSON_PREFIX}$1} \$_a_value\"" +} + +_get_var() { + # var=$1 + # value=$2 + eval "$1=\"\$$2\"" +} + +_set_var() { + # var=$1 + local __val="$2" + eval "$1=\"\$__val\"" +} + +_json_inc() { + # var=$1 + # dest=$2 + + let "${JSON_PREFIX}$1 += 1" "$2 = ${JSON_PREFIX}$1" +} + +_json_add_generic() { + # type=$1 + # name=$2 + # value=$3 + # cur=$4 + + local var + if [ "${4%%[0-9]*}" = "J_A" ]; then + _json_inc "S_$4" var + else + var="${2//[^a-zA-Z0-9_]/_}" + [[ "$var" == "$2" ]] || export -- "${JSON_PREFIX}N_${4}_${var}=$2" + fi + + export -- \ + "${JSON_PREFIX}${4}_$var=$3" \ + "${JSON_PREFIX}T_${4}_$var=$1" + _jshn_append "JSON_UNSET" "${4}_$var" + _jshn_append "K_$4" "$var" +} + +_json_add_table() { + # name=$1 + # type=$2 + # itype=$3 + local cur seq + + _json_get_var cur JSON_CUR + _json_inc JSON_SEQ seq + + local table="J_$3$seq" + _json_set_var "U_$table" "$cur" + export -- "${JSON_PREFIX}K_$table=" + unset "${JSON_PREFIX}S_$table" + _json_set_var JSON_CUR "$table" + _jshn_append "JSON_UNSET" "$table" + + _json_add_generic "$2" "$1" "$table" "$cur" +} + +_json_close_table() { + local _s_cur + + _json_get_var _s_cur JSON_CUR + _json_get_var "${JSON_PREFIX}JSON_CUR" "U_$_s_cur" +} + +json_set_namespace() { + local _new="$1" + local _old="$2" + + [ -n "$_old" ] && _set_var "$_old" "$JSON_PREFIX" + JSON_PREFIX="$_new" +} + +json_cleanup() { + local unset tmp + + _json_get_var unset JSON_UNSET + for tmp in $unset J_V; do + unset \ + ${JSON_PREFIX}U_$tmp \ + ${JSON_PREFIX}K_$tmp \ + ${JSON_PREFIX}S_$tmp \ + ${JSON_PREFIX}T_$tmp \ + ${JSON_PREFIX}N_$tmp \ + ${JSON_PREFIX}$tmp + done + + unset \ + ${JSON_PREFIX}JSON_SEQ \ + ${JSON_PREFIX}JSON_CUR \ + ${JSON_PREFIX}JSON_UNSET +} + +json_init() { + json_cleanup + export -n ${JSON_PREFIX}JSON_SEQ=0 + export -- \ + ${JSON_PREFIX}JSON_CUR="J_V" \ + ${JSON_PREFIX}K_J_V= +} + +json_add_object() { + _json_add_table "$1" object T +} + +json_close_object() { + _json_close_table +} + +json_add_array() { + _json_add_table "$1" array A +} + +json_close_array() { + _json_close_table +} + +json_add_string() { + local cur + _json_get_var cur JSON_CUR + _json_add_generic string "$1" "$2" "$cur" +} + +json_add_int() { + local cur + _json_get_var cur JSON_CUR + _json_add_generic int "$1" "$2" "$cur" +} + +json_add_boolean() { + local cur + _json_get_var cur JSON_CUR + _json_add_generic boolean "$1" "$2" "$cur" +} + +json_add_double() { + local cur + _json_get_var cur JSON_CUR + _json_add_generic double "$1" "$2" "$cur" +} + +# functions read access to json variables + +json_load() { + eval "`jshn -r "$1"`" +} + +json_dump() { + jshn "$@" ${JSON_PREFIX:+-p "$JSON_PREFIX"} -w +} + +json_get_type() { + local __dest="$1" + local __cur + + _json_get_var __cur JSON_CUR + local __var="${JSON_PREFIX}T_${__cur}_${2//[^a-zA-Z0-9_]/_}" + eval "export -- \"$__dest=\${$__var}\"; [ -n \"\${$__var+x}\" ]" +} + +json_get_keys() { + local __dest="$1" + local _tbl_cur + + if [ -n "$2" ]; then + json_get_var _tbl_cur "$2" + else + _json_get_var _tbl_cur JSON_CUR + fi + local __var="${JSON_PREFIX}K_${_tbl_cur}" + eval "export -- \"$__dest=\${$__var}\"; [ -n \"\${$__var+x}\" ]" +} + +json_get_values() { + local _v_dest="$1" + local _v_keys _v_val _select= + local _json_no_warning=1 + + unset "$_v_dest" + [ -n "$2" ] && { + json_select "$2" || return 1 + _select=1 + } + + json_get_keys _v_keys + set -- $_v_keys + while [ "$#" -gt 0 ]; do + json_get_var _v_val "$1" + __jshn_raw_append "$_v_dest" "$_v_val" + shift + done + [ -n "$_select" ] && json_select .. + + return 0 +} + +json_get_var() { + local __dest="$1" + local __cur + + _json_get_var __cur JSON_CUR + local __var="${JSON_PREFIX}${__cur}_${2//[^a-zA-Z0-9_]/_}" + eval "export -- \"$__dest=\${$__var:-$3}\"; [ -n \"\${$__var+x}\${3+x}\" ]" +} + +json_get_vars() { + while [ "$#" -gt 0 ]; do + local _var="$1"; shift + if [ "$_var" != "${_var#*:}" ]; then + json_get_var "${_var%%:*}" "${_var%%:*}" "${_var#*:}" + else + json_get_var "$_var" "$_var" + fi + done +} + +json_select() { + local target="$1" + local type + local cur + + [ -z "$1" ] && { + _json_set_var JSON_CUR "J_V" + return 0 + } + [[ "$1" == ".." ]] && { + _json_get_var cur JSON_CUR + _json_get_var cur "U_$cur" + _json_set_var JSON_CUR "$cur" + return 0 + } + json_get_type type "$target" + case "$type" in + object|array) + json_get_var cur "$target" + _json_set_var JSON_CUR "$cur" + ;; + *) + [ -n "$_json_no_warning" ] || \ + echo "WARNING: Variable '$target' does not exist or is not an array/object" + return 1 + ;; + esac +} + +json_is_a() { + local type + + json_get_type type "$1" + [ "$type" = "$2" ] +} diff --git a/release/src/router/uqmi/libubox/uloop.c b/release/src/router/uqmi/libubox/uloop.c new file mode 100644 index 0000000000..9a77ce49a5 --- /dev/null +++ b/release/src/router/uqmi/libubox/uloop.c @@ -0,0 +1,682 @@ +/* + * uloop - event loop implementation + * + * Copyright (C) 2010-2013 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uloop.h" +#include "utils.h" + +#ifdef USE_KQUEUE +#include +#endif +#ifdef USE_EPOLL +#include +#endif +#include + +struct uloop_fd_event { + struct uloop_fd *fd; + unsigned int events; +}; + +struct uloop_fd_stack { + struct uloop_fd_stack *next; + struct uloop_fd *fd; + unsigned int events; +}; + +static struct uloop_fd_stack *fd_stack = NULL; + +#define ULOOP_MAX_EVENTS 10 + +static struct list_head timeouts = LIST_HEAD_INIT(timeouts); +static struct list_head processes = LIST_HEAD_INIT(processes); + +static int poll_fd = -1; +bool uloop_cancelled = false; +static bool do_sigchld = false; + +static struct uloop_fd_event cur_fds[ULOOP_MAX_EVENTS]; +static int cur_fd, cur_nfds; + +#ifdef USE_KQUEUE + +int uloop_init(void) +{ + struct timespec timeout = { 0, 0 }; + struct kevent ev = {}; + + if (poll_fd >= 0) + return 0; + + poll_fd = kqueue(); + if (poll_fd < 0) + return -1; + + EV_SET(&ev, SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, 0); + kevent(poll_fd, &ev, 1, NULL, 0, &timeout); + + return 0; +} + + +static uint16_t get_flags(unsigned int flags, unsigned int mask) +{ + uint16_t kflags = 0; + + if (!(flags & mask)) + return EV_DELETE; + + kflags = EV_ADD; + if (flags & ULOOP_EDGE_TRIGGER) + kflags |= EV_CLEAR; + + return kflags; +} + +static struct kevent events[ULOOP_MAX_EVENTS]; + +static int register_kevent(struct uloop_fd *fd, unsigned int flags) +{ + struct timespec timeout = { 0, 0 }; + struct kevent ev[2]; + int nev = 0; + unsigned int fl = 0; + unsigned int changed; + uint16_t kflags; + + if (flags & ULOOP_EDGE_DEFER) + flags &= ~ULOOP_EDGE_TRIGGER; + + changed = flags ^ fd->flags; + if (changed & ULOOP_EDGE_TRIGGER) + changed |= flags; + + if (changed & ULOOP_READ) { + kflags = get_flags(flags, ULOOP_READ); + EV_SET(&ev[nev++], fd->fd, EVFILT_READ, kflags, 0, 0, fd); + } + + if (changed & ULOOP_WRITE) { + kflags = get_flags(flags, ULOOP_WRITE); + EV_SET(&ev[nev++], fd->fd, EVFILT_WRITE, kflags, 0, 0, fd); + } + + if (!flags) + fl |= EV_DELETE; + + fd->flags = flags; + if (kevent(poll_fd, ev, nev, NULL, fl, &timeout) == -1) + return -1; + + return 0; +} + +static int register_poll(struct uloop_fd *fd, unsigned int flags) +{ + if (flags & ULOOP_EDGE_TRIGGER) + flags |= ULOOP_EDGE_DEFER; + else + flags &= ~ULOOP_EDGE_DEFER; + + return register_kevent(fd, flags); +} + +static int __uloop_fd_delete(struct uloop_fd *fd) +{ + return register_poll(fd, 0); +} + +static int uloop_fetch_events(int timeout) +{ + struct timespec ts; + int nfds, n; + + if (timeout >= 0) { + ts.tv_sec = timeout / 1000; + ts.tv_nsec = (timeout % 1000) * 1000000; + } + + nfds = kevent(poll_fd, NULL, 0, events, ARRAY_SIZE(events), timeout >= 0 ? &ts : NULL); + for (n = 0; n < nfds; n++) { + struct uloop_fd_event *cur = &cur_fds[n]; + struct uloop_fd *u = events[n].udata; + unsigned int ev = 0; + + cur->fd = u; + if (!u) + continue; + + if (events[n].flags & EV_ERROR) { + u->error = true; + if (!(u->flags & ULOOP_ERROR_CB)) + uloop_fd_delete(u); + } + + if(events[n].filter == EVFILT_READ) + ev |= ULOOP_READ; + else if (events[n].filter == EVFILT_WRITE) + ev |= ULOOP_WRITE; + + if (events[n].flags & EV_EOF) + u->eof = true; + else if (!ev) + cur->fd = NULL; + + cur->events = ev; + if (u->flags & ULOOP_EDGE_DEFER) { + u->flags &= ~ULOOP_EDGE_DEFER; + u->flags |= ULOOP_EDGE_TRIGGER; + register_kevent(u, u->flags); + } + } + return nfds; +} + +#endif + +#ifdef USE_EPOLL + +/** + * FIXME: uClibc < 0.9.30.3 does not define EPOLLRDHUP for Linux >= 2.6.17 + */ +#ifndef EPOLLRDHUP +#define EPOLLRDHUP 0x2000 +#endif + +int uloop_init(void) +{ + if (poll_fd >= 0) + return 0; + + poll_fd = epoll_create(32); + if (poll_fd < 0) + return -1; + + fcntl(poll_fd, F_SETFD, fcntl(poll_fd, F_GETFD) | FD_CLOEXEC); + return 0; +} + +static int register_poll(struct uloop_fd *fd, unsigned int flags) +{ + struct epoll_event ev; + int op = fd->registered ? EPOLL_CTL_MOD : EPOLL_CTL_ADD; + + memset(&ev, 0, sizeof(struct epoll_event)); + + if (flags & ULOOP_READ) + ev.events |= EPOLLIN | EPOLLRDHUP; + + if (flags & ULOOP_WRITE) + ev.events |= EPOLLOUT; + + if (flags & ULOOP_EDGE_TRIGGER) + ev.events |= EPOLLET; + + ev.data.fd = fd->fd; + ev.data.ptr = fd; + fd->flags = flags; + + return epoll_ctl(poll_fd, op, fd->fd, &ev); +} + +static struct epoll_event events[ULOOP_MAX_EVENTS]; + +static int __uloop_fd_delete(struct uloop_fd *sock) +{ + sock->flags = 0; + return epoll_ctl(poll_fd, EPOLL_CTL_DEL, sock->fd, 0); +} + +static int uloop_fetch_events(int timeout) +{ + int n, nfds; + + nfds = epoll_wait(poll_fd, events, ARRAY_SIZE(events), timeout); + for (n = 0; n < nfds; ++n) { + struct uloop_fd_event *cur = &cur_fds[n]; + struct uloop_fd *u = events[n].data.ptr; + unsigned int ev = 0; + + cur->fd = u; + if (!u) + continue; + + if (events[n].events & (EPOLLERR|EPOLLHUP)) { + u->error = true; + if (!(u->flags & ULOOP_ERROR_CB)) + uloop_fd_delete(u); + } + + if(!(events[n].events & (EPOLLRDHUP|EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP))) { + cur->fd = NULL; + continue; + } + + if(events[n].events & EPOLLRDHUP) + u->eof = true; + + if(events[n].events & EPOLLIN) + ev |= ULOOP_READ; + + if(events[n].events & EPOLLOUT) + ev |= ULOOP_WRITE; + + cur->events = ev; + } + + return nfds; +} + +#endif + +static bool uloop_fd_stack_event(struct uloop_fd *fd, int events) +{ + struct uloop_fd_stack *cur; + + /* + * Do not buffer events for level-triggered fds, they will keep firing. + * Caller needs to take care of recursion issues. + */ + if (!(fd->flags & ULOOP_EDGE_TRIGGER)) + return false; + + for (cur = fd_stack; cur; cur = cur->next) { + if (cur->fd != fd) + continue; + + if (events < 0) + cur->fd = NULL; + else + cur->events |= events | ULOOP_EVENT_BUFFERED; + + return true; + } + + return false; +} + +static void uloop_run_events(int timeout) +{ + struct uloop_fd_event *cur; + struct uloop_fd *fd; + + if (!cur_nfds) { + cur_fd = 0; + cur_nfds = uloop_fetch_events(timeout); + if (cur_nfds < 0) + cur_nfds = 0; + } + + while (cur_nfds > 0) { + struct uloop_fd_stack stack_cur; + unsigned int events; + + cur = &cur_fds[cur_fd++]; + cur_nfds--; + + fd = cur->fd; + events = cur->events; + if (!fd) + continue; + + if (!fd->cb) + continue; + + if (uloop_fd_stack_event(fd, cur->events)) + continue; + + stack_cur.next = fd_stack; + stack_cur.fd = fd; + fd_stack = &stack_cur; + do { + stack_cur.events = 0; + fd->cb(fd, events); + events = stack_cur.events & ULOOP_EVENT_MASK; + } while (stack_cur.fd && events); + fd_stack = stack_cur.next; + + return; + } +} + +int uloop_fd_add(struct uloop_fd *sock, unsigned int flags) +{ + unsigned int fl; + int ret; + + if (!(flags & (ULOOP_READ | ULOOP_WRITE))) + return uloop_fd_delete(sock); + + if (!sock->registered && !(flags & ULOOP_BLOCKING)) { + fl = fcntl(sock->fd, F_GETFL, 0); + fl |= O_NONBLOCK; + fcntl(sock->fd, F_SETFL, fl); + } + + ret = register_poll(sock, flags); + if (ret < 0) + goto out; + + sock->registered = true; + sock->eof = false; + sock->error = false; + +out: + return ret; +} + +int uloop_fd_delete(struct uloop_fd *fd) +{ + int i; + + for (i = 0; i < cur_nfds; i++) { + if (cur_fds[cur_fd + i].fd != fd) + continue; + + cur_fds[cur_fd + i].fd = NULL; + } + + if (!fd->registered) + return 0; + + fd->registered = false; + uloop_fd_stack_event(fd, -1); + return __uloop_fd_delete(fd); +} + +static int tv_diff(struct timeval *t1, struct timeval *t2) +{ + return + (t1->tv_sec - t2->tv_sec) * 1000 + + (t1->tv_usec - t2->tv_usec) / 1000; +} + +int uloop_timeout_add(struct uloop_timeout *timeout) +{ + struct uloop_timeout *tmp; + struct list_head *h = &timeouts; + + if (timeout->pending) + return -1; + + list_for_each_entry(tmp, &timeouts, list) { + if (tv_diff(&tmp->time, &timeout->time) > 0) { + h = &tmp->list; + break; + } + } + + list_add_tail(&timeout->list, h); + timeout->pending = true; + + return 0; +} + +static void uloop_gettime(struct timeval *tv) +{ + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 1000; +} + +int uloop_timeout_set(struct uloop_timeout *timeout, int msecs) +{ + struct timeval *time = &timeout->time; + + if (timeout->pending) + uloop_timeout_cancel(timeout); + + uloop_gettime(&timeout->time); + + time->tv_sec += msecs / 1000; + time->tv_usec += (msecs % 1000) * 1000; + + if (time->tv_usec > 1000000) { + time->tv_sec++; + time->tv_usec %= 1000000; + } + + return uloop_timeout_add(timeout); +} + +int uloop_timeout_cancel(struct uloop_timeout *timeout) +{ + if (!timeout->pending) + return -1; + + list_del(&timeout->list); + timeout->pending = false; + + return 0; +} + +int uloop_timeout_remaining(struct uloop_timeout *timeout) +{ + struct timeval now; + + if (!timeout->pending) + return -1; + + uloop_gettime(&now); + + return tv_diff(&timeout->time, &now); +} + +int uloop_process_add(struct uloop_process *p) +{ + struct uloop_process *tmp; + struct list_head *h = &processes; + + if (p->pending) + return -1; + + list_for_each_entry(tmp, &processes, list) { + if (tmp->pid > p->pid) { + h = &tmp->list; + break; + } + } + + list_add_tail(&p->list, h); + p->pending = true; + + return 0; +} + +int uloop_process_delete(struct uloop_process *p) +{ + if (!p->pending) + return -1; + + list_del(&p->list); + p->pending = false; + + return 0; +} + +static void uloop_handle_processes(void) +{ + struct uloop_process *p, *tmp; + pid_t pid; + int ret; + + do_sigchld = false; + + while (1) { + pid = waitpid(-1, &ret, WNOHANG); + if (pid <= 0) + return; + + list_for_each_entry_safe(p, tmp, &processes, list) { + if (p->pid < pid) + continue; + + if (p->pid > pid) + break; + + uloop_process_delete(p); + p->cb(p, ret); + } + } + +} + +static void uloop_handle_sigint(int signo) +{ + uloop_cancelled = true; +} + +static void uloop_sigchld(int signo) +{ + do_sigchld = true; +} + +static void uloop_install_handler(int signum, void (*handler)(int), struct sigaction* old, bool add) +{ + struct sigaction s; + struct sigaction *act; + + act = NULL; + sigaction(signum, NULL, &s); + + if (add) { + if (s.sa_handler == SIG_DFL) { /* Do not override existing custom signal handlers */ + memcpy(old, &s, sizeof(struct sigaction)); + s.sa_handler = handler; + s.sa_flags = 0; + act = &s; + } + } + else if (s.sa_handler == handler) { /* Do not restore if someone modified our handler */ + act = old; + } + + if (act != NULL) + sigaction(signum, act, NULL); +} + +static void uloop_setup_signals(bool add) +{ + static struct sigaction old_sigint, old_sigchld, old_sigterm; + + uloop_install_handler(SIGINT, uloop_handle_sigint, &old_sigint, add); + uloop_install_handler(SIGTERM, uloop_handle_sigint, &old_sigterm, add); + uloop_install_handler(SIGCHLD, uloop_sigchld, &old_sigchld, add); +} + +static int uloop_get_next_timeout(struct timeval *tv) +{ + struct uloop_timeout *timeout; + int diff; + + if (list_empty(&timeouts)) + return -1; + + timeout = list_first_entry(&timeouts, struct uloop_timeout, list); + diff = tv_diff(&timeout->time, tv); + if (diff < 0) + return 0; + + return diff; +} + +static void uloop_process_timeouts(struct timeval *tv) +{ + struct uloop_timeout *t; + + while (!list_empty(&timeouts)) { + t = list_first_entry(&timeouts, struct uloop_timeout, list); + + if (tv_diff(&t->time, tv) > 0) + break; + + uloop_timeout_cancel(t); + if (t->cb) + t->cb(t); + } +} + +static void uloop_clear_timeouts(void) +{ + struct uloop_timeout *t, *tmp; + + list_for_each_entry_safe(t, tmp, &timeouts, list) + uloop_timeout_cancel(t); +} + +static void uloop_clear_processes(void) +{ + struct uloop_process *p, *tmp; + + list_for_each_entry_safe(p, tmp, &processes, list) + uloop_process_delete(p); +} + +void uloop_run(void) +{ + static int recursive_calls = 0; + struct timeval tv; + + /* + * Handlers are only updated for the first call to uloop_run() (and restored + * when this call is done). + */ + if (!recursive_calls++) + uloop_setup_signals(true); + + uloop_cancelled = false; + while(!uloop_cancelled) + { + uloop_gettime(&tv); + uloop_process_timeouts(&tv); + if (uloop_cancelled) + break; + + if (do_sigchld) + uloop_handle_processes(); + uloop_gettime(&tv); + uloop_run_events(uloop_get_next_timeout(&tv)); + } + + if (!--recursive_calls) + uloop_setup_signals(false); +} + +void uloop_done(void) +{ + if (poll_fd < 0) + return; + + close(poll_fd); + poll_fd = -1; + + uloop_clear_timeouts(); + uloop_clear_processes(); +} diff --git a/release/src/router/uqmi/libubox/uloop.h b/release/src/router/uqmi/libubox/uloop.h new file mode 100644 index 0000000000..7564514053 --- /dev/null +++ b/release/src/router/uqmi/libubox/uloop.h @@ -0,0 +1,109 @@ +/* + * uloop - event loop implementation + * + * Copyright (C) 2010-2013 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _ULOOP_H__ +#define _ULOOP_H__ + +#include +#include +#include +#include +#include + +#if defined(__APPLE__) || defined(__FreeBSD__) +#define USE_KQUEUE +#else +#define USE_EPOLL +#endif + +#include "list.h" + +struct uloop_fd; +struct uloop_timeout; +struct uloop_process; + +typedef void (*uloop_fd_handler)(struct uloop_fd *u, unsigned int events); +typedef void (*uloop_timeout_handler)(struct uloop_timeout *t); +typedef void (*uloop_process_handler)(struct uloop_process *c, int ret); + +#define ULOOP_READ (1 << 0) +#define ULOOP_WRITE (1 << 1) +#define ULOOP_EDGE_TRIGGER (1 << 2) +#define ULOOP_BLOCKING (1 << 3) + +#define ULOOP_EVENT_MASK (ULOOP_READ | ULOOP_WRITE) + +/* internal flags */ +#define ULOOP_EVENT_BUFFERED (1 << 4) +#ifdef USE_KQUEUE +#define ULOOP_EDGE_DEFER (1 << 5) +#endif + +#define ULOOP_ERROR_CB (1 << 6) + +struct uloop_fd +{ + uloop_fd_handler cb; + int fd; + bool eof; + bool error; + bool registered; + uint8_t flags; +}; + +struct uloop_timeout +{ + struct list_head list; + bool pending; + + uloop_timeout_handler cb; + struct timeval time; +}; + +struct uloop_process +{ + struct list_head list; + bool pending; + + uloop_process_handler cb; + pid_t pid; +}; + +extern bool uloop_cancelled; +extern bool uloop_handle_sigchld; + +int uloop_fd_add(struct uloop_fd *sock, unsigned int flags); +int uloop_fd_delete(struct uloop_fd *sock); + +int uloop_timeout_add(struct uloop_timeout *timeout); +int uloop_timeout_set(struct uloop_timeout *timeout, int msecs); +int uloop_timeout_cancel(struct uloop_timeout *timeout); +int uloop_timeout_remaining(struct uloop_timeout *timeout); + +int uloop_process_add(struct uloop_process *p); +int uloop_process_delete(struct uloop_process *p); + +static inline void uloop_end(void) +{ + uloop_cancelled = true; +} + +int uloop_init(void); +void uloop_run(void); +void uloop_done(void); + +#endif diff --git a/release/src/router/uqmi/libubox/usock.c b/release/src/router/uqmi/libubox/usock.c new file mode 100644 index 0000000000..64eab9e12c --- /dev/null +++ b/release/src/router/uqmi/libubox/usock.c @@ -0,0 +1,132 @@ +/* + * usock - socket helper functions + * + * Copyright (C) 2010 Steven Barth + * Copyright (C) 2011-2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "usock.h" + +static void usock_set_flags(int sock, unsigned int type) +{ + if (!(type & USOCK_NOCLOEXEC)) + fcntl(sock, F_SETFD, fcntl(sock, F_GETFD) | FD_CLOEXEC); + + if (type & USOCK_NONBLOCK) + fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK); +} + +static int usock_connect(struct sockaddr *sa, int sa_len, int family, int socktype, bool server) +{ + int sock; + + sock = socket(family, socktype, 0); + if (sock < 0) + return -1; + + if (server) { + const int one = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + + if (!bind(sock, sa, sa_len) && + (socktype != SOCK_STREAM || !listen(sock, SOMAXCONN))) + return sock; + } else { + if (!connect(sock, sa, sa_len) || errno == EINPROGRESS) + return sock; + } + + close(sock); + return -1; +} + +static int usock_unix(const char *host, int socktype, bool server) +{ + struct sockaddr_un sun = {.sun_family = AF_UNIX}; + + if (strlen(host) >= sizeof(sun.sun_path)) { + errno = EINVAL; + return -1; + } + strcpy(sun.sun_path, host); + + return usock_connect((struct sockaddr*)&sun, sizeof(sun), AF_UNIX, socktype, server); +} + +static int usock_inet(int type, const char *host, const char *service, int socktype, bool server) +{ + struct addrinfo *result, *rp; + struct addrinfo hints = { + .ai_family = (type & USOCK_IPV6ONLY) ? AF_INET6 : + (type & USOCK_IPV4ONLY) ? AF_INET : AF_UNSPEC, + .ai_socktype = socktype, + .ai_flags = AI_ADDRCONFIG + | ((type & USOCK_SERVER) ? AI_PASSIVE : 0) + | ((type & USOCK_NUMERIC) ? AI_NUMERICHOST : 0), + }; + int sock = -1; + + if (getaddrinfo(host, service, &hints, &result)) + return -1; + + for (rp = result; rp != NULL; rp = rp->ai_next) { + sock = usock_connect(rp->ai_addr, rp->ai_addrlen, rp->ai_family, socktype, server); + if (sock >= 0) + break; + } + + freeaddrinfo(result); + return sock; +} + +const char *usock_port(int port) +{ + static char buffer[sizeof("65535\0")]; + + if (port < 0 || port > 65535) + return NULL; + + snprintf(buffer, sizeof(buffer), "%u", port); + + return buffer; +} + +int usock(int type, const char *host, const char *service) { + int socktype = ((type & 0xff) == USOCK_TCP) ? SOCK_STREAM : SOCK_DGRAM; + bool server = !!(type & USOCK_SERVER); + int sock; + + if (type & USOCK_UNIX) + sock = usock_unix(host, socktype, server); + else + sock = usock_inet(type, host, service, socktype, server); + + if (sock < 0) + return -1; + + usock_set_flags(sock, type); + return sock; +} diff --git a/release/src/router/uqmi/libubox/usock.h b/release/src/router/uqmi/libubox/usock.h new file mode 100644 index 0000000000..8345581be5 --- /dev/null +++ b/release/src/router/uqmi/libubox/usock.h @@ -0,0 +1,36 @@ +/* + * usock - socket helper functions + * + * Copyright (C) 2010 Steven Barth + * Copyright (C) 2011-2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef USOCK_H_ +#define USOCK_H_ + +#define USOCK_TCP 0 +#define USOCK_UDP 1 + +#define USOCK_SERVER 0x0100 +#define USOCK_NOCLOEXEC 0x0200 +#define USOCK_NONBLOCK 0x0400 +#define USOCK_NUMERIC 0x0800 +#define USOCK_IPV6ONLY 0x2000 +#define USOCK_IPV4ONLY 0x4000 +#define USOCK_UNIX 0x8000 + +const char *usock_port(int port); +int usock(int type, const char *host, const char *service); + +#endif /* USOCK_H_ */ diff --git a/release/src/router/uqmi/libubox/ustream-fd.c b/release/src/router/uqmi/libubox/ustream-fd.c new file mode 100644 index 0000000000..4abb53053b --- /dev/null +++ b/release/src/router/uqmi/libubox/ustream-fd.c @@ -0,0 +1,163 @@ +/* + * ustream - library for stream buffer management + * + * Copyright (C) 2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include "ustream.h" + +static void ustream_fd_set_uloop(struct ustream *s, bool write) +{ + struct ustream_fd *sf = container_of(s, struct ustream_fd, stream); + struct ustream_buf *buf; + unsigned int flags = ULOOP_EDGE_TRIGGER; + + if (!s->read_blocked && !s->eof) + flags |= ULOOP_READ; + + buf = s->w.head; + if (write || (buf && s->w.data_bytes && !s->write_error)) + flags |= ULOOP_WRITE; + + uloop_fd_add(&sf->fd, flags); +} + +static void ustream_fd_set_read_blocked(struct ustream *s) +{ + ustream_fd_set_uloop(s, false); +} + +static void ustream_fd_read_pending(struct ustream_fd *sf, bool *more) +{ + struct ustream *s = &sf->stream; + int buflen = 0; + ssize_t len; + char *buf; + + do { + buf = ustream_reserve(s, 1, &buflen); + if (!buf) + break; + + len = read(sf->fd.fd, buf, buflen); + if (len < 0) { + if (errno == EINTR) + continue; + + if (errno == EAGAIN) + return; + + len = 0; + } + + if (!len) { + if (!s->eof) + ustream_state_change(s); + s->eof = true; + ustream_fd_set_uloop(s, false); + return; + } + + ustream_fill_read(s, len); + *more = true; + } while (1); +} + +static int ustream_fd_write(struct ustream *s, const char *buf, int buflen, bool more) +{ + struct ustream_fd *sf = container_of(s, struct ustream_fd, stream); + ssize_t ret = 0, len; + + if (!buflen) + return 0; + + while (buflen) { + len = write(sf->fd.fd, buf, buflen); + + if (len < 0) { + if (errno == EINTR) + continue; + + if (errno == EAGAIN || errno == EWOULDBLOCK) + break; + + return -1; + } + + ret += len; + buf += len; + buflen -= len; + } + + if (buflen) + ustream_fd_set_uloop(s, true); + + return ret; +} + +static bool __ustream_fd_poll(struct ustream_fd *sf, unsigned int events) +{ + struct ustream *s = &sf->stream; + bool more = false; + + if (events & ULOOP_READ) + ustream_fd_read_pending(sf, &more); + + if (events & ULOOP_WRITE) { + if (!ustream_write_pending(s)) + ustream_fd_set_uloop(s, false); + } + + return more; +} + +static bool ustream_fd_poll(struct ustream *s) +{ + struct ustream_fd *sf = container_of(s, struct ustream_fd, stream); + + return __ustream_fd_poll(sf, ULOOP_READ | ULOOP_WRITE); +} + +static void ustream_uloop_cb(struct uloop_fd *fd, unsigned int events) +{ + struct ustream_fd *sf = container_of(fd, struct ustream_fd, fd); + + __ustream_fd_poll(sf, events); +} + +static void ustream_fd_free(struct ustream *s) +{ + struct ustream_fd *sf = container_of(s, struct ustream_fd, stream); + + uloop_fd_delete(&sf->fd); +} + +void ustream_fd_init(struct ustream_fd *sf, int fd) +{ + struct ustream *s = &sf->stream; + + ustream_init_defaults(s); + + sf->fd.fd = fd; + sf->fd.cb = ustream_uloop_cb; + s->set_read_blocked = ustream_fd_set_read_blocked; + s->write = ustream_fd_write; + s->free = ustream_fd_free; + s->poll = ustream_fd_poll; + ustream_fd_set_uloop(s, false); +} diff --git a/release/src/router/uqmi/libubox/ustream.c b/release/src/router/uqmi/libubox/ustream.c new file mode 100644 index 0000000000..828a025b26 --- /dev/null +++ b/release/src/router/uqmi/libubox/ustream.c @@ -0,0 +1,514 @@ +/* + * ustream - library for stream buffer management + * + * Copyright (C) 2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include "ustream.h" + +static void ustream_init_buf(struct ustream_buf *buf, int len) +{ + if (!len) + abort(); + + memset(buf, 0, sizeof(*buf)); + buf->data = buf->tail = buf->head; + buf->end = buf->head + len; + *buf->head = 0; +} + +static void ustream_add_buf(struct ustream_buf_list *l, struct ustream_buf *buf) +{ + l->buffers++; + if (!l->tail) + l->head = buf; + else + l->tail->next = buf; + + buf->next = NULL; + l->tail = buf; + if (!l->data_tail) + l->data_tail = l->head; +} + +static bool ustream_can_alloc(struct ustream_buf_list *l) +{ + if (l->max_buffers <= 0) + return true; + + return (l->buffers < l->max_buffers); +} + +static int ustream_alloc_default(struct ustream *s, struct ustream_buf_list *l) +{ + struct ustream_buf *buf; + + if (!ustream_can_alloc(l)) + return -1; + + buf = malloc(sizeof(*buf) + l->buffer_len + s->string_data); + ustream_init_buf(buf, l->buffer_len); + ustream_add_buf(l, buf); + + return 0; +} + +static void ustream_free_buffers(struct ustream_buf_list *l) +{ + struct ustream_buf *buf = l->head; + + while (buf) { + struct ustream_buf *next = buf->next; + + free(buf); + buf = next; + } + l->head = NULL; + l->tail = NULL; + l->data_tail = NULL; +} + +void ustream_free(struct ustream *s) +{ + if (s->free) + s->free(s); + + uloop_timeout_cancel(&s->state_change); + ustream_free_buffers(&s->r); + ustream_free_buffers(&s->w); +} + +static void ustream_state_change_cb(struct uloop_timeout *t) +{ + struct ustream *s = container_of(t, struct ustream, state_change); + + if (s->write_error) + ustream_free_buffers(&s->w); + if (s->notify_state) + s->notify_state(s); +} + +void ustream_init_defaults(struct ustream *s) +{ +#define DEFAULT_SET(_f, _default) \ + do { \ + if (!_f) \ + _f = _default; \ + } while(0) + + DEFAULT_SET(s->r.alloc, ustream_alloc_default); + DEFAULT_SET(s->w.alloc, ustream_alloc_default); + + DEFAULT_SET(s->r.min_buffers, 1); + DEFAULT_SET(s->r.max_buffers, 1); + DEFAULT_SET(s->r.buffer_len, 4096); + + DEFAULT_SET(s->w.min_buffers, 2); + DEFAULT_SET(s->w.max_buffers, -1); + DEFAULT_SET(s->w.buffer_len, 256); + +#undef DEFAULT_SET + + s->state_change.cb = ustream_state_change_cb; + s->write_error = false; + s->eof = false; + s->eof_write_done = false; + s->read_blocked = 0; + + s->r.buffers = 0; + s->r.data_bytes = 0; + + s->w.buffers = 0; + s->w.data_bytes = 0; +} + +static bool ustream_should_move(struct ustream_buf_list *l, struct ustream_buf *buf, int len) +{ + int maxlen; + int offset; + + if (buf->data == buf->head) + return false; + + maxlen = buf->end - buf->head; + offset = buf->data - buf->head; + + if (offset > maxlen / 2) + return true; + + if (buf->tail - buf->data < 32 && offset > maxlen / 4) + return true; + + if (buf != l->tail || ustream_can_alloc(l)) + return false; + + return (buf->end - buf->tail < len); +} + +static void ustream_free_buf(struct ustream_buf_list *l, struct ustream_buf *buf) +{ + if (buf == l->head) + l->head = buf->next; + + if (buf == l->data_tail) + l->data_tail = buf->next; + + if (buf == l->tail) + l->tail = NULL; + + if (--l->buffers >= l->min_buffers) { + free(buf); + return; + } + + /* recycle */ + ustream_init_buf(buf, buf->end - buf->head); + ustream_add_buf(l, buf); +} + +static void __ustream_set_read_blocked(struct ustream *s, unsigned char val) +{ + bool changed = !!s->read_blocked != !!val; + + s->read_blocked = val; + if (changed) + s->set_read_blocked(s); +} + +void ustream_set_read_blocked(struct ustream *s, bool set) +{ + unsigned char val = s->read_blocked & ~READ_BLOCKED_USER; + + if (set) + val |= READ_BLOCKED_USER; + + __ustream_set_read_blocked(s, val); +} + +void ustream_consume(struct ustream *s, int len) +{ + struct ustream_buf *buf = s->r.head; + + if (!len) + return; + + s->r.data_bytes -= len; + if (s->r.data_bytes < 0) + abort(); + + do { + struct ustream_buf *next = buf->next; + int buf_len = buf->tail - buf->data; + + if (len < buf_len) { + buf->data += len; + break; + } + + len -= buf_len; + ustream_free_buf(&s->r, buf); + buf = next; + } while(len); + + __ustream_set_read_blocked(s, s->read_blocked & ~READ_BLOCKED_FULL); +} + +static void ustream_fixup_string(struct ustream *s, struct ustream_buf *buf) +{ + if (!s->string_data) + return; + + *buf->tail = 0; +} + +static bool ustream_prepare_buf(struct ustream *s, struct ustream_buf_list *l, int len) +{ + struct ustream_buf *buf; + + buf = l->data_tail; + if (buf) { + if (ustream_should_move(l, buf, len)) { + int len = buf->tail - buf->data; + + memmove(buf->head, buf->data, len); + buf->data = buf->head; + buf->tail = buf->data + len; + + if (l == &s->r) + ustream_fixup_string(s, buf); + } + if (buf->tail != buf->end) + return true; + } + + if (buf && buf->next) { + l->data_tail = buf->next; + return true; + } + + if (!ustream_can_alloc(l)) + return false; + + if (l->alloc(s, l) < 0) + return false; + + l->data_tail = l->tail; + return true; +} + +char *ustream_reserve(struct ustream *s, int len, int *maxlen) +{ + struct ustream_buf *buf; + + if (!ustream_prepare_buf(s, &s->r, len)) { + __ustream_set_read_blocked(s, s->read_blocked | READ_BLOCKED_FULL); + *maxlen = 0; + return NULL; + } + + buf = s->r.data_tail; + *maxlen = buf->end - buf->tail; + return buf->tail; +} + +void ustream_fill_read(struct ustream *s, int len) +{ + struct ustream_buf *buf = s->r.data_tail; + int n = len; + int maxlen; + + s->r.data_bytes += len; + do { + if (!buf) + abort(); + + maxlen = buf->end - buf->tail; + if (len < maxlen) + maxlen = len; + + len -= maxlen; + buf->tail += maxlen; + ustream_fixup_string(s, buf); + + s->r.data_tail = buf; + buf = buf->next; + } while (len); + + if (s->notify_read) + s->notify_read(s, n); +} + +char *ustream_get_read_buf(struct ustream *s, int *buflen) +{ + char *data = NULL; + int len = 0; + + if (s->r.head) { + len = s->r.head->tail - s->r.head->data; + if (len > 0) + data = s->r.head->data; + } + + if (buflen) + *buflen = len; + + return data; +} + +static void ustream_write_error(struct ustream *s) +{ + if (!s->write_error) + ustream_state_change(s); + s->write_error = true; +} + +bool ustream_write_pending(struct ustream *s) +{ + struct ustream_buf *buf = s->w.head; + int wr = 0, len; + + if (s->write_error) + return false; + + while (buf && s->w.data_bytes) { + struct ustream_buf *next = buf->next; + int maxlen = buf->tail - buf->data; + + len = s->write(s, buf->data, maxlen, !!buf->next); + if (len < 0) { + ustream_write_error(s); + break; + } + + if (len == 0) + break; + + wr += len; + s->w.data_bytes -= len; + if (len < maxlen) { + buf->data += len; + break; + } + + ustream_free_buf(&s->w, buf); + buf = next; + } + + if (s->notify_write) + s->notify_write(s, wr); + + if (s->eof && wr && !s->w.data_bytes) + ustream_state_change(s); + + return !s->w.data_bytes; +} + +static int ustream_write_buffered(struct ustream *s, const char *data, int len, int wr) +{ + struct ustream_buf_list *l = &s->w; + struct ustream_buf *buf; + int maxlen; + + while (len) { + if (!ustream_prepare_buf(s, &s->w, len)) + break; + + buf = l->data_tail; + + maxlen = buf->end - buf->tail; + if (maxlen > len) + maxlen = len; + + memcpy(buf->tail, data, maxlen); + buf->tail += maxlen; + data += maxlen; + len -= maxlen; + wr += maxlen; + l->data_bytes += maxlen; + } + + return wr; +} + +int ustream_write(struct ustream *s, const char *data, int len, bool more) +{ + struct ustream_buf_list *l = &s->w; + int wr = 0; + + if (s->write_error) + return 0; + + if (!l->data_bytes) { + wr = s->write(s, data, len, more); + if (wr == len) + return wr; + + if (wr < 0) { + ustream_write_error(s); + return wr; + } + + data += wr; + len -= wr; + } + + return ustream_write_buffered(s, data, len, wr); +} + +#define MAX_STACK_BUFLEN 256 + +int ustream_vprintf(struct ustream *s, const char *format, va_list arg) +{ + struct ustream_buf_list *l = &s->w; + char *buf; + va_list arg2; + int wr, maxlen, buflen; + + if (s->write_error) + return 0; + + if (!l->data_bytes) { + buf = alloca(MAX_STACK_BUFLEN); + va_copy(arg2, arg); + maxlen = vsnprintf(buf, MAX_STACK_BUFLEN, format, arg2); + va_end(arg2); + if (maxlen < MAX_STACK_BUFLEN) { + wr = s->write(s, buf, maxlen, false); + if (wr < 0) { + ustream_write_error(s); + return wr; + } + if (wr == maxlen) + return wr; + + buf += wr; + maxlen -= wr; + return ustream_write_buffered(s, buf, maxlen, wr); + } else { + buf = malloc(maxlen + 1); + wr = vsnprintf(buf, maxlen + 1, format, arg); + wr = ustream_write(s, buf, wr, false); + free(buf); + return wr; + } + } + + if (!ustream_prepare_buf(s, l, 1)) + return 0; + + buf = l->data_tail->tail; + buflen = l->data_tail->end - buf; + + va_copy(arg2, arg); + maxlen = vsnprintf(buf, buflen, format, arg2); + va_end(arg2); + + wr = maxlen; + if (wr >= buflen) + wr = buflen - 1; + + l->data_tail->tail += wr; + l->data_bytes += wr; + if (maxlen < buflen) + return wr; + + buf = malloc(maxlen + 1); + maxlen = vsnprintf(buf, maxlen + 1, format, arg); + wr = ustream_write_buffered(s, buf + wr, maxlen - wr, wr); + free(buf); + + return wr; +} + +int ustream_printf(struct ustream *s, const char *format, ...) +{ + va_list arg; + int ret; + + if (s->write_error) + return 0; + + va_start(arg, format); + ret = ustream_vprintf(s, format, arg); + va_end(arg); + + return ret; +} diff --git a/release/src/router/uqmi/libubox/ustream.h b/release/src/router/uqmi/libubox/ustream.h new file mode 100644 index 0000000000..6431744155 --- /dev/null +++ b/release/src/router/uqmi/libubox/ustream.h @@ -0,0 +1,214 @@ +/* + * ustream - library for stream buffer management + * + * Copyright (C) 2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __USTREAM_H +#define __USTREAM_H + +#include +#include "uloop.h" + +struct ustream; +struct ustream_buf; + +enum read_blocked_reason { + READ_BLOCKED_USER = (1 << 0), + READ_BLOCKED_FULL = (1 << 1), +}; + +struct ustream_buf_list { + struct ustream_buf *head; + struct ustream_buf *data_tail; + struct ustream_buf *tail; + + int (*alloc)(struct ustream *s, struct ustream_buf_list *l); + + int data_bytes; + + int min_buffers; + int max_buffers; + int buffer_len; + + int buffers; +}; + +struct ustream { + struct ustream_buf_list r, w; + struct uloop_timeout state_change; + struct ustream *next; + + /* + * notify_read: (optional) + * called by the ustream core to notify that new data is available + * for reading. + * must not free the ustream from this callback + */ + void (*notify_read)(struct ustream *s, int bytes_new); + + /* + * notify_write: (optional) + * called by the ustream core to notify that some buffered data has + * been written to the stream. + * must not free the ustream from this callback + */ + void (*notify_write)(struct ustream *s, int bytes); + + /* + * notify_state: (optional) + * called by the ustream implementation to notify that the read + * side of the stream is closed (eof is set) or there was a write + * error (write_error is set). + * will be called again after the write buffer has been emptied when + * the read side has hit EOF. + */ + void (*notify_state)(struct ustream *s); + + /* + * write: + * must be defined by ustream implementation, accepts new write data. + * 'more' is used to indicate that a subsequent call will provide more + * data (useful for aggregating writes) + * returns the number of bytes accepted, or -1 if no more writes can + * be accepted (link error) + */ + int (*write)(struct ustream *s, const char *buf, int len, bool more); + + /* + * free: (optional) + * defined by ustream implementation, tears down the ustream and frees data + */ + void (*free)(struct ustream *s); + + /* + * set_read_blocked: (optional) + * defined by ustream implementation, called when the read_blocked flag + * changes + */ + void (*set_read_blocked)(struct ustream *s); + + /* + * poll: (optional) + * defined by the upstream implementation, called to request polling for + * available data. + * returns true if data was fetched. + */ + bool (*poll)(struct ustream *s); + + /* + * ustream user should set this if the input stream is expected + * to contain string data. the core will keep all data 0-terminated. + */ + bool string_data; + bool write_error; + bool eof, eof_write_done; + + enum read_blocked_reason read_blocked; +}; + +struct ustream_fd { + struct ustream stream; + struct uloop_fd fd; +}; + +struct ustream_buf { + struct ustream_buf *next; + + char *data; + char *tail; + char *end; + + char head[]; +}; + +/* ustream_fd_init: create a file descriptor ustream (uses uloop) */ +void ustream_fd_init(struct ustream_fd *s, int fd); + +/* ustream_free: free all buffers and data associated with a ustream */ +void ustream_free(struct ustream *s); + +/* ustream_consume: remove data from the head of the read buffer */ +void ustream_consume(struct ustream *s, int len); + +/* ustream_write: add data to the write buffer */ +int ustream_write(struct ustream *s, const char *buf, int len, bool more); +int ustream_printf(struct ustream *s, const char *format, ...); +int ustream_vprintf(struct ustream *s, const char *format, va_list arg); + +/* ustream_get_read_buf: get a pointer to the next read buffer data */ +char *ustream_get_read_buf(struct ustream *s, int *buflen); + +/* + * ustream_set_read_blocked: set read blocked state + * + * if set, the ustream will no longer fetch pending data. + */ +void ustream_set_read_blocked(struct ustream *s, bool set); + +static inline bool ustream_read_blocked(struct ustream *s) +{ + return !!(s->read_blocked & READ_BLOCKED_USER); +} + +static inline int ustream_pending_data(struct ustream *s, bool write) +{ + struct ustream_buf_list *b = write ? &s->w : &s->r; + return b->data_bytes; +} + +static inline bool ustream_read_buf_full(struct ustream *s) +{ + struct ustream_buf *buf = s->r.data_tail; + return buf && buf->data == buf->head && buf->tail == buf->end && + s->r.buffers == s->r.max_buffers; +} + +/*** --- functions only used by ustream implementations --- ***/ + +/* ustream_init_defaults: fill default callbacks and options */ +void ustream_init_defaults(struct ustream *s); + +/* + * ustream_reserve: allocate rx buffer space + * + * len: hint for how much space is needed (not guaranteed to be met) + * maxlen: pointer to where the actual buffer size is going to be stored + */ +char *ustream_reserve(struct ustream *s, int len, int *maxlen); + +/* ustream_fill_read: mark rx buffer space as filled */ +void ustream_fill_read(struct ustream *s, int len); + +/* + * ustream_write_pending: attempt to write more data from write buffers + * returns true if all write buffers have been emptied. + */ +bool ustream_write_pending(struct ustream *s); + +static inline void ustream_state_change(struct ustream *s) +{ + uloop_timeout_set(&s->state_change, 0); +} + +static inline bool ustream_poll(struct ustream *s) +{ + if (!s->poll) + return false; + + return s->poll(s); +} + +#endif diff --git a/release/src/router/uqmi/libubox/utils.c b/release/src/router/uqmi/libubox/utils.c new file mode 100644 index 0000000000..078a8a191a --- /dev/null +++ b/release/src/router/uqmi/libubox/utils.c @@ -0,0 +1,94 @@ +/* + * utils - misc libubox utility functions + * + * Copyright (C) 2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "utils.h" +#include +#include +#include + +#define foreach_arg(_arg, _addr, _len, _first_addr, _first_len) \ + for (_addr = (_first_addr), _len = (_first_len); \ + _addr; \ + _addr = va_arg(_arg, void **), _len = _addr ? va_arg(_arg, size_t) : 0) + +void *__calloc_a(size_t len, ...) +{ + va_list ap, ap1; + void *ret; + void **cur_addr; + size_t cur_len; + int alloc_len = 0; + char *ptr; + + va_start(ap, len); + + va_copy(ap1, ap); + foreach_arg(ap1, cur_addr, cur_len, &ret, len) + alloc_len += cur_len; + va_end(ap1); + + ptr = calloc(1, alloc_len); + alloc_len = 0; + foreach_arg(ap, cur_addr, cur_len, &ret, len) { + *cur_addr = &ptr[alloc_len]; + alloc_len += cur_len; + } + va_end(ap); + + return ret; +} + +#ifdef __APPLE__ +#include + +static void clock_gettime_realtime(struct timespec *tv) +{ + struct timeval _tv; + + gettimeofday(&_tv, NULL); + tv->tv_sec = _tv.tv_sec; + tv->tv_nsec = _tv.tv_usec * 1000; +} + +static void clock_gettime_monotonic(struct timespec *tv) +{ + mach_timebase_info_data_t info; + float sec; + uint64_t val; + + mach_timebase_info(&info); + + val = mach_absolute_time(); + tv->tv_nsec = (val * info.numer / info.denom) % 1000000000; + + sec = val; + sec *= info.numer; + sec /= info.denom; + sec /= 1000000000; + tv->tv_sec = sec; +} + +void clock_gettime(int type, struct timespec *tv) +{ + if (type == CLOCK_REALTIME) + return clock_gettime_realtime(tv); + else + return clock_gettime_monotonic(tv); +} + +#endif diff --git a/release/src/router/uqmi/libubox/utils.h b/release/src/router/uqmi/libubox/utils.h new file mode 100644 index 0000000000..b65a4eee88 --- /dev/null +++ b/release/src/router/uqmi/libubox/utils.h @@ -0,0 +1,182 @@ +/* + * utils - misc libubox utility functions + * + * Copyright (C) 2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __LIBUBOX_UTILS_H +#define __LIBUBOX_UTILS_H + +#include +#include +#include +#include +#include + +/* + * calloc_a(size_t len, [void **addr, size_t len,...], NULL) + * + * allocate a block of memory big enough to hold multiple aligned objects. + * the pointer to the full object (starting with the first chunk) is returned, + * all other pointers are stored in the locations behind extra addr arguments. + * the last argument needs to be a NULL pointer + */ + +#define calloc_a(len, ...) __calloc_a(len, ##__VA_ARGS__, NULL) + +void *__calloc_a(size_t len, ...); + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#endif + +#define __BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) + +#ifdef __OPTIMIZE__ +extern int __BUILD_BUG_ON_CONDITION_FAILED; +#define BUILD_BUG_ON(condition) \ + do { \ + __BUILD_BUG_ON(condition); \ + if (condition) \ + __BUILD_BUG_ON_CONDITION_FAILED = 1; \ + } while(0) +#else +#define BUILD_BUG_ON __BUILD_BUG_ON +#endif + +#ifdef __APPLE__ + +#define CLOCK_REALTIME 0 +#define CLOCK_MONOTONIC 1 + +void clock_gettime(int type, struct timespec *tv); + +#endif + +#ifdef __GNUC__ +#define _GNUC_MIN_VER(maj, min) (((__GNUC__ << 8) + __GNUC_MINOR__) >= (((maj) << 8) + (min))) +#else +#define _GNUC_MIN_VER(maj, min) 0 +#endif + +#if defined(__linux__) || defined(__CYGWIN__) +#include +#include + +#elif defined(__APPLE__) +#include +#include +#define bswap_32(x) OSSwapInt32(x) +#define bswap_64(x) OSSwapInt64(x) +#elif defined(__FreeBSD__) +#include +#define bswap_32(x) bswap32(x) +#define bswap_64(x) bswap64(x) +#else +#include +#define bswap_32(x) swap32(x) +#define bswap_64(x) swap64(x) +#endif + +#ifndef __BYTE_ORDER +#define __BYTE_ORDER BYTE_ORDER +#endif +#ifndef __BIG_ENDIAN +#define __BIG_ENDIAN BIG_ENDIAN +#endif +#ifndef __LITTLE_ENDIAN +#define __LITTLE_ENDIAN LITTLE_ENDIAN +#endif + +static inline uint16_t __u_bswap16(uint16_t val) +{ + return ((val >> 8) & 0xffu) | ((val & 0xffu) << 8); +} + +//#if _GNUC_MIN_VER(4, 2) +//#define __u_bswap32(x) __builtin_bswap32(x) +//define __u_bswap64(x) __builtin_bswap64(x) +//#else +#define __u_bswap32(x) bswap_32(x) +#define __u_bswap64(x) bswap_64(x) +//#endif + +#if __BYTE_ORDER == __LITTLE_ENDIAN + +#define cpu_to_be64(x) __u_bswap64(x) +#define cpu_to_be32(x) __u_bswap32(x) +#define cpu_to_be16(x) __u_bswap16((uint16_t) (x)) + +#define be64_to_cpu(x) __u_bswap64(x) +#define be32_to_cpu(x) __u_bswap32(x) +#define be16_to_cpu(x) __u_bswap16((uint16_t) (x)) + +#define cpu_to_le64(x) (x) +#define cpu_to_le32(x) (x) +#define cpu_to_le16(x) (x) + +#define le64_to_cpu(x) (x) +#define le32_to_cpu(x) (x) +#define le16_to_cpu(x) (x) + +#else /* __BYTE_ORDER == __LITTLE_ENDIAN */ + +#define cpu_to_le64(x) __u_bswap64(x) +#define cpu_to_le32(x) __u_bswap32(x) +#define cpu_to_le16(x) __u_bswap16((uint16_t) (x)) + +#define le64_to_cpu(x) __u_bswap64(x) +#define le32_to_cpu(x) __u_bswap32(x) +#define le16_to_cpu(x) __u_bswap16((uint16_t) (x)) + +#define cpu_to_be64(x) (x) +#define cpu_to_be32(x) (x) +#define cpu_to_be16(x) (x) + +#define be64_to_cpu(x) (x) +#define be32_to_cpu(x) (x) +#define be16_to_cpu(x) (x) + +#endif + +#ifndef __packed +#define __packed __attribute__((packed)) +#endif + +#ifndef __constructor +#define __constructor __attribute__((constructor)) +#endif + +#ifndef __hidden +#define __hidden __attribute__((visibility("hidden"))) +#endif + +#ifndef BITS_PER_LONG +#define BITS_PER_LONG (8 * sizeof(unsigned long)) +#endif + +#define BITFIELD_SIZE(_n) (((_n) + (BITS_PER_LONG - 1)) / BITS_PER_LONG) + +static inline void bitfield_set(unsigned long *bits, int bit) +{ + bits[bit / BITS_PER_LONG] |= (1UL << (bit % BITS_PER_LONG)); +} + +static inline bool bitfield_test(unsigned long *bits, int bit) +{ + return !!(bits[bit / BITS_PER_LONG] & (1UL << (bit % BITS_PER_LONG))); +} + +#endif diff --git a/release/src/router/uqmi/libubox/vlist.c b/release/src/router/uqmi/libubox/vlist.c new file mode 100644 index 0000000000..d497c63284 --- /dev/null +++ b/release/src/router/uqmi/libubox/vlist.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "vlist.h" + +void +vlist_init(struct vlist_tree *tree, avl_tree_comp cmp, vlist_update_cb update) +{ + tree->update = update; + tree->version = 1; + + avl_init(&tree->avl, cmp, 0, tree); +} + +void +vlist_delete(struct vlist_tree *tree, struct vlist_node *node) +{ + if (!tree->no_delete) + avl_delete(&tree->avl, &node->avl); + tree->update(tree, NULL, node); +} + +void +vlist_add(struct vlist_tree *tree, struct vlist_node *node, const void *key) +{ + struct vlist_node *old_node = NULL; + struct avl_node *anode; + + node->avl.key = key; + node->version = tree->version; + + anode = avl_find(&tree->avl, key); + if (anode) { + old_node = container_of(anode, struct vlist_node, avl); + if (tree->keep_old || tree->no_delete) { + old_node->version = tree->version; + goto update_only; + } + + avl_delete(&tree->avl, anode); + } + + avl_insert(&tree->avl, &node->avl); + +update_only: + tree->update(tree, node, old_node); +} + +void +vlist_flush(struct vlist_tree *tree) +{ + struct vlist_node *node, *tmp; + + avl_for_each_element_safe(&tree->avl, node, avl, tmp) { + if ((node->version == tree->version || node->version == -1) && + tree->version != -1) + continue; + + vlist_delete(tree, node); + } +} + +void +vlist_flush_all(struct vlist_tree *tree) +{ + tree->version = -1; + vlist_flush(tree); +} + + diff --git a/release/src/router/uqmi/libubox/vlist.h b/release/src/router/uqmi/libubox/vlist.h new file mode 100644 index 0000000000..8170abf740 --- /dev/null +++ b/release/src/router/uqmi/libubox/vlist.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __LIBUBOX_VLIST_H +#define __LIBUBOX_VLIST_H + +#include "avl.h" + +struct vlist_tree; +struct vlist_node; + +typedef void (*vlist_update_cb)(struct vlist_tree *tree, + struct vlist_node *node_new, + struct vlist_node *node_old); + +struct vlist_tree { + struct avl_tree avl; + + vlist_update_cb update; + bool keep_old; + bool no_delete; + + int version; +}; + +struct vlist_node { + struct avl_node avl; + int version; +}; + +#define VLIST_TREE_INIT(_name, _comp, _update, _keep_old, _no_delete) \ + { \ + .avl = AVL_TREE_INIT(_name.avl, _comp, false, NULL), \ + .update = _update, \ + .version = 1, \ + .keep_old = _keep_old, \ + .no_delete = _no_delete, \ + } + +#define VLIST_TREE(_name, ...) \ + struct vlist_tree _name = \ + VLIST_TREE_INIT(_name, __VA_ARGS__) + +void vlist_init(struct vlist_tree *tree, avl_tree_comp cmp, vlist_update_cb update); + +#define vlist_find(tree, name, element, node_member) \ + avl_find_element(&(tree)->avl, name, element, node_member.avl) + +static inline void vlist_update(struct vlist_tree *tree) +{ + tree->version++; +} + +void vlist_add(struct vlist_tree *tree, struct vlist_node *node, const void *key); +void vlist_delete(struct vlist_tree *tree, struct vlist_node *node); +void vlist_flush(struct vlist_tree *tree); +void vlist_flush_all(struct vlist_tree *tree); + +#define vlist_for_each_element(tree, element, node_member) \ + avl_for_each_element(&(tree)->avl, element, node_member.avl) + +#endif diff --git a/release/src/router/uqmi/main.c b/release/src/router/uqmi/main.c new file mode 100644 index 0000000000..028c3a9bb1 --- /dev/null +++ b/release/src/router/uqmi/main.c @@ -0,0 +1,152 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2014-2015 Felix Fietkau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uqmi.h" +#include "commands.h" + +static const char *device; + +#define CMD_OPT(_arg) (-2 - _arg) + +#define __uqmi_command(_name, _optname, _arg, _option) { #_optname, _arg##_argument, NULL, CMD_OPT(__UQMI_COMMAND_##_name) } +static const struct option uqmi_getopt[] = { + __uqmi_commands, + { "single", no_argument, NULL, 's' }, + { "device", required_argument, NULL, 'd' }, + { "keep-client-id", required_argument, NULL, 'k' }, + { "release-client-id", required_argument, NULL, 'r' }, + { NULL, 0, NULL, 0 } +}; +#undef __uqmi_command + +static int usage(const char *progname) +{ + fprintf(stderr, "Usage: %s \n" + "Options:\n" + " --single, -s: Print output as a single line (for scripts)\n" + " --device=NAME, -d NAME: Set device name to NAME (required)\n" + " --keep-client-id : Keep Client ID for service \n" + " --release-client-id : Release Client ID after exiting\n" + "\n" + "Services: dms, nas, pds, wds, wms\n" + "\n" + "Actions:\n" + " --get-versions: Get service versions\n" + " --set-client-id ,: Set Client ID for service to \n" + " (implies --keep-client-id)\n" + " --get-client-id : Connect and get Client ID for service \n" + " (implies --keep-client-id)\n" + wds_helptext + dms_helptext + nas_helptext + wms_helptext + wda_helptext + "\n", progname); + return 1; +} + +static void keep_client_id(struct qmi_dev *qmi, const char *optarg) +{ + QmiService svc = qmi_service_get_by_name(optarg); + if (svc < 0) { + fprintf(stderr, "Invalid service %s\n", optarg); + exit(1); + } + qmi_service_get_client_id(qmi, svc); +} + +static void release_client_id(struct qmi_dev *qmi, const char *optarg) +{ + QmiService svc = qmi_service_get_by_name(optarg); + if (svc < 0) { + fprintf(stderr, "Invalid service %s\n", optarg); + exit(1); + } + qmi_service_release_client_id(qmi, svc); +} + +static void handle_exit_signal(int signal) +{ + cancel_all_requests = true; + uloop_end(); +} + +int main(int argc, char **argv) +{ + static struct qmi_dev dev; + int ch, ret; + + uloop_init(); + signal(SIGINT, handle_exit_signal); + signal(SIGTERM, handle_exit_signal); + + while ((ch = getopt_long(argc, argv, "d:k:s", uqmi_getopt, NULL)) != -1) { + int cmd_opt = CMD_OPT(ch); + + if (ch < 0 && cmd_opt >= 0 && cmd_opt < __UQMI_COMMAND_LAST) { + uqmi_add_command(optarg, cmd_opt); + continue; + } + + switch(ch) { + case 'r': + release_client_id(&dev, optarg); + break; + case 'k': + keep_client_id(&dev, optarg); + break; + case 'd': + device = optarg; + break; + case 's': + single_line = true; + break; + default: + return usage(argv[0]); + } + } + + if (!device) { + fprintf(stderr, "No device given\n"); + return usage(argv[0]); + } + + if (qmi_device_open(&dev, device)) { + fprintf(stderr, "Failed to open device\n"); + return 2; + } + + ret = uqmi_run_commands(&dev) ? 0 : -1; + + qmi_device_close(&dev); + + return ret; +} diff --git a/release/src/router/uqmi/qmi-enums-dms.h b/release/src/router/uqmi/qmi-enums-dms.h new file mode 100644 index 0000000000..62c31dabb0 --- /dev/null +++ b/release/src/router/uqmi/qmi-enums-dms.h @@ -0,0 +1,337 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * uqmi -- tiny QMI support implementation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012 Lanedo GmbH + */ + +#ifndef _LIBQMI_GLIB_QMI_ENUMS_DMS_H_ +#define _LIBQMI_GLIB_QMI_ENUMS_DMS_H_ + +/** + * SECTION: qmi-enums-dms + * @title: DMS enumerations and flags + * + * This section defines enumerations and flags used in the DMS service + * interface. + */ + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS Get Capabilities' message */ + +/** + * QmiDmsDataServiceCapability: + * @QMI_DMS_DATA_SERVICE_CAPABILITY_NONE: No data services supported. + * @QMI_DMS_DATA_SERVICE_CAPABILITY_CS: Only CS supported. + * @QMI_DMS_DATA_SERVICE_CAPABILITY_PS: Only PS supported. + * @QMI_DMS_DATA_SERVICE_CAPABILITY_SIMULTANEOUS_CS_PS: Simultaneous CS and PS supported. + * @QMI_DMS_DATA_SERVICE_CAPABILITY_NON_SIMULTANEOUS_CS_PS: Non simultaneous CS and PS supported. + * + * Data service capability. + */ +typedef enum { + QMI_DMS_DATA_SERVICE_CAPABILITY_NONE = 0, + QMI_DMS_DATA_SERVICE_CAPABILITY_CS = 1, + QMI_DMS_DATA_SERVICE_CAPABILITY_PS = 2, + QMI_DMS_DATA_SERVICE_CAPABILITY_SIMULTANEOUS_CS_PS = 3, + QMI_DMS_DATA_SERVICE_CAPABILITY_NON_SIMULTANEOUS_CS_PS = 4 +} QmiDmsDataServiceCapability; + +/** + * QmiDmsSimCapability: + * @QMI_DMS_SIM_CAPABILITY_NOT_SUPPORTED: SIM not supported. + * @QMI_DMS_SIM_CAPABILITY_SUPPORTED: SIM is supported. + * + * SIM capability. + */ +typedef enum { + QMI_DMS_SIM_CAPABILITY_NOT_SUPPORTED = 1, + QMI_DMS_SIM_CAPABILITY_SUPPORTED = 2 +} QmiDmsSimCapability; + +/** + * QmiDmsRadioInterface: + * @QMI_DMS_RADIO_INTERFACE_CDMA20001X: CDMA2000 1x. + * @QMI_DMS_RADIO_INTERFACE_EVDO: CDMA2000 HRPD (1xEV-DO) + * @QMI_DMS_RADIO_INTERFACE_GSM: GSM. + * @QMI_DMS_RADIO_INTERFACE_UMTS: UMTS. + * @QMI_DMS_RADIO_INTERFACE_LTE: LTE. + * + * Radio interface type. + */ +typedef enum { + QMI_DMS_RADIO_INTERFACE_CDMA20001X = 1, + QMI_DMS_RADIO_INTERFACE_EVDO = 2, + QMI_DMS_RADIO_INTERFACE_GSM = 4, + QMI_DMS_RADIO_INTERFACE_UMTS = 5, + QMI_DMS_RADIO_INTERFACE_LTE = 8 +} QmiDmsRadioInterface; + + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS Get Power State' message */ + +/** + * QmiDmsPowerState: + * @QMI_DMS_POWER_STATE_EXTERNAL_SOURCE: Powered by an external source. + * @QMI_DMS_POWER_STATE_BATTERY_CONNECTED: Battery is connected. + * @QMI_DMS_POWER_STATE_BATTERY_CHARGING: Battery is currently being charged. + * @QMI_DMS_POWER_STATE_FAULT: Recognized power fault. + * + * Flags specifying the current power state. + * + * If @QMI_DMS_POWER_STATE_EXTERNAL_SOURCE is set, the device is powerered by an + * external source; otherwise it is powered by a battery. + * + * If @QMI_DMS_POWER_STATE_BATTERY_CONNECTED is set, the battery is connected; + * otherwise the battery is not connected. + * + * If @QMI_DMS_POWER_STATE_BATTERY_CHARGING is set, the battery is being charged; + * otherwise the battery is not being charged. + * + * If @QMI_DMS_POWER_STATE_FAULT is set, a power fault has been detected. + */ +typedef enum { + QMI_DMS_POWER_STATE_EXTERNAL_SOURCE = 1 << 0, + QMI_DMS_POWER_STATE_BATTERY_CONNECTED = 1 << 1, + QMI_DMS_POWER_STATE_BATTERY_CHARGING = 1 << 2, + QMI_DMS_POWER_STATE_FAULT = 1 << 3, +} QmiDmsPowerState; + + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS UIM Set PIN Protection' message */ + +/** + * QmiDmsUimPinId: + * @QMI_DMS_UIM_PIN_ID_PIN: PIN. + * @QMI_DMS_UIM_PIN_ID_PIN2: PIN2. + * + * The PIN identifier. + */ +typedef enum { + QMI_DMS_UIM_PIN_ID_PIN = 1, + QMI_DMS_UIM_PIN_ID_PIN2 = 2 +} QmiDmsUimPinId; + + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS UIM Get PIN Status' message */ + +/** + * QmiDmsUimPinStatus: + * @QMI_DMS_UIM_PIN_STATUS_NOT_INITIALIZED: Not initialized. + * @QMI_DMS_UIM_PIN_STATUS_ENABLED_NOT_VERIFIED: Enabled, not verified. + * @QMI_DMS_UIM_PIN_STATUS_ENABLED_VERIFIED: Enabled, verified. + * @QMI_DMS_UIM_PIN_STATUS_DISABLED: Disabled. + * @QMI_DMS_UIM_PIN_STATUS_BLOCKED: Blocked. + * @QMI_DMS_UIM_PIN_STATUS_PERMANENTLY_BLOCKED: Permanently Blocked. + * @QMI_DMS_UIM_PIN_STATUS_UNBLOCKED: Unblocked. + * @QMI_DMS_UIM_PIN_STATUS_CHANGED: Changed. + * + * The PIN status. + */ +typedef enum { + QMI_DMS_UIM_PIN_STATUS_NOT_INITIALIZED = 0, + QMI_DMS_UIM_PIN_STATUS_ENABLED_NOT_VERIFIED = 1, + QMI_DMS_UIM_PIN_STATUS_ENABLED_VERIFIED = 2, + QMI_DMS_UIM_PIN_STATUS_DISABLED = 3, + QMI_DMS_UIM_PIN_STATUS_BLOCKED = 4, + QMI_DMS_UIM_PIN_STATUS_PERMANENTLY_BLOCKED = 5, + QMI_DMS_UIM_PIN_STATUS_UNBLOCKED = 6, + QMI_DMS_UIM_PIN_STATUS_CHANGED = 7, +} QmiDmsUimPinStatus; + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS Get Operating Mode' message */ + +/** + * QmiDmsOperatingMode: + * @QMI_DMS_OPERATING_MODE_ONLINE: Device can acquire a system and make calls. + * @QMI_DMS_OPERATING_MODE_LOW_POWER: Device has temporarily disabled RF. + * @QMI_DMS_OPERATING_MODE_PERSISTENT_LOW_POWER: Device has disabled RF and state persists even after a reset. + * @QMI_DMS_OPERATING_MODE_FACTORY_TEST: Special mode for manufacturer tests. + * @QMI_DMS_OPERATING_MODE_OFFLINE: Device has deactivated RF and is partially shutdown. + * @QMI_DMS_OPERATING_MODE_RESET: Device is in the process of power cycling. + * @QMI_DMS_OPERATING_MODE_SHUTTING_DOWN: Device is in the process of shutting down. + * @QMI_DMS_OPERATING_MODE_MODE_ONLY_LOW_POWER: Mode-only Low Power. + * @QMI_DMS_OPERATING_MODE_UNKNOWN: Unknown. + * + * Operating mode of the device. + */ +typedef enum { + QMI_DMS_OPERATING_MODE_ONLINE = 0, + QMI_DMS_OPERATING_MODE_LOW_POWER = 1, + QMI_DMS_OPERATING_MODE_FACTORY_TEST = 2, + QMI_DMS_OPERATING_MODE_OFFLINE = 3, + QMI_DMS_OPERATING_MODE_RESET = 4, + QMI_DMS_OPERATING_MODE_SHUTTING_DOWN = 5, + QMI_DMS_OPERATING_MODE_PERSISTENT_LOW_POWER = 6, + QMI_DMS_OPERATING_MODE_MODE_ONLY_LOW_POWER = 7, + QMI_DMS_OPERATING_MODE_UNKNOWN = 0xFF +} QmiDmsOperatingMode; + +/** + * QmiDmsOfflineReason: + * @QMI_DMS_OFFLINE_REASON_HOST_IMAGE_MISCONFIGURATION: Host image misconfiguration. + * @QMI_DMS_OFFLINE_REASON_PRI_IMAGE_MISCONFIGURATION: PRI image misconfiguration. + * @QMI_DMS_OFFLINE_REASON_PRI_VERSION_INCOMPATIBLE: PRI version incompatible. + * @QMI_DMS_OFFLINE_REASON_DEVICE_MEMORY_FULL: Memory full, cannot copy PRI information. + * + * Reasons for being in Offline (@QMI_DMS_OPERATING_MODE_OFFLINE) state. + */ +typedef enum { + QMI_DMS_OFFLINE_REASON_HOST_IMAGE_MISCONFIGURATION = 1 << 0, + QMI_DMS_OFFLINE_REASON_PRI_IMAGE_MISCONFIGURATION = 1 << 1, + QMI_DMS_OFFLINE_REASON_PRI_VERSION_INCOMPATIBLE = 1 << 2, + QMI_DMS_OFFLINE_REASON_DEVICE_MEMORY_FULL = 1 << 3 +} QmiDmsOfflineReason; + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS Get Time' message */ + +/** + * QmiDmsTimeSource: + * @QMI_DMS_TIME_SOURCE_DEVICE: 32 kHz device clock. + * @QMI_DMS_TIME_SOURCE_CDMA_NETWORK: CDMA network. + * @QMI_DMS_TIME_SOURCE_HDR_NETWORK: HDR network. + * + * Source of the timestamp. + */ +typedef enum { + QMI_DMS_TIME_SOURCE_DEVICE = 0, + QMI_DMS_TIME_SOURCE_CDMA_NETWORK = 1, + QMI_DMS_TIME_SOURCE_HDR_NETWORK = 2, +} QmiDmsTimeSource; + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS Get Activation State' message */ + +/** + * QmiDmsActivationState: + * @QMI_DMS_ACTIVATION_STATE_NOT_ACTIVATED: Service not activated. + * @QMI_DMS_ACTIVATION_STATE_ACTIVATED: Service is activated. + * @QMI_DMS_ACTIVATION_STATE_CONNECTING: Connection in progress for automatic activation. + * @QMI_DMS_ACTIVATION_STATE_CONNECTED: Connection connected for automatic activation. + * @QMI_DMS_ACTIVATION_STATE_OTASP_AUTHENTICATED: OTASP security authenticated. + * @QMI_DMS_ACTIVATION_STATE_OTASP_NAM: OTASP NAM downloaded. + * @QMI_DMS_ACTIVATION_STATE_OTASP_MDN: OTASP MDN downloaded. + * @QMI_DMS_ACTIVATION_STATE_OTASP_IMSI: OTASP IMSI downloaded. + * @QMI_DMS_ACTIVATION_STATE_OTASP_PRL: OTASP PRL downloaded. + * @QMI_DMS_ACTIVATION_STATE_OTASP_SPC: OTASP SPC downloaded. + * @QMI_DMS_ACTIVATION_STATE_OTASP_COMMITED: OTASP settings committed. + * + * State of the service activation. + */ +typedef enum { + QMI_DMS_ACTIVATION_STATE_NOT_ACTIVATED = 0x00, + QMI_DMS_ACTIVATION_STATE_ACTIVATED = 0x01, + QMI_DMS_ACTIVATION_STATE_CONNECTING = 0x02, + QMI_DMS_ACTIVATION_STATE_CONNECTED = 0x03, + QMI_DMS_ACTIVATION_STATE_OTASP_AUTHENTICATED = 0x04, + QMI_DMS_ACTIVATION_STATE_OTASP_NAM = 0x05, + QMI_DMS_ACTIVATION_STATE_OTASP_MDN = 0x06, + QMI_DMS_ACTIVATION_STATE_OTASP_IMSI = 0x07, + QMI_DMS_ACTIVATION_STATE_OTASP_PRL = 0x08, + QMI_DMS_ACTIVATION_STATE_OTASP_SPC = 0x09, + QMI_DMS_ACTIVATION_STATE_OTASP_COMMITED = 0x0A +} QmiDmsActivationState; + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS UIM Get CK Status' message */ + +/** + * QmiDmsUimFacility: + * @QMI_DMS_UIM_FACILITY_PN: Network personalization facility. + * @QMI_DMS_UIM_FACILITY_PU: Network subset personalization facility. + * @QMI_DMS_UIM_FACILITY_PP: Service provider facility. + * @QMI_DMS_UIM_FACILITY_PC: Corporate personalization facility. + * @QMI_DMS_UIM_FACILITY_PF: UIM personalization facility. + * + * UIM personalization facilities. + */ +typedef enum { + QMI_DMS_UIM_FACILITY_PN = 0, + QMI_DMS_UIM_FACILITY_PU = 1, + QMI_DMS_UIM_FACILITY_PP = 2, + QMI_DMS_UIM_FACILITY_PC = 3, + QMI_DMS_UIM_FACILITY_PF = 4 +} QmiDmsUimFacility; + +/** + * QmiDmsUimFacilityState: + * @QMI_DMS_UIM_FACILITY_STATE_DEACTIVATED: Facility is deactivated. + * @QMI_DMS_UIM_FACILITY_STATE_ACTIVATED: Facility is activated. + * @QMI_DMS_UIM_FACILITY_STATE_BLOCKED: Facility is blocked. + */ +typedef enum { + QMI_DMS_UIM_FACILITY_STATE_DEACTIVATED = 0, + QMI_DMS_UIM_FACILITY_STATE_ACTIVATED = 1, + QMI_DMS_UIM_FACILITY_STATE_BLOCKED = 2 +} QmiDmsUimFacilityState; + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS UIM Get State' message */ + +/** + * QmiDmsUimState: + * @QMI_DMS_UIM_STATE_INITIALIZATION_COMPLETED: UIM initialization completed. + * @QMI_DMS_UIM_STATE_LOCKED_OR_FAILED: UIM is locked or failed. + * @QMI_DMS_UIM_STATE_NOT_PRESENT: No UIM in the device. + * @QMI_DMS_UIM_STATE_RESERVED: Reserved, unknown. + * @QMI_DMS_UIM_STATE_UNKNOWN: UIM state currently unavailable. + * + * State of the UIM. + */ +typedef enum { + QMI_DMS_UIM_STATE_INITIALIZATION_COMPLETED = 0x00, + QMI_DMS_UIM_STATE_LOCKED_OR_FAILED = 0x01, + QMI_DMS_UIM_STATE_NOT_PRESENT = 0x02, + QMI_DMS_UIM_STATE_RESERVED = 0x03, + QMI_DMS_UIM_STATE_UNKNOWN = 0xFF +} QmiDmsUimState; + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS Set Time' message */ + +/** + * QmiDmsTimeReferenceType: + * @QMI_DMS_TIME_REFERENCE_TYPE_USER: User time. + * + * Time reference type. + */ +typedef enum { + QMI_DMS_TIME_REFERENCE_TYPE_USER = 0 +} QmiDmsTimeReferenceType; + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS Get Firmware Preference' message */ + +/** + * QmiDmsFirmwareImageType: + * @QMI_DMS_FIRMWARE_IMAGE_TYPE_MODEM: Modem image. + * @QMI_DMS_FIRMWARE_IMAGE_TYPE_PRI: PRI image. + * + * Type of firmware image. + */ +typedef enum { + QMI_DMS_FIRMWARE_IMAGE_TYPE_MODEM = 0, + QMI_DMS_FIRMWARE_IMAGE_TYPE_PRI = 1 +} QmiDmsFirmwareImageType; + +#endif /* _LIBQMI_GLIB_QMI_ENUMS_DMS_H_ */ diff --git a/release/src/router/uqmi/qmi-enums-nas.h b/release/src/router/uqmi/qmi-enums-nas.h new file mode 100644 index 0000000000..d278d812f1 --- /dev/null +++ b/release/src/router/uqmi/qmi-enums-nas.h @@ -0,0 +1,892 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * uqmi -- tiny QMI support implementation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012 Google Inc. + */ + +#ifndef _LIBQMI_GLIB_QMI_ENUMS_NAS_H_ +#define _LIBQMI_GLIB_QMI_ENUMS_NAS_H_ + +/** + * SECTION: qmi-enums-nas + * @title: NAS enumerations and flags + * + * This section defines enumerations and flags used in the NAS service + * interface. + */ + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Event Report' indication */ + +/** + * QmiNasRadioInterface: + * @QMI_NAS_RADIO_INTERFACE_UNKNOWN: Not known or not needed. + * @QMI_NAS_RADIO_INTERFACE_NONE: None, no service. + * @QMI_NAS_RADIO_INTERFACE_CDMA_1X: CDMA2000 1X. + * @QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO: CDMA2000 HRPD (1xEV-DO). + * @QMI_NAS_RADIO_INTERFACE_AMPS: AMPS. + * @QMI_NAS_RADIO_INTERFACE_GSM: GSM. + * @QMI_NAS_RADIO_INTERFACE_UMTS: UMTS. + * @QMI_NAS_RADIO_INTERFACE_LTE: LTE. + * @QMI_NAS_RADIO_INTERFACE_TD_SCDMA: TD-SCDMA. + * + * Radio interface technology. + */ +typedef enum { + QMI_NAS_RADIO_INTERFACE_UNKNOWN = -1, + QMI_NAS_RADIO_INTERFACE_NONE = 0x00, + QMI_NAS_RADIO_INTERFACE_CDMA_1X = 0x01, + QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO = 0x02, + QMI_NAS_RADIO_INTERFACE_AMPS = 0x03, + QMI_NAS_RADIO_INTERFACE_GSM = 0x04, + QMI_NAS_RADIO_INTERFACE_UMTS = 0x05, + QMI_NAS_RADIO_INTERFACE_LTE = 0x08, + QMI_NAS_RADIO_INTERFACE_TD_SCDMA = 0x09 +} QmiNasRadioInterface; + +/** + * QmiNasActiveBand: + * @QMI_NAS_ACTIVE_BAND_BC_0: Band class 0. + * @QMI_NAS_ACTIVE_BAND_BC_1: Band class 1. + * @QMI_NAS_ACTIVE_BAND_BC_2: Band class 2. + * @QMI_NAS_ACTIVE_BAND_BC_3: Band class 3. + * @QMI_NAS_ACTIVE_BAND_BC_4: Band class 4. + * @QMI_NAS_ACTIVE_BAND_BC_5: Band class 5. + * @QMI_NAS_ACTIVE_BAND_BC_6: Band class 6. + * @QMI_NAS_ACTIVE_BAND_BC_7: Band class 7. + * @QMI_NAS_ACTIVE_BAND_BC_8: Band class 8. + * @QMI_NAS_ACTIVE_BAND_BC_9: Band class 9. + * @QMI_NAS_ACTIVE_BAND_BC_10: Band class 10. + * @QMI_NAS_ACTIVE_BAND_BC_11: Band class 11. + * @QMI_NAS_ACTIVE_BAND_BC_12: Band class 12. + * @QMI_NAS_ACTIVE_BAND_BC_13: Band class 13. + * @QMI_NAS_ACTIVE_BAND_BC_14: Band class 14. + * @QMI_NAS_ACTIVE_BAND_BC_15: Band class 15. + * @QMI_NAS_ACTIVE_BAND_BC_16: Band class 16. + * @QMI_NAS_ACTIVE_BAND_BC_17: Band class 17. + * @QMI_NAS_ACTIVE_BAND_BC_18: Band class 18. + * @QMI_NAS_ACTIVE_BAND_BC_19: Band class 19. + * @QMI_NAS_ACTIVE_BAND_GSM_450: GSM 450. + * @QMI_NAS_ACTIVE_BAND_GSM_480: GSM 480. + * @QMI_NAS_ACTIVE_BAND_GSM_750: GSM 750. + * @QMI_NAS_ACTIVE_BAND_GSM_850: GSM 850. + * @QMI_NAS_ACTIVE_BAND_GSM_900_EXTENDED: GSM 900 (Extended). + * @QMI_NAS_ACTIVE_BAND_GSM_900_PRIMARY: GSM 900 (Primary). + * @QMI_NAS_ACTIVE_BAND_GSM_900_RAILWAYS: GSM 900 (Railways). + * @QMI_NAS_ACTIVE_BAND_GSM_DCS_1800: GSM 1800. + * @QMI_NAS_ACTIVE_BAND_GSM_PCS_1900: GSM 1900. + * @QMI_NAS_ACTIVE_BAND_WCDMA_2100: WCDMA 2100. + * @QMI_NAS_ACTIVE_BAND_WCDMA_PCS_1900: WCDMA PCS 1900. + * @QMI_NAS_ACTIVE_BAND_WCDMA_DCS_1800: WCDMA DCS 1800. + * @QMI_NAS_ACTIVE_BAND_WCDMA_1700_US: WCDMA 1700 (U.S.). + * @QMI_NAS_ACTIVE_BAND_WCDMA_850: WCDMA 850. + * @QMI_NAS_ACTIVE_BAND_WCDMA_800: WCDMA 800. + * @QMI_NAS_ACTIVE_BAND_WCDMA_2600: WCDMA 2600. + * @QMI_NAS_ACTIVE_BAND_WCDMA_900: WCDMA 900. + * @QMI_NAS_ACTIVE_BAND_WCDMA_1700_JAPAN: WCDMA 1700 (Japan). + * @QMI_NAS_ACTIVE_BAND_WCDMA_1500_JAPAN: WCDMA 1500 (Japan). + * @QMI_NAS_ACTIVE_BAND_WCDMA_850_JAPAN: WCDMA 850 (Japan). + * @QMI_NAS_ACTIVE_BAND_EUTRAN_1: EUTRAN band 1. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_2: EUTRAN band 2. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_3: EUTRAN band 3. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_4: EUTRAN band 4. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_5: EUTRAN band 5. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_6: EUTRAN band 6. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_7: EUTRAN band 7. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_8: EUTRAN band 8. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_9: EUTRAN band 9. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_10: EUTRAN band 10. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_11: EUTRAN band 11. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_12: EUTRAN band 12. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_13: EUTRAN band 13. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_14: EUTRAN band 14. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_17: EUTRAN band 17. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_18: EUTRAN band 18. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_19: EUTRAN band 19. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_20: EUTRAN band 20. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_21: EUTRAN band 21. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_24: EUTRAN band 24. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_25: EUTRAN band 25. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_33: EUTRAN band 33. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_34: EUTRAN band 34. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_35: EUTRAN band 35. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_36: EUTRAN band 36. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_37: EUTRAN band 37. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_38: EUTRAN band 38. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_39: EUTRAN band 39. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_40: EUTRAN band 40. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_41: EUTRAN band 41. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_42: EUTRAN band 42. + * @QMI_NAS_ACTIVE_BAND_EUTRAN_43: EUTRAN band 43. + * @QMI_NAS_ACTIVE_BAND_TDSCDMA_A: TD-SCDMA Band A. + * @QMI_NAS_ACTIVE_BAND_TDSCDMA_B: TD-SCDMA Band B. + * @QMI_NAS_ACTIVE_BAND_TDSCDMA_C: TD-SCDMA Band C. + * @QMI_NAS_ACTIVE_BAND_TDSCDMA_D: TD-SCDMA Band D. + * @QMI_NAS_ACTIVE_BAND_TDSCDMA_E: TD-SCDMA Band E. + * @QMI_NAS_ACTIVE_BAND_TDSCDMA_F: TD-SCDMA Band F. + * + * Band classes. + */ +typedef enum { + QMI_NAS_ACTIVE_BAND_BC_0 = 0, + QMI_NAS_ACTIVE_BAND_BC_1 = 1, + QMI_NAS_ACTIVE_BAND_BC_2 = 2, + QMI_NAS_ACTIVE_BAND_BC_3 = 3, + QMI_NAS_ACTIVE_BAND_BC_4 = 4, + QMI_NAS_ACTIVE_BAND_BC_5 = 5, + QMI_NAS_ACTIVE_BAND_BC_6 = 6, + QMI_NAS_ACTIVE_BAND_BC_7 = 7, + QMI_NAS_ACTIVE_BAND_BC_8 = 8, + QMI_NAS_ACTIVE_BAND_BC_9 = 9, + QMI_NAS_ACTIVE_BAND_BC_10 = 10, + QMI_NAS_ACTIVE_BAND_BC_11 = 11, + QMI_NAS_ACTIVE_BAND_BC_12 = 12, + QMI_NAS_ACTIVE_BAND_BC_13 = 13, + QMI_NAS_ACTIVE_BAND_BC_14 = 14, + QMI_NAS_ACTIVE_BAND_BC_15 = 15, + QMI_NAS_ACTIVE_BAND_BC_16 = 16, + QMI_NAS_ACTIVE_BAND_BC_17 = 17, + QMI_NAS_ACTIVE_BAND_BC_18 = 18, + QMI_NAS_ACTIVE_BAND_BC_19 = 19, + QMI_NAS_ACTIVE_BAND_GSM_450 = 40, + QMI_NAS_ACTIVE_BAND_GSM_480 = 41, + QMI_NAS_ACTIVE_BAND_GSM_750 = 42, + QMI_NAS_ACTIVE_BAND_GSM_850 = 43, + QMI_NAS_ACTIVE_BAND_GSM_900_EXTENDED = 44, + QMI_NAS_ACTIVE_BAND_GSM_900_PRIMARY = 45, + QMI_NAS_ACTIVE_BAND_GSM_900_RAILWAYS = 46, + QMI_NAS_ACTIVE_BAND_GSM_DCS_1800 = 47, + QMI_NAS_ACTIVE_BAND_GSM_PCS_1900 = 48, + QMI_NAS_ACTIVE_BAND_WCDMA_2100 = 80, + QMI_NAS_ACTIVE_BAND_WCDMA_PCS_1900 = 81, + QMI_NAS_ACTIVE_BAND_WCDMA_DCS_1800 = 82, + QMI_NAS_ACTIVE_BAND_WCDMA_1700_US = 83, + QMI_NAS_ACTIVE_BAND_WCDMA_850 = 84, + QMI_NAS_ACTIVE_BAND_WCDMA_800 = 85, + QMI_NAS_ACTIVE_BAND_WCDMA_2600 = 86, + QMI_NAS_ACTIVE_BAND_WCDMA_900 = 87, + QMI_NAS_ACTIVE_BAND_WCDMA_1700_JAPAN = 88, + QMI_NAS_ACTIVE_BAND_WCDMA_1500_JAPAN = 90, + QMI_NAS_ACTIVE_BAND_WCDMA_850_JAPAN = 91, + QMI_NAS_ACTIVE_BAND_EUTRAN_1 = 120, + QMI_NAS_ACTIVE_BAND_EUTRAN_2 = 121, + QMI_NAS_ACTIVE_BAND_EUTRAN_3 = 122, + QMI_NAS_ACTIVE_BAND_EUTRAN_4 = 123, + QMI_NAS_ACTIVE_BAND_EUTRAN_5 = 124, + QMI_NAS_ACTIVE_BAND_EUTRAN_6 = 125, + QMI_NAS_ACTIVE_BAND_EUTRAN_7 = 126, + QMI_NAS_ACTIVE_BAND_EUTRAN_8 = 127, + QMI_NAS_ACTIVE_BAND_EUTRAN_9 = 128, + QMI_NAS_ACTIVE_BAND_EUTRAN_10 = 129, + QMI_NAS_ACTIVE_BAND_EUTRAN_11 = 130, + QMI_NAS_ACTIVE_BAND_EUTRAN_12 = 131, + QMI_NAS_ACTIVE_BAND_EUTRAN_13 = 132, + QMI_NAS_ACTIVE_BAND_EUTRAN_14 = 133, + QMI_NAS_ACTIVE_BAND_EUTRAN_17 = 134, + QMI_NAS_ACTIVE_BAND_EUTRAN_18 = 143, + QMI_NAS_ACTIVE_BAND_EUTRAN_19 = 144, + QMI_NAS_ACTIVE_BAND_EUTRAN_20 = 145, + QMI_NAS_ACTIVE_BAND_EUTRAN_21 = 146, + QMI_NAS_ACTIVE_BAND_EUTRAN_24 = 147, + QMI_NAS_ACTIVE_BAND_EUTRAN_25 = 148, + QMI_NAS_ACTIVE_BAND_EUTRAN_33 = 135, + QMI_NAS_ACTIVE_BAND_EUTRAN_34 = 136, + QMI_NAS_ACTIVE_BAND_EUTRAN_35 = 137, + QMI_NAS_ACTIVE_BAND_EUTRAN_36 = 138, + QMI_NAS_ACTIVE_BAND_EUTRAN_37 = 139, + QMI_NAS_ACTIVE_BAND_EUTRAN_38 = 140, + QMI_NAS_ACTIVE_BAND_EUTRAN_39 = 141, + QMI_NAS_ACTIVE_BAND_EUTRAN_40 = 142, + QMI_NAS_ACTIVE_BAND_EUTRAN_41 = 149, + QMI_NAS_ACTIVE_BAND_EUTRAN_42 = 150, + QMI_NAS_ACTIVE_BAND_EUTRAN_43 = 151, + QMI_NAS_ACTIVE_BAND_TDSCDMA_A = 200, + QMI_NAS_ACTIVE_BAND_TDSCDMA_B = 201, + QMI_NAS_ACTIVE_BAND_TDSCDMA_C = 202, + QMI_NAS_ACTIVE_BAND_TDSCDMA_D = 203, + QMI_NAS_ACTIVE_BAND_TDSCDMA_E = 204, + QMI_NAS_ACTIVE_BAND_TDSCDMA_F = 205 +} QmiNasActiveBand; + +/** + * QmiNasNetworkServiceDomain: + * @QMI_NAS_NETWORK_SERVICE_DOMAIN_NONE: No service. + * @QMI_NAS_NETWORK_SERVICE_DOMAIN_CS: Circuit switched. + * @QMI_NAS_NETWORK_SERVICE_DOMAIN_PS: Packet switched. + * @QMI_NAS_NETWORK_SERVICE_DOMAIN_CS_PS: Circuit and packet switched. + * @QMI_NAS_NETWORK_SERVICE_DOMAIN_UNKNOWN: Unknown service. + * + * Network Service Domain. + */ +typedef enum { + QMI_NAS_NETWORK_SERVICE_DOMAIN_NONE = 0x00, + QMI_NAS_NETWORK_SERVICE_DOMAIN_CS = 0x01, + QMI_NAS_NETWORK_SERVICE_DOMAIN_PS = 0x02, + QMI_NAS_NETWORK_SERVICE_DOMAIN_CS_PS = 0x03, + QMI_NAS_NETWORK_SERVICE_DOMAIN_UNKNOWN = 0x04, +} QmiNasNetworkServiceDomain; + +/** + * QmiNasEvdoSinrLevel: + * @QMI_NAS_EVDO_SINR_LEVEL_0: -9 dB. + * @QMI_NAS_EVDO_SINR_LEVEL_1: -6 dB. + * @QMI_NAS_EVDO_SINR_LEVEL_2: -4.5 dB. + * @QMI_NAS_EVDO_SINR_LEVEL_3: -3 dB. + * @QMI_NAS_EVDO_SINR_LEVEL_4: -2 dB. + * @QMI_NAS_EVDO_SINR_LEVEL_5: +1 dB. + * @QMI_NAS_EVDO_SINR_LEVEL_6: +3 dB. + * @QMI_NAS_EVDO_SINR_LEVEL_7: +6 dB. + * @QMI_NAS_EVDO_SINR_LEVEL_8: +9 dB. + * + * EV-DO SINR level. + */ +typedef enum { + QMI_NAS_EVDO_SINR_LEVEL_0 = 0, + QMI_NAS_EVDO_SINR_LEVEL_1 = 1, + QMI_NAS_EVDO_SINR_LEVEL_2 = 2, + QMI_NAS_EVDO_SINR_LEVEL_3 = 3, + QMI_NAS_EVDO_SINR_LEVEL_4 = 4, + QMI_NAS_EVDO_SINR_LEVEL_5 = 5, + QMI_NAS_EVDO_SINR_LEVEL_6 = 6, + QMI_NAS_EVDO_SINR_LEVEL_7 = 7, + QMI_NAS_EVDO_SINR_LEVEL_8 = 8 +} QmiNasEvdoSinrLevel; + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Get Signal Strength' request/response */ + +/** + * QmiNasSignalStrengthRequest: + * @QMI_NAS_SIGNAL_STRENGTH_REQUEST_NONE: None. + * @QMI_NAS_SIGNAL_STRENGTH_REQUEST_RSSI: Request RSSI information. + * @QMI_NAS_SIGNAL_STRENGTH_REQUEST_ECIO: Request ECIO information. + * @QMI_NAS_SIGNAL_STRENGTH_REQUEST_IO: Request IO information. + * @QMI_NAS_SIGNAL_STRENGTH_REQUEST_SINR: Request SINR information. + * @QMI_NAS_SIGNAL_STRENGTH_REQUEST_ERROR_RATE: Request error rate information. + * @QMI_NAS_SIGNAL_STRENGTH_REQUEST_RSRQ: Request RSRQ information. + * @QMI_NAS_SIGNAL_STRENGTH_REQUEST_LTE_SNR: Request LTE SNR information. + * @QMI_NAS_SIGNAL_STRENGTH_REQUEST_LTE_RSRP: Request LTE RSRP information. + * + * Extra information to request when gathering Signal Strength. + */ +typedef enum { + QMI_NAS_SIGNAL_STRENGTH_REQUEST_NONE = 0, + QMI_NAS_SIGNAL_STRENGTH_REQUEST_RSSI = 1 << 0, + QMI_NAS_SIGNAL_STRENGTH_REQUEST_ECIO = 1 << 1, + QMI_NAS_SIGNAL_STRENGTH_REQUEST_IO = 1 << 2, + QMI_NAS_SIGNAL_STRENGTH_REQUEST_SINR = 1 << 3, + QMI_NAS_SIGNAL_STRENGTH_REQUEST_ERROR_RATE = 1 << 4, + QMI_NAS_SIGNAL_STRENGTH_REQUEST_RSRQ = 1 << 5, + QMI_NAS_SIGNAL_STRENGTH_REQUEST_LTE_SNR = 1 << 6, + QMI_NAS_SIGNAL_STRENGTH_REQUEST_LTE_RSRP = 1 << 7 +} QmiNasSignalStrengthRequest; + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Network Scan' request/response */ + +/** + * QmiNasNetworkScanType: + * @QMI_NAS_NETWORK_SCAN_TYPE_GSM: GSM network. + * @QMI_NAS_NETWORK_SCAN_TYPE_UMTS: UMTS network. + * @QMI_NAS_NETWORK_SCAN_TYPE_LTE: LTE network. + * @QMI_NAS_NETWORK_SCAN_TYPE_TD_SCDMA: TD-SCDMA network. + * + * Flags to use when specifying which networks to scan. + */ +typedef enum { + QMI_NAS_NETWORK_SCAN_TYPE_GSM = 1 << 0, + QMI_NAS_NETWORK_SCAN_TYPE_UMTS = 1 << 1, + QMI_NAS_NETWORK_SCAN_TYPE_LTE = 1 << 2, + QMI_NAS_NETWORK_SCAN_TYPE_TD_SCDMA = 1 << 3 +} QmiNasNetworkScanType; + +/** + * QmiNasNetworkStatus: + * @QMI_NAS_NETWORK_STATUS_CURRENT_SERVING: Network is in use, current serving. + * @QMI_NAS_NETWORK_STATUS_AVAILABLE: Network is vailable. + * @QMI_NAS_NETWORK_STATUS_HOME: Network is home network. + * @QMI_NAS_NETWORK_STATUS_ROAMING: Network is a roaming network. + * @QMI_NAS_NETWORK_STATUS_FORBIDDEN: Network is forbidden. + * @QMI_NAS_NETWORK_STATUS_NOT_FORBIDDEN: Network is not forbidden. + * @QMI_NAS_NETWORK_STATUS_PREFERRED: Network is preferred. + * @QMI_NAS_NETWORK_STATUS_NOT_PREFERRED: Network is not preferred. + * + * Flags to specify the status of a given network. + */ +typedef enum { + QMI_NAS_NETWORK_STATUS_CURRENT_SERVING = 1 << 0, + QMI_NAS_NETWORK_STATUS_AVAILABLE = 1 << 1, + QMI_NAS_NETWORK_STATUS_HOME = 1 << 2, + QMI_NAS_NETWORK_STATUS_ROAMING = 1 << 3, + QMI_NAS_NETWORK_STATUS_FORBIDDEN = 1 << 4, + QMI_NAS_NETWORK_STATUS_NOT_FORBIDDEN = 1 << 5, + QMI_NAS_NETWORK_STATUS_PREFERRED = 1 << 6, + QMI_NAS_NETWORK_STATUS_NOT_PREFERRED = 1 << 7 +} QmiNasNetworkStatus; + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Initiate Network Register' request/response */ + +/** + * QmiNasNetworkRegisterType: + * @QMI_NAS_NETWORK_REGISTER_TYPE_AUTOMATIC: Automatic network registration. + * @QMI_NAS_NETWORK_REGISTER_TYPE_MANUAL: Manual network registration. + * + * Type of network registration. + */ +typedef enum { + QMI_NAS_NETWORK_REGISTER_TYPE_AUTOMATIC = 0x01, + QMI_NAS_NETWORK_REGISTER_TYPE_MANUAL = 0x02 +} QmiNasNetworkRegisterType; + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Get Serving System' request/response */ + +/** + * QmiNasRegistrationState: + * @QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED: Not registered. + * @QMI_NAS_REGISTRATION_STATE_REGISTERED: Registered. + * @QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED_SEARCHING: Searching. + * @QMI_NAS_REGISTRATION_STATE_REGISTRATION_DENIED: Registration denied. + * @QMI_NAS_REGISTRATION_STATE_UNKNOWN: Unknown. + * + * Status of the network registration. + */ +typedef enum { + QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED = 0x00, + QMI_NAS_REGISTRATION_STATE_REGISTERED = 0x01, + QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED_SEARCHING = 0x02, + QMI_NAS_REGISTRATION_STATE_REGISTRATION_DENIED = 0x03, + QMI_NAS_REGISTRATION_STATE_UNKNOWN = 0x04 +} QmiNasRegistrationState; + +/** + * QmiNasAttachState: + * @QMI_NAS_ATTACH_STATE_UNKNOWN: Unknown attach state. + * @QMI_NAS_ATTACH_STATE_ATTACHED: Attached. + * @QMI_NAS_ATTACH_STATE_DETACHED: Detached. + * + * Domain attach state. + */ +typedef enum { + QMI_NAS_ATTACH_STATE_UNKNOWN = 0x00, + QMI_NAS_ATTACH_STATE_ATTACHED = 0x01, + QMI_NAS_ATTACH_STATE_DETACHED = 0x02, +} QmiNasAttachState; + +/** + * QmiNasNetworkType: + * @QMI_NAS_NETWORK_TYPE_UNKNOWN: Unknown. + * @QMI_NAS_NETWORK_TYPE_3GPP2: 3GPP2 network. + * @QMI_NAS_NETWORK_TYPE_3GPP: 3GPP network. + * + * Type of network. + */ +typedef enum { + QMI_NAS_NETWORK_TYPE_UNKNOWN = 0x00, + QMI_NAS_NETWORK_TYPE_3GPP2 = 0x01, + QMI_NAS_NETWORK_TYPE_3GPP = 0x02, +} QmiNasNetworkType; + +/** + * QmiNasRoamingIndicatorStatus: + * @QMI_NAS_ROAMING_INDICATOR_STATUS_ON: Roaming. + * @QMI_NAS_ROAMING_INDICATOR_STATUS_OFF: Home. + * + * Status of the roaming indication. + */ +typedef enum { + QMI_NAS_ROAMING_INDICATOR_STATUS_ON = 0x00, + QMI_NAS_ROAMING_INDICATOR_STATUS_OFF = 0x01, + /* next values only for 3GPP2 */ +} QmiNasRoamingIndicatorStatus; + +/** + * QmiNasDataCapability: + * @QMI_NAS_DATA_CAPABILITY_NONE: None or unknown. + * @QMI_NAS_DATA_CAPABILITY_GPRS: GPRS. + * @QMI_NAS_DATA_CAPABILITY_EDGE: EDGE. + * @QMI_NAS_DATA_CAPABILITY_HSDPA: HSDPA. + * @QMI_NAS_DATA_CAPABILITY_HSUPA: HSUPA. + * @QMI_NAS_DATA_CAPABILITY_WCDMA: WCDMA. + * @QMI_NAS_DATA_CAPABILITY_CDMA: CDMA. + * @QMI_NAS_DATA_CAPABILITY_EVDO_REV_0: EV-DO revision 0. + * @QMI_NAS_DATA_CAPABILITY_EVDO_REV_A: EV-DO revision A. + * @QMI_NAS_DATA_CAPABILITY_GSM: GSM. + * @QMI_NAS_DATA_CAPABILITY_EVDO_REV_B: EV-DO revision B. + * @QMI_NAS_DATA_CAPABILITY_LTE: LTE. + * @QMI_NAS_DATA_CAPABILITY_HSDPA_PLUS: HSDPA+. + * @QMI_NAS_DATA_CAPABILITY_DC_HSDPA_PLUS: DC-HSDPA+. + * + * Data capability of the network. + */ +typedef enum { + QMI_NAS_DATA_CAPABILITY_NONE = 0x00, + QMI_NAS_DATA_CAPABILITY_GPRS = 0x01, + QMI_NAS_DATA_CAPABILITY_EDGE = 0x02, + QMI_NAS_DATA_CAPABILITY_HSDPA = 0x03, + QMI_NAS_DATA_CAPABILITY_HSUPA = 0x04, + QMI_NAS_DATA_CAPABILITY_WCDMA = 0x05, + QMI_NAS_DATA_CAPABILITY_CDMA = 0x06, + QMI_NAS_DATA_CAPABILITY_EVDO_REV_0 = 0x07, + QMI_NAS_DATA_CAPABILITY_EVDO_REV_A = 0x08, + QMI_NAS_DATA_CAPABILITY_GSM = 0x09, + QMI_NAS_DATA_CAPABILITY_EVDO_REV_B = 0x0A, + QMI_NAS_DATA_CAPABILITY_LTE = 0x0B, + QMI_NAS_DATA_CAPABILITY_HSDPA_PLUS = 0x0C, + QMI_NAS_DATA_CAPABILITY_DC_HSDPA_PLUS = 0x0D +} QmiNasDataCapability; + +/** + * QmiNasServiceStatus: + * @QMI_NAS_SERVICE_STATUS_NONE: No service. + * @QMI_NAS_SERVICE_STATUS_LIMITED: Limited service. + * @QMI_NAS_SERVICE_STATUS_AVAILABLE: Service available. + * @QMI_NAS_SERVICE_STATUS_LIMITED_REGIONAL: Limited regional service. + * @QMI_NAS_SERVICE_STATUS_POWER_SAVE: Device in power save mode. + * + * Status of the service. + */ +typedef enum { + QMI_NAS_SERVICE_STATUS_NONE = 0x00, + QMI_NAS_SERVICE_STATUS_LIMITED = 0x01, + QMI_NAS_SERVICE_STATUS_AVAILABLE = 0x02, + QMI_NAS_SERVICE_STATUS_LIMITED_REGIONAL = 0x03, + QMI_NAS_SERVICE_STATUS_POWER_SAVE = 0x04 +} QmiNasServiceStatus; + +/** + * QmiNasHdrPersonality: + * @QMI_NAS_HDR_PERSONALITY_UNKNOWN: Unknown. + * @QMI_NAS_HDR_PERSONALITY_HRPD: HRPD. + * @QMI_NAS_HDR_PERSONALITY_EHRPD: eHRPD. + * + * HDR personality type. + */ +typedef enum { + QMI_NAS_HDR_PERSONALITY_UNKNOWN = 0x00, + QMI_NAS_HDR_PERSONALITY_HRPD = 0x01, + QMI_NAS_HDR_PERSONALITY_EHRPD = 0x02, +} QmiNasHdrPersonality; + +/** + * QmiNasCallBarringStatus: + * @QMI_NAS_CALL_BARRING_STATUS_NORMAL_ONLY: Normal calls only. + * @QMI_NAS_CALL_BARRING_STATUS_EMERGENCY_ONLY: Emergency calls only. + * @QMI_NAS_CALL_BARRING_STATUS_NO_CALLS: No calls allowed. + * @QMI_NAS_CALL_BARRING_STATUS_ALL_CALLS: All calls allowed. + * @QMI_NAS_CALL_BARRING_STATUS_UNKNOWN: Unknown. + * + * Status of the call barring functionality. + */ +typedef enum { + QMI_NAS_CALL_BARRING_STATUS_NORMAL_ONLY = 0x00, + QMI_NAS_CALL_BARRING_STATUS_EMERGENCY_ONLY = 0x01, + QMI_NAS_CALL_BARRING_STATUS_NO_CALLS = 0x02, + QMI_NAS_CALL_BARRING_STATUS_ALL_CALLS = 0x03, + QMI_NAS_CALL_BARRING_STATUS_UNKNOWN = -1 +} QmiNasCallBarringStatus; + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Get Home Network' request/response */ + +/** + * QmiNasNetworkDescriptionDisplay: + * @QMI_NAS_NETWORK_DESCRIPTION_DISPLAY_NO: Don't display. + * @QMI_NAS_NETWORK_DESCRIPTION_DISPLAY_YES: Display. + * @QMI_NAS_NETWORK_DESCRIPTION_DISPLAY_UNKNOWN: Unknown. + * + * Setup to define whether the network description should be displayed. + */ +typedef enum { + QMI_NAS_NETWORK_DESCRIPTION_DISPLAY_NO = 0x00, + QMI_NAS_NETWORK_DESCRIPTION_DISPLAY_YES = 0x01, + QMI_NAS_NETWORK_DESCRIPTION_DISPLAY_UNKNOWN = 0xFF +} QmiNasNetworkDescriptionDisplay; + +/** + * QmiNasNetworkDescriptionEncoding: + * @QMI_NAS_NETWORK_DESCRIPTION_ENCODING_UNSPECIFIED: Unspecified. + * @QMI_NAS_NETWORK_DESCRIPTION_ENCODING_ASCII7: ASCII-7. + * @QMI_NAS_NETWORK_DESCRIPTION_ENCODING_UNICODE: Unicode. + * @QMI_NAS_NETWORK_DESCRIPTION_ENCODING_GSM: GSM 7-bit. + * + * Type of encoding used in the network description. + */ +typedef enum { + QMI_NAS_NETWORK_DESCRIPTION_ENCODING_UNSPECIFIED = 0x00, + QMI_NAS_NETWORK_DESCRIPTION_ENCODING_ASCII7 = 0x01, + QMI_NAS_NETWORK_DESCRIPTION_ENCODING_UNICODE = 0x04, + QMI_NAS_NETWORK_DESCRIPTION_ENCODING_GSM = 0x09 +} QmiNasNetworkDescriptionEncoding; + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Get Technology Preference' request/response */ + +/** + * QmiNasRadioTechnologyPreference: + * @QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO: Automatic selection. + * @QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP2: 3GPP2 technology. + * @QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP: 3GPP technology. + * @QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AMPS_OR_GSM: AMPS if 3GPP2, GSM if 3GPP. + * @QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_CDMA_OR_WCDMA: CDMA if 3GPP2, WCDMA if 3GPP. + * @QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_HDR: CDMA EV-DO. + * @QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_LTE: LTE. + * + * Flags to specify the radio technology preference. + */ +typedef enum { + QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO = 0, + QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP2 = 1 << 0, + QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP = 1 << 1, + QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AMPS_OR_GSM = 1 << 2, + QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_CDMA_OR_WCDMA = 1 << 3, + QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_HDR = 1 << 4, + QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_LTE = 1 << 5 +} QmiNasRadioTechnologyPreference; + +/** + * QmiNasPreferenceDuration: + * @QMI_NAS_PREFERENCE_DURATION_PERMANENT: Permanent. + * @QMI_NAS_PREFERENCE_DURATION_POWER_CYCLE: Until the next power cycle. + * @QMI_NAS_PREFERENCE_DURATION_ONE_CALL: Until end of call. + * @QMI_NAS_PREFERENCE_DURATION_ONE_CALL_OR_TIME: Until end of call or a specified time. + * @QMI_NAS_PREFERENCE_DURATION_INTERNAL_ONE_CALL_1: Internal reason 1, one call. + * @QMI_NAS_PREFERENCE_DURATION_INTERNAL_ONE_CALL_2: Internal reason 2, one call. + * @QMI_NAS_PREFERENCE_DURATION_INTERNAL_ONE_CALL_3: Internal reason 3, one call. + * + * Duration of the preference setting. + */ +typedef enum { + QMI_NAS_PREFERENCE_DURATION_PERMANENT = 0x00, + QMI_NAS_PREFERENCE_DURATION_POWER_CYCLE = 0x01, + QMI_NAS_PREFERENCE_DURATION_ONE_CALL = 0x02, + QMI_NAS_PREFERENCE_DURATION_ONE_CALL_OR_TIME = 0x03, + QMI_NAS_PREFERENCE_DURATION_INTERNAL_ONE_CALL_1 = 0x04, + QMI_NAS_PREFERENCE_DURATION_INTERNAL_ONE_CALL_2 = 0x05, + QMI_NAS_PREFERENCE_DURATION_INTERNAL_ONE_CALL_3 = 0x06 +} QmiNasPreferenceDuration; + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Get/Set System Selection Preference' + * requests/responses */ + +/** + * QmiNasRatModePreference: + * @QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1X: CDMA2000 1X. + * @QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1XEVDO: CDMA2000 HRPD (1xEV-DO). + * @QMI_NAS_RAT_MODE_PREFERENCE_GSM: GSM. + * @QMI_NAS_RAT_MODE_PREFERENCE_UMTS: UMTS. + * @QMI_NAS_RAT_MODE_PREFERENCE_LTE: LTE. + * @QMI_NAS_RAT_MODE_PREFERENCE_TD_SCDMA: TD-SCDMA. + * + * Flags specifying radio access technology mode preference. + */ +typedef enum { + QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1X = 1 << 0, + QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1XEVDO = 1 << 1, + QMI_NAS_RAT_MODE_PREFERENCE_GSM = 1 << 2, + QMI_NAS_RAT_MODE_PREFERENCE_UMTS = 1 << 3, + QMI_NAS_RAT_MODE_PREFERENCE_LTE = 1 << 4, + QMI_NAS_RAT_MODE_PREFERENCE_TD_SCDMA = 1 << 5 +} QmiNasRatModePreference; + +/** + * QmiNasCdmaPrlPreference: + * @QMI_NAS_CDMA_PRL_PREFERENCE_A_SIDE_ONLY: System A only. + * @QMI_NAS_CDMA_PRL_PREFERENCE_B_SIDE_ONLY: System B only. + * @QMI_NAS_CDMA_PRL_PREFERENCE_ANY: Any system. + * + * Flags specifying the preference when using CDMA Band Class 0. + */ +typedef enum { + QMI_NAS_CDMA_PRL_PREFERENCE_A_SIDE_ONLY = 0x0001, + QMI_NAS_CDMA_PRL_PREFERENCE_B_SIDE_ONLY = 0x0002, + QMI_NAS_CDMA_PRL_PREFERENCE_ANY = 0x3FFF +} QmiNasCdmaPrlPreference; + +/** + * QmiNasRoamingPreference: + * @QMI_NAS_ROAMING_PREFERENCE_OFF: Only non-roaming networks. + * @QMI_NAS_ROAMING_PREFERENCE_NOT_OFF: Only roaming networks. + * @QMI_NAS_ROAMING_PREFERENCE_NOT_FLASHING: Only non-roaming networks or not flashing. + * @QMI_NAS_ROAMING_PREFERENCE_ANY: Don't filter by roaming when acquiring networks. + * + * Roaming preference. + */ +typedef enum { + QMI_NAS_ROAMING_PREFERENCE_OFF = 0x01, + QMI_NAS_ROAMING_PREFERENCE_NOT_OFF = 0x02, + QMI_NAS_ROAMING_PREFERENCE_NOT_FLASHING = 0x03, + QMI_NAS_ROAMING_PREFERENCE_ANY = 0xFF +} QmiNasRoamingPreference; + +/** + * QmiNasNetworkSelectionPreference: + * @QMI_NAS_NETWORK_SELECTION_PREFERENCE_AUTOMATIC: Automatic. + * @QMI_NAS_NETWORK_SELECTION_PREFERENCE_MANUAL: Manual. + * + * Network selection preference. + */ +typedef enum { + QMI_NAS_NETWORK_SELECTION_PREFERENCE_AUTOMATIC = 0x00, + QMI_NAS_NETWORK_SELECTION_PREFERENCE_MANUAL = 0x01 +} QmiNasNetworkSelectionPreference; + +/** + * QmiNasChangeDuration: + * @QMI_NAS_CHANGE_DURATION_PERMANENT: Permanent. + * @QMI_NAS_CHANGE_DURATION_POWER_CYCLE: Until the next power cycle. + * + * Duration of the change setting. + */ +typedef enum { + QMI_NAS_CHANGE_DURATION_POWER_CYCLE = 0x00, + QMI_NAS_CHANGE_DURATION_PERMANENT = 0x01 +} QmiNasChangeDuration; + +/** + * QmiNasServiceDomainPreference: + * @QMI_NAS_SERVICE_DOMAIN_PREFERENCE_CS_ONLY: Circuit-switched only. + * @QMI_NAS_SERVICE_DOMAIN_PREFERENCE_PS_ONLY: Packet-switched only. + * @QMI_NAS_SERVICE_DOMAIN_PREFERENCE_CS_PS: Circuit-switched and packet-switched. + * @QMI_NAS_SERVICE_DOMAIN_PREFERENCE_PS_ATTACH: Packet-switched attach. + * @QMI_NAS_SERVICE_DOMAIN_PREFERENCE_PS_DETACH:Packet-switched dettach. + * + * Service domain preference. + */ +typedef enum { + QMI_NAS_SERVICE_DOMAIN_PREFERENCE_CS_ONLY = 0x00, + QMI_NAS_SERVICE_DOMAIN_PREFERENCE_PS_ONLY = 0x01, + QMI_NAS_SERVICE_DOMAIN_PREFERENCE_CS_PS = 0x02, + QMI_NAS_SERVICE_DOMAIN_PREFERENCE_PS_ATTACH = 0x03, + QMI_NAS_SERVICE_DOMAIN_PREFERENCE_PS_DETACH = 0x04, +} QmiNasServiceDomainPreference; + +/** + * QmiNasGsmWcdmaAcquisitionOrderPreference: + * @QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_AUTOMATIC: Automatic. + * @QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_GSM: GSM first, then WCDMA. + * @QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_WCDMA: WCDMA first, then GSM. + * + * GSM/WCDMA acquisition order preference. + */ +typedef enum { + QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_AUTOMATIC = 0x00, + QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_GSM = 0x01, + QMI_NAS_GSM_WCDMA_ACQUISITION_ORDER_PREFERENCE_WCDMA = 0x02 +} QmiNasGsmWcdmaAcquisitionOrderPreference; + +/** + * QmiNasTdScdmaBandPreference: + * @QMI_NAS_TD_SCDMA_BAND_PREFERENCE_A: Band A. + * @QMI_NAS_TD_SCDMA_BAND_PREFERENCE_B: Band B. + * @QMI_NAS_TD_SCDMA_BAND_PREFERENCE_C: Band C. + * @QMI_NAS_TD_SCDMA_BAND_PREFERENCE_D: Band D. + * @QMI_NAS_TD_SCDMA_BAND_PREFERENCE_E: Band E. + * @QMI_NAS_TD_SCDMA_BAND_PREFERENCE_F: Band F. + * + * Flags to specify TD-SCDMA-specific frequency band preferences. + */ +typedef enum { + QMI_NAS_TD_SCDMA_BAND_PREFERENCE_A = 1 << 0, + QMI_NAS_TD_SCDMA_BAND_PREFERENCE_B = 1 << 1, + QMI_NAS_TD_SCDMA_BAND_PREFERENCE_C = 1 << 2, + QMI_NAS_TD_SCDMA_BAND_PREFERENCE_D = 1 << 3, + QMI_NAS_TD_SCDMA_BAND_PREFERENCE_E = 1 << 4, + QMI_NAS_TD_SCDMA_BAND_PREFERENCE_F = 1 << 5 +} QmiNasTdScdmaBandPreference; + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Get System Info' request/response */ + +/** + * QmiNasRoamingStatus: + * @QMI_NAS_ROAMING_STATUS_OFF: Off. + * @QMI_NAS_ROAMING_STATUS_ON: On. + * @QMI_NAS_ROAMING_STATUS_BLINK: Blinking. + * @QMI_NAS_ROAMING_STATUS_OUT_OF_NEIGHBORHOOD: Out of neighborhood. + * @QMI_NAS_ROAMING_STATUS_OUT_OF_BUILDING: Out of building. + * @QMI_NAS_ROAMING_STATUS_PREFERRED_SYSTEM: Preferred system. + * @QMI_NAS_ROAMING_STATUS_AVAILABLE_SYSTEM: Available system. + * @QMI_NAS_ROAMING_STATUS_ALLIANCE_PARTNER: Alliance partner. + * @QMI_NAS_ROAMING_STATUS_PREMIUM_PARTNER: Premium partner. + * @QMI_NAS_ROAMING_STATUS_FULL_SERVICE: Full service. + * @QMI_NAS_ROAMING_STATUS_PARTIAL_SERVICE: Partial service. + * @QMI_NAS_ROAMING_STATUS_BANNER_ON: Banner on. + * @QMI_NAS_ROAMING_STATUS_BANNER_OFF: Banner off. +*/ +typedef enum { + QMI_NAS_ROAMING_STATUS_OFF = 0x00, + QMI_NAS_ROAMING_STATUS_ON = 0x01, + /* Next ones only for 3GPP2 */ + QMI_NAS_ROAMING_STATUS_BLINK = 0x02, + QMI_NAS_ROAMING_STATUS_OUT_OF_NEIGHBORHOOD = 0x03, + QMI_NAS_ROAMING_STATUS_OUT_OF_BUILDING = 0x04, + QMI_NAS_ROAMING_STATUS_PREFERRED_SYSTEM = 0x05, + QMI_NAS_ROAMING_STATUS_AVAILABLE_SYSTEM = 0x06, + QMI_NAS_ROAMING_STATUS_ALLIANCE_PARTNER = 0x07, + QMI_NAS_ROAMING_STATUS_PREMIUM_PARTNER = 0x08, + QMI_NAS_ROAMING_STATUS_FULL_SERVICE = 0x09, + QMI_NAS_ROAMING_STATUS_PARTIAL_SERVICE = 0x0A, + QMI_NAS_ROAMING_STATUS_BANNER_ON = 0x0B, + QMI_NAS_ROAMING_STATUS_BANNER_OFF = 0x0C +} QmiNasRoamingStatus; + +/** + * QmiNasHdrProtocolRevision: + * @QMI_NAS_HDR_PROTOCOL_REVISION_NONE: None. + * @QMI_NAS_HDR_PROTOCOL_REVISION_REL_0: HDR Rel 0. + * @QMI_NAS_HDR_PROTOCOL_REVISION_REL_A: HDR Rel A. + * @QMI_NAS_HDR_PROTOCOL_REVISION_REL_B: HDR Rel B. + * + * HDR protocol revision. + */ +typedef enum { + QMI_NAS_HDR_PROTOCOL_REVISION_NONE = 0x00, + QMI_NAS_HDR_PROTOCOL_REVISION_REL_0 = 0x01, + QMI_NAS_HDR_PROTOCOL_REVISION_REL_A = 0x02, + QMI_NAS_HDR_PROTOCOL_REVISION_REL_B = 0x03 +} QmiNasHdrProtocolRevision; + +/** + * QmiNasWcdmaHsService: + * @QMI_NAS_WCDMA_HS_SERVICE_HSDPA_HSUPA_UNSUPPORTED: HSDPA and HSUPA not supported. + * @QMI_NAS_WCDMA_HS_SERVICE_HSDPA_SUPPORTED: HSDPA supported. + * @QMI_NAS_WCDMA_HS_SERVICE_HSUPA_SUPPORTED: HSUPA supported. + * @QMI_NAS_WCDMA_HS_SERVICE_HSDPA_HSUPA_SUPPORTED: HSDPA and HSUPA supported. + * @QMI_NAS_WCDMA_HS_SERVICE_HSDPA_PLUS_SUPPORTED: HSDPA+ supported. + * @QMI_NAS_WCDMA_HS_SERVICE_HSDPA_PLUS_HSUPA_SUPPORTED: HSDPA+ and HSUPA supported. + * @QMI_NAS_WCDMA_HS_SERVICE_DC_HSDPA_PLUS_SUPPORTED: DC-HSDPA+ supported. + * @QMI_NAS_WCDMA_HS_SERVICE_DC_HSDPA_PLUS_HSUPA_SUPPORTED: DC-HSDPA+ and HSUPA supported. + * Call status on high speed. + */ +typedef enum { + QMI_NAS_WCDMA_HS_SERVICE_HSDPA_HSUPA_UNSUPPORTED = 0x00, + QMI_NAS_WCDMA_HS_SERVICE_HSDPA_SUPPORTED = 0x01, + QMI_NAS_WCDMA_HS_SERVICE_HSUPA_SUPPORTED = 0x02, + QMI_NAS_WCDMA_HS_SERVICE_HSDPA_HSUPA_SUPPORTED = 0x03, + QMI_NAS_WCDMA_HS_SERVICE_HSDPA_PLUS_SUPPORTED = 0x04, + QMI_NAS_WCDMA_HS_SERVICE_HSDPA_PLUS_HSUPA_SUPPORTED = 0x05, + QMI_NAS_WCDMA_HS_SERVICE_DC_HSDPA_PLUS_SUPPORTED = 0x06, + QMI_NAS_WCDMA_HS_SERVICE_DC_HSDPA_PLUS_HSUPA_SUPPORTED = 0x07 +} QmiNasWcdmaHsService; + +/** + * QmiNasCellBroadcastCapability: + * @QMI_NAS_CELL_BROADCAST_CAPABILITY_UNKNOWN: Unknown. + * @QMI_NAS_CELL_BROADCAST_CAPABILITY_OFF: Cell broadcast not supported. + * @QMI_NAS_CELL_BROADCAST_CAPABILITY_ON: Cell broadcast supported. + * + * Cell broadcast support. + */ +typedef enum { + QMI_NAS_CELL_BROADCAST_CAPABILITY_UNKNOWN = 0x00, + QMI_NAS_CELL_BROADCAST_CAPABILITY_OFF = 0x01, + QMI_NAS_CELL_BROADCAST_CAPABILITY_ON = 0x02 +} QmiNasCellBroadcastCapability; + +/** + * QmiNasSimRejectState: + * @QMI_NAS_SIM_REJECT_STATE_SIM_UNAVAILABLE: SIM not available. + * @QMI_NAS_SIM_REJECT_STATE_SIM_VAILABLE: SIM available. + * @QMI_NAS_SIM_REJECT_STATE_SIM_CS_INVALID: SIM invalid for circuit-switched connections. + * @QMI_NAS_SIM_REJECT_STATE_SIM_PS_INVALID: SIM invalid for packet-switched connections. + * @QMI_NAS_SIM_REJECT_STATE_SIM_CS_PS_INVALID: SIM invalid for circuit-switched and packet-switched connections. + * + * Reject information of the SIM. + */ +typedef enum { + QMI_NAS_SIM_REJECT_STATE_SIM_UNAVAILABLE = 0, + QMI_NAS_SIM_REJECT_STATE_SIM_VAILABLE = 1, + QMI_NAS_SIM_REJECT_STATE_SIM_CS_INVALID = 2, + QMI_NAS_SIM_REJECT_STATE_SIM_PS_INVALID = 3, + QMI_NAS_SIM_REJECT_STATE_SIM_CS_PS_INVALID = 4 +} QmiNasSimRejectState; + +/** + * QmiNasCdmaPilotType: + * @QMI_NAS_CDMA_PILOT_TYPE_ACTIVE: the pilot is part of the active set. + * @QMI_NAS_CDMA_PILOT_TYPE_NEIGHBOR: the pilot is part of the neighbor set. + * + * The pilot set the pilot belongs to. + */ +typedef enum { + QMI_NAS_CDMA_PILOT_TYPE_ACTIVE = 0, + QMI_NAS_CDMA_PILOT_TYPE_NEIGHBOR = 1, +} QmiNasCdmaPilotType; + +/** + * QmiNasDayOfWeek: + * @QMI_NAS_DAY_OF_WEEK_MONDAY: Monday + * @QMI_NAS_DAY_OF_WEEK_TUESDAY: Tuesday + * @QMI_NAS_DAY_OF_WEEK_WEDNESDAY: Wednesday + * @QMI_NAS_DAY_OF_WEEK_THURSDAY: Thursday + * @QMI_NAS_DAY_OF_WEEK_FRIDAY: Friday + * @QMI_NAS_DAY_OF_WEEK_SATURDAY: Saturday + * @QMI_NAS_DAY_OF_WEEK_SUNDAY: Sunday + * + * The day of the week. + */ +typedef enum { + QMI_NAS_DAY_OF_WEEK_MONDAY = 0, + QMI_NAS_DAY_OF_WEEK_TUESDAY = 1, + QMI_NAS_DAY_OF_WEEK_WEDNESDAY = 2, + QMI_NAS_DAY_OF_WEEK_THURSDAY = 3, + QMI_NAS_DAY_OF_WEEK_FRIDAY = 4, + QMI_NAS_DAY_OF_WEEK_SATURDAY = 5, + QMI_NAS_DAY_OF_WEEK_SUNDAY = 6 +} QmiNasDayOfWeek; + +/** + * QmiNasDaylightSavingsAdjustment: + * @QMI_NAS_DAYLIGHT_SAVINGS_ADJUSTMENT_NONE: no adjustment + * @QMI_NAS_DAYLIGHT_SAVINGS_ADJUSTMENT_ONE_HOUR: one hour adjustment + * @QMI_NAS_DAYLIGHT_SAVINGS_ADJUSTMENT_TWO_HOURS: two hours adjustment + * + * The number of hours a time is adjusted for daylight savings. + */ +typedef enum { + QMI_NAS_DAYLIGHT_SAVINGS_ADJUSTMENT_NONE = 0, + QMI_NAS_DAYLIGHT_SAVINGS_ADJUSTMENT_ONE_HOUR = 1, + QMI_NAS_DAYLIGHT_SAVINGS_ADJUSTMENT_TWO_HOURS = 2 +} QmiNasDaylightSavingsAdjustment; + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Get Cell Location Info' request/response */ + +/** + * QmiNasWcdmaRrcState: + * @QMI_NAS_WCDMA_RRC_STATE_DISCONNECTED: Disconnected. + * @QMI_NAS_WCDMA_RRC_STATE_CELL_PCH: WCDMA RRC state is CELL_PCH. + * @QMI_NAS_WCDMA_RRC_STATE_URA_PCH: WCDMA RRC state is URA_PCH. + * @QMI_NAS_WCDMA_RRC_STATE_CELL_FACH: WCDMA RRC state is CELL_FACH. + * @QMI_NAS_WCDMA_RRC_STATE_CELL_DCH: WCDMA RRC state is CELL_DCH. + * + * RRC state. + */ +typedef enum { + QMI_NAS_WCDMA_RRC_STATE_DISCONNECTED = 0, + QMI_NAS_WCDMA_RRC_STATE_CELL_PCH = 1, + QMI_NAS_WCDMA_RRC_STATE_URA_PCH = 2, + QMI_NAS_WCDMA_RRC_STATE_CELL_FACH = 3, + QMI_NAS_WCDMA_RRC_STATE_CELL_DCH = 4 +} QmiNasWcdmaRrcState; + +#endif /* _LIBQMI_GLIB_QMI_ENUMS_NAS_H_ */ diff --git a/release/src/router/uqmi/qmi-enums-pds.h b/release/src/router/uqmi/qmi-enums-pds.h new file mode 100644 index 0000000000..ee26418a48 --- /dev/null +++ b/release/src/router/uqmi/qmi-enums-pds.h @@ -0,0 +1,182 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * uqmi -- tiny QMI support implementation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012 Google Inc. + */ + +#ifndef _LIBQMI_GLIB_QMI_ENUMS_PDS_H_ +#define _LIBQMI_GLIB_QMI_ENUMS_PDS_H_ + +/** + * SECTION: qmi-enums-pds + * @title: PDS enumerations and flags + * + * This section defines enumerations and flags used in the PDS service + * interface. + */ + +/*****************************************************************************/ +/* Helper enums for the 'QMI PDS Event Report' indication */ + +/** + * QmiPdsOperationMode: + * @QMI_PDS_OPERATION_MODE_UNKNOWN: Unknown (position not fixed yet). + * @QMI_PDS_OPERATION_MODE_STANDALONE: Standalone. + * @QMI_PDS_OPERATION_MODE_MS_BASED: MS based. + * @QMI_PDS_OPERATION_MODE_MS_ASSISTED: MS assisted. + * + * Operation mode used to compute the position. + */ +typedef enum { + QMI_PDS_OPERATION_MODE_UNKNOWN = -1, + QMI_PDS_OPERATION_MODE_STANDALONE = 0, + QMI_PDS_OPERATION_MODE_MS_BASED = 1, + QMI_PDS_OPERATION_MODE_MS_ASSISTED = 2 +} QmiPdsOperationMode; + +/** + * QmiPdsPositionSessionStatus: + * @QMI_PDS_POSITION_SESSION_STATUS_SUCCESS: Success. + * @QMI_PDS_POSITION_SESSION_STATUS_IN_PROGRESS: In progress. + * @QMI_PDS_POSITION_SESSION_STATUS_GENERAL_FAILURE: General failure. + * @QMI_PDS_POSITION_SESSION_STATUS_TIMEOUT: Timeout. + * @QMI_PDS_POSITION_SESSION_STATUS_USER_ENDED_SESSION: User ended session. + * @QMI_PDS_POSITION_SESSION_STATUS_BAD_PARAMETER: Bad parameter. + * @QMI_PDS_POSITION_SESSION_STATUS_PHONE_OFFLINE: Phone is offline. + * @QMI_PDS_POSITION_SESSION_STATUS_ENGINE_LOCKED: Engine locked. + * @QMI_PDS_POSITION_SESSION_STATUS_E911_SESSION_IN_PROGRESS: Emergency call in progress. + * + * Status of the positioning session. + */ +typedef enum { + QMI_PDS_POSITION_SESSION_STATUS_SUCCESS = 0x00, + QMI_PDS_POSITION_SESSION_STATUS_IN_PROGRESS = 0x01, + QMI_PDS_POSITION_SESSION_STATUS_GENERAL_FAILURE = 0x02, + QMI_PDS_POSITION_SESSION_STATUS_TIMEOUT = 0x03, + QMI_PDS_POSITION_SESSION_STATUS_USER_ENDED_SESSION = 0x04, + QMI_PDS_POSITION_SESSION_STATUS_BAD_PARAMETER = 0x05, + QMI_PDS_POSITION_SESSION_STATUS_PHONE_OFFLINE = 0x06, + QMI_PDS_POSITION_SESSION_STATUS_ENGINE_LOCKED = 0x07, + QMI_PDS_POSITION_SESSION_STATUS_E911_SESSION_IN_PROGRESS = 0x08 +} QmiPdsPositionSessionStatus; + +/** + * QmiPdsDataValid: + * @QMI_PDS_DATA_VALID_TIMESTAMP_CALENDAR: Timestamp calendar (GPS time). + * @QMI_PDS_DATA_VALID_TIMESTAMP_UTC: Timestamp (UTC). + * @QMI_PDS_DATA_VALID_LEAP_SECONDS: Leap seconds. + * @QMI_PDS_DATA_VALID_TIME_UNCERTAINTY: Time uncertainty. + * @QMI_PDS_DATA_VALID_LATITUDE: Latitude. + * @QMI_PDS_DATA_VALID_LONGITUDE: Longitude. + * @QMI_PDS_DATA_VALID_ELLIPSOID_ALTITUDE: Ellipsoid altitude. + * @QMI_PDS_DATA_VALID_MEAN_SEA_LEVEL_ALTITUDE: Mean sea level altitude. + * @QMI_PDS_DATA_VALID_HORIZONTAL_SPEED: Horizontal speed. + * @QMI_PDS_DATA_VALID_VERTICAL_SPEED: Vertical speed. + * @QMI_PDS_DATA_VALID_HEADING: Heading. + * @QMI_PDS_DATA_VALID_HORIZONTAL_UNCERTAINTY_CIRCULAR: Horizontal uncertainty circular. + * @QMI_PDS_DATA_VALID_HORIZONTAL_UNCERTAINTY_ELLIPSE_SEMI_MAJOR: Horizontal uncertainty ellipse semi-major. + * @QMI_PDS_DATA_VALID_HORIZONTAL_UNCERTAINTY_ELLIPSE_SEMI_MINOR: Horizontal uncertainty ellipse semi-minor. + * @QMI_PDS_DATA_VALID_HORIZONTAL_UNCERTAINTY_ELLIPSE_ORIENT_AZIMUTH: Horizontal uncertainty ellipse orient azimuth. + * @QMI_PDS_DATA_VALID_VERTICAL_UNCERTAINTY: Vertical uncertainty. + * @QMI_PDS_DATA_VALID_HORIZONTAL_VELOCITY_UNCERTAINTY: Horizontal velocity uncertainty. + * @QMI_PDS_DATA_VALID_VERTICAL_VELOCITY_UNCERTAINTY: Vertical velocity uncertainty. + * @QMI_PDS_DATA_VALID_HORIZONTAL_CONFIDENCE: Horizontal confidence. + * @QMI_PDS_DATA_VALID_POSITION_DOP: Position dillution of precision. + * @QMI_PDS_DATA_VALID_HORIZONTAL_DOP: Horizontal dillution of precision. + * @QMI_PDS_DATA_VALID_VERTICAL_DOP: Vertical dillution of precision. + * @QMI_PDS_DATA_VALID_OPERATING_MODE: Operating mode. + * + * Flags to indicate which position data parameters are valid. + */ +typedef enum { + QMI_PDS_DATA_VALID_TIMESTAMP_CALENDAR = 1 << 0, + QMI_PDS_DATA_VALID_TIMESTAMP_UTC = 1 << 1, + QMI_PDS_DATA_VALID_LEAP_SECONDS = 1 << 2, + QMI_PDS_DATA_VALID_TIME_UNCERTAINTY = 1 << 3, + QMI_PDS_DATA_VALID_LATITUDE = 1 << 4, + QMI_PDS_DATA_VALID_LONGITUDE = 1 << 5, + QMI_PDS_DATA_VALID_ELLIPSOID_ALTITUDE = 1 << 6, + QMI_PDS_DATA_VALID_MEAN_SEA_LEVEL_ALTITUDE = 1 << 7, + QMI_PDS_DATA_VALID_HORIZONTAL_SPEED = 1 << 8, + QMI_PDS_DATA_VALID_VERTICAL_SPEED = 1 << 9, + QMI_PDS_DATA_VALID_HEADING = 1 << 10, + QMI_PDS_DATA_VALID_HORIZONTAL_UNCERTAINTY_CIRCULAR = 1 << 11, + QMI_PDS_DATA_VALID_HORIZONTAL_UNCERTAINTY_ELLIPSE_SEMI_MAJOR = 1 << 12, + QMI_PDS_DATA_VALID_HORIZONTAL_UNCERTAINTY_ELLIPSE_SEMI_MINOR = 1 << 13, + QMI_PDS_DATA_VALID_HORIZONTAL_UNCERTAINTY_ELLIPSE_ORIENT_AZIMUTH = 1 << 14, + QMI_PDS_DATA_VALID_VERTICAL_UNCERTAINTY = 1 << 15, + QMI_PDS_DATA_VALID_HORIZONTAL_VELOCITY_UNCERTAINTY = 1 << 16, + QMI_PDS_DATA_VALID_VERTICAL_VELOCITY_UNCERTAINTY = 1 << 17, + QMI_PDS_DATA_VALID_HORIZONTAL_CONFIDENCE = 1 << 18, + QMI_PDS_DATA_VALID_POSITION_DOP = 1 << 19, + QMI_PDS_DATA_VALID_HORIZONTAL_DOP = 1 << 20, + QMI_PDS_DATA_VALID_VERTICAL_DOP = 1 << 21, + QMI_PDS_DATA_VALID_OPERATING_MODE = 1 << 22 +} QmiPdsDataValid; + +/*****************************************************************************/ +/* Helper enums for the 'QMI PDS Get GPS Service State' request/response */ + +/** + * QmiPdsTrackingSessionState: + * @QMI_PDS_TRACKING_SESSION_STATE_UNKNOWN: Unknown state. + * @QMI_PDS_TRACKING_SESSION_STATE_INACTIVE: Session inactive. + * @QMI_PDS_TRACKING_SESSION_STATE_ACTIVE: Session active. + * + * State of the tracking session. + */ +typedef enum { + QMI_PDS_TRACKING_SESSION_STATE_UNKNOWN = 0, + QMI_PDS_TRACKING_SESSION_STATE_INACTIVE = 1, + QMI_PDS_TRACKING_SESSION_STATE_ACTIVE = 2 +} QmiPdsTrackingSessionState; + +/*****************************************************************************/ +/* Helper enums for the 'QMI PDS Get Default Tracking Session' request/response */ + +/** + * QmiPdsOperatingMode: + * @QMI_PDS_OPERATING_MODE_STANDALONE: Standalone (GPS only). + * @QMI_PDS_OPERATING_MODE_MS_BASED: MS-based. + * @QMI_PDS_OPERATING_MODE_MS_ASSISTED: MS-assisted (A-GPS). + * + * GPS operating mode. + */ +typedef enum { + QMI_PDS_OPERATING_MODE_STANDALONE = 0, + QMI_PDS_OPERATING_MODE_MS_BASED = 1, + QMI_PDS_OPERATING_MODE_MS_ASSISTED = 2, +} QmiPdsOperatingMode; + +/*****************************************************************************/ +/* Helper enums for the 'QMI PDS Get AGPS Config' request/response */ + +/** + * QmiPdsNetworkMode: + * @QMI_PDS_NETWORK_MODE_UMTS: UMTS. + * @QMI_PDS_NETWORK_MODE_CDMA: CDMA. + * + * Network mode used during the A-GPS setup. + */ +typedef enum { + QMI_PDS_NETWORK_MODE_UMTS = 0, + QMI_PDS_NETWORK_MODE_CDMA = 1, +} QmiPdsNetworkMode; + +#endif /* _LIBQMI_GLIB_QMI_ENUMS_PDS_H_ */ diff --git a/release/src/router/uqmi/qmi-enums-private.h b/release/src/router/uqmi/qmi-enums-private.h new file mode 100644 index 0000000000..d383f562ef --- /dev/null +++ b/release/src/router/uqmi/qmi-enums-private.h @@ -0,0 +1,85 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * uqmi -- tiny QMI support implementation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012 Google Inc. + */ + +#ifndef _LIBQMI_GLIB_QMI_ENUMS_PRIVATE_H_ +#define _LIBQMI_GLIB_QMI_ENUMS_PRIVATE_H_ + +/*****************************************************************************/ +/* QMI Control */ + +/** + * QmiCtlDataFormat: + * @QMI_CTL_DATA_FORMAT_QOS_FLOW_HEADER_ABSENT: QoS header absent + * @QMI_CTL_DATA_FORMAT_QOS_FLOW_HEADER_PRESENT: QoS header present + * + * Controls whether the network port data format includes a QoS header or not. + * Should normally be set to ABSENT. + */ +typedef enum { + QMI_CTL_DATA_FORMAT_QOS_FLOW_HEADER_ABSENT = 0, + QMI_CTL_DATA_FORMAT_QOS_FLOW_HEADER_PRESENT = 1, +} QmiCtlDataFormat; + +/** + * QmiCtlDataLinkProtocol: + * @QMI_CTL_DATA_LINK_PROTOCOL_802_3: data frames formatted as 802.3 Ethernet + * @QMI_CTL_DATA_LINK_PROTOCOL_RAW_IP: data frames are raw IP packets + * + * Determines the network port data format. + */ +typedef enum { + QMI_CTL_DATA_LINK_PROTOCOL_UNKNOWN = 0, + QMI_CTL_DATA_LINK_PROTOCOL_802_3 = 1, + QMI_CTL_DATA_LINK_PROTOCOL_RAW_IP = 2, +} QmiCtlDataLinkProtocol; + +/** + * QmiCtlFlag: + * @QMI_CTL_FLAG_NONE: None. + * @QMI_CTL_FLAG_RESPONSE: Message is a response. + * @QMI_CTL_FLAG_INDICATION: Message is an indication. + * + * QMI flags in messages of the %QMI_SERVICE_CTL service. + */ +typedef enum { + QMI_CTL_FLAG_NONE = 0, + QMI_CTL_FLAG_RESPONSE = 1 << 0, + QMI_CTL_FLAG_INDICATION = 1 << 1 +} QmiCtlFlag; + +/** + * QmiServiceFlag: + * @QMI_SERVICE_FLAG_NONE: None. + * @QMI_SERVICE_FLAG_COMPOUND: Message is compound. + * @QMI_SERVICE_FLAG_RESPONSE: Message is a response. + * @QMI_SERVICE_FLAG_INDICATION: Message is an indication. + * + * QMI flags in messages which are not of the %QMI_SERVICE_CTL service. + */ +typedef enum { + QMI_SERVICE_FLAG_NONE = 0, + QMI_SERVICE_FLAG_COMPOUND = 1 << 0, + QMI_SERVICE_FLAG_RESPONSE = 1 << 1, + QMI_SERVICE_FLAG_INDICATION = 1 << 2 +} QmiServiceFlag; + +#endif /* _LIBQMI_GLIB_QMI_ENUMS_PRIVATE_H_ */ diff --git a/release/src/router/uqmi/qmi-enums-wda.h b/release/src/router/uqmi/qmi-enums-wda.h new file mode 100644 index 0000000000..b45bae0f5b --- /dev/null +++ b/release/src/router/uqmi/qmi-enums-wda.h @@ -0,0 +1,68 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * libqmi-glib -- GLib/GIO based library to control QMI devices + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2014 Aleksander Morgado + */ + +#ifndef _LIBQMI_GLIB_QMI_ENUMS_WDA_H_ +#define _LIBQMI_GLIB_QMI_ENUMS_WDA_H_ + +/** + * SECTION: qmi-enums-wda + * @title: WDA enumerations and flags + * + * This section defines enumerations and flags used in the WDA service + * interface. + */ + +/** + * QmiWdaLinkLayerProtocol: + * @QMI_WDA_LINK_LAYER_PROTOCOL_UNKNOWN: Unknown. + * @QMI_WDA_LINK_LAYER_PROTOCOL_802_3: 802.3 ethernet mode. + * @QMI_WDA_LINK_LAYER_PROTOCOL_RAW_IP: Raw IP mode. + * + * Link layer protocol. + */ +typedef enum { + QMI_WDA_LINK_LAYER_PROTOCOL_UNKNOWN = 0x00, + QMI_WDA_LINK_LAYER_PROTOCOL_802_3 = 0x01, + QMI_WDA_LINK_LAYER_PROTOCOL_RAW_IP = 0x02, +} QmiWdaLinkLayerProtocol; + +/** + * QmiWdaDataAggregationProtocol: + * @QMI_WDA_DATA_AGGREGATION_PROTOCOL_DISABLED: Disabled. + * @QMI_WDA_DATA_AGGREGATION_PROTOCOL_TLP: TLP enabled. + * @QMI_WDA_DATA_AGGREGATION_PROTOCOL_QC_NCM: QC NCM enabled. + * @QMI_WDA_DATA_AGGREGATION_PROTOCOL_MBIM: MBIM enabled. + * @QMI_WDA_DATA_AGGREGATION_PROTOCOL_RNDIS: RNDIS enabled. + * @QMI_WDA_DATA_AGGREGATION_PROTOCOL_QMAP: QMAP enabled. + * + * Data aggregation protocol in uplink or downlink. + */ +typedef enum { + QMI_WDA_DATA_AGGREGATION_PROTOCOL_DISABLED = 0x00, + QMI_WDA_DATA_AGGREGATION_PROTOCOL_TLP = 0x01, + QMI_WDA_DATA_AGGREGATION_PROTOCOL_QC_NCM = 0x02, + QMI_WDA_DATA_AGGREGATION_PROTOCOL_MBIM = 0x03, + QMI_WDA_DATA_AGGREGATION_PROTOCOL_RNDIS = 0x04, + QMI_WDA_DATA_AGGREGATION_PROTOCOL_QMAP = 0x05, +} QmiWdaDataAggregationProtocol; + +#endif /* _LIBQMI_GLIB_QMI_ENUMS_WDA_H_ */ diff --git a/release/src/router/uqmi/qmi-enums-wds.h b/release/src/router/uqmi/qmi-enums-wds.h new file mode 100644 index 0000000000..6af59363fb --- /dev/null +++ b/release/src/router/uqmi/qmi-enums-wds.h @@ -0,0 +1,1017 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * uqmi -- tiny QMI support implementation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012 Lanedo GmbH + */ + +#ifndef _LIBQMI_GLIB_QMI_ENUMS_WDS_H_ +#define _LIBQMI_GLIB_QMI_ENUMS_WDS_H_ + +/*****************************************************************************/ +/* Helper enums for the 'QMI WDS Start Network' message */ + +/** + * QmiWdsIpFamily: + * @QMI_WDS_IP_FAMILY_IPV4: IPv4. + * @QMI_WDS_IP_FAMILY_IPV6: IPv6. + * @QMI_WDS_IP_FAMILY_UNSPECIFIED: None specified. + * + * Type of IP family preference. + */ +typedef enum { + QMI_WDS_IP_FAMILY_IPV4 = 4, + QMI_WDS_IP_FAMILY_IPV6 = 6, + QMI_WDS_IP_FAMILY_UNSPECIFIED = 8 +} QmiWdsIpFamily; + +/** + * QmiWdsTechnologyPreference: + * @QMI_WDS_TECHNOLOGY_PREFERENCE_ALLOW_3GPP: 3GPP allowed. + * @QMI_WDS_TECHNOLOGY_PREFERENCE_ALLOW_3GPP2: 3GPP2 allowed. + * + * Type of network allowed when trying to connect. + */ +typedef enum { + QMI_WDS_TECHNOLOGY_PREFERENCE_ALLOW_3GPP = 1 << 0, + QMI_WDS_TECHNOLOGY_PREFERENCE_ALLOW_3GPP2 = 1 << 1 +} QmiWdsTechnologyPreference; + +/** + * QmiWdsExtendedTechnologyPreference: + * @QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_CDMA: Use CDMA. + * @QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_UMTS: Use UMTS. + * @QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_EPC: Use EPC (LTE). + * @QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_EMBMS: Use eMBMS. + * @QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_MODEM_LINK_LOCAL: Use modem link-local. + * + * Type of network allowed when trying to connect. + */ +typedef enum { + QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_CDMA = 32769, + QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_UMTS = 32772, + QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_EPC = 34944, + QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_EMBMS = 34946, + QMI_WDS_EXTENDED_TECHNOLOGY_PREFERENCE_MODEM_LINK_LOCAL = 34952, +} QmiWdsExtendedTechnologyPreference; + +/** + * QmiWdsCallType: + * @QMI_WDS_CALL_TYPE_LAPTOP: Laptop call. + * @QMI_WDS_CALL_TYPE_EMBEDDED: Embedded call. + * + * Type of call to originate. + */ +typedef enum { + QMI_WDS_CALL_TYPE_LAPTOP = 0, + QMI_WDS_CALL_TYPE_EMBEDDED = 1 +} QmiWdsCallType; + +/** + * QmiWdsCallEndReason: + * @QMI_WDS_CALL_END_REASON_GENERIC_UNSPECIFIED: Unspecified reason. + * @QMI_WDS_CALL_END_REASON_GENERIC_CLIENT_END: Client end. + * @QMI_WDS_CALL_END_REASON_GENERIC_NO_SERVICE: No service. + * @QMI_WDS_CALL_END_REASON_GENERIC_FADE: Fade. + * @QMI_WDS_CALL_END_REASON_GENERIC_RELEASE_NORMAL: Release normal. + * @QMI_WDS_CALL_END_REASON_GENERIC_ACCESS_ATTEMPT_IN_PROGRESS: Access attempt in progress. + * @QMI_WDS_CALL_END_REASON_GENERIC_ACCESS_FAILURE: Access Failure. + * @QMI_WDS_CALL_END_REASON_GENERIC_REDIRECTION_OR_HANDOFF: Redirection or handoff. + * @QMI_WDS_CALL_END_REASON_GENERIC_CLOSE_IN_PROGRESS: Close in progress. + * @QMI_WDS_CALL_END_REASON_GENERIC_AUTHENTICATION_FAILED: Authentication failed. + * @QMI_WDS_CALL_END_REASON_GENERIC_INTERNAL_ERROR: Internal error. + * @QMI_WDS_CALL_END_REASON_CDMA_LOCK: (CDMA) Phone is CDMA-locked. + * @QMI_WDS_CALL_END_REASON_CDMA_INTERCEPT: (CDMA) Received intercept from the BS. + * @QMI_WDS_CALL_END_REASON_CDMA_REORDER: (CDMA) Received reorder from the BS. + * @QMI_WDS_CALL_END_REASON_CDMA_RELEASE_SO_REJECT: (CDMA) Received release from the BS, SO reject. + * @QMI_WDS_CALL_END_REASON_CDMA_INCOMING_CALL: (CDMA) Received incoming call from the BS. + * @QMI_WDS_CALL_END_REASON_CDMA_ALERT_STOP: (CDMA) Received alert stop from the BS. + * @QMI_WDS_CALL_END_REASON_CDMA_ACTIVATION: (CDMA) Received end activation. + * @QMI_WDS_CALL_END_REASON_CDMA_MAX_ACCESS_PROBES: (CDMA) Maximum access probes transmitted. + * @QMI_WDS_CALL_END_REASON_CDMA_CCS_NOT_SUPPORTED_BY_BS: (CDMA) Concurrent service not supported by the BS. + * @QMI_WDS_CALL_END_REASON_CDMA_NO_RESPONSE_FROM_BS: (CDMA) No response received from the BS. + * @QMI_WDS_CALL_END_REASON_CDMA_REJECTED_BY_BS: (CDMA) Rejected by the BS. + * @QMI_WDS_CALL_END_REASON_CDMA_INCOMPATIBLE: (CDMA) Concurrent services requested are incompatible. + * @QMI_WDS_CALL_END_REASON_CDMA_ALREADY_IN_TC: (CDMA) Already in TC. + * @QMI_WDS_CALL_END_REASON_CDMA_USER_CALL_ORIGINATED_DURING_GPS: (CDMA) Call originated during GPS. + * @QMI_WDS_CALL_END_REASON_CDMA_USER_CALL_ORIGINATED_DURING_SMS: (CDMA) Call originated during SMS. + * @QMI_WDS_CALL_END_REASON_CDMA_NO_SERVICE: (CDMA) No service. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_CONFERENCE_FAILED: (GSM/WCDMA) Call origination request failed. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_INCOMING_REJECTED: (GSM/WCDMA) Client rejected incoming call. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_NO_SERVICE: (GSM/WCDMA) No service. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_NETWORK_END: (GSM/WCDMA) Network ended the call. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_LLC_SNDCP_FAILURE: (GSM/WCDMA) LLC or SNDCP failure. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_INSUFFICIENT_RESOURCES: (GSM/WCDMA) Insufficient resources. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_OPTION_TEMPORARILY_OUT_OF_ORDER: (GSM/WCDMA) Service option temporarily out of order. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_NSAPI_ALREADY_USED: (GSM/WCDMA) NSAPI already used. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_REGULAR_DEACTIVATION: (GSM/WCDMA) Regular PDP context deactivation. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_NETWORK_FAILURE: (GSM/WCDMA) Network failure. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_REATTACH_REQUIRED: (GSM/WCDMA) Reattach required. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_PROTOCOL_ERROR: (GSM/WCDMA) Protocol error. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_OPERATOR_DETERMINED_BARRING: (GSM/WCDMA) Operator-determined barring. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_UNKNOWN_APN: (GSM/WCDMA) Unknown or missing APN. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_UNKNOWN_PDP: (GSM/WCDMA) Unknown PDP address or type. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_GGSN_REJECT: (GSM/WCDMA) Activation rejected by GGSN. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_ACTIVATION_REJECT: (GSM/WCDMA) Activation rejected. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_OPTION_NOT_SUPPORTED: (GSM/WCDMA) Service option not supported. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_OPTION_UNSUBSCRIBED: (GSM/WCDMA) Service option not subscribed. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_QOS_NOT_ACCEPTED: (GSM/WCDMA) QoS not accepted. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_TFT_SEMANTIC_ERROR: (GSM/WCDMA) Semantic error in TFT operation. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_TFT_SYNTAX_ERROR: (GSM/WCDMA) Syntax error in TFT operation. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_UNKNOWN_PDP_CONTEXT: (GSM/WCDMA) Unknown PDP context. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_FILTER_SEMANTIC_ERROR: (GSM/WCDMA) Semantic error in packet filters. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_FILTER_SYNTAX_ERROR: (GSM/WCDMA) Syntax error in packet filters. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_PDP_WITHOUT_ACTIVE_TFT: (GSM/WCDMA) PDP context without TFT activated. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_INVALID_TRANSACTION_ID: (GSM/WCDMA) Invalid transaction ID. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_MESSAGE_INCORRECT_SEMANTIC: (GSM/WCDMA) Message incorrect semantically. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_INVALID_MANDATORY_INFO: (GSM/WCDMA) Invalid mandatory information. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_MESSAGE_TYPE_UNSUPPORTED: (GSM/WCDMA) Message type not implemented. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_MESSAGE_TYPE_NONCOMPATIBLE_STATE: (GSM/WCDMA) Message not compatible with state. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_UNKNOWN_INFO_ELEMENT: (GSM/WCDMA) Information element unknown. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_CONDITIONAL_IE_ERROR: (GSM/WCDMA) Conditional IE error. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_MESSAGE_AND_PROTOCOL_STATE_UNCOMPATIBLE: (GSM/WCDMA) Message and protocol state uncompatible. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_APN_TYPE_CONFLICT: (GSM/WCDMA) APN type conflict. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_NO_GPRS_CONTEXT: (GSM/WCDMA) No GPRS context. + * @QMI_WDS_CALL_END_REASON_GSM_WCDMA_FEATURE_NOT_SUPPORTED: (GSM/WCDMA) Feature not supported. + * @QMI_WDS_CALL_END_REASON_EVDO_CONNECTION_DENY_GENERAL_OR_BUSY: (EV-DO) Received Connection Deny (General or Network busy). + * @QMI_WDS_CALL_END_REASON_EVDO_CONNECTION_DENY_BILLING_OR_AUTHENTICATION_FAILURE: (EV-DO) Received Connection Deny (Billing or Authentication failure). + * @QMI_WDS_CALL_END_REASON_EVDO_HDR_CHANGE: (EV-DO) Change HDR. + * @QMI_WDS_CALL_END_REASON_EVDO_HDR_EXIT: (EV-DO) Exit HDR. + * @QMI_WDS_CALL_END_REASON_EVDO_HDR_NO_SESSION: (EV-DO) No HDR session. + * @QMI_WDS_CALL_END_REASON_EVDO_HDR_ORIGINATION_DURING_GPS_FIX: (EV-DO) HDR call ended in favor of a GPS fix. + * @QMI_WDS_CALL_END_REASON_EVDO_HDR_CONNECTION_SETUP_TIMEOUT: (EV-DO) Connection setup timeout. + * @QMI_WDS_CALL_END_REASON_EVDO_HDR_RELEASED_BY_CM: (EV-DO) Released HDR call by call manager. + * + * Reason for ending the call. + */ +typedef enum { + /* Generic reasons */ + QMI_WDS_CALL_END_REASON_GENERIC_UNSPECIFIED = 1, + QMI_WDS_CALL_END_REASON_GENERIC_CLIENT_END = 2, + QMI_WDS_CALL_END_REASON_GENERIC_NO_SERVICE = 3, + QMI_WDS_CALL_END_REASON_GENERIC_FADE = 4, + QMI_WDS_CALL_END_REASON_GENERIC_RELEASE_NORMAL = 5, + QMI_WDS_CALL_END_REASON_GENERIC_ACCESS_ATTEMPT_IN_PROGRESS = 6, + QMI_WDS_CALL_END_REASON_GENERIC_ACCESS_FAILURE = 7, + QMI_WDS_CALL_END_REASON_GENERIC_REDIRECTION_OR_HANDOFF = 8, + QMI_WDS_CALL_END_REASON_GENERIC_CLOSE_IN_PROGRESS = 9, + QMI_WDS_CALL_END_REASON_GENERIC_AUTHENTICATION_FAILED = 10, + QMI_WDS_CALL_END_REASON_GENERIC_INTERNAL_ERROR = 11, + + /* CDMA specific reasons */ + QMI_WDS_CALL_END_REASON_CDMA_LOCK = 500, + QMI_WDS_CALL_END_REASON_CDMA_INTERCEPT = 501, + QMI_WDS_CALL_END_REASON_CDMA_REORDER = 502, + QMI_WDS_CALL_END_REASON_CDMA_RELEASE_SO_REJECT = 503, + QMI_WDS_CALL_END_REASON_CDMA_INCOMING_CALL = 504, + QMI_WDS_CALL_END_REASON_CDMA_ALERT_STOP = 505, + QMI_WDS_CALL_END_REASON_CDMA_ACTIVATION = 506, + QMI_WDS_CALL_END_REASON_CDMA_MAX_ACCESS_PROBES = 507, + QMI_WDS_CALL_END_REASON_CDMA_CCS_NOT_SUPPORTED_BY_BS = 508, + QMI_WDS_CALL_END_REASON_CDMA_NO_RESPONSE_FROM_BS = 509, + QMI_WDS_CALL_END_REASON_CDMA_REJECTED_BY_BS = 510, + QMI_WDS_CALL_END_REASON_CDMA_INCOMPATIBLE = 511, + QMI_WDS_CALL_END_REASON_CDMA_ALREADY_IN_TC = 512, + QMI_WDS_CALL_END_REASON_CDMA_USER_CALL_ORIGINATED_DURING_GPS = 513, + QMI_WDS_CALL_END_REASON_CDMA_USER_CALL_ORIGINATED_DURING_SMS = 514, + QMI_WDS_CALL_END_REASON_CDMA_NO_SERVICE = 515, + + /* GSM/WCDMA specific reasons */ + QMI_WDS_CALL_END_REASON_GSM_WCDMA_CONFERENCE_FAILED = 1000, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_INCOMING_REJECTED = 1001, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_NO_SERVICE = 1002, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_NETWORK_END = 1003, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_LLC_SNDCP_FAILURE = 1004, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_INSUFFICIENT_RESOURCES = 1005, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_OPTION_TEMPORARILY_OUT_OF_ORDER = 1006, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_NSAPI_ALREADY_USED = 1007, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_REGULAR_DEACTIVATION = 1008, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_NETWORK_FAILURE = 1009, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_REATTACH_REQUIRED = 1010, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_PROTOCOL_ERROR = 1011, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_OPERATOR_DETERMINED_BARRING = 1012, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_UNKNOWN_APN = 1013, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_UNKNOWN_PDP = 1014, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_GGSN_REJECT = 1015, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_ACTIVATION_REJECT = 1016, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_OPTION_NOT_SUPPORTED = 1017, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_OPTION_UNSUBSCRIBED = 1018, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_QOS_NOT_ACCEPTED = 1019, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_TFT_SEMANTIC_ERROR = 1020, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_TFT_SYNTAX_ERROR = 1021, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_UNKNOWN_PDP_CONTEXT = 1022, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_FILTER_SEMANTIC_ERROR = 1023, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_FILTER_SYNTAX_ERROR = 1024, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_PDP_WITHOUT_ACTIVE_TFT = 1025, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_INVALID_TRANSACTION_ID = 1026, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_MESSAGE_INCORRECT_SEMANTIC = 1027, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_INVALID_MANDATORY_INFO = 1028, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_MESSAGE_TYPE_UNSUPPORTED = 1029, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_MESSAGE_TYPE_NONCOMPATIBLE_STATE = 1030, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_UNKNOWN_INFO_ELEMENT = 1031, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_CONDITIONAL_IE_ERROR = 1032, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_MESSAGE_AND_PROTOCOL_STATE_UNCOMPATIBLE = 1033, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_APN_TYPE_CONFLICT = 1034, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_NO_GPRS_CONTEXT = 1035, + QMI_WDS_CALL_END_REASON_GSM_WCDMA_FEATURE_NOT_SUPPORTED = 1036, + + /* EV-DO specific reasons */ + QMI_WDS_CALL_END_REASON_EVDO_CONNECTION_DENY_GENERAL_OR_BUSY = 1500, + QMI_WDS_CALL_END_REASON_EVDO_CONNECTION_DENY_BILLING_OR_AUTHENTICATION_FAILURE = 1501, + QMI_WDS_CALL_END_REASON_EVDO_HDR_CHANGE = 1502, + QMI_WDS_CALL_END_REASON_EVDO_HDR_EXIT = 1503, + QMI_WDS_CALL_END_REASON_EVDO_HDR_NO_SESSION = 1504, + QMI_WDS_CALL_END_REASON_EVDO_HDR_ORIGINATION_DURING_GPS_FIX = 1505, + QMI_WDS_CALL_END_REASON_EVDO_HDR_CONNECTION_SETUP_TIMEOUT = 1506, + QMI_WDS_CALL_END_REASON_EVDO_HDR_RELEASED_BY_CM = 1507 +} QmiWdsCallEndReason; + +/** + * QmiWdsVerboseCallEndReasonType: + * @QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_MIP: Mobile IP. + * @QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_INTERNAL: Internal. + * @QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_CM: Call manager. + * @QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_3GPP: 3GPP. + * @QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_PPP: PPP. + * @QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_EHRPD: eHRPD. + * @QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_IPV6: IPv6. + * + * Type of verbose call end reason. + */ +typedef enum { + QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_MIP = 1, + QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_INTERNAL = 2, + QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_CM = 3, + QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_3GPP = 6, + QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_PPP = 7, + QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_EHRPD = 8, + QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_IPV6 = 9 +} QmiWdsVerboseCallEndReasonType; + +/** + * QmiWdsVerboseCallEndReasonMip: + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_ERROR_REASON_UNKNOWN: Unknown reason. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_REASON_UNSPECIFIED: (FA error) Reason unspecified. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_ADMINISTRATIVELY_PROHIBITED: (FA error) Administratively prohibited. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_INSUFFICIENT_RESOURCES: (FA error) Insufficient resources. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MOBILE_NODE_AUTHENTICATION_FAILURE: (FA error) Mobile node authenticatin failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_HA_AUTHENTICATION_FAILURE: (FA error) HA authentication failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_REQUESTED_LIFETIME_TOO_LONG: (FA error) Requested lifetime too long. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MALFORMED_REQUEST: (FA error) Malformed request. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MALFORMED_REPLY: (FA error) Malformed reply. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_ENCAPSULATION_UNAVAILABLE: (FA error) Encapsulation unavailable. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_VJHC_UNAVAILABLE: (FA error) VJHC unavailable. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_REVERSE_TUNNEL_UNAVAILABLE: (FA error) Reverse tunnel unavailable. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_REVERSE_TUNNEL_MANDATORY_AND_T_BIT_NOT_SET: (FA error) Reverse tunnel mandatory and T bit not set. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_DELIVERY_STYLE_NOT_SUPPORTED: (FA error) Delivery style not supported. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MISSING_NAI: (FA error) Missing NAI. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MISSING_HA: (FA error) Missing HA. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MISSING_HOME_ADDRESS: (FA error) Missing home address. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_UNKNOWN_CHALLENGE: (FA error) Unknown challenge. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MISSING_CHALLENGE: (FA error) Missing challenge. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_STALE_CHALLENGE: (FA error) Stale challenge. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_REASON_UNSPECIFIED: (HA error) Reason unspecified. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_ADMINISTRATIVELY_PROHIBITED: (HA error) Administratively prohibited. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_INSUFFICIENT_RESOURCES: (HA error) Insufficient resources. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_MOBILE_NODE_AUTHENTICATION_FAILURE: (HA error) Mobile node authentication failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_FA_AUTHENTICATION_FAILURE: (HA error) FA authentication failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_REGISTRATION_ID_MISMATCH: (HA error) Registration ID mismatch. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_MALFORMED_REQUEST: (HA error) Malformed request. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_UNKNOWN_HA_ADDRESS: (HA error) Unknown HA address. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_REVERSE_TUNNEL_UNAVAILABLE: (HA error) Reverse tunnel unavailable. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_REVERSE_TUNNEL_MANDATORY_AND_T_BIT_NOT_SET: (HA error) Reverse tunnel mandatory and T bit not set. + * @QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_ENCAPSULATION_UNAVAILABLE: (HA error) Encapsulation unavailable. + * + * Mobile IP specific call end reasons, given when the @QmiWdsVerboseCallEndReasonType is #QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_MIP. + */ +typedef enum { + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_ERROR_REASON_UNKNOWN = -1, + + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_REASON_UNSPECIFIED = 64, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_ADMINISTRATIVELY_PROHIBITED = 65, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_INSUFFICIENT_RESOURCES = 66, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MOBILE_NODE_AUTHENTICATION_FAILURE = 67, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_HA_AUTHENTICATION_FAILURE = 68, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_REQUESTED_LIFETIME_TOO_LONG = 69, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MALFORMED_REQUEST = 70, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MALFORMED_REPLY = 71, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_ENCAPSULATION_UNAVAILABLE = 72, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_VJHC_UNAVAILABLE = 73, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_REVERSE_TUNNEL_UNAVAILABLE = 74, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_REVERSE_TUNNEL_MANDATORY_AND_T_BIT_NOT_SET = 75, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_DELIVERY_STYLE_NOT_SUPPORTED = 79, + + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MISSING_NAI = 97, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MISSING_HA = 98, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MISSING_HOME_ADDRESS = 99, + + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_UNKNOWN_CHALLENGE = 104, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_MISSING_CHALLENGE = 105, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_FA_ERROR_STALE_CHALLENGE = 106, + + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_REASON_UNSPECIFIED = 128, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_ADMINISTRATIVELY_PROHIBITED = 129, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_INSUFFICIENT_RESOURCES = 130, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_MOBILE_NODE_AUTHENTICATION_FAILURE = 131, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_FA_AUTHENTICATION_FAILURE = 132, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_REGISTRATION_ID_MISMATCH = 133, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_MALFORMED_REQUEST = 134, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_UNKNOWN_HA_ADDRESS = 136, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_REVERSE_TUNNEL_UNAVAILABLE = 137, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_REVERSE_TUNNEL_MANDATORY_AND_T_BIT_NOT_SET = 138, + QMI_WDS_VERBOSE_CALL_END_REASON_MIP_HA_ERROR_ENCAPSULATION_UNAVAILABLE = 139 +} QmiWdsVerboseCallEndReasonMip; + +/** + * QmiWdsVerboseCallEndReasonInternal: + * @QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_ERROR: Internal error. + * @QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_CALL_ENDED: Call ended. + * @QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_UNKNOWN_INTERNAL_CAUSE: Unknown internal cause. + * @QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_UNKNOWN_CAUSE: Unknown cause. + * @QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_CLOSE_IN_PROGRESS: Close in progress. + * @QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_NETWORK_INITIATED_TERMINATION: Network initiated termination. + * @QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_APP_PREEMPTED: App preempted. + * + * Internal call end reasons, given when the @QmiWdsVerboseCallEndReasonType is #QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_INTERNAL. + */ +typedef enum { + QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_ERROR = 201, + QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_CALL_ENDED = 202, + QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_UNKNOWN_INTERNAL_CAUSE = 203, + QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_UNKNOWN_CAUSE = 204, + QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_CLOSE_IN_PROGRESS = 205, + QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_NETWORK_INITIATED_TERMINATION = 206, + QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_APP_PREEMPTED = 207 +} QmiWdsVerboseCallEndReasonInternal; + +/** + * QmiWdsVerboseCallEndReasonCm: + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_CDMA_LOCK: (CDMA) Phone is CDMA-locked. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_INTERCEPT: (CDMA) Received intercept from the BS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_REORDER: (CDMA) Received reorder from the BS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_RELEASE_SO_REJECT: (CDMA) Received release from the BS, SO reject. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_INCOMING_CALL: (CDMA) Received incoming call from the BS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_ALERT_STOP: (CDMA) Received alert stop from the BS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_ACTIVATION: (CDMA) Received end activation. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_MAX_ACCESS_PROBES: (CDMA) Maximum access probes transmitted. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_CCS_NOT_SUPPORTED_BY_BS: (CDMA) Concurrent service not supported by the BS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_RESPONSE_FROM_BS: (CDMA) No response received from the BS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_REJECTED_BY_BS: (CDMA) Rejected by the BS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_INCOMPATIBLE: (CDMA) Concurrent services requested are incompatible. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_ALREADY_IN_TC: (CDMA) Already in TC. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_USER_CALL_ORIGINATED_DURING_GPS: (CDMA) Call originated during GPS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_USER_CALL_ORIGINATED_DURING_SMS: (CDMA) Call originated during SMS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_CDMA_SERVICE: (CDMA) No service. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_RETRY_ORDER: Retry order. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_CONFIGURATION_FAILED: Configuration failed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_INCOMING_REJECTED: Incoming rejected. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_GATEWAY_SERVICE: No gateway service. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_GPRS_CONTEXT: No GPRS context. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_ILLEGAL_MS: Illegal MS. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_ILLEGAL_ME: Illegal ME. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_GPRS_AND_NON_GPRS_SERVICES_NOT_ALLOWED: GPRS and non GPRS services not allowed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_GPRS_SERVICES_NOT_ALLOWED: GPRS services not allowed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_MS_IDENTITY_NOT_DERIVED_BY_THE_NETWORK: MS identity not derived by the network. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_IMPLICITLY_DETACHED: Implicitly detached. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_PLMN_NOT_ALLOWED: PLMN not allowed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_LA_NOT_ALLOWED: LA not allowed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_GPRS_SERVICES_NOT_ALLOWED_IN_PLMN: GPRS services not allowed in PLMN. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_PDP_DUPLICATE: PDP duplicate. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_UE_RAT_CHANGE: UE radio access technology change. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_CONGESTION: Congestion. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_PDP_CONTEXT_ACTIVATED: No PDP context activated. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_ACCESS_CLASS_DSAC_REJECTION: Access class DSAC rejection. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_CONNECTION_DENY_GENERAL_OR_BUSY: (EV-DO) Received Connection Deny (General or Network busy). + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_CONNECTION_DENY_BILLING_OR_AUTHENTICATION_FAILURE: (EV-DO) Received Connection Deny (Billing or Authentication failure). + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_CHANGE: (EV-DO) Change HDR. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_EXIT: (EV-DO) Exit HDR. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_NO_SESSION: (EV-DO) No HDR session. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_ORIGINATION_DURING_GPS_FIX: (EV-DO) HDR call ended in favor of a GPS fix. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_CONNECTION_SETUP_TIMEOUT: (EV-DO) Connection setup timeout. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_RELEASED_BY_CM: (EV-DO) Released HDR call by call manager. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_HYBRID_HDR_SERVICE: (EV-DO) No hybrid HDR service. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_CLIENT_END: Client end. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_SERVICE: No service. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_FADE: Fade. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_RELEASE_NORMAL: Release normal. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_ACCESS_ATTEMPT_IN_PROGRESS: Access attempt in progress. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_ACCESS_FAILURE: Access Failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_CM_REDIRECTION_OR_HANDOFF: Redirection or handoff. + * + * Call manager specific call end reasons, given when the @QmiWdsVerboseCallEndReasonType is #QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_CM. + */ +typedef enum { + QMI_WDS_VERBOSE_CALL_END_REASON_CM_CDMA_LOCK = 500, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_INTERCEPT = 501, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_REORDER = 502, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_RELEASE_SO_REJECT = 503, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_INCOMING_CALL = 504, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_ALERT_STOP = 505, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_ACTIVATION = 506, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_MAX_ACCESS_PROBES = 507, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_CCS_NOT_SUPPORTED_BY_BS = 508, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_RESPONSE_FROM_BS = 509, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_REJECTED_BY_BS = 510, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_INCOMPATIBLE = 511, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_ALREADY_IN_TC = 512, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_USER_CALL_ORIGINATED_DURING_GPS = 513, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_USER_CALL_ORIGINATED_DURING_SMS = 514, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_CDMA_SERVICE = 515, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_RETRY_ORDER = 519, + + QMI_WDS_VERBOSE_CALL_END_REASON_CM_CONFIGURATION_FAILED = 1000, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_INCOMING_REJECTED = 1001, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_GATEWAY_SERVICE = 1002, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_GPRS_CONTEXT = 1003, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_ILLEGAL_MS = 1004, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_ILLEGAL_ME = 1005, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_GPRS_AND_NON_GPRS_SERVICES_NOT_ALLOWED = 1006, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_GPRS_SERVICES_NOT_ALLOWED = 1007, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_MS_IDENTITY_NOT_DERIVED_BY_THE_NETWORK = 1008, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_IMPLICITLY_DETACHED = 1009, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_PLMN_NOT_ALLOWED = 1010, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_LA_NOT_ALLOWED = 1011, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_GPRS_SERVICES_NOT_ALLOWED_IN_PLMN = 1012, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_PDP_DUPLICATE = 1013, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_UE_RAT_CHANGE = 1014, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_CONGESTION = 1015, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_PDP_CONTEXT_ACTIVATED = 1016, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_ACCESS_CLASS_DSAC_REJECTION = 1017, + + QMI_WDS_VERBOSE_CALL_END_REASON_CM_CONNECTION_DENY_GENERAL_OR_BUSY = 1500, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_CONNECTION_DENY_BILLING_OR_AUTHENTICATION_FAILURE = 1501, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_CHANGE = 1502, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_EXIT = 1503, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_NO_SESSION = 1504, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_ORIGINATION_DURING_GPS_FIX = 1505, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_CONNECTION_SETUP_TIMEOUT = 1506, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_HDR_RELEASED_BY_CM = 1507, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_HYBRID_HDR_SERVICE = 1510, + + QMI_WDS_VERBOSE_CALL_END_REASON_CM_CLIENT_END = 2000, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_NO_SERVICE = 2001, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_FADE = 2002, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_RELEASE_NORMAL = 2003, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_ACCESS_ATTEMPT_IN_PROGRESS = 2004, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_ACCESS_FAILURE = 2005, + QMI_WDS_VERBOSE_CALL_END_REASON_CM_REDIRECTION_OR_HANDOFF = 2006 +} QmiWdsVerboseCallEndReasonCm; + +/** + * QmiWdsVerboseCallEndReason3gpp: + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPERATOR_DETERMINED_BARRING: Operator-determined barring. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_LLC_SNDCP_FAILURE: LLC or SNDCP failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_INSUFFICIENT_RESOURCES: Insufficient resources. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_APN: Unknown or missing APN. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_PDP: Unknown PDP address or type. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_AUTHENTICATION_FAILED: Authentication failed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_GGSN_REJECT: Activation rejected by GGSN. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_ACTIVATION_REJECT: Activation rejected. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPTION_NOT_SUPPORTED: Service option not supported. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPTION_UNSUBSCRIBED: Service option not subscribed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPTION_TEMPORARILY_OUT_OF_ORDER: Service option temporarily out of order. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_NSAPI_ALREADY_USED: NSAPI already used. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_REGULAR_DEACTIVATION: Regular PDP context deactivation. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_QOS_NOT_ACCEPTED: QoS not accepted. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_NETWORK_FAILURE: Network failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_REATTACH_REQUIRED: Reattach required. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_FEATURE_NOT_SUPPORTED: Feature not supported. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_TFT_SEMANTIC_ERROR: Semantic error in TFT operation. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_TFT_SYNTAX_ERROR: Syntax error in TFT operation. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_PDP_CONTEXT: Unknown PDP context. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_FILTER_SEMANTIC_ERROR: Semantic error in packet filters. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_FILTER_SYNTAX_ERROR: Syntax error in packet filters. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_PDP_WITHOUT_ACTIVE_TFT: PDP context without TFT activated. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_IPV4_ONLY_ALLOWED: IPv4 only allowed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_IPV6_ONLY_ALLOWED: IPv6 only allowed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_SINGLE_ADDRESS_BEARER_ONLY: Single address bearer only. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_ESM_INFO_NOT_RECEIVED: ESM information not received. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_PDN_CONNECTION_DOES_NOT_EXIST: PDN connection does not exist. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MULTIPLE_CONNECTION_TO_SAME_PDN_NOT_ALLOWED: Multiple connection to same PDN not allowed. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_INVALID_TRANSACTION_ID: Invalid transaction ID. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_INCORRECT_SEMANTIC: Message incorrect semantically. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_INVALID_MANDATORY_INFO: Invalid mandatory information. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_TYPE_UNSUPPORTED: Message type not implemented. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_TYPE_NONCOMPATIBLE_STATE: Message not compatible with state. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_INFO_ELEMENT: Information element unknown. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_CONDITIONAL_IE_ERROR: Conditional IE error. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_AND_PROTOCOL_STATE_UNCOMPATIBLE: Message and protocol state uncompatible. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_PROTOCOL_ERROR: Protocol error. + * @QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_APN_TYPE_CONFLICT: APN type conflict. + * + * 3GPP-specific call end reasons, given when the @QmiWdsVerboseCallEndReasonType is #QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_3GPP. + */ +typedef enum { /*< underscore_name=qmi_wds_verbose_call_end_reason_3gpp >*/ + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPERATOR_DETERMINED_BARRING = 8, + + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_LLC_SNDCP_FAILURE = 25, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_INSUFFICIENT_RESOURCES = 26, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_APN = 27, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_PDP = 28, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_AUTHENTICATION_FAILED = 29, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_GGSN_REJECT = 30, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_ACTIVATION_REJECT = 31, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPTION_NOT_SUPPORTED = 32, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPTION_UNSUBSCRIBED = 33, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPTION_TEMPORARILY_OUT_OF_ORDER = 34, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_NSAPI_ALREADY_USED = 35, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_REGULAR_DEACTIVATION = 36, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_QOS_NOT_ACCEPTED = 37, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_NETWORK_FAILURE = 38, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_REATTACH_REQUIRED = 39, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_FEATURE_NOT_SUPPORTED = 40, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_TFT_SEMANTIC_ERROR = 41, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_TFT_SYNTAX_ERROR = 42, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_PDP_CONTEXT = 43, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_FILTER_SEMANTIC_ERROR = 44, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_FILTER_SYNTAX_ERROR = 45, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_PDP_WITHOUT_ACTIVE_TFT = 46, + + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_IPV4_ONLY_ALLOWED = 50, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_IPV6_ONLY_ALLOWED = 51, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_SINGLE_ADDRESS_BEARER_ONLY = 52, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_ESM_INFO_NOT_RECEIVED = 53, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_PDN_CONNECTION_DOES_NOT_EXIST = 54, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MULTIPLE_CONNECTION_TO_SAME_PDN_NOT_ALLOWED = 55, + + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_INVALID_TRANSACTION_ID = 81, + + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_INCORRECT_SEMANTIC = 95, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_INVALID_MANDATORY_INFO = 96, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_TYPE_UNSUPPORTED = 97, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_TYPE_NONCOMPATIBLE_STATE = 98, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_INFO_ELEMENT = 99, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_CONDITIONAL_IE_ERROR = 100, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_AND_PROTOCOL_STATE_UNCOMPATIBLE = 101, + + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_PROTOCOL_ERROR = 111, + QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_APN_TYPE_CONFLICT = 112 +} QmiWdsVerboseCallEndReason3gpp; + +/** + * QmiWdsVerboseCallEndReasonPpp: + * @QMI_WDS_VERBOSE_CALL_END_REASON_PPP_UNKNOWN: Unknown error. + * @QMI_WDS_VERBOSE_CALL_END_REASON_PPP_TIMEOUT: Timeout. + * @QMI_WDS_VERBOSE_CALL_END_REASON_PPP_AUTHENTICATION_FAILURE: Authentication failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_PPP_OPTION_MISMATCH: Option mismatch. + * @QMI_WDS_VERBOSE_CALL_END_REASON_PPP_PAP_FAILURE: PAP failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_PPP_CHAP_FAILURE: CHAP failure. + * + * PPP-specific call end reasons, given when the @QmiWdsVerboseCallEndReasonType is #QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_PPP. + */ +typedef enum { + QMI_WDS_VERBOSE_CALL_END_REASON_PPP_UNKNOWN = -1, + + QMI_WDS_VERBOSE_CALL_END_REASON_PPP_TIMEOUT = 1, + QMI_WDS_VERBOSE_CALL_END_REASON_PPP_AUTHENTICATION_FAILURE = 2, + QMI_WDS_VERBOSE_CALL_END_REASON_PPP_OPTION_MISMATCH = 3, + + QMI_WDS_VERBOSE_CALL_END_REASON_PPP_PAP_FAILURE = 31, + QMI_WDS_VERBOSE_CALL_END_REASON_PPP_CHAP_FAILURE = 32 +} QmiWdsVerboseCallEndReasonPpp; + +/** + * QmiWdsVerboseCallEndReasonEhrpd: + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_SUBSCRIPTION_LIMITED_TO_IPV4: Subscription limited to IPv4. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_SUBSCRIPTION_LIMITED_TO_IPV6: Subscription limited to IPv6. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_TIMEOUT: (VSNCP) timeout. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_FAILURE: (VSNCP) failure. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_GENERAL_ERROR: (VSCNP) 3GPP2 general error. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_UNAUTHENTICATED_APN: (VSCNP) 3GPP2 unauthenticated APN. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_LIMIT_EXCEEDED: (VSCNP) 3GPP2 PDN limit exceeded. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_NO_PDN_GATEWAY: (VSCNP) 3GPP2 no PDN gateway. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_GATEWAY_UNREACHABLE: (VSCNP) 3GPP2 PDN gateway unreachable. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_GATEWAY_REJECTED: (VSCNP) 3GPP2 PDN gateway rejected. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_INSUFFICIENT_PARAMETERS: (VSCNP) 3GPP2 insufficient parameters. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_RESOURCE_UNAVAILABLE: (VSCNP) 3GPP2 resource unavailable. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_ADMINISTRATIVELY_PROHIBITED: (VSCNP) 3GPP2 administratively prohibited. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_ID_IN_USE: (VSCNP) 3GPP2 PDN ID in use. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_SUBSCRIPTION_LIMITATION: (VSCNP) 3GPP2 subscription limitation. + * @QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_EXISTS_FOR_THIS_APN: (VSCNP) 3GPP2 PDN exists for this APN. + * + * eHRPD-specific call end reasons, given when the @QmiWdsVerboseCallEndReasonType is #QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_EHRPD. + */ +typedef enum { + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_SUBSCRIPTION_LIMITED_TO_IPV4 = 1, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_SUBSCRIPTION_LIMITED_TO_IPV6 = 2, + + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_TIMEOUT = 4, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_FAILURE = 5, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_GENERAL_ERROR = 6, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_UNAUTHENTICATED_APN = 7, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_LIMIT_EXCEEDED = 8, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_NO_PDN_GATEWAY = 9, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_GATEWAY_UNREACHABLE = 10, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_GATEWAY_REJECTED = 11, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_INSUFFICIENT_PARAMETERS = 12, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_RESOURCE_UNAVAILABLE = 13, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_ADMINISTRATIVELY_PROHIBITED = 14, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_ID_IN_USE = 15, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_SUBSCRIPTION_LIMITATION = 16, + QMI_WDS_VERBOSE_CALL_END_REASON_EHRPD_VSNCP_3GPP2_PDN_EXISTS_FOR_THIS_APN = 17 +} QmiWdsVerboseCallEndReasonEhrpd; + +/** + * QmiWdsVerboseCallEndReasonIpv6: + * @QMI_WDS_VERBOSE_CALL_END_REASON_IPV6_PREFIX_UNAVAILABLE: Prefix unavailable. + * @QMI_WDS_VERBOSE_CALL_END_REASON_IPV6_HRPD_IPV6_DISABLED: HRDP IPv6 disabled. + * + * IPv6-specific call end reasons, given when the @QmiWdsVerboseCallEndReasonType is #QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_IPV6. + */ +typedef enum { + QMI_WDS_VERBOSE_CALL_END_REASON_IPV6_PREFIX_UNAVAILABLE = 1, + QMI_WDS_VERBOSE_CALL_END_REASON_IPV6_HRPD_IPV6_DISABLED = 2 +} QmiWdsVerboseCallEndReasonIpv6; + +/*****************************************************************************/ +/* Helper enums for the 'QMI WDS Get Packet Service Status' message */ + +/** + * QmiWdsConnectionStatus: + * @QMI_WDS_CONNECTION_STATUS_UNKNOWN: Unknown status. + * @QMI_WDS_CONNECTION_STATUS_DISCONNECTED: Network is disconnected + * @QMI_WDS_CONNECTION_STATUS_CONNECTED: Network is connected. + * @QMI_WDS_CONNECTION_STATUS_SUSPENDED: Network connection is suspended. + * @QMI_WDS_CONNECTION_STATUS_AUTHENTICATING: Network authentication is ongoing. + * + * Status of the network connection. + */ +typedef enum { + QMI_WDS_CONNECTION_STATUS_UNKNOWN = 0, + QMI_WDS_CONNECTION_STATUS_DISCONNECTED = 1, + QMI_WDS_CONNECTION_STATUS_CONNECTED = 2, + QMI_WDS_CONNECTION_STATUS_SUSPENDED = 3, + QMI_WDS_CONNECTION_STATUS_AUTHENTICATING = 4 +} QmiWdsConnectionStatus; + + +/*****************************************************************************/ +/* Helper enums for the 'QMI WDS Get Data Bearer Technology' message */ + +/** + * QmiWdsDataBearerTechnology: + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_UNKNOWN: Unknown. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_CDMA20001X: CDMA2000 1x. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_1xEVDO: CDMA2000 HRPD 1xEV-DO. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_GSM: GSM. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_UMTS: UMTS. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_1xEVDO_REVA: CDMA2000 HRPD 1xEV-DO RevA. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_EDGE: EDGE. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_HSDPA: HSDPA and WCDMA. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_HSUPA: WCDMA and HSUPA. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_HSDPA_HSUPDA: HSDPA and HSUPA. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_LTE: LTE. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_EHRPD: CDMA2000 eHRPD. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_HSDPAPLUS: HSDPA+ and WCDMA. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_HSDPAPLUS_HSUPA: HSDPA+ and HSUPA. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_DCHSDPAPLUS: DC-HSDPA+ and WCDMA. + * @QMI_WDS_DATA_BEARER_TECHNOLOGY_DCHSDPAPLUS_HSUPA: DC-HSDPA+ and HSUPA. + * + * Data bearer technology. + */ +typedef enum { + QMI_WDS_DATA_BEARER_TECHNOLOGY_UNKNOWN = -1, + QMI_WDS_DATA_BEARER_TECHNOLOGY_CDMA20001X = 0x01, + QMI_WDS_DATA_BEARER_TECHNOLOGY_1xEVDO = 0x02, + QMI_WDS_DATA_BEARER_TECHNOLOGY_GSM = 0x03, + QMI_WDS_DATA_BEARER_TECHNOLOGY_UMTS = 0x04, + QMI_WDS_DATA_BEARER_TECHNOLOGY_1xEVDO_REVA = 0x05, + QMI_WDS_DATA_BEARER_TECHNOLOGY_EDGE = 0x06, + QMI_WDS_DATA_BEARER_TECHNOLOGY_HSDPA = 0x07, + QMI_WDS_DATA_BEARER_TECHNOLOGY_HSUPA = 0x08, + QMI_WDS_DATA_BEARER_TECHNOLOGY_HSDPA_HSUPDA = 0x09, + QMI_WDS_DATA_BEARER_TECHNOLOGY_LTE = 0x0A, + QMI_WDS_DATA_BEARER_TECHNOLOGY_EHRPD = 0x0B, + QMI_WDS_DATA_BEARER_TECHNOLOGY_HSDPAPLUS = 0x0C, + QMI_WDS_DATA_BEARER_TECHNOLOGY_HSDPAPLUS_HSUPA = 0x0D, + QMI_WDS_DATA_BEARER_TECHNOLOGY_DCHSDPAPLUS = 0x0E, + QMI_WDS_DATA_BEARER_TECHNOLOGY_DCHSDPAPLUS_HSUPA = 0x0F +} QmiWdsDataBearerTechnology; + + +/*****************************************************************************/ +/* Helper enums for the 'QMI WDS Get Current Data Bearer Technology' message */ + +/** + * QmiWdsNetworkType: + * @QMI_WDS_NETWORK_TYPE_UNKNOWN: Unknown. + * @QMI_WDS_NETWORK_TYPE_3GPP2: 3GPP2 network type. + * @QMI_WDS_NETWORK_TYPE_3GPP: 3GPP network type. + * + * Network type of the data bearer. + */ +typedef enum { + QMI_WDS_NETWORK_TYPE_UNKNOWN = 0, + QMI_WDS_NETWORK_TYPE_3GPP2 = 1, + QMI_WDS_NETWORK_TYPE_3GPP = 2 +} QmiWdsNetworkType; + +/** + * QmiWdsRat3gpp2: + * @QMI_WDS_RAT_3GPP2_NONE: Unknown, to be ignored. + * @QMI_WDS_RAT_3GPP2_CDMA1X: CDMA 1x. + * @QMI_WDS_RAT_3GPP2_EVDO_REV0: EVDO Rev0. + * @QMI_WDS_RAT_3GPP2_EVDO_REVA: EVDO RevA. + * @QMI_WDS_RAT_3GPP2_EVDO_REVB: EVDO RevB. + * @QMI_WDS_RAT_3GPP2_NULL_BEARER: No bearer. + * + * Flags specifying the 3GPP2-specific Radio Access Technology, when the data + * bearer network type is @QMI_WDS_NETWORK_TYPE_3GPP2. + */ +typedef enum { /*< underscore_name=qmi_wds_rat_3gpp2 >*/ + QMI_WDS_RAT_3GPP2_NONE = 0, + QMI_WDS_RAT_3GPP2_CDMA1X = 1 << 0, + QMI_WDS_RAT_3GPP2_EVDO_REV0 = 1 << 1, + QMI_WDS_RAT_3GPP2_EVDO_REVA = 1 << 2, + QMI_WDS_RAT_3GPP2_EVDO_REVB = 1 << 3, + QMI_WDS_RAT_3GPP2_NULL_BEARER = 1 << 15 +} QmiWdsRat3gpp2; + +/** + * QmiWdsRat3gpp: + * @QMI_WDS_RAT_3GPP_NONE: Unknown, to be ignored. + * @QMI_WDS_RAT_3GPP_WCDMA: WCDMA. + * @QMI_WDS_RAT_3GPP_GPRS: GPRS. + * @QMI_WDS_RAT_3GPP_HSDPA: HSDPA. + * @QMI_WDS_RAT_3GPP_HSUPA: HSUPA. + * @QMI_WDS_RAT_3GPP_EDGE: EDGE. + * @QMI_WDS_RAT_3GPP_LTE: LTE. + * @QMI_WDS_RAT_3GPP_HSDPAPLUS: HSDPA+. + * @QMI_WDS_RAT_3GPP_DCHSDPAPLUS: DC-HSDPA+ + * @QMI_WDS_RAT_3GPP_NULL_BEARER: No bearer. + * + * Flags specifying the 3GPP-specific Radio Access Technology, when the data + * bearer network type is @QMI_WDS_NETWORK_TYPE_3GPP. + */ +typedef enum { /*< underscore_name=qmi_wds_rat_3gpp >*/ + QMI_WDS_RAT_3GPP_NONE = 0, + QMI_WDS_RAT_3GPP_WCDMA = 1 << 0, + QMI_WDS_RAT_3GPP_GPRS = 1 << 1, + QMI_WDS_RAT_3GPP_HSDPA = 1 << 2, + QMI_WDS_RAT_3GPP_HSUPA = 1 << 3, + QMI_WDS_RAT_3GPP_EDGE = 1 << 4, + QMI_WDS_RAT_3GPP_LTE = 1 << 5, + QMI_WDS_RAT_3GPP_HSDPAPLUS = 1 << 6, + QMI_WDS_RAT_3GPP_DCHSDPAPLUS = 1 << 7, + QMI_WDS_RAT_3GPP_NULL_BEARER = 1 << 15 +} QmiWdsRat3gpp; + +/** + * QmiWdsSoCdma1x: + * @QMI_WDS_SO_CDMA1X_NONE: Unknown, to be ignored. + * @QMI_WDS_SO_CDMA1X_IS95: IS95. + * @QMI_WDS_SO_CDMA1X_IS2000: IS2000. + * @QMI_WDS_SO_CDMA1X_IS2000_REL_A: IS2000 RelA. + * + * Flags specifying the Service Option when the bearer network type is + * @QMI_WDS_NETWORK_TYPE_3GPP2 and when the Radio Access Technology mask + * contains @QMI_WDS_RAT_3GPP2_CDMA1X. + */ +typedef enum { + QMI_WDS_SO_CDMA1X_NONE = 0, + QMI_WDS_SO_CDMA1X_IS95 = 1 << 0, + QMI_WDS_SO_CDMA1X_IS2000 = 1 << 1, + QMI_WDS_SO_CDMA1X_IS2000_REL_A = 1 << 2 +} QmiWdsSoCdma1x; + +/** + * QmiWdsSoEvdoRevA: + * @QMI_WDS_SO_EVDO_REVA_NONE: Unknown, to be ignored. + * @QMI_WDS_SO_EVDO_REVA_DPA: DPA. + * @QMI_WDS_SO_EVDO_REVA_MFPA: MFPA. + * @QMI_WDS_SO_EVDO_REVA_EMPA: EMPA. + * @QMI_WDS_SO_EVDO_REVA_EMPA_EHRPD: EMPA EHRPD. + * + * Flags specifying the Service Option when the bearer network type is + * @QMI_WDS_NETWORK_TYPE_3GPP2 and when the Radio Access Technology mask + * contains @QMI_WDS_RAT_3GPP2_EVDO_REVA. + */ +typedef enum { /*< underscore_name=qmi_wds_so_evdo_reva >*/ + QMI_WDS_SO_EVDO_REVA_NONE = 0, + QMI_WDS_SO_EVDO_REVA_DPA = 1 << 0, + QMI_WDS_SO_EVDO_REVA_MFPA = 1 << 1, + QMI_WDS_SO_EVDO_REVA_EMPA = 1 << 2, + QMI_WDS_SO_EVDO_REVA_EMPA_EHRPD = 1 << 3 +} QmiWdsSoEvdoRevA; + + +/*****************************************************************************/ +/* Helper enums for the 'QMI WDS Get Current Settings' message */ + +/** + * QmiWdsGetCurrentSettingsRequestedSettings: + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_NONE: no settings requested + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PROFILE_ID: request profile ID + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PROFILE_NAME: request profile name + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PDP_TYPE: request PDP context type + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_APN_NAME: request APN name + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DNS_ADDRESS: request DNS server addresses + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GRANTED_QOS: request granted QoS + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_USERNAME: request username + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_AUTH_PROTOCOL: request authentication protocol (ie PAP/CHAP/none) + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_ADDRESS: request IP address + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GATEWAY_INFO: request gateway address + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PCSCF_ADDRESS: request PCSCF address + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PCSCF_SERVER_ADDRESS_LIST: request PCSCF server address list + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PCSCF_DOMAIN_NAME_LIST: request PCSCF domain name list + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_MTU: request MTU + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DOMAIN_NAME_LIST: request domain name list + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_FAMILY: request IP family (ie IPv4 or IPv6) + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IMCN_FLAG: request IMCN flag + * @QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_EXTENDED_TECHNOLOGY: request extended technology info + * + * Flags specifying which specific settings to return when requesting the + * current WDS bearer settings. + */ +typedef enum { /*< underscore_name=qmi_wds_get_current_settings_requested_settings >*/ + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_NONE = 0, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PROFILE_ID = 1 << 0, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PROFILE_NAME = 1 << 1, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PDP_TYPE = 1 << 2, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_APN_NAME = 1 << 3, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DNS_ADDRESS = 1 << 4, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GRANTED_QOS = 1 << 5, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_USERNAME = 1 << 6, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_AUTH_PROTOCOL = 1 << 7, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_ADDRESS = 1 << 8, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GATEWAY_INFO = 1 << 9, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PCSCF_ADDRESS = 1 << 10, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PCSCF_SERVER_ADDRESS_LIST = 1 << 11, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PCSCF_DOMAIN_NAME_LIST = 1 << 12, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_MTU = 1 << 13, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DOMAIN_NAME_LIST = 1 << 14, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_FAMILY = 1 << 15, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IMCN_FLAG = 1 << 16, + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_EXTENDED_TECHNOLOGY = 1 << 17, +} QmiWdsGetCurrentSettingsRequestedSettings; + +/** + * QmiWdsPdpType: + * @QMI_WDS_PDP_TYPE_IPV4: IPv4 + * @QMI_WDS_PDP_TYPE_PPP: PPP + * @QMI_WDS_PDP_TYPE_IPV6: IPv6 + * @QMI_WDS_PDP_TYPE_IPV4_OR_IPV6: IPv4 and IPv6 combined context + * + * PDP context type. + */ +typedef enum { /*< underscore_name=qmi_wds_pdp_type >*/ + QMI_WDS_PDP_TYPE_IPV4 = 0, + QMI_WDS_PDP_TYPE_PPP = 1, + QMI_WDS_PDP_TYPE_IPV6 = 2, + QMI_WDS_PDP_TYPE_IPV4_OR_IPV6 = 3 +} QmiWdsPdpType; + +/** + * QmiWdsTrafficClass: + * @QMI_WDS_TRAFFIC_CLASS_SUBSCRIBED: default (?) class, best-effort + * @QMI_WDS_TRAFFIC_CLASS_CONVERSATIONAL: two-way video/voice, most delay sensitive + * @QMI_WDS_TRAFFIC_CLASS_STREAMING: one-way video/audio, delay sensitive + * @QMI_WDS_TRAFFIC_CLASS_INTERACTIVE: delay-insensitive (browsing, SSH) + * @QMI_WDS_TRAFFIC_CLASS_BACKGROUND: delay-insensitive (downloads, email) + * + * QoS Traffic Classes. + */ +typedef enum { /*< underscore_name=qmi_wds_traffic_class >*/ + QMI_WDS_TRAFFIC_CLASS_SUBSCRIBED = 0, + QMI_WDS_TRAFFIC_CLASS_CONVERSATIONAL = 1, + QMI_WDS_TRAFFIC_CLASS_STREAMING = 2, + QMI_WDS_TRAFFIC_CLASS_INTERACTIVE = 3, + QMI_WDS_TRAFFIC_CLASS_BACKGROUND = 4 +} QmiWdsTrafficClass; + +/** + * QmiWdsAuthentication: + * @QMI_WDS_AUTHENTICATION_NONE: no authentication + * @QMI_WDS_AUTHENTICATION_PAP: PAP authentication + * @QMI_WDS_AUTHENTICATION_CHAP: CHAP authentication + * + * PDP context authentication protocols. + */ +typedef enum { /*< underscore_name=qmi_wds_authentication >*/ + QMI_WDS_AUTHENTICATION_NONE = 0, + QMI_WDS_AUTHENTICATION_PAP = 1 << 0, + QMI_WDS_AUTHENTICATION_CHAP = 1 << 1 +} QmiWdsAuthentication; + +/** + * QmiWdsProfileType: + * @QMI_WDS_PROFILE_TYPE_3GPP: 3GPP profile type. + * @QMI_WDS_PROFILE_TYPE_3GPP2: 3GPP2 profile type. + * + * Profile network type family. + */ +typedef enum { + QMI_WDS_PROFILE_TYPE_3GPP = 0, + QMI_WDS_PROFILE_TYPE_3GPP2 = 1 +} QmiWdsProfileType; + +/*****************************************************************************/ +/* Helper enums for the 'QMI WDS Get Packet Statistics' message */ + +/** + * QmiWdsPacketStatisticsMaskFlag: + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_PACKETS_OK: Request count of correctly sent packets. + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_PACKETS_OK: Request count of correctly received packets. + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_PACKETS_ERROR: Request count of sent packets with error. + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_PACKETS_ERROR: Request count of received packets with error. + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_OVERFLOWS: Request count of transmitter overflows. + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_OVERFLOWS: Request count of receiver overflows. + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_BYTES_OK: Request count of correctly sent bytes. + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_BYTES_OK: Request count of correctly received bytes. + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_PACKETS_DROPPED: Request count of dropped packets in transmission. + * @QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_PACKETS_DROPPED: Request count of dropped packets in reception. + * + * Mask to use when requesting packet statistics. + */ +typedef enum { + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_PACKETS_OK = 1 << 0, + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_PACKETS_OK = 1 << 1, + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_PACKETS_ERROR = 1 << 2, + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_PACKETS_ERROR = 1 << 3, + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_OVERFLOWS = 1 << 4, + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_OVERFLOWS = 1 << 5, + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_BYTES_OK = 1 << 6, + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_BYTES_OK = 1 << 7, + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_TX_PACKETS_DROPPED = 1 << 8, + QMI_WDS_PACKET_STATISTICS_MASK_FLAG_RX_PACKETS_DROPPED = 1 << 9 +} QmiWdsPacketStatisticsMaskFlag; + +/*****************************************************************************/ +/* Helper enums for the 'QMI WDS Get Profile List' message */ + +/** + * QmiWdsDsProfileError: + * @QMI_WDS_DS_PROFILE_ERROR_UNKNOWN: Unknown DS profile error. + * @QMI_WDS_DS_PROFILE_ERROR_FAIL: General failure. + * @QMI_WDS_DS_PROFILE_ERROR_INVALID_HANDLE: Invalid handle. + * @QMI_WDS_DS_PROFILE_ERROR_INVALID_OPERATION: Invalid operation. + * @QMI_WDS_DS_PROFILE_ERROR_INVALID_PROFILE_TYPE: Invalid profile type. + * @QMI_WDS_DS_PROFILE_ERROR_INVALID_PROFILE_NUMBER: Invalid profile number. + * @QMI_WDS_DS_PROFILE_ERROR_INVALID_PROFILE_ID: Invalid profile identifier. + * @QMI_WDS_DS_PROFILE_ERROR_INVALID_ARGUMENT: Invalid argument. + * @QMI_WDS_DS_PROFILE_ERROR_REGISTRY_NOT_INITIALIZED: Registry not initialized. + * @QMI_WDS_DS_PROFILE_ERROR_INVALID_PARAMETER_LENGTH: Invalid parameter length. + * @QMI_WDS_DS_PROFILE_ERROR_LIST_END: List end, profile not found. + * @QMI_WDS_DS_PROFILE_ERROR_INVALID_SUBSCRIPTION_ID: Invalid subscription identifier. + * @QMI_WDS_DS_PROFILE_ERROR_INVALID_PROFILE_FAMILY: Invalid profile family. + * @QMI_WDS_DS_PROFILE_ERROR_3GPP_INVALID_PROFILE_FAMILY: Invalid 3GPP profile family. + * @QMI_WDS_DS_PROFILE_ERROR_3GPP_ACCESS_ERROR: Error accessing 3GPP profiles. + * @QMI_WDS_DS_PROFILE_ERROR_3GPP_CONTEXT_NOT_DEFINED: 3GPP profile doesn't have a valid context. + * @QMI_WDS_DS_PROFILE_ERROR_3GPP_VALID_FLAG_NOT_SET: 3GPP profile doesn't have valid flag set. + * @QMI_WDS_DS_PROFILE_ERROR_3GPP_READ_ONLY_FLAG_SET: 3GPP profile has read-only flag set. + * @QMI_WDS_DS_PROFILE_ERROR_3GPP_OUT_OF_PROFILES: Out of 3GPP profiles. + * @QMI_WDS_DS_PROFILE_ERROR_3GPP2_INVALID_PROFILE_ID: Invalid 3GPP2 profile identifier. + * + * Extended DS profile errors. + */ +typedef enum { + QMI_WDS_DS_PROFILE_ERROR_UNKNOWN = 0, + QMI_WDS_DS_PROFILE_ERROR_FAIL = 1, + QMI_WDS_DS_PROFILE_ERROR_INVALID_HANDLE = 2, + QMI_WDS_DS_PROFILE_ERROR_INVALID_OPERATION = 3, + QMI_WDS_DS_PROFILE_ERROR_INVALID_PROFILE_TYPE = 4, + QMI_WDS_DS_PROFILE_ERROR_INVALID_PROFILE_NUMBER = 5, + QMI_WDS_DS_PROFILE_ERROR_INVALID_PROFILE_ID = 6, + QMI_WDS_DS_PROFILE_ERROR_INVALID_ARGUMENT = 7, + QMI_WDS_DS_PROFILE_ERROR_REGISTRY_NOT_INITIALIZED = 8, + QMI_WDS_DS_PROFILE_ERROR_INVALID_PARAMETER_LENGTH = 9, + QMI_WDS_DS_PROFILE_ERROR_LIST_END = 10, + QMI_WDS_DS_PROFILE_ERROR_INVALID_SUBSCRIPTION_ID = 11, + QMI_WDS_DS_PROFILE_ERROR_INVALID_PROFILE_FAMILY = 12, + QMI_WDS_DS_PROFILE_ERROR_3GPP_INVALID_PROFILE_FAMILY = 1001, + QMI_WDS_DS_PROFILE_ERROR_3GPP_ACCESS_ERROR = 1002, + QMI_WDS_DS_PROFILE_ERROR_3GPP_CONTEXT_NOT_DEFINED = 1003, + QMI_WDS_DS_PROFILE_ERROR_3GPP_VALID_FLAG_NOT_SET = 1004, + QMI_WDS_DS_PROFILE_ERROR_3GPP_READ_ONLY_FLAG_SET = 1005, + QMI_WDS_DS_PROFILE_ERROR_3GPP_OUT_OF_PROFILES = 1006, + QMI_WDS_DS_PROFILE_ERROR_3GPP2_INVALID_PROFILE_ID = 1101, +} QmiWdsDsProfileError; + +/** + * QmiWdsAutoconnectSetting: + * @QMI_WDS_AUTOCONNECT_DISABLED: Disabled + * @QMI_WDS_AUTOCONNECT_ENABLED: Enabled + * @QMI_WDS_AUTOCONNECT_PAUSED: Paused (resume on power cycle) + */ +typedef enum { + QMI_WDS_AUTOCONNECT_DISABLED = 0, + QMI_WDS_AUTOCONNECT_ENABLED = 1, + QMI_WDS_AUTOCONNECT_PAUSED = 2, +} QmiWdsAutoconnectSetting; + +#endif /* _LIBQMI_GLIB_QMI_ENUMS_WDS_H_ */ diff --git a/release/src/router/uqmi/qmi-enums-wms.h b/release/src/router/uqmi/qmi-enums-wms.h new file mode 100644 index 0000000000..5b54ac95fd --- /dev/null +++ b/release/src/router/uqmi/qmi-enums-wms.h @@ -0,0 +1,425 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * uqmi -- tiny QMI support implementation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012 Google Inc. + */ + +#ifndef _LIBQMI_GLIB_QMI_ENUMS_WMS_H_ +#define _LIBQMI_GLIB_QMI_ENUMS_WMS_H_ + +/** + * SECTION: qmi-enums-wms + * @title: WMS enumerations and flags + * + * This section defines enumerations and flags used in the WMS service + * interface. + */ + +/*****************************************************************************/ +/* Helper enums for the 'QMI WMS Event Report' indication */ + +/** + * QmiWmsStorageType: + * @QMI_WMS_STORAGE_TYPE_UIM: Message stored in UIM. + * @QMI_WMS_STORAGE_TYPE_NV: Message stored in non-volatile memory. + * @QMI_WMS_STORAGE_TYPE_NONE: None. + * + * Type of messaging storage + */ +typedef enum { + QMI_WMS_STORAGE_TYPE_UIM = 0x00, + QMI_WMS_STORAGE_TYPE_NV = 0x01, + QMI_WMS_STORAGE_TYPE_NONE = 0xFF +} QmiWmsStorageType; + +/** + * QmiWmsAckIndicator: + * @QMI_WMS_ACK_INDICATOR_SEND: ACK needs to be sent. + * @QMI_WMS_ACK_INDICATOR_DO_NOT_SEND: ACK doesn't need to be sent. + * + * Indication of whether ACK needs to be sent or not. + */ +typedef enum { + QMI_WMS_ACK_INDICATOR_SEND = 0x00, + QMI_WMS_ACK_INDICATOR_DO_NOT_SEND = 0x01 +} QmiWmsAckIndicator; + +/** + * QmiWmsMessageFormat: + * @QMI_WMS_MESSAGE_FORMAT_CDMA: CDMA message. + * @QMI_WMS_MESSAGE_FORMAT_GSM_WCDMA_POINT_TO_POINT: Point-to-point 3GPP message. + * @QMI_WMS_MESSAGE_FORMAT_GSM_WCDMA_BROADCAST: Broadcast 3GPP message. + * @QMI_WMS_MESSAGE_FORMAT_MWI: Message Waiting Indicator. + * + * Type of message. + */ +typedef enum { + QMI_WMS_MESSAGE_FORMAT_CDMA = 0x00, + QMI_WMS_MESSAGE_FORMAT_GSM_WCDMA_POINT_TO_POINT = 0x06, + QMI_WMS_MESSAGE_FORMAT_GSM_WCDMA_BROADCAST = 0x07, + QMI_WMS_MESSAGE_FORMAT_MWI = 0x08 +} QmiWmsMessageFormat; + +/** + * QmiWmsMessageMode: + * @QMI_WMS_MESSAGE_MODE_CDMA: Message sent using 3GPP2 technologies. + * @QMI_WMS_MESSAGE_MODE_GSM_WCDMA: Message sent using 3GPP technologies. + * + * Message mode. + */ +typedef enum { + QMI_WMS_MESSAGE_MODE_CDMA = 0x00, + QMI_WMS_MESSAGE_MODE_GSM_WCDMA = 0x01 +} QmiWmsMessageMode; + +/** + * QmiWmsNotificationType: + * @QMI_WMS_NOTIFICATION_TYPE_PRIMARY: Primary. + * @QMI_WMS_NOTIFICATION_TYPE_SECONDARY_GSM: Secondary GSM. + * @QMI_WMS_NOTIFICATION_TYPE_SECONDARY_UMTS: Secondary UMTS. + * + * Type of notification. + */ +typedef enum { + QMI_WMS_NOTIFICATION_TYPE_PRIMARY = 0x00, + QMI_WMS_NOTIFICATION_TYPE_SECONDARY_GSM = 0x01, + QMI_WMS_NOTIFICATION_TYPE_SECONDARY_UMTS = 0x02 +} QmiWmsNotificationType; + +/*****************************************************************************/ +/* Helper enums for the 'QMI WMS Raw Send' request/response */ + +/** + * QmiWmsCdmaServiceOption: + * @QMI_WMS_CDMA_SERVICE_OPTION_AUTO: Automatic selection of service option. + * @QMI_WMS_CDMA_SERVICE_OPTION_6: Use service option 6. + * @QMI_WMS_CDMA_SERVICE_OPTION_14: Use service option 14. + * + * CDMA service option selection. + */ +typedef enum { + QMI_WMS_CDMA_SERVICE_OPTION_AUTO = 0x00, + QMI_WMS_CDMA_SERVICE_OPTION_6 = 0x06, + QMI_WMS_CDMA_SERVICE_OPTION_14 = 0x0E +} QmiWmsCdmaServiceOption; + +/** + * QmiWmsCdmaCauseCode: + * @QMI_WDS_CDMA_CAUSE_CODE_NETWORK_ADDRESS_VACANT: Address is valid but not yet allocated. + * @QMI_WDS_CDMA_CAUSE_CODE_NETWORK_ADDRESS_TRANSLATION_FAILURE: Address is invalid. + * @QMI_WDS_CDMA_CAUSE_CODE_NETWORK_RESOURCE_SHORTAGE: Network resource shortage. + * @QMI_WDS_CDMA_CAUSE_CODE_NETWORK_FAILURE: Network failed. + * @QMI_WDS_CDMA_CAUSE_CODE_NETWORK_INVALID_TELESERVICE_ID: SMS teleservice ID is invalid. + * @QMI_WDS_CDMA_CAUSE_CODE_NETWORK_OTHER: Other network error. + * @QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_NO_PAGE_RESPONSE: No page response from destination. + * @QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_BUSY: Destination is busy. + * @QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_NO_ACK: No acknowledge from destination. + * @QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_RESOURCE_SHORTAGE: Destination resource shortage. + * @QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_SMS_DELIVERY_POSTPONED: SMS deliver postponed. + * @QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_OUT_OF_SERVICE: Destination out of service. + * @QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_NOT_AT_ADDRESS: Destination not at address. + * @QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_OTHER: Other destination error. + * @QMI_WDS_CDMA_CAUSE_CODE_RADIO_INTERFACE_RESOURCE_SHORTAGE: Radio interface resource shortage. + * @QMI_WDS_CDMA_CAUSE_CODE_RADIO_INTERFACE_INCOMPATIBILITY: Radio interface incompatibility. + * @QMI_WDS_CDMA_CAUSE_CODE_RADIO_INTERFACE_OTHER: Other radio interface error. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_ENCODING: Encoding error. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_SMS_ORIGIN_DENIED: SMS origin denied. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_SMS_DESTINATION_DENIED: SMS destination denied. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_SUPPLEMENTARY_SERVICE_NOT_SUPPORTED: Supplementary service not supported. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_SMS_NOT_SUPPORTED: SMS not supported. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_MISSING_EXPECTED_PARAMETER: Missing optional expected parameter. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_MISSING_MANDATORY_PARAMETER: Missing mandatory parameter. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_UNRECOGNIZED_PARAMETER_VALUE: Unrecognized parameter value. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_UNEXPECTED_PARAMETER_VALUE: Unexpected parameter value. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_USER_DATA_SIZE_ERROR: user data size error. + * @QMI_WDS_CDMA_CAUSE_CODE_GENERAL_OTHER: Other general error. + * + * Cause codes when failed to send an SMS in CDMA. + */ +typedef enum { + /* Network errors */ + QMI_WDS_CDMA_CAUSE_CODE_NETWORK_ADDRESS_VACANT = 0x00, + QMI_WDS_CDMA_CAUSE_CODE_NETWORK_ADDRESS_TRANSLATION_FAILURE = 0x01, + QMI_WDS_CDMA_CAUSE_CODE_NETWORK_RESOURCE_SHORTAGE = 0x02, + QMI_WDS_CDMA_CAUSE_CODE_NETWORK_FAILURE = 0x03, + QMI_WDS_CDMA_CAUSE_CODE_NETWORK_INVALID_TELESERVICE_ID = 0x04, + QMI_WDS_CDMA_CAUSE_CODE_NETWORK_OTHER = 0x05, + + /* Destination errors */ + QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_NO_PAGE_RESPONSE = 0x20, + QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_BUSY = 0x21, + QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_NO_ACK = 0x22, + QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_RESOURCE_SHORTAGE = 0x23, + QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_SMS_DELIVERY_POSTPONED = 0x24, + QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_OUT_OF_SERVICE = 0x25, + QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_NOT_AT_ADDRESS = 0x26, + QMI_WDS_CDMA_CAUSE_CODE_DESTINATION_OTHER = 0x27, + + /* Radio Interface errors */ + QMI_WDS_CDMA_CAUSE_CODE_RADIO_INTERFACE_RESOURCE_SHORTAGE = 0x40, + QMI_WDS_CDMA_CAUSE_CODE_RADIO_INTERFACE_INCOMPATIBILITY = 0x41, + QMI_WDS_CDMA_CAUSE_CODE_RADIO_INTERFACE_OTHER = 0x42, + + /* General errors */ + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_ENCODING = 0x60, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_SMS_ORIGIN_DENIED = 0x61, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_SMS_DESTINATION_DENIED = 0x62, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_SUPPLEMENTARY_SERVICE_NOT_SUPPORTED = 0x63, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_SMS_NOT_SUPPORTED = 0x64, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_MISSING_EXPECTED_PARAMETER = 0x65, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_MISSING_MANDATORY_PARAMETER = 0x66, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_UNRECOGNIZED_PARAMETER_VALUE = 0x67, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_UNEXPECTED_PARAMETER_VALUE = 0x68, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_USER_DATA_SIZE_ERROR = 0x69, + QMI_WDS_CDMA_CAUSE_CODE_GENERAL_OTHER = 0x6A +} QmiWmsCdmaCauseCode; + +/** + * QmiWmsCdmaErrorClass: + * @QMI_WMS_CDMA_ERROR_CLASS_TEMPORARY: Temporary error. + * @QMI_WMS_CDMA_ERROR_CLASS_PERMANENT: Permanent error. + * + * Error class when failed to send an SMS in CDMA. + */ +typedef enum { + QMI_WMS_CDMA_ERROR_CLASS_TEMPORARY = 0x00, + QMI_WMS_CDMA_ERROR_CLASS_PERMANENT = 0x01 +} QmiWmsCdmaErrorClass; + +/** + * QmiWmsGsmUmtsRpCause: + * @QMI_WMS_GSM_UMTS_RP_CAUSE_UNASSIGNED_NUMBER: Unassigned number. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_OPERATOR_DETERMINED_BARRING: Operator determined barring. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_CALL_BARRED: Call barred. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_RESERVED: Reserved. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_SMS_TRANSFER_REJECTED: SMS transfer rejected. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_MEMORY_CAPACITY_EXCEEDED: Memory capacity exceeded. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_DESTINATION_OUT_OF_ORDER: Destination out of order. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_UNIDENTIFIED_SUBSCRIBER: Unidentified subscriber. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_FACILITY_REJECTED: Facility rejected. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_UNKNOWN_SUBSCRIBER: Unknown subscriber. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_NETWORK_OUF_OF_ORDER: Network out of order. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_TEMPORARY_FAILURE: Temporary failure. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_CONGESTION: Congestion. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_RESOURCES_UNAVAILABLE: Resources unavailable. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_FACILITY_NOT_SUBSCRIBED: Facility not subscribed. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_FACILITY_NOT_IMPLEMENTED: Facility not implemented. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_INVALID_SMS_TRANSFER_REFERENCE_VALUE: Invalid SMS transfer reference value. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE: Semantically incorrect message. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_INVALID_MANDATORY_INFO: Invalid mandatory info. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_MESSAGE_TYPE_NOT_IMPLEMENTED: Message type not implemented. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_MESSAGE_NOT_COMPATIBLE_WITH_SMS: Message not compatible with SMS. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_INFORMATION_ELEMENT_NOT_IMPLEMENTED: Information element not implemented. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_PROTOCOL_ERROR: Protocol error. + * @QMI_WMS_GSM_UMTS_RP_CAUSE_INTERWORKING: Interworking error. + * + * RP cause codes when failed to send an SMS in GSM/WCDMA. + */ +typedef enum { + QMI_WMS_GSM_UMTS_RP_CAUSE_UNASSIGNED_NUMBER = 0x01, + QMI_WMS_GSM_UMTS_RP_CAUSE_OPERATOR_DETERMINED_BARRING = 0x08, + QMI_WMS_GSM_UMTS_RP_CAUSE_CALL_BARRED = 0x0A, + QMI_WMS_GSM_UMTS_RP_CAUSE_RESERVED = 0x0B, + QMI_WMS_GSM_UMTS_RP_CAUSE_SMS_TRANSFER_REJECTED = 0x15, + QMI_WMS_GSM_UMTS_RP_CAUSE_MEMORY_CAPACITY_EXCEEDED = 0x16, + QMI_WMS_GSM_UMTS_RP_CAUSE_DESTINATION_OUT_OF_ORDER = 0x1B, + QMI_WMS_GSM_UMTS_RP_CAUSE_UNIDENTIFIED_SUBSCRIBER = 0x1C, + QMI_WMS_GSM_UMTS_RP_CAUSE_FACILITY_REJECTED = 0x1D, + QMI_WMS_GSM_UMTS_RP_CAUSE_UNKNOWN_SUBSCRIBER = 0x1E, + QMI_WMS_GSM_UMTS_RP_CAUSE_NETWORK_OUF_OF_ORDER = 0x20, + QMI_WMS_GSM_UMTS_RP_CAUSE_TEMPORARY_FAILURE = 0x21, + QMI_WMS_GSM_UMTS_RP_CAUSE_CONGESTION = 0x2A, + QMI_WMS_GSM_UMTS_RP_CAUSE_RESOURCES_UNAVAILABLE = 0x2F, + QMI_WMS_GSM_UMTS_RP_CAUSE_FACILITY_NOT_SUBSCRIBED = 0x32, + QMI_WMS_GSM_UMTS_RP_CAUSE_FACILITY_NOT_IMPLEMENTED = 0x45, + QMI_WMS_GSM_UMTS_RP_CAUSE_INVALID_SMS_TRANSFER_REFERENCE_VALUE = 0x51, + QMI_WMS_GSM_UMTS_RP_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE = 0x5F, + QMI_WMS_GSM_UMTS_RP_CAUSE_INVALID_MANDATORY_INFO = 0x60, + QMI_WMS_GSM_UMTS_RP_CAUSE_MESSAGE_TYPE_NOT_IMPLEMENTED = 0x61, + QMI_WMS_GSM_UMTS_RP_CAUSE_MESSAGE_NOT_COMPATIBLE_WITH_SMS = 0x62, + QMI_WMS_GSM_UMTS_RP_CAUSE_INFORMATION_ELEMENT_NOT_IMPLEMENTED = 0x63, + QMI_WMS_GSM_UMTS_RP_CAUSE_PROTOCOL_ERROR = 0x6F, + QMI_WMS_GSM_UMTS_RP_CAUSE_INTERWORKING = 0x7F +} QmiWmsGsmUmtsRpCause; + +/** + * QmiWmsGsmUmtsTpCause: + * @QMI_WMS_GSM_UMTS_TP_CAUSE_TELE_INTERWORKING_NOT_SUPPORTED: Tele interworking not supported. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_SHORT_MESSAGE_TYPE_0_NOT_SUPPORTED: Short message type 0 not supported. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_SHORT_MESSAGE_CANNOT_BE_REPLACED: Short message cannot be replaced. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_UNSPECIFIED_PID_ERROR: Unspecified TP-PID error. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_DCS_NOT_SUPPORTED: Data coding scheme not supported. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_MESSAGE_CLASS_NOT_SUPPORTED: Message class not supported. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_UNSPECIFIED_DCS_ERROR: Unspecified data coding scheme error. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_COMMAND_CANNOT_BE_ACTIONED: Command cannot be actioned. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_COMMAND_UNSUPPORTED: Command unsupported. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_UNSPECIFIED_COMMAND_ERROR: Unspecified command error. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_TPDU_NOT_SUPPORTED: TPDU not supported. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_SC_BUSY: SC busy. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_NO_SC_SUBSCRIPTION: No SC subscription. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_SC_SYSTEM_FAILURE: SC system failure. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_INVALID_SME_ADDRESS: Invalid SME address. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_DESTINATION_SME_BARRED: Destination SME barred. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_SM_REJECTED_OR_DUPLICATE: SM rejected or duplicate. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_VPF_NOT_SUPPORTED: TP-VPF not supported. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_VP_NOT_SUPPORTED: TP-VP not supported. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_SIM_SMS_STORAGE_FULL: SIM SMS storage full. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_NO_SMS_STORAGE_CAPABILITY_IN_SIM: No SMS storage capability in SIM. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_MS_ERROR: MS error. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_MEMORY_CAPACITY_EXCEEDED: Memory capacity exceeded. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_SIM_APPLICATION_TOOLKIT_BUSY: SIM application toolkit busy. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_SIM_DATA_DOWNLOAD_ERROR: SIM data download error. + * @QMI_WMS_GSM_UMTS_TP_CAUSE_UNSPECIFIED_ERROR: Unspecified error. + * + * RT cause codes when failed to send an SMS in GSM/WCDMA. + */ +typedef enum { + QMI_WMS_GSM_UMTS_TP_CAUSE_TELE_INTERWORKING_NOT_SUPPORTED = 0x80, + QMI_WMS_GSM_UMTS_TP_CAUSE_SHORT_MESSAGE_TYPE_0_NOT_SUPPORTED = 0x81, + QMI_WMS_GSM_UMTS_TP_CAUSE_SHORT_MESSAGE_CANNOT_BE_REPLACED = 0x82, + QMI_WMS_GSM_UMTS_TP_CAUSE_UNSPECIFIED_PID_ERROR = 0x8F, + QMI_WMS_GSM_UMTS_TP_CAUSE_DCS_NOT_SUPPORTED = 0x90, + QMI_WMS_GSM_UMTS_TP_CAUSE_MESSAGE_CLASS_NOT_SUPPORTED = 0x91, + QMI_WMS_GSM_UMTS_TP_CAUSE_UNSPECIFIED_DCS_ERROR = 0x9F, + QMI_WMS_GSM_UMTS_TP_CAUSE_COMMAND_CANNOT_BE_ACTIONED = 0xA0, + QMI_WMS_GSM_UMTS_TP_CAUSE_COMMAND_UNSUPPORTED = 0xA1, + QMI_WMS_GSM_UMTS_TP_CAUSE_UNSPECIFIED_COMMAND_ERROR = 0xAF, + QMI_WMS_GSM_UMTS_TP_CAUSE_TPDU_NOT_SUPPORTED = 0xB0, + QMI_WMS_GSM_UMTS_TP_CAUSE_SC_BUSY = 0xC0, + QMI_WMS_GSM_UMTS_TP_CAUSE_NO_SC_SUBSCRIPTION = 0xC1, + QMI_WMS_GSM_UMTS_TP_CAUSE_SC_SYSTEM_FAILURE = 0xC2, + QMI_WMS_GSM_UMTS_TP_CAUSE_INVALID_SME_ADDRESS = 0xC3, + QMI_WMS_GSM_UMTS_TP_CAUSE_DESTINATION_SME_BARRED = 0xC4, + QMI_WMS_GSM_UMTS_TP_CAUSE_SM_REJECTED_OR_DUPLICATE = 0xC5, + QMI_WMS_GSM_UMTS_TP_CAUSE_VPF_NOT_SUPPORTED = 0xC6, + QMI_WMS_GSM_UMTS_TP_CAUSE_VP_NOT_SUPPORTED = 0xC7, + QMI_WMS_GSM_UMTS_TP_CAUSE_SIM_SMS_STORAGE_FULL = 0xD0, + QMI_WMS_GSM_UMTS_TP_CAUSE_NO_SMS_STORAGE_CAPABILITY_IN_SIM = 0xD1, + QMI_WMS_GSM_UMTS_TP_CAUSE_MS_ERROR = 0xD2, + QMI_WMS_GSM_UMTS_TP_CAUSE_MEMORY_CAPACITY_EXCEEDED = 0xD3, + QMI_WMS_GSM_UMTS_TP_CAUSE_SIM_APPLICATION_TOOLKIT_BUSY = 0xD4, + QMI_WMS_GSM_UMTS_TP_CAUSE_SIM_DATA_DOWNLOAD_ERROR = 0xD5, + QMI_WMS_GSM_UMTS_TP_CAUSE_UNSPECIFIED_ERROR = 0xFF +} QmiWmsGsmUmtsTpCause; + +/** + * QmiWmsMessageDeliveryFailureType: + * @QMI_WMS_MESSAGE_DELIVERY_FAILURE_TYPE_TEMPORARY: Temporary failure. + * @QMI_WMS_MESSAGE_DELIVERY_FAILURE_TYPE_PERMANENT: Permanent failure. + * + * Type of message delivery failure. + */ +typedef enum { + QMI_WMS_MESSAGE_DELIVERY_FAILURE_TYPE_TEMPORARY = 0x00, + QMI_WMS_MESSAGE_DELIVERY_FAILURE_TYPE_PERMANENT = 0x01 +} QmiWmsMessageDeliveryFailureType; + +/*****************************************************************************/ +/* Helper enums for the 'QMI WMS Read Raw' request/response */ + +/** + * QmiWmsMessageTagType: + * @QMI_WMS_MESSAGE_TAG_TYPE_MT_READ: Received SMS, already read. + * @QMI_WMS_MESSAGE_TAG_TYPE_MT_NOT_READ: Received SMS, not read. + * @QMI_WMS_MESSAGE_TAG_TYPE_MO_SENT: Sent SMS. + * @QMI_WMS_MESSAGE_TAG_TYPE_MO_NOT_SENT: Not yet sent SMS. + * + * Type of message tag. + */ +typedef enum { + QMI_WMS_MESSAGE_TAG_TYPE_MT_READ = 0x00, + QMI_WMS_MESSAGE_TAG_TYPE_MT_NOT_READ = 0x01, + QMI_WMS_MESSAGE_TAG_TYPE_MO_SENT = 0x02, + QMI_WMS_MESSAGE_TAG_TYPE_MO_NOT_SENT = 0x03 +} QmiWmsMessageTagType; + +/** + * QmiWmsMessageProtocol: + * @QMI_WMS_MESSAGE_PROTOCOL_CDMA: CDMA. + * @QMI_WMS_MESSAGE_PROTOCOL_WCDMA: WCDMA. + * + * Type of message protocol. + */ +typedef enum { + QMI_WMS_MESSAGE_PROTOCOL_CDMA = 0x00, + QMI_WMS_MESSAGE_PROTOCOL_WCDMA = 0x01 +} QmiWmsMessageProtocol; + +/*****************************************************************************/ +/* Helper enums for the 'QMI WMS Set Routes' request/response */ + +/** + * QmiWmsMessageType: + * @QMI_WMS_MESSAGE_TYPE_POINT_TO_POINT: Point to point message. + * + * Type of message. + */ +typedef enum { + QMI_WMS_MESSAGE_TYPE_POINT_TO_POINT = 0x00 +} QmiWmsMessageType; + +/** + * QmiWmsMessageClass: + * @QMI_WMS_MESSAGE_CLASS_0: Class 0. + * @QMI_WMS_MESSAGE_CLASS_1: Class 1. + * @QMI_WMS_MESSAGE_CLASS_2: Class 2. + * @QMI_WMS_MESSAGE_CLASS_3: Class 3. + * @QMI_WMS_MESSAGE_CLASS_NONE: Class none. + * @QMI_WMS_MESSAGE_CLASS_CDMA: Class CDMA. + * + * Message class. + */ +typedef enum { + QMI_WMS_MESSAGE_CLASS_0 = 0x00, + QMI_WMS_MESSAGE_CLASS_1 = 0x01, + QMI_WMS_MESSAGE_CLASS_2 = 0x02, + QMI_WMS_MESSAGE_CLASS_3 = 0x03, + QMI_WMS_MESSAGE_CLASS_NONE = 0x04, + QMI_WMS_MESSAGE_CLASS_CDMA = 0x05 +} QmiWmsMessageClass; + +/** + * QmiWmsReceiptAction: + * @QMI_WMS_RECEIPT_ACTION_DISCARD: Discard message. + * @QMI_WMS_RECEIPT_ACTION_STORE_AND_NOTIFY: Store and notify to client. + * @QMI_WMS_RECEIPT_ACTION_TRANSFER_ONLY: Notify to client, which should send back ACK. + * @QMI_WMS_RECEIPT_ACTION_TRANSFER_AND_ACK: Notify to client and send back ACK. + * @QMI_WMS_RECEIPT_ACTION_UNKNOWN: Unknown action. + * + * Action to perform when a message is received. + */ +typedef enum { + QMI_WMS_RECEIPT_ACTION_DISCARD = 0x00, + QMI_WMS_RECEIPT_ACTION_STORE_AND_NOTIFY = 0x01, + QMI_WMS_RECEIPT_ACTION_TRANSFER_ONLY = 0x02, + QMI_WMS_RECEIPT_ACTION_TRANSFER_AND_ACK = 0x03, + QMI_WMS_RECEIPT_ACTION_UNKNOWN = 0xFF +} QmiWmsReceiptAction; + +/** + * QmiWmsTransferIndication: + * @QMI_WMS_TRANSFER_INDICATION_CLIENT: Status reports transferred to the client. + * + * Transfer indication actions. + */ +typedef enum { + QMI_WMS_TRANSFER_INDICATION_CLIENT = 0x01 +} QmiWmsTransferIndication; + +#endif /* _LIBQMI_GLIB_QMI_ENUMS_WMS_H_ */ diff --git a/release/src/router/uqmi/qmi-enums.h b/release/src/router/uqmi/qmi-enums.h new file mode 100644 index 0000000000..3cd8de3a00 --- /dev/null +++ b/release/src/router/uqmi/qmi-enums.h @@ -0,0 +1,135 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * uqmi -- tiny QMI support implementation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012 Google, Inc. + */ + +#ifndef _LIBQMI_GLIB_QMI_ENUMS_H_ +#define _LIBQMI_GLIB_QMI_ENUMS_H_ + +/** + * SECTION: qmi-enums + * @title: Common enumerations and flags + * + * This section defines common enumerations and flags used in the interface. + */ + +/** + * QmiService: + * @QMI_SERVICE_UNKNOWN: Unknown service. + * @QMI_SERVICE_CTL: Control service. + * @QMI_SERVICE_WDS: Wireless Data Service. + * @QMI_SERVICE_DMS: Device Management Service. + * @QMI_SERVICE_NAS: Network Access Service. + * @QMI_SERVICE_QOS: Quality Of Service service. + * @QMI_SERVICE_WMS: Wireless Messaging Service. + * @QMI_SERVICE_PDS: Position Determination Service. + * @QMI_SERVICE_AUTH: Authentication service. + * @QMI_SERVICE_AT: AT service. + * @QMI_SERVICE_VOICE: Voice service. + * @QMI_SERVICE_CAT2: Card Application Toolkit service (v2). + * @QMI_SERVICE_UIM: User Identity Module service. + * @QMI_SERVICE_PBM: Phonebook Management service. + * @QMI_SERVICE_QCHAT: QCHAT service. + * @QMI_SERVICE_RMTFS: Remote file system service. + * @QMI_SERVICE_TEST: Test service. + * @QMI_SERVICE_LOC: Location service (~ PDS v2). + * @QMI_SERVICE_SAR: Service access proxy service. + * @QMI_SERVICE_IMS: IMS settings service. + * @QMI_SERVICE_ADC: Analog to digital converter driver service. + * @QMI_SERVICE_CSD: Core sound driver service. + * @QMI_SERVICE_MFS: Modem embedded file system service. + * @QMI_SERVICE_TIME: Time service. + * @QMI_SERVICE_TS: Thermal sensors service. + * @QMI_SERVICE_TMD: Thermal mitigation device service. + * @QMI_SERVICE_SAP: Service access proxy service. + * @QMI_SERVICE_WDA: Wireless data administrative service. + * @QMI_SERVICE_TSYNC: TSYNC control service. + * @QMI_SERVICE_RFSA: Remote file system access service. + * @QMI_SERVICE_CSVT: Circuit switched videotelephony service. + * @QMI_SERVICE_QCMAP: Qualcomm mobile access point service. + * @QMI_SERVICE_IMSP: IMS presence service. + * @QMI_SERVICE_IMSVT: IMS videotelephony service. + * @QMI_SERVICE_IMSA: IMS application service. + * @QMI_SERVICE_COEX: Coexistence service. + * @QMI_SERVICE_PDC: Persistent device configuration service. + * @QMI_SERVICE_STX: Simultaneous transmit service. + * @QMI_SERVICE_BIT: Bearer independent transport service. + * @QMI_SERVICE_IMSRTP: IMS RTP service. + * @QMI_SERVICE_RFRPE: RF radiated performance enhancement service. + * @QMI_SERVICE_DSD: Data system determination service. + * @QMI_SERVICE_SSCTL: Subsystem control service. + * @QMI_SERVICE_CAT: Card Application Toolkit service (v1). + * @QMI_SERVICE_RMS: Remote Management Service. + * @QMI_SERVICE_OMA: Open Mobile Alliance device management service. + * + * QMI services. + */ +typedef enum { + QMI_SERVICE_UNKNOWN = -1, + QMI_SERVICE_CTL = 0, + QMI_SERVICE_WDS = 1, + QMI_SERVICE_DMS = 2, + QMI_SERVICE_NAS = 3, + QMI_SERVICE_QOS = 4, + QMI_SERVICE_WMS = 5, + QMI_SERVICE_PDS = 6, + QMI_SERVICE_AUTH = 7, + QMI_SERVICE_AT = 8, + QMI_SERVICE_VOICE = 9, + QMI_SERVICE_CAT2 = 10, + QMI_SERVICE_UIM = 11, + QMI_SERVICE_PBM = 12, + QMI_SERVICE_QCHAT = 13, + QMI_SERVICE_RMTFS = 14, + QMI_SERVICE_TEST = 15, + QMI_SERVICE_LOC = 16, + QMI_SERVICE_SAR = 17, + QMI_SERVICE_IMS = 18, + QMI_SERVICE_ADC = 19, + QMI_SERVICE_CSD = 20, + QMI_SERVICE_MFS = 21, + QMI_SERVICE_TIME = 22, + QMI_SERVICE_TS = 23, + QMI_SERVICE_TMD = 24, + QMI_SERVICE_SAP = 25, + QMI_SERVICE_WDA = 26, + QMI_SERVICE_TSYNC = 27, + QMI_SERVICE_RFSA = 28, + QMI_SERVICE_CSVT = 29, + QMI_SERVICE_QCMAP = 30, + QMI_SERVICE_IMSP = 31, + QMI_SERVICE_IMSVT = 32, + QMI_SERVICE_IMSA = 33, + QMI_SERVICE_COEX = 34, + /* 35, reserved */ + QMI_SERVICE_PDC = 36, + /* 37, reserved */ + QMI_SERVICE_STX = 38, + QMI_SERVICE_BIT = 39, + QMI_SERVICE_IMSRTP = 40, + QMI_SERVICE_RFRPE = 41, + QMI_SERVICE_DSD = 42, + QMI_SERVICE_SSCTL = 43, + QMI_SERVICE_CAT = 224, + QMI_SERVICE_RMS = 225, + QMI_SERVICE_OMA = 226 +} QmiService; + +#endif /* _LIBQMI_GLIB_QMI_ENUMS_H_ */ diff --git a/release/src/router/uqmi/qmi-errors.h b/release/src/router/uqmi/qmi-errors.h new file mode 100644 index 0000000000..c3c520bfc2 --- /dev/null +++ b/release/src/router/uqmi/qmi-errors.h @@ -0,0 +1,270 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * libqmi-glib -- GLib/GIO based library to control QMI devices + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012 Aleksander Morgado + */ + +#ifndef _LIBQMI_GLIB_QMI_ERRORS_H_ +#define _LIBQMI_GLIB_QMI_ERRORS_H_ + +/** + * SECTION: qmi-errors + * @title: Errors + * + * This section defines common error types used in the interface. + */ + +/** + * QmiCoreError: + * @QMI_CORE_ERROR_FAILED: Operation failed. + * @QMI_CORE_ERROR_WRONG_STATE: Operation cannot be executed in the current state. + * @QMI_CORE_ERROR_TIMEOUT: Operation timed out. + * @QMI_CORE_ERROR_INVALID_ARGS: Invalid arguments given. + * @QMI_CORE_ERROR_INVALID_MESSAGE: QMI message is invalid. + * @QMI_CORE_ERROR_TLV_NOT_FOUND: TLV not found. + * @QMI_CORE_ERROR_TLV_TOO_LONG: TLV is too long. + * @QMI_CORE_ERROR_UNSUPPORTED: Not supported. + * + * Common errors that may be reported by libqmi-glib. + */ +typedef enum { /*< underscore_name=qmi_core_error >*/ + QMI_CORE_ERROR_FAILED = 0, /*< nick=Failed >*/ + QMI_CORE_ERROR_WRONG_STATE = 1, /*< nick=WrongState >*/ + QMI_CORE_ERROR_TIMEOUT = 2, /*< nick=Timeout >*/ + QMI_CORE_ERROR_INVALID_ARGS = 3, /*< nick=InvalidArgs >*/ + QMI_CORE_ERROR_INVALID_MESSAGE = 4, /*< nick=InvalidMessage >*/ + QMI_CORE_ERROR_TLV_NOT_FOUND = 5, /*< nick=TlvNotFound >*/ + QMI_CORE_ERROR_TLV_TOO_LONG = 6, /*< nick=TlvTooLong >*/ + QMI_CORE_ERROR_UNSUPPORTED = 7 /*< nick=Unsupported >*/ +} QmiCoreError; + +/** + * QmiProtocolError: + * @QMI_PROTOCOL_ERROR_NONE: No error. + * @QMI_PROTOCOL_ERROR_MALFORMED_MESSAGE: Malformed message. + * @QMI_PROTOCOL_ERROR_NO_MEMORY: No memory. + * @QMI_PROTOCOL_ERROR_INTERNAL: Internal. + * @QMI_PROTOCOL_ERROR_ABORTED: Aborted. + * @QMI_PROTOCOL_ERROR_CLIENT_IDS_EXHAUSTED: Client IDs exhausted. + * @QMI_PROTOCOL_ERROR_UNABORTABLE_TRANSACTION: Unabortable transaction. + * @QMI_PROTOCOL_ERROR_INVALID_CLIENT_ID: Invalid client ID. + * @QMI_PROTOCOL_ERROR_NO_THRESHOLDS_PROVIDED: No thresholds provided. + * @QMI_PROTOCOL_ERROR_INVALID_HANDLE: Invalid handle. + * @QMI_PROTOCOL_ERROR_INVALID_PROFILE: Invalid profile. + * @QMI_PROTOCOL_ERROR_INVALID_PIN_ID: Invalid PIN ID. + * @QMI_PROTOCOL_ERROR_INCORRECT_PIN: Incorrect PIN. + * @QMI_PROTOCOL_ERROR_NO_NETWORK_FOUND: No network found. + * @QMI_PROTOCOL_ERROR_CALL_FAILED: Call failed. + * @QMI_PROTOCOL_ERROR_OUT_OF_CALL: Out of call. + * @QMI_PROTOCOL_ERROR_NOT_PROVISIONED: Not provisioned. + * @QMI_PROTOCOL_ERROR_MISSING_ARGUMENT: Missing argument. + * @QMI_PROTOCOL_ERROR_ARGUMENT_TOO_LONG: Argument too long. + * @QMI_PROTOCOL_ERROR_INVALID_TRANSACTION_ID: Invalid transaction ID. + * @QMI_PROTOCOL_ERROR_DEVICE_IN_USE: Device in use. + * @QMI_PROTOCOL_ERROR_NETWORK_UNSUPPORTED: Network unsupported. + * @QMI_PROTOCOL_ERROR_DEVICE_UNSUPPORTED: Device unsupported. + * @QMI_PROTOCOL_ERROR_NO_EFFECT: No effect. + * @QMI_PROTOCOL_ERROR_NO_FREE_PROFILE: No free profile. + * @QMI_PROTOCOL_ERROR_INVALID_PDP_TYPE: Invalid PDP type. + * @QMI_PROTOCOL_ERROR_INVALID_TECHNOLOGY_PREFERENCE: Invalid technology preference. + * @QMI_PROTOCOL_ERROR_INVALID_PROFILE_TYPE: Invalid profile type. + * @QMI_PROTOCOL_ERROR_INVALID_SERVICE_TYPE: Invalid service type. + * @QMI_PROTOCOL_ERROR_INVALID_REGISTER_ACTION: Invalid register action. + * @QMI_PROTOCOL_ERROR_INVALID_PS_ATTACH_ACTION: Invalid PS attach action. + * @QMI_PROTOCOL_ERROR_AUTHENTICATION_FAILED: Authentication failed. + * @QMI_PROTOCOL_ERROR_PIN_BLOCKED: PIN blocked. + * @QMI_PROTOCOL_ERROR_PIN_ALWAYS_BLOCKED: PIN always blocked. + * @QMI_PROTOCOL_ERROR_UIM_UNINITIALIZED: UIM uninitialized. + * @QMI_PROTOCOL_ERROR_MAXIMUM_QOS_REQUESTS_IN_USE: Maximum QoS requests in use. + * @QMI_PROTOCOL_ERROR_INCORRECT_FLOW_FILTER: Incorrect flow filter. + * @QMI_PROTOCOL_ERROR_NETWORK_QOS_UNAWARE: Network QoS unaware. + * @QMI_PROTOCOL_ERROR_INVALID_QOS_ID: Invalid QoS ID. + * @QMI_PROTOCOL_ERROR_QOS_UNAVAILABLE: QoS unavailable. + * @QMI_PROTOCOL_ERROR_FLOW_SUSPENDED: Flow suspended. + * @QMI_PROTOCOL_ERROR_GENERAL_ERROR: General error. + * @QMI_PROTOCOL_ERROR_UNKNOWN_ERROR: Unknown error. + * @QMI_PROTOCOL_ERROR_INVALID_ARGUMENT: Invalid argument. + * @QMI_PROTOCOL_ERROR_INVALID_INDEX: Invalid index. + * @QMI_PROTOCOL_ERROR_NO_ENTRY: No entry. + * @QMI_PROTOCOL_ERROR_DEVICE_STORAGE_FULL: Device storage full. + * @QMI_PROTOCOL_ERROR_DEVICE_NOT_READY: Device not ready. + * @QMI_PROTOCOL_ERROR_NETWORK_NOT_READY: Network not ready. + * @QMI_PROTOCOL_ERROR_WMS_CAUSE_CODE: WMS cause code. + * @QMI_PROTOCOL_ERROR_WMS_MESSAGE_NOT_SENT: WMS message not sent. + * @QMI_PROTOCOL_ERROR_WMS_MESSAGE_DELIVERY_FAILURE: WMS message delivery failure. + * @QMI_PROTOCOL_ERROR_WMS_INVALID_MESSAGE_ID: WMS invalid message ID. + * @QMI_PROTOCOL_ERROR_WMS_ENCODING: WMS encoding. + * @QMI_PROTOCOL_ERROR_AUTHENTICATION_LOCK: Authentication lock. + * @QMI_PROTOCOL_ERROR_INVALID_TRANSITION: Invalid transition. + * @QMI_PROTOCOL_ERROR_SESSION_INACTIVE: Session inactive. + * @QMI_PROTOCOL_ERROR_SESSION_INVALID: Session invalid. + * @QMI_PROTOCOL_ERROR_SESSION_OWNERSHIP: Session ownership. + * @QMI_PROTOCOL_ERROR_INSUFFICIENT_RESOURCES: Insufficient resources. + * @QMI_PROTOCOL_ERROR_DISABLED: Disabled. + * @QMI_PROTOCOL_ERROR_INVALID_OPERATION: Invalid operation. + * @QMI_PROTOCOL_ERROR_INVALID_QMI_COMMAND: Invalid QMI command. + * @QMI_PROTOCOL_ERROR_WMS_T_PDU_TYPE: WMS T-PDU type. + * @QMI_PROTOCOL_ERROR_WMS_SMSC_ADDRESS: WMS SMSC address. + * @QMI_PROTOCOL_ERROR_INFORMATION_UNAVAILABLE: Information unavailable. + * @QMI_PROTOCOL_ERROR_SEGMENT_TOO_LONG: Segment too long. + * @QMI_PROTOCOL_ERROR_SEGMENT_ORDER: Segment order. + * @QMI_PROTOCOL_ERROR_BUNDLING_NOT_SUPPORTED: Bundling not supported. + * @QMI_PROTOCOL_ERROR_POLICY_MISMATCH: Policy mismatch. + * @QMI_PROTOCOL_ERROR_SIM_FILE_NOT_FOUND: SIM file not found. + * @QMI_PROTOCOL_ERROR_EXTENDED_INTERNAL: Extended internal error. + * @QMI_PROTOCOL_ERROR_ACCESS_DENIED: Access denied. + * @QMI_PROTOCOL_ERROR_HARDWARE_RESTRICTED: Hardware restricted. + * @QMI_PROTOCOL_ERROR_ACK_NOT_SENT: ACK not sent. + * @QMI_PROTOCOL_ERROR_INJECT_TIMEOUT: Inject timeout. + * @QMI_PROTOCOL_ERROR_INCOMPATIBLE_STATE: Incompatible state. + * @QMI_PROTOCOL_ERROR_FDN_RESTRICT: FDN restrict. + * @QMI_PROTOCOL_ERROR_SUPS_FAILURE_CASE: SUPS failure case. + * @QMI_PROTOCOL_ERROR_NO_RADIO: No radio. + * @QMI_PROTOCOL_ERROR_NOT_SUPPORTED: Not supported. + * @QMI_PROTOCOL_ERROR_NO_SUBSCRIPTION: No subscription. + * @QMI_PROTOCOL_ERROR_CARD_CALL_CONTROL_FAILED: Card call control failed. + * @QMI_PROTOCOL_ERROR_NETWORK_ABORTED: Network aborted. + * @QMI_PROTOCOL_ERROR_MSG_BLOCKED: Message blocked. + * @QMI_PROTOCOL_ERROR_INVALID_SESSION_TYPE: Invalid session type. + * @QMI_PROTOCOL_ERROR_INVALID_PB_TYPE: Invalid PB type. + * @QMI_PROTOCOL_ERROR_NO_SIM: No SIM. + * @QMI_PROTOCOL_ERROR_PB_NOT_READY: PB not ready. + * @QMI_PROTOCOL_ERROR_PIN_RESTRICTION: PIN restriction. + * @QMI_PROTOCOL_ERROR_PIN2_RESTRICTION: PIN2 restriction. + * @QMI_PROTOCOL_ERROR_PUK_RESTRICTION: PUK restriction. + * @QMI_PROTOCOL_ERROR_PUK2_RESTRICTION: PUK2 restriction. + * @QMI_PROTOCOL_ERROR_PB_ACCESS_RESTRICTED: PB access restricted. + * @QMI_PROTOCOL_ERROR_PB_TEXT_TOO_LONG: PB text too long. + * @QMI_PROTOCOL_ERROR_PB_NUMBER_TOO_LONG: PB number too long. + * @QMI_PROTOCOL_ERROR_PB_HIDDEN_KEY_RESTRICTION: PB hidden key restriction. + * @QMI_PROTOCOL_ERROR_CAT_EVENT_REGISTRATION_FAILED: Event registration failed. + * @QMI_PROTOCOL_ERROR_CAT_INVALID_TERMINAL_RESPONSE: Invalid terminal response. + * @QMI_PROTOCOL_ERROR_CAT_INVALID_ENVELOPE_COMMAND: Invalid envelope command. + * @QMI_PROTOCOL_ERROR_CAT_ENVELOPE_COMMAND_BUSY: Envelope command busy. + * @QMI_PROTOCOL_ERROR_CAT_ENVELOPE_COMMAND_FAILED: Envelope command failed. + * + * QMI protocol errors. + */ +typedef enum { /*< underscore_name=qmi_protocol_error >*/ + QMI_PROTOCOL_ERROR_NONE = 0, /*< nick=None >*/ + QMI_PROTOCOL_ERROR_MALFORMED_MESSAGE = 1, /*< nick=MalformedMessage >*/ + QMI_PROTOCOL_ERROR_NO_MEMORY = 2, /*< nick=NoMemory >*/ + QMI_PROTOCOL_ERROR_INTERNAL = 3, /*< nick=Internal >*/ + QMI_PROTOCOL_ERROR_ABORTED = 4, /*< nick=Aborted >*/ + QMI_PROTOCOL_ERROR_CLIENT_IDS_EXHAUSTED = 5, /*< nick=ClientIdsExhausted >*/ + QMI_PROTOCOL_ERROR_UNABORTABLE_TRANSACTION = 6, /*< nick=UnabortableTransaction >*/ + QMI_PROTOCOL_ERROR_INVALID_CLIENT_ID = 7, /*< nick=InvalidClientId >*/ + QMI_PROTOCOL_ERROR_NO_THRESHOLDS_PROVIDED = 8, /*< nick=NoThresholdsProvided >*/ + QMI_PROTOCOL_ERROR_INVALID_HANDLE = 9, /*< nick=InvalidHandle >*/ + QMI_PROTOCOL_ERROR_INVALID_PROFILE = 10, /*< nick=InvalidProfile >*/ + QMI_PROTOCOL_ERROR_INVALID_PIN_ID = 11, /*< nick=InvalidPinId >*/ + QMI_PROTOCOL_ERROR_INCORRECT_PIN = 12, /*< nick=IncorrectPin >*/ + QMI_PROTOCOL_ERROR_NO_NETWORK_FOUND = 13, /*< nick=NoNetworkFound >*/ + QMI_PROTOCOL_ERROR_CALL_FAILED = 14, /*< nick=CallFailed >*/ + QMI_PROTOCOL_ERROR_OUT_OF_CALL = 15, /*< nick=OutOfCall >*/ + QMI_PROTOCOL_ERROR_NOT_PROVISIONED = 16, /*< nick=NotProvisioned >*/ + QMI_PROTOCOL_ERROR_MISSING_ARGUMENT = 17, /*< nick=MissingArgument >*/ + QMI_PROTOCOL_ERROR_ARGUMENT_TOO_LONG = 19, /*< nick=ArgumentTooLong >*/ + QMI_PROTOCOL_ERROR_INVALID_TRANSACTION_ID = 22, /*< nick=InvalidTransactionId >*/ + QMI_PROTOCOL_ERROR_DEVICE_IN_USE = 23, /*< nick=DeviceInUse >*/ + QMI_PROTOCOL_ERROR_NETWORK_UNSUPPORTED = 24, /*< nick=NetworkUnsupported >*/ + QMI_PROTOCOL_ERROR_DEVICE_UNSUPPORTED = 25, /*< nick=DeviceUnsupported >*/ + QMI_PROTOCOL_ERROR_NO_EFFECT = 26, /*< nick=NoEffect >*/ + QMI_PROTOCOL_ERROR_NO_FREE_PROFILE = 27, /*< nick=NoFreeProfile >*/ + QMI_PROTOCOL_ERROR_INVALID_PDP_TYPE = 28, /*< nick=InvalidPdpType >*/ + QMI_PROTOCOL_ERROR_INVALID_TECHNOLOGY_PREFERENCE = 29, /*< nick=InvalidTechnologyPreference >*/ + QMI_PROTOCOL_ERROR_INVALID_PROFILE_TYPE = 30, /*< nick=InvalidProfileType >*/ + QMI_PROTOCOL_ERROR_INVALID_SERVICE_TYPE = 31, /*< nick=InvalidServiceType >*/ + QMI_PROTOCOL_ERROR_INVALID_REGISTER_ACTION = 32, /*< nick=InvalidRegisterAction >*/ + QMI_PROTOCOL_ERROR_INVALID_PS_ATTACH_ACTION = 33, /*< nick=InvalidPsAttachAction >*/ + QMI_PROTOCOL_ERROR_AUTHENTICATION_FAILED = 34, /*< nick=AuthenticationFailed >*/ + QMI_PROTOCOL_ERROR_PIN_BLOCKED = 35, /*< nick=PinBlocked >*/ + QMI_PROTOCOL_ERROR_PIN_ALWAYS_BLOCKED = 36, /*< nick=PinAlwaysBlocked >*/ + QMI_PROTOCOL_ERROR_UIM_UNINITIALIZED = 37, /*< nick=UimUninitialized >*/ + QMI_PROTOCOL_ERROR_MAXIMUM_QOS_REQUESTS_IN_USE = 38, /*< nick=MaximumQosRequestsInUse >*/ + QMI_PROTOCOL_ERROR_INCORRECT_FLOW_FILTER = 39, /*< nick=IncorrectFlowFilter >*/ + QMI_PROTOCOL_ERROR_NETWORK_QOS_UNAWARE = 40, /*< nick= NetworkQosUnaware >*/ + QMI_PROTOCOL_ERROR_INVALID_QOS_ID = 41, /*< nick=InvalidQosId >*/ + QMI_PROTOCOL_ERROR_QOS_UNAVAILABLE = 42, /*< nick=QosUnavailable >*/ + QMI_PROTOCOL_ERROR_FLOW_SUSPENDED = 43, /*< nick=FlowSuspended >*/ + QMI_PROTOCOL_ERROR_GENERAL_ERROR = 46, /*< nick=GeneralError >*/ + QMI_PROTOCOL_ERROR_UNKNOWN_ERROR = 47, /*< nick=UnknownError >*/ + QMI_PROTOCOL_ERROR_INVALID_ARGUMENT = 48, /*< nick=InvalidArgument >*/ + QMI_PROTOCOL_ERROR_INVALID_INDEX = 49, /*< nick=InvalidIndex >*/ + QMI_PROTOCOL_ERROR_NO_ENTRY = 50, /*< nick=NoEntry >*/ + QMI_PROTOCOL_ERROR_DEVICE_STORAGE_FULL = 51, /*< nick=DeviceStorageFull >*/ + QMI_PROTOCOL_ERROR_DEVICE_NOT_READY = 52, /*< nick=DeviceNotReady >*/ + QMI_PROTOCOL_ERROR_NETWORK_NOT_READY = 53, /*< nick=NetworkNotReady >*/ + QMI_PROTOCOL_ERROR_WMS_CAUSE_CODE = 54, /*< nick=Wms.CauseCode >*/ + QMI_PROTOCOL_ERROR_WMS_MESSAGE_NOT_SENT = 55, /*< nick=Wms.MessageNotSent >*/ + QMI_PROTOCOL_ERROR_WMS_MESSAGE_DELIVERY_FAILURE = 56, /*< nick=Wms.MessageDeliveryFailure >*/ + QMI_PROTOCOL_ERROR_WMS_INVALID_MESSAGE_ID = 57, /*< nick=Wms.InvalidMessageId >*/ + QMI_PROTOCOL_ERROR_WMS_ENCODING = 58, /*< nick=Wms.Encoding >*/ + QMI_PROTOCOL_ERROR_AUTHENTICATION_LOCK = 59, /*< nick=AuthenticationLock >*/ + QMI_PROTOCOL_ERROR_INVALID_TRANSITION = 60, /*< nick=InvalidTransaction >*/ + QMI_PROTOCOL_ERROR_SESSION_INACTIVE = 65, /*< nick=SessionInactive >*/ + QMI_PROTOCOL_ERROR_SESSION_INVALID = 66, /*< nick=SessionInvalid >*/ + QMI_PROTOCOL_ERROR_SESSION_OWNERSHIP = 67, /*< nick=SessionOwnership >*/ + QMI_PROTOCOL_ERROR_INSUFFICIENT_RESOURCES = 68, /*< nick=InsufficientResources >*/ + QMI_PROTOCOL_ERROR_DISABLED = 69, /*< nick=Disabled >*/ + QMI_PROTOCOL_ERROR_INVALID_OPERATION = 70, /*< nick=InvalidOperation >*/ + QMI_PROTOCOL_ERROR_INVALID_QMI_COMMAND = 71, /*< nick=InvalidQmiCommand >*/ + QMI_PROTOCOL_ERROR_WMS_T_PDU_TYPE = 72, /*< nick=Wms.TPduType >*/ + QMI_PROTOCOL_ERROR_WMS_SMSC_ADDRESS = 73, /*< nick=Wms.SmscAddress >*/ + QMI_PROTOCOL_ERROR_INFORMATION_UNAVAILABLE = 74, /*< nick=InformationUnavailable >*/ + QMI_PROTOCOL_ERROR_SEGMENT_TOO_LONG = 75, /*< nick=SegmentTooLong >*/ + QMI_PROTOCOL_ERROR_SEGMENT_ORDER = 76, /*< nick=SegmentOrder >*/ + QMI_PROTOCOL_ERROR_BUNDLING_NOT_SUPPORTED = 77, /*< nick=BundlingNotSupported >*/ + /* 0x004E, 78: unused */ + QMI_PROTOCOL_ERROR_POLICY_MISMATCH = 79, /*< nick=PolicyMismatch >*/ + QMI_PROTOCOL_ERROR_SIM_FILE_NOT_FOUND = 80, /*< nick=SimFileNotFound >*/ + QMI_PROTOCOL_ERROR_EXTENDED_INTERNAL = 81, /*< nick=ExtendedInternal >*/ + QMI_PROTOCOL_ERROR_ACCESS_DENIED = 82, /*< nick=AccessDenied >*/ + QMI_PROTOCOL_ERROR_HARDWARE_RESTRICTED = 83, /*< nick=HardwareRestricted >*/ + QMI_PROTOCOL_ERROR_ACK_NOT_SENT = 84, /*< nick=AckNotSent >*/ + QMI_PROTOCOL_ERROR_INJECT_TIMEOUT = 85, /*< nick=InjectTimeout >*/ + QMI_PROTOCOL_ERROR_INCOMPATIBLE_STATE = 90, /*< nick=IncompatibleState >*/ + QMI_PROTOCOL_ERROR_FDN_RESTRICT = 91, /*< nick=FdnRestrict >*/ + QMI_PROTOCOL_ERROR_SUPS_FAILURE_CASE = 92, /*< nick=SupsFailureCase >*/ + QMI_PROTOCOL_ERROR_NO_RADIO = 93, /*< nick=NoRadio >*/ + QMI_PROTOCOL_ERROR_NOT_SUPPORTED = 94, /*< nick=NotSupported >*/ + QMI_PROTOCOL_ERROR_NO_SUBSCRIPTION = 95, /*< nick=NoSubscription >*/ + QMI_PROTOCOL_ERROR_CARD_CALL_CONTROL_FAILED = 96, /*< nick=CardCallControlFailed >*/ + QMI_PROTOCOL_ERROR_NETWORK_ABORTED = 97, /*< nick=NetworkAborted >*/ + QMI_PROTOCOL_ERROR_MSG_BLOCKED = 98, /*< nick=MsgBlocked >*/ + QMI_PROTOCOL_ERROR_INVALID_SESSION_TYPE = 100, /*< nick=InvalidSessionType >*/ + QMI_PROTOCOL_ERROR_INVALID_PB_TYPE = 101, /*< nick=InvalidPbType >*/ + QMI_PROTOCOL_ERROR_NO_SIM = 102, /*< nick=NoSim >*/ + QMI_PROTOCOL_ERROR_PB_NOT_READY = 103, /*< nick=PbNotReady >*/ + QMI_PROTOCOL_ERROR_PIN_RESTRICTION = 104, /*< nick=PinRestriction >*/ + QMI_PROTOCOL_ERROR_PIN2_RESTRICTION = 105, /*< nick=Pin1Restriction >*/ + QMI_PROTOCOL_ERROR_PUK_RESTRICTION = 106, /*< nick=PukRestriction >*/ + QMI_PROTOCOL_ERROR_PUK2_RESTRICTION = 107, /*< nick=Puk2Restriction >*/ + QMI_PROTOCOL_ERROR_PB_ACCESS_RESTRICTED = 108, /*< nick=PbAccessRestricted >*/ + QMI_PROTOCOL_ERROR_PB_TEXT_TOO_LONG = 109, /*< nick=PbTextTooLong >*/ + QMI_PROTOCOL_ERROR_PB_NUMBER_TOO_LONG = 110, /*< nick=PbNumberTooLong >*/ + QMI_PROTOCOL_ERROR_PB_HIDDEN_KEY_RESTRICTION = 111, /*< nick=PbHiddenKeyRestriction >*/ + QMI_PROTOCOL_ERROR_CAT_EVENT_REGISTRATION_FAILED = 61441, /*< nick=Cat.EventRegistrationFailed >*/ + QMI_PROTOCOL_ERROR_CAT_INVALID_TERMINAL_RESPONSE = 61442, /*< nick=Cat.InvalidTerminalResponse >*/ + QMI_PROTOCOL_ERROR_CAT_INVALID_ENVELOPE_COMMAND = 61443, /*< nick=Cat.InvalidEnvelopeCommand >*/ + QMI_PROTOCOL_ERROR_CAT_ENVELOPE_COMMAND_BUSY = 61444, /*< nick=Cat.EnvelopCommandBusy >*/ + QMI_PROTOCOL_ERROR_CAT_ENVELOPE_COMMAND_FAILED = 61445 /*< nick=Cat.EnvelopeCommandFailed >*/ +} QmiProtocolError; + +#endif /* _LIBQMI_GLIB_QMI_ERRORS_H_ */ diff --git a/release/src/router/uqmi/qmi-flags64-dms.h b/release/src/router/uqmi/qmi-flags64-dms.h new file mode 100644 index 0000000000..b51b5cfaf1 --- /dev/null +++ b/release/src/router/uqmi/qmi-flags64-dms.h @@ -0,0 +1,198 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * libqmi-glib -- GLib/GIO based library to control QMI devices + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012 Lanedo GmbH + * Copyright (C) 2012 Google, Inc. + */ + +#ifndef _LIBQMI_GLIB_QMI_FLAGS64_DMS_H_ +#define _LIBQMI_GLIB_QMI_FLAGS64_DMS_H_ + +/*****************************************************************************/ +/* Helper enums for the 'QMI DMS Get Band Capability' message */ + +/** + * QmiDmsBandCapability: + * @QMI_DMS_BAND_CAPABILITY_BC_0_A_SYSTEM: Band class 0, A-system. + * @QMI_DMS_BAND_CAPABILITY_BC_0_B_SYSTEM: Band class 0, B-system. + * @QMI_DMS_BAND_CAPABILITY_BC_1_ALL_BLOCKS: Band class 1, all blocks. + * @QMI_DMS_BAND_CAPABILITY_BC_2: Band class 2. + * @QMI_DMS_BAND_CAPABILITY_BC_3_A_SYSTEM: Band class 3, A-system. + * @QMI_DMS_BAND_CAPABILITY_BC_4_ALL_BLOCKS: Band class 4, all blocks. + * @QMI_DMS_BAND_CAPABILITY_BC_5_ALL_BLOCKS: Band class 5, all blocks. + * @QMI_DMS_BAND_CAPABILITY_BC_6: Band class 6. + * @QMI_DMS_BAND_CAPABILITY_BC_7: Band class 7. + * @QMI_DMS_BAND_CAPABILITY_BC_8: Band class 8. + * @QMI_DMS_BAND_CAPABILITY_BC_9: Band class 9. + * @QMI_DMS_BAND_CAPABILITY_BC_10: Band class 10. + * @QMI_DMS_BAND_CAPABILITY_BC_11: Band class 11. + * @QMI_DMS_BAND_CAPABILITY_BC_12: Band class 12. + * @QMI_DMS_BAND_CAPABILITY_BC_14: Band class 14. + * @QMI_DMS_BAND_CAPABILITY_BC_15: Band class 15. + * @QMI_DMS_BAND_CAPABILITY_BC_16: Band class 16. + * @QMI_DMS_BAND_CAPABILITY_BC_17: Band class 17. + * @QMI_DMS_BAND_CAPABILITY_BC_18: Band class 18. + * @QMI_DMS_BAND_CAPABILITY_BC_19: Band class 19. + * @QMI_DMS_BAND_CAPABILITY_GSM_DCS_1800: GSM DCS band. + * @QMI_DMS_BAND_CAPABILITY_GSM_900_EXTENDED: GSM Extended GSM band (900). + * @QMI_DMS_BAND_CAPABILITY_GSM_900_PRIMARY: GSM Primary GSM band (900). + * @QMI_DMS_BAND_CAPABILITY_GSM_450: GSM 450 band. + * @QMI_DMS_BAND_CAPABILITY_GSM_480: GSM 480 band. + * @QMI_DMS_BAND_CAPABILITY_GSM_750: GSM 750 band. + * @QMI_DMS_BAND_CAPABILITY_GSM_850: GSM 850 band. + * @QMI_DMS_BAND_CAPABILITY_GSM_900_RAILWAYS: GSM railways band (900). + * @QMI_DMS_BAND_CAPABILITY_GSM_PCS_1900: GSM PCS band (1900). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_2100: WCDMA 2100 band (Europe, Japan, China). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_PCS_1900: WCDMA PCS 1900 band (US). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_DCS_1800: WCDMA DCS 1800 band (Europe, China). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_1700_US: WCDMA 1700 band (US). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_850_US: WCDMA 850 band (US). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_800: QWCDMA 850 band (Japan). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_2600: WCDMA 2600 band (Europe). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_900: WCDMA 900 band (Europe, Japan). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_1700_JAPAN: WCDMA 1700 band (Japan). + * @QMI_DMS_BAND_CAPABILITY_WCDMA_850_JAPAN: WCDMA 850 band (Japan) + * @QMI_DMS_BAND_CAPABILITY_WCDMA_1500: WCDMA 1500 band. + * + * Frequency band capabilities. + */ +typedef enum { + QMI_DMS_BAND_CAPABILITY_BC_0_A_SYSTEM = 1 << 0, + QMI_DMS_BAND_CAPABILITY_BC_0_B_SYSTEM = 1 << 1, + QMI_DMS_BAND_CAPABILITY_BC_1_ALL_BLOCKS = 1 << 2, + QMI_DMS_BAND_CAPABILITY_BC_2 = 1 << 3, + QMI_DMS_BAND_CAPABILITY_BC_3_A_SYSTEM = 1 << 4, + QMI_DMS_BAND_CAPABILITY_BC_4_ALL_BLOCKS = 1 << 5, + QMI_DMS_BAND_CAPABILITY_BC_5_ALL_BLOCKS = 1 << 6, + QMI_DMS_BAND_CAPABILITY_GSM_DCS_1800 = 1 << 7, + QMI_DMS_BAND_CAPABILITY_GSM_900_EXTENDED = 1 << 8, + QMI_DMS_BAND_CAPABILITY_GSM_900_PRIMARY = 1 << 9, + QMI_DMS_BAND_CAPABILITY_BC_6 = 1 << 10, + QMI_DMS_BAND_CAPABILITY_BC_7 = 1 << 11, + QMI_DMS_BAND_CAPABILITY_BC_8 = 1 << 12, + QMI_DMS_BAND_CAPABILITY_BC_9 = 1 << 13, + QMI_DMS_BAND_CAPABILITY_BC_10 = 1 << 14, + QMI_DMS_BAND_CAPABILITY_BC_11 = 1 << 15, + QMI_DMS_BAND_CAPABILITY_GSM_450 = 1 << 16, + QMI_DMS_BAND_CAPABILITY_GSM_480 = 1 << 17, + QMI_DMS_BAND_CAPABILITY_GSM_750 = 1 << 18, + QMI_DMS_BAND_CAPABILITY_GSM_850 = 1 << 19, + QMI_DMS_BAND_CAPABILITY_GSM_900_RAILWAYS = 1 << 20, + QMI_DMS_BAND_CAPABILITY_GSM_PCS_1900 = 1 << 21, + QMI_DMS_BAND_CAPABILITY_WCDMA_2100 = 1 << 22, + QMI_DMS_BAND_CAPABILITY_WCDMA_PCS_1900 = 1 << 23, + QMI_DMS_BAND_CAPABILITY_WCDMA_DCS_1800 = 1 << 24, + QMI_DMS_BAND_CAPABILITY_WCDMA_1700_US = 1 << 25, + QMI_DMS_BAND_CAPABILITY_WCDMA_850_US = 1 << 26, + QMI_DMS_BAND_CAPABILITY_WCDMA_800 = 1 << 27, + QMI_DMS_BAND_CAPABILITY_BC_12 = 1 << 28, + QMI_DMS_BAND_CAPABILITY_BC_14 = 1 << 29, + /* Bit 30 reserved */ + QMI_DMS_BAND_CAPABILITY_BC_15 = 1 << 31, + /* Bits 32-47 reserved */ + QMI_DMS_BAND_CAPABILITY_WCDMA_2600 = ((uint64_t) 1) << 48, + QMI_DMS_BAND_CAPABILITY_WCDMA_900 = ((uint64_t) 1) << 49, + QMI_DMS_BAND_CAPABILITY_WCDMA_1700_JAPAN = ((uint64_t) 1) << 50, + /* Bits 51-55 reserved */ + QMI_DMS_BAND_CAPABILITY_BC_16 = ((uint64_t) 1) << 56, + QMI_DMS_BAND_CAPABILITY_BC_17 = ((uint64_t) 1) << 57, + QMI_DMS_BAND_CAPABILITY_BC_18 = ((uint64_t) 1) << 58, + QMI_DMS_BAND_CAPABILITY_BC_19 = ((uint64_t) 1) << 59, + QMI_DMS_BAND_CAPABILITY_WCDMA_850_JAPAN = ((uint64_t) 1) << 60, + QMI_DMS_BAND_CAPABILITY_WCDMA_1500 = ((uint64_t) 1) << 61 + /* Bits 62-63 reserved */ +} QmiDmsBandCapability; + +/** + * QmiDmsLteBandCapability: + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_1: LTE EUTRAN Band 1 + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_2: LTE EUTRAN Band 2. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_3: LTE EUTRAN Band 3. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_4: LTE EUTRAN Band 4. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_5: LTE EUTRAN Band 5. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_6: LTE EUTRAN Band 6. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_7: LTE EUTRAN Band 7. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_8: LTE EUTRAN Band 8. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_9: LTE EUTRAN Band 9. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_10: LTE EUTRAN Band 10. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_11: LTE EUTRAN Band 11. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_12: LTE EUTRAN Band 12. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_13: LTE EUTRAN Band 13. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_14: LTE EUTRAN Band 14. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_17: LTE EUTRAN Band 17. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_18: LTE EUTRAN Band 18. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_19: LTE EUTRAN Band 19. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_20: LTE EUTRAN Band 20. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_21: LTE EUTRAN Band 21. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_24: LTE EUTRAN Band 24. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_25: LTE EUTRAN Band 25. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_33: LTE EUTRAN Band 33. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_34: LTE EUTRAN Band 34. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_35: LTE EUTRAN Band 35. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_36: LTE EUTRAN Band 36. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_37: LTE EUTRAN Band 37. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_38: LTE EUTRAN Band 38. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_39: LTE EUTRAN Band 39. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_40: LTE EUTRAN Band 40. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_41: LTE EUTRAN Band 41. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_42: LTE EUTRAN Band 42. + * @QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_43: LTE EUTRAN Band 43. + * + * LTE-specific Frequency bands. + */ +typedef enum { + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_1 = 1 << 0, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_2 = 1 << 1, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_3 = 1 << 2, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_4 = 1 << 3, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_5 = 1 << 4, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_6 = 1 << 5, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_7 = 1 << 6, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_8 = 1 << 7, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_9 = 1 << 8, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_10 = 1 << 9, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_11 = 1 << 10, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_12 = 1 << 11, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_13 = 1 << 12, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_14 = 1 << 13, + /* Bit 14-15 reserved */ + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_17 = 1 << 16, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_18 = 1 << 17, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_19 = 1 << 18, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_20 = 1 << 19, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_21 = 1 << 20, + /* Bit 21-22 reserved */ + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_24 = 1 << 23, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_25 = 1 << 24, + /* Bit 25-31 reserved */ + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_33 = ((uint64_t) 1) << 32, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_34 = ((uint64_t) 1) << 33, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_35 = ((uint64_t) 1) << 34, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_36 = ((uint64_t) 1) << 35, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_37 = ((uint64_t) 1) << 36, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_38 = ((uint64_t) 1) << 37, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_39 = ((uint64_t) 1) << 38, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_40 = ((uint64_t) 1) << 39, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_41 = ((uint64_t) 1) << 40, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_42 = ((uint64_t) 1) << 41, + QMI_DMS_LTE_BAND_CAPABILITY_EUTRAN_43 = ((uint64_t) 1) << 42 + /* Bit 43-64 reserved */ +} QmiDmsLteBandCapability; + +#endif /* _LIBQMI_GLIB_QMI_FLAGS64_DMS_H_ */ diff --git a/release/src/router/uqmi/qmi-flags64-nas.h b/release/src/router/uqmi/qmi-flags64-nas.h new file mode 100644 index 0000000000..1820adb473 --- /dev/null +++ b/release/src/router/uqmi/qmi-flags64-nas.h @@ -0,0 +1,194 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * libqmi-glib -- GLib/GIO based library to control QMI devices + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2012 Google Inc. + */ + +#ifndef _LIBQMI_GLIB_QMI_FLAGS64_NAS_H_ +#define _LIBQMI_GLIB_QMI_FLAGS64_NAS_H_ + +/*****************************************************************************/ +/* Helper enums for the 'QMI NAS Get System Selection Preference' + * request/response */ + +/** + * QmiNasBandPreference: + * @QMI_NAS_BAND_PREFERENCE_BC_0_A_SYSTEM: Band class 0, A system. + * @QMI_NAS_BAND_PREFERENCE_BC_0_B_SYSTEM: Band class 0, B system. + * @QMI_NAS_BAND_PREFERENCE_BC_1_ALL_BLOCKS: Band class 1. + * @QMI_NAS_BAND_PREFERENCE_BC_2: Band class 2. + * @QMI_NAS_BAND_PREFERENCE_BC_3_A_SYSTEM: Band class 3, A system. + * @QMI_NAS_BAND_PREFERENCE_BC_4_ALL_BLOCKS: Band class 4, all blocks. + * @QMI_NAS_BAND_PREFERENCE_BC_5_ALL_BLOCKS: Band class 5, all blocks. + * @QMI_NAS_BAND_PREFERENCE_BC_6: Band class 6. + * @QMI_NAS_BAND_PREFERENCE_BC_7: Band class 7. + * @QMI_NAS_BAND_PREFERENCE_BC_8: Band class 8. + * @QMI_NAS_BAND_PREFERENCE_BC_9: Band class 9. + * @QMI_NAS_BAND_PREFERENCE_BC_10: Band class 10. + * @QMI_NAS_BAND_PREFERENCE_BC_11: Band class 11. + * @QMI_NAS_BAND_PREFERENCE_BC_12: Band class 12. + * @QMI_NAS_BAND_PREFERENCE_BC_14: Band class 14. + * @QMI_NAS_BAND_PREFERENCE_BC_15: Band class 15. + * @QMI_NAS_BAND_PREFERENCE_BC_16: Band class 16. + * @QMI_NAS_BAND_PREFERENCE_BC_17: Band class 17. + * @QMI_NAS_BAND_PREFERENCE_BC_18: Band class 18. + * @QMI_NAS_BAND_PREFERENCE_BC_19: Band class 19. + * @QMI_NAS_BAND_PREFERENCE_GSM_DCS_1800: GSM DCS 1800 band. + * @QMI_NAS_BAND_PREFERENCE_GSM_900_EXTENDED: Extended GSM 900 band. + * @QMI_NAS_BAND_PREFERENCE_GSM_900_PRIMARY: Primary GSM 900 band. + * @QMI_NAS_BAND_PREFERENCE_GSM_450: GSM 450. + * @QMI_NAS_BAND_PREFERENCE_GSM_480: GSM 480. + * @QMI_NAS_BAND_PREFERENCE_GSM_750: GSM 750. + * @QMI_NAS_BAND_PREFERENCE_GSM_850: GSM 850. + * @QMI_NAS_BAND_PREFERENCE_GSM_900_RAILWAYS: GSM 900 (Railways). + * @QMI_NAS_BAND_PREFERENCE_GSM_PCS_1900: GSM 1900. + * @QMI_NAS_BAND_PREFERENCE_WCDMA_2100: WCDMA 2100. + * @QMI_NAS_BAND_PREFERENCE_WCDMA_PCS_1900: WCDMA PCS 1900. + * @QMI_NAS_BAND_PREFERENCE_WCDMA_DCS_1800: WCDMA DCS 1800. + * @QMI_NAS_BAND_PREFERENCE_WCDMA_1700_US: WCDMA 1700 (U.S.). + * @QMI_NAS_BAND_PREFERENCE_WCDMA_850_US: WCDMA 850. + * @QMI_NAS_BAND_PREFERENCE_WCDMA_800: WCDMA 800. + * @QMI_NAS_BAND_PREFERENCE_WCDMA_2600: WCDMA 2600. + * @QMI_NAS_BAND_PREFERENCE_WCDMA_900: WCDMA 900. + * @QMI_NAS_BAND_PREFERENCE_WCDMA_1700_JAPAN: WCDMA 1700 (Japan). + * + * Flags to specify frequency band preferences. + */ +typedef enum { + QMI_NAS_BAND_PREFERENCE_BC_0_A_SYSTEM = 1 << 0, + QMI_NAS_BAND_PREFERENCE_BC_0_B_SYSTEM = 1 << 1, + QMI_NAS_BAND_PREFERENCE_BC_1_ALL_BLOCKS = 1 << 2, + QMI_NAS_BAND_PREFERENCE_BC_2 = 1 << 3, + QMI_NAS_BAND_PREFERENCE_BC_3_A_SYSTEM = 1 << 4, + QMI_NAS_BAND_PREFERENCE_BC_4_ALL_BLOCKS = 1 << 5, + QMI_NAS_BAND_PREFERENCE_BC_5_ALL_BLOCKS = 1 << 6, + QMI_NAS_BAND_PREFERENCE_GSM_DCS_1800 = 1 << 7, + QMI_NAS_BAND_PREFERENCE_GSM_900_EXTENDED = 1 << 8, + QMI_NAS_BAND_PREFERENCE_GSM_900_PRIMARY = 1 << 9, + QMI_NAS_BAND_PREFERENCE_BC_6 = 1 << 10, + QMI_NAS_BAND_PREFERENCE_BC_7 = 1 << 11, + QMI_NAS_BAND_PREFERENCE_BC_8 = 1 << 12, + QMI_NAS_BAND_PREFERENCE_BC_9 = 1 << 13, + QMI_NAS_BAND_PREFERENCE_BC_10 = 1 << 14, + QMI_NAS_BAND_PREFERENCE_BC_11 = 1 << 15, + QMI_NAS_BAND_PREFERENCE_GSM_450 = 1 << 16, + QMI_NAS_BAND_PREFERENCE_GSM_480 = 1 << 17, + QMI_NAS_BAND_PREFERENCE_GSM_750 = 1 << 18, + QMI_NAS_BAND_PREFERENCE_GSM_850 = 1 << 19, + QMI_NAS_BAND_PREFERENCE_GSM_900_RAILWAYS = 1 << 20, + QMI_NAS_BAND_PREFERENCE_GSM_PCS_1900 = 1 << 21, + QMI_NAS_BAND_PREFERENCE_WCDMA_2100 = 1 << 22, + QMI_NAS_BAND_PREFERENCE_WCDMA_PCS_1900 = 1 << 23, + QMI_NAS_BAND_PREFERENCE_WCDMA_DCS_1800 = 1 << 24, + QMI_NAS_BAND_PREFERENCE_WCDMA_1700_US = 1 << 25, + QMI_NAS_BAND_PREFERENCE_WCDMA_850_US = 1 << 26, + QMI_NAS_BAND_PREFERENCE_WCDMA_800 = 1 << 27, + QMI_NAS_BAND_PREFERENCE_BC_12 = 1 << 28, + QMI_NAS_BAND_PREFERENCE_BC_14 = 1 << 29, + /* Bit 30 reserved */ + QMI_NAS_BAND_PREFERENCE_BC_15 = 1 << 31, + /* Bits 32-47 reserved */ + QMI_NAS_BAND_PREFERENCE_WCDMA_2600 = ((uint64_t) 1) << 48, + QMI_NAS_BAND_PREFERENCE_WCDMA_900 = ((uint64_t) 1) << 49, + QMI_NAS_BAND_PREFERENCE_WCDMA_1700_JAPAN = ((uint64_t) 1) << 50, + /* Bits 51-55 reserved */ + QMI_NAS_BAND_PREFERENCE_BC_16 = ((uint64_t) 1) << 56, + QMI_NAS_BAND_PREFERENCE_BC_17 = ((uint64_t) 1) << 57, + QMI_NAS_BAND_PREFERENCE_BC_18 = ((uint64_t) 1) << 58, + QMI_NAS_BAND_PREFERENCE_BC_19 = ((uint64_t) 1) << 59 + /* Bits 60-63 reserved */ +} QmiNasBandPreference; + +/** + * QmiNasLteBandPreference: + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_1: LTE EUTRAN Band 1 + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_2: LTE EUTRAN Band 2. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_3: LTE EUTRAN Band 3. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_4: LTE EUTRAN Band 4. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_5: LTE EUTRAN Band 5. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_6: LTE EUTRAN Band 6. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_7: LTE EUTRAN Band 7. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_8: LTE EUTRAN Band 8. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_9: LTE EUTRAN Band 9. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_10: LTE EUTRAN Band 10. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_11: LTE EUTRAN Band 11. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_12: LTE EUTRAN Band 12. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_13: LTE EUTRAN Band 13. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_14: LTE EUTRAN Band 14. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_17: LTE EUTRAN Band 17. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_18: LTE EUTRAN Band 18. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_19: LTE EUTRAN Band 19. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_20: LTE EUTRAN Band 20. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_21: LTE EUTRAN Band 21. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_24: LTE EUTRAN Band 24. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_25: LTE EUTRAN Band 25. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_33: LTE EUTRAN Band 33. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_34: LTE EUTRAN Band 34. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_35: LTE EUTRAN Band 35. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_36: LTE EUTRAN Band 36. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_37: LTE EUTRAN Band 37. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_38: LTE EUTRAN Band 38. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_39: LTE EUTRAN Band 39. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_40: LTE EUTRAN Band 40. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_41: LTE EUTRAN Band 41. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_42: LTE EUTRAN Band 42. + * @QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_43: LTE EUTRAN Band 43. + * + * Flags to specify LTE-specific frequency band preferences. + */ +typedef enum { + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_1 = 1 << 0, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_2 = 1 << 1, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_3 = 1 << 2, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_4 = 1 << 3, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_5 = 1 << 4, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_6 = 1 << 5, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_7 = 1 << 6, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_8 = 1 << 7, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_9 = 1 << 8, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_10 = 1 << 9, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_11 = 1 << 10, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_12 = 1 << 11, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_13 = 1 << 12, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_14 = 1 << 13, + /* Bit 14-15 reserved */ + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_17 = 1 << 16, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_18 = 1 << 17, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_19 = 1 << 18, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_20 = 1 << 19, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_21 = 1 << 20, + /* Bit 21-22 reserved */ + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_24 = 1 << 23, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_25 = 1 << 24, + /* Bit 25-31 reserved */ + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_33 = ((uint64_t) 1) << 32, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_34 = ((uint64_t) 1) << 33, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_35 = ((uint64_t) 1) << 34, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_36 = ((uint64_t) 1) << 35, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_37 = ((uint64_t) 1) << 36, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_38 = ((uint64_t) 1) << 37, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_39 = ((uint64_t) 1) << 38, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_40 = ((uint64_t) 1) << 39, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_41 = ((uint64_t) 1) << 40, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_42 = ((uint64_t) 1) << 41, + QMI_NAS_LTE_BAND_PREFERENCE_EUTRAN_43 = ((uint64_t) 1) << 42 + /* Bit 43-64 reserved */ +} QmiNasLteBandPreference; + +#endif /* _LIBQMI_GLIB_QMI_FLAGS64_NAS_H_ */ diff --git a/release/src/router/uqmi/qmi-message.c b/release/src/router/uqmi/qmi-message.c new file mode 100644 index 0000000000..21515f9b85 --- /dev/null +++ b/release/src/router/uqmi/qmi-message.c @@ -0,0 +1,176 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2014-2015 Felix Fietkau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include +#include +#include + +#include "qmi-message.h" + +static uint8_t buf[QMI_BUFFER_LEN]; +static unsigned int buf_ofs; + +uint8_t *__qmi_get_buf(unsigned int *ofs) +{ + *ofs = buf_ofs; + return buf; +} + +void __qmi_alloc_reset(void) +{ + buf_ofs = 0; +} + +void *__qmi_alloc_static(unsigned int len) +{ + void *ret; + + if (buf_ofs + len > sizeof(buf)) { + fprintf(stderr, "ERROR: static buffer for message data too small\n"); + abort(); + } + + ret = &buf[buf_ofs]; + buf_ofs += len; + memset(ret, 0, len); + return ret; +} + +char *__qmi_copy_string(void *data, unsigned int len) +{ + char *res; + + res = (char *) &buf[buf_ofs]; + buf_ofs += len + 1; + memcpy(res, data, len); + res[len] = 0; + return res; +} + +struct tlv *tlv_get_next(void **buf, unsigned int *buflen) +{ + struct tlv *tlv = NULL; + unsigned int tlv_len; + + if (*buflen < sizeof(*tlv)) + return NULL; + + tlv = *buf; + tlv_len = le16_to_cpu(tlv->len) + sizeof(*tlv); + if (tlv_len > *buflen) + return NULL; + + *buflen -= tlv_len; + *buf += tlv_len; + return tlv; +} + +static struct tlv *qmi_msg_next_tlv(struct qmi_msg *qm, int add) +{ + int tlv_len; + void *tlv; + + if (qm->qmux.service == QMI_SERVICE_CTL) { + tlv = qm->ctl.tlv; + tlv_len = le16_to_cpu(qm->ctl.tlv_len); + qm->ctl.tlv_len = cpu_to_le16(tlv_len + add); + } else { + tlv = qm->svc.tlv; + tlv_len = le16_to_cpu(qm->svc.tlv_len); + qm->svc.tlv_len = cpu_to_le16(tlv_len + add); + } + + tlv += tlv_len; + + return tlv; +} + +void tlv_new(struct qmi_msg *qm, uint8_t type, uint16_t len, void *data) +{ + struct tlv *tlv; + + tlv = qmi_msg_next_tlv(qm, sizeof(*tlv) + len); + tlv->type = type; + tlv->len = cpu_to_le16(len); + memcpy(tlv->data, data, len); +} + +void qmi_init_request_message(struct qmi_msg *qm, QmiService service) +{ + memset(qm, 0, sizeof(*qm)); + qm->marker = 1; + qm->qmux.service = service; +} + +int qmi_complete_request_message(struct qmi_msg *qm) +{ + void *tlv_end = qmi_msg_next_tlv(qm, 0); + void *msg_start = &qm->qmux; + + qm->qmux.len = cpu_to_le16(tlv_end - msg_start); + return tlv_end - msg_start + 1; +} + +int qmi_check_message_status(void *tlv_buf, unsigned int len) +{ + struct tlv *tlv; + struct { + uint16_t status; + uint16_t code; + } __packed *status; + + while ((tlv = tlv_get_next(&tlv_buf, &len)) != NULL) { + if (tlv->type != 2) + continue; + + if (tlv_data_len(tlv) != sizeof(*status)) + return QMI_ERROR_INVALID_DATA; + + status = (void *) tlv->data; + if (!status->status) + return 0; + + return le16_to_cpu(status->code); + } + + return QMI_ERROR_NO_DATA; +} + +void *qmi_msg_get_tlv_buf(struct qmi_msg *qm, int *tlv_len) +{ + void *ptr; + int len; + + if (qm->qmux.service == QMI_SERVICE_CTL) { + ptr = qm->ctl.tlv; + len = qm->ctl.tlv_len; + } else { + ptr = qm->svc.tlv; + len = qm->svc.tlv_len; + } + + if (tlv_len) + *tlv_len = len; + + return ptr; +} + + diff --git a/release/src/router/uqmi/qmi-message.h b/release/src/router/uqmi/qmi-message.h new file mode 100644 index 0000000000..61112140d1 --- /dev/null +++ b/release/src/router/uqmi/qmi-message.h @@ -0,0 +1,123 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2014-2015 Felix Fietkau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#ifndef __UQMI_MESSAGE_H +#define __UQMI_MESSAGE_H + +#include +#include + +#include "qmi-struct.h" +#include "qmi-enums.h" + +#include "qmi-enums-private.h" +#include "qmi-message-ctl.h" + +#include "qmi-enums-dms.h" +#include "qmi-flags64-dms.h" +#include "qmi-message-dms.h" + +#include "qmi-enums-nas.h" +#include "qmi-flags64-nas.h" +#include "qmi-message-nas.h" + +#include "qmi-enums-pds.h" +#include "qmi-message-pds.h" + +#include "qmi-enums-wds.h" +#include "qmi-message-wds.h" + +#include "qmi-enums-wms.h" +#include "qmi-message-wms.h" + +#include "qmi-enums-wda.h" +#include "qmi-message-wda.h" + +#define qmi_set(_data, _field, _val) \ + do { \ + (_data)->set._field = 1; \ + (_data)->data._field = _val; \ + } while (0) + +#define qmi_set_ptr(_data, _field, _val) \ + do { \ + (_data)->data._field = _val; \ + } while (0) + +#define qmi_set_static_array(_data, _field, _val) \ + do { \ + (_data)->data._field##_n = ARRAY_SIZE(_val); \ + (_data)->data._field = _val; \ + } while (0); + +#define qmi_set_array(_data, _field, _val, _n) \ + do { \ + (_data)->data.n_##_field = _n; \ + (_data)->data._field = _val; \ + } while (0); + +#define QMI_INIT(_field, _val) \ + .set._field = 1, \ + .data._field = (_val) + +#define QMI_INIT_SEQUENCE(_field, ...) \ + .set._field = 1, \ + .data._field = { __VA_ARGS__ } + +#define QMI_INIT_PTR(_field, _val) \ + .data._field = (_val) + +#define QMI_INIT_STATIC_ARRAY(_field, _val) \ + .data._field##_n = ARRAY_SIZE(_val), \ + .data._field = (_val) + +#define QMI_INIT_ARRAY(_field, _val, _n) \ + .data._field##_n = (_n), \ + .data._field = (_val) + + +enum { + QMI_ERROR_NO_DATA = -1, + QMI_ERROR_INVALID_DATA = -2, + QMI_ERROR_CANCELLED = -3, +}; + +#define QMI_BUFFER_LEN 2048 + +void __qmi_alloc_reset(void); +void *__qmi_alloc_static(unsigned int len); +char *__qmi_copy_string(void *data, unsigned int len); +uint8_t *__qmi_get_buf(unsigned int *ofs); + +static inline int tlv_data_len(struct tlv *tlv) +{ + return le16_to_cpu(tlv->len); +} + +struct tlv *tlv_get_next(void **buf, unsigned int *buflen); +void tlv_new(struct qmi_msg *qm, uint8_t type, uint16_t len, void *data); + +void qmi_init_request_message(struct qmi_msg *qm, QmiService service); +int qmi_complete_request_message(struct qmi_msg *qm); +int qmi_check_message_status(void *buf, unsigned int len); +void *qmi_msg_get_tlv_buf(struct qmi_msg *qm, int *len); + +#endif diff --git a/release/src/router/uqmi/qmi-struct.h b/release/src/router/uqmi/qmi-struct.h new file mode 100644 index 0000000000..52f1c56bc4 --- /dev/null +++ b/release/src/router/uqmi/qmi-struct.h @@ -0,0 +1,62 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2014-2015 Felix Fietkau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#ifndef __QMI_STRUCT_H +#define __QMI_STRUCT_H + +struct qmux { + uint16_t len; + uint8_t flags; + uint8_t service; + uint8_t client; +} __packed; + +struct tlv { + uint8_t type; + uint16_t len; + uint8_t data[]; +} __packed; + +struct qmi_ctl { + uint8_t transaction; + uint16_t message; + uint16_t tlv_len; + struct tlv tlv[]; +} __packed; + +struct qmi_svc { + uint16_t transaction; + uint16_t message; + uint16_t tlv_len; + struct tlv tlv[]; +} __packed; + +struct qmi_msg { + uint8_t marker; + struct qmux qmux; + uint8_t flags; + union { + struct qmi_ctl ctl; + struct qmi_svc svc; + }; +} __packed; + +#endif diff --git a/release/src/router/uqmi/uqmi.h b/release/src/router/uqmi/uqmi.h new file mode 100644 index 0000000000..5cd3bff06e --- /dev/null +++ b/release/src/router/uqmi/uqmi.h @@ -0,0 +1,124 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2014-2015 Felix Fietkau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#ifndef __UQMI_H +#define __UQMI_H + +#include + +#include +#include + +#include "qmi-message.h" + +#ifdef DEBUG_PACKET +void dump_packet(const char *prefix, void *ptr, int len); +#else +static inline void dump_packet(const char *prefix, void *ptr, int len) +{ +} +#endif + +#define __qmi_services \ + __qmi_service(QMI_SERVICE_WDS), \ + __qmi_service(QMI_SERVICE_DMS), \ + __qmi_service(QMI_SERVICE_NAS), \ + __qmi_service(QMI_SERVICE_QOS), \ + __qmi_service(QMI_SERVICE_WMS), \ + __qmi_service(QMI_SERVICE_PDS), \ + __qmi_service(QMI_SERVICE_AUTH), \ + __qmi_service(QMI_SERVICE_AT), \ + __qmi_service(QMI_SERVICE_VOICE), \ + __qmi_service(QMI_SERVICE_CAT2), \ + __qmi_service(QMI_SERVICE_UIM), \ + __qmi_service(QMI_SERVICE_PBM), \ + __qmi_service(QMI_SERVICE_LOC), \ + __qmi_service(QMI_SERVICE_SAR), \ + __qmi_service(QMI_SERVICE_RMTFS), \ + __qmi_service(QMI_SERVICE_CAT), \ + __qmi_service(QMI_SERVICE_RMS), \ + __qmi_service(QMI_SERVICE_OMA), \ + __qmi_service(QMI_SERVICE_WDA) + +#define __qmi_service(_n) __##_n +enum { + __qmi_services, + __QMI_SERVICE_LAST +}; +#undef __qmi_service + +struct qmi_dev; +struct qmi_request; +struct qmi_msg; + +typedef void (*request_cb)(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg); + +struct qmi_dev { + struct ustream_fd sf; + + struct list_head req; + + struct { + bool connected; + uint8_t client_id; + uint16_t tid; + } service_data[__QMI_SERVICE_LAST]; + + uint32_t service_connected; + uint32_t service_keep_cid; + uint32_t service_release_cid; + + uint8_t ctl_tid; +}; + +struct qmi_request { + struct list_head list; + + request_cb cb; + + bool *complete; + bool pending; + bool no_error_cb; + uint8_t service; + uint16_t tid; + int ret; +}; + +extern bool cancel_all_requests; +int qmi_device_open(struct qmi_dev *qmi, const char *path); +void qmi_device_close(struct qmi_dev *qmi); + +int qmi_request_start(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, request_cb cb); +void qmi_request_cancel(struct qmi_dev *qmi, struct qmi_request *req); +int qmi_request_wait(struct qmi_dev *qmi, struct qmi_request *req); + +static inline bool qmi_request_pending(struct qmi_request *req) +{ + return req->pending; +} + +int qmi_service_connect(struct qmi_dev *qmi, QmiService svc, int client_id); +int qmi_service_get_client_id(struct qmi_dev *qmi, QmiService svc); +int qmi_service_release_client_id(struct qmi_dev *qmi, QmiService svc); +QmiService qmi_service_get_by_name(const char *str); +const char *qmi_get_error_str(int code); + +#endif -- 2.11.4.GIT