From 2e6123a7f8ddfe99d214b24fc07a2ef3354abfd1 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 13 May 2010 12:10:24 -0700 Subject: work on usrp2 card burner, uses blockdev and /proc/paritions to check for devices, windows tweaks as well --- host/utils/usrp2_card_burner.py | 120 +++++++++++++++++++++++++++------------- 1 file changed, 83 insertions(+), 37 deletions(-) diff --git a/host/utils/usrp2_card_burner.py b/host/utils/usrp2_card_burner.py index 99cdcb626..5f876c7bc 100755 --- a/host/utils/usrp2_card_burner.py +++ b/host/utils/usrp2_card_burner.py @@ -1,9 +1,24 @@ #!/usr/bin/env python +# +# Copyright 2010 Ettus Research LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# ######################################################################## # Deal with raw devices ######################################################################## -import glob import platform import tempfile import subprocess @@ -15,6 +30,19 @@ MAX_FILE_SIZE = 1 * (2**20) # maximum number of bytes we'll burn to a slot FPGA_OFFSET = 0 # offset in flash to fpga image FIRMWARE_OFFSET = 1 * (2**20) # offset in flash to firmware image +MAX_SD_CARD_SIZE = 2048e6 # bytes (any bigger is sdhc) + +def command(*args): + p = subprocess.Popen( + args, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) + ret = p.wait() + verbose = p.stdout.read() + if ret != 0: raise Exception, verbose + return verbose + def get_dd_path(): if platform.system() == 'Windows': dd_path = os.path.join(tempfile.gettempdir(), 'dd.exe') @@ -26,26 +54,57 @@ def get_dd_path(): return 'dd' def get_raw_device_hints(): + #################################################################### + # Platform Windows: parse the output of dd.exe --list + #################################################################### if platform.system() == 'Windows': - output = subprocess.Popen( - [get_dd_path(), '--list'],#, '--filter=removable'], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - ).stdout.read() volumes = list() + try: output = command(get_dd_path(), '--list') + except: return volumes + + #coagulate info for identical links + link_to_info = dict() for info in output.replace('\r', '').split('\n\\\\'): - if 'removeable' not in info.lower(): continue if 'link to' not in info: continue + link = info.split('link to')[-1].split()[0].strip() + if not link_to_info.has_key(link): link_to_info[link] = '\n\n' + link_to_info[link] += info + + #parse info only keeping viable volumes + for link, info in link_to_info.iteritems(): + if 'removable' not in info.lower(): continue if 'size is' in info: - size = info.split('size is')[-1].split()[0] - if int(size) > 2048e6: continue + size = info.split('size is')[-1].split()[0].strip() + if int(size) > MAX_SD_CARD_SIZE: continue if 'Mounted on' in info: volumes.append(info.split('Mounted on')[-1].split()[0]) continue - volumes.append(info.split('link to')[-1].split()[0]) - return volumes + volumes.append(link) + + return sorted(set(volumes)) + + #################################################################### + # Platform Linux: call blockdev on all the /dev/sd* devices + #################################################################### if platform.system() == 'Linux': - return sorted(set(filter(lambda sd: not sd[-1].isdigit(), glob.glob("/dev/sd*")))) + devs = list() + try: output = open('/proc/partitions', 'r').read() + except: return devs + for line in output.splitlines(): + try: + major, minor, blocks, name = line.split() + if name[-1].isdigit(): assert int(minor) == 0 + dev = os.path.join('/dev/', name) + size = int(command('blockdev', '--getsz', dev))*512 + assert size <= MAX_SD_CARD_SIZE + except: continue + devs.append(dev) + + return sorted(set(devs)) + + #################################################################### + # Platform Others: + #################################################################### return () def verify_image(image_file, device_file, offset): @@ -55,22 +114,14 @@ def verify_image(image_file, device_file, offset): tmp_file = tmp[1] #execute a dd subprocess - args = [ + verbose = command( get_dd_path(), "of=%s"%tmp_file, "if=%s"%device_file, "skip=%d"%offset, "bs=%d"%SECTOR_SIZE, "count=%d"%(MAX_FILE_SIZE/SECTOR_SIZE), - ] - p = subprocess.Popen( - args, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, ) - ret = p.wait() - verbose = p.stdout.read() - if ret != 0: raise Exception, verbose #read in the image and readback img_data = open(image_file, 'rb').read() @@ -81,24 +132,13 @@ def verify_image(image_file, device_file, offset): return 'Verification Passed:\n%s'%verbose def write_image(image_file, device_file, offset): - args = [ + return command( get_dd_path(), "if=%s"%image_file, "of=%s"%device_file, "seek=%d"%offset, "bs=%d"%SECTOR_SIZE, - ] - p = subprocess.Popen( - args, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, ) - ret = p.wait() - verbose = p.stdout.read() - - #get the verbose back to the caller - if ret != 0: raise Exception, verbose - return verbose def write_and_verify(image_file, device_file, offset): if os.path.getsize(image_file) > MAX_FILE_SIZE: @@ -117,10 +157,10 @@ def write_and_verify(image_file, device_file, offset): def burn_sd_card(dev, fw, fpga): verbose = '' - if fw: verbose += 'Burn firmware image verbose:\n%s\n'%write_and_verify( + if fw: verbose += 'Burn firmware image:\n%s\n'%write_and_verify( image_file=fw, device_file=dev, offset=FIRMWARE_OFFSET ) - if fpga: verbose += 'Burn fpga image verbose:\n%s\n'%write_and_verify( + if fpga: verbose += 'Burn fpga image:\n%s\n'%write_and_verify( image_file=fpga, device_file=dev, offset=FPGA_OFFSET ) return verbose @@ -171,10 +211,11 @@ class DeviceEntryWidget(Tkinter.Frame): def __init__(self, root, text=''): Tkinter.Frame.__init__(self, root) + Tkinter.Button(self, text="Reload Possible Devices", command=self._reload_cb).pack() + self._hints = Tkinter.Listbox(self) self._hints.bind("<>", self._listbox_cb) - for hint in get_raw_device_hints(): - self._hints.insert(Tkinter.END, hint) + self._reload_cb() self._hints.pack(expand=Tkinter.YES, fill=Tkinter.X) frame = Tkinter.Frame(self) @@ -185,6 +226,11 @@ class DeviceEntryWidget(Tkinter.Frame): self._entry.insert(Tkinter.END, text) self._entry.pack(side=Tkinter.LEFT) + def _reload_cb(self): + self._hints.delete(0, Tkinter.END) + for hint in get_raw_device_hints(): + self._hints.insert(Tkinter.END, hint) + def _listbox_cb(self, event): try: sel = self._hints.get(self._hints.curselection()[0]) -- cgit v1.2.3