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.

234 lines
8.6 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. # The MIT License (MIT)
  2. #
  3. # Copyright (c) 2020 Melissa LeBlanc-Williams for Adafruit Industries
  4. #
  5. # Permission is hereby granted, free of charge, to any person obtaining a copy
  6. # of this software and associated documentation files (the "Software"), to deal
  7. # in the Software without restriction, including without limitation the rights
  8. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. # copies of the Software, and to permit persons to whom the Software is
  10. # furnished to do so, subject to the following conditions:
  11. #
  12. # The above copyright notice and this permission notice shall be included in
  13. # all copies or substantial portions of the Software.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. # THE SOFTWARE.
  22. """
  23. `adafruit_platformdetect.chip`
  24. ================================================================================
  25. Attempt detection of current chip / CPU
  26. * Author(s): Melissa LeBlanc-Williams
  27. Implementation Notes
  28. --------------------
  29. **Software and Dependencies:**
  30. * Linux and Python 3.5 or Higher
  31. """
  32. # imports
  33. import os
  34. import sys
  35. from adafruit_platformdetect.constants import chips
  36. __version__ = "0.0.0-auto.0"
  37. __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PlatformDetect.git"
  38. class Chip:
  39. """Attempt detection of current chip / CPU."""
  40. def __init__(self, detector):
  41. self.detector = detector
  42. @property
  43. def id(
  44. self,
  45. ): # pylint: disable=invalid-name,too-many-branches,too-many-return-statements
  46. """Return a unique id for the detected chip, if any."""
  47. # There are some times we want to trick the platform detection
  48. # say if a raspberry pi doesn't have the right ID, or for testing
  49. try:
  50. return os.environ["BLINKA_FORCECHIP"]
  51. except KeyError: # no forced chip, continue with testing!
  52. pass
  53. # Special cases controlled by environment var
  54. if os.environ.get("BLINKA_FT232H"):
  55. from pyftdi.usbtools import UsbTools
  56. # look for it based on PID/VID
  57. count = len(UsbTools.find_all([(0x0403, 0x6014)]))
  58. if count == 0:
  59. raise RuntimeError(
  60. "BLINKA_FT232H environment variable "
  61. + "set, but no FT232H device found"
  62. )
  63. return chips.FT232H
  64. if os.environ.get("BLINKA_MCP2221"):
  65. import hid
  66. # look for it based on PID/VID
  67. for dev in hid.enumerate():
  68. if dev["vendor_id"] == 0x04D8 and dev["product_id"] == 0x00DD:
  69. return chips.MCP2221
  70. raise RuntimeError(
  71. "BLINKA_MCP2221 environment variable "
  72. + "set, but no MCP2221 device found"
  73. )
  74. if os.environ.get("BLINKA_GREATFET"):
  75. import usb
  76. if usb.core.find(idVendor=0x1D50, idProduct=0x60E6) is not None:
  77. return chips.LPC4330
  78. raise RuntimeError(
  79. "BLINKA_GREATFET environment variable "
  80. + "set, but no GreatFET device found"
  81. )
  82. if os.environ.get("BLINKA_NOVA"):
  83. return chips.BINHO
  84. platform = sys.platform
  85. if platform in ("linux", "linux2"):
  86. return self._linux_id()
  87. if platform == "esp8266":
  88. return chips.ESP8266
  89. if platform == "samd21":
  90. return chips.SAMD21
  91. if platform == "pyboard":
  92. return chips.STM32
  93. # nothing found!
  94. return None
  95. # pylint: enable=invalid-name
  96. def _linux_id(self):
  97. # pylint: disable=too-many-branches,too-many-statements
  98. # pylint: disable=too-many-return-statements
  99. """Attempt to detect the CPU on a computer running the Linux kernel."""
  100. if self.detector.check_dt_compatible_value("qcom,apq8016"):
  101. return chips.APQ8016
  102. if self.detector.check_dt_compatible_value("fu500"):
  103. return chips.HFU540
  104. if self.detector.check_dt_compatible_value("sun8i-a33"):
  105. return chips.A33
  106. if self.detector.check_dt_compatible_value("rockchip,rk3308"):
  107. return chips.RK3308
  108. linux_id = None
  109. hardware = self.detector.get_cpuinfo_field("Hardware")
  110. if hardware is None:
  111. vendor_id = self.detector.get_cpuinfo_field("vendor_id")
  112. if vendor_id == "AuthenticAMD":
  113. model_name = self.detector.get_cpuinfo_field("model name").upper()
  114. if "RYZEN EMBEDDED V1605B" in model_name:
  115. linux_id = chips.RYZEN_V1605B
  116. else:
  117. linux_id = chips.GENERIC_X86
  118. elif vendor_id == "GenuineIntel":
  119. linux_id = chips.GENERIC_X86
  120. compatible = self.detector.get_device_compatible()
  121. if compatible and "tegra" in compatible:
  122. compats = compatible.split("\x00")
  123. if "nvidia,tegra210" in compats:
  124. linux_id = chips.T210
  125. elif "nvidia,tegra186" in compats:
  126. linux_id = chips.T186
  127. elif "nvidia,tegra194" in compats:
  128. linux_id = chips.T194
  129. if compatible and "imx8m" in compatible:
  130. linux_id = chips.IMX8MX
  131. if compatible and "odroid-c2" in compatible:
  132. linux_id = chips.S905
  133. if compatible and "amlogic" in compatible:
  134. compatible_list = (
  135. compatible.replace("\x00", ",").replace(" ", "").split(",")
  136. )
  137. if "g12a" in compatible_list:
  138. # 'sm1' is correct for S905X3, but some kernels use 'g12a'
  139. return chips.S905X3
  140. if "g12b" in compatible_list:
  141. return chips.S922X
  142. if "sm1" in compatible_list:
  143. return chips.S905X3
  144. if compatible and "sun50i-a64" in compatible:
  145. linux_id = chips.A64
  146. if compatible and "odroid-xu4" in compatible:
  147. linux_id = chips.EXYNOS5422
  148. cpu_model = self.detector.get_cpuinfo_field("cpu model")
  149. if cpu_model is not None:
  150. if "MIPS 24Kc" in cpu_model:
  151. linux_id = chips.MIPS24KC
  152. elif "MIPS 24KEc" in cpu_model:
  153. linux_id = chips.MIPS24KEC
  154. # we still haven't identified the hardware, so
  155. # convert it to a list and let the remaining
  156. # conditions attempt.
  157. if not linux_id:
  158. hardware = [
  159. entry.replace("\x00", "") for entry in compatible.split(",")
  160. ]
  161. if not linux_id:
  162. if "AM33XX" in hardware:
  163. linux_id = chips.AM33XX
  164. elif "sun8i" in hardware:
  165. linux_id = chips.SUN8I
  166. elif "ODROIDC" in hardware:
  167. linux_id = chips.S805
  168. elif "ODROID-C2" in hardware:
  169. linux_id = chips.S905
  170. elif "ODROID-N2" in hardware:
  171. linux_id = chips.S922X
  172. elif "ODROID-C4" in hardware:
  173. linux_id = chips.S905X3
  174. elif "ODROID-XU4" in hardware:
  175. linux_id = chips.EXYNOS5422
  176. elif "SAMA5" in hardware:
  177. linux_id = chips.SAMA5
  178. elif "Pinebook" in hardware:
  179. linux_id = chips.A64
  180. elif "sun50iw1p1" in hardware:
  181. linux_id = chips.A64
  182. elif "Xilinx Zynq" in hardware:
  183. compatible = self.detector.get_device_compatible()
  184. if compatible and "xlnx,zynq-7000" in compatible:
  185. linux_id = chips.ZYNQ7000
  186. else:
  187. if isinstance(hardware, str):
  188. if hardware.upper() in chips.BCM_RANGE:
  189. linux_id = chips.BCM2XXX
  190. elif isinstance(hardware, list):
  191. if {model.upper() for model in hardware} & chips.BCM_RANGE:
  192. linux_id = chips.BCM2XXX
  193. return linux_id
  194. def __getattr__(self, attr):
  195. """
  196. Detect whether the given attribute is the currently-detected chip. See
  197. list of constants at the top of this module for available options.
  198. """
  199. if self.id == attr:
  200. return True
  201. return False