2 * WPA Supplicant - AmigaOS/MorphOS/AROS SANA-II driver interface
3 * Copyright (c) 2010-2011, 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
);
154 return (cur_bssid
!= NULL
) ? 0 : 1;
158 static int wpa_driver_sana2_scan(void *priv
,
159 struct wpa_driver_scan_params
*params
)
161 struct wpa_driver_sana2_data
*drv
= priv
;
163 struct IOSana2Req
*request
= drv
->request
;
166 TEXT
*ssid_str
= NULL
;
167 struct TagItem
*tag_list
;
171 printf("[scan] MULTIPLE CONCURRENT SCAN REQUESTS!\n");
176 pool
= CreatePool(MEMF_PUBLIC
| MEMF_CLEAR
, PUDDLE_SIZE
, PUDDLE_SIZE
);
181 ssid
= params
->ssids
[0].ssid
;
182 ssid_len
= params
->ssids
[0].ssid_len
;
184 ssid_str
= AllocPooled(pool
, ssid_len
+ 1);
185 if (ssid_str
!= NULL
) {
186 CopyMem(ssid
, ssid_str
, ssid_len
);
187 ssid_str
[ssid_len
] = '\0';
194 tag_list
= AllocPooled(pool
, sizeof(struct TagItem
) * 2);
195 if (tag_list
== NULL
)
200 tag_list
[0].ti_Tag
= S2INFO_SSID
;
201 tag_list
[0].ti_Data
= (UPINT
)ssid_str
;
202 tag_list
[1].ti_Tag
= TAG_END
;
204 request
->ios2_Req
.io_Command
= S2_GETNETWORKS
;
205 request
->ios2_Data
= pool
;
206 request
->ios2_StatData
= tag_list
;
207 SendIO((APTR
)request
);
215 static struct wpa_scan_results
* wpa_driver_sana2_get_scan_results(void *priv
)
217 struct wpa_driver_sana2_data
*drv
= priv
;
219 struct IOSana2Req
*request
= drv
->request
;
220 struct wpa_scan_results
*results
;
222 struct TagItem
**tag_lists
, *tag
;
226 u16 ie_len
, ssid_len
, *data
;
228 if (request
->ios2_Req
.io_Command
!= S2_GETNETWORKS
) return NULL
;
230 count
= request
->ios2_DataLength
;
231 tag_lists
= request
->ios2_StatData
;
233 results
= os_zalloc(sizeof(struct wpa_scan_results
));
234 if (results
== NULL
) {
240 os_zalloc(count
* sizeof(struct wpa_scan_res
*));
241 if (results
->res
!= NULL
)
242 results
->num
= count
;
247 for (i
= 0; i
< count
&& err
== 0; i
++) {
248 struct wpa_scan_res
*res
;
249 data
= (u16
*)GetTagData(S2INFO_InfoElements
,
250 (UPINT
)NULL
, tag_lists
[i
]);
254 ie_len
= MAX_SSID_LEN
+ 2;
255 res
= results
->res
[i
] =
256 os_zalloc(sizeof(struct wpa_scan_res
) + ie_len
);
261 tag
= FindTagItem(S2INFO_BSSID
, tag_lists
[i
]);
263 os_memcpy(res
->bssid
, (void *)tag
->ti_Data
,
266 num
= GetTagData(S2INFO_Channel
, 0, tag_lists
[i
]);
270 res
->freq
= 2407 + num
* 5;
272 res
->beacon_int
= GetTagData(S2INFO_BeaconInterval
,
275 res
->caps
= GetTagData(S2INFO_Capabilities
, 0,
278 res
->level
= GetTagData(S2INFO_Signal
, 0, tag_lists
[i
]);
280 res
->noise
= GetTagData(S2INFO_Noise
, 0, tag_lists
[i
]);
282 if (res
->level
> res
->noise
)
283 res
->qual
= res
->level
- res
->noise
;
285 /* Copy all IEs if available, or make fake IEs
286 * containing just SSID */
287 ie
= (u8
*)(res
+ 1);
289 res
->ie_len
= ie_len
;
290 os_memcpy(ie
, data
+ 1, ie_len
);
292 str
= (TEXT
*)GetTagData(S2INFO_SSID
,
293 (UPINT
)NULL
, tag_lists
[i
]);
295 ssid_len
= strlen((char *)str
);
296 res
->ie_len
= ssid_len
+ 2;
299 os_memcpy(ie
+ 2, str
, ssid_len
);
305 DeletePool(request
->ios2_Data
);
308 wpa_scan_results_free(results
);
317 static int wpa_driver_sana2_cipher(int cipher
)
335 static int wpa_driver_sana2_band(enum hostapd_hw_mode mode
)
338 case HOSTAPD_MODE_IEEE80211B
:
340 case HOSTAPD_MODE_IEEE80211G
:
342 case HOSTAPD_MODE_IEEE80211A
:
350 static int wpa_driver_sana2_set_key(const char *ifname
, void *priv
,
351 enum wpa_alg alg
, const u8
*addr
, int key_idx
, int set_tx
,
352 const u8
*seq
, size_t seq_len
, const u8
*key
, size_t key_len
)
354 struct wpa_driver_sana2_data
*drv
= priv
;
356 struct IOSana2Req
*request
= drv
->request
;
358 request
->ios2_Req
.io_Command
= S2_SETKEY
;
359 request
->ios2_WireError
= key_idx
;
360 request
->ios2_PacketType
= wpa_driver_sana2_cipher(alg
);
361 request
->ios2_DataLength
= key_len
;
362 request
->ios2_Data
= (u8
*) key
;
363 request
->ios2_StatData
= (u8
*) seq
;
365 /* Work-around for a bug in MLME code */
366 if(wpa_driver_sana2_cipher(alg
) == S2ENC_WEP
)
369 err
= DoIO((APTR
)request
);
375 static int wpa_driver_sana2_associate(
376 void *priv
, struct wpa_driver_associate_params
*params
)
378 struct wpa_driver_sana2_data
*drv
= priv
;
380 struct IOSana2Req
*request
= drv
->request
;
381 struct TagItem
*tag_list2
= NULL
;
382 char *ssid
= os_zalloc(MAX_SSID_LEN
+ 1);
383 struct TagItem tag_list
[] =
384 {{S2INFO_SSID
, (UPINT
)ssid
},
385 {(params
->bssid
!= NULL
) ? S2INFO_BSSID
: TAG_IGNORE
,
386 (UPINT
)params
->bssid
},
388 wpa_driver_sana2_cipher(params
->group_suite
)},
389 {S2INFO_PortType
, (params
->mode
== IEEE80211_MODE_IBSS
) ?
390 S2PORT_ADHOC
: S2PORT_MANAGED
},
391 {S2INFO_Channel
, params
->freq
== 2484 ?
392 2484 : (params
->freq
- 2407) / 5},
393 {S2INFO_WPAInfo
, (params
->wpa_ie_len
> 0) ?
394 (UPINT
)params
->wpa_ie
: (UPINT
)NULL
},
395 {S2INFO_AuthTypes
, params
->auth_alg
},
403 CopyMem(params
->ssid
, ssid
, params
->ssid_len
);
404 ssid
[params
->ssid_len
] = '\0';
406 tag_list2
= CloneTagItems(tag_list
);
407 if (tag_list2
== NULL
) {
412 /* Set or clear WEP keys */
413 for (i
= 0; i
< 4; i
++) {
414 if (params
->wep_key_len
[i
] > 0)
418 wpa_driver_sana2_set_key(NULL
, priv
, alg
, broadcast_addr
, i
,
419 i
== params
->wep_tx_keyidx
, NULL
, 0,
420 params
->wep_key
[i
], params
->wep_key_len
[i
]);
423 /* Set other options */
425 request
->ios2_Req
.io_Command
= S2_SETOPTIONS
;
426 request
->ios2_Data
= tag_list2
;
427 err
= DoIO((APTR
)request
);
428 FreeTagItems(tag_list2
);
431 /* Store current SSID and BSSID */
434 strcpy(drv
->ssid
, ssid
);
441 static int wpa_driver_sana2_get_capa(void *priv
, struct wpa_driver_capa
*capa
)
443 struct wpa_driver_sana2_data
*drv
= priv
;
445 os_memset(capa
, 0, sizeof(*capa
));
447 capa
->key_mgmt
= WPA_DRIVER_CAPA_KEY_MGMT_WPA
|
448 WPA_DRIVER_CAPA_KEY_MGMT_WPA2
|
449 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK
|
450 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK
;
451 capa
->enc
= WPA_DRIVER_CAPA_ENC_WEP40
| WPA_DRIVER_CAPA_ENC_WEP104
|
452 WPA_DRIVER_CAPA_ENC_TKIP
| WPA_DRIVER_CAPA_ENC_CCMP
;
454 capa
->flags
= WPA_DRIVER_FLAGS_USER_SPACE_MLME
;
460 static int wpa_driver_sana2_send_eapol(void *priv
, const u8
*dest
, u16 proto
,
461 const u8
*data
, size_t data_len
)
463 struct wpa_driver_sana2_data
*drv
= priv
;
464 struct IOSana2Req
*request
= drv
->request
;
466 request
->ios2_Req
.io_Command
= CMD_WRITE
;
467 request
->ios2_Req
.io_Flags
= 0;
468 CopyMem(dest
, request
->ios2_DstAddr
, ETH_ALEN
);
469 request
->ios2_PacketType
= proto
;
470 request
->ios2_DataLength
= data_len
;
471 request
->ios2_Data
= (APTR
)data
;
473 return DoIO((APTR
)request
);
477 static void wpa_driver_sana2_stay_alive(void *eloop_ctx
, void *timeout_ctx
)
479 struct wpa_driver_sana2_data
*drv
= timeout_ctx
;
481 wpa_driver_sana2_send_eapol(drv
, drv
->bssid
, 0, NULL
, 0);
482 eloop_register_timeout(NULL_INTERVAL
, 0, wpa_driver_sana2_stay_alive
,
487 static const u8
*wpa_driver_sana2_get_mac_addr(void *priv
)
489 struct wpa_driver_sana2_data
*drv
= priv
;
495 static struct hostapd_hw_modes
* wpa_driver_sana2_get_hw_feature_data(
496 void *priv
, u16
*num_modes
, u16
*flags
)
498 int err
= 0, i
, mode_count
, channel_count
, rate_count
;
499 struct hostapd_hw_modes
*modes
;
506 modes
= os_zalloc(sizeof(struct hostapd_hw_modes
) * mode_count
);
512 modes
[0].mode
= HOSTAPD_MODE_IEEE80211B
;
514 modes
[0].num_channels
= channel_count
;
515 modes
[0].channels
= os_zalloc(
516 channel_count
* sizeof(struct hostapd_channel_data
));
517 if (modes
[0].channels
== NULL
)
522 for (i
= 0; i
< 13; i
++) {
523 modes
[0].channels
[i
].chan
= i
+ 1;
524 modes
[0].channels
[i
].freq
= 2407 + (i
+ 1) * 5;
525 modes
[0].channels
[i
].flag
= 0;
526 modes
[0].channels
[i
].max_tx_power
= MAX_TX_POWER
;
528 modes
[0].channels
[i
].chan
= 14;
529 modes
[0].channels
[i
].freq
= 2484;
530 modes
[0].channels
[i
].flag
= 0;
531 modes
[0].channels
[i
].max_tx_power
= MAX_TX_POWER
;
535 modes
[0].num_rates
= rate_count
;
536 modes
[0].rates
= os_zalloc(rate_count
* sizeof(int));
537 if (modes
[0].rates
== NULL
)
542 os_memcpy(modes
[0].rates
, b_rates
, sizeof(b_rates
));
550 modes
[1].mode
= HOSTAPD_MODE_IEEE80211G
;
552 modes
[1].num_channels
= channel_count
;
553 modes
[1].channels
= os_zalloc(
554 channel_count
* sizeof(struct hostapd_channel_data
));
555 if (modes
[1].channels
== NULL
)
560 for (i
= 0; i
< 13; i
++) {
561 modes
[1].channels
[i
].chan
= i
+ 1;
562 modes
[1].channels
[i
].freq
= 2407 + (i
+ 1) * 5;
563 modes
[1].channels
[i
].flag
= 0;
564 modes
[1].channels
[i
].max_tx_power
= MAX_TX_POWER
;
569 modes
[1].num_rates
= rate_count
;
570 modes
[1].rates
= os_zalloc(rate_count
* sizeof(int));
571 if (modes
[1].rates
== NULL
)
576 os_memcpy(modes
[1].rates
, g_rates
, sizeof(g_rates
));
580 os_free(modes
[0].channels
);
581 os_free(modes
[0].rates
);
582 os_free(modes
[1].channels
);
583 os_free(modes
[1].rates
);
587 *num_modes
= mode_count
;
593 static int wpa_driver_sana2_set_channel(void *priv
,
594 enum hostapd_hw_mode phymode
, int chan
, int freq
)
596 struct wpa_driver_sana2_data
*drv
= priv
;
597 struct IOSana2Req
*request
= drv
->request
;
598 struct TagItem tag_list
[] =
599 {{S2INFO_Band
, wpa_driver_sana2_band(phymode
)},
600 {S2INFO_Channel
, chan
},
604 request
->ios2_Req
.io_Command
= S2_SETOPTIONS
;
605 request
->ios2_Data
= tag_list
;
606 return DoIO((APTR
)request
);
610 static int wpa_driver_sana2_set_ssid(void *priv
, const u8
*ssid
,
613 struct wpa_driver_sana2_data
*drv
= priv
;
614 struct IOSana2Req
*request
= drv
->request
;
615 TEXT ssid_str
[ssid_len
+ 1];
616 struct TagItem tag_list
[] =
617 {{S2INFO_SSID
, (UPINT
)ssid_str
},
620 CopyMem(ssid
, ssid_str
, ssid_len
);
621 ssid_str
[ssid_len
] = '\0';
623 request
->ios2_Req
.io_Command
= S2_SETOPTIONS
;
624 request
->ios2_Data
= tag_list
;
625 return DoIO((APTR
)request
);
629 static int wpa_driver_sana2_set_bssid(void *priv
, const u8
*bssid
)
631 struct wpa_driver_sana2_data
*drv
= priv
;
632 struct IOSana2Req
*request
= drv
->request
;
633 struct TagItem tag_list
[] =
634 {{S2INFO_BSSID
, (UPINT
)bssid
},
637 CopyMem(bssid
, drv
->bssid
, ETH_ALEN
);
639 request
->ios2_Req
.io_Command
= S2_SETOPTIONS
;
640 request
->ios2_Data
= tag_list
;
641 return DoIO((APTR
)request
);
645 static int wpa_driver_sana2_set_associd(void *priv
, u16 aid
)
647 struct wpa_driver_sana2_data
*drv
= priv
;
648 struct IOSana2Req
*request
= drv
->request
;
649 struct TagItem tag_list
[] =
650 {{S2INFO_AssocID
, aid
},
653 eloop_register_timeout(NULL_INTERVAL
, 0, wpa_driver_sana2_stay_alive
,
656 request
->ios2_Req
.io_Command
= S2_SETOPTIONS
;
657 request
->ios2_Data
= tag_list
;
658 return DoIO((APTR
)request
);
662 static int wpa_driver_sana2_set_capabilities(void *priv
, u16 capab
)
664 struct wpa_driver_sana2_data
*drv
= priv
;
665 struct IOSana2Req
*request
= drv
->request
;
666 struct TagItem tag_list
[] =
667 {{S2INFO_Capabilities
, capab
},
670 wpa_printf(MSG_DEBUG
, "sana2: setting negotiated capabilities");
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_send_mlme(void *priv
, const u8
*data
,
680 struct wpa_driver_sana2_data
*drv
= priv
;
681 struct IOSana2Req
*request
= drv
->request
;
683 wpa_printf(MSG_DEBUG
, "sana2: sending MLME frame");
684 request
->ios2_Req
.io_Command
= S2_WRITEMGMT
;
685 request
->ios2_Req
.io_Flags
= 0;
686 request
->ios2_DataLength
= data_len
;
687 request
->ios2_Data
= (APTR
)data
;
689 return DoIO((APTR
)request
);
693 static int wpa_driver_sana2_mlme_add_sta(void *priv
, const u8
*addr
,
694 const u8
*supp_rates
, size_t supp_rates_len
)
700 static int wpa_driver_sana2_mlme_remove_sta(void *priv
, const u8
*addr
)
706 static void wpa_driver_sana2_event_handler(int sig
, void *sig_ctx
)
708 struct wpa_driver_sana2_data
*drv
= sig_ctx
;
711 struct IOSana2Req
*request
;
712 union wpa_event_data event_data
;
713 struct TagItem
*tag_list
;
717 os_memset(&event_data
, 0, sizeof(event_data
));
719 /* Propagate events */
720 while((request
= (APTR
)GetMsg(drv
->port
)) != NULL
)
722 switch(request
->ios2_Req
.io_Command
)
725 if(request
->ios2_Req
.io_Error
== 0) {
726 /* Deliver frame to supplicant */
727 drv_event_eapol_rx(drv
->ctx
,
728 request
->ios2_SrcAddr
,
730 request
->ios2_DataLength
);
732 if(request
->ios2_Req
.io_Error
!= S2ERR_OUTOFSERVICE
) {
733 /* Send request back for next frame */
734 SendIO((APTR
)request
);
739 if(request
->ios2_Req
.io_Error
== 0) {
740 /* Deliver frame to supplicant */
741 os_memset(&event_data
, 0, sizeof(event_data
));
742 event_data
.mlme_rx
.buf
= request
->ios2_Data
;
743 event_data
.mlme_rx
.len
=
744 request
->ios2_DataLength
;
745 event_data
.mlme_rx
.freq
= drv
->freq
;
746 wpa_supplicant_event(drv
->ctx
, EVENT_MLME_RX
,
749 if(request
->ios2_Req
.io_Error
!= S2ERR_OUTOFSERVICE
) {
750 /* Send request back for next frame */
751 request
->ios2_DataLength
= ETH_MTU
;
752 SendIO((APTR
)request
);
757 events
= request
->ios2_WireError
;
758 if (request
->ios2_Req
.io_Error
!= 0)
760 if (events
& S2EVENT_CONNECT
)
762 request
->ios2_Req
.io_Command
=
764 pool
= CreatePool(MEMF_PUBLIC
| MEMF_CLEAR
,
765 PUDDLE_SIZE
, PUDDLE_SIZE
);
766 request
->ios2_Data
= pool
;
767 if (pool
!= NULL
&& DoIO((APTR
)request
) == 0)
769 tag_list
= request
->ios2_StatData
;
770 event_data
.assoc_info
.req_ies
= ie
=
771 (u8
*)GetTagData(S2INFO_WPAInfo
,
777 event_data
.assoc_info
.req_ies_len
=
780 event_data
.assoc_info
.req_ies_len
= 0;
782 wpa_supplicant_event(drv
->ctx
, EVENT_ASSOC
,
787 /* Start periodic sending of null-data frames */
788 eloop_register_timeout(NULL_INTERVAL
, 0,
789 wpa_driver_sana2_stay_alive
,
793 if (events
& S2EVENT_DISCONNECT
) {
794 wpa_supplicant_event(drv
->ctx
, EVENT_DISASSOC
,
797 /* Stop periodic sending of null-data frames */
798 eloop_cancel_timeout(
799 wpa_driver_sana2_stay_alive
,
803 if (events
& S2EVENT_ONLINE
) {
804 drv
->event_mask
&= ~S2EVENT_ONLINE
;
805 drv
->event_mask
|= S2EVENT_OFFLINE
;
807 /* Send read requests back for next frame */
808 SendIO((APTR
)drv
->eapol_request
);
810 for(i
= 0; i
< MLME_REQ_COUNT
; i
++)
812 drv
->mlme_requests
[i
]);
815 if (events
& S2EVENT_OFFLINE
) {
816 drv
->event_mask
&= ~S2EVENT_OFFLINE
;
817 drv
->event_mask
|= S2EVENT_ONLINE
;
820 /* Send request back to receive next event */
821 request
->ios2_Req
.io_Command
= S2_ONEVENT
;
822 request
->ios2_WireError
= drv
->event_mask
;
823 SendIO((APTR
)request
);
827 wpa_supplicant_event(drv
->ctx
, EVENT_SCAN_RESULTS
,
835 static void wpa_driver_sana2_deinit(void *priv
)
837 struct wpa_driver_sana2_data
*drv
= priv
;
840 /* Abort outstanding I/O requests */
841 if(drv
->eapol_request
!= NULL
) {
842 AbortIO((APTR
)drv
->eapol_request
);
843 WaitIO((APTR
)drv
->eapol_request
);
844 FreeVec(drv
->eapol_request
);
847 for(i
= 0; i
< MLME_REQ_COUNT
; i
++) {
848 if(drv
->mlme_requests
[i
] != NULL
) {
849 AbortIO((APTR
)drv
->mlme_requests
[i
]);
850 WaitIO((APTR
)drv
->mlme_requests
[i
]);
851 FreeVec(drv
->mlme_requests
[i
]);
855 if(drv
->event_request
!= NULL
) {
856 AbortIO((APTR
)drv
->event_request
);
857 WaitIO((APTR
)drv
->event_request
);
861 if(drv
->device_opened
) {
862 AbortIO((APTR
)drv
->request
);
863 WaitIO((APTR
)drv
->request
);
864 CloseDevice((APTR
)drv
->request
);
866 DeleteIORequest((APTR
)drv
->request
);
867 DeleteMsgPort(drv
->port
);
869 FreeVec(drv
->device_name
);
875 static void * wpa_driver_sana2_init(void *ctx
, const char *ifname
)
877 struct wpa_driver_sana2_data
*drv
;
881 struct IOSana2Req
*request
, *eapol_request
, *mlme_request
;
882 struct NSDeviceQueryResult device_info
=
883 {0, sizeof(struct NSDeviceQueryResult
)};
885 drv
= os_zalloc(sizeof(*drv
));
889 drv
->device_name
= AllocVec(strlen(device_dir
) + strlen(ifname
),
891 if(drv
->device_name
== NULL
)
894 /* Split fake interface name into device and unit */
896 end
= strrchr(ifname
, ':');
897 if(strchr(ifname
, ':') == end
&& strchr(ifname
, '/') == NULL
) {
898 strcpy(drv
->device_name
, device_dir
);
899 p
= drv
->device_name
+ strlen(device_dir
);
901 p
= drv
->device_name
;
902 strncpy(p
, ifname
, end
- ifname
);
903 p
[end
- ifname
] = '\0';
905 unit_no
= atoi(end
+ 1);
907 drv
->port
= CreateMsgPort();
908 drv
->request
= (APTR
)CreateIORequest(drv
->port
,
909 sizeof(struct IOSana2Req
));
910 if(drv
->request
== NULL
)
916 drv
->request
->ios2_BufferManagement
= (APTR
)buffer_tags
;
917 if(OpenDevice((TEXT
*)drv
->device_name
, unit_no
,
918 (APTR
)drv
->request
, 0) != 0)
922 /* Register a handler for the port's signal */
924 drv
->device_opened
= 1;
926 eloop_register_signal(drv
->port
->mp_SigBit
,
927 wpa_driver_sana2_event_handler
, drv
);
930 /* Check if this is a hard-MAC device */
932 request
= drv
->request
;
933 ((struct IOStdReq
*)request
)->io_Command
= NSCMD_DEVICEQUERY
;
934 ((struct IOStdReq
*)request
)->io_Data
= &device_info
;
935 if(DoIO((APTR
)request
) != 0)
938 for(i
= 0; device_info
.SupportedCommands
[i
] != 0; i
++)
939 if(device_info
.SupportedCommands
[i
]
945 /* Put device online */
947 request
= drv
->request
;
948 request
->ios2_Req
.io_Command
= S2_GETSTATIONADDRESS
;
949 if(DoIO((APTR
)request
) != 0)
954 CopyMem(request
->ios2_DstAddr
, drv
->addr
, ETH_ALEN
);
956 request
->ios2_Req
.io_Command
= S2_CONFIGINTERFACE
;
957 CopyMem(drv
->addr
, request
->ios2_SrcAddr
, ETH_ALEN
);
959 if(DoIO((APTR
)request
) != 0) {
960 if(request
->ios2_WireError
== S2WERR_IS_CONFIGURED
) {
961 request
->ios2_Req
.io_Command
= S2_ONLINE
;
969 /* Create and queue up EAPOL frame read request */
971 request
= drv
->request
;
972 request
->ios2_Req
.io_Command
= CMD_READ
;
973 request
->ios2_PacketType
= ETH_P_EAPOL
;
975 eapol_request
= AllocVec(sizeof(struct IOSana2Req
) + ETH_MTU
,
976 MEMF_PUBLIC
| MEMF_CLEAR
);
977 if(eapol_request
== NULL
)
982 CopyMem(drv
->request
, eapol_request
,
983 sizeof(struct IOSana2Req
));
984 eapol_request
->ios2_Data
= eapol_request
+ 1;
985 drv
->eapol_request
= eapol_request
;
987 SendIO((APTR
)eapol_request
);
990 /* Create and queue up management frame read requests */
991 if(err
== 0 && !drv
->hard_mac
) {
992 request
= drv
->request
;
993 request
->ios2_Req
.io_Command
= S2_READMGMT
;
994 request
->ios2_DataLength
= ETH_MTU
;
995 for(i
= 0; i
< MLME_REQ_COUNT
; i
++) {
997 AllocVec(sizeof(struct IOSana2Req
) + ETH_MTU
,
998 MEMF_PUBLIC
| MEMF_CLEAR
);
999 if(mlme_request
== NULL
)
1003 CopyMem(drv
->request
, mlme_request
,
1004 sizeof(struct IOSana2Req
));
1005 mlme_request
->ios2_Data
= mlme_request
+ 1;
1006 drv
->mlme_requests
[i
] = mlme_request
;
1008 SendIO((APTR
)mlme_request
);
1014 /* Create and send event-notification request */
1015 request
= drv
->request
;
1016 request
->ios2_Req
.io_Command
= S2_ONEVENT
;
1018 drv
->event_mask
= S2EVENT_CONNECT
| S2EVENT_DISCONNECT
1021 drv
->event_mask
= S2EVENT_OFFLINE
;
1022 request
->ios2_WireError
= drv
->event_mask
;
1024 drv
->event_request
= AllocVec(sizeof(struct IOSana2Req
),
1025 MEMF_PUBLIC
| MEMF_CLEAR
);
1026 if(drv
->event_request
== NULL
)
1031 CopyMem(drv
->request
, drv
->event_request
,
1032 sizeof(struct IOSana2Req
));
1034 SendIO((APTR
)drv
->event_request
);
1038 wpa_driver_sana2_deinit(drv
);
1046 const struct wpa_driver_ops wpa_driver_sana2_ops
= {
1048 .desc
= "SANA-II driver",
1049 .get_bssid
= wpa_driver_sana2_get_bssid
,
1050 .get_ssid
= wpa_driver_sana2_get_ssid
,
1051 .set_key
= wpa_driver_sana2_set_key
,
1052 .init
= wpa_driver_sana2_init
,
1053 .deinit
= wpa_driver_sana2_deinit
,
1054 .scan2
= wpa_driver_sana2_scan
,
1055 .associate
= wpa_driver_sana2_associate
,
1056 .get_capa
= wpa_driver_sana2_get_capa
,
1057 .get_mac_addr
= wpa_driver_sana2_get_mac_addr
,
1058 .send_eapol
= wpa_driver_sana2_send_eapol
,
1059 .get_scan_results2
= wpa_driver_sana2_get_scan_results
,
1060 .get_hw_feature_data
= wpa_driver_sana2_get_hw_feature_data
,
1061 .set_channel
= wpa_driver_sana2_set_channel
,
1062 .set_ssid
= wpa_driver_sana2_set_ssid
,
1063 .set_bssid
= wpa_driver_sana2_set_bssid
,
1064 .set_associd
= wpa_driver_sana2_set_associd
,
1065 .set_capabilities
= wpa_driver_sana2_set_capabilities
,
1066 .send_mlme
= wpa_driver_sana2_send_mlme
,
1067 .mlme_add_sta
= wpa_driver_sana2_mlme_add_sta
,
1068 .mlme_remove_sta
= wpa_driver_sana2_mlme_remove_sta
,