Skip to content

Vid pid details #369

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jul 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,12 @@ $ mbedls --json
"mount_point": "D:",
"platform_name": "K64F",
"platform_name_unique": "K64F[0]",
"product_id": "0204",
"serial_port": "COM18",
"target_id": "0240000032044e4500257009997b00386781000097969900",
"target_id_mbed_htm": "0240000032044e4500257009997b00386781000097969900",
"target_id_usb_id": "0240000032044e4500257009997b00386781000097969900"
"target_id_usb_id": "0240000032044e4500257009997b00386781000097969900",
"vendor_id": "0d28"
}
]
```
Expand Down Expand Up @@ -288,7 +290,7 @@ If set to `'+'`, the mocked platform is enabled. If `'-'`, the mocked platform i

## Logging

Mbed LS uses the Python `logging` module for all of its logging needs. Mbed LS uses the logger `"mbedls"` as its root, and all other loggers start with `"mbedls."`. Configuring the Python root logger automatically redirects all of the Mbed LS logs to the configured endpoint. When using the Python API, configure logging, such as by calling `logging.basicConfig()`.
Mbed LS uses the Python `logging` module for all of its logging needs. Mbed LS uses the logger `"mbedls"` as its root, and all other loggers start with `"mbedls."`. Configuring the Python root logger automatically redirects all of the Mbed LS logs to the configured endpoint. When using the Python API, configure logging, such as by calling `logging.basicConfig()`.

# Testing

Expand Down
16 changes: 9 additions & 7 deletions mbed_lstools/darwin.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ def _find_TTY(obj):


def _prune(current, keys):
""" Reduce the amount of data we have to sift through to only
""" Reduce the amount of data we have to sift through to only
include the specified keys, and children that contain the
specified keys
"""
pruned_current = {k: current[k] for k in keys if k in current}
pruned_children = list(
filter(None, [_prune(c, keys) for c in
filter(None, [_prune(c, keys) for c in
current.get('IORegistryEntryChildren', [])]))
keep_current = any(k in current for k in keys) or pruned_children
if keep_current:
Expand All @@ -63,7 +63,7 @@ def _prune(current, keys):


def _dfs_usb_info(obj, parents):
""" Find all of the usb info that we can from this particular IORegistry
""" Find all of the usb info that we can from this particular IORegistry
tree with depth first search (and searching the parent stack....)
"""
output = {}
Expand All @@ -80,10 +80,10 @@ def _dfs_usb_info(obj, parents):
if 'USB Serial Number' in parent:
usb_info['serial'] = parent['USB Serial Number']
if 'idVendor' in parent and 'idProduct' in parent:
usb_info['vendor_id'] = parent['idVendor']
usb_info['product_id'] = parent['idProduct']
usb_info['vendor_id'] = format(parent['idVendor'], '04x')
usb_info['product_id'] = format(parent['idProduct'], '04x')
if usb_info['serial']:
usb_info['tty'] = _find_TTY(parent)
usb_info['tty'] = _find_TTY(parent)
if all(usb_info.values()):
break
logger.debug("found usb info %r", usb_info)
Expand Down Expand Up @@ -111,7 +111,9 @@ def find_candidates(self):
{
'mount_point': mounts[v],
'serial_port': volumes[v]['tty'],
'target_id_usb_id': volumes[v].get('serial')
'target_id_usb_id': volumes[v].get('serial'),
'vendor_id': volumes[v].get('vendor_id'),
'product_id': volumes[v].get('product_id')
} for v in set(volumes.keys()) and set(mounts.keys())
if v in mounts and v in volumes
]
Expand Down
57 changes: 56 additions & 1 deletion mbed_lstools/linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
logger.addHandler(logging.NullHandler())
del logging

SYSFS_BLOCK_DEVICE_PATH = '/sys/class/block'

def _readlink(link):
content = os.readlink(link)
if content.startswith(".."):
Expand All @@ -45,18 +47,22 @@ def __init__(self, **kwargs):
r'(pci|usb)-[0-9a-zA-Z_-]*_(?P<usbid>[0-9a-zA-Z]*)-.*$')
self.mmp = re.compile(
r'(?P<dev>(/[^/ ]*)+) on (?P<dir>(/[^/ ]*)+) ')
self.udp = re.compile(r'[0-9]+-[0-9]+')

def find_candidates(self):
disk_ids = self._dev_by_id('disk')
serial_ids = self._dev_by_id('serial')
mount_ids = dict(self._fat_mounts())
usb_info = self._sysfs_block_devices(disk_ids.values())
logger.debug("Mount mapping %r", mount_ids)

return [
{
'mount_point' : mount_ids.get(disk_dev),
'serial_port' : serial_ids.get(disk_uuid),
'target_id_usb_id' : disk_uuid
'target_id_usb_id' : disk_uuid,
'vendor_id': usb_info[disk_dev]['vendor_id'],
'product_id': usb_info[disk_dev]['product_id']
} for disk_uuid, disk_dev in disk_ids.items()
]

Expand Down Expand Up @@ -104,3 +110,52 @@ def _hex_ids(self, dev_list):
match = self.nlp.search(dl)
if match:
yield match.group("usbid"), _readlink(dl)

def _sysfs_block_devices(self, block_devices):
device_names = { os.path.basename(d): d for d in block_devices }
sysfs_block_devices = set(os.listdir(SYSFS_BLOCK_DEVICE_PATH))
common_device_names = sysfs_block_devices.intersection(set(device_names.keys()))
result = {}

for common_device_name in common_device_names:
sysfs_path = os.path.join(SYSFS_BLOCK_DEVICE_PATH, common_device_name)
full_sysfs_path = os.readlink(sysfs_path)
path_parts = full_sysfs_path.split('/')

end_index = None
for index, part in enumerate(path_parts):
if self.udp.search(part):
end_index = index
break

if end_index == None:
logger.debug('Did not find suitable usb folder for usb info: %s', full_sysfs_path)
continue

usb_info_rel_path = path_parts[:end_index + 1]
usb_info_path = os.path.join(SYSFS_BLOCK_DEVICE_PATH, os.sep.join(usb_info_rel_path))

vendor_id = None
product_id = None

vendor_id_file_paths = os.path.join(usb_info_path, 'idVendor')
product_id_file_paths = os.path.join(usb_info_path, 'idProduct')

try:
with open(vendor_id_file_paths, 'r') as vendor_file:
vendor_id = vendor_file.read().strip()
except OSError as e:
logger.debug('Failed to read vendor id file %s weith error:', vendor_id_file_paths, e)

try:
with open(product_id_file_paths, 'r') as product_file:
product_id = product_file.read().strip()
except OSError as e:
logger.debug('Failed to read product id file %s weith error:', product_id_file_paths, e)

result[device_names[common_device_name]] = {
'vendor_id': vendor_id,
'product_id': product_id
}

return result
30 changes: 30 additions & 0 deletions mbed_lstools/windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ def _determine_valid_non_composite_devices(devices, target_id_usb_id_mount_point
'target_id_usb_id': target_id_usb_id,
'mount_point': target_id_usb_id_mount_point_map[target_id_usb_id]
}

candidates[target_id_usb_id].update(_vid_pid_path_to_usb_info(device['vid_pid_path']))
except KeyError:
pass

Expand All @@ -180,6 +182,32 @@ def _determine_subdevice_capability(key):
logger.debug('Unknown capabilities from the following ids: %s', compatible_ids)
return None


def _vid_pid_path_to_usb_info(vid_pid_path):
"""! Provide the vendor ID and product ID of a device based on its entry in the registry
@return Returns {'vendor_id': '<vendor ID>', 'product': '<product ID>'}
@details If the vendor ID or product ID can't be determined, they will be returned
as None.
"""
result = {
'vendor_id': None,
'product_id': None
}

for component in vid_pid_path.split('&'):
component_part = component.lower().split('_')

if len(component_part) != 2:
logger.debug('Unexpected VID/PID string structure %s', component)
break

if component_part[0] == 'vid':
result['vendor_id'] = component_part[1]
elif component_part[0] == 'pid':
result['product_id'] = component_part[1]

return result

# =============================== Start Registry Functions ====================================

def _iter_keys_as_str(key):
Expand Down Expand Up @@ -350,6 +378,7 @@ def find_candidates(self):
if capability == 'msd':
candidates[entry_data['target_id_usb_id']]['mount_point'] = \
target_id_usb_id_mount_point_map[entry_data['target_id_usb_id']]
candidates[entry_data['target_id_usb_id']].update(_vid_pid_path_to_usb_info(vid_pid_path))
elif capability == 'serial':
try:
device_parameters_key = winreg.OpenKey(subdevice_key,
Expand All @@ -361,6 +390,7 @@ def find_candidates(self):
try:
candidates[entry_data['target_id_usb_id']]['serial_port'], _ = winreg.QueryValueEx(
device_parameters_key, 'PortName')
candidates[entry_data['target_id_usb_id']].update(_vid_pid_path_to_usb_info(vid_pid_path))
except OSError:
logger.debug('"PortName" value not found under serial device entry')
continue
Expand Down
4 changes: 3 additions & 1 deletion test/os_darwin.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,5 +165,7 @@ def do_popen(command, *args, **kwargs):
candidates = self.darwin.find_candidates()
self.assertIn({'mount_point': '/Volumes/DAPLINK',
'serial_port': '/dev/tty.usbmodem1422',
'target_id_usb_id': '0240000034544e45003a00048e3800525a91000097969900'},
'target_id_usb_id': '0240000034544e45003a00048e3800525a91000097969900',
'vendor_id': '0d28',
'product_id': '0204'},
candidates)
Loading