From 70897c9d7fead219818ebb4485bee61e76079935 Mon Sep 17 00:00:00 2001 From: Andrey Zhuchkov Date: Tue, 2 Jun 2026 16:32:24 +0400 Subject: [PATCH 1/2] fix: report CoreWLAN channel widths correctly CoreWLAN reports channel width as enum raw values where 0 is unknown and 1 through 4 represent 20, 40, 80, and 160 MHz. The helper previously treated 0 as 20 MHz and shifted the known values, which made the scan example print incorrect WIDTH values. Add a Swift helper regression test for the raw-value mapping. Verified with make swift-check, a targeted Swift helper test run, and go test -short ./.... --- scanner/Sources/WifiScanner.swift | 2 +- scanner/Tests/WifiScannerTests.swift | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/scanner/Sources/WifiScanner.swift b/scanner/Sources/WifiScanner.swift index f58d911..acb97ff 100644 --- a/scanner/Sources/WifiScanner.swift +++ b/scanner/Sources/WifiScanner.swift @@ -138,7 +138,7 @@ func mapBand(_ b: CWChannelBand) -> UInt8 { switch b.rawValue { case 1: return 1; case 2: return 2; case 3: return 3; default: return 0 } } func mapWidth(_ w: CWChannelWidth) -> UInt16 { - switch w.rawValue { case 0: return 20; case 1: return 40; case 2: return 80; case 3: return 160; default: return 0 } + switch w.rawValue { case 1: return 20; case 2: return 40; case 3: return 80; case 4: return 160; default: return 0 } } func detectSecurity(_ n: CWNetwork) -> UInt8 { let probes: [(CWSecurity, UInt8)] = [ diff --git a/scanner/Tests/WifiScannerTests.swift b/scanner/Tests/WifiScannerTests.swift index b3ea3ff..c53b88e 100644 --- a/scanner/Tests/WifiScannerTests.swift +++ b/scanner/Tests/WifiScannerTests.swift @@ -1,5 +1,6 @@ import Darwin import Foundation +import CoreWLAN struct TestFailure: Error, CustomStringConvertible { let message: String @@ -107,6 +108,27 @@ func testParseBSSIDRejectsMissingInvalidOrShortValues() throws { try expectEqual(parseBSSID("01:23:45:67:89:xx"), Data(), "invalid BSSID should parse as empty data") } +func testMapWidthUsesCoreWLANRawValues() throws { + let cases: [(Int, UInt16)] = [ + (0, 0), + (1, 20), + (2, 40), + (3, 80), + (4, 160), + ] + + for (rawValue, expectedWidth) in cases { + guard let width = CWChannelWidth(rawValue: rawValue) else { + throw TestFailure(message: "CWChannelWidth(rawValue: \(rawValue)) should exist") + } + try expectEqual( + mapWidth(width), + expectedWidth, + "mapWidth should convert CoreWLAN raw value \(rawValue)" + ) + } +} + func testEncodePasswordResponseMatchesWireFormat() throws { let response = encodePasswordResponse(password: "secret", error: "denied") @@ -180,6 +202,7 @@ struct WifiScannerTestRunner { ("writeAll writes full payloads", testWriteAllWritesFullPayload), ("parseBSSID accepts valid hex octets", testParseBSSIDAcceptsHexOctets), ("parseBSSID rejects invalid values", testParseBSSIDRejectsMissingInvalidOrShortValues), + ("mapWidth uses CoreWLAN raw values", testMapWidthUsesCoreWLANRawValues), ("encodePasswordResponse matches wire format", testEncodePasswordResponseMatchesWireFormat), ("encodeScanResponse matches wire format", testEncodeScanResponseMatchesWireFormat), ] From 7df75a0c1501380cdcaefb5acd8b5095c01edbad Mon Sep 17 00:00:00 2001 From: Andrey Zhuchkov Date: Sat, 6 Jun 2026 21:13:20 +0400 Subject: [PATCH 2/2] fix: map CoreWLAN widths by enum constants --- scanner/Sources/WifiScanner.swift | 9 ++++++++- scanner/Tests/WifiScannerTests.swift | 23 ++++++++++------------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/scanner/Sources/WifiScanner.swift b/scanner/Sources/WifiScanner.swift index acb97ff..5322709 100644 --- a/scanner/Sources/WifiScanner.swift +++ b/scanner/Sources/WifiScanner.swift @@ -138,7 +138,14 @@ func mapBand(_ b: CWChannelBand) -> UInt8 { switch b.rawValue { case 1: return 1; case 2: return 2; case 3: return 3; default: return 0 } } func mapWidth(_ w: CWChannelWidth) -> UInt16 { - switch w.rawValue { case 1: return 20; case 2: return 40; case 3: return 80; case 4: return 160; default: return 0 } + switch w { + case .widthUnknown: return 0 + case .width20MHz: return 20 + case .width40MHz: return 40 + case .width80MHz: return 80 + case .width160MHz: return 160 + @unknown default: return 0 + } } func detectSecurity(_ n: CWNetwork) -> UInt8 { let probes: [(CWSecurity, UInt8)] = [ diff --git a/scanner/Tests/WifiScannerTests.swift b/scanner/Tests/WifiScannerTests.swift index c53b88e..2169f5e 100644 --- a/scanner/Tests/WifiScannerTests.swift +++ b/scanner/Tests/WifiScannerTests.swift @@ -108,23 +108,20 @@ func testParseBSSIDRejectsMissingInvalidOrShortValues() throws { try expectEqual(parseBSSID("01:23:45:67:89:xx"), Data(), "invalid BSSID should parse as empty data") } -func testMapWidthUsesCoreWLANRawValues() throws { - let cases: [(Int, UInt16)] = [ - (0, 0), - (1, 20), - (2, 40), - (3, 80), - (4, 160), +func testMapWidthUsesCoreWLANChannelWidthConstants() throws { + let cases: [(CWChannelWidth, UInt16, String)] = [ + (.widthUnknown, 0, "unknown"), + (.width20MHz, 20, "20 MHz"), + (.width40MHz, 40, "40 MHz"), + (.width80MHz, 80, "80 MHz"), + (.width160MHz, 160, "160 MHz"), ] - for (rawValue, expectedWidth) in cases { - guard let width = CWChannelWidth(rawValue: rawValue) else { - throw TestFailure(message: "CWChannelWidth(rawValue: \(rawValue)) should exist") - } + for (width, expectedWidth, name) in cases { try expectEqual( mapWidth(width), expectedWidth, - "mapWidth should convert CoreWLAN raw value \(rawValue)" + "mapWidth should convert CoreWLAN \(name) channel width" ) } } @@ -202,7 +199,7 @@ struct WifiScannerTestRunner { ("writeAll writes full payloads", testWriteAllWritesFullPayload), ("parseBSSID accepts valid hex octets", testParseBSSIDAcceptsHexOctets), ("parseBSSID rejects invalid values", testParseBSSIDRejectsMissingInvalidOrShortValues), - ("mapWidth uses CoreWLAN raw values", testMapWidthUsesCoreWLANRawValues), + ("mapWidth uses CoreWLAN channel width constants", testMapWidthUsesCoreWLANChannelWidthConstants), ("encodePasswordResponse matches wire format", testEncodePasswordResponseMatchesWireFormat), ("encodeScanResponse matches wire format", testEncodeScanResponseMatchesWireFormat), ]