3 Copyright (c) 2017 ARM Limited
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
9 http://www.apache.org/licenses/LICENSE-2.0
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
18 """Functions that manage a platform database"""
23 from collections
import OrderedDict, defaultdict
26 from os
import makedirs
27 from os.path
import join, dirname, getmtime
28 from appdirs
import user_data_dir
29 from fasteners
import InterProcessLock
38 logger = logging.getLogger(
"mbedls.platform_database")
39 logger.addHandler(logging.NullHandler())
42 LOCAL_PLATFORM_DATABASE = join(user_data_dir(
"mbedls"),
"platforms.json")
43 LOCAL_MOCKS_DATABASE = join(user_data_dir(
"mbedls"),
"mock.json")
45 DEFAULT_PLATFORM_DB = {
55 u'0183':
u'UBLOX_C027',
63 u'0227':
u'MIMXRT1050_EVK',
64 u'0228':
u'RAPIDIOT_K64F',
67 u'0234':
u'RAPIDIOT_KW41Z',
73 u'0300':
u'MTS_GAMBIT',
74 u'0305':
u'MTS_MDOT_F405RG',
75 u'0310':
u'MTS_DRAGONFLY_F411RE',
77 u'0312':
u'MTS_DRAGONFLY_L471QG',
78 u'0315':
u'MTS_MDOT_F411RE',
79 u'0350':
u'XDOT_L151CC',
80 u'0400':
u'MAXWSNENV',
81 u'0405':
u'MAX32600MBED',
82 u'0406':
u'MAX32620MBED',
83 u'0407':
u'MAX32620HSP',
84 u'0408':
u'MAX32625NEXPAQ',
85 u'0409':
u'MAX32630FTHR',
86 u'0410':
u'ETTEPLAN_LORA',
87 u'0415':
u'MAX32625MBED',
88 u'0416':
u'MAX32625PICO',
89 u'0417':
u'MAX32630MBED',
90 u'0418':
u'MAX32620FTHR',
91 u'0419':
u'MAX35103EVKIT2',
92 u'0420':
u'MAX32630HSP3',
93 u'0450':
u'MTB_UBLOX_ODIN_W2',
94 u'0451':
u'MTB_MXCHIP_EMW3166',
95 u'0452':
u'MTB_LAIRD_BL600',
96 u'0453':
u'MTB_MTS_XDOT',
97 u'0454':
u'MTB_MTS_DRAGONFLY',
98 u'0455':
u'MTB_UBLOX_NINA_B1',
99 u'0456':
u'MTB_MURATA_ABZ',
100 u'0457':
u'MTB_RAK811',
101 u'0458':
u'MTB_ADV_WISE_1510',
102 u'0459':
u'MTB_ADV_WISE_1530',
103 u'0460':
u'MTB_ADV_WISE_1570',
104 u'0461':
u'MTB_LAIRD_BL652',
105 u'0462':
u'MTB_USI_WM_BN_BM_22',
106 u'0465':
u'MTB_LAIRD_BL654',
107 u'0466':
u'MTB_MURATA_WSM_BL241',
108 u'0472':
u'MTB_ACONNO_ACN52832',
109 u'0500':
u'SPANSION_PLACEHOLDER',
110 u'0505':
u'SPANSION_PLACEHOLDER',
111 u'0510':
u'SPANSION_PLACEHOLDER',
112 u'0602':
u'EV_COG_AD3029LZ',
113 u'0603':
u'EV_COG_AD4050LZ',
114 u'0700':
u'NUCLEO_F103RB',
115 u'0705':
u'NUCLEO_F302R8',
116 u'0710':
u'NUCLEO_L152RE',
117 u'0715':
u'NUCLEO_L053R8',
118 u'0720':
u'NUCLEO_F401RE',
119 u'0725':
u'NUCLEO_F030R8',
120 u'0730':
u'NUCLEO_F072RB',
121 u'0735':
u'NUCLEO_F334R8',
122 u'0740':
u'NUCLEO_F411RE',
123 u'0742':
u'NUCLEO_F413ZH',
124 u'0743':
u'DISCO_F413ZH',
125 u'0744':
u'NUCLEO_F410RB',
126 u'0745':
u'NUCLEO_F303RE',
127 u'0746':
u'DISCO_F303VC',
128 u'0747':
u'NUCLEO_F303ZE',
129 u'0750':
u'NUCLEO_F091RC',
130 u'0755':
u'NUCLEO_F070RB',
131 u'0760':
u'NUCLEO_L073RZ',
132 u'0764':
u'DISCO_L475VG_IOT01A',
133 u'0765':
u'NUCLEO_L476RG',
134 u'0766':
u'SILICA_SENSOR_NODE',
135 u'0770':
u'NUCLEO_L432KC',
136 u'0774':
u'DISCO_L4R9I',
137 u'0775':
u'NUCLEO_F303K8',
138 u'0776':
u'NUCLEO_L4R5ZI',
139 u'0777':
u'NUCLEO_F446RE',
140 u'0778':
u'NUCLEO_F446ZE',
141 u'0779':
u'NUCLEO_L433RC_P',
142 u'0780':
u'NUCLEO_L011K4',
143 u'0781':
u'NUCLEO_L4R5ZI_P',
144 u'0785':
u'NUCLEO_F042K6',
145 u'0788':
u'DISCO_F469NI',
146 u'0790':
u'NUCLEO_L031K6',
147 u'0791':
u'NUCLEO_F031K6',
148 u'0795':
u'DISCO_F429ZI',
149 u'0796':
u'NUCLEO_F429ZI',
150 u'0797':
u'NUCLEO_F439ZI',
151 u'0799':
u'ST_PLACEHOLDER',
152 u'0805':
u'DISCO_L053C8',
153 u'0810':
u'DISCO_F334C8',
154 u'0812':
u'NUCLEO_F722ZE',
155 u'0813':
u'NUCLEO_H743ZI',
156 u'0815':
u'DISCO_F746NG',
157 u'0816':
u'NUCLEO_F746ZG',
158 u'0817':
u'DISCO_F769NI',
159 u'0818':
u'NUCLEO_F767ZI',
160 u'0820':
u'DISCO_L476VG',
161 u'0821':
u'NUCLEO_L452RE',
162 u'0822':
u'DISCO_L496AG',
163 u'0823':
u'NUCLEO_L496ZG',
166 u'0826':
u'NUCLEO_F412ZG',
167 u'0827':
u'NUCLEO_L486RG',
168 u'0828':
u'NUCLEO_L496ZG_P',
169 u'0829':
u'NUCLEO_L452RE_P',
170 u'0830':
u'DISCO_F407VG',
171 u'0833':
u'DISCO_L072CZ_LRWAN1',
172 u'0835':
u'NUCLEO_F207ZG',
173 u'0839':
u'NUCLEO_WB55RG',
174 u'0840':
u'B96B_F446VE',
175 u'0879':
u'NUCLEO_F756ZG',
176 u'0900':
u'XPRO_SAMR21',
177 u'0905':
u'XPRO_SAMW25',
178 u'0910':
u'XPRO_SAML21',
179 u'0915':
u'XPRO_SAMD21',
185 u'1019':
u'TY51822R3',
187 u'1034':
u'LPC11U34',
188 u'1040':
u'LPC11U24',
189 u'1045':
u'LPC11U24',
191 u'1054':
u'LPC54114',
192 u'1056':
u'LPC546XX',
194 u'1061':
u'LPC11U35_401',
195 u'1062':
u'LPC4088_DM',
196 u'1070':
u'NRF51822',
197 u'1075':
u'NRF51822_OTA',
198 u'1080':
u'OC_MBUINO',
199 u'1090':
u'RBLAB_NRF51822',
200 u'1093':
u'RBLAB_BLENANO2',
201 u'1095':
u'RBLAB_BLENANO',
202 u'1100':
u'NRF51_DK',
203 u'1101':
u'NRF52_DK',
204 u'1102':
u'NRF52840_DK',
205 u'1105':
u'NRF51_DK_OTA',
207 u'1120':
u'NRF51_DONGLE',
208 u'1130':
u'NRF51822_SBK',
209 u'1140':
u'WALLBOT_BLE',
210 u'1168':
u'LPC11U68',
211 u'1200':
u'NCS36510',
212 u'1234':
u'UBLOX_C027',
213 u'1235':
u'UBLOX_C027',
214 u'1236':
u'UBLOX_EVK_ODIN_W2',
215 u'1237':
u'UBLOX_EVK_NINA_B1',
216 u'1300':
u'NUC472-NUTINY',
218 u'1302':
u'NUMAKER_PFM_NUC472',
219 u'1303':
u'NUMAKER_PFM_M453',
220 u'1304':
u'NUMAKER_PFM_M487',
221 u'1305':
u'NUMAKER_PFM_M2351',
222 u'1306':
u'NUMAKER_PFM_NANO130',
223 u'1307':
u'NUMAKER_PFM_NUC240',
224 u'1308':
u'NUMAKER_IOT_M487',
226 u'1600':
u'LPC4330_M4',
227 u'1605':
u'LPC4330_M4',
228 u'1701':
u'GD32_F307VG',
229 u'1702':
u'GD32_F450ZI',
230 u'2000':
u'EFM32_G8XX_STK',
231 u'2005':
u'EFM32HG_STK3400',
232 u'2010':
u'EFM32WG_STK3800',
233 u'2015':
u'EFM32GG_STK3700',
234 u'2020':
u'EFM32LG_STK3600',
235 u'2025':
u'EFM32TG_STK3300',
236 u'2030':
u'EFM32ZG_STK3200',
237 u'2035':
u'EFM32PG_STK3401',
238 u'2040':
u'EFM32PG12_STK3402',
239 u'2041':
u'TB_SENSE_12',
240 u'2045':
u'TB_SENSE_1',
241 u'2100':
u'XBED_LPC1768',
242 u'2201':
u'WIZWIKI_W7500',
243 u'2202':
u'WIZWIKI_W7500ECO',
244 u'2203':
u'WIZWIKI_W7500P',
245 u'2500':
u'ADV_WISE_1570',
246 u'3001':
u'LPC11U24',
247 u'3101':
u'SDT32620B',
248 u'3102':
u'SDT32625B',
249 u'3103':
u'SDT51822B',
250 u'3104':
u'SDT52832B',
252 u'3106':
u'SDT8195B',
253 u'3108':
u'SDT32429B',
254 u'3110':
u'SDT32439B',
255 u'3300':
u'CC3220SF',
256 u'4000':
u'LPC11U35_Y5_MBUG',
257 u'4005':
u'NRF51822_Y5_MBUG',
258 u'4100':
u'MOTE_L152RC',
260 u'4500':
u'DELTA_DFCM_NNN40',
261 u'4501':
u'DELTA_DFBM_NQ620',
262 u'4502':
u'DELTA_DFCM_NNN50',
263 u'4600':
u'REALTEK_RTL8195AM',
264 u'5000':
u'ARM_MPS2',
265 u'5001':
u'ARM_MPS2_M0',
266 u'5002':
u'ARM_BEETLE_SOC',
267 u'5003':
u'ARM_MPS2_M0P',
268 u'5005':
u'ARM_MPS2_M0DS',
269 u'5006':
u'ARM_MUSCA_A1',
270 u'5007':
u'ARM_MPS2_M1',
271 u'5009':
u'ARM_MPS2_M3',
272 u'5011':
u'ARM_MPS2_M4',
273 u'5015':
u'ARM_MPS2_M7',
274 u'5020':
u'HOME_GATEWAY_6LOWPAN',
276 u'5501':
u'GR_LYCHEE',
277 u'6000':
u'FUTURE_SEQUANA',
278 u'6660':
u'NZ32_SC151',
279 u'7010':
u'BLUENINJA_CDP_TZ01B',
282 u'7402':
u'MBED_BR_HAT',
283 u'7778':
u'TEENSY3_1',
286 u'8003':
u'UNO_81AM',
288 u'8080':
u'FF1705_L151CC',
289 u'8081':
u'FF_LPC546XX',
291 u'9002':
u'LPC11U24',
293 u'9004':
u'ARCH_PRO',
294 u'9006':
u'LPC11U24',
295 u'9007':
u'LPC11U35_501',
296 u'9008':
u'XADOW_M0',
297 u'9009':
u'ARCH_BLE',
298 u'9010':
u'ARCH_GPRS',
299 u'9011':
u'ARCH_MAX',
300 u'9012':
u'SEEED_TINY_BLE',
302 u'9015':
u'WIO_BG96',
303 u'9900':
u'NRF51_MICROBIT',
304 u'C002':
u'VK_RZ_A1H',
305 u'C005':
u'MTM_MTCONNECT04S',
306 u'C006':
u'VBLUNO51',
307 u'C008':
u'SAKURAIO_EVB_01',
308 u'C030':
u'UBLOX_C030_U201',
309 u'C031':
u'UBLOX_C030_N211',
310 u'C032':
u'UBLOX_C030_R404M',
311 u'C033':
u'UBLOX_C030_R410M',
312 u'C034':
u'UBLOX_C030_S200',
313 u'C035':
u'UBLOX_C030_R3121',
314 u'FFFF':
u'K20 BOOTLOADER',
319 u'platform_name':
u'NRF51_DK',
320 u'jlink_device_name':
u'nRF51422_xxAC'
323 u'platform_name':
u'NRF52_DK',
324 u'jlink_device_name':
u'nRF52832_xxaa'
327 u'platform_name':
u'KL25Z',
328 u'jlink_device_name':
u'MKL25Z128xxx4'
331 u'platform_name':
u'KL27Z',
332 u'jlink_device_name':
u'MKL27Z64xxx4'
335 u'platform_name':
u'KL43Z',
336 u'jlink_device_name':
u'MKL43Z256xxx4'
340 u'2241':
'SAML21J18A'
345 def _get_modified_time(path):
347 mtime = getmtime(path)
350 return datetime.datetime.fromtimestamp(mtime)
353 def _older_than_me(path):
354 return _get_modified_time(path) < _get_modified_time(__file__)
357 def _modify_data_format(data, verbose_data, simple_data_key='platform_name'):
358 if isinstance(data, dict):
362 return data[simple_data_key]
366 simple_data_key: data
372 def _overwrite_or_open(db):
374 if db
is LOCAL_PLATFORM_DATABASE
and _older_than_me(db):
375 raise ValueError(
"Platform Database is out of date")
376 with open(db, encoding=
"utf-8")
as db_in:
377 return json.load(db_in)
378 except (IOError, ValueError)
as exc:
379 if db
is LOCAL_PLATFORM_DATABASE:
381 "Error loading database %s: %s; Recreating", db, str(exc))
383 makedirs(dirname(db))
387 with open(db,
"w", encoding=
"utf-8")
as out:
388 out.write(
unicode(json.dumps(DEFAULT_PLATFORM_DB)))
391 return copy(DEFAULT_PLATFORM_DB)
397 """Represents a union of multiple platform database files.
398 Handles inter-process synchronization of database files.
401 target_id_pattern = re.compile(
r'^[a-fA-F0-9]{4}$')
403 def __init__(self, database_files, primary_database=None):
404 """Construct a PlatformDatabase object from a series of platform database files"""
405 self.
_prim_db_prim_db = primary_database
406 if not self.
_prim_db_prim_db
and len(database_files) == 1:
407 self.
_prim_db_prim_db = database_files[0]
408 self.
_dbs_dbs = OrderedDict()
409 self.
_keys_keys = defaultdict(set)
410 for db
in database_files:
411 new_db = _overwrite_or_open(db)
414 first_value = next(iter(new_db.values()))
415 if not isinstance(first_value, dict):
421 for device_type
in new_db:
422 duplicates = self.
_keys_keys[device_type].intersection(set(new_db[device_type].keys()))
423 duplicates = set([
"%s.%s" % (device_type, k)
for k
in duplicates])
426 "Duplicate platform ids found: %s,"
427 " ignoring the definitions from %s",
428 " ".join(duplicates), db)
429 self.
_dbs_dbs[db] = new_db
430 self.
_keys_keys[device_type] = self.
_keys_keys[device_type].union(new_db[device_type].keys())
432 self.
_dbs_dbs[db] = new_db
435 def items(self, device_type='daplink'):
436 for db
in self.
_dbs_dbs.values():
437 for entry
in db.get(device_type, {}).
items():
441 return iter(self.
_keys_keys[device_type])
443 def get(self, index, default=None, device_type='daplink', verbose_data=False):
444 """Standard lookup function. Works exactly like a dict. If 'verbose_data'
445 is True, all data for the platform is returned as a dict."""
446 for db
in self.
_dbs_dbs.values():
447 if device_type
in db:
448 maybe_answer = db[device_type].
get(index,
None)
450 return _modify_data_format(maybe_answer, verbose_data)
454 def _update_db(self):
456 lock = InterProcessLock(
"%s.lock" % self.
_prim_db_prim_db)
457 acquired = lock.acquire(blocking=
False)
459 logger.debug(
"Waiting 60 seconds for file lock")
460 acquired = lock.acquire(blocking=
True, timeout=60)
463 with open(self.
_prim_db_prim_db,
"w", encoding=
"utf-8")
as out:
470 logger.error(
"Could not update platform database: "
471 "Lock acquire failed after 60 seconds")
474 logger.error(
"Can't update platform database: "
475 "destination database is ambiguous")
478 def add(self, id, platform_name, permanent=False, device_type='daplink'):
479 """Add a platform to this database, optionally updating an origin
484 if device_type
not in self.
_dbs_dbs[self.
_prim_db_prim_db]:
486 self.
_dbs_dbs[self.
_prim_db_prim_db][device_type][id] = platform_name
488 cur_db = next(iter(self.
_dbs_dbs.values()))
489 if device_type
not in cur_db:
490 cur_db[device_type] = {}
491 cur_db[device_type][id] = platform_name
492 self.
_keys_keys[device_type].
add(id)
496 raise ValueError(
"Invald target id: %s" % id)
498 def remove(self, id, permanent=False, device_type='daplink', verbose_data=False):
499 """Remove a platform from this database, optionally updating an origin
500 database. If 'verbose_data' is True, all data for the platform is returned
503 logger.debug(
"Trying remove of %s", id)
504 if id
is '*' and device_type
in self.
_dbs_dbs[self.
_prim_db_prim_db]:
506 for db
in self.
_dbs_dbs.values():
507 if device_type
in db
and id
in db[device_type]:
508 logger.debug(
"Removing id...")
509 removed = db[device_type][id]
510 del db[device_type][id]
515 return _modify_data_format(removed, verbose_data)