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.

262 lines
9.7 KiB

4 years ago
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. self._chip_id = None
  43. @property
  44. def id(
  45. self,
  46. ): # pylint: disable=invalid-name,too-many-branches,too-many-return-statements
  47. """Return a unique id for the detected chip, if any."""
  48. # There are some times we want to trick the platform detection
  49. # say if a raspberry pi doesn't have the right ID, or for testing
  50. # Caching
  51. if self._chip_id:
  52. return self._chip_id
  53. try:
  54. return os.environ["BLINKA_FORCECHIP"]
  55. except KeyError: # no forced chip, continue with testing!
  56. pass
  57. # Special cases controlled by environment var
  58. if os.environ.get("BLINKA_FT232H"):
  59. from pyftdi.usbtools import UsbTools
  60. # look for it based on PID/VID
  61. count = len(UsbTools.find_all([(0x0403, 0x6014)]))
  62. if count == 0:
  63. raise RuntimeError(
  64. "BLINKA_FT232H environment variable "
  65. + "set, but no FT232H device found"
  66. )
  67. self._chip_id = chips.FT232H
  68. return self._chip_id
  69. if os.environ.get("BLINKA_MCP2221"):
  70. import hid
  71. # look for it based on PID/VID
  72. for dev in hid.enumerate():
  73. if dev["vendor_id"] == 0x04D8 and dev["product_id"] == 0x00DD:
  74. self._chip_id = chips.MCP2221
  75. return self._chip_id
  76. raise RuntimeError(
  77. "BLINKA_MCP2221 environment variable "
  78. + "set, but no MCP2221 device found"
  79. )
  80. if os.environ.get("BLINKA_GREATFET"):
  81. import usb
  82. if usb.core.find(idVendor=0x1D50, idProduct=0x60E6) is not None:
  83. self._chip_id = chips.LPC4330
  84. return self._chip_id
  85. raise RuntimeError(
  86. "BLINKA_GREATFET environment variable "
  87. + "set, but no GreatFET device found"
  88. )
  89. if os.environ.get("BLINKA_NOVA"):
  90. self._chip_id = chips.BINHO
  91. return self._chip_id
  92. platform = sys.platform
  93. if platform in ("linux", "linux2"):
  94. self._chip_id = self._linux_id()
  95. return self._chip_id
  96. if platform == "esp8266":
  97. self._chip_id = chips.ESP8266
  98. return self._chip_id
  99. if platform == "samd21":
  100. self._chip_id = chips.SAMD21
  101. return self._chip_id
  102. if platform == "pyboard":
  103. self._chip_id = chips.STM32F405
  104. return self._chip_id
  105. # nothing found!
  106. return None
  107. # pylint: enable=invalid-name
  108. def _linux_id(self):
  109. # pylint: disable=too-many-branches,too-many-statements
  110. # pylint: disable=too-many-return-statements
  111. """Attempt to detect the CPU on a computer running the Linux kernel."""
  112. if self.detector.check_dt_compatible_value("qcom,apq8016"):
  113. return chips.APQ8016
  114. if self.detector.check_dt_compatible_value("fu500"):
  115. return chips.HFU540
  116. if self.detector.check_dt_compatible_value("sun8i-a33"):
  117. return chips.A33
  118. if self.detector.check_dt_compatible_value("rockchip,rk3308"):
  119. return chips.RK3308
  120. if self.detector.check_dt_compatible_value("rockchip,rk3288"):
  121. return chips.RK3288
  122. if self.detector.check_dt_compatible_value("st,stm32mp157"):
  123. return chips.STM32MP157
  124. linux_id = None
  125. hardware = self.detector.get_cpuinfo_field("Hardware")
  126. if hardware is None:
  127. vendor_id = self.detector.get_cpuinfo_field("vendor_id")
  128. if vendor_id == "AuthenticAMD":
  129. model_name = self.detector.get_cpuinfo_field("model name").upper()
  130. if "RYZEN EMBEDDED V1202B" in model_name:
  131. linux_id = chips.RYZEN_V1202B
  132. if "RYZEN EMBEDDED V1605B" in model_name:
  133. linux_id = chips.RYZEN_V1605B
  134. elif vendor_id == "GenuineIntel":
  135. model_name = self.detector.get_cpuinfo_field("model name").upper()
  136. ## print('model_name =', model_name)
  137. if "N3710" in model_name:
  138. linux_id = chips.PENTIUM_N3710
  139. else:
  140. linux_id = chips.GENERIC_X86
  141. ## print("linux_id = ", linux_id)
  142. compatible = self.detector.get_device_compatible()
  143. if compatible and "tegra" in compatible:
  144. compats = compatible.split("\x00")
  145. if "nvidia,tegra210" in compats:
  146. linux_id = chips.T210
  147. elif "nvidia,tegra186" in compats:
  148. linux_id = chips.T186
  149. elif "nvidia,tegra194" in compats:
  150. linux_id = chips.T194
  151. if compatible and "imx8m" in compatible:
  152. linux_id = chips.IMX8MX
  153. if compatible and "odroid-c2" in compatible:
  154. linux_id = chips.S905
  155. if compatible and "amlogic" in compatible:
  156. compatible_list = (
  157. compatible.replace("\x00", ",").replace(" ", "").split(",")
  158. )
  159. if "g12a" in compatible_list:
  160. # 'sm1' is correct for S905X3, but some kernels use 'g12a'
  161. return chips.S905X3
  162. if "g12b" in compatible_list:
  163. return chips.S922X
  164. if "sm1" in compatible_list:
  165. return chips.S905X3
  166. if compatible and "sun50i-a64" in compatible:
  167. linux_id = chips.A64
  168. if compatible and "odroid-xu4" in compatible:
  169. linux_id = chips.EXYNOS5422
  170. cpu_model = self.detector.get_cpuinfo_field("cpu model")
  171. if cpu_model is not None:
  172. if "MIPS 24Kc" in cpu_model:
  173. linux_id = chips.MIPS24KC
  174. elif "MIPS 24KEc" in cpu_model:
  175. linux_id = chips.MIPS24KEC
  176. # we still haven't identified the hardware, so
  177. # convert it to a list and let the remaining
  178. # conditions attempt.
  179. if not linux_id:
  180. hardware = [
  181. entry.replace("\x00", "") for entry in compatible.split(",")
  182. ]
  183. if not linux_id:
  184. if "AM33XX" in hardware:
  185. linux_id = chips.AM33XX
  186. elif "sun8i" in hardware:
  187. linux_id = chips.SUN8I
  188. elif "ODROIDC" in hardware:
  189. linux_id = chips.S805
  190. elif "ODROID-C2" in hardware:
  191. linux_id = chips.S905
  192. elif "ODROID-N2" in hardware:
  193. linux_id = chips.S922X
  194. elif "ODROID-C4" in hardware:
  195. linux_id = chips.S905X3
  196. elif "ODROID-XU4" in hardware:
  197. linux_id = chips.EXYNOS5422
  198. elif "SAMA5" in hardware:
  199. linux_id = chips.SAMA5
  200. elif "Pinebook" in hardware:
  201. linux_id = chips.A64
  202. elif "sun50iw1p1" in hardware:
  203. linux_id = chips.A64
  204. elif "ASUS_TINKER_BOARD" in hardware:
  205. linux_id = chips.RK3288
  206. elif "Xilinx Zynq" in hardware:
  207. compatible = self.detector.get_device_compatible()
  208. if compatible and "xlnx,zynq-7000" in compatible:
  209. linux_id = chips.ZYNQ7000
  210. else:
  211. if isinstance(hardware, str):
  212. if hardware.upper() in chips.BCM_RANGE:
  213. linux_id = chips.BCM2XXX
  214. elif isinstance(hardware, list):
  215. if {model.upper() for model in hardware} & chips.BCM_RANGE:
  216. linux_id = chips.BCM2XXX
  217. return linux_id
  218. def __getattr__(self, attr):
  219. """
  220. Detect whether the given attribute is the currently-detected chip. See
  221. list of constants at the top of this module for available options.
  222. """
  223. if self.id == attr:
  224. return True
  225. return False