From 9fd30e928e3599b43b3d9bbd7be82793a62d7944 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 12 May 2010 18:59:15 -0700 Subject: Added card burner python app with gui and windows support. --- host/utils/CMakeLists.txt | 12 +- host/utils/usrp2_addr_burner.cpp | 90 +++++++++++++ host/utils/usrp2_burner.cpp | 90 ------------- host/utils/usrp2_card_burner.py | 285 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 383 insertions(+), 94 deletions(-) create mode 100644 host/utils/usrp2_addr_burner.cpp delete mode 100644 host/utils/usrp2_burner.cpp create mode 100755 host/utils/usrp2_card_burner.py (limited to 'host/utils') diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index 3c2236379..d28576e8c 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -19,12 +19,16 @@ ADD_EXECUTABLE(uhd_find_devices uhd_find_devices.cpp) TARGET_LINK_LIBRARIES(uhd_find_devices uhd) INSTALL(TARGETS uhd_find_devices RUNTIME DESTINATION ${RUNTIME_DIR}) -ADD_EXECUTABLE(usrp2_burner usrp2_burner.cpp) -TARGET_LINK_LIBRARIES(usrp2_burner uhd) -INSTALL(TARGETS usrp2_burner RUNTIME DESTINATION ${PKG_DATA_DIR}/utils) +ADD_EXECUTABLE(usrp2_addr_burner usrp2_addr_burner.cpp) +TARGET_LINK_LIBRARIES(usrp2_addr_burner uhd) +INSTALL(TARGETS usrp2_addr_burner RUNTIME DESTINATION ${PKG_DATA_DIR}/utils) ADD_EXECUTABLE(uhd_burn_db_eeprom uhd_burn_db_eeprom.cpp) TARGET_LINK_LIBRARIES(uhd_burn_db_eeprom uhd) INSTALL(TARGETS uhd_burn_db_eeprom RUNTIME DESTINATION ${PKG_DATA_DIR}/utils) -INSTALL(PROGRAMS usrp2_recovery.py DESTINATION ${PKG_DATA_DIR}/utils) +INSTALL(PROGRAMS + usrp2_recovery.py + usrp2_card_burner.py + DESTINATION ${PKG_DATA_DIR}/utils +) diff --git a/host/utils/usrp2_addr_burner.cpp b/host/utils/usrp2_addr_burner.cpp new file mode 100644 index 000000000..08fc1e218 --- /dev/null +++ b/host/utils/usrp2_addr_burner.cpp @@ -0,0 +1,90 @@ +// +// 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 . +// + +#include +#include +#include +#include +#include +#include + +namespace po = boost::program_options; + +int UHD_SAFE_MAIN(int argc, char *argv[]){ + po::options_description desc("Allowed options"); + desc.add_options() + ("help", "help message") + ("addr", po::value(), "resolvable network address") + ("new-ip", po::value(), "new ip address (optional)") + ("new-mac", po::value(), "new mac address (optional)") + ; + + po::variables_map vm; + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + //print the help message + if (vm.count("help")){ + std::cout << boost::format("USRP2 Address Burner %s") % desc << std::endl; + return ~0; + } + + //load the options into the address + uhd::device_addr_t device_addr; + if (vm.count("addr")){ + device_addr["addr"] = vm["addr"].as(); + } + else{ + std::cerr << "Error: missing addr option" << std::endl; + return ~0; + } + + //create a usrp2 device + uhd::device::sptr u2_dev = uhd::usrp::usrp2::make(device_addr); + //FIXME usees the default mboard for now (until the mimo link is supported) + wax::obj u2_mb = (*u2_dev)[uhd::usrp::DEVICE_PROP_MBOARD]; + std::cout << std::endl; + + //fetch and print current settings + std::cout << "Fetching current settings from usrp2 eeprom:" << std::endl; + std::string curr_ip = u2_mb[std::string("ip-addr")].as(); + std::cout << boost::format(" Current IP Address: %s") % curr_ip << std::endl; + std::string curr_mac = u2_mb[std::string("mac-addr")].as(); + std::cout << boost::format(" Current MAC Address: %s") % curr_mac << std::endl; + std::cout << " Done" << std::endl << std::endl; + + //try to set the new ip (if provided) + if (vm.count("new-ip")){ + std::cout << "Burning a new ip address into the usrp2 eeprom:" << std::endl; + std::string new_ip = vm["new-ip"].as(); + std::cout << boost::format(" New IP Address: %s") % new_ip << std::endl; + u2_mb[std::string("ip-addr")] = new_ip; + std::cout << " Done" << std::endl << std::endl; + } + + //try to set the new mac (if provided) + if (vm.count("new-mac")){ + std::cout << "Burning a new mac address into the usrp2 eeprom:" << std::endl; + std::string new_mac = vm["new-mac"].as(); + std::cout << boost::format(" New MAC Address: %s") % new_mac << std::endl; + u2_mb[std::string("mac-addr")] = new_mac; + std::cout << " Done" << std::endl << std::endl; + } + + std::cout << "Power-cycle the usrp2 for the changes to take effect." << std::endl; + return 0; +} diff --git a/host/utils/usrp2_burner.cpp b/host/utils/usrp2_burner.cpp deleted file mode 100644 index 9c1bf72fe..000000000 --- a/host/utils/usrp2_burner.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// 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 . -// - -#include -#include -#include -#include -#include -#include - -namespace po = boost::program_options; - -int UHD_SAFE_MAIN(int argc, char *argv[]){ - po::options_description desc("Allowed options"); - desc.add_options() - ("help", "help message") - ("addr", po::value(), "resolvable network address") - ("new-ip", po::value(), "new ip address (optional)") - ("new-mac", po::value(), "new mac address (optional)") - ; - - po::variables_map vm; - po::store(po::parse_command_line(argc, argv, desc), vm); - po::notify(vm); - - //print the help message - if (vm.count("help")){ - std::cout << boost::format("USRP2 Burner %s") % desc << std::endl; - return ~0; - } - - //load the options into the address - uhd::device_addr_t device_addr; - if (vm.count("addr")){ - device_addr["addr"] = vm["addr"].as(); - } - else{ - std::cerr << "Error: missing addr option" << std::endl; - return ~0; - } - - //create a usrp2 device - uhd::device::sptr u2_dev = uhd::usrp::usrp2::make(device_addr); - //FIXME usees the default mboard for now (until the mimo link is supported) - wax::obj u2_mb = (*u2_dev)[uhd::usrp::DEVICE_PROP_MBOARD]; - std::cout << std::endl; - - //fetch and print current settings - std::cout << "Fetching current settings from usrp2 eeprom:" << std::endl; - std::string curr_ip = u2_mb[std::string("ip-addr")].as(); - std::cout << boost::format(" Current IP Address: %s") % curr_ip << std::endl; - std::string curr_mac = u2_mb[std::string("mac-addr")].as(); - std::cout << boost::format(" Current MAC Address: %s") % curr_mac << std::endl; - std::cout << " Done" << std::endl << std::endl; - - //try to set the new ip (if provided) - if (vm.count("new-ip")){ - std::cout << "Burning a new ip address into the usrp2 eeprom:" << std::endl; - std::string new_ip = vm["new-ip"].as(); - std::cout << boost::format(" New IP Address: %s") % new_ip << std::endl; - u2_mb[std::string("ip-addr")] = new_ip; - std::cout << " Done" << std::endl << std::endl; - } - - //try to set the new mac (if provided) - if (vm.count("new-mac")){ - std::cout << "Burning a new mac address into the usrp2 eeprom:" << std::endl; - std::string new_mac = vm["new-mac"].as(); - std::cout << boost::format(" New MAC Address: %s") % new_mac << std::endl; - u2_mb[std::string("mac-addr")] = new_mac; - std::cout << " Done" << std::endl << std::endl; - } - - std::cout << "Power-cycle the usrp2 for the changes to take effect." << std::endl; - return 0; -} diff --git a/host/utils/usrp2_card_burner.py b/host/utils/usrp2_card_burner.py new file mode 100755 index 000000000..99cdcb626 --- /dev/null +++ b/host/utils/usrp2_card_burner.py @@ -0,0 +1,285 @@ +#!/usr/bin/env python + +######################################################################## +# Deal with raw devices +######################################################################## +import glob +import platform +import tempfile +import subprocess +import urllib + +SECTOR_SIZE = 512 # bytes +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 + +def get_dd_path(): + if platform.system() == 'Windows': + dd_path = os.path.join(tempfile.gettempdir(), 'dd.exe') + if not os.path.exists(dd_path): + print 'Downloading dd.exe to %s'%dd_path + dd_bin = urllib.urlopen('http://www.ettus.com/downloads/dd.exe').read() + open(dd_path, 'wb').write(dd_bin) + return dd_path + return 'dd' + +def get_raw_device_hints(): + if platform.system() == 'Windows': + output = subprocess.Popen( + [get_dd_path(), '--list'],#, '--filter=removable'], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ).stdout.read() + volumes = list() + for info in output.replace('\r', '').split('\n\\\\'): + if 'removeable' not in info.lower(): continue + if 'link to' not in info: continue + if 'size is' in info: + size = info.split('size is')[-1].split()[0] + if int(size) > 2048e6: 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 + if platform.system() == 'Linux': + return sorted(set(filter(lambda sd: not sd[-1].isdigit(), glob.glob("/dev/sd*")))) + return () + +def verify_image(image_file, device_file, offset): + #create a temporary file to store the readback + tmp = tempfile.mkstemp() + os.close(tmp[0]) + tmp_file = tmp[1] + + #execute a dd subprocess + args = [ + 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() + tmp_data = open(tmp_file, 'rb').read(len(img_data)) + + #verfy the data + if img_data != tmp_data: return 'Verification Failed:\n%s'%verbose + return 'Verification Passed:\n%s'%verbose + +def write_image(image_file, device_file, offset): + args = [ + 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: + raise Exception, 'Image file larger than %d bytes!'%MAX_FILE_SIZE + return '%s\n%s'%( + write_image( + image_file=image_file, + device_file=device_file, + offset=offset, + ), verify_image( + image_file=image_file, + device_file=device_file, + offset=offset, + ), + ) + +def burn_sd_card(dev, fw, fpga): + verbose = '' + if fw: verbose += 'Burn firmware image verbose:\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( + image_file=fpga, device_file=dev, offset=FPGA_OFFSET + ) + return verbose + +######################################################################## +# Graphical Tk stuff +######################################################################## +import Tkinter, Tkconstants, tkFileDialog, tkFont, tkMessageBox +import os + +class BinFileEntry(Tkinter.Frame): + """ + Simple file entry widget for getting the file path of bin files. + Combines a label, entry, and button with file dialog callback. + """ + + def __init__(self, root, what, def_path=''): + self._what = what + Tkinter.Frame.__init__(self, root) + Tkinter.Label(self, text=what+":").pack(side=Tkinter.LEFT) + self._entry = Tkinter.Entry(self, width=50) + self._entry.insert(Tkinter.END, def_path) + self._entry.pack(side=Tkinter.LEFT) + Tkinter.Button(self, text="...", command=self._button_cb).pack(side=Tkinter.LEFT) + + def _button_cb(self): + filename = tkFileDialog.askopenfilename( + parent=self, + filetypes=[('bin files', '*.bin'), ('all files', '*.*')], + title="Select bin file for %s"%self._what, + initialdir=os.path.dirname(self.get_filename()), + ) + + # open file on your own + if filename: + self._entry.delete(0, Tkinter.END) + self._entry.insert(0, filename) + + def get_filename(self): + return self._entry.get() + +class DeviceEntryWidget(Tkinter.Frame): + """ + Simple entry widget for getting the raw device name. + Combines a label, entry, and helpful text box with hints. + """ + + def __init__(self, root, text=''): + Tkinter.Frame.__init__(self, root) + + 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._hints.pack(expand=Tkinter.YES, fill=Tkinter.X) + + frame = Tkinter.Frame(self) + frame.pack() + + Tkinter.Label(frame, text="Raw Device:").pack(side=Tkinter.LEFT) + self._entry = Tkinter.Entry(frame, width=50) + self._entry.insert(Tkinter.END, text) + self._entry.pack(side=Tkinter.LEFT) + + def _listbox_cb(self, event): + try: + sel = self._hints.get(self._hints.curselection()[0]) + self._entry.delete(0, Tkinter.END) + self._entry.insert(0, sel) + except Exception, e: print e + + def get_devname(self): + return self._entry.get() + +class SectionLabel(Tkinter.Label): + """ + Make a text label with bold font. + """ + + def __init__(self, root, text): + Tkinter.Label.__init__(self, root, text=text) + + #set the font bold + f = tkFont.Font(font=self['font']) + f['weight'] = 'bold' + self['font'] = f.name + +class USRP2CardBurnerApp(Tkinter.Frame): + """ + The top level gui application for the usrp2 sd card burner. + Creates entry widgets and button with callback to write images. + """ + + def __init__(self, root, dev, fw, fpga): + + Tkinter.Frame.__init__(self, root) + + #pack the file entry widgets + SectionLabel(self, text="Select Images").pack(pady=5) + self._fw_img_entry = BinFileEntry(self, "Firmware Image", def_path=fw) + self._fw_img_entry.pack() + self._fpga_img_entry = BinFileEntry(self, "FPGA Image", def_path=fpga) + self._fpga_img_entry.pack() + + #pack the destination entry widget + SectionLabel(self, text="Select Device").pack(pady=5) + self._raw_dev_entry = DeviceEntryWidget(self, text=dev) + self._raw_dev_entry.pack() + + #the do it button + SectionLabel(self, text="").pack(pady=5) + Tkinter.Button(self, text="Burn SD Card", command=self._burn).pack() + + def _burn(self): + #grab strings from the gui + fw = self._fw_img_entry.get_filename() + fpga = self._fpga_img_entry.get_filename() + dev = self._raw_dev_entry.get_devname() + + #check input + if not dev: + tkMessageBox.showerror('Error:', 'No device specified!') + return + if not fw and not fpga: + tkMessageBox.showerror('Error:', 'No images specified!') + return + if fw and not os.path.exists(fw): + tkMessageBox.showerror('Error:', 'Firmware image not found!') + return + if fpga and not os.path.exists(fpga): + tkMessageBox.showerror('Error:', 'FPGA image not found!') + return + + #burn the sd card + try: + verbose = burn_sd_card(dev=dev, fw=fw, fpga=fpga) + tkMessageBox.showinfo('Verbose:', verbose) + except Exception, e: + tkMessageBox.showerror('Verbose:', 'Error: %s'%str(e)) + +######################################################################## +# Main +######################################################################## +import optparse + +if __name__=='__main__': + parser = optparse.OptionParser() + parser.add_option("--gui", action="store_true", default=False, help="run in gui mode") + parser.add_option("--dev", type="string", help="raw device path", default='') + parser.add_option("--fw", type="string", help="firmware image path (optional)", default='') + parser.add_option("--fpga", type="string", help="fpga image path (optional)", default='') + (options, args) = parser.parse_args() + + if options.gui: + root = Tkinter.Tk() + root.title('USRP2 SD Card Burner') + USRP2CardBurnerApp(root, dev=options.dev, fw=options.fw, fpga=options.fpga).pack() + root.mainloop() + exit() + + if not options.dev: raise Exception, 'no raw device path specified' + print burn_sd_card(dev=options.dev, fw=options.fw, fpga=options.fpga) -- cgit v1.2.3 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(-) (limited to 'host/utils') 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 From 573872edd90207b2c73c7d028868d01afc8b8a5c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 13 May 2010 14:07:18 -0700 Subject: card burner: added --list option, added warning, added sync on linux --- host/utils/usrp2_card_burner.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'host/utils') diff --git a/host/utils/usrp2_card_burner.py b/host/utils/usrp2_card_burner.py index 5f876c7bc..a1d4c5ed1 100755 --- a/host/utils/usrp2_card_burner.py +++ b/host/utils/usrp2_card_burner.py @@ -132,7 +132,7 @@ def verify_image(image_file, device_file, offset): return 'Verification Passed:\n%s'%verbose def write_image(image_file, device_file, offset): - return command( + verbose = command( get_dd_path(), "if=%s"%image_file, "of=%s"%device_file, @@ -140,6 +140,12 @@ def write_image(image_file, device_file, offset): "bs=%d"%SECTOR_SIZE, ) + try: #exec the sync command (only works on linux) + if platform.system() == 'Linux': command('sync') + except: pass + + return verbose + def write_and_verify(image_file, device_file, offset): if os.path.getsize(image_file) > MAX_FILE_SIZE: raise Exception, 'Image file larger than %d bytes!'%MAX_FILE_SIZE @@ -211,7 +217,7 @@ 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() + Tkinter.Button(self, text="Rescan for Devices", command=self._reload_cb).pack() self._hints = Tkinter.Listbox(self) self._hints.bind("<>", self._listbox_cb) @@ -278,6 +284,7 @@ class USRP2CardBurnerApp(Tkinter.Frame): #the do it button SectionLabel(self, text="").pack(pady=5) + Tkinter.Label(self, text="Warning! This tool can overwrite your hard drive. Use with caution.").pack() Tkinter.Button(self, text="Burn SD Card", command=self._burn).pack() def _burn(self): @@ -314,12 +321,18 @@ import optparse if __name__=='__main__': parser = optparse.OptionParser() - parser.add_option("--gui", action="store_true", default=False, help="run in gui mode") - parser.add_option("--dev", type="string", help="raw device path", default='') - parser.add_option("--fw", type="string", help="firmware image path (optional)", default='') - parser.add_option("--fpga", type="string", help="fpga image path (optional)", default='') + parser.add_option("--dev", type="string", help="raw device path", default='') + parser.add_option("--fw", type="string", help="firmware image path (optional)", default='') + parser.add_option("--fpga", type="string", help="fpga image path (optional)", default='') + parser.add_option("--list", action="store_true", help="list possible raw devices", default=False) + parser.add_option("--gui", action="store_true", help="run in gui mode", default=False) (options, args) = parser.parse_args() + if options.list: + print 'Possible raw devices:' + print ' ' + '\n '.join(get_raw_device_hints()) + exit() + if options.gui: root = Tkinter.Tk() root.title('USRP2 SD Card Burner') -- cgit v1.2.3 From 7c98884eda041b676584059ca3a63b11f1bbd505 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 18 May 2010 10:28:37 -0700 Subject: burn sd card fix, units for seek and skip in blocks not bytes --- host/utils/usrp2_card_burner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/utils') diff --git a/host/utils/usrp2_card_burner.py b/host/utils/usrp2_card_burner.py index a1d4c5ed1..dfdc663bc 100755 --- a/host/utils/usrp2_card_burner.py +++ b/host/utils/usrp2_card_burner.py @@ -118,7 +118,7 @@ def verify_image(image_file, device_file, offset): get_dd_path(), "of=%s"%tmp_file, "if=%s"%device_file, - "skip=%d"%offset, + "skip=%d"%(offset/SECTOR_SIZE), "bs=%d"%SECTOR_SIZE, "count=%d"%(MAX_FILE_SIZE/SECTOR_SIZE), ) @@ -136,7 +136,7 @@ def write_image(image_file, device_file, offset): get_dd_path(), "if=%s"%image_file, "of=%s"%device_file, - "seek=%d"%offset, + "seek=%d"%(offset/SECTOR_SIZE), "bs=%d"%SECTOR_SIZE, ) -- cgit v1.2.3 From a0bdd2d25aee9934c4457eb5f05341927438fb1e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 20 May 2010 14:39:55 -0700 Subject: split the card burner into two python apps, one command line app with implementation, and the other a gui only app, updated docs as well --- host/docs/usrp2.rst | 4 +- host/utils/CMakeLists.txt | 1 + host/utils/usrp2_card_burner.py | 181 +++++------------------------------- host/utils/usrp2_card_burner_gui.py | 169 +++++++++++++++++++++++++++++++++ 4 files changed, 195 insertions(+), 160 deletions(-) create mode 100755 host/utils/usrp2_card_burner_gui.py (limited to 'host/utils') diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst index 4731b73cf..c4a7aa64f 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -57,7 +57,7 @@ Use the card burner tool (unix) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: - sudo /share/uhd/utils/usrp2_card_burner.py --gui + sudo /share/uhd/utils/usrp2_card_burner_gui.py -- OR -- @@ -70,7 +70,7 @@ Use the card burner tool (windows) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: - /share/uhd/utils/usrp2_card_burner.py --gui + /share/uhd/utils/usrp2_card_burner_gui.py ------------------------------------------------------------------------ diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index d28576e8c..69a013a28 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -30,5 +30,6 @@ INSTALL(TARGETS uhd_burn_db_eeprom RUNTIME DESTINATION ${PKG_DATA_DIR}/utils) INSTALL(PROGRAMS usrp2_recovery.py usrp2_card_burner.py + usrp2_card_burner_gui.py DESTINATION ${PKG_DATA_DIR}/utils ) diff --git a/host/utils/usrp2_card_burner.py b/host/utils/usrp2_card_burner.py index dfdc663bc..59d0b3231 100755 --- a/host/utils/usrp2_card_burner.py +++ b/host/utils/usrp2_card_burner.py @@ -16,14 +16,16 @@ # along with this program. If not, see . # -######################################################################## -# Deal with raw devices -######################################################################## import platform import tempfile import subprocess import urllib +import optparse +import os +######################################################################## +# constants +######################################################################## SECTOR_SIZE = 512 # bytes MAX_FILE_SIZE = 1 * (2**20) # maximum number of bytes we'll burn to a slot @@ -32,6 +34,9 @@ FIRMWARE_OFFSET = 1 * (2**20) # offset in flash to firmware image MAX_SD_CARD_SIZE = 2048e6 # bytes (any bigger is sdhc) +######################################################################## +# helper functions +######################################################################## def command(*args): p = subprocess.Popen( args, @@ -53,6 +58,9 @@ def get_dd_path(): return dd_path return 'dd' +######################################################################## +# list possible devices +######################################################################## def get_raw_device_hints(): #################################################################### # Platform Windows: parse the output of dd.exe --list @@ -84,7 +92,7 @@ def get_raw_device_hints(): return sorted(set(volumes)) #################################################################### - # Platform Linux: call blockdev on all the /dev/sd* devices + # Platform Linux: call blockdev on all the dev0 devices #################################################################### if platform.system() == 'Linux': devs = list() @@ -107,6 +115,9 @@ def get_raw_device_hints(): #################################################################### return () +######################################################################## +# write and verify with dd +######################################################################## def verify_image(image_file, device_file, offset): #create a temporary file to store the readback tmp = tempfile.mkstemp() @@ -172,160 +183,14 @@ def burn_sd_card(dev, fw, fpga): return verbose ######################################################################## -# Graphical Tk stuff +# command line options ######################################################################## -import Tkinter, Tkconstants, tkFileDialog, tkFont, tkMessageBox -import os - -class BinFileEntry(Tkinter.Frame): - """ - Simple file entry widget for getting the file path of bin files. - Combines a label, entry, and button with file dialog callback. - """ - - def __init__(self, root, what, def_path=''): - self._what = what - Tkinter.Frame.__init__(self, root) - Tkinter.Label(self, text=what+":").pack(side=Tkinter.LEFT) - self._entry = Tkinter.Entry(self, width=50) - self._entry.insert(Tkinter.END, def_path) - self._entry.pack(side=Tkinter.LEFT) - Tkinter.Button(self, text="...", command=self._button_cb).pack(side=Tkinter.LEFT) - - def _button_cb(self): - filename = tkFileDialog.askopenfilename( - parent=self, - filetypes=[('bin files', '*.bin'), ('all files', '*.*')], - title="Select bin file for %s"%self._what, - initialdir=os.path.dirname(self.get_filename()), - ) - - # open file on your own - if filename: - self._entry.delete(0, Tkinter.END) - self._entry.insert(0, filename) - - def get_filename(self): - return self._entry.get() - -class DeviceEntryWidget(Tkinter.Frame): - """ - Simple entry widget for getting the raw device name. - Combines a label, entry, and helpful text box with hints. - """ - - def __init__(self, root, text=''): - Tkinter.Frame.__init__(self, root) - - Tkinter.Button(self, text="Rescan for Devices", command=self._reload_cb).pack() - - self._hints = Tkinter.Listbox(self) - self._hints.bind("<>", self._listbox_cb) - self._reload_cb() - self._hints.pack(expand=Tkinter.YES, fill=Tkinter.X) - - frame = Tkinter.Frame(self) - frame.pack() - - Tkinter.Label(frame, text="Raw Device:").pack(side=Tkinter.LEFT) - self._entry = Tkinter.Entry(frame, width=50) - 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]) - self._entry.delete(0, Tkinter.END) - self._entry.insert(0, sel) - except Exception, e: print e - - def get_devname(self): - return self._entry.get() - -class SectionLabel(Tkinter.Label): - """ - Make a text label with bold font. - """ - - def __init__(self, root, text): - Tkinter.Label.__init__(self, root, text=text) - - #set the font bold - f = tkFont.Font(font=self['font']) - f['weight'] = 'bold' - self['font'] = f.name - -class USRP2CardBurnerApp(Tkinter.Frame): - """ - The top level gui application for the usrp2 sd card burner. - Creates entry widgets and button with callback to write images. - """ - - def __init__(self, root, dev, fw, fpga): - - Tkinter.Frame.__init__(self, root) - - #pack the file entry widgets - SectionLabel(self, text="Select Images").pack(pady=5) - self._fw_img_entry = BinFileEntry(self, "Firmware Image", def_path=fw) - self._fw_img_entry.pack() - self._fpga_img_entry = BinFileEntry(self, "FPGA Image", def_path=fpga) - self._fpga_img_entry.pack() - - #pack the destination entry widget - SectionLabel(self, text="Select Device").pack(pady=5) - self._raw_dev_entry = DeviceEntryWidget(self, text=dev) - self._raw_dev_entry.pack() - - #the do it button - SectionLabel(self, text="").pack(pady=5) - Tkinter.Label(self, text="Warning! This tool can overwrite your hard drive. Use with caution.").pack() - Tkinter.Button(self, text="Burn SD Card", command=self._burn).pack() - - def _burn(self): - #grab strings from the gui - fw = self._fw_img_entry.get_filename() - fpga = self._fpga_img_entry.get_filename() - dev = self._raw_dev_entry.get_devname() - - #check input - if not dev: - tkMessageBox.showerror('Error:', 'No device specified!') - return - if not fw and not fpga: - tkMessageBox.showerror('Error:', 'No images specified!') - return - if fw and not os.path.exists(fw): - tkMessageBox.showerror('Error:', 'Firmware image not found!') - return - if fpga and not os.path.exists(fpga): - tkMessageBox.showerror('Error:', 'FPGA image not found!') - return - - #burn the sd card - try: - verbose = burn_sd_card(dev=dev, fw=fw, fpga=fpga) - tkMessageBox.showinfo('Verbose:', verbose) - except Exception, e: - tkMessageBox.showerror('Verbose:', 'Error: %s'%str(e)) - -######################################################################## -# Main -######################################################################## -import optparse - -if __name__=='__main__': +def get_options(): parser = optparse.OptionParser() parser.add_option("--dev", type="string", help="raw device path", default='') parser.add_option("--fw", type="string", help="firmware image path (optional)", default='') parser.add_option("--fpga", type="string", help="fpga image path (optional)", default='') parser.add_option("--list", action="store_true", help="list possible raw devices", default=False) - parser.add_option("--gui", action="store_true", help="run in gui mode", default=False) (options, args) = parser.parse_args() if options.list: @@ -333,12 +198,12 @@ if __name__=='__main__': print ' ' + '\n '.join(get_raw_device_hints()) exit() - if options.gui: - root = Tkinter.Tk() - root.title('USRP2 SD Card Burner') - USRP2CardBurnerApp(root, dev=options.dev, fw=options.fw, fpga=options.fpga).pack() - root.mainloop() - exit() + return options +######################################################################## +# main +######################################################################## +if __name__=='__main__': + options = get_options() if not options.dev: raise Exception, 'no raw device path specified' print burn_sd_card(dev=options.dev, fw=options.fw, fpga=options.fpga) diff --git a/host/utils/usrp2_card_burner_gui.py b/host/utils/usrp2_card_burner_gui.py new file mode 100755 index 000000000..61fbadbe3 --- /dev/null +++ b/host/utils/usrp2_card_burner_gui.py @@ -0,0 +1,169 @@ +#!/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 . +# + +import usrp2_card_burner #import implementation +import Tkinter, Tkconstants, tkFileDialog, tkFont, tkMessageBox +import os + +class BinFileEntry(Tkinter.Frame): + """ + Simple file entry widget for getting the file path of bin files. + Combines a label, entry, and button with file dialog callback. + """ + + def __init__(self, root, what, def_path=''): + self._what = what + Tkinter.Frame.__init__(self, root) + Tkinter.Label(self, text=what+":").pack(side=Tkinter.LEFT) + self._entry = Tkinter.Entry(self, width=50) + self._entry.insert(Tkinter.END, def_path) + self._entry.pack(side=Tkinter.LEFT) + Tkinter.Button(self, text="...", command=self._button_cb).pack(side=Tkinter.LEFT) + + def _button_cb(self): + filename = tkFileDialog.askopenfilename( + parent=self, + filetypes=[('bin files', '*.bin'), ('all files', '*.*')], + title="Select bin file for %s"%self._what, + initialdir=os.path.dirname(self.get_filename()), + ) + + # open file on your own + if filename: + self._entry.delete(0, Tkinter.END) + self._entry.insert(0, filename) + + def get_filename(self): + return self._entry.get() + +class DeviceEntryWidget(Tkinter.Frame): + """ + Simple entry widget for getting the raw device name. + Combines a label, entry, and helpful text box with hints. + """ + + def __init__(self, root, text=''): + Tkinter.Frame.__init__(self, root) + + Tkinter.Button(self, text="Rescan for Devices", command=self._reload_cb).pack() + + self._hints = Tkinter.Listbox(self) + self._hints.bind("<>", self._listbox_cb) + self._reload_cb() + self._hints.pack(expand=Tkinter.YES, fill=Tkinter.X) + + frame = Tkinter.Frame(self) + frame.pack() + + Tkinter.Label(frame, text="Raw Device:").pack(side=Tkinter.LEFT) + self._entry = Tkinter.Entry(frame, width=50) + 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 usrp2_card_burner.get_raw_device_hints(): + self._hints.insert(Tkinter.END, hint) + + def _listbox_cb(self, event): + try: + sel = self._hints.get(self._hints.curselection()[0]) + self._entry.delete(0, Tkinter.END) + self._entry.insert(0, sel) + except Exception, e: print e + + def get_devname(self): + return self._entry.get() + +class SectionLabel(Tkinter.Label): + """ + Make a text label with bold font. + """ + + def __init__(self, root, text): + Tkinter.Label.__init__(self, root, text=text) + + #set the font bold + f = tkFont.Font(font=self['font']) + f['weight'] = 'bold' + self['font'] = f.name + +class USRP2CardBurnerApp(Tkinter.Frame): + """ + The top level gui application for the usrp2 sd card burner. + Creates entry widgets and button with callback to write images. + """ + + def __init__(self, root, dev, fw, fpga): + + Tkinter.Frame.__init__(self, root) + + #pack the file entry widgets + SectionLabel(self, text="Select Images").pack(pady=5) + self._fw_img_entry = BinFileEntry(self, "Firmware Image", def_path=fw) + self._fw_img_entry.pack() + self._fpga_img_entry = BinFileEntry(self, "FPGA Image", def_path=fpga) + self._fpga_img_entry.pack() + + #pack the destination entry widget + SectionLabel(self, text="Select Device").pack(pady=5) + self._raw_dev_entry = DeviceEntryWidget(self, text=dev) + self._raw_dev_entry.pack() + + #the do it button + SectionLabel(self, text="").pack(pady=5) + Tkinter.Label(self, text="Warning! This tool can overwrite your hard drive. Use with caution.").pack() + Tkinter.Button(self, text="Burn SD Card", command=self._burn).pack() + + def _burn(self): + #grab strings from the gui + fw = self._fw_img_entry.get_filename() + fpga = self._fpga_img_entry.get_filename() + dev = self._raw_dev_entry.get_devname() + + #check input + if not dev: + tkMessageBox.showerror('Error:', 'No device specified!') + return + if not fw and not fpga: + tkMessageBox.showerror('Error:', 'No images specified!') + return + if fw and not os.path.exists(fw): + tkMessageBox.showerror('Error:', 'Firmware image not found!') + return + if fpga and not os.path.exists(fpga): + tkMessageBox.showerror('Error:', 'FPGA image not found!') + return + + #burn the sd card + try: + verbose = usrp2_card_burner.burn_sd_card(dev=dev, fw=fw, fpga=fpga) + tkMessageBox.showinfo('Verbose:', verbose) + except Exception, e: + tkMessageBox.showerror('Verbose:', 'Error: %s'%str(e)) + +######################################################################## +# main +######################################################################## +if __name__=='__main__': + options = usrp2_card_burner.get_options() + root = Tkinter.Tk() + root.title('USRP2 SD Card Burner') + USRP2CardBurnerApp(root, dev=options.dev, fw=options.fw, fpga=options.fpga).pack() + root.mainloop() + exit() -- cgit v1.2.3 From 221909b36b2a08a5817e75a3d13ebfe56716c7da Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 20 May 2010 17:08:53 -0700 Subject: use only procfs /proc/partitions for discovering raw devices on linux --- host/include/uhd/types/dict.hpp | 2 +- host/utils/usrp2_card_burner.py | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'host/utils') diff --git a/host/include/uhd/types/dict.hpp b/host/include/uhd/types/dict.hpp index b5fb11120..50a2b5c3b 100644 --- a/host/include/uhd/types/dict.hpp +++ b/host/include/uhd/types/dict.hpp @@ -46,7 +46,7 @@ namespace uhd{ * \param first the begin iterator * \param last the end iterator */ - template + template dict(InputIterator first, InputIterator last){ for(InputIterator it = first; it != last; it++){ _map.push_back(*it); diff --git a/host/utils/usrp2_card_burner.py b/host/utils/usrp2_card_burner.py index 59d0b3231..c39fb9d19 100755 --- a/host/utils/usrp2_card_burner.py +++ b/host/utils/usrp2_card_burner.py @@ -92,7 +92,7 @@ def get_raw_device_hints(): return sorted(set(volumes)) #################################################################### - # Platform Linux: call blockdev on all the dev0 devices + # Platform Linux: parse procfs /proc/partitions #################################################################### if platform.system() == 'Linux': devs = list() @@ -101,12 +101,10 @@ def get_raw_device_hints(): 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 + assert not name[-1].isdigit() or int(minor) == 0 + assert int(blocks)*1024 <= MAX_SD_CARD_SIZE except: continue - devs.append(dev) + devs.append(os.path.join('/dev', name)) return sorted(set(devs)) -- cgit v1.2.3 From 98bd3e1ddc0189f45f209c02b7dc7877ab377960 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 21 May 2010 15:06:54 -0700 Subject: clean up parsing of dd.exe --list for windows usrp2 card burner --- host/utils/usrp2_card_burner.py | 46 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 24 deletions(-) (limited to 'host/utils') diff --git a/host/utils/usrp2_card_burner.py b/host/utils/usrp2_card_burner.py index c39fb9d19..60aca9133 100755 --- a/host/utils/usrp2_card_burner.py +++ b/host/utils/usrp2_card_burner.py @@ -66,30 +66,28 @@ def get_raw_device_hints(): # Platform Windows: parse the output of dd.exe --list #################################################################### if platform.system() == 'Windows': - 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 '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].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(link) - - return sorted(set(volumes)) + def extract_info_value(info, key): + return info.split(key)[-1].split()[0] + def get_info_list(output): + in_info = False + for line in output.splitlines(): + if line.startswith('\\\\'): in_info = True; info = '' + elif in_info and not line.strip(): in_info = False; yield info + if in_info: info += '\n'+line.strip() + def is_info_valid(info): + try: + assert 'link to' in info + #handles two spellings of remov(e)able: + assert 'remov' in info.lower() + if 'size is' in info: assert int(extract_info_value(info, 'size is')) <= MAX_SD_CARD_SIZE + return True + except: return False + def extract_info_name(info): + for key in ('Mounted on', 'link to'): + if key in info: return extract_info_value(info, key) + return info.splitlines()[0].strip() + + return sorted(set(map(extract_info_name, filter(is_info_valid, get_info_list(command(get_dd_path(), '--list')))))) #################################################################### # Platform Linux: parse procfs /proc/partitions -- cgit v1.2.3 From 76ce1d824a41beacdb5bd603549c9b0e3f64d98f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 21 May 2010 17:30:05 -0700 Subject: mac os x card burner support and documentation notes --- host/docs/build.rst | 31 ++++++++++++++++++++++++++----- host/docs/usrp2.rst | 2 +- host/lib/transport/gen_vrt.py | 2 +- host/utils/usrp2_card_burner.py | 21 +++++++++++++++++++++ 4 files changed, 49 insertions(+), 7 deletions(-) (limited to 'host/utils') diff --git a/host/docs/build.rst b/host/docs/build.rst index d28682764..f5a8dac8d 100644 --- a/host/docs/build.rst +++ b/host/docs/build.rst @@ -8,9 +8,14 @@ UHD - Build Guide Build Dependencies ------------------------------------------------------------------------ -**Unix Notes:** +**Linux Notes:** The dependencies can be acquired through the package manager. +**Mac OS X Notes:** +Install the "Xcode Developer Tools" to get the build tools (gcc and make). +Use MacPorts to get the Boost and Cheetah dependencies. +Other dependencies can be downloaded as dmg installers from the web. + **Windows Notes:** The dependencies can be acquired through installable exe files. Usually, the windows installer can be found on the project's website. @@ -27,12 +32,13 @@ or install msysgit from http://code.google.com/p/msysgit/downloads/list ^^^^^^^^^^^^^^^^ C++ ^^^^^^^^^^^^^^^^ -On unix, this is GCC 4.0 and above. On windows, this is MSVC 2008. +On Unix, this is GCC 4.0 and above. On Windows, this is MSVC 2008. Other compilers have not been tested yet or confirmed working. ^^^^^^^^^^^^^^^^ CMake ^^^^^^^^^^^^^^^^ +* **Purpose:** generates project build files * **Version:** at least 2.8 * **Required for:** build time * **Download URL:** http://www.cmake.org/cmake/resources/software.html @@ -40,6 +46,7 @@ CMake ^^^^^^^^^^^^^^^^ Boost ^^^^^^^^^^^^^^^^ +* **Purpose:** C++ library * **Version:** at least 3.6 unix, at least 4.0 windows * **Required for:** build time + run time * **Download URL:** http://www.boost.org/users/download/ @@ -48,13 +55,15 @@ Boost ^^^^^^^^^^^^^^^^ Python ^^^^^^^^^^^^^^^^ +* **Purpose:** used by Cheetah and utility scripts * **Version:** at least 2.6 -* **Required for:** build time +* **Required for:** build time + run time utility scripts * **Download URL:** http://www.python.org/download/ ^^^^^^^^^^^^^^^^ Cheetah ^^^^^^^^^^^^^^^^ +* **Purpose:** source code generation * **Version:** at least 2.0 * **Required for:** build time * **Download URL:** http://www.cheetahtemplate.org/download.html @@ -63,9 +72,17 @@ Cheetah ^^^^^^^^^^^^^^^^ Doxygen ^^^^^^^^^^^^^^^^ +* **Purpose:** generates html api documentation * **Required for:** build time (optional) * **Download URL:** http://www.stack.nl/~dimitri/doxygen/download.html#latestsrc +^^^^^^^^^^^^^^^^ +Docutils +^^^^^^^^^^^^^^^^ +* **Purpose:** generates html user manual +* **Required for:** build time (optional) +* **Download URL:** http://docutils.sourceforge.net/ + ------------------------------------------------------------------------ Build Instructions (Unix) ------------------------------------------------------------------------ @@ -80,7 +97,7 @@ Generate Makefiles with cmake cd build cmake ../ -For a custom prefix, use: cmake -DCMAKE_INSTALL_PREFIX= ../ +For a custom prefix, use: cmake -DCMAKE_INSTALL_PREFIX= ../ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Build and install @@ -92,11 +109,15 @@ Build and install sudo make install ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Setup the library path +Setup the library path (Linux) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Make sure that libuhd.so is in your LD_LIBRARY_PATH or add it to /etc/ld.so.conf and make sure to run sudo ldconfig +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Setup the library path (Mac OS X) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Make sure that libuhd.dylib is in your DYLD_LIBRARY_PATH ------------------------------------------------------------------------ Build Instructions (Windows) diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst index c4a7aa64f..1bd95cefa 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -50,7 +50,7 @@ you could overwrite your hard drive. Make sure that --dev= specifies the SD card Use the *--list* option to get a list of possible raw devices. The list result will filter out disk partitions and devices too large to be the sd card. -The list option has not yet been implemented on macosx. +The list option has been implemented on Linux, Mac OS X, and Windows. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the card burner tool (unix) diff --git a/host/lib/transport/gen_vrt.py b/host/lib/transport/gen_vrt.py index 9a57c83c3..c34ffb198 100755 --- a/host/lib/transport/gen_vrt.py +++ b/host/lib/transport/gen_vrt.py @@ -57,7 +57,7 @@ void vrt::pack( size_t packet_count, //input double tick_rate //input ){ - boost::uint32_t vrt_hdr_flags; + boost::uint32_t vrt_hdr_flags = 0; boost::uint8_t pred = 0; if (metadata.has_stream_id) pred |= $hex($sid_p); diff --git a/host/utils/usrp2_card_burner.py b/host/utils/usrp2_card_burner.py index 60aca9133..d47a4f5f4 100755 --- a/host/utils/usrp2_card_burner.py +++ b/host/utils/usrp2_card_burner.py @@ -22,6 +22,7 @@ import subprocess import urllib import optparse import os +import re ######################################################################## # constants @@ -106,6 +107,26 @@ def get_raw_device_hints(): return sorted(set(devs)) + #################################################################### + # Platform Mac OS X: parse diskutil list and info commands + #################################################################### + if platform.system() == 'Darwin': + devs = map(lambda d: d.split()[0], filter(lambda l: l.startswith('/dev'), command('diskutil', 'list').splitlines())) + def output_to_info(output): + return dict([map(str.strip, pair.lower().split(':')) for pair in filter(lambda l: ':' in l, output.splitlines())]) + def is_dev_valid(dev): + info = output_to_info(command('diskutil', 'info', dev)) + try: + if info.has_key('internal'): assert info['internal'] == 'no' + if info.has_key('ejectable'): assert info['ejectable'] == 'yes' + if info.has_key('total size'): + size_match = re.match('^.*\((\d+)\s*bytes\).*$', info['total size']) + if size_match: assert int(size_match.groups()[0]) <= MAX_SD_CARD_SIZE + return True + except: return False + + return sorted(set(filter(is_dev_valid, devs))) + #################################################################### # Platform Others: #################################################################### -- cgit v1.2.3