dbc_cli.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #!/usr/bin/python3
  2. # SPDX-License-Identifier: GPL-2.0
  3. import argparse
  4. import binascii
  5. import os
  6. import errno
  7. from dbc import *
  8. ERRORS = {
  9. errno.EACCES: "Access is denied",
  10. errno.E2BIG: "Excess data provided",
  11. errno.EINVAL: "Bad parameters",
  12. errno.EAGAIN: "Bad state",
  13. errno.ENOENT: "Not implemented or message failure",
  14. errno.EBUSY: "Busy",
  15. errno.ENFILE: "Overflow",
  16. errno.EPERM: "Signature invalid",
  17. }
  18. messages = {
  19. "get-fmax-cap": PARAM_GET_FMAX_CAP,
  20. "set-fmax-cap": PARAM_SET_FMAX_CAP,
  21. "get-power-cap": PARAM_GET_PWR_CAP,
  22. "set-power-cap": PARAM_SET_PWR_CAP,
  23. "get-graphics-mode": PARAM_GET_GFX_MODE,
  24. "set-graphics-mode": PARAM_SET_GFX_MODE,
  25. "get-current-temp": PARAM_GET_CURR_TEMP,
  26. "get-fmax-max": PARAM_GET_FMAX_MAX,
  27. "get-fmax-min": PARAM_GET_FMAX_MIN,
  28. "get-soc-power-max": PARAM_GET_SOC_PWR_MAX,
  29. "get-soc-power-min": PARAM_GET_SOC_PWR_MIN,
  30. "get-soc-power-cur": PARAM_GET_SOC_PWR_CUR,
  31. }
  32. def _pretty_buffer(ba):
  33. return str(binascii.hexlify(ba, " "))
  34. def parse_args():
  35. parser = argparse.ArgumentParser(
  36. description="Dynamic Boost control command line interface"
  37. )
  38. parser.add_argument(
  39. "command",
  40. choices=["get-nonce", "get-param", "set-param", "set-uid"],
  41. help="Command to send",
  42. )
  43. parser.add_argument("--device", default="/dev/dbc", help="Device to operate")
  44. parser.add_argument("--signature", help="File containing signature for command")
  45. parser.add_argument("--message", choices=messages.keys(), help="Message index")
  46. parser.add_argument("--data", help="Argument to pass to message")
  47. parser.add_argument("--uid", help="File containing UID to pass")
  48. return parser.parse_args()
  49. def pretty_error(code):
  50. if code in ERRORS:
  51. print(ERRORS[code])
  52. else:
  53. print("failed with return code %d" % code)
  54. if __name__ == "__main__":
  55. args = parse_args()
  56. data = 0
  57. sig = None
  58. uid = None
  59. if not os.path.exists(args.device):
  60. raise IOError("Missing device {device}".format(device=args.device))
  61. if args.signature:
  62. if not os.path.exists(args.signature):
  63. raise ValueError("Invalid signature file %s" % args.signature)
  64. with open(args.signature, "rb") as f:
  65. sig = f.read()
  66. if len(sig) != DBC_SIG_SIZE:
  67. raise ValueError(
  68. "Invalid signature length %d (expected %d)" % (len(sig), DBC_SIG_SIZE)
  69. )
  70. if args.uid:
  71. if not os.path.exists(args.uid):
  72. raise ValueError("Invalid uid file %s" % args.uid)
  73. with open(args.uid, "rb") as f:
  74. uid = f.read()
  75. if len(uid) != DBC_UID_SIZE:
  76. raise ValueError(
  77. "Invalid UID length %d (expected %d)" % (len(uid), DBC_UID_SIZE)
  78. )
  79. if args.data:
  80. try:
  81. data = int(args.data, 10)
  82. except ValueError:
  83. data = int(args.data, 16)
  84. with open(args.device) as d:
  85. if args.command == "get-nonce":
  86. try:
  87. nonce = get_nonce(d, sig)
  88. print("Nonce: %s" % _pretty_buffer(bytes(nonce)))
  89. except OSError as e:
  90. pretty_error(e.errno)
  91. elif args.command == "set-uid":
  92. try:
  93. result = set_uid(d, uid, sig)
  94. if result:
  95. print("Set UID")
  96. except OSError as e:
  97. pretty_error(e.errno)
  98. elif args.command == "get-param":
  99. if not args.message or args.message.startswith("set"):
  100. raise ValueError("Invalid message %s" % args.message)
  101. try:
  102. param, signature = process_param(d, messages[args.message], sig)
  103. print(
  104. "Parameter: {par}, response signature {sig}".format(
  105. par=param,
  106. sig=_pretty_buffer(bytes(signature)),
  107. )
  108. )
  109. except OSError as e:
  110. pretty_error(e.errno)
  111. elif args.command == "set-param":
  112. if not args.message or args.message.startswith("get"):
  113. raise ValueError("Invalid message %s" % args.message)
  114. try:
  115. param, signature = process_param(d, messages[args.message], sig, data)
  116. print(
  117. "Parameter: {par}, response signature {sig}".format(
  118. par=param,
  119. sig=_pretty_buffer(bytes(signature)),
  120. )
  121. )
  122. except OSError as e:
  123. pretty_error(e.errno)