You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
5.5 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. """Attempt detection of current chip / CPU."""
  2. import os
  3. import sys
  4. AM33XX = "AM33XX"
  5. IMX8MX = "IMX8MX"
  6. BCM2XXX = "BCM2XXX"
  7. ESP8266 = "ESP8266"
  8. SAMD21 = "SAMD21"
  9. STM32 = "STM32"
  10. SUN8I = "SUN8I"
  11. S805 = "S805"
  12. S905 = "S905"
  13. S922X = "S922X"
  14. SAMA5 = "SAMA5"
  15. T210 = "T210"
  16. T186 = "T186"
  17. T194 = "T194"
  18. APQ8016 = "APQ8016"
  19. GENERIC_X86 = "GENERIC_X86"
  20. FT232H = "FT232H"
  21. HFU540 = "HFU540"
  22. MCP2221 = "MCP2221"
  23. BINHO = "BINHO"
  24. MIPS24KC = "MIPS24KC"
  25. MIPS24KEC = "MIPS24KEC"
  26. A64 = "A64"
  27. BCM_RANGE = {'BCM2708', 'BCM2709', 'BCM2835', 'BCM2837', 'bcm2708', 'bcm2709',
  28. 'bcm2835', 'bcm2837'}
  29. class Chip:
  30. """Attempt detection of current chip / CPU."""
  31. def __init__(self, detector):
  32. self.detector = detector
  33. @property
  34. def id(self): # pylint: disable=invalid-name,too-many-branches,too-many-return-statements
  35. """Return a unique id for the detected chip, if any."""
  36. # There are some times we want to trick the platform detection
  37. # say if a raspberry pi doesn't have the right ID, or for testing
  38. try:
  39. return os.environ['BLINKA_FORCECHIP']
  40. except KeyError: # no forced chip, continue with testing!
  41. pass
  42. # Special cases controlled by environment var
  43. if os.environ.get('BLINKA_FT232H'):
  44. from pyftdi.usbtools import UsbTools # pylint: disable=import-error
  45. # look for it based on PID/VID
  46. count = len(UsbTools.find_all([(0x0403, 0x6014)]))
  47. if count == 0:
  48. raise RuntimeError('BLINKA_FT232H environment variable ' + \
  49. 'set, but no FT232H device found')
  50. return FT232H
  51. if os.environ.get('BLINKA_MCP2221'):
  52. import hid # pylint: disable=import-error
  53. # look for it based on PID/VID
  54. for dev in hid.enumerate():
  55. if dev['vendor_id'] == 0x04D8 and dev['product_id'] == 0x00DD:
  56. return MCP2221
  57. raise RuntimeError('BLINKA_MCP2221 environment variable ' + \
  58. 'set, but no MCP2221 device found')
  59. if os.environ.get('BLINKA_NOVA'):
  60. return BINHO
  61. platform = sys.platform
  62. if platform in ('linux', 'linux2'):
  63. return self._linux_id()
  64. if platform == 'esp8266':
  65. return ESP8266
  66. if platform == 'samd21':
  67. return SAMD21
  68. if platform == 'pyboard':
  69. return STM32
  70. # nothing found!
  71. return None
  72. # pylint: enable=invalid-name
  73. def _linux_id(self): # pylint: disable=too-many-branches,too-many-statements
  74. """Attempt to detect the CPU on a computer running the Linux kernel."""
  75. if self.detector.check_dt_compatible_value('qcom,apq8016'):
  76. return APQ8016
  77. if self.detector.check_dt_compatible_value('fu500'):
  78. return HFU540
  79. linux_id = None
  80. hardware = self.detector.get_cpuinfo_field('Hardware')
  81. if hardware is None:
  82. vendor_id = self.detector.get_cpuinfo_field('vendor_id')
  83. if vendor_id in ('GenuineIntel', 'AuthenticAMD'):
  84. linux_id = GENERIC_X86
  85. compatible = self.detector.get_device_compatible()
  86. if compatible and 'tegra' in compatible:
  87. if 'cv' in compatible or 'nano' in compatible:
  88. linux_id = T210
  89. elif 'quill' in compatible:
  90. linux_id = T186
  91. elif 'xavier' in compatible:
  92. linux_id = T194
  93. if compatible and 'imx8m' in compatible:
  94. linux_id = IMX8MX
  95. if compatible and 'odroid-c2' in compatible:
  96. linux_id = S905
  97. if compatible and 'amlogic, g12b' in compatible:
  98. linux_id = S922X
  99. cpu_model = self.detector.get_cpuinfo_field("cpu model")
  100. if cpu_model is not None:
  101. if "MIPS 24Kc" in cpu_model:
  102. linux_id = MIPS24KC
  103. elif "MIPS 24KEc" in cpu_model:
  104. linux_id = MIPS24KEC
  105. # we still haven't identified the hardware, so
  106. # convert it to a list and let the remaining
  107. # conditions attempt.
  108. if not linux_id:
  109. hardware = [
  110. entry.replace('\x00', '') for entry in compatible.split(',')
  111. ]
  112. if not linux_id:
  113. if 'AM33XX' in hardware:
  114. linux_id = AM33XX
  115. elif 'sun8i' in hardware:
  116. linux_id = SUN8I
  117. elif 'ODROIDC' in hardware:
  118. linux_id = S805
  119. elif 'ODROID-C2' in hardware:
  120. linux_id = S905
  121. elif 'ODROID-N2' in hardware:
  122. linux_id = S922X
  123. elif 'SAMA5' in hardware:
  124. linux_id = SAMA5
  125. elif "Pinebook" in hardware:
  126. linux_id = A64
  127. elif "sun50iw1p1" in hardware:
  128. linux_id = A64
  129. else:
  130. if isinstance(hardware, str):
  131. if hardware in BCM_RANGE:
  132. linux_id = BCM2XXX
  133. elif isinstance(hardware, list):
  134. if set(hardware) & BCM_RANGE:
  135. linux_id = BCM2XXX
  136. return linux_id
  137. def __getattr__(self, attr):
  138. """
  139. Detect whether the given attribute is the currently-detected chip. See
  140. list of constants at the top of this module for available options.
  141. """
  142. if self.id == attr:
  143. return True
  144. return False