1 : /* ***** BEGIN LICENSE BLOCK *****
2 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 : *
4 : * The contents of this file are subject to the Mozilla Public License Version
5 : * 1.1 (the "License"); you may not use this file except in compliance with
6 : * the License. You may obtain a copy of the License at
7 : * http://www.mozilla.org/MPL/
8 : *
9 : * Software distributed under the License is distributed on an "AS IS" basis,
10 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 : * for the specific language governing rights and limitations under the
12 : * License.
13 : *
14 : * The Original Code is Geolocation.
15 : *
16 : * The Initial Developer of the Original Code is Mozilla Foundation
17 : * Portions created by the Initial Developer are Copyright (C) 2008
18 : * the Initial Developer. All Rights Reserved.
19 : *
20 : * This is a derivative of work done by Google under a BSD style License.
21 : * See: http://gears.googlecode.com/svn/trunk/gears/geolocation/
22 : *
23 : * Contributor(s):
24 : * Doug Turner <dougt@meer.net> (Original Author)
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either the GNU General Public License Version 2 or later (the "GPL"), or
28 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "iwlib.h"
41 :
42 : #include "dlfcn.h"
43 :
44 : #include "nsWifiMonitor.h"
45 : #include "nsWifiAccessPoint.h"
46 :
47 : #include "nsServiceManagerUtils.h"
48 : #include "nsComponentManagerUtils.h"
49 : #include "nsIMutableArray.h"
50 : #include "nsThreadUtils.h"
51 :
52 : using namespace mozilla;
53 :
54 :
55 : typedef int (*iw_open_t)(void);
56 :
57 : typedef void (*iw_enum_t)(int skfd,
58 : iw_enum_handler fn,
59 : char *args[],
60 : int count);
61 :
62 : typedef int (*iw_stats_t)(int skfd,
63 : const char *ifname,
64 : iwstats *stats,
65 : const iwrange *range,
66 : int has_range);
67 :
68 3 : static int scan_wifi(int skfd, char* ifname, char* args[], int count)
69 : {
70 3 : nsCOMArray<nsWifiAccessPoint>* accessPoints = (nsCOMArray<nsWifiAccessPoint>*) args[0];
71 3 : iw_stats_t iw_stats = (iw_stats_t) args[1];
72 :
73 : struct iwreq wrq;
74 :
75 : int result = iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq);
76 3 : if (result < 0)
77 3 : return 0;
78 :
79 : // We only cared about "Managed" mode. 2 is the magic number. There isn't a #define for this.
80 0 : if (wrq.u.mode != 2)
81 0 : return 0;
82 :
83 0 : nsWifiAccessPoint* ap = new nsWifiAccessPoint();
84 0 : if (!ap)
85 0 : return 0;
86 :
87 : char buffer[128];
88 0 : wrq.u.essid.pointer = buffer;
89 0 : wrq.u.essid.length = 128;
90 0 : wrq.u.essid.flags = 0;
91 : result = iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq);
92 0 : if (result < 0) {
93 0 : delete ap;
94 0 : return 0;
95 : }
96 :
97 0 : ap->setSSID(buffer, wrq.u.essid.length);
98 :
99 : result = iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq);
100 0 : if (result < 0) {
101 0 : delete ap;
102 0 : return 0;
103 : }
104 0 : ap->setMac( (const uint8*) wrq.u.ap_addr.sa_data );
105 :
106 : iwrange range;
107 : iwstats stats;
108 0 : result = (*iw_stats)(skfd, ifname, &stats, &range, 1);
109 0 : if (result < 0) {
110 0 : delete ap;
111 0 : return 0;
112 : }
113 :
114 0 : if(stats.qual.level > range.max_qual.level)
115 0 : ap->setSignal(stats.qual.level - 0x100);
116 : else
117 0 : ap->setSignal(0);
118 :
119 0 : accessPoints->AppendObject(ap);
120 0 : return 0;
121 : }
122 :
123 : nsresult
124 1 : nsWifiMonitor::DoScan()
125 : {
126 : static void* iwlib_handle = NULL;
127 :
128 1 : if (!iwlib_handle) {
129 1 : iwlib_handle = dlopen("libiw.so", RTLD_NOW);
130 1 : if (!iwlib_handle) {
131 0 : iwlib_handle = dlopen("libiw.so.29", RTLD_NOW);
132 0 : if (!iwlib_handle) {
133 0 : iwlib_handle = dlopen("libiw.so.30", RTLD_NOW);
134 0 : if (!iwlib_handle) {
135 0 : LOG(("Could not load libiw\n"));
136 0 : return NS_ERROR_NOT_AVAILABLE;
137 : }
138 : }
139 : }
140 : }
141 : else {
142 0 : LOG(("Loaded libiw\n"));
143 : }
144 :
145 : static iw_open_t iw_open = NULL;
146 1 : if (!iw_open)
147 1 : iw_open = (iw_open_t) dlsym(iwlib_handle, "iw_sockets_open");
148 :
149 : static iw_enum_t iw_enum = NULL;
150 1 : if (!iw_enum)
151 1 : iw_enum = (iw_enum_t) dlsym(iwlib_handle, "iw_enum_devices");
152 :
153 : static iw_stats_t iw_stats = NULL;
154 1 : if (!iw_stats)
155 1 : iw_stats = (iw_stats_t)dlsym(iwlib_handle, "iw_get_stats");
156 :
157 1 : if (!iw_open || !iw_enum || !iw_stats) {
158 0 : LOG(("Could not load a symbol from iwlib.so\n"));
159 0 : return NS_ERROR_FAILURE;
160 : }
161 :
162 1 : int skfd = (*iw_open)();
163 :
164 1 : if (skfd < 0) {
165 0 : LOG(("Could not iw_open\n"));
166 0 : return NS_ERROR_FAILURE;
167 : }
168 :
169 : struct SocketsGuard {
170 : int skfd;
171 1 : SocketsGuard(int skfd) : skfd(skfd) {}
172 2 : ~SocketsGuard() { iw_sockets_close(skfd); }
173 2 : } guard(skfd);
174 :
175 2 : nsCOMArray<nsWifiAccessPoint> lastAccessPoints;
176 2 : nsCOMArray<nsWifiAccessPoint> accessPoints;
177 :
178 1 : char* args[] = {(char*) &accessPoints, (char*) iw_stats, nsnull };
179 :
180 3 : while (mKeepGoing) {
181 1 : accessPoints.Clear();
182 :
183 1 : (*iw_enum)(skfd, &scan_wifi, args, 1);
184 :
185 1 : bool accessPointsChanged = !AccessPointsEqual(accessPoints, lastAccessPoints);
186 1 : ReplaceArray(lastAccessPoints, accessPoints);
187 :
188 1 : nsresult rv = CallWifiListeners(lastAccessPoints, accessPointsChanged);
189 1 : NS_ENSURE_SUCCESS(rv, rv);
190 :
191 1 : LOG(("waiting on monitor\n"));
192 :
193 2 : ReentrantMonitorAutoEnter mon(mReentrantMonitor);
194 1 : mon.Wait(PR_SecondsToInterval(60));
195 : }
196 :
197 1 : return NS_OK;
198 : }
|