2 * WPA Supplicant - AmigaOS/MorphOS/AROS SANA-II driver interface
3 * Copyright (c) 2010-2013, Neil Cafferkey
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
21 #include <exec/types.h>
23 #include <exec/memory.h>
25 #include <devices/sana2.h>
26 #include <devices/sana2wireless.h>
27 #include <devices/newstyle.h>
29 #include <proto/exec.h>
30 #include <proto/utility.h>
31 #include <proto/dos.h>
44 #define MAX_SSID_LEN 32
46 #define MAX_TX_POWER 15
48 #define PUDDLE_SIZE 2000
49 #define MLME_REQ_COUNT 5
50 #define NULL_INTERVAL 30
54 void wpa_scan_results_free(struct wpa_scan_results
*res
);
56 static const char device_dir
[] = "Networks/";
58 static const u8 broadcast_addr
[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
61 static BOOL
wpa_driver_sana2_buffer_hook(UBYTE
*dest
, UBYTE
*src
,
64 CopyMem(src
, dest
, size
);
68 /* m68k code to do the same as above */
69 static const ULONG wpa_driver_sana2_buffer_hook
[] =
70 {0xC1492C78, 0x00044EAE, 0xFD907001, 0x4E754E71};
73 static const struct TagItem buffer_tags
[] = {
74 {S2_CopyToBuff
, (UPINT
)wpa_driver_sana2_buffer_hook
},
75 {S2_CopyFromBuff
, (UPINT
)wpa_driver_sana2_buffer_hook
},
79 struct wpa_driver_sana2_data
{
83 struct IOSana2Req
*request
;
84 struct IOSana2Req
*event_request
;
85 struct IOSana2Req
*eapol_request
;
86 struct IOSana2Req
*mlme_requests
[MLME_REQ_COUNT
];
90 char ssid
[MAX_SSID_LEN
+ 1];
98 static int b_rates
[] = {
105 static int g_rates
[] = {
121 static int wpa_driver_sana2_get_ssid(void *priv
, u8
*ssid
)
123 struct wpa_driver_sana2_data
*drv
= priv
;
126 len
= strlen(drv
->ssid
);
127 os_memcpy(ssid
, drv
->ssid
, len
);
133 static int wpa_driver_sana2_get_bssid(void *priv
, u8
*bssid
)
135 struct wpa_driver_sana2_data
*drv
= priv
;
136 u8
*cur_bssid
= NULL
;
137 struct TagItem
*tag_list
;
138 struct IOSana2Req
*request
= drv
->request
;
141 request
->ios2_Req
.io_Command
= S2_GETNETWORKINFO
;
142 pool
= CreatePool(MEMF_PUBLIC
| MEMF_CLEAR
, PUDDLE_SIZE
, PUDDLE_SIZE
);
143 request
->ios2_Data
= pool
;
144 if (pool
!= NULL
&& DoIO((APTR
)request
) == 0) {
145 tag_list
= request
->ios2_StatData
;
146 cur_bssid
= (u8
*)GetTagData(S2INFO_BSSID
, (UPINT
)NULL
,
149 if (cur_bssid
!= NULL
) {
150 os_memcpy(bssid
, cur_bssid
, ETH_ALEN
);
151 os_memcpy(drv
->bssid
, cur_bssid
, ETH_ALEN
);
155 return (cur_bssid
!= NULL
) ? 0 : 1;
159 static int wpa_driver_sana2_scan(void *priv
,
160 struct wpa_driver_scan_params
*params
)
162 struct wpa_driver_sana2_data
*drv
= priv
;
164 struct IOSana2Req
*request
= drv
->request
;
167 TEXT
*ssid_str
= NULL
;
168 struct TagItem
*tag_list
;
172 printf("[scan] MULTIPLE CONCURRENT SCAN REQUESTS!\n");
177 pool
= CreatePool(MEMF_PUBLIC
| MEMF_CLEAR
, PUDDLE_SIZE
, PUDDLE_SIZE
);
182 ssid
= params
->ssids
[0].ssid
;
183 ssid_len
= params
->ssids
[0].ssid_len
;
185 ssid_str
= AllocPooled(pool
, ssid_len
+ 1);
186 if (ssid_str
!= NULL
) {
187 CopyMem(ssid
, ssid_str
, ssid_len
);
188 ssid_str
[ssid_len
] = '\0';
195 tag_list
= AllocPooled(pool
, sizeof(struct TagItem
) * 2);
196 if (tag_list
== NULL
)
201 tag_list
[0].ti_Tag
= S2INFO_SSID
;
202 tag_list
[0].ti_Data
= (UPINT
)ssid_str
;
203 tag_list
[1].ti_Tag
= TAG_END
;
205 request
->ios2_Req
.io_Command
= S2_GETNETWORKS
;
206 request
->ios2_Data
= pool
;
207 request
->ios2_StatData
= tag_list
;
208 SendIO((APTR
)request
);
216 static struct wpa_scan_results
* wpa_driver_sana2_get_scan_results(void *priv
)
218 struct wpa_driver_sana2_data
*drv
= priv
;
220 struct IOSana2Req
*request
= drv
->request
;
221 struct wpa_scan_results
*results
;
223 struct TagItem
**tag_lists
, *tag
;
227 u16 ie_len
, ssid_len
, *data
;
229 if (request
->ios2_Req
.io_Command
!= S2_GETNETWORKS
) return NULL
;
231 count
= request
->ios2_DataLength
;
232 tag_lists
= request
->ios2_StatData
;
234 results
= os_zalloc(sizeof(struct wpa_scan_results
));
235 if (results
== NULL
) {
241 os_zalloc(count
* sizeof(struct wpa_scan_res
*));
242 if (results
->res
!= NULL
)
243 results
->num
= count
;
248 for (i
= 0; i
< count
&& err
== 0; i
++) {
249 struct wpa_scan_res
*res
;
250 data
= (u16
*)GetTagData(S2INFO_InfoElements
,
251 (UPINT
)NULL
, tag_lists
[i
]);
255 ie_len
= MAX_SSID_LEN
+ 2;
256 res
= results
->res
[i
] =
257 os_zalloc(sizeof(struct wpa_scan_res
) + ie_len
);
262 tag
= FindTagItem(S2INFO_BSSID
, tag_lists
[i
]);
264 os_memcpy(res
->bssid
, (void *)tag
->ti_Data
,
267 num
= GetTagData(S2INFO_Channel
, 0, tag_lists
[i
]);
271 res
->freq
= 2407 + num
* 5;
273 res
->beacon_int
= GetTagData(S2INFO_BeaconInterval
,
276 res
->caps
= GetTagData(S2INFO_Capabilities
, 0,
279 res
->level
= GetTagData(S2INFO_Signal
, 0, tag_lists
[i
]);
281 res
->noise
= GetTagData(S2INFO_Noise
, 0, tag_lists
[i
]);
283 if (res
->level
> res
->noise
)
284 res
->qual
= res
->level
- res
->noise
;
286 /* Copy all IEs if available, or make fake IEs
287 * containing just SSID */
288 ie
= (u8
*)(res
+ 1);
290 res
->ie_len
= ie_len
;
291 os_memcpy(ie
, data
+ 1, ie_len
);
293 str
= (TEXT
*)GetTagData(S2INFO_SSID
,
294 (UPINT
)NULL
, tag_lists
[i
]);
296 ssid_len
= strlen((char *)str
);
297 res
->ie_len
= ssid_len
+ 2;
300 os_memcpy(ie
+ 2, str
, ssid_len
);
306 DeletePool(request
->ios2_Data
);
309 wpa_scan_results_free(results
);
318 static int wpa_driver_sana2_cipher(int cipher
)
336 static int wpa_driver_sana2_band(enum hostapd_hw_mode mode
)
339 case HOSTAPD_MODE_IEEE80211B
:
341 case HOSTAPD_MODE_IEEE80211G
:
343 case HOSTAPD_MODE_IEEE80211A
:
351 static int wpa_driver_sana2_set_key(const char *ifname
, void *priv
,
352 enum wpa_alg alg
, const u8
*addr
, int key_idx
, int set_tx
,
353 const u8
*seq
, size_t seq_len
, const u8
*key
, size_t key_len
)
355 struct wpa_driver_sana2_data
*drv
= priv
;
357 struct IOSana2Req
*request
= drv
->request
;
359 request
->ios2_Req
.io_Command
= S2_SETKEY
;
360 request
->ios2_WireError
= key_idx
;
361 request
->ios2_PacketType
= wpa_driver_sana2_cipher(alg
);
362 request
->ios2_DataLength
= key_len
;
363 request
->ios2_Data
= (u8
*) key
;
364 request
->ios2_StatData
= (u8
*) seq
;
366 /* Work-around for a bug in MLME code */
367 if (wpa_driver_sana2_cipher(alg
) == S2ENC_WEP
)
370 err
= DoIO((APTR
)request
);
376 static int wpa_driver_sana2_associate(
377 void *priv
, struct wpa_driver_associate_params
*params
)
379 struct wpa_driver_sana2_data
*drv
= priv
;
381 struct IOSana2Req
*request
= drv
->request
;
382 struct TagItem
*tag_list2
= NULL
;
383 char *ssid
= os_zalloc(MAX_SSID_LEN
+ 1);
384 struct TagItem tag_list
[] =
385 {{S2INFO_SSID
, (UPINT
)ssid
},
386 {(params
->bssid
!= NULL
) ? S2INFO_BSSID
: TAG_IGNORE
,
387 (UPINT
)params
->bssid
},
388 {S2INFO_PortType
, (params
->mode
== IEEE80211_MODE_IBSS
) ?
389 S2PORT_ADHOC
: S2PORT_MANAGED
},
390 {S2INFO_Channel
, params
->freq
== 2484 ?
391 14 : (params
->freq
- 2407) / 5},
392 {S2INFO_WPAInfo
, (params
->wpa_ie_len
> 0) ?
393 (UPINT
)params
->wpa_ie
: (UPINT
)NULL
},
394 {S2INFO_AuthTypes
, params
->auth_alg
},
402 CopyMem(params
->ssid
, ssid
, params
->ssid_len
);
403 ssid
[params
->ssid_len
] = '\0';
405 tag_list2
= CloneTagItems(tag_list
);
406 if (tag_list2
== NULL
) {
411 /* Set or clear WEP keys */
412 for (i
= 0; i
< 4; i
++) {
413 if (params
->wep_key_len
[i
] > 0)
417 wpa_driver_sana2_set_key(NULL
, priv
, alg
, broadcast_addr
, i
,
418 i
== params
->wep_tx_keyidx
, NULL
, 0,
419 params
->wep_key
[i
], params
->wep_key_len
[i
]);
422 /* Set other options */
424 request
->ios2_Req
.io_Command
= S2_SETOPTIONS
;
425 request
->ios2_Data
= tag_list2
;
426 err
= DoIO((APTR
)request
);
427 FreeTagItems(tag_list2
);
430 /* Store current SSID and BSSID */
432 strcpy(drv
->ssid
, ssid
);
439 static int wpa_driver_sana2_get_capa(void *priv
, struct wpa_driver_capa
*capa
)
441 struct wpa_driver_sana2_data
*drv
= priv
;
444 struct IOSana2Req
*request
= drv
->request
;
447 os_memset(capa
, 0, sizeof(*capa
));
449 request
->ios2_Req
.io_Command
= S2_GETCRYPTTYPES
;
450 pool
= CreatePool(MEMF_PUBLIC
| MEMF_CLEAR
, PUDDLE_SIZE
, PUDDLE_SIZE
);
451 request
->ios2_Data
= pool
;
452 if (pool
!= NULL
&& DoIO((APTR
)request
) == 0) {
453 enc_list
= request
->ios2_StatData
;
454 for (i
= 0; i
< request
->ios2_DataLength
; i
++)
456 switch (enc_list
[i
]) {
458 capa
->enc
|= WPA_DRIVER_CAPA_ENC_WEP40
459 | WPA_DRIVER_CAPA_ENC_WEP104
;
462 capa
->enc
|= WPA_DRIVER_CAPA_ENC_TKIP
;
465 capa
->enc
|= WPA_DRIVER_CAPA_ENC_CCMP
;
470 capa
->enc
= WPA_DRIVER_CAPA_ENC_WEP40
|
471 WPA_DRIVER_CAPA_ENC_WEP104
|
472 WPA_DRIVER_CAPA_ENC_TKIP
|
473 WPA_DRIVER_CAPA_ENC_CCMP
;
476 if (capa
->enc
& WPA_DRIVER_CAPA_ENC_TKIP
) {
477 capa
->key_mgmt
|= WPA_DRIVER_CAPA_KEY_MGMT_WPA
|
478 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK
;
480 if (capa
->enc
& WPA_DRIVER_CAPA_ENC_CCMP
) {
481 capa
->key_mgmt
|= WPA_DRIVER_CAPA_KEY_MGMT_WPA2
|
482 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK
;
486 capa
->flags
= WPA_DRIVER_FLAGS_USER_SPACE_MLME
;
492 static int wpa_driver_sana2_send_eapol(void *priv
, const u8
*dest
, u16 proto
,
493 const u8
*data
, size_t data_len
)
495 struct wpa_driver_sana2_data
*drv
= priv
;
496 struct IOSana2Req
*request
= drv
->request
;
498 request
->ios2_Req
.io_Command
= CMD_WRITE
;
499 request
->ios2_Req
.io_Flags
= 0;
500 CopyMem(dest
, request
->ios2_DstAddr
, ETH_ALEN
);
501 request
->ios2_PacketType
= proto
;
502 request
->ios2_DataLength
= data_len
;
503 request
->ios2_Data
= (APTR
)data
;
505 return DoIO((APTR
)request
);
509 static void wpa_driver_sana2_stay_alive(void *eloop_ctx
, void *timeout_ctx
)
511 struct wpa_driver_sana2_data
*drv
= timeout_ctx
;
513 wpa_driver_sana2_send_eapol(drv
, drv
->bssid
, 0, NULL
, 0);
514 eloop_register_timeout(NULL_INTERVAL
, 0, wpa_driver_sana2_stay_alive
,
519 static const u8
*wpa_driver_sana2_get_mac_addr(void *priv
)
521 struct wpa_driver_sana2_data
*drv
= priv
;
527 static struct hostapd_hw_modes
* wpa_driver_sana2_get_hw_feature_data(
528 void *priv
, u16
*num_modes
, u16
*flags
)
530 int err
= 0, i
, mode_count
, channel_count
, rate_count
;
531 struct hostapd_hw_modes
*modes
;
538 modes
= os_zalloc(sizeof(struct hostapd_hw_modes
) * mode_count
);
544 modes
[0].mode
= HOSTAPD_MODE_IEEE80211B
;
546 modes
[0].num_channels
= channel_count
;
547 modes
[0].channels
= os_zalloc(
548 channel_count
* sizeof(struct hostapd_channel_data
));
549 if (modes
[0].channels
== NULL
)
554 for (i
= 0; i
< 13; i
++) {
555 modes
[0].channels
[i
].chan
= i
+ 1;
556 modes
[0].channels
[i
].freq
= 2407 + (i
+ 1) * 5;
557 modes
[0].channels
[i
].flag
= 0;
558 modes
[0].channels
[i
].max_tx_power
= MAX_TX_POWER
;
560 modes
[0].channels
[i
].chan
= 14;
561 modes
[0].channels
[i
].freq
= 2484;
562 modes
[0].channels
[i
].flag
= 0;
563 modes
[0].channels
[i
].max_tx_power
= MAX_TX_POWER
;
567 modes
[0].num_rates
= rate_count
;
568 modes
[0].rates
= os_zalloc(rate_count
* sizeof(int));
569 if (modes
[0].rates
== NULL
)
574 os_memcpy(modes
[0].rates
, b_rates
, sizeof(b_rates
));
582 modes
[1].mode
= HOSTAPD_MODE_IEEE80211G
;
584 modes
[1].num_channels
= channel_count
;
585 modes
[1].channels
= os_zalloc(
586 channel_count
* sizeof(struct hostapd_channel_data
));
587 if (modes
[1].channels
== NULL
)
592 for (i
= 0; i
< 13; i
++) {
593 modes
[1].channels
[i
].chan
= i
+ 1;
594 modes
[1].channels
[i
].freq
= 2407 + (i
+ 1) * 5;
595 modes
[1].channels
[i
].flag
= 0;
596 modes
[1].channels
[i
].max_tx_power
= MAX_TX_POWER
;
601 modes
[1].num_rates
= rate_count
;
602 modes
[1].rates
= os_zalloc(rate_count
* sizeof(int));
603 if (modes
[1].rates
== NULL
)
608 os_memcpy(modes
[1].rates
, g_rates
, sizeof(g_rates
));
612 os_free(modes
[0].channels
);
613 os_free(modes
[0].rates
);
614 os_free(modes
[1].channels
);
615 os_free(modes
[1].rates
);
619 *num_modes
= mode_count
;
625 static int wpa_driver_sana2_set_channel(void *priv
,
626 enum hostapd_hw_mode phymode
, int chan
, int freq
)
628 struct wpa_driver_sana2_data
*drv
= priv
;
629 struct IOSana2Req
*request
= drv
->request
;
630 struct TagItem tag_list
[] =
631 {{S2INFO_Band
, wpa_driver_sana2_band(phymode
)},
632 {S2INFO_Channel
, chan
},
636 request
->ios2_Req
.io_Command
= S2_SETOPTIONS
;
637 request
->ios2_Data
= tag_list
;
638 return DoIO((APTR
)request
);
642 static int wpa_driver_sana2_set_ssid(void *priv
, const u8
*ssid
,
645 struct wpa_driver_sana2_data
*drv
= priv
;
646 struct IOSana2Req
*request
= drv
->request
;
647 TEXT ssid_str
[ssid_len
+ 1];
648 struct TagItem tag_list
[] =
649 {{S2INFO_SSID
, (UPINT
)ssid_str
},
652 CopyMem(ssid
, ssid_str
, ssid_len
);
653 ssid_str
[ssid_len
] = '\0';
655 request
->ios2_Req
.io_Command
= S2_SETOPTIONS
;
656 request
->ios2_Data
= tag_list
;
657 return DoIO((APTR
)request
);
661 static int wpa_driver_sana2_set_bssid(void *priv
, const u8
*bssid
)
663 struct wpa_driver_sana2_data
*drv
= priv
;
664 struct IOSana2Req
*request
= drv
->request
;
665 struct TagItem tag_list
[] =
666 {{S2INFO_BSSID
, (UPINT
)bssid
},
669 CopyMem(bssid
, drv
->bssid
, ETH_ALEN
);
671 request
->ios2_Req
.io_Command
= S2_SETOPTIONS
;
672 request
->ios2_Data
= tag_list
;
673 return DoIO((APTR
)request
);
677 static int wpa_driver_sana2_set_associd(void *priv
, u16 aid
)
679 struct wpa_driver_sana2_data
*drv
= priv
;
680 struct IOSana2Req
*request
= drv
->request
;
681 struct TagItem tag_list
[] =
682 {{S2INFO_AssocID
, aid
},
685 eloop_register_timeout(NULL_INTERVAL
, 0, wpa_driver_sana2_stay_alive
,
688 request
->ios2_Req
.io_Command
= S2_SETOPTIONS
;
689 request
->ios2_Data
= tag_list
;
690 return DoIO((APTR
)request
);
694 static int wpa_driver_sana2_set_capabilities(void *priv
, u16 capab
)
696 struct wpa_driver_sana2_data
*drv
= priv
;
697 struct IOSana2Req
*request
= drv
->request
;
698 struct TagItem tag_list
[] =
699 {{S2INFO_Capabilities
, capab
},
702 request
->ios2_Req
.io_Command
= S2_SETOPTIONS
;
703 request
->ios2_Data
= tag_list
;
704 return DoIO((APTR
)request
);
708 static int wpa_driver_sana2_send_mlme(void *priv
, const u8
*data
,
711 struct wpa_driver_sana2_data
*drv
= priv
;
712 struct IOSana2Req
*request
= drv
->request
;
714 wpa_printf(MSG_DEBUG
, "sana2: sending MLME frame");
715 request
->ios2_Req
.io_Command
= S2_WRITEMGMT
;
716 request
->ios2_Req
.io_Flags
= 0;
717 request
->ios2_DataLength
= data_len
;
718 request
->ios2_Data
= (APTR
)data
;
720 return DoIO((APTR
)request
);
724 static int wpa_driver_sana2_mlme_add_sta(void *priv
, const u8
*addr
,
725 const u8
*supp_rates
, size_t supp_rates_len
)
731 static int wpa_driver_sana2_mlme_remove_sta(void *priv
, const u8
*addr
)
737 static void wpa_driver_sana2_event_handler(int sig
, void *sig_ctx
)
739 struct wpa_driver_sana2_data
*drv
= sig_ctx
;
742 struct IOSana2Req
*request
;
743 union wpa_event_data event_data
;
744 struct TagItem
*tag_list
;
748 os_memset(&event_data
, 0, sizeof(event_data
));
750 /* Propagate events */
751 while ((request
= (APTR
)GetMsg(drv
->port
)) != NULL
)
753 switch (request
->ios2_Req
.io_Command
)
756 if (request
->ios2_Req
.io_Error
== 0) {
757 /* Deliver frame to supplicant */
758 drv_event_eapol_rx(drv
->ctx
,
759 request
->ios2_SrcAddr
,
761 request
->ios2_DataLength
);
763 if (request
->ios2_Req
.io_Error
!= S2ERR_OUTOFSERVICE
) {
764 /* Send request back for next frame */
765 SendIO((APTR
)request
);
770 if (request
->ios2_Req
.io_Error
== 0) {
771 /* Deliver frame to supplicant */
772 os_memset(&event_data
, 0, sizeof(event_data
));
773 event_data
.mlme_rx
.buf
= request
->ios2_Data
;
774 event_data
.mlme_rx
.len
=
775 request
->ios2_DataLength
;
776 event_data
.mlme_rx
.freq
= drv
->freq
;
777 wpa_supplicant_event(drv
->ctx
, EVENT_MLME_RX
,
780 if (request
->ios2_Req
.io_Error
!= S2ERR_OUTOFSERVICE
) {
781 /* Send request back for next frame */
782 request
->ios2_DataLength
= ETH_MTU
;
783 SendIO((APTR
)request
);
788 events
= request
->ios2_WireError
;
789 if (request
->ios2_Req
.io_Error
!= 0)
791 if (events
& S2EVENT_CONNECT
)
793 request
->ios2_Req
.io_Command
=
795 pool
= CreatePool(MEMF_PUBLIC
| MEMF_CLEAR
,
796 PUDDLE_SIZE
, PUDDLE_SIZE
);
797 request
->ios2_Data
= pool
;
798 if (pool
!= NULL
&& DoIO((APTR
)request
) == 0)
800 tag_list
= request
->ios2_StatData
;
801 event_data
.assoc_info
.req_ies
= ie
=
802 (u8
*)GetTagData(S2INFO_WPAInfo
,
808 event_data
.assoc_info
.req_ies_len
=
811 event_data
.assoc_info
.req_ies_len
= 0;
813 wpa_supplicant_event(drv
->ctx
, EVENT_ASSOC
,
818 /* Start periodic sending of null-data frames */
819 eloop_register_timeout(NULL_INTERVAL
, 0,
820 wpa_driver_sana2_stay_alive
,
824 if (events
& S2EVENT_DISCONNECT
) {
825 wpa_supplicant_event(drv
->ctx
, EVENT_DISASSOC
,
828 /* Stop periodic sending of null-data frames */
829 eloop_cancel_timeout(
830 wpa_driver_sana2_stay_alive
,
834 if (events
& S2EVENT_ONLINE
) {
835 drv
->event_mask
&= ~S2EVENT_ONLINE
;
836 drv
->event_mask
|= S2EVENT_OFFLINE
;
838 /* Send read requests back for next frame */
839 SendIO((APTR
)drv
->eapol_request
);
841 for (i
= 0; i
< MLME_REQ_COUNT
; i
++)
843 drv
->mlme_requests
[i
]);
846 if (events
& S2EVENT_OFFLINE
) {
847 drv
->event_mask
&= ~S2EVENT_OFFLINE
;
848 drv
->event_mask
|= S2EVENT_ONLINE
;
851 /* Send request back to receive next event */
852 request
->ios2_Req
.io_Command
= S2_ONEVENT
;
853 request
->ios2_WireError
= drv
->event_mask
;
854 SendIO((APTR
)request
);
858 wpa_supplicant_event(drv
->ctx
, EVENT_SCAN_RESULTS
,
866 static void wpa_driver_sana2_deinit(void *priv
)
868 struct wpa_driver_sana2_data
*drv
= priv
;
871 /* Abort outstanding I/O requests */
872 if (drv
->eapol_request
!= NULL
) {
873 AbortIO((APTR
)drv
->eapol_request
);
874 WaitIO((APTR
)drv
->eapol_request
);
875 FreeVec(drv
->eapol_request
);
878 for (i
= 0; i
< MLME_REQ_COUNT
; i
++) {
879 if (drv
->mlme_requests
[i
] != NULL
) {
880 AbortIO((APTR
)drv
->mlme_requests
[i
]);
881 WaitIO((APTR
)drv
->mlme_requests
[i
]);
882 FreeVec(drv
->mlme_requests
[i
]);
886 if (drv
->event_request
!= NULL
) {
887 AbortIO((APTR
)drv
->event_request
);
888 WaitIO((APTR
)drv
->event_request
);
892 if (drv
->device_opened
) {
893 AbortIO((APTR
)drv
->request
);
894 WaitIO((APTR
)drv
->request
);
895 CloseDevice((APTR
)drv
->request
);
897 DeleteIORequest((APTR
)drv
->request
);
898 DeleteMsgPort(drv
->port
);
900 FreeVec(drv
->device_name
);
906 static void * wpa_driver_sana2_init(void *ctx
, const char *ifname
)
908 struct wpa_driver_sana2_data
*drv
;
912 struct IOSana2Req
*request
, *eapol_request
, *mlme_request
;
913 struct NSDeviceQueryResult device_info
=
914 {0, sizeof(struct NSDeviceQueryResult
)};
916 drv
= os_zalloc(sizeof(*drv
));
920 drv
->device_name
= AllocVec(strlen(device_dir
) + strlen(ifname
),
922 if (drv
->device_name
== NULL
)
925 /* Split fake interface name into device and unit */
927 end
= strrchr(ifname
, ':');
928 if (strchr(ifname
, ':') == end
&& strchr(ifname
, '/') == NULL
) {
929 strcpy(drv
->device_name
, device_dir
);
930 p
= drv
->device_name
+ strlen(device_dir
);
932 p
= drv
->device_name
;
933 strncpy(p
, ifname
, end
- ifname
);
934 p
[end
- ifname
] = '\0';
936 unit_no
= atoi(end
+ 1);
938 drv
->port
= CreateMsgPort();
939 drv
->request
= (APTR
)CreateIORequest(drv
->port
,
940 sizeof(struct IOSana2Req
));
941 if (drv
->request
== NULL
)
947 drv
->request
->ios2_BufferManagement
= (APTR
)buffer_tags
;
948 if (OpenDevice((TEXT
*)drv
->device_name
, unit_no
,
949 (APTR
)drv
->request
, 0) != 0)
953 /* Register a handler for the port's signal */
955 drv
->device_opened
= 1;
957 eloop_register_signal(drv
->port
->mp_SigBit
,
958 wpa_driver_sana2_event_handler
, drv
);
961 /* Check if this is a hard-MAC device */
963 request
= drv
->request
;
964 ((struct IOStdReq
*)request
)->io_Command
= NSCMD_DEVICEQUERY
;
965 ((struct IOStdReq
*)request
)->io_Data
= &device_info
;
966 if (DoIO((APTR
)request
) != 0)
969 for (i
= 0; device_info
.SupportedCommands
[i
] != 0; i
++)
970 if (device_info
.SupportedCommands
[i
]
976 /* Put device online */
978 request
= drv
->request
;
979 request
->ios2_Req
.io_Command
= S2_GETSTATIONADDRESS
;
980 if (DoIO((APTR
)request
) != 0)
985 CopyMem(request
->ios2_DstAddr
, drv
->addr
, ETH_ALEN
);
987 request
->ios2_Req
.io_Command
= S2_CONFIGINTERFACE
;
988 CopyMem(drv
->addr
, request
->ios2_SrcAddr
, ETH_ALEN
);
990 if (DoIO((APTR
)request
) != 0) {
991 if (request
->ios2_WireError
== S2WERR_IS_CONFIGURED
) {
992 request
->ios2_Req
.io_Command
= S2_ONLINE
;
1000 /* Create and queue up EAPOL frame read request */
1002 request
= drv
->request
;
1003 request
->ios2_Req
.io_Command
= CMD_READ
;
1004 request
->ios2_PacketType
= ETH_P_EAPOL
;
1006 eapol_request
= AllocVec(sizeof(struct IOSana2Req
) + ETH_MTU
,
1007 MEMF_PUBLIC
| MEMF_CLEAR
);
1008 if (eapol_request
== NULL
)
1013 CopyMem(drv
->request
, eapol_request
,
1014 sizeof(struct IOSana2Req
));
1015 eapol_request
->ios2_Data
= eapol_request
+ 1;
1016 drv
->eapol_request
= eapol_request
;
1018 SendIO((APTR
)eapol_request
);
1021 /* Create and queue up management frame read requests */
1022 if (err
== 0 && !drv
->hard_mac
) {
1023 request
= drv
->request
;
1024 request
->ios2_Req
.io_Command
= S2_READMGMT
;
1025 request
->ios2_DataLength
= ETH_MTU
;
1026 for (i
= 0; i
< MLME_REQ_COUNT
; i
++) {
1028 AllocVec(sizeof(struct IOSana2Req
) + ETH_MTU
,
1029 MEMF_PUBLIC
| MEMF_CLEAR
);
1030 if (mlme_request
== NULL
)
1034 CopyMem(drv
->request
, mlme_request
,
1035 sizeof(struct IOSana2Req
));
1036 mlme_request
->ios2_Data
= mlme_request
+ 1;
1037 drv
->mlme_requests
[i
] = mlme_request
;
1039 SendIO((APTR
)mlme_request
);
1045 /* Create and send event-notification request */
1046 request
= drv
->request
;
1047 request
->ios2_Req
.io_Command
= S2_ONEVENT
;
1049 drv
->event_mask
= S2EVENT_CONNECT
| S2EVENT_DISCONNECT
1052 drv
->event_mask
= S2EVENT_OFFLINE
;
1053 request
->ios2_WireError
= drv
->event_mask
;
1055 drv
->event_request
= AllocVec(sizeof(struct IOSana2Req
),
1056 MEMF_PUBLIC
| MEMF_CLEAR
);
1057 if (drv
->event_request
== NULL
)
1062 CopyMem(drv
->request
, drv
->event_request
,
1063 sizeof(struct IOSana2Req
));
1065 SendIO((APTR
)drv
->event_request
);
1069 wpa_driver_sana2_deinit(drv
);
1077 const struct wpa_driver_ops wpa_driver_sana2_ops
= {
1079 .desc
= "SANA-II driver",
1080 .get_bssid
= wpa_driver_sana2_get_bssid
,
1081 .get_ssid
= wpa_driver_sana2_get_ssid
,
1082 .set_key
= wpa_driver_sana2_set_key
,
1083 .init
= wpa_driver_sana2_init
,
1084 .deinit
= wpa_driver_sana2_deinit
,
1085 .scan2
= wpa_driver_sana2_scan
,
1086 .associate
= wpa_driver_sana2_associate
,
1087 .get_capa
= wpa_driver_sana2_get_capa
,
1088 .get_mac_addr
= wpa_driver_sana2_get_mac_addr
,
1089 .send_eapol
= wpa_driver_sana2_send_eapol
,
1090 .get_scan_results2
= wpa_driver_sana2_get_scan_results
,
1091 .get_hw_feature_data
= wpa_driver_sana2_get_hw_feature_data
,
1092 .set_channel
= wpa_driver_sana2_set_channel
,
1093 .set_ssid
= wpa_driver_sana2_set_ssid
,
1094 .set_bssid
= wpa_driver_sana2_set_bssid
,
1095 .set_associd
= wpa_driver_sana2_set_associd
,
1096 .set_capabilities
= wpa_driver_sana2_set_capabilities
,
1097 .send_mlme
= wpa_driver_sana2_send_mlme
,
1098 .mlme_add_sta
= wpa_driver_sana2_mlme_add_sta
,
1099 .mlme_remove_sta
= wpa_driver_sana2_mlme_remove_sta
,