@@ -92,10 +92,12 @@ pub const Cmd = enum(u32) {
9292 set_auth = 22 ,
9393 set_ssid = 26 ,
9494 set_antdiv = 64 ,
95+ set_pm = 86 ,
9596 set_gmode = 110 ,
9697 set_wsec = 134 ,
9798 set_band = 142 ,
9899 set_wpa_auth = 165 ,
100+ set_scan_channel_time = 185 ,
99101 get_var = 262 ,
100102 set_var = 263 ,
101103 set_wsec_pmk = 268 ,
@@ -184,7 +186,7 @@ pub const Response = struct {
184186 return .{ head , self .sdp .len - head };
185187 }
186188
187- pub fn event (self : Self ) EventPacket {
189+ pub fn event (self : Self ) ? EventPacket {
188190 assert (self .sdp .channel () == .event );
189191 const buf = self .data ();
190192 if (buf .len < @sizeOf (EventPacket )) {
@@ -195,8 +197,64 @@ pub const Response = struct {
195197 var evt : EventPacket = undefined ;
196198 @memcpy (std .mem .asBytes (& evt ), buf [0.. @sizeOf (EventPacket )]);
197199 std .mem .byteSwapAllFields (EventPacket , & evt );
200+
201+ if (evt .eth .ether_type != 0x886c ) return null ;
202+ if (! mem .eql (u8 , & evt .hdr .oui , &.{ 0x00 , 0x10 , 0x18 })) return null ;
203+
198204 return evt ;
199205 }
206+
207+ pub fn event_scan_result (self : Self ) ! struct { EventScanResult , Security } {
208+ var res : EventScanResult = undefined ;
209+ var sec : Security = .{};
210+
211+ assert (self .sdp .channel () == .event );
212+ const buf = self .data ();
213+ if (buf .len < @sizeOf (EventPacket ) + @sizeOf (EventScanResult )) {
214+ return error .Cyw43InsufficientData ;
215+ }
216+ const res_buf = buf [@sizeOf (EventPacket ).. ];
217+ @memcpy (std .mem .asBytes (& res ), res_buf [0.. @sizeOf (EventScanResult )]);
218+ res .channel &= 0xff ;
219+ if (res_buf .len < res .ie_offset + res .ie_length ) {
220+ return error .Cyw43InsufficientData ;
221+ }
222+
223+ // ref: https://github.com/georgerobotics/cyw43-driver/blob/13004039ffe127519f33824bf7d240e1f23fbdcd/src/cyw43_ll.c#L538
224+ const is_open = res .capability & 0x0010 == 0 ;
225+ if (! is_open ) sec .wep_psk = true ;
226+
227+ var ie_buf = res_buf [res .ie_offset .. ][0.. res .ie_length ];
228+ while (ie_buf .len >= 2 ) {
229+ const typ = ie_buf [0 ];
230+ const len = ie_buf [1 ];
231+ ie_buf = ie_buf [2.. ];
232+ if (typ == 48 ) {
233+ sec .wpa2 = true ;
234+ } else {
235+ const wpa_oui_type1 = "\x00\x50\xF2\x01 " ;
236+ if (typ == 221 and ie_buf .len >= wpa_oui_type1 .len ) {
237+ if (mem .eql (u8 , ie_buf [0.. wpa_oui_type1 .len ], wpa_oui_type1 )) {
238+ sec .wpa = true ;
239+ }
240+ }
241+ }
242+ if (ie_buf .len <= len ) break ;
243+ ie_buf = ie_buf [len .. ];
244+ }
245+
246+ return .{ res , sec };
247+ }
248+ };
249+
250+ pub const Security = packed struct {
251+ wep_psk : bool = false ,
252+ wpa : bool = false ,
253+ wpa2 : bool = false ,
254+
255+ pub fn open (s : Security ) bool {
256+ return @as (u3 , @bitCast (s )) == 0 ;
257+ }
200258};
201259
202260pub fn response (buf : []const u8 ) ! Response {
@@ -350,12 +408,43 @@ const EventPacket = extern struct {
350408};
351409
352410// Escan result event (excluding 12-byte IOCTL header and BDC header)
353- const EventScanResult = extern struct {
354- eth : EthernetHeader ,
355- hdr : EventHeader ,
356- msg : EventMessage ,
357- scan : ScanResultHeader ,
358- info : BssInfo ,
411+ pub const EventScanResult = extern struct {
412+ // Scan result header
413+ const Header = extern struct {
414+ buflen : u32 ,
415+ version : u32 ,
416+ sync_id : u16 ,
417+ bss_count : u16 ,
418+ };
419+
420+ hdr : Header ,
421+
422+ version : u32 , // version field
423+ length : u32 , // byte length of data in this record, starting at version and including IEs
424+ bssid : [6 ]u8 , // The MAC address of the Access Point (AP)
425+ beacon_period : u16 , // Interval between two consecutive beacon frames. Units are Kusec
426+ capability : u16 , // Capability information
427+ ssid_len : u8 , // SSID length
428+ ssid : [32 ]u8 , // Array to store SSID
429+ nrates : u32 , // Count of rates in this set
430+ rates : [16 ]u8 , // rates in 500kbps units, higher bit set if basic
431+ channel : u16 , // Channel specification for basic service set
432+ atim_window : u16 , // Announcement traffic indication message window size. Units are Kusec
433+ dtim_period : u8 , // Delivery traffic indication message period
434+ rssi : u16 , // receive signal strength (in dBm)
435+ phy_noise : u8 , // noise (in dBm)
436+ // The following fields assume the 'version' field is 109 (0x6D)
437+ n_cap : u8 , // BSS is 802.11N Capable
438+ nbss_cap : u32 , // 802.11N BSS Capabilities (based on HT_CAP_*)
439+ ctl_ch : u8 , // 802.11N BSS control channel number
440+ reserved1 : u32 , // Reserved for expansion of BSS properties
441+ flags : u8 , // flags
442+ reserved2 : [3 ]u8 , // Reserved for expansion of BSS properties
443+ basic_mcs : [16 ]u8 , // 802.11N BSS required MCS set
444+ ie_offset : u16 , // offset at which IEs start, from beginning
445+ ie_length : u32 , // byte length of Information Elements
446+ snr : u16 , // Average SNR(signal to noise ratio) during frame reception
447+ // Variable-length Information Elements follow, see cyw43_ll_wifi_parse_scan_result
359448};
360449
361450// Ethernet header (sdpcm_ethernet_header_t)
@@ -375,7 +464,7 @@ const EventHeader = extern struct {
375464};
376465
377466// Raw event header (sdpcm_raw_event_header_t)
378- const EventMessage = extern struct {
467+ pub const EventMessage = extern struct {
379468 version : u16 ,
380469 flags : u16 ,
381470 event_type : EventType ,
@@ -389,48 +478,9 @@ const EventMessage = extern struct {
389478 bsscfgidx : u8 ,
390479};
391480
392- // Scan result header (part of wl_escan_result_t)
393- const ScanResultHeader = extern struct {
394- buflen : u32 ,
395- version : u32 ,
396- sync_id : u16 ,
397- bss_count : u16 ,
398- };
399-
400- // BSS info from EScan (part of wl_bss_info_t)
401- const BssInfo = extern struct {
402- version : u32 , // version field
403- length : u32 , // byte length of data in this record, starting at version and including IEs
404- bssid : [6 ]u8 , // Unique 6-byte MAC address
405- beacon_period : u16 , // Interval between two consecutive beacon frames. Units are Kusec
406- capability : u16 , // Capability information
407- ssid_len : u8 , // SSID length
408- ssid : [32 ]u8 , // Array to store SSID
409- nrates : u32 , // Count of rates in this set
410- rates : [16 ]u8 , // rates in 500kbps units, higher bit set if basic
411- channel : u16 , // Channel specification for basic service set
412- atim_window : u16 , // Announcement traffic indication message window size. Units are Kusec
413- dtim_period : u8 , // Delivery traffic indication message period
414- rssi : u16 , // receive signal strength (in dBm)
415- phy_noise : u8 , // noise (in dBm)
416- // The following fields assume the 'version' field is 109 (0x6D)
417- n_cap : u8 , // BSS is 802.11N Capable
418- nbss_cap : u32 , // 802.11N BSS Capabilities (based on HT_CAP_*)
419- ctl_ch : u8 , // 802.11N BSS control channel number
420- reserved1 : u32 , // Reserved for expansion of BSS properties
421- flags : u8 , // flags
422- reserved2 : [3 ]u8 , // Reserved for expansion of BSS properties
423- basic_mcs : [16 ]u8 , // 802.11N BSS required MCS set
424- ie_offset : u16 , // offset at which IEs start, from beginning
425- ie_length : u32 , // byte length of Information Elements
426- snr : u16 , // Average SNR(signal to noise ratio) during frame reception
427- // Variable-length Information Elements follow, see cyw43_ll_wifi_parse_scan_result
428- };
429-
430- // zig fmt: off
431-
432481// Async events
433- const EventType = enum (u32 ) {
482+ pub const EventType = enum (u32 ) {
483+ // zig fmt: off
434484 none = 0xffffffff ,
435485 set_ssid = 0 , // indicates status of set ssid ,
436486 join = 1 , // differentiates join ibss from found (wlc_e_start) ibss
@@ -582,9 +632,17 @@ const EventType = enum(u32) {
582632 ext_auth_frame_rx = 188 , // authentication request received
583633 mgmt_frame_txstatus = 189 , // mgmt frame Tx complete
584634 _ ,
585- };
635+ // zig fmt: on
586636
587- // zig fmt: on
637+ pub fn mask (events : []const EventType ) [26 ]u8 {
638+ var m : [26 ]u8 = @splat (0 );
639+ for (events ) | event | {
640+ const e : u32 = @intFromEnum (event );
641+ m [4 + e / 8 ] |= @as (u8 , 1 ) << @as (u3 , @truncate (e & 7 ));
642+ }
643+ return m ;
644+ }
645+ };
588646
589647pub const EventStatus = enum (u32 ) {
590648 /// operation was successful
@@ -718,3 +776,22 @@ test "small data is padded in request to 4 bytes" {
718776
719777 try testing .expectEqualSlices (u8 , r1 , r2 );
720778}
779+
780+ test "events mask" {
781+ const buf = hex_to_bytes ("000000008B120102004000000000800100000000000000000000" );
782+ try testing .expectEqual (26 , buf .len );
783+ const mask = EventType .mask (&.{
784+ .join ,
785+ .assoc ,
786+ .reassoc ,
787+ .assoc_req_ie ,
788+ .assoc_resp_ie ,
789+ .set_ssid ,
790+ .link ,
791+ .auth ,
792+ .psk_sup ,
793+ .eapol_msg ,
794+ .disassoc_ind ,
795+ });
796+ try testing .expectEqualSlices (u8 , & buf , & mask );
797+ }
0 commit comments