1 /*
2 * wmtop.c -- WindowMaker process view dock app
3 * Derived by Carsten Schuermann carsten@schuermann.org
4 * http://www.schuermann.org/~carsten
5 * from
6 * Dan Piponi dan@tanelorn.demon.co.uk
7 * http://www.tanelorn.demon.co.uk
8 * who derived it
9 * from code originally contained in wmsysmon by Dave Clark (clarkd@skynet.ca)
10 * This software is licensed through the GNU General Public License.
11 * $Log: wmwave.c,v $
12 * Revision 1.7 1999/08/20 13:44:21 carsten
13 * version 0.4 complete
14 *
15 * Revision 1.6 1999/08/19 17:58:52 carsten
16 * Almost final version
17 *
18 * Revision 1.5 1999/08/19 13:54:30 carsten
19 * done
20 *
21 * Revision 1.4 1999/08/19 11:14:50 carsten
22 * hookup to /proc/net/wirless complete
23 *
24 * Revision 1.3 1999/08/19 02:39:07 carsten
25 * improved design and hooked it up
26 *
27 * Revision 1.2 1999/08/16 03:45:34 carsten
28 * Added dots
29 *
30 * Revision 1.1 1999/08/15 15:39:18 carsten
31 * Added wmwave project to repository
32 *
33 * Authors (in reverse chronological order):
34 * Benjamin Close <benjsc@freebsd.org>
35 * Hendrik Scholz <hscholz@raisdorf.net>
36 * Bruce M. Simpson <bms@spc.org>
37 * Carsten Schuermann <carsten@schuermann.org>
38 * Dan Piponi <dan@tanelorn.demon.co.uk>
39 * Dave Clark <clarkd@skynet.ca>
40 *
41 * The FreeBSD version of this software is released under the GNU GPL, and
42 * forms part of the Consume Project <URL: http://www.consume.net/>.
43 *
44 *
45 */
46
47
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <time.h>
51 #include <dirent.h>
52 #include <string.h>
53 #include <fcntl.h>
54 #include <unistd.h>
55 #include <ctype.h>
56 #include <math.h>
57 #include <limits.h>
58 #include <errno.h>
59 #include <signal.h>
60
61 #include <sys/wait.h>
62 #include <sys/stat.h>
63 #include <sys/param.h>
64 #include <sys/types.h>
65 #include <sys/ioctl.h>
66 #include <sys/time.h>
67
68 #include <X11/Xlib.h>
69 #include <X11/xpm.h>
70 #include <X11/extensions/shape.h>
71
72 #include <sys/socket.h>
73 #include <sys/sockio.h>
74 #include <netdb.h>
75 #include <net/if.h>
76 #include <net/if_var.h>
77 #include <net/route.h>
78 #include <net/ethernet.h>
79 #include <netinet/in.h>
80 #include <netinet/in_systm.h>
81 #include <netinet/in_var.h>
82 #include <netinet/ip.h>
83 #include <netinet/ip_var.h>
84 #include <arpa/inet.h>
85 #include <netproto/802_11/_ieee80211.h>
86 #include <netproto/802_11/ieee80211.h>
87 #include <netproto/802_11/ieee80211_crypto.h>
88 #include <netproto/802_11/ieee80211_ioctl.h>
89
90 #include "wmgeneral.h"
91
92 #include "wmwave-master.xpm"
93
94 char wmwave_mask_bits[64*64];
95 int wmwave_mask_width = 64;
96 int wmwave_mask_height = 64;
97
98 #define WMWAVE_VERSION "0.4_FreeBSD-2"
99 #define WMWAVE_DEFAULT_INTERFACE "wi0"
100 char *iface = WMWAVE_DEFAULT_INTERFACE;
101
102 int update_rate=100000;
103
104 char *ProgName;
105
106 time_t curtime;
107 time_t prevtime;
108
109 int mode = 0; // default: no card detected
110 int screen = 0; // default: Quality screen is displayed
111
112 void usage(void);
113 void printversion(void);
114 void BlitString(char *name, int x, int y);
115 void BlitNum(int num, int x, int y);
116 void wmwave_routine(int, char **);
117 void DrawBar(float percent, int dx, int dy);
118 void DrawGreenBar(float percent, int dx, int dy);
119
DrawBar(float percent,int dx,int dy)120 inline void DrawBar(float percent, int dx, int dy) {
121 int tx;
122
123 tx = (float)((float)54 * ((float)percent / (float)100.0));
124 copyXPMArea(67, 36, tx, 4, dx, dy);
125 copyXPMArea(67, 43, 54-tx, 4, dx+tx, dy);
126 }
127
128
DrawGreenBar(float percent,int dx,int dy)129 inline void DrawGreenBar(float percent, int dx, int dy) {
130 int tx;
131
132 tx = (float)((float)54 * ((float)percent / (float)100.0));
133 copyXPMArea(67, 58, tx, 4, dx, dy);
134 copyXPMArea(67, 43, 54-tx, 4, dx+tx, dy);
135 }
136
DrawRedDot()137 inline void DrawRedDot() {
138 copyXPMArea(80, 65, 6, 6, 52, 5);
139 }
140
DrawYellowDot()141 inline void DrawYellowDot() {
142 copyXPMArea(86, 65, 6, 6, 52, 5);
143 }
144
DrawGreenDot()145 inline void DrawGreenDot() {
146 copyXPMArea(92, 65, 6, 6, 52, 5);
147 }
148
DrawEmptyDot()149 inline void DrawEmptyDot() {
150 copyXPMArea(98, 65, 6, 6, 52, 5);
151 }
152
min(float x,float y)153 float min (float x, float y) {
154 if (x < y) {return x;}
155 else {return y;}
156 }
157
158 /*
159 * XXX: Fetch OS-specific wireless statistics.
160 *
161 * These are: quality, signal, noise. On NetBSD, the
162 * statistics kept on an AP-basis for the driver are valid.
163 * On FreeBSD, we make use of the net80211 layer to display the
164 * required stats.
165 */
DisplayWireless(void)166 void DisplayWireless(void)
167 {
168 struct ifreq ifr;
169 struct ieee80211req ireq;
170 union {
171 struct ieee80211req_sta_req stareq;
172 uint8_t buf[24*1024];
173 } u;
174 int s, mode, err;
175 float link, level, noise;
176 enum {
177 MODE_NO_CARD = 0,
178 MODE_HAVE_CARD = 1
179 };
180
181 s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
182 if (s == -1)
183 errx(errno, "socket");
184 bzero(&ifr, sizeof(ifr));
185 strncpy(ifr.ifr_name, iface, strlen(iface));
186
187 memset(&ireq, 0, sizeof(ireq));
188 strncpy(ireq.i_name, iface, sizeof(ireq.i_name));
189
190 // Get the currently associated ap
191 ireq.i_type = IEEE80211_IOC_BSSID;
192 ireq.i_data = u.stareq.is_u.macaddr;
193 ireq.i_len = IEEE80211_ADDR_LEN;
194 err = ioctl(s, SIOCG80211, &ireq);
195 if ( err >= 0 ){
196
197 // Get the station info for the ap
198 memset(&ireq, 0, sizeof(ireq));
199 strncpy(ireq.i_name, iface, sizeof(ireq.i_name));
200 ireq.i_type = IEEE80211_IOC_STA_INFO;
201 ireq.i_data = &u;
202 ireq.i_len = sizeof(u);
203 err = ioctl(s, SIOCG80211, &ireq);
204 if ( err >= 0 ){
205 const struct ieee80211req_sta_info *si = u.stareq.info;
206 mode = MODE_HAVE_CARD;
207 // net80211 doesn't have a link quality field so we base it on the
208 // noise/signal level
209 link = (si->isi_rssi-si->isi_noise)/2;
210 level = si->isi_rssi/2;
211 noise = abs(si->isi_noise);
212 }
213 }
214
215 if (err < 0) {
216 mode = MODE_NO_CARD;
217 }
218
219 draw:
220 /*
221 * Print channel information, and signal ratio
222 */
223 switch (mode) {
224 case MODE_HAVE_CARD:
225 BlitString("Quality", 4, 4);
226 if (link <= 10) {
227 DrawRedDot();
228 } else if (link <= 20) {
229 DrawYellowDot();
230 } else {
231 DrawGreenDot();
232 };
233 BlitString("Quality ", 4, 18);
234 DrawBar(min((int)(link * 1.8), 100.0), 4, 27);
235 BlitString("Signal ", 4, 32);
236 DrawGreenBar(min((int)(level * 0.3), 100.0), 4, 41);
237 BlitString("Noise ", 4, 46);
238 DrawGreenBar(min((int)(noise * 0.3), 100.0), 4, 55);
239 break;
240 case MODE_NO_CARD:
241 default:
242 BlitString("NO CARD", 4, 4);
243 DrawEmptyDot();
244 BlitString(" ", 4, 18);
245 DrawBar(0.0, 4, 27);
246 BlitString(" ", 4, 32);
247 DrawGreenBar(0.0, 4, 41);
248 BlitString(" ", 4, 46);
249 DrawGreenBar(0.0, 4, 55);
250 break;
251 };
252 close(s);
253 }
254
255 /* SIGCHLD handler */
sig_chld(int signo)256 void sig_chld(int signo)
257 {
258 waitpid((pid_t) -1, NULL, WNOHANG);
259 signal(SIGCHLD, sig_chld);
260 }
261
main(int argc,char * argv[])262 int main(int argc, char *argv[]) {
263 int i;
264
265 /* Parse Command Line */
266
267 signal(SIGCHLD, sig_chld);
268 ProgName = argv[0];
269 if (strlen(ProgName) >= 5)
270 ProgName += (strlen(ProgName) - 5);
271
272 for (i=1; i<argc; i++) {
273 char *arg = argv[i];
274
275 if (*arg=='-') {
276 switch (arg[1]) {
277 case 'i':
278 if (argc > (i + 1)) {
279 iface = argv[i+1];
280 }
281 break;
282 case 'd' :
283 if (strcmp(arg+1, "display")) {
284 usage();
285 exit(1);
286 }
287 break;
288 case 'g' :
289 if (strcmp(arg+1, "geometry")) {
290 usage();
291 exit(1);
292 }
293 break;
294 case 'v' :
295 printversion();
296 exit(0);
297 break;
298 case 'r':
299 if (argc > (i+1)) {
300 update_rate = (atoi(argv[i+1]) * 1000);
301 i++;
302 }
303 break;
304 default:
305 usage();
306 exit(0);
307 break;
308 }
309 }
310 }
311
312 wmwave_routine(argc, argv);
313
314 return 0;
315 }
316
317 /*
318 * Main loop
319 */
wmwave_routine(int argc,char ** argv)320 void wmwave_routine(int argc, char **argv) {
321 XEvent Event;
322 struct timeval tv={0,0};
323 struct timeval last={0,0};
324
325 createXBMfromXPM(wmwave_mask_bits, wmwave_master_xpm, wmwave_mask_width, wmwave_mask_height);
326
327 openXwindow(argc, argv, wmwave_master_xpm, wmwave_mask_bits, wmwave_mask_width, wmwave_mask_height);
328
329 RedrawWindow();
330
331
332 while (1) {
333
334 curtime = time(0);
335
336 if (1) {
337 memcpy(&last, &tv, sizeof(tv));
338
339 /*
340 * Update display
341 */
342 DisplayWireless();
343
344 RedrawWindow();
345 }
346
347 /*
348 * X Events
349 */
350 while (XPending(display)) {
351 XNextEvent(display, &Event);
352 switch (Event.type) {
353 case Expose:
354 RedrawWindow();
355 break;
356 case DestroyNotify:
357 XCloseDisplay(display);
358 exit(0);
359 case ButtonPress:
360 switch (screen) {
361 case 0: screen=1; break;
362 case 1: screen=0; break;
363 };
364 break;
365 }
366 }
367
368 usleep(update_rate);
369 }
370 }
371
372 /*
373 * Blits a string at given co-ordinates
374 */
BlitString(char * name,int x,int y)375 void BlitString(char *name, int x, int y) {
376 int i;
377 int c;
378 int k;
379
380 k = x;
381 for (i=0; name[i]; i++)
382 {
383
384 c = toupper(name[i]);
385 if (c >= 'A' && c <= 'Z')
386 { // its a letter
387 c -= 'A';
388 copyXPMArea(c * 6, 74, 6, 8, k, y);
389 k += 6;
390 } else
391 if (c>='0' && c<='9') { // its a number or symbol
392 c -= '0';
393 copyXPMArea(c * 6, 64, 6, 8, k, y);
394 k += 6;
395 } else {
396 copyXPMArea(5, 84, 6, 8, k, y);
397 k += 6;
398
399 }
400 }
401 }
402
BlitNum(int num,int x,int y)403 void BlitNum(int num, int x, int y) {
404 char buf[1024];
405 int newx=x;
406
407 sprintf(buf, "%03i", num);
408
409 BlitString(buf, newx, y);
410 }
411
412 /*
413 * Usage
414 */
usage(void)415 void usage(void) {
416 fprintf(stderr, "\nWmwave - Carsten Schuermann <carsten@schuermann.org> http://www.schuermann.org/~dockapps\n\n");
417 fprintf(stderr, "usage:\n");
418 fprintf(stderr, " -display <display name>\n");
419 fprintf(stderr, " -i interface to use (default to wi0)\n");
420 fprintf(stderr, " -r update rate in milliseconds (default:100)\n");
421 fprintf(stderr, "\n");
422 }
423
424 /*
425 * printversion
426 */
printversion(void)427 void printversion(void) {
428 fprintf(stderr, "wmwave v%s\n", WMWAVE_VERSION);
429 }
430