Imported Upstream version 3.2.2
[debian/gnuradio] / usrp2 / host / apps / usrp2_burn_mac_addr.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2007,2008 Free Software Foundation, Inc.
4  *
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.
9  *
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.
14  *
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/>.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22 #include <usrp2/usrp2.h>
23 #include <iostream>
24 #include <getopt.h>
25 #include <string.h>
26 #include <time.h>
27 #include <stdio.h>
28 #include <signal.h>
29 #include <stdexcept>
30
31
32 static volatile bool signaled = false;
33
34 static void 
35 sig_handler(int sig)
36 {
37   signaled = true;
38 }
39
40 static void
41 install_sig_handler(int signum,
42                     void (*new_handler)(int))
43 {
44   struct sigaction new_action;
45   memset (&new_action, 0, sizeof (new_action));
46
47   new_action.sa_handler = new_handler;
48   sigemptyset (&new_action.sa_mask);
49   new_action.sa_flags = 0;
50
51   if (sigaction (signum, &new_action, 0) < 0){
52     perror ("sigaction (install new)");
53     throw std::runtime_error ("sigaction");
54   }
55 }
56
57
58 static void
59 usage(const char *progname)
60 {
61   fprintf(stderr, "usage: %s [-e ethN] [-m old_mac_addr] new_mac_addr\n",
62           progname);
63   fprintf(stderr, "  old_mac_addr defaults to 00:50:c2:85:3f:ff\n");
64   fprintf(stderr, "  new_mac_address must be HH:HH or HH:HH:HH:HH:HH:HH\n");
65 }
66
67 static bool
68 check_mac_addr_syntax(const std::string &s)
69 {
70   unsigned char addr[6];
71
72   addr[0] = 0x00;               // Matt's IAB
73   addr[1] = 0x50;
74   addr[2] = 0xC2;
75   addr[3] = 0x85;
76   addr[4] = 0x30;
77   addr[5] = 0x00;
78     
79   int len = s.size();
80     
81   switch (len){
82       
83   case 5:
84     return sscanf(s.c_str(), "%hhx:%hhx", &addr[4], &addr[5]) == 2;
85       
86   case 17:
87     return sscanf(s.c_str(), "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
88                   &addr[0], &addr[1], &addr[2],
89                   &addr[3], &addr[4], &addr[5]) == 6;
90   default:
91     return false;
92   }
93
94   return true;
95 }
96
97
98 int
99 main(int argc, char **argv)
100 {
101   int ch;
102   const char *interface = "eth0";
103   const char *old_mac_addr = "00:50:c2:85:3f:ff";
104   const char *new_mac_addr = 0;
105
106   while ((ch = getopt(argc, argv, "he:m:")) != EOF){
107     switch (ch){
108     case 'e':
109       interface = optarg;
110       break;
111       
112     case 'm':
113       old_mac_addr = optarg;
114       break;
115       
116     case 'h':
117     default:
118       usage(argv[0]);
119       exit(1);
120     }
121   }
122
123   if (argc - optind != 1){
124     usage(argv[0]);
125     exit(1);
126   }
127
128   new_mac_addr = argv[optind];
129
130   if (!check_mac_addr_syntax(old_mac_addr)){
131     fprintf(stderr, "invalid mac address: %s\n", old_mac_addr);
132     exit(1);
133   }
134   if (!check_mac_addr_syntax(new_mac_addr)){
135     fprintf(stderr, "invalid mac address: %s\n", new_mac_addr);
136     exit(1);
137   }
138   
139   install_sig_handler(SIGINT, sig_handler);
140
141   usrp2::usrp2::sptr u2;
142
143   try {
144     u2 = usrp2::usrp2::make(interface, old_mac_addr);
145   }
146   catch (std::exception const &e){
147     std::cerr << e.what() << std::endl;
148     return 1;
149   }
150
151   if (!u2->burn_mac_addr(new_mac_addr)){
152     std::cerr << "Failed to burn mac address: "
153               << new_mac_addr << std::endl;
154     return 1;
155   }
156
157   u2.reset();   // close
158
159   // wait 250 ms
160   struct timespec ts;
161   ts.tv_sec = 0;
162   ts.tv_nsec = 250000000;
163   nanosleep(&ts, 0);
164
165   try {
166     u2 = usrp2::usrp2::make(interface, new_mac_addr);
167   }
168   catch (std::exception const &e){
169     std::cerr << "Failed to connect to USRP2 using new addr: "
170               << new_mac_addr << std::endl;
171     std::cerr << e.what() << std::endl;
172     return 1;
173   }
174
175   return 0;
176 }