Skip to content

Commit 8932387

Browse files
committed
Merge pull request #1 from autopulated/master
Mac OS X Support
2 parents 3c9a511 + 4786016 commit 8932387

File tree

2 files changed

+169
-2
lines changed

2 files changed

+169
-2
lines changed

mbed_lstools/lstools_darwin.py

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
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+
import plistlib
21+
22+
from lstools_base import MbedLsToolsBase
23+
24+
class MbedLsToolsDarwin(MbedLsToolsBase):
25+
""" MbedLsToolsDarwin supports mbed-enabled platforms detection on Mac OS X
26+
"""
27+
28+
mbed_volume_name_match = re.compile(r'\bmbed\b', re.I)
29+
30+
def list_mbeds(self):
31+
""" returns mbed list with platform names if possible
32+
"""
33+
34+
result = []
35+
36+
# {volume_id: {serial:, vendor_id:, product_id:, tty:}}
37+
volumes = self.get_mbed_volumes()
38+
#print 'volumes:', volumes
39+
40+
# {volume_id: mount_point}
41+
mounts = self.get_mount_points()
42+
#print "mounts:", mounts
43+
44+
# put together all of that info into the expected format:
45+
result = [
46+
{
47+
'mount_point': mounts[v],
48+
'serial_port': volumes[v]['tty'],
49+
'target_id': self.target_id(volumes[v]),
50+
'platform_name': self.platform_name(self.target_id(volumes[v]))
51+
} for v in volumes
52+
]
53+
54+
# if we're missing any platform names, try to fill those in by reading
55+
# mbed.htm:
56+
for m in result:
57+
if m['mount_point'] and not m['platform_name']:
58+
htm_target_id = self.get_mbed_htm_target_id(m['mount_point'])
59+
if htm_target_id:
60+
m['target_id'] = htm_target_id
61+
m['platform_name'] = self.platform_name(htm_target_id[:4])
62+
63+
return result
64+
65+
66+
def get_mount_points(self):
67+
''' Returns map {volume_id: mount_point} '''
68+
69+
# list disks, this gives us disk name, and volume name + mount point:
70+
diskutil_ls = subprocess.Popen(['diskutil', 'list', '-plist'], stdout=subprocess.PIPE)
71+
disks = plistlib.readPlist(diskutil_ls.stdout)
72+
diskutil_ls.wait()
73+
74+
r = {}
75+
76+
for disk in disks['AllDisksAndPartitions']:
77+
mount_point = None
78+
if 'MountPoint' in disk:
79+
mount_point = disk['MountPoint']
80+
r[disk['DeviceIdentifier']] = mount_point
81+
82+
return r
83+
84+
85+
def get_mbed_volumes(self):
86+
''' returns a map {volume_id: {serial:, vendor_id:, product_id:, tty:}'''
87+
88+
# to find all the possible mbed volumes, we look for registry entries
89+
# under the USB bus which have a "BSD Name" that starts with "disk"
90+
# (i.e. this is a USB disk), and have a IORegistryEntryName that
91+
# matches /\cmbed/
92+
# Once we've found a disk, we can search up for a parent with a valid
93+
# serial number, and then search down again to find a tty that's part
94+
# of the same composite device
95+
# ioreg -a -r -n "AppleUSBXHCI" -l
96+
ioreg_usb = subprocess.Popen(['ioreg', '-a', '-r', '-n', 'AppleUSBXHCI', '-l'], stdout=subprocess.PIPE)
97+
usb_bus = plistlib.readPlist(ioreg_usb.stdout)
98+
ioreg_usb.wait()
99+
100+
r = {}
101+
102+
def findTTYRecursive(obj):
103+
''' return the first tty (AKA IODialinDevice) that we can find in the
104+
children of the specified object, or None if no tty is present.
105+
'''
106+
if 'IODialinDevice' in obj:
107+
return obj['IODialinDevice']
108+
if 'IORegistryEntryChildren' in obj:
109+
for child in obj['IORegistryEntryChildren']:
110+
found = findTTYRecursive(child)
111+
if found:
112+
return found
113+
return None
114+
115+
def findVolumesRecursive(obj, parents):
116+
if 'BSD Name' in obj and obj['BSD Name'].startswith('disk') and \
117+
self.mbed_volume_name_match.search(obj['IORegistryEntryName']):
118+
disk_id = obj['BSD Name']
119+
# now search up through our parents until we find a serial number:
120+
usb_info = {
121+
'serial':None,
122+
'vendor_id':None,
123+
'product_id':None,
124+
'tty':None,
125+
}
126+
for parent in [obj] + parents:
127+
if 'USB Serial Number' in parent:
128+
usb_info['serial'] = parent['USB Serial Number']
129+
if 'idVendor' in parent and 'idProduct' in parent:
130+
usb_info['vendor_id'] = parent['idVendor']
131+
usb_info['product_id'] = parent['idProduct']
132+
if usb_info['serial']:
133+
# stop at the first one we find (or we'll pick up hubs,
134+
# etc.), but first check for a tty that's also a child of
135+
# this device:
136+
usb_info['tty'] = findTTYRecursive(parent)
137+
break
138+
r[disk_id] = usb_info
139+
if 'IORegistryEntryChildren' in obj:
140+
for child in obj['IORegistryEntryChildren']:
141+
findVolumesRecursive(child, [obj] + parents)
142+
143+
for obj in usb_bus:
144+
findVolumesRecursive(obj, [])
145+
146+
return r
147+
148+
149+
def target_id(self, usb_info):
150+
if usb_info['serial'] is not None:
151+
return usb_info['serial']
152+
else:
153+
return None
154+
155+
def platform_name(self, target_id):
156+
if target_id[:4] in self.manufacture_ids:
157+
return self.manufacture_ids[target_id[:4]]
158+
159+

