3 * Copyright 2008 Free Software Foundation, Inc.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include <usrp2_eth_packet.h>
24 #include <usrp2/usrp2.h>
25 #include <boost/scoped_ptr.hpp>
26 #include <boost/date_time/posix_time/posix_time_types.hpp>
28 #include "pktfilter.h"
36 // FIXME move to gruel
39 time_duration_to_timeval(boost::posix_time::time_duration delta)
41 long total_us = delta.total_microseconds();
43 throw std::invalid_argument("duration_to_time: delta is negative");
46 tv.tv_sec = total_us / 1000000;
47 tv.tv_usec = total_us % 1000000;
55 reply_to_props(const op_id_reply_t *r)
57 const uint8_t *mac = (const uint8_t *)&r->addr;
59 snprintf(addr_buf, sizeof(addr_buf), "%02x:%02x:%02x:%02x:%02x:%02x",
60 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
63 p.addr = std::string(addr_buf);
64 p.hw_rev = ntohs(r->hw_rev);
65 memcpy(p.fpga_md5sum, r->fpga_md5sum, sizeof(p.fpga_md5sum));
66 memcpy(p.sw_md5sum, r->sw_md5sum, sizeof(p.sw_md5sum));
71 read_replies(ethernet *enet, struct timeval timeout,
72 const std::string &target_addr, props_vector_t &result)
76 op_id_reply_t op_id_reply;
79 uint8_t pktbuf[ethernet::MAX_PKTLEN];
80 memset(pktbuf, 0, sizeof(pktbuf));
84 FD_SET(enet->fd(), &read_fds);
86 select(enet->fd()+1, &read_fds, 0, 0, &timeout);
88 memset(pktbuf, 0, sizeof(pktbuf));
89 int len = enet->read_packet_dont_block(pktbuf, sizeof(pktbuf));
91 perror("usrp2_basic: read_packet_dont_block");
97 reply *rp = (reply *)pktbuf;
98 if (u2p_chan(&rp->h.fixed) != CONTROL_CHAN) // ignore
100 if (rp->op_id_reply.opcode != OP_ID_REPLY) // ignore
103 props p = reply_to_props(&rp->op_id_reply);
105 std::cerr << "usrp2::find: response from " << p.addr << std::endl;
107 if ((target_addr == "") || (target_addr == p.addr))
113 find(const std::string &ifc, const std::string &addr)
116 std::cerr << "usrp2::find: Searching interface " << ifc << " for "
117 << (addr == "" ? "all USRP2s" : addr)
121 props_vector_t result;
127 std::auto_ptr<ethernet> enet(new ethernet());
129 if (!enet->open(ifc, htons(U2_ETHERTYPE)))
132 std::auto_ptr<pktfilter> pf(pktfilter::make_ethertype_inbound(U2_ETHERTYPE, enet->mac()));
133 if (!enet->attach_pktfilter(pf.get()))
136 static u2_mac_addr_t broadcast_mac_addr =
137 {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }};
139 uint8_t pktbuf[ethernet::MAX_PKTLEN];
140 memset(pktbuf, 0, sizeof(pktbuf));
142 command *c = (command *)pktbuf;
143 c->h.ehdr.ethertype = htons(U2_ETHERTYPE);
144 c->h.ehdr.dst = broadcast_mac_addr;
145 memcpy(&c->h.ehdr.src, enet->mac(), 6);
149 u2p_set_word0(&c->h.fixed, 0, CONTROL_CHAN);
150 u2p_set_timestamp(&c->h.fixed, -1);
151 c->op_id.opcode = OP_ID;
152 c->op_id.len = sizeof(c->op_id);
153 int len = std::max((size_t) ethernet::MIN_PKTLEN, sizeof(command));
154 if (enet->write_packet(c, len) != len)
158 std::cerr << "usrp2::find: broadcast ID command" << std::endl;
161 * Gather all responses that occur within 50ms
163 boost::posix_time::ptime start(boost::posix_time::microsec_clock::universal_time());
164 boost::posix_time::ptime limit(start + boost::posix_time::milliseconds(50));
165 boost::posix_time::ptime now;
168 now = boost::posix_time::microsec_clock::universal_time();
172 boost::posix_time::time_duration delta(limit - now);
173 struct timeval timeout = time_duration_to_timeval(delta);
175 read_replies(enet.get(), timeout, addr, result);