Download
jcs
/wifi_da
/main.c
(View History)
jcs *: Make some warnings less warny | Latest amendment: 22 on 2023-10-25 |
1 | /* |
2 | * Copyright (c) 2023 joshua stein <jcs@jcs.org> |
3 | * |
4 | * Permission to use, copy, modify, and distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above |
6 | * copyright notice and this permission notice appear in all copies. |
7 | * |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ |
16 | |
17 | #include <stdarg.h> |
18 | #include <stdio.h> |
19 | #include <string.h> |
20 | #include "wi-fi.h" |
21 | |
22 | /* device control entry */ |
23 | DCtlPtr dce = NULL; |
24 | |
25 | SysEnvRec world; |
26 | #define ON_SYSTEM_7 (world.systemVersion >= 0x0700) |
27 | |
28 | short da_state = STATE_CLOSED; |
29 | short wifi_scsi_id = WIFI_SCSI_ID_FINDING; |
30 | unsigned long wifi_scan_started = 0; |
31 | struct wifi_network_entry wifi_cur_info = { 0 }; |
32 | struct wifi_network_entry wifi_scan_networks[10] = { 0 }; |
33 | MenuHandle menu, apple_menu; |
34 | short menuID = 0; |
35 | WindowPtr win = 0L; |
36 | Cursor watch; |
37 | short logger_y = 12; |
38 | WindowPtr logger = 0; |
39 | |
40 | short main(cntrlParam *p, DCtlPtr d, short n); |
41 | void da_open(void); |
42 | void da_control(short code, short *parm); |
43 | void da_close(void); |
44 | bool handle_menu(short i); |
45 | void handle_event(EventRecord *e); |
46 | void handle_timer(void); |
47 | #ifdef DEBUG_LOGGING |
48 | void logger_vprintf(const char *format, va_list ap); |
49 | #endif |
50 | |
51 | short |
52 | main(cntrlParam *p, DCtlPtr d, short n) |
53 | { |
54 | if (d->dCtlStorage == 0) { |
55 | /* open */ |
56 | if (n == 0) { |
57 | SysBeep(3); |
58 | CloseDriver(d->dCtlRefNum); |
59 | } |
60 | return 0; |
61 | } |
62 | |
63 | if (dce == NULL) { |
64 | util_init(d); |
65 | SysEnvirons(1, &world); |
66 | } |
67 | |
68 | dce = d; |
69 | dce->dCtlFlags &= ~dCtlEnable; |
70 | |
71 | switch (n) { |
72 | case 0: |
73 | da_open(); |
74 | break; |
75 | case 2: |
76 | da_control(p->csCode, p->csParam); |
77 | break; |
78 | case 4: |
79 | da_close(); |
80 | break; |
81 | } |
82 | |
83 | dce->dCtlFlags |= dCtlEnable; |
84 | |
85 | return 0; |
86 | } |
87 | |
88 | /* |
89 | * This is called each time the DA is selected from the Apple menu, |
90 | * even if we're already open. However, the Device Manager resets |
91 | * the "dCtlFlags", "dCtlMenu", "dCtlDelay", and "dCtlEMask" fields |
92 | * of the device control entry from the corresponding fields of the |
93 | * device header each time the desk accessory is opened. |
94 | */ |
95 | void |
96 | da_open(void) |
97 | { |
98 | CursHandle h; |
99 | Rect bounds; |
100 | bool dispose; |
101 | |
102 | dce->dCtlFlags |= dNeedLock | dNeedTime | dNeedGoodBye; |
103 | dce->dCtlDelay = 61; |
104 | |
105 | #ifdef DEBUG_LOGGING |
106 | if (!logger) { |
107 | bounds.top = 150; |
108 | bounds.bottom = 320; |
109 | bounds.left = 20; |
110 | bounds.right = 400; |
111 | logger = NewWindow(0L, &bounds, "\pLogger", true, rDocProc, 0L, |
112 | true, 0L); |
113 | ((WindowPeek)logger)->windowKind = dce->dCtlRefNum; |
114 | } |
115 | #endif |
116 | |
117 | if (win) |
118 | SelectWindow(win); |
119 | |
120 | if (da_state != STATE_CLOSED) { |
121 | dce->dCtlMenu = menuID; |
122 | return; |
123 | } |
124 | |
125 | da_state = STATE_INIT; |
126 | |
127 | SetResLoad(false); |
128 | h = GetCursor(watchCursor); |
129 | dispose = (GetHandleSize((Handle)h) == 0); |
130 | SetResLoad(true); |
131 | BlockMove(*(h = GetCursor(watchCursor)), &watch, sizeof(Cursor)); |
132 | if (dispose) |
133 | ReleaseResource((Handle)h); |
134 | |
135 | if (!ON_SYSTEM_7) { |
136 | dce->dCtlMenu = menuID = OwnedResourceID(MAIN_MENU_ID); |
137 | menu = GetMenu(menuID); |
138 | (**menu).menuID = menuID; |
139 | InsertMenu(menu = GetMenu(menuID), 0); |
140 | DrawMenuBar(); |
141 | } |
142 | |
143 | dce->dCtlWindow = create_window(dce->dCtlRefNum); |
144 | |
145 | HiliteMenu(0); |
146 | } |
147 | |
148 | void |
149 | da_control(short code, short *param) |
150 | { |
151 | switch (code) { |
152 | case accMenu: |
153 | handle_menu(param[1]); |
154 | break; |
155 | case accEvent: |
156 | handle_event(*((EventRecord **)param)); |
157 | break; |
158 | case accRun: |
159 | handle_timer(); |
160 | break; |
161 | case goodbye: |
162 | break; |
163 | } |
164 | } |
165 | |
166 | void |
167 | da_close(void) |
168 | { |
169 | if (!ON_SYSTEM_7) { |
170 | DeleteMenu(dce->dCtlMenu); |
171 | DrawMenuBar(); |
172 | DisposeMenu(menu); |
173 | } |
174 | |
175 | dce->dCtlMenu = 0; |
176 | destroy_window(); |
177 | if (logger) { |
178 | DisposeWindow(logger); |
179 | logger = 0; |
180 | } |
181 | dce->dCtlWindow = 0; |
182 | da_state = STATE_CLOSED; |
183 | } |
184 | |
185 | bool |
186 | handle_menu(short i) |
187 | { |
188 | bool ret = true; |
189 | |
190 | switch (i) { |
191 | case MAIN_MENU_ABOUT_ID: |
192 | wifi_about(); |
193 | break; |
194 | case MAIN_MENU_QUIT_ID: |
195 | CloseDriver(dce->dCtlRefNum); |
196 | break; |
197 | default: |
198 | ret = false; |
199 | } |
200 | |
201 | HiliteMenu(0); |
202 | return ret; |
203 | } |
204 | |
205 | void |
206 | handle_event(EventRecord *e) |
207 | { |
208 | short key, mk; |
209 | |
210 | switch (e->what) { |
211 | case updateEvt: |
212 | update_window(false); |
213 | break; |
214 | case mouseDown: |
215 | window_mousedown(e->where); |
216 | update_window(false); |
217 | break; |
218 | case activateEvt: |
219 | activate_window((bool)(e->modifiers & activeFlag)); |
220 | break; |
221 | case keyDown: |
222 | case autoKey: |
223 | key = e->message & charCodeMask; |
224 | if ((e->modifiers & cmdKey) != 0) { |
225 | mk = MenuKey(key); |
226 | if (mk != 0 && handle_menu(mk)) |
227 | break; |
228 | } |
229 | break; |
230 | } |
231 | } |
232 | |
233 | void |
234 | handle_timer(void) |
235 | { |
236 | static long last_update = 0; |
237 | static long last_scan = 0; |
238 | |
239 | if (!win) |
240 | return; |
241 | |
242 | switch (da_state) { |
243 | case STATE_SCANNING: |
244 | /* check every second */ |
245 | if ((Ticks - last_update) < (60 * 1)) |
246 | break; |
247 | DEBUG_LOG(("%ld - handle_timer - checking for scan completion", |
248 | Ticks)); |
249 | last_update = Ticks; |
250 | if (!scsi_wifi_scan_finished(wifi_scsi_id)) { |
251 | DEBUG_LOG(("%ld - handle_timer - scan not done", Ticks)); |
252 | if (Time - wifi_scan_started <= 5) |
253 | break; |
254 | DEBUG_LOG(("Wi-Fi scan failed to finish, canceling")); |
255 | } |
256 | last_scan = Ticks; |
257 | da_state = STATE_IDLE; |
258 | DEBUG_LOG(("%ld - handle_timer - scan done, updating list", Ticks)); |
259 | update_wifi_ssid_list(true); |
260 | break; |
261 | case STATE_IDLE: |
262 | /* refresh SSID/RSSI every 5 seconds, scan every 30 */ |
263 | if ((Ticks - last_update) < (60 * 5)) |
264 | break; |
265 | last_update = Ticks; |
266 | |
267 | if ((Ticks - last_scan) > (60 * 30)) { |
268 | da_state = STATE_SCANNING; |
269 | DEBUG_LOG(("%ld - handle_timer - idle, scanning", Ticks)); |
270 | scsi_wifi_scan(wifi_scsi_id); |
271 | } else { |
272 | DEBUG_LOG(("%ld - handle_timer - idle, updating info", Ticks)); |
273 | update_wifi_cur_info(); |
274 | } |
275 | break; |
276 | } |
277 | } |
278 | |
279 | #ifdef DEBUG_LOGGING |
280 | void |
281 | logger_printf(const char *format, ...) |
282 | { |
283 | va_list va; |
284 | |
285 | if (!logger) |
286 | return; |
287 | |
288 | va_start(va, format); |
289 | logger_vprintf(format, va); |
290 | va_end(va); |
291 | } |
292 | |
293 | void |
294 | logger_vprintf(const char *format, va_list ap) |
295 | { |
296 | static char buf[512]; |
297 | GrafPtr savePort; |
298 | ssize_t len; |
299 | |
300 | len = vsnprintf(buf, sizeof(buf), format, ap); |
301 | |
302 | GetPort(&savePort); |
303 | SetPort(logger); |
304 | |
305 | if (logger_y >= (logger->portRect.bottom - logger->portRect.top)) { |
306 | EraseRect(&logger->portRect); |
307 | logger_y = 12; |
308 | } |
309 | |
310 | MoveTo(4, logger_y); |
311 | TextFont(geneva); |
312 | TextSize(9); |
313 | DrawText(buf, 0, len); |
314 | logger_y += 10; |
315 | |
316 | ValidRect(&logger->portRect); |
317 | SetPort(savePort); |
318 | } |
319 | #endif |