aboutsummaryrefslogtreecommitdiffstats
path: root/host/utils/fx2_init_eeprom.cpp
blob: e0915d9f2d039b6f078d20a56012417baffc5f33 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//
// Copyright 2010,2014,2016 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 <http://www.gnu.org/licenses/>.
//

#include <uhd/utils/safe_main.hpp>
#include <uhd/device.hpp>
#include <uhd/property_tree.hpp>
#include <boost/program_options.hpp>
#include <boost/format.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <iostream>
#include <fstream>
#include "usrp1_eeprom.h"
#include "b100_eeprom.h"
#ifdef UHD_PLATFORM_LINUX
#include <unistd.h> // syscall constants
#include <fcntl.h> // O_NONBLOCK
#include <sys/syscall.h>
#include <cerrno>
#include <cstring> // for std::strerror
#endif //UHD_PLATFORM_LINUX

const std::string FX2_VENDOR_ID("0x04b4");
const std::string FX2_PRODUCT_ID("0x8613");

namespace po = boost::program_options;

int UHD_SAFE_MAIN(int argc, char *argv[]){
    std::string type;
    std::string image;
    po::options_description desc("Allowed options");
    desc.add_options()
        ("help", "help message")
        ("image", po::value<std::string>(), "BIN image file; if not specified, use built-in image")
        ("vid", po::value<std::string>(), "VID of device to program")
        ("pid", po::value<std::string>(), "PID of device to program")
        ("type", po::value<std::string>(&type), "device type (usrp1 or b100, required if using built-in image)")
    ;

    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("USRP EEPROM initialization %s") % desc << std::endl;
        return EXIT_FAILURE;
    }

#ifdef UHD_PLATFORM_LINUX
    //can't find an uninitialized usrp with this mystery usbtest in the way...
    std::string module("usbtest");
    std::ifstream modules("/proc/modules");
    bool module_found = false;
    std::string module_line;
    while(std::getline(modules, module_line) && (!module_found)) {
        module_found = boost::starts_with(module_line, module);
    }
    if(module_found) {
        std::cout << boost::format("Found the '%s' module. Unloading it.\n" ) % module;
        int fail = syscall(__NR_delete_module, module.c_str(), O_NONBLOCK);
        if(fail)
            std::cerr << ( boost::format("Removing the '%s' module failed with error '%s'.\n") % module % std::strerror(errno) );
    }
#endif //UHD_PLATFORM_LINUX

    //load the options into the address
    uhd::device_addr_t device_addr;
    device_addr["type"] = type;
    if(vm.count("vid") or vm.count("pid")) {
        if(not (vm.count("vid") and vm.count("pid") and vm.count("type"))) {
            std::cerr << "ERROR: Must specify vid, pid, and type if specifying any of the two former args" << std::endl;
        } else {
            device_addr["vid"] = vm["vid"].as<std::string>();
            device_addr["pid"] = vm["pid"].as<std::string>();
            device_addr["type"] = vm["type"].as<std::string>();
        }
    } else {
        device_addr["vid"] = FX2_VENDOR_ID;
        device_addr["pid"] = FX2_PRODUCT_ID;
    }
    if(vm.count("image")) {
      //if specified, use external image file
      image = vm["image"].as<std::string>();
    } else {
      //if not specified, use built-ins; requires user to define type
      size_t image_len;
      unsigned const char* image_data;

      if(!vm.count("type")) {
        std::cerr << boost::format("ERROR: Image file not specified and type of device not given. Cannot use built-in images.\n");
        return EXIT_FAILURE;
      }

      std::cout << boost::format("Using built-in image for \"%s\".\n") % type;

      if(vm["type"].as<std::string>() == "usrp1") {
        image_len = usrp1_eeprom_bin_len;
        image_data = usrp1_eeprom_bin;
      } else if(vm["type"].as<std::string>() == "b100") {
        image_len = b100_eeprom_bin_len;
        image_data = b100_eeprom_bin;
      } else {
        std::cerr << boost::format("ERROR: Unsupported device type \"%s\" specified and no EEPROM image file given.\n") % type;
        return EXIT_FAILURE;
      }

      //get temporary file name, and write image to that.
      image = boost::filesystem::unique_path().string();
      std::ofstream tmp_image(image, std::ofstream::binary);
      tmp_image.write((const char*)image_data, image_len);
      tmp_image.close();
    }

    //find and create a control transport to do the writing.

    uhd::device_addrs_t found_addrs = uhd::device::find(device_addr, uhd::device::USRP);

    if (found_addrs.size() == 0){
        std::cerr << "No USRP devices found" << std::endl;
        return EXIT_FAILURE;
    }

    for (size_t i = 0; i < found_addrs.size(); i++){
        std::cout << "Writing EEPROM data..." << std::endl;
        //uhd::device_addrs_t devs = uhd::device::find(found_addrs[i]);
        uhd::device::sptr dev = uhd::device::make(found_addrs[i], uhd::device::USRP);
        uhd::property_tree::sptr tree = dev->get_tree();
        tree->access<std::string>("/mboards/0/load_eeprom").set(image);
    }

    //delete temporary image file if we created one
    if(!vm.count("image")) {
      boost::filesystem::remove(image);
    }

    std::cout << "Power-cycle the usrp for the changes to take effect." << std::endl;
    return EXIT_SUCCESS;
}