|
| 1 | +""" |
| 2 | +mbed SDK |
| 3 | +Copyright (c) 2011-2015 ARM Limited |
| 4 | +
|
| 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 |
| 8 | +
|
| 9 | + http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | +
|
| 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. |
| 16 | +""" |
| 17 | + |
| 18 | +import re |
| 19 | +import subprocess |
| 20 | + |
| 21 | +from lstools_base import MbedLsToolsBase |
| 22 | + |
| 23 | + |
| 24 | +class MbedLsToolsLinuxGeneric(MbedLsToolsBase): |
| 25 | + """ MbedLsToolsLinuxGeneric supports mbed-enabled platforms detection across Linux family |
| 26 | + """ |
| 27 | + def __init__(self): |
| 28 | + """ ctor |
| 29 | + """ |
| 30 | + MbedLsToolsBase.__init__(self) |
| 31 | + self.os_supported.append('LinuxGeneric') |
| 32 | + self.hex_uuid_pattern = "usb-[0-9a-zA-Z_-]*_([0-9a-zA-Z]*)-.*" |
| 33 | + self.name_link_pattern = "(usb-[0-9a-zA-Z_-]*_[0-9a-zA-Z]*-.*$)" |
| 34 | + self.mount_media_pattern = "^/[a-zA-Z0-9/]* on (/[a-zA-Z0-9/]*) " |
| 35 | + |
| 36 | + def list_mbeds(self): |
| 37 | + """! Returns detailed list of connected mbeds |
| 38 | +
|
| 39 | + @return Returns list of structures with detailed info about each mbed |
| 40 | +
|
| 41 | + @details Function returns list of dictionaries with mbed attributes such as mount point, TargetID name etc. |
| 42 | +
|
| 43 | + Function returns mbed list with platform names if possible |
| 44 | + all_devices = |
| 45 | + [ |
| 46 | + ['*not detected', 'sdi', '/media/usb3', '/dev/ttyACM7', 'usb-MBED_microcontroller_066EFF534951775087215736-0:0 -> ../../sdi'], |
| 47 | + ['*not detected', 'sdg', '/media/usb5', '/dev/ttyACM5', 'usb-MBED_microcontroller_066EFF525257775087141721-0:0 -> ../../sdg'], |
| 48 | + ['*not detected', 'sdf', '/media/przemek/NUCLEO', '/dev/ttyACM4', 'usb-MBED_microcontroller_0671FF534951775087131543-0:0 -> ../../sdf'], |
| 49 | + ['*not detected', 'sdd', '/media/usb4', '/dev/ttyACM2', 'usb-MBED_microcontroller_0670FF494951785087152739-0:0 -> ../../sdd'], |
| 50 | + ['*not detected', 'sdb', '/media/usb0', '/dev/ttyACM0', 'usb-MBED_microcontroller_0674FF484951775087083114-0:0 -> ../../sdb'], |
| 51 | + ['*not detected', 'sdh', '/media/usb6', '/dev/ttyACM6', 'usb-MBED_microcontroller_066FFF525257775087155144-0:0 -> ../../sdh'], |
| 52 | + ['*not detected', 'sdc', '/media/usb1', '/dev/ttyACM1', 'usb-MBED_microcontroller_066AFF494956805087155327-0:0 -> ../../sdc'], |
| 53 | + ['*not detected', 'sde', '/media/usb2', '/dev/ttyACM3', 'usb-MBED_microcontroller_066CFF534951775087112139-0:0 -> ../../sde'] |
| 54 | + ] |
| 55 | +
|
| 56 | + MBED format |
| 57 | + { |
| 58 | + 'mount_point' : <>, |
| 59 | + 'serial_port' : <>, |
| 60 | + 'target_id' : <>, |
| 61 | + 'platform_name' : <>, |
| 62 | + } |
| 63 | +
|
| 64 | + TIDS format |
| 65 | + { |
| 66 | + "1168": "LPC11U68", |
| 67 | + "1549": "LPC1549", |
| 68 | + "1070": "NRF51822", |
| 69 | + "0200": "KL25Z", |
| 70 | + "0220": "KL46Z", |
| 71 | + "0230": "K20D50M", |
| 72 | + "0240": "K64F" |
| 73 | + } |
| 74 | + """ |
| 75 | + # We harness information about what is mounted and connected to serial ports |
| 76 | + disk_ids = self.get_dev_by_id('disk') |
| 77 | + serial_ids = self.get_dev_by_id('serial') |
| 78 | + mount_ids = self.get_mounts() |
| 79 | + |
| 80 | + # Extra data to identify mbeds by target_id |
| 81 | + tids = self.manufacture_ids |
| 82 | + |
| 83 | + # Listing known and undetected / orphan devices |
| 84 | + mbeds = self.get_detected(tids, disk_ids, serial_ids, mount_ids) |
| 85 | + orphans = self.get_not_detected(tids, disk_ids, serial_ids, mount_ids) |
| 86 | + all_devices = mbeds + orphans |
| 87 | + |
| 88 | + self.ERRORLEVEL_FLAG = 0 |
| 89 | + |
| 90 | + result = [] |
| 91 | + tidhex = re.compile(r'_([0-9a-fA-F]+)-\d+:\d+') |
| 92 | + for device in all_devices: |
| 93 | + tid = None |
| 94 | + m = tidhex.search(device[4]) |
| 95 | + if m and len(m.groups()): |
| 96 | + tid = m.group(1) |
| 97 | + mbed = {'mount_point' : device[2], |
| 98 | + 'serial_port' : device[3], |
| 99 | + 'target_id' : tid, |
| 100 | + 'platform_name' : device[0] |
| 101 | + } |
| 102 | + |
| 103 | + # Deducing mbed-enabled TargetID based on available targetID definition DB. |
| 104 | + # If TargetID from USBID is not recognized we will try to check URL in mbed.htm |
| 105 | + mbed_htm_target_id = self.get_mbed_htm_target_id(device[2]) # device[2] is a 'mount_point' |
| 106 | + if mbed_htm_target_id is not None: |
| 107 | + mbed_htm_target_id_prefix = mbed_htm_target_id[0:4] |
| 108 | + if mbed_htm_target_id_prefix in tids: |
| 109 | + # We need to update platform_name and corresponding TargetID (not USBID, but from mbed.htm) |
| 110 | + mbed['platform_name'] = tids[mbed_htm_target_id_prefix] |
| 111 | + mbed['target_id'] = mbed_htm_target_id |
| 112 | + mbed['target_id_usb_id'] = tid |
| 113 | + mbed['target_id_mbed_htm'] = mbed_htm_target_id |
| 114 | + result.append(mbed) |
| 115 | + |
| 116 | + if None in mbed: |
| 117 | + self.ERRORLEVEL_FLAG = -1 |
| 118 | + |
| 119 | + return result |
| 120 | + |
| 121 | + # Private methods |
| 122 | + |
| 123 | + def get_dev_by_id(self, subdir): |
| 124 | + """! Lists disk devices by id |
| 125 | +
|
| 126 | + @return List of strings from 'ls' command executed in shell |
| 127 | +
|
| 128 | + @details Uses Linux shell command: 'ls -oA /dev/disk/by-id/' |
| 129 | + """ |
| 130 | + result = [] |
| 131 | + cmd = 'ls -oA /dev/' + subdir + '/by-id/' |
| 132 | + if self.DEBUG_FLAG: |
| 133 | + self.debug(self.get_dev_by_id.__name__, cmd) |
| 134 | + |
| 135 | + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
| 136 | + for line in p.stdout.readlines(): |
| 137 | + line = line.rstrip() |
| 138 | + result.append(line) |
| 139 | + if self.DEBUG_FLAG: |
| 140 | + self.debug(self.get_dev_by_id.__name__, line) |
| 141 | + retval = p.wait() |
| 142 | + return result |
| 143 | + |
| 144 | + def get_mounts(self): |
| 145 | + """! Lists mounted devices with vfat file system (potential mbeds) |
| 146 | +
|
| 147 | + @result Returns list of all mounted vfat devices |
| 148 | +
|
| 149 | + @details Uses Linux shell command: 'mount | grep vfat' |
| 150 | + """ |
| 151 | + result = [] |
| 152 | + cmd = 'mount | grep vfat' |
| 153 | + if self.DEBUG_FLAG: |
| 154 | + self.debug(self.get_mounts.__name__, cmd) |
| 155 | + |
| 156 | + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
| 157 | + for line in p.stdout.readlines(): |
| 158 | + line = line.rstrip() |
| 159 | + result.append(line) |
| 160 | + if self.DEBUG_FLAG: |
| 161 | + self.debug(self.get_mounts.__name__, line) |
| 162 | + retval = p.wait() |
| 163 | + return result |
| 164 | + |
| 165 | + def get_disk_hex_ids(self, disk_list): |
| 166 | + """! Get only hexadecimal IDs for mbed disks |
| 167 | +
|
| 168 | + @param disk_list List of disks in a system with USBID decoration |
| 169 | +
|
| 170 | + @return Returns map of disks and corresponding disks' Hex ids |
| 171 | +
|
| 172 | + @details Uses regular expressions to get Hex strings (TargeTIDs) from list of disks |
| 173 | + """ |
| 174 | + nlp = re.compile(self.name_link_pattern) |
| 175 | + hup = re.compile(self.hex_uuid_pattern) |
| 176 | + disk_hex_ids = {} |
| 177 | + for dl in disk_list: |
| 178 | + m = nlp.search(dl) |
| 179 | + if m and len(m.groups()): |
| 180 | + disk_link = m.group(1) |
| 181 | + m = hup.search(disk_link) |
| 182 | + if m and len(m.groups()): |
| 183 | + disk_hex_ids[m.group(1)] = disk_link |
| 184 | + return disk_hex_ids |
| 185 | + |
| 186 | + def get_mbed_serial(self, serial_list, dhi): |
| 187 | + """! Get mbed serial by unique hex id (dhi) in disk name |
| 188 | +
|
| 189 | + @return Returns None if corresponding serial device is not found, else returns serial device path |
| 190 | +
|
| 191 | + @param serial_list List of all serial ports |
| 192 | + @param dhi Unique Hex id of possible mbed device |
| 193 | +
|
| 194 | + @details Devices are located in Linux '/dev/' directory structure |
| 195 | + """ |
| 196 | + nlp = re.compile(self.name_link_pattern) |
| 197 | + for sl in serial_list: |
| 198 | + if dhi in sl: |
| 199 | + m = nlp.search(sl) |
| 200 | + if m and len(m.groups()): |
| 201 | + serial_link = m.group(1) |
| 202 | + mbed_dev_serial = "/dev/" + self.get_dev_name(serial_link) |
| 203 | + return mbed_dev_serial |
| 204 | + return None |
| 205 | + |
| 206 | + def get_detected(self, tids, disk_list, serial_list, mount_list): |
| 207 | + """! Find all known mbed devices and assign name by targetID |
| 208 | +
|
| 209 | + @return list of lists [mbed_name, mbed_dev_disk, mbed_mount_point, mbed_dev_serial, disk_hex_id] |
| 210 | +
|
| 211 | + @param tids TargetID comprehensive list for detection (manufacturers_ids) |
| 212 | + @param disk_list List of disks (mount points in /dev/disk) |
| 213 | + @param serial_list List of serial devices (serial ports in /dev/serial) |
| 214 | + @param mount_list List of lines from 'mount' command |
| 215 | +
|
| 216 | + @details Find for all disk connected all MBED ones we know about from TID list |
| 217 | + """ |
| 218 | + # Find for all disk connected all MBED ones we know about from TID list |
| 219 | + disk_hex_ids = self.get_disk_hex_ids(disk_list) |
| 220 | + map_tid_to_mbed = self.get_tid_mbed_name_remap(tids) |
| 221 | + |
| 222 | + result = [] |
| 223 | + |
| 224 | + # Search if we have |
| 225 | + for dhi in disk_hex_ids.keys(): |
| 226 | + for mttm in map_tid_to_mbed.keys(): |
| 227 | + if dhi.startswith(mttm): |
| 228 | + mbed_name = map_tid_to_mbed[mttm] |
| 229 | + mbed_dev_disk = "" |
| 230 | + mbed_dev_serial = "" |
| 231 | + |
| 232 | + disk_link = disk_hex_ids[dhi] |
| 233 | + # print "Fount MBED disk: " + disk_link #mbed_name + ": " + mttm + " (" + dhi + ")" |
| 234 | + mbed_dev_disk = self.get_dev_name(disk_link) # m.group(1) if m and len(m.groups()) else "unknown" |
| 235 | + mbed_dev_serial = self.get_mbed_serial(serial_list, dhi) |
| 236 | + # Print detected device |
| 237 | + mbed_mount_point = self.get_mount_point(mbed_dev_disk, mount_list) |
| 238 | + if mbed_mount_point: |
| 239 | + result.append([mbed_name, mbed_dev_disk, mbed_mount_point, mbed_dev_serial, disk_hex_ids[dhi]]) |
| 240 | + return result |
| 241 | + |
| 242 | + def get_not_detected(self, tids, disk_list, serial_list, mount_list): |
| 243 | + """! Find all unknown mbed-enabled devices (may have 'mbed' string in USBID name) |
| 244 | +
|
| 245 | + @return list of lists [mbed_name, mbed_dev_disk, mbed_mount_point, mbed_dev_serial, disk_hex_id] |
| 246 | +
|
| 247 | + @param tids TargetID comprehensive list for detection (manufacturers_ids) |
| 248 | + @param disk_list List of disks (mount points in /dev/disk) |
| 249 | + @param serial_list List of serial devices (serial ports in /dev/serial) |
| 250 | + @param mount_list List of lines from 'mount' command |
| 251 | +
|
| 252 | + @details Find for all disk connected all MBED ones we know about from TID list |
| 253 | + """ |
| 254 | + map_tid_to_mbed = self.get_tid_mbed_name_remap(tids) |
| 255 | + orphan_mbeds = [] |
| 256 | + for disk in disk_list: |
| 257 | + if "mbed" in disk.lower(): |
| 258 | + orphan_found = True |
| 259 | + for tid in map_tid_to_mbed.keys(): |
| 260 | + if tid in disk: |
| 261 | + orphan_found = False |
| 262 | + break |
| 263 | + if orphan_found: |
| 264 | + orphan_mbeds.append(disk) |
| 265 | + |
| 266 | + # Search for corresponding MBED serial |
| 267 | + disk_hex_ids = self.get_disk_hex_ids(orphan_mbeds) |
| 268 | + |
| 269 | + result = [] |
| 270 | + # FInd orphan serial name |
| 271 | + for dhi in disk_hex_ids: |
| 272 | + orphan_serial = self.get_mbed_serial(serial_list, dhi) |
| 273 | + if orphan_serial: |
| 274 | + orphan_dev_disk = self.get_dev_name(disk_hex_ids[dhi]) |
| 275 | + orphan_dev_serial = '/dev/' + self.get_dev_name(orphan_serial) |
| 276 | + orphan_mount_point = self.get_mount_point(orphan_dev_disk, mount_list) |
| 277 | + if orphan_mount_point and orphan_dev_serial: |
| 278 | + result.append([None, orphan_dev_disk, orphan_mount_point, orphan_dev_serial, disk_hex_ids[dhi]]) |
| 279 | + return result |
| 280 | + |
| 281 | + def get_tid_mbed_name_remap(self, tids): |
| 282 | + """ Remap to get mapping: ID -> mbed name |
| 283 | + """ |
| 284 | + return tids |
| 285 | + |
| 286 | + def get_dev_name(self, link): |
| 287 | + """ Get device name from symbolic link list |
| 288 | + """ |
| 289 | + device_sufix_pattern = ".*/([a-zA-Z0-9]*)$" |
| 290 | + dsp = re.compile(device_sufix_pattern) |
| 291 | + m = dsp.search(link) |
| 292 | + mbed_dev = m.group(1) if m and len(m.groups()) else "unknown" |
| 293 | + return mbed_dev |
| 294 | + |
| 295 | + def get_mount_point(self, dev_name, mount_list): |
| 296 | + """ Find mount points for MBED devices using mount command output |
| 297 | +
|
| 298 | + @return Returns None if mount point not found. Else returns device mount path |
| 299 | +
|
| 300 | + @param dev_name Device name (e.g 'sda') |
| 301 | + @param mount_list List of all mounted devices (strings from Linux mount shell command) |
| 302 | +
|
| 303 | + @details |
| 304 | + """ |
| 305 | + mount_media_pattern = "^/[a-zA-Z0-9/]*/" + dev_name + " on (/[a-zA-Z0-9/]*) " |
| 306 | + mmp = re.compile(mount_media_pattern) |
| 307 | + for mount in mount_list: |
| 308 | + m = mmp.search(mount) |
| 309 | + if m and len(m.groups()): |
| 310 | + return m.group(1) |
| 311 | + return None |
0 commit comments