Skip to content

Commit

Permalink
Merge pull request #15 from labgrid-project/dev
Browse files Browse the repository at this point in the history
improve USB device handling and remote tools
  • Loading branch information
Emantor committed Mar 2, 2017
2 parents ded90bb + 9a7a09d commit 558ec88
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 58 deletions.
4 changes: 2 additions & 2 deletions labgrid/remote/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def print_resources(self):
continue
for group_name, group in sorted(groups.items()):
for resource_name, resource in sorted(group.items()):
if not resource.avail:
if not (resource.avail or self.args.verbose >= 2):
continue
if self.args.acquired and resource.acquired is None:
continue
Expand Down Expand Up @@ -456,7 +456,7 @@ def main():
subparser = subparsers.add_parser('resources')
subparser.add_argument('-a', '--acquired', action='store_true')
subparser.add_argument('-e', '--exporter')
subparser.add_argument('-v', '--verbose', action='store_true')
subparser.add_argument('-v', '--verbose', action='count')
subparser.add_argument('match', nargs='?')
subparser.set_defaults(func=ClientSession.print_resources)

Expand Down
18 changes: 9 additions & 9 deletions labgrid/remote/exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def get_free_port():


exports = {}

reexec = False

@attr.s
class ResourceExport(ResourceEntry):
Expand Down Expand Up @@ -187,19 +187,17 @@ def onLeave(self, details):
"""Cleanup after leaving the coordinator connection"""
self.poll_task.cancel()
yield from asyncio.wait([self.poll_task])
#for resource in self.resources.values():
# try:
# resource.invalidate()
# except ResourceStatusError:
# pass
super().onLeave(details)

@asyncio.coroutine
def onDisconnect(self):
#self.uevent_task.cancel()
#yield from asyncio.wait([self.uevent_task])
self.loop.stop()
print("connection lost")
global reexec
reexec = True
self.poll_task.cancel()
yield from asyncio.wait([self.poll_task])
yield from asyncio.sleep(0.5) # give others a chance to clean up
self.loop.stop()

@asyncio.coroutine
def acquire(self, group_name, resource_name):
Expand Down Expand Up @@ -305,6 +303,8 @@ def main():
#loop.set_debug(True)
runner = ApplicationRunner(url=args.crossbar, realm="realm1", extra=extra)
runner.run(ExporterSession)
if reexec:
exit(100)


if __name__ == "__main__":
Expand Down
122 changes: 75 additions & 47 deletions labgrid/resource/udev.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,51 +37,92 @@ class USBResource(ManagedResource):
manager_cls = UdevManager

match = attr.ib(validator=attr.validators.instance_of(dict), hash=False)
_device = attr.ib(default=None, hash=False)
device = attr.ib(default=None, hash=False)

def __attrs_post_init__(self):
self.match.setdefault('SUBSYSTEM', 'usb')
super().__attrs_post_init__()

def filter_match(self, device):
return True

def try_match(self, device):
def match_ancestors(key, value):
for ancestor in device.ancestors:
if ancestor.get(key) == value:
if self.device:
if self.device.sys_path != device.sys_path:
return False
else: # new device
def match_single(dev, key, value):
if dev.get(key) == value:
return True
elif dev.attributes.get(key) == value:
return True
elif getattr(dev, key, None) == value:
return True
return False
for k, v in self.match.items():
if k.startswith('@') and match_ancestors(k[1:], v):
continue
elif device.get(k) == v:
continue
else:
return False
print(" found match: {}".format(self))
self.device = device
return True

def on_device_set(self):
raise NotImplementedError()
def match_ancestors(key, value):
for ancestor in device.ancestors:
if match_single(ancestor, key, value):
return True
return False

@property
def device(self):
return self._device
for k, v in self.match.items():
if k.startswith('@'):
if match_ancestors(k[1:], v):
continue
elif match_single(device, k, v):
continue
else:
return False
if not self.filter_match(device):
return False
print(" found match: {}".format(self))
if device.action in [None, 'add', 'change']:
self.avail = True
self.device = device
self.update()
else:
self.avail = False
self.device = None
return True

@device.setter
def device(self, value):
self._device = value
self.on_device_set()
def update(self):
pass

@property
def busnum(self):
if self._device:
if self.device:
return int(self.device.get('BUSNUM'))

@property
def devnum(self):
if self._device:
if self.device:
return int(self.device.get('DEVNUM'))

def _get_usb_device(self):
device = self.device
if self.device and (self.device.subsystem != 'usb' or self.device.device_type != 'usb_device'):
device = self.device.find_parent('usb', 'usb_device')
return device

@property
def path(self):
device = self._get_usb_device()
if device:
return str(device.sys_name)

@property
def vendor_id(self):
device = self._get_usb_device()
if device:
return int(device.get('ID_VENDOR_ID'), 16)

@property
def model_id(self):
device = self._get_usb_device()
if device:
return int(device.get('ID_MODEL_ID'), 16)


@target_factory.reg_resource
@attr.s
Expand All @@ -90,9 +131,9 @@ def __attrs_post_init__(self):
self.match['SUBSYSTEM'] = 'tty'
super().__attrs_post_init__()

def on_device_set(self):
def update(self):
super().update()
self.port = self.device.device_node
self.avail = self.device.action in [None, 'add', 'change']

@target_factory.reg_resource
@attr.s
Expand All @@ -103,52 +144,39 @@ def __attrs_post_init__(self):
self.match['@SUBSYSTEM'] = 'usb'
super().__attrs_post_init__()

def on_device_set(self):
self.avail = True

@property
def path(self):
return self.device.device_node

@target_factory.reg_resource
@attr.s
class IMXUSBLoader(USBResource):
def try_match(self, device):
def filter_match(self, device):
if device.get('ID_VENDOR_ID') != "15a2":
return False
if device.get('ID_MODEL_ID') not in ["0054", "0061"]:
return False
return super().try_match(device)

def on_device_set(self):
self.avail = True
return super().filter_match(device)


@target_factory.reg_resource
@attr.s
class MXSUSBLoader(USBResource):
def try_match(self, device):
def filter_match(self, device):
if device.get('ID_VENDOR_ID') != "066f":
return False
if device.get('ID_MODEL_ID') not in ["3780"]:
return False

return super().try_match(device)

def on_device_set(self):
self.avail = True
return super().filter_match(device)

@target_factory.reg_resource
@attr.s
class AndroidFastboot(USBResource):
def try_match(self, device):
def filter_match(self, device):
if device.get('ID_VENDOR_ID') != "1d6b":
return False
if device.get('ID_VENDOR_ID') != "0104":
if device.get('ID_MODEL_ID') != "0104":
return False
while device.parent and device.parent.driver != 'usb':
device = device.parent
return super().try_match(device)

def on_device_set(self):
self.avail = True
return super().filter_match(device)

0 comments on commit 558ec88

Please sign in to comment.