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 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
|
//
// Copyright 2017-18 Ettus Research (National Instruments Corp.)
//
// SPDX-License-Identifier: GPL-3.0-or-later
//
#include "x300_mb_eeprom.hpp"
#include <uhd/types/serial.hpp>
#include <uhd/usrp/mboard_eeprom.hpp>
#include <uhdlib/utils/eeprom_utils.hpp>
namespace {
const uint8_t X300_EEPROM_ADDR = 0x50;
struct x300_eeprom_map
{
// identifying numbers
unsigned char revision[2];
unsigned char product[2];
unsigned char revision_compat[2];
uint8_t _pad0[2];
// all the mac addrs
uint8_t mac_addr0[6];
uint8_t _pad1[2];
uint8_t mac_addr1[6];
uint8_t _pad2[2];
// all the IP addrs
uint32_t gateway;
uint32_t subnet[4];
uint32_t ip_addr[4];
uint8_t _pad3[16];
// names and serials
unsigned char name[NAME_MAX_LEN];
unsigned char serial[SERIAL_LEN];
};
} // namespace
using namespace uhd;
using uhd::usrp::mboard_eeprom_t;
mboard_eeprom_t uhd::usrp::x300::get_mb_eeprom(uhd::i2c_iface::sptr iface)
{
byte_vector_t bytes =
iface->read_eeprom(X300_EEPROM_ADDR, 0, sizeof(struct x300_eeprom_map));
mboard_eeprom_t mb_eeprom;
if (bytes.empty()) {
return mb_eeprom;
}
// extract the revision number
mb_eeprom["revision"] = uint16_bytes_to_string(
byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, revision),
bytes.begin() + (offsetof(x300_eeprom_map, revision) + 2)));
// extract the revision compat number
mb_eeprom["revision_compat"] = uint16_bytes_to_string(
byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, revision_compat),
bytes.begin() + (offsetof(x300_eeprom_map, revision_compat) + 2)));
// extract the product code
mb_eeprom["product"] = uint16_bytes_to_string(
byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, product),
bytes.begin() + (offsetof(x300_eeprom_map, product) + 2)));
// extract the mac addresses
mb_eeprom["mac-addr0"] = mac_addr_t::from_bytes(
byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, mac_addr0),
bytes.begin() + (offsetof(x300_eeprom_map, mac_addr0) + 6)))
.to_string();
mb_eeprom["mac-addr1"] = mac_addr_t::from_bytes(
byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, mac_addr1),
bytes.begin() + (offsetof(x300_eeprom_map, mac_addr1) + 6)))
.to_string();
// extract the ip addresses
boost::asio::ip::address_v4::bytes_type ip_addr_bytes;
byte_copy(byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, gateway),
bytes.begin() + (offsetof(x300_eeprom_map, gateway) + 4)),
ip_addr_bytes);
mb_eeprom["gateway"] = boost::asio::ip::address_v4(ip_addr_bytes).to_string();
for (size_t i = 0; i < 4; i++) {
const std::string n(1, char(i) + '0');
byte_copy(
byte_vector_t(bytes.begin() + (offsetof(x300_eeprom_map, ip_addr) + (i * 4)),
bytes.begin() + (offsetof(x300_eeprom_map, ip_addr) + (i * 4) + 4)),
ip_addr_bytes);
mb_eeprom["ip-addr" + n] = boost::asio::ip::address_v4(ip_addr_bytes).to_string();
byte_copy(
byte_vector_t(bytes.begin() + (offsetof(x300_eeprom_map, subnet) + (i * 4)),
bytes.begin() + (offsetof(x300_eeprom_map, subnet) + (i * 4) + 4)),
ip_addr_bytes);
mb_eeprom["subnet" + n] = boost::asio::ip::address_v4(ip_addr_bytes).to_string();
}
// extract the serial
mb_eeprom["serial"] =
bytes_to_string(byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, serial),
bytes.begin() + (offsetof(x300_eeprom_map, serial) + SERIAL_LEN)));
// extract the name
mb_eeprom["name"] =
bytes_to_string(byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, name),
bytes.begin() + (offsetof(x300_eeprom_map, name) + NAME_MAX_LEN)));
return mb_eeprom;
}
void uhd::usrp::x300::set_mb_eeprom(
i2c_iface::sptr iface, const mboard_eeprom_t& mb_eeprom)
{
const mboard_eeprom_t curr_eeprom = uhd::usrp::x300::get_mb_eeprom(iface);
// Check for duplicate MAC and IP addresses
const std::vector<std::string> mac_keys{"mac-addr0", "mac-addr1"};
const std::vector<std::string> ip_keys{
"ip-addr0", "ip-addr1", "ip-addr2", "ip-addr3"};
// make sure there are no duplicate values
if (check_for_duplicates<uhd::mac_addr_t>(
"X300", mb_eeprom, curr_eeprom, "MAC address", mac_keys)
or check_for_duplicates<boost::asio::ip::address_v4>(
"X300", mb_eeprom, curr_eeprom, "IP address", ip_keys)) {
throw uhd::value_error(
"Duplicate values not permitted - write to EEPROM aborted");
}
// parse the revision number
if (mb_eeprom.has_key("revision"))
iface->write_eeprom(X300_EEPROM_ADDR,
offsetof(x300_eeprom_map, revision),
string_to_uint16_bytes(mb_eeprom["revision"]));
// parse the revision compat number
if (mb_eeprom.has_key("revision_compat"))
iface->write_eeprom(X300_EEPROM_ADDR,
offsetof(x300_eeprom_map, revision_compat),
string_to_uint16_bytes(mb_eeprom["revision_compat"]));
// parse the product code
if (mb_eeprom.has_key("product"))
iface->write_eeprom(X300_EEPROM_ADDR,
offsetof(x300_eeprom_map, product),
string_to_uint16_bytes(mb_eeprom["product"]));
// store the mac addresses
if (mb_eeprom.has_key("mac-addr0"))
iface->write_eeprom(X300_EEPROM_ADDR,
offsetof(x300_eeprom_map, mac_addr0),
mac_addr_t::from_string(mb_eeprom["mac-addr0"]).to_bytes());
if (mb_eeprom.has_key("mac-addr1"))
iface->write_eeprom(X300_EEPROM_ADDR,
offsetof(x300_eeprom_map, mac_addr1),
mac_addr_t::from_string(mb_eeprom["mac-addr1"]).to_bytes());
// store the ip addresses
byte_vector_t ip_addr_bytes(4);
if (mb_eeprom.has_key("gateway")) {
byte_copy(
boost::asio::ip::address_v4::from_string(mb_eeprom["gateway"]).to_bytes(),
ip_addr_bytes);
iface->write_eeprom(
X300_EEPROM_ADDR, offsetof(x300_eeprom_map, gateway), ip_addr_bytes);
}
for (size_t i = 0; i < 4; i++) {
const std::string n(1, char(i) + '0');
if (mb_eeprom.has_key("ip-addr" + n)) {
byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["ip-addr" + n])
.to_bytes(),
ip_addr_bytes);
iface->write_eeprom(X300_EEPROM_ADDR,
offsetof(x300_eeprom_map, ip_addr) + (i * 4),
ip_addr_bytes);
}
if (mb_eeprom.has_key("subnet" + n)) {
byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["subnet" + n])
.to_bytes(),
ip_addr_bytes);
iface->write_eeprom(X300_EEPROM_ADDR,
offsetof(x300_eeprom_map, subnet) + (i * 4),
ip_addr_bytes);
}
}
// store the serial
if (mb_eeprom.has_key("serial"))
iface->write_eeprom(X300_EEPROM_ADDR,
offsetof(x300_eeprom_map, serial),
string_to_bytes(mb_eeprom["serial"], SERIAL_LEN));
// store the name
if (mb_eeprom.has_key("name"))
iface->write_eeprom(X300_EEPROM_ADDR,
offsetof(x300_eeprom_map, name),
string_to_bytes(mb_eeprom["name"], NAME_MAX_LEN));
}
|