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.

722 lines
25 KiB

2 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
3 years ago
4 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
3 years ago
3 years ago
3 years ago
  1. # SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
  2. #
  3. # SPDX-License-Identifier: MIT
  4. """
  5. `adafruit_platformdetect.board`
  6. ================================================================================
  7. Detect boards
  8. * Author(s): Melissa LeBlanc-Williams
  9. Implementation Notes
  10. --------------------
  11. **Software and Dependencies:**
  12. * Linux and Python 3.6 or Higher
  13. """
  14. # imports
  15. import os
  16. import re
  17. from adafruit_platformdetect.constants import boards, chips
  18. __version__ = "0.0.0-auto.0"
  19. __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PlatformDetect.git"
  20. class Board:
  21. """Attempt to detect specific boards."""
  22. def __init__(self, detector):
  23. self.detector = detector
  24. self._board_id = None
  25. # pylint: disable=invalid-name, protected-access, too-many-return-statements
  26. @property
  27. def id(self):
  28. """Return a unique id for the detected board, if any."""
  29. # There are some times we want to trick the platform detection
  30. # say if a raspberry pi doesn't have the right ID, or for testing
  31. # Caching
  32. if self._board_id:
  33. return self._board_id
  34. try:
  35. return os.environ["BLINKA_FORCEBOARD"]
  36. except (AttributeError, KeyError): # no forced board, continue with testing!
  37. pass
  38. chip_id = self.detector.chip.id
  39. board_id = None
  40. if chip_id == chips.H3:
  41. board_id = self._armbian_id() or self._allwinner_variants_id()
  42. elif chip_id == chips.BCM2XXX:
  43. board_id = self._pi_id()
  44. elif chip_id == chips.AM33XX:
  45. board_id = self._beaglebone_id()
  46. elif chip_id == chips.DRA74X:
  47. board_id = self._bbai_id()
  48. elif chip_id == chips.SUN8I:
  49. board_id = self._armbian_id() or self._allwinner_variants_id()
  50. elif chip_id == chips.SAMA5:
  51. board_id = self._sama5_id()
  52. elif chip_id == chips.IMX8MX:
  53. board_id = self._imx8mx_id()
  54. elif chip_id == chips.IMX6ULL:
  55. board_id = self._imx6ull_id()
  56. elif chip_id == chips.ESP8266:
  57. board_id = boards.FEATHER_HUZZAH
  58. elif chip_id == chips.SAMD21:
  59. board_id = boards.FEATHER_M0_EXPRESS
  60. elif chip_id == chips.STM32F405:
  61. board_id = boards.PYBOARD
  62. elif chip_id == chips.RP2040:
  63. board_id = boards.RASPBERRY_PI_PICO
  64. elif chip_id == chips.S805:
  65. board_id = boards.ODROID_C1
  66. elif chip_id == chips.S905:
  67. board_id = boards.ODROID_C2
  68. elif chip_id == chips.S905X3:
  69. board_id = boards.ODROID_C4
  70. elif chip_id == chips.S922X:
  71. board_id = boards.ODROID_N2
  72. elif chip_id == chips.EXYNOS5422:
  73. board_id = boards.ODROID_XU4
  74. elif chip_id == chips.FT232H:
  75. board_id = boards.FTDI_FT232H
  76. elif chip_id == chips.FT2232H:
  77. board_id = boards.FTDI_FT2232H
  78. elif chip_id == chips.APQ8016:
  79. board_id = boards.DRAGONBOARD_410C
  80. elif chip_id in (chips.T210, chips.T186, chips.T194):
  81. board_id = self._tegra_id()
  82. elif chip_id == chips.HFU540:
  83. board_id = self._sifive_id()
  84. elif chip_id == chips.C906:
  85. board_id = self._allwinner_id()
  86. elif chip_id == chips.JH71x0:
  87. board_id = self._beaglebone_id()
  88. elif chip_id == chips.MCP2221:
  89. board_id = boards.MICROCHIP_MCP2221
  90. elif chip_id == chips.BINHO:
  91. board_id = boards.BINHO_NOVA
  92. elif chip_id == chips.LPC4330:
  93. board_id = boards.GREATFET_ONE
  94. elif chip_id == chips.MIPS24KC:
  95. board_id = boards.ONION_OMEGA
  96. elif chip_id == chips.MIPS24KEC:
  97. board_id = boards.ONION_OMEGA2
  98. elif chip_id == chips.ZYNQ7000:
  99. board_id = self._pynq_id()
  100. elif chip_id == chips.A64:
  101. board_id = self._pine64_id()
  102. elif chip_id == chips.H6:
  103. board_id = self._pine64_id() or self._armbian_id()
  104. elif chip_id == chips.H5:
  105. board_id = self._armbian_id() or self._allwinner_variants_id()
  106. elif chip_id == chips.H616:
  107. board_id = self._armbian_id() or self._allwinner_variants_id()
  108. elif chip_id == chips.A33:
  109. board_id = self._clockwork_pi_id()
  110. elif chip_id == chips.RK3308:
  111. board_id = self._rock_pi_id()
  112. elif chip_id == chips.RK3399:
  113. board_id = self._rock_pi_id()
  114. elif chip_id == chips.ATOM_X5_Z8350:
  115. board_id = self._rock_pi_id()
  116. elif chip_id == chips.RK3288:
  117. board_id = self._asus_tinker_board_id()
  118. elif chip_id == chips.RK3328:
  119. board_id = self._rock_pi_id()
  120. elif chip_id == chips.RYZEN_V1605B:
  121. board_id = self._udoo_id()
  122. elif chip_id == chips.PENTIUM_N3710:
  123. board_id = self._udoo_id()
  124. elif chip_id == chips.STM32MP157:
  125. board_id = self._stm32mp1_id()
  126. elif chip_id == chips.MT8167:
  127. board_id = boards.CORAL_EDGE_TPU_DEV_MINI
  128. elif chip_id == chips.RP2040_U2IF:
  129. board_id = self._rp2040_u2if_id()
  130. elif chip_id == chips.GENERIC_X86:
  131. board_id = boards.GENERIC_LINUX_PC
  132. elif chip_id == chips.TDA4VM:
  133. board_id = self._tisk_id()
  134. self._board_id = board_id
  135. return board_id
  136. # pylint: enable=invalid-name
  137. def _pi_id(self):
  138. """Try to detect id of a Raspberry Pi."""
  139. # Check for Pi boards:
  140. pi_rev_code = self._pi_rev_code()
  141. if pi_rev_code:
  142. for model, codes in boards._PI_REV_CODES.items():
  143. if pi_rev_code in codes:
  144. return model
  145. # We may be on a non-Raspbian OS, so try to lazily determine
  146. # the version based on `get_device_model`
  147. else:
  148. pi_model = self.detector.get_device_model()
  149. if pi_model:
  150. pi_model = pi_model.upper().replace(" ", "_")
  151. if "PLUS" in pi_model:
  152. re_model = re.search(r"(RASPBERRY_PI_\d).*([AB]_*)(PLUS)", pi_model)
  153. elif "CM" in pi_model: # untested for Compute Module
  154. re_model = re.search(r"(RASPBERRY_PI_CM)(\d)", pi_model)
  155. else: # untested for non-plus models
  156. re_model = re.search(r"(RASPBERRY_PI_\d).*([AB])", pi_model)
  157. if re_model:
  158. pi_model = "".join(re_model.groups())
  159. available_models = boards._PI_REV_CODES.keys()
  160. for model in available_models:
  161. if model == pi_model:
  162. return model
  163. return None
  164. def _pi_rev_code(self):
  165. """Attempt to find a Raspberry Pi revision code for this board."""
  166. # 2708 is Pi 1
  167. # 2709 is Pi 2
  168. # 2835 is Pi 3 (or greater) on 4.9.x kernel
  169. # Anything else is not a Pi.
  170. if self.detector.chip.id != chips.BCM2XXX:
  171. # Something else, not a Pi.
  172. return None
  173. rev = self.detector.get_cpuinfo_field("Revision")
  174. if rev is not None:
  175. return rev
  176. try:
  177. with open("/proc/device-tree/system/linux,revision", "rb") as revision:
  178. rev_bytes = revision.read()
  179. if rev_bytes[:1] == b"\x00":
  180. rev_bytes = rev_bytes[1:]
  181. return rev_bytes.hex()
  182. except FileNotFoundError:
  183. return None
  184. # pylint: disable=no-self-use
  185. def _beaglebone_id(self):
  186. """Try to detect id of a Beaglebone."""
  187. board_value = self.detector.get_device_compatible()
  188. # Older Builds
  189. if "freedom-u74-arty" in board_value:
  190. return boards.BEAGLEV_STARLIGHT
  191. # Newer Builds
  192. if "beaglev-starlight" in board_value:
  193. return boards.BEAGLEV_STARLIGHT
  194. try:
  195. with open("/sys/bus/nvmem/devices/0-00500/nvmem", "rb") as eeprom:
  196. eeprom_bytes = eeprom.read(16)
  197. except FileNotFoundError:
  198. return None
  199. if eeprom_bytes[:4] != b"\xaaU3\xee":
  200. return None
  201. # special condition for BeagleBone Green rev. 1A
  202. # refer to GitHub issue #57 in this repo for more info
  203. if eeprom_bytes == b"\xaaU3\xeeA335BNLT\x1a\x00\x00\x00":
  204. return boards.BEAGLEBONE_GREEN
  205. id_string = eeprom_bytes[4:].decode("ascii")
  206. for model, bb_ids in boards._BEAGLEBONE_BOARD_IDS.items():
  207. for bb_id in bb_ids:
  208. if id_string == bb_id[1]:
  209. return model
  210. board_value = self.detector.get_armbian_release_field("BOARD")
  211. return None
  212. # pylint: enable=no-self-use
  213. def _bbai_id(self):
  214. """Try to detect id of a Beaglebone AI related board."""
  215. board_value = self.detector.get_device_model()
  216. if "BeagleBone AI" in board_value:
  217. return boards.BEAGLEBONE_AI
  218. return None
  219. def _tisk_id(self):
  220. """Try to detect the id of aarch64 board."""
  221. compatible = self.detector.get_device_compatible()
  222. print(compatible)
  223. if not compatible:
  224. return None
  225. compats = compatible.split("\x00")
  226. for board_id, board_compats in boards._TI_SK_BOARD_IDS:
  227. if any(v in compats for v in board_compats):
  228. return board_id
  229. return None
  230. # pylint: disable=too-many-return-statements
  231. def _armbian_id(self):
  232. """Check whether the current board is an OrangePi board."""
  233. board_value = self.detector.get_armbian_release_field("BOARD")
  234. board = None
  235. if board_value == "orangepipc":
  236. board = boards.ORANGE_PI_PC
  237. elif board_value == "orangepi-r1":
  238. board = boards.ORANGE_PI_R1
  239. elif board_value == "orangepizero":
  240. board = boards.ORANGE_PI_ZERO
  241. elif board_value == "orangepione":
  242. board = boards.ORANGE_PI_ONE
  243. elif board_value == "orangepilite":
  244. board = boards.ORANGE_PI_LITE
  245. elif board_value == "orangepiplus2e":
  246. board = boards.ORANGE_PI_PLUS_2E
  247. elif board_value == "orangepipcplus":
  248. board = boards.ORANGE_PI_PC_PLUS
  249. elif board_value == "pinebook-a64":
  250. board = boards.PINEBOOK
  251. elif board_value == "pineH64":
  252. board = boards.PINEH64
  253. elif board_value == "orangepi2":
  254. board = boards.ORANGE_PI_2
  255. elif board_value == "orangepi3":
  256. board = boards.ORANGE_PI_3
  257. elif board_value == "bananapim2zero":
  258. board = boards.BANANA_PI_M2_ZERO
  259. elif board_value == "orangepizeroplus2-h5":
  260. board = boards.ORANGE_PI_ZERO_PLUS_2H5
  261. elif board_value == "orangepizeroplus":
  262. board = boards.ORANGE_PI_ZERO_PLUS
  263. elif board_value == "orangepizero2":
  264. board = boards.ORANGE_PI_ZERO_2
  265. elif board_value == "nanopiair":
  266. board = boards.NANOPI_NEO_AIR
  267. elif board_value == "nanopiduo2":
  268. board = boards.NANOPI_DUO2
  269. elif board_value == "nanopineo":
  270. board = boards.NANOPI_NEO
  271. return board
  272. # pylint: enable=too-many-return-statements
  273. # pylint: enable=too-many-return-statements
  274. def _sama5_id(self):
  275. """Check what type sama5 board."""
  276. board_value = self.detector.get_device_model()
  277. if "Giant Board" in board_value:
  278. return boards.GIANT_BOARD
  279. return None
  280. def _stm32mp1_id(self):
  281. """Check what type stm32mp1 board."""
  282. board_value = self.detector.get_device_model()
  283. if "STM32MP157C-DK2" in board_value:
  284. return boards.STM32MP157C_DK2
  285. if "LubanCat" in board_value:
  286. return boards.LUBANCAT_STM32MP157
  287. if "OSD32MP1-BRK" in board_value:
  288. return boards.OSD32MP1_BRK
  289. if "OSD32MP1-RED" in board_value:
  290. return boards.OSD32MP1_RED
  291. return None
  292. def _imx8mx_id(self):
  293. """Check what type iMX8M board."""
  294. board_value = self.detector.get_device_model()
  295. if "FSL i.MX8MM DDR4 EVK" in board_value:
  296. return boards.MAAXBOARD_MINI
  297. if "Freescale i.MX8MQ EVK" in board_value:
  298. return boards.MAAXBOARD
  299. if "Phanbell" in board_value:
  300. return boards.CORAL_EDGE_TPU_DEV
  301. return None
  302. def _imx6ull_id(self):
  303. """Check what type iMX6ULL board."""
  304. board_value = self.detector.get_device_model()
  305. if "LubanCat" in board_value or "Embedfire" in board_value:
  306. return boards.LUBANCAT_IMX6ULL
  307. return None
  308. def _tegra_id(self):
  309. """Try to detect the id of aarch64 board."""
  310. compatible = self.detector.get_device_compatible()
  311. if not compatible:
  312. return None
  313. compats = compatible.split("\x00")
  314. for board_id, board_compats in boards._JETSON_IDS:
  315. if any(v in compats for v in board_compats):
  316. return board_id
  317. return None
  318. def _sifive_id(self):
  319. """Try to detect the id for Sifive RISCV64 board."""
  320. board_value = self.detector.get_device_model()
  321. if "hifive-unleashed-a00" in board_value:
  322. return boards.SIFIVE_UNLEASHED
  323. return None
  324. def _allwinner_id(self):
  325. """Try to detect the id for Allwiner D1 board."""
  326. board_value = self.detector.get_device_model()
  327. if "sun20iw1p1" in board_value:
  328. return boards.ALLWINER_D1
  329. return None
  330. def _pine64_id(self):
  331. """Try to detect the id for Pine64 board or device."""
  332. board_value = self.detector.get_device_model()
  333. board = None
  334. if "pine64" in board_value.lower():
  335. board = boards.PINE64
  336. elif "pine h64" in board_value.lower():
  337. board = boards.PINEH64
  338. elif "pinebook" in board_value.lower():
  339. board = boards.PINEBOOK
  340. elif "pinephone" in board_value.lower():
  341. board = boards.PINEPHONE
  342. elif "sopine" in board_value.lower():
  343. board = boards.SOPINE
  344. return board
  345. # pylint: disable=no-self-use
  346. def _pynq_id(self):
  347. """Try to detect the id for Xilinx PYNQ boards."""
  348. try:
  349. with open(
  350. "/proc/device-tree/chosen/pynq_board", "r", encoding="utf-8"
  351. ) as board_file:
  352. board_model = board_file.read()
  353. match = board_model.upper().replace("-", "_").rstrip("\x00")
  354. for model in boards._PYNQ_IDS:
  355. if model == match:
  356. return model
  357. return None
  358. except FileNotFoundError:
  359. return None
  360. def _rock_pi_id(self):
  361. """Check what type of Rock Pi board."""
  362. board_value = self.detector.get_device_model()
  363. board = None
  364. if board_value and "ROCK Pi S" in board_value:
  365. board = boards.ROCK_PI_S
  366. if board_value and "ROCK PI 4" in board_value.upper():
  367. board = boards.ROCK_PI_4
  368. if board_value and "ROCK PI E" in board_value.upper():
  369. board = boards.ROCK_PI_E
  370. if self.detector.check_board_name_value() == "ROCK Pi X":
  371. board = boards.ROCK_PI_X
  372. return board
  373. def _clockwork_pi_id(self):
  374. """Check what type of Clockwork Pi board."""
  375. board_value = self.detector.get_device_model()
  376. board = None
  377. if board_value and "Clockwork CPI3" in board_value:
  378. board = boards.CLOCKWORK_CPI3
  379. return board
  380. def _udoo_id(self):
  381. """Try to detect the id of udoo board."""
  382. board_asset_tag = self.detector.check_board_asset_tag_value()
  383. for board_id, board_tags in boards._UDOO_BOARD_IDS.items():
  384. if any(v == board_asset_tag for v in board_tags):
  385. return board_id
  386. if self.detector.check_board_name_value() == "UDOO x86":
  387. return boards.UDOO_X86
  388. return None
  389. def _asus_tinker_board_id(self):
  390. """Check what type of Tinker Board."""
  391. board_value = self.detector.get_device_model()
  392. board = None
  393. if board_value and "ASUS Tinker Board" in board_value:
  394. board = boards._ASUS_TINKER_BOARD_IDS
  395. return board
  396. def _allwinner_variants_id(self):
  397. """Try to detect the id of allwinner based board. (orangepi, nanopi)"""
  398. board_value = self.detector.get_device_model()
  399. board = None
  400. if not board_value:
  401. return board
  402. board_value = board_value.lower()
  403. chip_id = self.detector.chip.id
  404. if "nanopi" in board_value:
  405. if "neo" in board_value and "SUN8I" in chip_id:
  406. board = boards.NANOPI_NEO_AIR
  407. # TODO: Add other specifc board contexts here
  408. elif "orange pi" in board_value:
  409. if "zero" in board_value:
  410. if "H5" in chip_id:
  411. board = boards.ORANGE_PI_ZERO_PLUS_2H5
  412. elif "H616" in chip_id:
  413. board = boards.ORANGE_PI_ZERO_2
  414. # TODO: Add other specifc board contexts here
  415. return board
  416. def _rp2040_u2if_id(self):
  417. import hid
  418. # look for it based on PID/VID
  419. for dev in hid.enumerate():
  420. # Raspberry Pi Pico
  421. vendor = dev["vendor_id"]
  422. product = dev["product_id"]
  423. if vendor == 0xCAFE and product == 0x4005:
  424. return boards.PICO_U2IF
  425. if vendor == 0x239A:
  426. # Feather RP2040
  427. if product == 0x00F1:
  428. return boards.FEATHER_U2IF
  429. # Itsy Bitsy RP2040
  430. if product == 0x00FD:
  431. return boards.ITSYBITSY_U2IF
  432. # QT Py RP2040
  433. if product == 0x00F7:
  434. return boards.QTPY_U2IF
  435. # QT2040 Trinkey
  436. if product == 0x0109:
  437. return boards.QT2040_TRINKEY_U2IF
  438. # MacroPad RP2040
  439. if product == 0x0107:
  440. return boards.MACROPAD_U2IF
  441. # Will only reach here if a device was added in chip.py but here.
  442. raise RuntimeError("RP2040_U2IF device was added to chip but not board.")
  443. @property
  444. def any_nanopi(self):
  445. """Check whether the current board is any defined Nano Pi."""
  446. return self.id in boards._NANOPI_IDS
  447. @property
  448. def any_96boards(self):
  449. """Check whether the current board is any 96boards board."""
  450. return self.id in boards._LINARO_96BOARDS_IDS
  451. @property
  452. def any_raspberry_pi(self):
  453. """Check whether the current board is any Raspberry Pi."""
  454. return self._pi_rev_code() is not None
  455. @property
  456. def any_raspberry_pi_40_pin(self):
  457. """Check whether the current board is any 40-pin Raspberry Pi."""
  458. return self.id in boards._RASPBERRY_PI_40_PIN_IDS
  459. @property
  460. def any_raspberry_pi_cm(self):
  461. """Check whether the current board is any Compute Module Raspberry Pi."""
  462. return self.id in boards._RASPBERRY_PI_CM_IDS
  463. @property
  464. def any_beaglebone(self):
  465. """Check whether the current board is any Beaglebone-family system."""
  466. return self.id in boards._BEAGLEBONE_IDS
  467. @property
  468. def any_orange_pi(self):
  469. """Check whether the current board is any defined Orange Pi."""
  470. return self.id in boards._ORANGE_PI_IDS
  471. @property
  472. def any_lubancat(self):
  473. """Check whether the current board is any defined lubancat."""
  474. return self.id in boards._LUBANCAT_IDS
  475. @property
  476. def any_coral_board(self):
  477. """Check whether the current board is any defined Coral."""
  478. return self.id in boards._CORAL_IDS
  479. @property
  480. def any_pynq_board(self):
  481. """Check whether the current board is any defined PYNQ Board."""
  482. return self.id in boards._PYNQ_IDS
  483. @property
  484. def any_giant_board(self):
  485. """Check whether the current board is any defined Giant Board."""
  486. return self.GIANT_BOARD
  487. @property
  488. def any_odroid_40_pin(self):
  489. """Check whether the current board is any defined 40-pin Odroid."""
  490. return self.id in boards._ODROID_40_PIN_IDS
  491. @property
  492. def any_jetson_board(self):
  493. """Check whether the current board is any defined Jetson Board."""
  494. return self.id in [v[0] for v in boards._JETSON_IDS]
  495. @property
  496. def any_sifive_board(self):
  497. """Check whether the current board is any defined Jetson Board."""
  498. return self.id in boards._SIFIVE_IDS
  499. @property
  500. def any_onion_omega_board(self):
  501. """Check whether the current board is any defined OpenWRT board."""
  502. return self.id in boards._ONION_OMEGA_BOARD_IDS
  503. @property
  504. def any_pine64_board(self):
  505. """Check whether the current board is any Pine64 device."""
  506. return self.id in boards._PINE64_DEV_IDS
  507. @property
  508. def any_rock_pi_board(self):
  509. """Check whether the current board is any Rock Pi device."""
  510. return self.id in boards._ROCK_PI_IDS
  511. @property
  512. def any_clockwork_pi_board(self):
  513. """Check whether the current board is any Clockwork Pi device."""
  514. return self.CLOCKWORK_CPI3
  515. @property
  516. def any_udoo_board(self):
  517. """Check to see if the current board is an UDOO board"""
  518. return self.id in boards._UDOO_BOARD_IDS
  519. @property
  520. def any_asus_tinker_board(self):
  521. """Check to see if the current board is an ASUS Tinker Board"""
  522. return self.id in boards._ASUS_TINKER_BOARD_IDS
  523. @property
  524. def any_stm32mp1(self):
  525. """Check whether the current board is any stm32mp1 board."""
  526. return self.id in boards._STM32MP1_IDS
  527. @property
  528. def any_bananapi(self):
  529. """Check whether the current board is any BananaPi-family system."""
  530. return self.id in boards._BANANA_PI_IDS
  531. @property
  532. def any_maaxboard(self):
  533. """Check whether the current board is any BananaPi-family system."""
  534. return self.id in boards._MAAXBOARD_IDS
  535. @property
  536. def any_tisk_board(self):
  537. """Check whether the current board is any defined TI SK Board."""
  538. return self.id in [v[0] for v in boards._TI_SK_BOARD_IDS]
  539. @property
  540. def any_embedded_linux(self):
  541. """Check whether the current board is any embedded Linux device."""
  542. return any(
  543. [
  544. self.any_raspberry_pi_40_pin,
  545. self.any_raspberry_pi,
  546. self.any_beaglebone,
  547. self.any_orange_pi,
  548. self.any_nanopi,
  549. self.any_giant_board,
  550. self.any_jetson_board,
  551. self.any_coral_board,
  552. self.any_odroid_40_pin,
  553. self.any_96boards,
  554. self.any_sifive_board,
  555. self.any_onion_omega_board,
  556. self.any_pine64_board,
  557. self.any_pynq_board,
  558. self.any_rock_pi_board,
  559. self.any_clockwork_pi_board,
  560. self.any_udoo_board,
  561. self.any_asus_tinker_board,
  562. self.any_stm32mp1,
  563. self.any_lubancat,
  564. self.any_bananapi,
  565. self.any_maaxboard,
  566. self.any_tisk_board,
  567. ]
  568. )
  569. @property
  570. def ftdi_ft232h(self):
  571. """Check whether the current board is an FTDI FT232H."""
  572. return self.id == boards.FTDI_FT232H
  573. @property
  574. def ftdi_ft2232h(self):
  575. """Check whether the current board is an FTDI FT2232H."""
  576. return self.id == boards.FTDI_FT2232H
  577. @property
  578. def microchip_mcp2221(self):
  579. """Check whether the current board is a Microchip MCP2221."""
  580. return self.id == boards.MICROCHIP_MCP2221
  581. @property
  582. def pico_u2if(self):
  583. """Check whether the current board is a RPi Pico w/ u2if."""
  584. return self.id == boards.PICO_U2IF
  585. @property
  586. def feather_u2if(self):
  587. """Check whether the current board is a Feather RP2040 w/ u2if."""
  588. return self.id == boards.FEATHER_U2IF
  589. @property
  590. def itsybitsy_u2if(self):
  591. """Check whether the current board is a Itsy Bitsy w/ u2if."""
  592. return self.id == boards.ITSYBITSY_U2IF
  593. @property
  594. def macropad_u2if(self):
  595. """Check whether the current board is a MacroPad w/ u2if."""
  596. return self.id == boards.MACROPAD_U2IF
  597. @property
  598. def qtpy_u2if(self):
  599. """Check whether the current board is a QT Py w/ u2if."""
  600. return self.id == boards.QTPY_U2IF
  601. @property
  602. def qt2040_trinkey_u2if(self):
  603. """Check whether the current board is a QT Py w/ u2if."""
  604. return self.id == boards.QT2040_TRINKEY_U2IF
  605. @property
  606. def binho_nova(self):
  607. """Check whether the current board is an BINHO NOVA."""
  608. return self.id == boards.BINHO_NOVA
  609. @property
  610. def greatfet_one(self):
  611. """Check whether the current board is a GreatFET One."""
  612. return self.id == boards.GREATFET_ONE
  613. def __getattr__(self, attr):
  614. """
  615. Detect whether the given attribute is the currently-detected board. See list
  616. of constants at the top of this module for available options.
  617. """
  618. if self.id == attr:
  619. return True
  620. return False