Corrections to SVN properties.
[AROS.git] / workbench / network / WirelessManager / src / drivers / driver_sana2.c
blobb897e423f62ffb4ef6020a87444937602b5f68b6
1 /*
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
10 * license.
12 * See README and COPYING for more details.
15 #include "includes.h"
17 #include "common.h"
18 #include "driver.h"
19 #include "eloop.h"
21 #include <exec/types.h>
22 #include <exec/io.h>
23 #include <exec/memory.h>
24 #include <dos/dos.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>
33 #ifndef UPINT
34 #ifdef __AROS__
35 typedef IPTR UPINT;
36 typedef SIPTR PINT;
37 #else
38 typedef ULONG UPINT;
39 typedef LONG PINT;
40 #endif
41 #endif
43 #define ETH_MTU 1500
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
52 int using_wep = 0;
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};
60 #ifdef __AROS__
61 static BOOL wpa_driver_sana2_buffer_hook(UBYTE *dest, UBYTE *src,
62 ULONG size)
64 CopyMem(src, dest, size);
65 return TRUE;
67 #else
68 /* m68k code to do the same as above */
69 static const ULONG wpa_driver_sana2_buffer_hook[] =
70 {0xC1492C78, 0x00044EAE, 0xFD907001, 0x4E754E71};
71 #endif
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},
76 {TAG_END, 0}
79 struct wpa_driver_sana2_data {
80 void *ctx;
81 char *device_name;
82 struct MsgPort *port;
83 struct IOSana2Req *request;
84 struct IOSana2Req *event_request;
85 struct IOSana2Req *eapol_request;
86 struct IOSana2Req *mlme_requests[MLME_REQ_COUNT];
87 ULONG event_mask;
88 u8 addr[ETH_ALEN];
89 u8 bssid[ETH_ALEN];
90 char ssid[MAX_SSID_LEN + 1];
91 int freq;
92 int device_opened;
93 int hard_mac;
94 int scanning;
95 int online;
98 static int b_rates[] = {
99 10,
105 static int g_rates[] = {
109 110,
112 120,
113 180,
114 240,
115 360,
116 480,
121 static int wpa_driver_sana2_get_ssid(void *priv, u8 *ssid)
123 struct wpa_driver_sana2_data *drv = priv;
124 u16 len;
126 len = strlen(drv->ssid);
127 os_memcpy(ssid, drv->ssid, len);
129 return 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;
139 APTR pool;
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,
147 tag_list);
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;
162 int err = 0;
163 struct IOSana2Req *request = drv->request;
164 const u8 *ssid;
165 size_t ssid_len;
166 TEXT *ssid_str = NULL;
167 struct TagItem *tag_list;
168 APTR pool;
170 if (drv->scanning) {
171 printf("[scan] MULTIPLE CONCURRENT SCAN REQUESTS!\n");
172 Delay(200);
173 return 1;
176 pool = CreatePool(MEMF_PUBLIC | MEMF_CLEAR, PUDDLE_SIZE, PUDDLE_SIZE);
177 if (pool == NULL)
178 err = 1;
180 if (err == 0) {
181 ssid = params->ssids[0].ssid;
182 ssid_len = params->ssids[0].ssid_len;
183 if (ssid != NULL) {
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';
188 } else
189 err = 1;
193 if (err == 0) {
194 tag_list = AllocPooled(pool, sizeof(struct TagItem) * 2);
195 if (tag_list == NULL)
196 err = 1;
199 if (err == 0) {
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);
208 drv->scanning = 1;
211 return err;
215 static struct wpa_scan_results * wpa_driver_sana2_get_scan_results(void *priv)
217 struct wpa_driver_sana2_data *drv = priv;
218 int err = 0;
219 struct IOSana2Req *request = drv->request;
220 struct wpa_scan_results *results;
221 size_t i, count;
222 struct TagItem **tag_lists, *tag;
223 TEXT *str;
224 UPINT num;
225 u8 *ie;
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) {
235 err = 1;
238 if (err == 0) {
239 results->res =
240 os_zalloc(count * sizeof(struct wpa_scan_res *));
241 if (results->res != NULL)
242 results->num = count;
243 else
244 err = 1;
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]);
251 if (data != NULL)
252 ie_len = data[0];
253 else
254 ie_len = MAX_SSID_LEN + 2;
255 res = results->res[i] =
256 os_zalloc(sizeof(struct wpa_scan_res) + ie_len);
257 if (res == NULL)
258 err = 1;
260 if (err == 0) {
261 tag = FindTagItem(S2INFO_BSSID, tag_lists[i]);
262 if (tag != NULL)
263 os_memcpy(res->bssid, (void *)tag->ti_Data,
264 ETH_ALEN);
266 num = GetTagData(S2INFO_Channel, 0, tag_lists[i]);
267 if (num == 14)
268 res->freq = 2484;
269 else if (num != 0)
270 res->freq = 2407 + num * 5;
272 res->beacon_int = GetTagData(S2INFO_BeaconInterval,
273 0, tag_lists[i]);
275 res->caps = GetTagData(S2INFO_Capabilities, 0,
276 tag_lists[i]);
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);
288 if (data != NULL) {
289 res->ie_len = ie_len;
290 os_memcpy(ie, data + 1, ie_len);
291 } else {
292 str = (TEXT *)GetTagData(S2INFO_SSID,
293 (UPINT)NULL, tag_lists[i]);
294 if (str != NULL) {
295 ssid_len = strlen((char *)str);
296 res->ie_len = ssid_len + 2;
297 ie[0] = 0;
298 ie[1] = ssid_len;
299 os_memcpy(ie + 2, str, ssid_len);
305 DeletePool(request->ios2_Data);
307 if (err != 0) {
308 wpa_scan_results_free(results);
309 results = NULL;
312 drv->scanning = 0;
313 return results;
317 static int wpa_driver_sana2_cipher(int cipher)
319 switch (cipher) {
320 case CIPHER_NONE:
321 return S2ENC_NONE;
322 case CIPHER_WEP40:
323 case CIPHER_WEP104:
324 return S2ENC_WEP;
325 case CIPHER_TKIP:
326 return S2ENC_TKIP;
327 case CIPHER_CCMP:
328 return S2ENC_CCMP;
329 default:
330 return 0;
335 static int wpa_driver_sana2_band(enum hostapd_hw_mode mode)
337 switch (mode) {
338 case HOSTAPD_MODE_IEEE80211B:
339 return S2BAND_B;
340 case HOSTAPD_MODE_IEEE80211G:
341 return S2BAND_G;
342 case HOSTAPD_MODE_IEEE80211A:
343 return S2BAND_A;
344 default:
345 return 0;
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;
355 int err = 0;
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)
367 using_wep = 1;
369 err = DoIO((APTR)request);
371 return err;
375 static int wpa_driver_sana2_associate(
376 void *priv, struct wpa_driver_associate_params *params)
378 struct wpa_driver_sana2_data *drv = priv;
379 int err = 0, i, alg;
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},
387 {S2INFO_Encryption,
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},
396 {TAG_END, 0}};
398 if (ssid == NULL) {
399 err = 1;
402 if (err == 0) {
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) {
408 err = 1;
412 /* Set or clear WEP keys */
413 for (i = 0; i < 4; i++) {
414 if (params->wep_key_len[i] > 0)
415 alg = WPA_ALG_WEP;
416 else
417 alg = WPA_ALG_NONE;
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 */
424 if (err == 0) {
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 */
433 if (err == 0) {
434 strcpy(drv->ssid, ssid);
437 return 0;
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;
453 if(!drv->hard_mac)
454 capa->flags = WPA_DRIVER_FLAGS_USER_SPACE_MLME;
456 return 0;
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,
483 drv->ctx, drv);
487 static const u8 *wpa_driver_sana2_get_mac_addr(void *priv)
489 struct wpa_driver_sana2_data *drv = priv;
491 return drv->addr;
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;
501 /* IEEE 802.11b */
502 mode_count = 2;
503 channel_count = 14;
504 rate_count = 4;
506 modes = os_zalloc(sizeof(struct hostapd_hw_modes) * mode_count);
507 if (modes == NULL) {
508 err = 1;
511 if (err == 0) {
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)
518 err = 1;
521 if (err == 0) {
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;
534 if (err == 0) {
535 modes[0].num_rates = rate_count;
536 modes[0].rates = os_zalloc(rate_count * sizeof(int));
537 if (modes[0].rates == NULL)
538 err = 1;
541 if (err == 0) {
542 os_memcpy(modes[0].rates, b_rates, sizeof(b_rates));
545 /* IEEE 802.11g */
546 channel_count = 13;
547 rate_count = 12;
549 if (err == 0) {
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)
556 err = 1;
559 if (err == 0) {
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;
568 if (err == 0) {
569 modes[1].num_rates = rate_count;
570 modes[1].rates = os_zalloc(rate_count * sizeof(int));
571 if (modes[1].rates == NULL)
572 err = 1;
575 if (err == 0) {
576 os_memcpy(modes[1].rates, g_rates, sizeof(g_rates));
579 if (err != 0) {
580 os_free(modes[0].channels);
581 os_free(modes[0].rates);
582 os_free(modes[1].channels);
583 os_free(modes[1].rates);
584 modes = NULL;
587 *num_modes = mode_count;
588 *flags = 0;
589 return modes;
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},
601 {TAG_END, 0}};
603 drv->freq = freq;
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,
611 size_t ssid_len)
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},
618 {TAG_END, 0}};
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},
635 {TAG_END, 0}};
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},
651 {TAG_END, 0}};
653 eloop_register_timeout(NULL_INTERVAL, 0, wpa_driver_sana2_stay_alive,
654 drv->ctx, drv);
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},
668 {TAG_END, 0}};
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,
678 size_t data_len)
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)
696 return 0;
700 static int wpa_driver_sana2_mlme_remove_sta(void *priv, const u8 *addr)
702 return 0;
706 static void wpa_driver_sana2_event_handler(int sig, void *sig_ctx)
708 struct wpa_driver_sana2_data *drv = sig_ctx;
709 int i;
710 ULONG events;
711 struct IOSana2Req *request;
712 union wpa_event_data event_data;
713 struct TagItem *tag_list;
714 u8 *ie;
715 APTR pool;
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)
724 case CMD_READ:
725 if(request->ios2_Req.io_Error == 0) {
726 /* Deliver frame to supplicant */
727 drv_event_eapol_rx(drv->ctx,
728 request->ios2_SrcAddr,
729 request->ios2_Data,
730 request->ios2_DataLength);
732 if(request->ios2_Req.io_Error != S2ERR_OUTOFSERVICE) {
733 /* Send request back for next frame */
734 SendIO((APTR)request);
736 break;
738 case S2_READMGMT:
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,
747 &event_data);
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);
754 break;
756 case S2_ONEVENT:
757 events = request->ios2_WireError;
758 if (request->ios2_Req.io_Error != 0)
759 events = 0;
760 if (events & S2EVENT_CONNECT)
762 request->ios2_Req.io_Command =
763 S2_GETNETWORKINFO;
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,
772 (UPINT)NULL,
773 tag_list);
774 } else
775 ie = NULL;
776 if (ie != NULL)
777 event_data.assoc_info.req_ies_len =
778 ie[1] + 2;
779 else
780 event_data.assoc_info.req_ies_len = 0;
782 wpa_supplicant_event(drv->ctx, EVENT_ASSOC,
783 &event_data);
785 DeletePool(pool);
787 /* Start periodic sending of null-data frames */
788 eloop_register_timeout(NULL_INTERVAL, 0,
789 wpa_driver_sana2_stay_alive,
790 drv->ctx, drv);
793 if (events & S2EVENT_DISCONNECT) {
794 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC,
795 NULL);
797 /* Stop periodic sending of null-data frames */
798 eloop_cancel_timeout(
799 wpa_driver_sana2_stay_alive,
800 drv->ctx, drv);
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);
809 if(!drv->hard_mac)
810 for(i = 0; i < MLME_REQ_COUNT; i++)
811 SendIO((APTR)
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);
824 break;
826 case S2_GETNETWORKS:
827 wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS,
828 NULL);
829 break;
835 static void wpa_driver_sana2_deinit(void *priv)
837 struct wpa_driver_sana2_data *drv = priv;
838 int i;
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);
860 /* Close device */
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);
871 os_free(drv);
875 static void * wpa_driver_sana2_init(void *ctx, const char *ifname)
877 struct wpa_driver_sana2_data *drv;
878 int err = 0, i;
879 char *end, *p;
880 ULONG unit_no;
881 struct IOSana2Req *request, *eapol_request, *mlme_request;
882 struct NSDeviceQueryResult device_info =
883 {0, sizeof(struct NSDeviceQueryResult)};
885 drv = os_zalloc(sizeof(*drv));
886 if (drv == NULL)
887 return NULL;
888 drv->ctx = ctx;
889 drv->device_name = AllocVec(strlen(device_dir) + strlen(ifname),
890 MEMF_PUBLIC);
891 if(drv->device_name == NULL)
892 err = 1;
894 /* Split fake interface name into device and unit */
895 if(err == 0) {
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);
900 } else
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)
911 err = 1;
914 if(err == 0) {
915 /* Open device */
916 drv->request->ios2_BufferManagement = (APTR)buffer_tags;
917 if(OpenDevice((TEXT *)drv->device_name, unit_no,
918 (APTR)drv->request, 0) != 0)
919 err = 1;
922 /* Register a handler for the port's signal */
923 if(err == 0) {
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 */
931 if(err == 0) {
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)
936 err = 1;
937 else {
938 for(i = 0; device_info.SupportedCommands[i] != 0; i++)
939 if(device_info.SupportedCommands[i]
940 == S2_GETNETWORKS)
941 drv->hard_mac = 1;
945 /* Put device online */
946 if(err == 0) {
947 request = drv->request;
948 request->ios2_Req.io_Command = S2_GETSTATIONADDRESS;
949 if(DoIO((APTR)request) != 0)
950 err = 1;
953 if(err == 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;
962 DoIO((APTR)request);
963 } else
964 err = 1;
966 drv->online = 1;
969 /* Create and queue up EAPOL frame read request */
970 if(err == 0) {
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)
978 err = 1;
981 if(err == 0) {
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++) {
996 mlme_request =
997 AllocVec(sizeof(struct IOSana2Req) + ETH_MTU,
998 MEMF_PUBLIC | MEMF_CLEAR);
999 if(mlme_request == NULL)
1000 err = 1;
1002 if(err == 0) {
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);
1013 if(err == 0) {
1014 /* Create and send event-notification request */
1015 request = drv->request;
1016 request->ios2_Req.io_Command = S2_ONEVENT;
1017 if(drv->hard_mac)
1018 drv->event_mask = S2EVENT_CONNECT | S2EVENT_DISCONNECT
1019 | S2EVENT_OFFLINE;
1020 else
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)
1027 err = 1;
1030 if(err == 0) {
1031 CopyMem(drv->request, drv->event_request,
1032 sizeof(struct IOSana2Req));
1034 SendIO((APTR)drv->event_request);
1037 if(err != 0) {
1038 wpa_driver_sana2_deinit(drv);
1039 drv = NULL;
1042 return drv;
1046 const struct wpa_driver_ops wpa_driver_sana2_ops = {
1047 .name = "sana2",
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,