Skip to content

Commit 7568658

Browse files
committed
Wifi (macOS): improve support for macOS Sequoia
Fix #1194
1 parent c64720c commit 7568658

File tree

1 file changed

+103
-1
lines changed

1 file changed

+103
-1
lines changed

src/detection/wifi/wifi_apple.m

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "wifi.h"
22
#include "common/processing.h"
3+
#include "util/stringUtils.h"
34

45
#import <CoreWLAN/CoreWLAN.h>
56

@@ -20,7 +21,7 @@ @interface CWInterface()
2021
return CFBridgingRelease(result);
2122
}
2223

23-
const char* ffDetectWifi(FFlist* result)
24+
static const char* detectWifiByCoreWlan(FFlist* result)
2425
{
2526
NSArray<CWInterface*>* interfaces = CWWiFiClient.sharedWiFiClient.interfaces;
2627
if(!interfaces)
@@ -211,3 +212,104 @@ @interface CWInterface()
211212
}
212213
return NULL;
213214
}
215+
216+
static const char* detectWifiBySystemProfiler(FFlist* result)
217+
{
218+
// Warning: costs about 2s on my machine
219+
220+
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
221+
if (ffProcessAppendStdOut(&buffer, (char* const[]) {
222+
"system_profiler",
223+
"SPAirPortDataType",
224+
"-xml",
225+
"-detailLevel",
226+
"basic",
227+
NULL
228+
}) != NULL)
229+
return "Starting `system_profiler SPAirPortDataType -xml -detailLevel basic` failed";
230+
231+
NSArray* arr = [NSPropertyListSerialization propertyListWithData:[NSData dataWithBytes:buffer.chars length:buffer.length]
232+
options:NSPropertyListImmutable
233+
format:nil
234+
error:nil];
235+
if (!arr || !arr.count)
236+
return "system_profiler SPAirPortDataType returned an empty array";
237+
238+
for (NSDictionary* data in arr[0][@"_items"])
239+
{
240+
for (NSDictionary* inf in data[@"spairport_airport_interfaces"])
241+
{
242+
if (![inf[@"spairport_wireless_card_type"] isEqualToString:@"spairport_wireless_card_type_wifi (0x14E4, 0x4387)"]) continue;
243+
244+
FFWifiResult* item = (FFWifiResult*)ffListAdd(result);
245+
ffStrbufInitS(&item->inf.description, [inf[@"_name"] UTF8String]);
246+
ffStrbufInit(&item->inf.status);
247+
ffStrbufInit(&item->conn.status);
248+
ffStrbufInit(&item->conn.ssid);
249+
ffStrbufInit(&item->conn.bssid);
250+
ffStrbufInit(&item->conn.protocol);
251+
ffStrbufInit(&item->conn.security);
252+
item->conn.signalQuality = 0.0/0.0;
253+
item->conn.rxRate = 0.0/0.0;
254+
item->conn.txRate = 0.0/0.0;
255+
256+
NSString* status = inf[@"spairport_status_information"]; // spairport_status_connected spairport_status_disassociated spairport_status_off
257+
258+
ffStrbufSetStatic(&item->inf.status, [status isEqualToString:@"spairport_status_off"] ? "Power Off" : "Power On");
259+
260+
NSDictionary* station = inf[@"spairport_current_network_information"];
261+
if (!station) continue;
262+
263+
ffStrbufSetS(&item->conn.status, status.UTF8String + strlen("spairport_status_"));
264+
item->conn.status.chars[0] = (char) toupper(item->conn.status.chars[0]);
265+
266+
ffStrbufSetS(&item->conn.ssid, [station[@"_name"] UTF8String]);
267+
268+
ffStrbufSetS(&item->conn.protocol, [station[@"spairport_network_phymode"] UTF8String]);
269+
if (ffStrbufStartsWithS(&item->conn.protocol, "802.11"))
270+
{
271+
const char* subProtocol = item->conn.protocol.chars + strlen("802.11");
272+
if (ffStrEquals(subProtocol, "be"))
273+
ffStrbufSetStatic(&item->conn.protocol, "802.11be (Wi-Fi 7)");
274+
else if (ffStrEquals(subProtocol, "ax"))
275+
ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
276+
else if (ffStrEquals(subProtocol, "ac"))
277+
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
278+
else if (ffStrEquals(subProtocol, "n"))
279+
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
280+
}
281+
282+
ffStrbufSetS(&item->conn.security, [station[@"spairport_security_mode"] UTF8String]);
283+
ffStrbufSubstrAfterFirstS(&item->conn.security, "_mode_");
284+
if (ffStrbufEqualS(&item->conn.security, "none"))
285+
ffStrbufSetStatic(&item->conn.security, "Insecure");
286+
else
287+
{
288+
ffStrbufReplaceAllC(&item->conn.security, '_', ' ');
289+
if (ffStrbufStartsWithS(&item->conn.security, "wpa"))
290+
{
291+
item->conn.security.chars[0] = 'W';
292+
item->conn.security.chars[1] = 'P';
293+
item->conn.security.chars[2] = 'A';
294+
char* sub = strchr(item->conn.security.chars, ' ');
295+
if (sub && sub[1])
296+
sub[1] = (char) toupper(sub[1]);
297+
}
298+
}
299+
300+
double rssiValue = strtod([station[@"spairport_signal_noise"] UTF8String], nil);
301+
item->conn.signalQuality = (double) (rssiValue >= -50 ? 100 : rssiValue <= -100 ? 0 : (rssiValue + 100) * 2);
302+
item->conn.txRate = (double) [station[@"spairport_network_rate"] longValue];
303+
}
304+
}
305+
306+
return NULL;
307+
}
308+
309+
const char* ffDetectWifi(FFlist* result)
310+
{
311+
if (@available(macOS 15.0, *))
312+
return detectWifiBySystemProfiler(result);
313+
else
314+
return detectWifiByCoreWlan(result);
315+
}

0 commit comments

Comments
 (0)