mbed_lstools/main.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from lstools_win7 import MbedLsToolsWin7
1111
from lstools_ubuntu import MbedLsToolsUbuntu
12+
from lstools_darwin import MbedLsToolsDarwin
1213

1314

1415
def create():
@@ -19,6 +20,7 @@ def create():
1920
if mbed_os is not None:
2021
if mbed_os == 'Windows7': result = MbedLsToolsWin7()
2122
elif mbed_os == 'Ubuntu': result = MbedLsToolsUbuntu()
23+
elif mbed_os == 'Darwin': result = MbedLsToolsDarwin()
2224
return result
2325

2426
def mbed_os_support():
@@ -31,6 +33,8 @@ def mbed_os_support():
3133
result = 'Windows7'
3234
elif (os_info[0] == 'posix' and os_info[1] == 'Linux' and ('Ubuntu' in os_info[3])):
3335
result = 'Ubuntu'
36+
elif (os_info[0] == 'posix' and os_info[1] == 'Darwin'):
37+
result = 'Darwin'
3438
return result
3539

3640
def mbed_lstools_os_info():
@@ -52,13 +56,13 @@ def cmd_parser_setup():
5256
dest='simple',
5357
default=False,
5458
action="store_true",
55-
help='Pareser friendly verbose mode')
59+
help='Parser friendly verbose mode')
5660

5761
parser.add_option('', '--json',
5862
dest='json',
5963
default=False,
6064
action="store_true",
61-
help='JSON formated output')
65+
help='JSON formatted output')
6266

6367
(opts, args) = parser.parse_args()
6468
return (opts, args)
@@ -71,6 +75,10 @@ def mbedls_main():
7175
(opts, args) = cmd_parser_setup()
7276
mbeds = create()
7377

78+
if mbeds is None:
79+
sys.stderr.write('This platform is not supported! Pull requests welcome at github.com/ARMmbed/mbed-ls\n')
80+
sys.exit(-1)
81+
7482
if opts.json:
7583
mbeds_data = mbeds.list_mbeds()
7684
print json.dumps(mbeds_data, indent=4, sort_keys=True)

0 commit comments

Comments
 (0)