Skip to content

Commit a404bdc

Browse files
authored
Merge pull request #933 from Bastian-Krause/bst/dfu
Introduce DFUDevice, DFUDriver
2 parents 0cae479 + 817166e commit a404bdc

File tree

11 files changed

+152
-0
lines changed

11 files changed

+152
-0
lines changed

CHANGES.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ New Features in 0.5.0
2323
which expects ``boot_secret`` without new line with new ``boot_secret_nolf``
2424
boolean config option.
2525
- labgrid-client add-match/add-named-match check for duplicate matches
26+
- `DFUDriver` has been added to communicate with a `DFUDevice`, a device in DFU
27+
(Device Firmware Upgrade) mode.
28+
- ``labgrid-client dfu`` added to allow communcation with devices in DFU mode.
2629

2730
Bug fixes in 0.5.0
2831
~~~~~~~~~~~~~~~~~~

doc/configuration.rst

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,23 @@ Arguments:
625625
Used by:
626626
- `AndroidFastbootDriver`_
627627

628+
DFUDevice
629+
~~~~~~~~~
630+
A DFUDevice resource describes a USB device in DFU (Device Firmware Upgrade)
631+
mode.
632+
633+
.. code-block:: yaml
634+
635+
DFUDevice:
636+
match:
637+
ID_PATH: pci-0000:06:00.0-usb-0:1.3.2:1.0
638+
639+
Arguments:
640+
- match (dict): key and value pairs for a udev match, see `udev Matching`_
641+
642+
Used by:
643+
- `DFUDriver`_
644+
628645
USBNetworkInterface
629646
~~~~~~~~~~~~~~~~~~~~
630647
A USBNetworkInterface resource describes a USB network adapter (such as
@@ -1556,6 +1573,25 @@ Arguments:
15561573
same as the fastboot default, which is computed after querying the target's
15571574
``max-download-size`` variable.
15581575

1576+
DFUDriver
1577+
~~~~~~~~~
1578+
A DFUDriver allows the download of images to a device in DFU (Device Firmware
1579+
Upgrade) mode.
1580+
1581+
Binds to:
1582+
dfu:
1583+
- `DFUDevice`_
1584+
1585+
Implements:
1586+
- None (yet)
1587+
1588+
.. code-block:: yaml
1589+
1590+
DFUDriver: {}
1591+
1592+
Arguments:
1593+
- None
1594+
15591595
OpenOCDDriver
15601596
~~~~~~~~~~~~~
15611597
An OpenOCDDriver controls OpenOCD to bootstrap a target with a bootloader.

labgrid/driver/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from .externalconsoledriver import ExternalConsoleDriver
88
from .exception import CleanUpError, ExecutionError
99
from .fastbootdriver import AndroidFastbootDriver
10+
from .dfudriver import DFUDriver
1011
from .openocddriver import OpenOCDDriver
1112
from .quartushpsdriver import QuartusHPSDriver
1213
from .flashromdriver import FlashromDriver

labgrid/driver/dfudriver.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# pylint: disable=no-member
2+
import attr
3+
4+
from ..factory import target_factory
5+
from ..step import step
6+
from .common import Driver
7+
from ..util.managedfile import ManagedFile
8+
from ..util.helper import processwrapper
9+
10+
11+
@target_factory.reg_driver
12+
@attr.s(eq=False)
13+
class DFUDriver(Driver):
14+
bindings = {
15+
"dfu": {"DFUDevice", "NetworkDFUDevice"},
16+
}
17+
18+
def __attrs_post_init__(self):
19+
super().__attrs_post_init__()
20+
# FIXME make sure we always have an environment or config
21+
if self.target.env:
22+
self.tool = self.target.env.config.get_tool('dfu-util') or 'dfu-util'
23+
else:
24+
self.tool = 'dfu-util'
25+
26+
def _get_dfu_prefix(self):
27+
return self.dfu.command_prefix + [
28+
self.tool,
29+
"-p", self.dfu.path,
30+
]
31+
32+
def on_activate(self):
33+
pass
34+
35+
def on_deactivate(self):
36+
pass
37+
38+
@Driver.check_active
39+
@step(args=['altsetting', 'filename'])
40+
def download(self, altsetting, filename):
41+
mf = ManagedFile(filename, self.dfu)
42+
mf.sync_to_resource()
43+
44+
processwrapper.check_output(
45+
self._get_dfu_prefix() + ['--alt', str(altsetting), '--download', mf.get_remote_path()],
46+
print_on_silent_log=True
47+
)
48+
49+
@step()
50+
def detach(self, altsetting):
51+
processwrapper.check_output(
52+
self._get_dfu_prefix() + ['--alt', str(altsetting), '--detach']
53+
)
54+
55+
@step()
56+
def list(self):
57+
processwrapper.check_output(
58+
self._get_dfu_prefix() + ['--list'],
59+
print_on_silent_log=True
60+
)

labgrid/remote/client.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -913,6 +913,25 @@ async def console(self, place, target):
913913
await asyncio.sleep(1.0)
914914
console.needs_target = True
915915

916+
def dfu(self):
917+
place = self.get_acquired_place()
918+
target = self._get_target(place)
919+
if self.args.action == 'download' and not self.args.filename:
920+
raise UserError('not enough arguments for dfu download')
921+
from ..driver.dfudriver import DFUDriver
922+
try:
923+
drv = target.get_driver(DFUDriver)
924+
except NoDriverFoundError:
925+
drv = DFUDriver(target, name=None)
926+
drv.dfu.timeout = self.args.wait
927+
target.activate(drv)
928+
if self.args.action == 'download':
929+
drv.download(self.args.altsetting, os.path.abspath(self.args.filename))
930+
if self.args.action == 'detach':
931+
drv.detach(self.args.altsetting)
932+
if self.args.action == 'list':
933+
drv.list()
934+
916935
def fastboot(self):
917936
place = self.get_acquired_place()
918937
args = self.args.fastboot_args
@@ -1697,6 +1716,15 @@ def main():
16971716
subparser.add_argument('--logfile', metavar="FILE", help="Log output to FILE", default=None)
16981717
subparser.set_defaults(func=ClientSession.console)
16991718

1719+
subparser = subparsers.add_parser('dfu',
1720+
help="communicate with device in DFU mode")
1721+
subparser.add_argument('action', choices=['download', 'detach', 'list'], help='action')
1722+
subparser.add_argument('altsetting', help='altsetting name or number (download, detach only)',
1723+
nargs='?')
1724+
subparser.add_argument('filename', help='file to write into device (download only)', nargs='?')
1725+
subparser.add_argument('--wait', type=float, default=10.0)
1726+
subparser.set_defaults(func=ClientSession.dfu)
1727+
17001728
subparser = subparsers.add_parser('fastboot',
17011729
help="run fastboot")
17021730
subparser.add_argument('fastboot_args', metavar='ARG', nargs=argparse.REMAINDER,

labgrid/remote/exporter.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,7 @@ def _get_params(self):
492492
return p
493493

494494
exports["AndroidFastboot"] = USBGenericExport
495+
exports["DFUDevice"] = USBGenericExport
495496
exports["IMXUSBLoader"] = USBGenericExport
496497
exports["MXSUSBLoader"] = USBGenericExport
497498
exports["RKUSBLoader"] = USBGenericExport

labgrid/resource/remote.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,14 @@ def __attrs_post_init__(self):
119119
super().__attrs_post_init__()
120120

121121

122+
@target_factory.reg_resource
123+
@attr.s(eq=False)
124+
class NetworkDFUDevice(RemoteUSBResource):
125+
def __attrs_post_init__(self):
126+
self.timeout = 10.0
127+
super().__attrs_post_init__()
128+
129+
122130
@target_factory.reg_resource
123131
@attr.s(eq=False)
124132
class NetworkIMXUSBLoader(RemoteUSBResource):

labgrid/resource/suggest.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
USBVideo,
1212
IMXUSBLoader,
1313
AndroidFastboot,
14+
DFUDevice,
1415
USBSDMuxDevice,
1516
USBSDWireDevice,
1617
AlteraUSBBlaster,
@@ -41,6 +42,7 @@ def __init__(self, args):
4142
self.resources.append(USBVideo(**args))
4243
self.resources.append(IMXUSBLoader(**args))
4344
self.resources.append(AndroidFastboot(**args))
45+
self.resources.append(DFUDevice(**args))
4446
self.resources.append(USBMassStorage(**args))
4547
self.resources.append(USBSDMuxDevice(**args))
4648
self.resources.append(USBSDWireDevice(**args))

labgrid/resource/udev.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,15 @@ def filter_match(self, device):
322322
return False
323323
return super().filter_match(device)
324324

325+
@target_factory.reg_resource
326+
@attr.s(eq=False)
327+
class DFUDevice(USBResource):
328+
def filter_match(self, device):
329+
if ':fe0102:' not in device.properties.get('ID_USB_INTERFACES', ''):
330+
return False
331+
332+
return super().filter_match(device)
333+
325334
@target_factory.reg_resource
326335
@attr.s(eq=False)
327336
class USBNetworkInterface(USBResource, NetworkInterface):

man/labgrid-client.1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ not at all.
174174
.sp
175175
\fBconsole (con)\fP Connect to the console
176176
.sp
177+
\fBdfu\fP arg Run dfu commands
178+
.sp
177179
\fBfastboot\fP arg Run fastboot with argument
178180
.sp
179181
\fBflashscript\fP script arg Run arbitrary script with arguments to flash device

0 commit comments

Comments
 (0)