00001 #include <ros/ros.h>
00002 #include <boost/thread.hpp>
00003 #include <actionlib/server/action_server.h>
00004 #include <actionlib_msgs/GoalStatus.h>
00005 #include <unistd.h>
00006 #include <fcntl.h>
00007 #include <queue>
00008 #include <wpa_supplicant_node/ScanAction.h>
00009 #include <wpa_supplicant_node/AssociateAction.h>
00010 #include <wpa_supplicant_node/AddNetwork.h>
00011 #include <wpa_supplicant_node/RemoveNetwork.h>
00012 #include <wpa_supplicant_node/SetNetworkState.h>
00013 #include <wpa_supplicant_node/SetNetworkParameters.h>
00014 #include <wpa_supplicant_node/NetworkList.h>
00015 #include <wpa_supplicant_node/FrequencyList.h>
00016
00017 extern "C" {
00018 #include <includes.h>
00019 #include <common.h>
00020 #include <wpa_supplicant_i.h>
00021 #include <eloop.h>
00022 #include <drivers/driver.h>
00023 #include <scan.h>
00024 #include <bss.h>
00025 #include <config.h>
00026 #include <common/wpa_common.h>
00027 #include <common/ieee802_11_defs.h>
00028 #include "wpa_supplicant_node.h"
00029 }
00030
00031 typedef boost::function<void ()> WorkFunction;
00032
00033 static class RosApi {
00034
00035 bool initialized_;
00036 std::queue<WorkFunction> work_queue_;
00037 boost::condition_variable main_thread_cv_;
00038 enum main_thread_states { MAIN_THREAD_NOT_WAITING, MAIN_THREAD_WAITING, MAIN_THREAD_PAUSED };
00039 volatile main_thread_states main_thread_state_;
00040 int pipefd[2];
00041 boost::shared_ptr<boost::thread> ros_spin_loop_;
00042 volatile bool shutting_down_;
00043
00044 public:
00045 boost::mutex mutex_;
00046
00047 RosApi()
00048 {
00049 shutting_down_ = false;
00050 main_thread_state_ = MAIN_THREAD_NOT_WAITING;
00051 }
00052
00053 void doWork()
00054 {
00055 char buffer[16];
00056
00057 ROS_INFO("doWork()");
00058
00059 {
00060 boost::mutex::scoped_lock lock(mutex_);
00061 mainThreadWait(lock);
00062 }
00063
00064 int bytes;
00065 do {
00066 bytes = read(pipefd[0], buffer, sizeof(buffer));
00067 ROS_INFO("doWork read %i bytes from the dummy fifo.", bytes);
00068 } while (bytes == sizeof(buffer));
00069
00070 while (1)
00071 {
00072 WorkFunction work;
00073 {
00074 boost::mutex::scoped_lock lock(mutex_);
00075 if (work_queue_.empty())
00076 break;
00077 work = work_queue_.front();
00078 work_queue_.pop();
00079 }
00080 work();
00081 }
00082 }
00083
00084 void addWork(const WorkFunction &f)
00085 {
00086 ROS_INFO("addWork()");
00087
00088 boost::mutex::scoped_lock lock(mutex_);
00089
00090 work_queue_.push(f);
00091 triggerWork();
00092 }
00093
00094 void triggerWork()
00095 {
00096 if (write(pipefd[1], pipefd, 1) != 1)
00097 ROS_ERROR("addWork Failed to write to wakeup pipe.");
00098 }
00099
00100 int init(int *argc, char ***argv)
00101 {
00102 ROS_INFO("ros_init");
00103
00104
00105 if (pipe2(pipefd, O_NONBLOCK | O_CLOEXEC))
00106 {
00107 ROS_FATAL("pipe2 failed: %s (%i)", strerror(errno), errno);
00108 return -1;
00109 }
00110 ROS_INFO("pipefds: %i <- %i", pipefd[0], pipefd[1]);
00111
00112 ros::init(*argc, *argv, "wpa_supplicant", ros::init_options::NoSigintHandler);
00113 ros_spin_loop_.reset(new boost::thread(boost::bind(&ros::spin)));
00114
00115 return 0;
00116 }
00117
00118 private:
00119 void waitForMainThreadState(boost::mutex::scoped_lock &lock, main_thread_states target)
00120 {
00121 while (main_thread_state_ != target && !shutting_down_)
00122 {
00123 main_thread_cv_.notify_one();
00124 main_thread_cv_.wait(lock);
00125 }
00126 }
00127
00128 void mainThreadWait(boost::mutex::scoped_lock &lock)
00129 {
00130 if (main_thread_state_ == MAIN_THREAD_WAITING)
00131 {
00132 main_thread_state_ = MAIN_THREAD_PAUSED;
00133 waitForMainThreadState(lock, MAIN_THREAD_PAUSED);
00134 }
00135 }
00136
00137 public:
00138 bool waitForMainThread(boost::mutex::scoped_lock &lock)
00139 {
00140 main_thread_state_ = MAIN_THREAD_WAITING;
00141 waitForMainThreadState(lock, MAIN_THREAD_PAUSED);
00142 main_thread_state_ = MAIN_THREAD_NOT_WAITING;
00143 return !shutting_down_;
00144 }
00145
00146 void init2()
00147 {
00148 ROS_INFO("ros_init");
00149 eloop_register_read_sock(pipefd[0], &ros_do_work, NULL, NULL);
00150 }
00151
00152 void uninit()
00153 {
00154 ROS_INFO("ros_deinit");
00155
00156 boost::mutex::scoped_lock lock(mutex_);
00157 shutting_down_ = true;
00158 mainThreadWait(lock);
00159
00160 ros::shutdown();
00161
00162
00163 if (ros_spin_loop_ && !ros_spin_loop_->timed_join((boost::posix_time::milliseconds) 2000))
00164 ROS_ERROR("ROS thread did not die after two seconds. Exiting anyways. This is probably a bad sign.");
00165
00166 eloop_unregister_read_sock(pipefd[0]);
00167 close(pipefd[0]);
00168 close(pipefd[1]);
00169 }
00170 } g_ros_api;
00171
00172 typedef actionlib::ActionServer<wpa_supplicant_node::ScanAction> ScanActionServer;
00173 typedef actionlib::ActionServer<wpa_supplicant_node::AssociateAction> AssociateActionServer;
00174 const ScanActionServer ::GoalHandle null_scan_goal_handle_;
00175 const AssociateActionServer::GoalHandle null_associate_goal_handle_;
00176
00177 struct ros_interface
00178 {
00179 private:
00180 wpa_supplicant *wpa_s_;
00181
00182 ros::NodeHandle nh_;
00183
00184
00185 boost::recursive_mutex scan_mutex_;
00186 ScanActionServer sas_;
00187 std::queue<ScanActionServer::GoalHandle> scan_queue_;
00188 ScanActionServer::GoalHandle current_scan_;
00189 std::vector<int> current_scan_frequencies_;
00190
00191
00192 boost::recursive_mutex associate_mutex_;
00193 AssociateActionServer aas_;
00194 AssociateActionServer::GoalHandle active_association_;
00195 bool associate_work_requested_;
00196 std::queue<AssociateActionServer::GoalHandle> associate_goal_queue_;
00197 std::queue<AssociateActionServer::GoalHandle> associate_cancel_queue_;
00198
00199
00200 ros::ServiceServer add_network_service_;
00201 ros::ServiceServer remove_network_service_;
00202 ros::ServiceServer set_network_state_service_;
00203 ros::ServiceServer set_network_parameter_service_;
00204
00205
00206 ros::Publisher frequency_list_publisher_;
00207 ros::Publisher network_list_publisher_;
00208 ros::Publisher association_publisher_;
00209 ros::Publisher scan_publisher_;
00210
00211 public:
00212 ros_interface(const ros::NodeHandle &nh, wpa_supplicant *wpa_s) :
00213 wpa_s_(wpa_s),
00214 nh_(ros::NodeHandle(nh, wpa_s->ifname)),
00215 sas_(nh_, "scan", boost::bind(&ros_interface::scanGoalCallback, this, _1), boost::bind(&ros_interface::scanCancelCallback, this, _1), true),
00216 aas_(nh_, "associate", boost::bind(&ros_interface::associateGoalCallback, this, _1), boost::bind(&ros_interface::associateCancelCallback, this, _1), true)
00217 {
00218 add_network_service_ = nh_.advertiseService("add_network", &ros_interface::addNetwork, this);
00219 remove_network_service_ = nh_.advertiseService("remove_network", &ros_interface::removeNetwork, this);
00220 set_network_state_service_ = nh_.advertiseService("set_network_state", &ros_interface::setNetworkState, this);
00221 set_network_parameter_service_ = nh_.advertiseService("set_network_parameter", &ros_interface::setNetworkParameter, this);
00222
00223 network_list_publisher_ = nh_.advertise<wpa_supplicant_node::NetworkList>("network_list", 1, true);
00224 frequency_list_publisher_ = nh_.advertise<wpa_supplicant_node::FrequencyList>("frequency_list", 1, true);
00225 association_publisher_ = nh_.advertise<wpa_supplicant_node::AssociateFeedback>("association_state", 1, true);
00226 scan_publisher_ = nh_.advertise<wpa_supplicant_node::ScanResult>("scan_results", 1, true);
00227
00228 publishFrequencyList();
00229 publishNetworkList();
00230 publishUnassociated();
00231 }
00232
00233 void publishUnassociated()
00234 {
00235 wpa_supplicant_node::AssociateFeedback fbk;
00236 association_publisher_.publish(fbk);
00237 }
00238
00239 void ifaceIdle()
00240 {
00241 }
00242
00243 void scanCompleted(wpa_scan_results *scan_res)
00244 {
00245 ROS_INFO("scanCompleted");
00246
00247 boost::recursive_mutex::scoped_lock lock(scan_mutex_);
00248
00249 eloop_cancel_timeout(scanTimeoutHandler, wpa_s_, NULL);
00250
00251 wpa_supplicant_node::ScanResult rslt;
00252 if (scan_res)
00253 {
00254 fillRosResp(rslt, *scan_res);
00255 scan_publisher_.publish(rslt);
00256 }
00257
00258 if (current_scan_ == null_scan_goal_handle_)
00259 ROS_ERROR("scanCompleted with current_scan_ not set.");
00260 else
00261 {
00262 if (scan_res)
00263 {
00264
00265 ROS_INFO("Scan completed successfully.");
00266 current_scan_.setSucceeded(rslt);
00267 }
00268 else
00269 {
00270 ROS_INFO("Scan failed.");
00271 current_scan_.setAborted(rslt);
00272 }
00273 current_scan_ = null_scan_goal_handle_;
00274 lockedScanTryActivate();
00275 }
00276 }
00277
00278 void assocFailed(const u8 *bssid, const char *s)
00279 {
00280 ROS_INFO("assocFailed");
00281 boost::recursive_mutex::scoped_lock lock(associate_mutex_);
00282
00283 eloop_cancel_timeout(associateTimeoutHandler, wpa_s_, NULL);
00284
00285 if (active_association_ == null_associate_goal_handle_)
00286 {
00287 ROS_ERROR("Got disassociation with no active association on BSSID: " MACSTR " (%s)", MAC2STR(bssid), s);
00288 }
00289 else
00290 {
00291 if (os_memcmp(bssid, &active_association_.getGoal()->bssid, ETH_ALEN) &&
00292 !is_zero_ether_addr(bssid))
00293 {
00294 ROS_ERROR("Got disassociation on unexpected BSSID: " MACSTR " (%s)", MAC2STR(bssid), s);
00295 }
00296
00297 active_association_.setAborted();
00298 active_association_ = null_associate_goal_handle_;
00299 }
00300
00301 publishUnassociated();
00302 requestAssociateWork();
00303 }
00304
00305 void assocSucceeded()
00306 {
00307 ROS_INFO("assocSucceeded");
00308 boost::recursive_mutex::scoped_lock lock(associate_mutex_);
00309
00310 eloop_cancel_timeout(associateTimeoutHandler, wpa_s_, NULL);
00311
00312 wpa_supplicant_node::AssociateFeedback fbk;
00313 fbk.associated = true;
00314 fillRosBss(fbk.bss, *wpa_s_->current_bss);
00315
00316
00317 active_association_.publishFeedback(fbk);
00318 association_publisher_.publish(fbk);
00319 }
00320
00321 private:
00322 void publishNetworkList()
00323 {
00324 wpa_supplicant_node::NetworkList netlist;
00325
00326 for (wpa_ssid *ssid = wpa_s_->conf->ssid; ssid; ssid = ssid->next)
00327 {
00328 wpa_supplicant_node::Network net;
00329 net.network_id = ssid->id;
00330 net.enabled = !ssid->disabled;
00331
00332 char **parameters = wpa_config_get_all(ssid, 0);
00333 for (char **cur_parameter = parameters; *cur_parameter; cur_parameter += 2)
00334 {
00335 wpa_supplicant_node::NetworkParameter param;
00336 param.key = cur_parameter[0];
00337 param.value = cur_parameter[1];
00338 net.parameters.push_back(param);
00339 free(cur_parameter[0]);
00340 free(cur_parameter[1]);
00341 }
00342 free(parameters);
00343
00344 netlist.networks.push_back(net);
00345 }
00346
00347 network_list_publisher_.publish(netlist);
00348 }
00349
00350 void publishFrequencyList()
00351 {
00352
00353
00354 wpa_supplicant_node::FrequencyList f;
00355 for (int i = 2412; i <= 2462; i += 5)
00356 f.frequencies.push_back(i);
00357 for (int i = 5180; i <= 5320; i += 20)
00358 f.frequencies.push_back(i);
00359 for (int i = 5500; i <= 5580; i += 20)
00360 f.frequencies.push_back(i);
00361 for (int i = 5500; i <= 5580; i += 20)
00362 f.frequencies.push_back(i);
00363 for (int i = 5680; i <= 5700; i += 20)
00364 f.frequencies.push_back(i);
00365 for (int i = 5745; i <= 5825; i += 20)
00366 f.frequencies.push_back(i);
00367
00368 frequency_list_publisher_.publish(f);
00369 }
00370
00371 bool addNetwork(wpa_supplicant_node::AddNetwork::Request &req, wpa_supplicant_node::AddNetwork::Response &rsp)
00372 {
00373 ROS_INFO("addNetwork");
00374
00375 boost::mutex::scoped_lock lock(g_ros_api.mutex_);
00376 if (!g_ros_api.waitForMainThread(lock))
00377 return false;
00378
00379
00380 return true;
00381 }
00382
00383 bool removeNetwork(wpa_supplicant_node::RemoveNetwork::Request &req, wpa_supplicant_node::RemoveNetwork::Response &rsp)
00384 {
00385 ROS_INFO("removeNetwork");
00386
00387 boost::mutex::scoped_lock lock(g_ros_api.mutex_);
00388 if (!g_ros_api.waitForMainThread(lock))
00389 return false;
00390
00391
00392 return true;
00393 }
00394
00395 bool setNetworkState(wpa_supplicant_node::SetNetworkState::Request &req, wpa_supplicant_node::SetNetworkState::Response &rsp)
00396 {
00397 ROS_INFO("setNetworkState");
00398
00399 boost::mutex::scoped_lock lock(g_ros_api.mutex_);
00400 if (!g_ros_api.waitForMainThread(lock))
00401 return false;
00402
00403
00404 return true;
00405 }
00406
00407 bool setNetworkParameter(wpa_supplicant_node::SetNetworkParameters::Request &req, wpa_supplicant_node::SetNetworkParameters::Response &rsp)
00408 {
00409 ROS_INFO("setNetworkParameter");
00410
00411 boost::mutex::scoped_lock lock(g_ros_api.mutex_);
00412 if (!g_ros_api.waitForMainThread(lock))
00413 return false;
00414
00415
00416 return true;
00417 }
00418 void requestAssociateWork()
00419 {
00420 associate_work_requested_ = true;
00421 g_ros_api.addWork(boost::bind(&ros_interface::associateWork, this));
00422 }
00423
00424 void stopActiveAssociation()
00425 {
00426 ROS_INFO("stopActiveAssociation()");
00427 if (active_association_ == null_associate_goal_handle_)
00428 ROS_ERROR("stopActiveAssociation called with no active association.");
00429
00430 wpa_supplicant_disassociate(wpa_s_, WLAN_REASON_DEAUTH_LEAVING);
00431 }
00432
00433 void startActiveAssociation(AssociateActionServer::GoalHandle &gh)
00434 {
00435 ROS_INFO("startActiveAssociation()");
00436 if (active_association_ != null_associate_goal_handle_)
00437 ROS_ERROR("startActiveAssociation called with no active association.");
00438
00439 wpa_bss *bss;
00440 boost::shared_ptr<const wpa_supplicant_node::AssociateGoal> goal = gh.getGoal();
00441 const u8 *bssid = &goal->bssid[0];
00442 std::string ssid = goal->ssid;
00443
00444 bss = wpa_bss_get(wpa_s_, bssid, (u8 *) ssid.c_str(), ssid.length());
00445
00446 wpa_ssid *net;
00447 for (net = wpa_s_->conf->ssid; net != NULL; net = net->next)
00448 if (ssid.length() == net->ssid_len && !os_memcmp(ssid.c_str(), net->ssid, net->ssid_len))
00449 break;
00450
00451 if (bss && net)
00452 {
00453 gh.setAccepted();
00454 active_association_ = gh;
00455 wpa_supplicant_node::AssociateFeedback fbk;
00456 fbk.associated = false;
00457 active_association_.publishFeedback(fbk);
00458
00459 eloop_register_timeout(5, 0, associateTimeoutHandler, wpa_s_, NULL);
00460
00461
00462
00463 wpa_supplicant_associate(wpa_s_, bss, net);
00464 }
00465 else
00466 {
00467 if (!bss)
00468 ROS_ERROR("startActiveAssociation could not find requested bss.");
00469 if (!net)
00470 ROS_ERROR("startActiveAssociation could not find requested ssid.");
00471 gh.setRejected();
00472 }
00473 ROS_INFO("startActiveAssociation() done");
00474 }
00475
00476 void associateWork()
00477 {
00478 boost::recursive_mutex::scoped_lock lock(associate_mutex_);
00479 associate_work_requested_ = false;
00480
00481 while (!associate_cancel_queue_.empty())
00482 {
00483 AssociateActionServer::GoalHandle gh = associate_cancel_queue_.front();
00484 associate_cancel_queue_.pop();
00485 if (gh == active_association_)
00486 {
00487 stopActiveAssociation();
00488 return;
00489 }
00490 else
00491 gh.setCanceled();
00492 }
00493
00494 while (associate_goal_queue_.size() > 1)
00495 {
00496 AssociateActionServer::GoalHandle gh = associate_goal_queue_.front();
00497 associate_goal_queue_.pop();
00498 gh.setRejected();
00499 }
00500
00501 if (!associate_goal_queue_.empty())
00502 {
00503 AssociateActionServer::GoalHandle gh = associate_goal_queue_.front();
00504 if (active_association_ != null_associate_goal_handle_ && active_association_.getGoal()->ssid != gh.getGoal()->ssid)
00505 {
00506 ROS_INFO("Unassociating prior to ESSID switch.");
00507 stopActiveAssociation();
00511
00512
00513 }
00514 else
00515 {
00516 if (active_association_ != null_associate_goal_handle_)
00517 {
00518 active_association_.setAborted();
00519 active_association_ = null_associate_goal_handle_;
00520 }
00521
00522 associate_goal_queue_.pop();
00523
00524 startActiveAssociation(gh);
00525 }
00526 }
00527 }
00528
00529 void associateGoalCallback(AssociateActionServer::GoalHandle &gh)
00530 {
00531 boost::recursive_mutex::scoped_lock lock(associate_mutex_);
00532
00533 associate_goal_queue_.push(gh);
00534 requestAssociateWork();
00535 }
00536
00537 void associateCancelCallback(AssociateActionServer::GoalHandle &gh)
00538 {
00539 boost::recursive_mutex::scoped_lock lock(associate_mutex_);
00540
00541 associate_cancel_queue_.push(gh);
00542 requestAssociateWork();
00543 }
00544
00545 void fillRosBss(wpa_supplicant_node::Bss &ros_bss, wpa_bss &bss)
00546 {
00547 ros_bss.stamp = ros::Time(bss.last_update.sec + 1e-6 * bss.last_update.usec);
00548 ros_bss.ssid.assign((const char *) bss.ssid, bss.ssid_len);
00549 memcpy(&ros_bss.bssid[0], bss.bssid, sizeof(bss.bssid));
00550 ros_bss.frequency = bss.freq;
00551 ros_bss.beacon_interval = bss.beacon_int;
00552 ros_bss.capabilities = bss.caps;
00553 ros_bss.quality = bss.qual;
00554 ros_bss.level = bss.level;
00555 ros_bss.noise = bss.noise;
00556 }
00557
00558 void fillRosResp(wpa_supplicant_node::ScanResult &rslt, wpa_scan_results &scan_res)
00559 {
00560 rslt.success = true;
00561 rslt.bss.clear();
00562 for (size_t i = 0; i < scan_res.num; i++)
00563 {
00564 wpa_scan_res &cur = *scan_res.res[i];
00565 wpa_supplicant_node::Bss bss;
00566 const u8* ssid_ie = wpa_scan_get_ie(&cur, WLAN_EID_SSID);
00567 int ssid_len = ssid_ie ? ssid_ie[1] : 0;
00568 const char *ssid = ssid_ie ? (const char *) ssid_ie + 2 : "";
00569 bss.ssid.assign(ssid, ssid_len);
00570 memcpy(&bss.bssid[0], cur.bssid, sizeof(bss.bssid));
00571 bss.noise = cur.noise;
00572 bss.quality = cur.qual;
00573 bss.level = cur.level;
00574 bss.capabilities = cur.caps;
00575 bss.beacon_interval = cur.beacon_int;
00576 bss.frequency = cur.freq;
00577 bss.stamp = ros::Time::now() - ros::Duration(cur.age / 1000.0);
00578 rslt.bss.push_back(bss);
00579 }
00580 }
00581
00582 void scanGoalCallback(ScanActionServer::GoalHandle &gh)
00583 {
00584 boost::recursive_mutex::scoped_lock lock(scan_mutex_);
00585
00586 ROS_INFO("scanGoalCallback()");
00587
00588 scan_queue_.push(gh);
00589
00590 if (current_scan_ == null_scan_goal_handle_)
00591 g_ros_api.addWork(boost::bind(&ros_interface::scanTryActivate, this));
00592 }
00593
00594 void scanCancelCallback(ScanActionServer::GoalHandle &gh)
00595 {
00596 boost::recursive_mutex::scoped_lock lock(scan_mutex_);
00597
00598 unsigned int status = gh.getGoalStatus().status;
00599
00600 if (current_scan_ == gh)
00601 {
00602 g_ros_api.addWork(boost::bind(&ros_interface::scanCancel, this, gh));
00603 }
00604 else
00605 {
00606 if (status != actionlib_msgs::GoalStatus::PREEMPTING)
00607 ROS_ERROR("scanCancelCallback called with unexpected goal status %i", status);
00608 gh.setCanceled();
00609 }
00610 }
00611
00612 void scanCancel(ScanActionServer::GoalHandle &gh)
00613 {
00614 ROS_INFO("scanCancel()");
00615 boost::recursive_mutex::scoped_lock lock(scan_mutex_);
00616
00617
00618 if (current_scan_ == gh)
00619 {
00620
00621 gh.setCanceled();
00622 current_scan_ = null_scan_goal_handle_;
00623 scanTryActivate();
00624 }
00625 }
00626
00627 void lockedScanTryActivate()
00628 {
00629
00630 ROS_INFO("scanTryActivate()");
00631
00632
00633 while (!scan_queue_.empty() && current_scan_ == null_scan_goal_handle_)
00634 {
00635 current_scan_ = scan_queue_.front();
00636 scan_queue_.pop();
00637
00638
00639
00640 if (current_scan_.getGoalStatus().status != actionlib_msgs::GoalStatus::PENDING)
00641 {
00642 ROS_INFO("Skipping canceled scan.");
00643 current_scan_ = null_scan_goal_handle_;
00644 continue;
00645 }
00646
00647 boost::shared_ptr<const wpa_supplicant_node::ScanGoal> goal = current_scan_.getGoal();
00648 struct wpa_driver_scan_params wpa_req;
00649 bzero(&wpa_req, sizeof(wpa_req));
00650
00651 std::string err = fillWpaReq(goal, wpa_req);
00652
00653 if (err.empty())
00654 {
00655 current_scan_.setAccepted();
00656
00657 ROS_INFO("Starting scan.");
00658
00659
00660
00661 int timeout;
00662 if (wpa_req.freqs == 0)
00663 timeout = 10000;
00664 else
00665 timeout = goal->frequencies.size() * 550;
00666 eloop_register_timeout(timeout / 1000, 1000 * (timeout % 1000), scanTimeoutHandler, wpa_s_, NULL);
00667 wpa_supplicant_trigger_scan(wpa_s_, &wpa_req);
00668 }
00669 else
00670 {
00671 current_scan_.setRejected(wpa_supplicant_node::ScanResult(), err);
00672 current_scan_ = null_scan_goal_handle_;
00673 continue;
00674 }
00675 }
00676
00677 ROS_INFO("Leaving scanTryActivate");
00678 if (scan_queue_.empty())
00679 ROS_INFO("scan_queue_ is empty.");
00680 if (current_scan_ != null_scan_goal_handle_)
00681 ROS_INFO("A scan is active.");
00682 }
00683
00684 static void scanTimeoutHandler(void *wpa_s, void *unused)
00685 {
00686 ROS_INFO("Scan timeout!");
00687 ((wpa_supplicant *) wpa_s)->ros_api->scanCompleted(NULL);
00688 }
00689
00690 static void associateTimeoutHandler(void *wpa_s, void *unused)
00691 {
00692 ROS_INFO("Associate timeout!");
00693 static const u8 zeroMAC[] = "\0\0\0\0\0\0";
00694 ((wpa_supplicant *) wpa_s)->ros_api->assocFailed(zeroMAC, "Associatiot timed out.");
00695 }
00696
00697 std::string fillWpaReq(boost::shared_ptr<const wpa_supplicant_node::ScanGoal> &g, struct wpa_driver_scan_params &wpa_req)
00698 {
00699 wpa_req.num_ssids = g->ssids.size();
00700
00701 #define QUOTEME(x) #x
00702 if (wpa_req.num_ssids > WPAS_MAX_SCAN_SSIDS)
00703 return "Too many ESSIDs in scan request. Maximum number is "QUOTEME(WPAS_MAX_SCAN_SSIDS)".";
00704
00705 for (unsigned int i = 0; i < wpa_req.num_ssids; i++)
00706 {
00707 wpa_req.ssids[i].ssid = (const u8 *) g->ssids[i].c_str();
00708 wpa_req.ssids[i].ssid_len = g->ssids[i].size();
00709
00710 if (wpa_req.ssids[i].ssid_len > WPA_MAX_SSID_LEN)
00711 return "Ssid is too long. Maximum length is "QUOTEME(WPA_MAX_SSID_LEN)" characters.";
00712 }
00713 #undef QUOTEME
00714
00715 current_scan_frequencies_.clear();
00716 int num_frequencies = g->frequencies.size();
00717
00718 if (num_frequencies > 0)
00719 {
00720 for (int i = 0; i < num_frequencies; i++)
00721 current_scan_frequencies_.push_back(g->frequencies[i]);
00722 current_scan_frequencies_.push_back(0);
00723 wpa_req.freqs = ¤t_scan_frequencies_[0];
00724 }
00725
00726 return "";
00727 }
00728
00729 void scanTryActivate()
00730 {
00731 boost::recursive_mutex::scoped_lock lock(scan_mutex_);
00732 lockedScanTryActivate();
00733 }
00734 };
00735
00736 extern "C" {
00737
00738 int ros_init(int *argc, char ***argv)
00739 {
00740 return g_ros_api.init(argc, argv);
00741 }
00742
00743 void ros_init2()
00744 {
00745 return g_ros_api.init2();
00746 }
00747
00748 void ros_deinit()
00749 {
00750 g_ros_api.uninit();
00751 }
00752
00753 void ros_add_iface(wpa_supplicant *wpa_s)
00754 {
00755 wpa_s->ros_api = new ros_interface(ros::NodeHandle("wifi"), wpa_s);
00756 }
00757
00758 void ros_remove_iface(wpa_supplicant *wpa_s)
00759 {
00760 delete wpa_s->ros_api;
00761 wpa_s->ros_api = NULL;
00762 }
00763
00764 void ros_iface_idle(wpa_supplicant *wpa_s)
00765 {
00766 if (wpa_s->ros_api)
00767 wpa_s->ros_api->ifaceIdle();
00768 }
00769
00770 void ros_scan_completed(wpa_supplicant *wpa_s, wpa_scan_results *scan_res)
00771 {
00772 if (wpa_s->ros_api)
00773 wpa_s->ros_api->scanCompleted(scan_res);
00774 }
00775
00776 void ros_do_work(int, void *, void *)
00777 {
00778 g_ros_api.doWork();
00779 }
00780
00781 void ros_assoc_failed(wpa_supplicant *wpa_s, const u8 *bssid, const char *reason)
00782 {
00783 if (wpa_s->ros_api)
00784 wpa_s->ros_api->assocFailed(bssid, reason);
00785 }
00786
00787 void ros_assoc_success(wpa_supplicant *wpa_s)
00788 {
00789 if (wpa_s->ros_api)
00790 wpa_s->ros_api->assocSucceeded();
00791 }
00792
00793 }