1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
|
# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
`adafruit_platformdetect.chip`
================================================================================
Attempt detection of current chip / CPU
* Author(s): Melissa LeBlanc-Williams
Implementation Notes
--------------------
**Software and Dependencies:**
* Linux and Python 3.7 or Higher
"""
import os
import sys
try:
from typing import Optional
except ImportError:
pass
from adafruit_platformdetect.constants import chips
__version__ = "0.0.0+auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PlatformDetect.git"
class Chip:
"""Attempt detection of current chip / CPU."""
def __init__(self, detector) -> None:
self.detector = detector
self._chip_id = None
# pylint: disable=invalid-name,too-many-branches,too-many-return-statements
@property
def id(
self,
) -> Optional[str]:
"""Return a unique id for the detected chip, if any."""
# There are some times we want to trick the platform detection
# say if a raspberry pi doesn't have the right ID, or for testing
# Caching
if self._chip_id:
return self._chip_id
if getattr(os, "environ", None) is not None:
try:
return os.environ["BLINKA_FORCECHIP"]
except KeyError: # no forced chip, continue with testing!
pass
# Special cases controlled by environment var
if os.environ.get("BLINKA_FT232H"):
from pyftdi.usbtools import UsbTools
# look for it based on PID/VID
count = len(UsbTools.find_all([(0x0403, 0x6014)]))
if count == 0:
raise RuntimeError(
"BLINKA_FT232H environment variable "
+ "set, but no FT232H device found"
)
self._chip_id = chips.FT232H
return self._chip_id
if os.environ.get("BLINKA_FT2232H"):
from pyftdi.usbtools import UsbTools
# look for it based on PID/VID
count = len(UsbTools.find_all([(0x0403, 0x6010)]))
if count == 0:
raise RuntimeError(
"BLINKA_FT2232H environment variable "
+ "set, but no FT2232H device found"
)
self._chip_id = chips.FT2232H
return self._chip_id
if os.environ.get("BLINKA_FT4232H"):
from pyftdi.usbtools import UsbTools
# look for it based on PID/VID
count = len(UsbTools.find_all([(0x0403, 0x6011)]))
if count == 0:
raise RuntimeError(
"BLINKA_FT4232H environment variable "
+ "set, but no FT4232H device found"
)
self._chip_id = chips.FT4232H
return self._chip_id
if os.environ.get("BLINKA_MCP2221"):
import hid
# look for it based on PID/VID
for dev in hid.enumerate():
if dev["vendor_id"] == 0x04D8 and dev["product_id"] == 0x00DD:
self._chip_id = chips.MCP2221
return self._chip_id
raise RuntimeError(
"BLINKA_MCP2221 environment variable "
+ "set, but no MCP2221 device found"
)
if os.environ.get("BLINKA_SPIDRIVER"):
self._chip_id = chips.SPIDRIVER
return self._chip_id
if os.environ.get("BLINKA_OS_AGNOSTIC"):
# we don't need to look for this chip, it's just a flag
self._chip_id = chips.OS_AGNOSTIC
return self._chip_id
if os.environ.get("BLINKA_U2IF"):
import hid
# look for it based on PID/VID
for dev in hid.enumerate():
vendor = dev["vendor_id"]
product = dev["product_id"]
# NOTE: If any products are added here, they need added
# to _rp2040_u2if_id() in board.py as well.
# pylint: disable=too-many-boolean-expressions
if (
(
# Raspberry Pi Pico
# Radxa X4
vendor in (0xCAFE, 0xCAFF)
and product == 0x4005
)
or (
# Waveshare RP2040 One
vendor == 0x2E8A
and product == 0x103A
)
or (
# Feather RP2040
# Itsy Bitsy RP2040
# QT Py RP2040
# QT2040 Trinkey
# MacroPad RP2040
# Feather RP2040 ThinkInk
# Feather RP2040 RFM
# Feather RP2040 CAN Bus
vendor == 0x239A
and product
in (
0x00F1,
0x00FD,
0x00F7,
0x0109,
0x0107,
0x812C,
0x812E,
0x8130,
0x0105,
)
)
):
self._chip_id = chips.RP2040_U2IF
return self._chip_id
raise RuntimeError(
"BLINKA_U2IF environment variable "
+ "set, but no compatible device found"
)
if os.environ.get("BLINKA_GREATFET"):
import usb
if usb.core.find(idVendor=0x1D50, idProduct=0x60E6) is not None:
self._chip_id = chips.LPC4330
return self._chip_id
raise RuntimeError(
"BLINKA_GREATFET environment variable "
+ "set, but no GreatFET device found"
)
if os.environ.get("BLINKA_NOVA"):
self._chip_id = chips.BINHO
return self._chip_id
platform = sys.platform
if platform in ("linux", "linux2"):
self._chip_id = self._linux_id()
return self._chip_id
if platform == "esp8266":
self._chip_id = chips.ESP8266
return self._chip_id
if platform == "samd21":
self._chip_id = chips.SAMD21
return self._chip_id
if platform == "pyboard":
self._chip_id = chips.STM32F405
return self._chip_id
if platform == "rp2":
self._chip_id = chips.RP2040
return self._chip_id
# nothing found!
return None
# pylint: enable=invalid-name
def _linux_id(self) -> Optional[str]:
# pylint: disable=too-many-branches,too-many-statements
# pylint: disable=too-many-return-statements
"""Attempt to detect the CPU on a computer running the Linux kernel."""
if self.detector.check_dt_compatible_value("beagle,am67a-beagley-ai"):
return chips.AM67A
if self.detector.check_dt_compatible_value("ti,am625"):
return chips.AM625X
if self.detector.check_dt_compatible_value("ti,am654"):
return chips.AM65XX
if self.detector.check_dt_compatible_value("ti,am652"):
return chips.AM65XX
if self.detector.check_dt_compatible_value("sun4i-a10"):
return chips.A10
if self.detector.check_dt_compatible_value("sun7i-a20"):
return chips.A20
if self.detector.check_dt_compatible_value("amlogic,g12a"):
return chips.S905Y2
if self.detector.check_dt_compatible_value("amlogic, g12a"):
return chips.S905X3
if self.detector.check_dt_compatible_value("sun8i-h3"):
return chips.H3
if self.detector.check_dt_compatible_value("qcom,apq8016"):
return chips.APQ8016
if self.detector.check_dt_compatible_value("fu500"):
return chips.HFU540
if self.detector.check_dt_compatible_value("sun20iw1p1"):
return chips.C906
# Older Builds
if self.detector.check_dt_compatible_value("sifive"):
return chips.JH71X0
# Newer Builds
if self.detector.check_dt_compatible_value("jh7100"):
return chips.JH71X0
if self.detector.check_dt_compatible_value("jh7110"):
return chips.JH7110
if self.detector.check_dt_compatible_value("sun8i-a33"):
return chips.A33
if self.detector.check_dt_compatible_value("rockchip,rk3308"):
return chips.RK3308
if self.detector.check_dt_compatible_value("radxa,rock-4c-plus"):
return chips.RK3399_T
if self.detector.check_dt_compatible_value("rockchip,rk3399pro"):
return chips.RK3399PRO
if self.detector.check_dt_compatible_value("rockchip,rk3399"):
return chips.RK3399
if self.detector.check_dt_compatible_value("rockchip,rk3288"):
return chips.RK3288
if self.detector.check_dt_compatible_value("rockchip,rk3328"):
return chips.RK3328
if self.detector.check_dt_compatible_value("rockchip,rk3566"):
return chips.RK3566
if self.detector.check_dt_compatible_value("rockchip,rk3568"):
return chips.RK3568
if self.detector.check_dt_compatible_value("rockchip,rk3588s"):
return chips.RK3588S
if self.detector.check_dt_compatible_value("rockchip,rk3588"):
return chips.RK3588
if self.detector.check_dt_compatible_value("rockchip,rv1106"):
return chips.RV1106
if self.detector.check_dt_compatible_value("rockchip,rv1103"):
return chips.RV1103
if self.detector.check_dt_compatible_value("amlogic,a311d"):
return chips.A311D
if self.detector.check_dt_compatible_value("st,stm32mp157"):
return chips.STM32MP157
if self.detector.check_dt_compatible_value("st,stm32mp153"):
return chips.STM32MP157DAA1
if self.detector.check_dt_compatible_value("sun50i-a64"):
return chips.A64
if self.detector.check_dt_compatible_value("sun50i-h5"):
return chips.H5
if self.detector.check_dt_compatible_value("sun50i-h618"):
return chips.H618
if self.detector.check_dt_compatible_value("sun50i-h616"):
return chips.H616
if self.detector.check_dt_compatible_value("sun50iw9"):
return chips.H616
if self.detector.check_dt_compatible_value("sun50i-h6"):
return chips.H6
if self.detector.check_dt_compatible_value("sun55iw3"):
return chips.T527
if self.detector.check_dt_compatible_value("spacemit,k1-x"):
return chips.K1
if self.detector.check_dt_compatible_value("renesas,r9a09g056"):
return chips.RZV2N
if self.detector.check_dt_compatible_value("renesas,r9a09g057"):
return chips.RZV2H
if self.detector.check_dt_compatible_value("mediatek,mt8167"):
return chips.MT8167
if self.detector.check_dt_compatible_value("imx6ull"):
return chips.IMX6ULL
if self.detector.check_dt_compatible_value("ti,j721e"):
return chips.TDA4VM
if self.detector.check_dt_compatible_value("sun20i-d1"):
return chips.D1_RISCV
if self.detector.check_dt_compatible_value("imx8mp"):
return chips.IMX8MP
if self.detector.check_dt_compatible_value("libretech,aml-s905x-cc"):
return chips.S905X
if self.detector.check_dt_compatible_value("light-lpi4a"):
return chips.TH1520
if self.detector.check_dt_compatible_value("hobot,x3"):
return chips.SUNRISE_X3
if self.detector.check_dt_compatible_value("Horizon, x5"):
return chips.SUNRISE_X5
if self.detector.check_dt_compatible_value("particle,tachyon"):
return chips.QCM6490
linux_id = None
hardware = self.detector.get_cpuinfo_field("Hardware")
if hardware is None:
vendor_id = self.detector.get_cpuinfo_field("vendor_id")
if vendor_id == "AuthenticAMD":
model_name = self.detector.get_cpuinfo_field("model name").upper()
if "RYZEN EMBEDDED V1202B" in model_name:
linux_id = chips.RYZEN_V1202B
if "RYZEN EMBEDDED V1605B" in model_name:
linux_id = chips.RYZEN_V1605B
else:
linux_id = chips.GENERIC_X86
## print("linux_id = ", linux_id)
elif vendor_id == "GenuineIntel":
model_name = self.detector.get_cpuinfo_field("model name").upper()
## print('model_name =', model_name)
if "N3710" in model_name:
linux_id = chips.PENTIUM_N3710
if "N5105" in model_name:
linux_id = chips.CELERON_N5105
elif "X5-Z8350" in model_name:
linux_id = chips.ATOM_X5_Z8350
elif "J4105" in model_name:
linux_id = chips.ATOM_J4105
else:
linux_id = chips.GENERIC_X86
## print("linux_id = ", linux_id)
compatible = self.detector.get_device_compatible()
if compatible and "tegra" in compatible:
compats = compatible.split("\x00")
if "nvidia,tegra210" in compats:
linux_id = chips.T210
elif "nvidia,tegra186" in compats:
linux_id = chips.T186
elif "nvidia,tegra194" in compats:
linux_id = chips.T194
elif "nvidia,tegra234" in compats:
linux_id = chips.T234
elif "nvidia,tegra264" in compats:
linux_id = chips.T264
if compatible and "imx8m" in compatible:
linux_id = chips.IMX8MX
if compatible and "odroid-c2" in compatible:
linux_id = chips.S905
if compatible and "amlogic" in compatible:
compatible_list = (
compatible.replace("\x00", ",").replace(" ", "").split(",")
)
if "g12a" in compatible_list:
# 'sm1' is correct for S905X3, but some kernels use 'g12a'
return chips.S905X3
if "g12b" in compatible_list:
return chips.S922X
if "sm1" in compatible_list:
return chips.S905X3
if "vim3amlogic" in compatible_list:
return chips.A311D
if compatible and "sun50i-a64" in compatible:
linux_id = chips.A64
if compatible and "sun50i-h6" in compatible:
linux_id = chips.H6
if compatible and "sun50i-h5" in compatible:
linux_id = chips.H5
if compatible and "odroid-xu4" in compatible:
linux_id = chips.EXYNOS5422
if compatible and "cvitek,cv180x" in compatible:
linux_id = chips.CV1800B
if compatible and "xlnx,zynqmp" in compatible:
linux_id = chips.ZYNQMP
cpu_model = self.detector.get_cpuinfo_field("cpu model")
if cpu_model is not None:
if "MIPS 24Kc" in cpu_model:
linux_id = chips.MIPS24KC
elif "MIPS 24KEc" in cpu_model:
linux_id = chips.MIPS24KEC
# we still haven't identified the hardware, so
# convert it to a list and let the remaining
# conditions attempt.
if not linux_id:
hardware = [
entry.replace("\x00", "") for entry in compatible.split(",")
]
if not linux_id:
if "AM33XX" in hardware:
linux_id = chips.AM33XX
elif "DRA74X" in hardware:
linux_id = chips.DRA74X
elif "sun4i" in hardware:
linux_id = chips.A10
elif "sun7i" in hardware:
linux_id = chips.A20
elif "sun8i" in hardware:
linux_id = chips.SUN8I
elif "ODROIDC" in hardware:
linux_id = chips.S805
elif "ODROID-C2" in hardware:
linux_id = chips.S905
elif "ODROID-N2" in hardware:
linux_id = chips.S922X
elif "ODROID-C4" in hardware:
linux_id = chips.S905X3
elif "ODROID-XU4" in hardware:
linux_id = chips.EXYNOS5422
elif "KHADAS-VIM3" in hardware:
linux_id = chips.A311D
elif "SAMA5" in hardware:
linux_id = chips.SAMA5
elif "Pinebook" in hardware:
linux_id = chips.A64
elif "ASUS_TINKER_BOARD" in hardware:
linux_id = chips.RK3288
elif "Xilinx Zynq" in hardware:
compatible = self.detector.get_device_compatible()
if compatible and "xlnx,zynq-7000" in compatible:
linux_id = chips.ZYNQ7000
else:
if isinstance(hardware, str):
if hardware.upper() in chips.BCM_RANGE:
linux_id = chips.BCM2XXX
elif isinstance(hardware, list):
if {model.upper() for model in hardware} & chips.BCM_RANGE:
linux_id = chips.BCM2XXX
return linux_id
def __getattr__(self, attr: str) -> bool:
"""
Detect whether the given attribute is the currently-detected chip. See
list of constants at the top of this module for available options.
"""
if attr == "id":
raise AttributeError() # Avoid infinite recursion
if self.id == attr:
return True
return False
|