add place-holder directory for the a3000 wd533c93 scsi controller implementation.
[AROS.git] / workbench / network / WirelessManager / src / drivers / driver_sana2.c
blob3c95ed238cdc794ca80bb86d387d082fdf6afbff
1 /*
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
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);
153 DeletePool(pool);
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;
163 int err = 0;
164 struct IOSana2Req *request = drv->request;
165 const u8 *ssid;
166 size_t ssid_len;
167 TEXT *ssid_str = NULL;
168 struct TagItem *tag_list;
169 APTR pool;
171 if (drv->scanning) {
172 printf("[scan] MULTIPLE CONCURRENT SCAN REQUESTS!\n");
173 Delay(200);
174 return 1;
177 pool = CreatePool(MEMF_PUBLIC | MEMF_CLEAR, PUDDLE_SIZE, PUDDLE_SIZE);
178 if (pool == NULL)
179 err = 1;
181 if (err == 0) {
182 ssid = params->ssids[0].ssid;
183 ssid_len = params->ssids[0].ssid_len;
184 if (ssid != NULL) {
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';
189 } else
190 err = 1;
194 if (err == 0) {
195 tag_list = AllocPooled(pool, sizeof(struct TagItem) * 2);
196 if (tag_list == NULL)
197 err = 1;
200 if (err == 0) {
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);
209 drv->scanning = 1;
212 return err;
216 static struct wpa_scan_results * wpa_driver_sana2_get_scan_results(void *priv)
218 struct wpa_driver_sana2_data *drv = priv;
219 int err = 0;
220 struct IOSana2Req *request = drv->request;
221 struct wpa_scan_results *results;
222 size_t i, count;
223 struct TagItem **tag_lists, *tag;
224 TEXT *str;
225 UPINT num;
226 u8 *ie;
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) {
236 err = 1;
239 if (err == 0) {
240 results->res =
241 os_zalloc(count * sizeof(struct wpa_scan_res *));
242 if (results->res != NULL)
243 results->num = count;
244 else
245 err = 1;
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]);
252 if (data != NULL)
253 ie_len = data[0];
254 else
255 ie_len = MAX_SSID_LEN + 2;
256 res = results->res[i] =
257 os_zalloc(sizeof(struct wpa_scan_res) + ie_len);
258 if (res == NULL)
259 err = 1;
261 if (err == 0) {
262 tag = FindTagItem(S2INFO_BSSID, tag_lists[i]);
263 if (tag != NULL)
264 os_memcpy(res->bssid, (void *)tag->ti_Data,
265 ETH_ALEN);
267 num = GetTagData(S2INFO_Channel, 0, tag_lists[i]);
268 if (num == 14)
269 res->freq = 2484;
270 else if (num != 0)
271 res->freq = 2407 + num * 5;
273 res->beacon_int = GetTagData(S2INFO_BeaconInterval,
274 0, tag_lists[i]);
276 res->caps = GetTagData(S2INFO_Capabilities, 0,
277 tag_lists[i]);
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);
289 if (data != NULL) {
290 res->ie_len = ie_len;
291 os_memcpy(ie, data + 1, ie_len);
292 } else {
293 str = (TEXT *)GetTagData(S2INFO_SSID,
294 (UPINT)NULL, tag_lists[i]);
295 if (str != NULL) {
296 ssid_len = strlen((char *)str);
297 res->ie_len = ssid_len + 2;
298 ie[0] = 0;
299 ie[1] = ssid_len;
300 os_memcpy(ie + 2, str, ssid_len);
306 DeletePool(request->ios2_Data);
308 if (err != 0) {
309 wpa_scan_results_free(results);
310 results = NULL;
313 drv->scanning = 0;
314 return results;
318 static int wpa_driver_sana2_cipher(int cipher)
320 switch (cipher) {
321 case CIPHER_NONE:
322 return S2ENC_NONE;
323 case CIPHER_WEP40:
324 case CIPHER_WEP104:
325 return S2ENC_WEP;
326 case CIPHER_TKIP:
327 return S2ENC_TKIP;
328 case CIPHER_CCMP:
329 return S2ENC_CCMP;
330 default:
331 return 0;
336 static int wpa_driver_sana2_band(enum hostapd_hw_mode mode)
338 switch (mode) {
339 case HOSTAPD_MODE_IEEE80211B:
340 return S2BAND_B;
341 case HOSTAPD_MODE_IEEE80211G:
342 return S2BAND_G;
343 case HOSTAPD_MODE_IEEE80211A:
344 return S2BAND_A;
345 default:
346 return 0;
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;
356 int err = 0;
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)
368 using_wep = 1;
370 err = DoIO((APTR)request);
372 return err;
376 static int wpa_driver_sana2_associate(
377 void *priv, struct wpa_driver_associate_params *params)
379 struct wpa_driver_sana2_data *drv = priv;
380 int err = 0, i, alg;
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},
395 {TAG_END, 0}};
397 if (ssid == NULL) {
398 err = 1;
401 if (err == 0) {
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) {
407 err = 1;
411 /* Set or clear WEP keys */
412 for (i = 0; i < 4; i++) {
413 if (params->wep_key_len[i] > 0)
414 alg = WPA_ALG_WEP;
415 else
416 alg = WPA_ALG_NONE;
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 */
423 if (err == 0) {
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 */
431 if (err == 0) {
432 strcpy(drv->ssid, ssid);
435 return 0;
439 static int wpa_driver_sana2_get_capa(void *priv, struct wpa_driver_capa *capa)
441 struct wpa_driver_sana2_data *drv = priv;
442 u8 *enc_list = NULL;
443 int i;
444 struct IOSana2Req *request = drv->request;
445 APTR pool;
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]) {
457 case S2ENC_WEP:
458 capa->enc |= WPA_DRIVER_CAPA_ENC_WEP40
459 | WPA_DRIVER_CAPA_ENC_WEP104;
460 break;
461 case S2ENC_TKIP:
462 capa->enc |= WPA_DRIVER_CAPA_ENC_TKIP;
463 break;
464 case S2ENC_CCMP:
465 capa->enc |= WPA_DRIVER_CAPA_ENC_CCMP;
466 break;
469 } else
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;
474 DeletePool(pool);
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;
485 if (!drv->hard_mac)
486 capa->flags = WPA_DRIVER_FLAGS_USER_SPACE_MLME;
488 return 0;
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,
515 drv->ctx, drv);
519 static const u8 *wpa_driver_sana2_get_mac_addr(void *priv)
521 struct wpa_driver_sana2_data *drv = priv;
523 return drv->addr;
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;
533 /* IEEE 802.11b */
534 mode_count = 2;
535 channel_count = 14;
536 rate_count = 4;
538 modes = os_zalloc(sizeof(struct hostapd_hw_modes) * mode_count);
539 if (modes == NULL) {
540 err = 1;
543 if (err == 0) {
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)
550 err = 1;
553 if (err == 0) {
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;
566 if (err == 0) {
567 modes[0].num_rates = rate_count;
568 modes[0].rates = os_zalloc(rate_count * sizeof(int));
569 if (modes[0].rates == NULL)
570 err = 1;
573 if (err == 0) {
574 os_memcpy(modes[0].rates, b_rates, sizeof(b_rates));
577 /* IEEE 802.11g */
578 channel_count = 13;
579 rate_count = 12;
581 if (err == 0) {
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)
588 err = 1;
591 if (err == 0) {
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;
600 if (err == 0) {
601 modes[1].num_rates = rate_count;
602 modes[1].rates = os_zalloc(rate_count * sizeof(int));
603 if (modes[1].rates == NULL)
604 err = 1;
607 if (err == 0) {
608 os_memcpy(modes[1].rates, g_rates, sizeof(g_rates));
611 if (err != 0) {
612 os_free(modes[0].channels);
613 os_free(modes[0].rates);
614 os_free(modes[1].channels);
615 os_free(modes[1].rates);
616 modes = NULL;
619 *num_modes = mode_count;
620 *flags = 0;
621 return modes;
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},
633 {TAG_END, 0}};
635 drv->freq = freq;
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,
643 size_t ssid_len)
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},
650 {TAG_END, 0}};
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},
667 {TAG_END, 0}};
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},
683 {TAG_END, 0}};
685 eloop_register_timeout(NULL_INTERVAL, 0, wpa_driver_sana2_stay_alive,
686 drv->ctx, drv);
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},
700 {TAG_END, 0}};
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,
709 size_t data_len)
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)
727 return 0;
731 static int wpa_driver_sana2_mlme_remove_sta(void *priv, const u8 *addr)
733 return 0;
737 static void wpa_driver_sana2_event_handler(int sig, void *sig_ctx)
739 struct wpa_driver_sana2_data *drv = sig_ctx;
740 int i;
741 ULONG events;
742 struct IOSana2Req *request;
743 union wpa_event_data event_data;
744 struct TagItem *tag_list;
745 u8 *ie;
746 APTR pool;
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)
755 case CMD_READ:
756 if (request->ios2_Req.io_Error == 0) {
757 /* Deliver frame to supplicant */
758 drv_event_eapol_rx(drv->ctx,
759 request->ios2_SrcAddr,
760 request->ios2_Data,
761 request->ios2_DataLength);
763 if (request->ios2_Req.io_Error != S2ERR_OUTOFSERVICE) {
764 /* Send request back for next frame */
765 SendIO((APTR)request);
767 break;
769 case S2_READMGMT:
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,
778 &event_data);
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);
785 break;
787 case S2_ONEVENT:
788 events = request->ios2_WireError;
789 if (request->ios2_Req.io_Error != 0)
790 events = 0;
791 if (events & S2EVENT_CONNECT)
793 request->ios2_Req.io_Command =
794 S2_GETNETWORKINFO;
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,
803 (UPINT)NULL,
804 tag_list);
805 } else
806 ie = NULL;
807 if (ie != NULL)
808 event_data.assoc_info.req_ies_len =
809 ie[1] + 2;
810 else
811 event_data.assoc_info.req_ies_len = 0;
813 wpa_supplicant_event(drv->ctx, EVENT_ASSOC,
814 &event_data);
816 DeletePool(pool);
818 /* Start periodic sending of null-data frames */
819 eloop_register_timeout(NULL_INTERVAL, 0,
820 wpa_driver_sana2_stay_alive,
821 drv->ctx, drv);
824 if (events & S2EVENT_DISCONNECT) {
825 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC,
826 NULL);
828 /* Stop periodic sending of null-data frames */
829 eloop_cancel_timeout(
830 wpa_driver_sana2_stay_alive,
831 drv->ctx, drv);
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);
840 if (!drv->hard_mac)
841 for (i = 0; i < MLME_REQ_COUNT; i++)
842 SendIO((APTR)
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);
855 break;
857 case S2_GETNETWORKS:
858 wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS,
859 NULL);
860 break;
866 static void wpa_driver_sana2_deinit(void *priv)
868 struct wpa_driver_sana2_data *drv = priv;
869 int i;
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);
891 /* Close device */
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);
902 os_free(drv);
906 static void * wpa_driver_sana2_init(void *ctx, const char *ifname)
908 struct wpa_driver_sana2_data *drv;
909 int err = 0, i;
910 char *end, *p;
911 ULONG unit_no;
912 struct IOSana2Req *request, *eapol_request, *mlme_request;
913 struct NSDeviceQueryResult device_info =
914 {0, sizeof(struct NSDeviceQueryResult)};
916 drv = os_zalloc(sizeof(*drv));
917 if (drv == NULL)
918 return NULL;
919 drv->ctx = ctx;
920 drv->device_name = AllocVec(strlen(device_dir) + strlen(ifname),
921 MEMF_PUBLIC);
922 if (drv->device_name == NULL)
923 err = 1;
925 /* Split fake interface name into device and unit */
926 if (err == 0) {
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);
931 } else
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)
942 err = 1;
945 if (err == 0) {
946 /* Open device */
947 drv->request->ios2_BufferManagement = (APTR)buffer_tags;
948 if (OpenDevice((TEXT *)drv->device_name, unit_no,
949 (APTR)drv->request, 0) != 0)
950 err = 1;
953 /* Register a handler for the port's signal */
954 if (err == 0) {
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 */
962 if (err == 0) {
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)
967 err = 1;
968 else {
969 for (i = 0; device_info.SupportedCommands[i] != 0; i++)
970 if (device_info.SupportedCommands[i]
971 == S2_GETNETWORKS)
972 drv->hard_mac = 1;
976 /* Put device online */
977 if (err == 0) {
978 request = drv->request;
979 request->ios2_Req.io_Command = S2_GETSTATIONADDRESS;
980 if (DoIO((APTR)request) != 0)
981 err = 1;
984 if (err == 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;
993 DoIO((APTR)request);
994 } else
995 err = 1;
997 drv->online = 1;
1000 /* Create and queue up EAPOL frame read request */
1001 if (err == 0) {
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)
1009 err = 1;
1012 if (err == 0) {
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++) {
1027 mlme_request =
1028 AllocVec(sizeof(struct IOSana2Req) + ETH_MTU,
1029 MEMF_PUBLIC | MEMF_CLEAR);
1030 if (mlme_request == NULL)
1031 err = 1;
1033 if (err == 0) {
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);
1044 if (err == 0) {
1045 /* Create and send event-notification request */
1046 request = drv->request;
1047 request->ios2_Req.io_Command = S2_ONEVENT;
1048 if (drv->hard_mac)
1049 drv->event_mask = S2EVENT_CONNECT | S2EVENT_DISCONNECT
1050 | S2EVENT_OFFLINE;
1051 else
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)
1058 err = 1;
1061 if (err == 0) {
1062 CopyMem(drv->request, drv->event_request,
1063 sizeof(struct IOSana2Req));
1065 SendIO((APTR)drv->event_request);
1068 if (err != 0) {
1069 wpa_driver_sana2_deinit(drv);
1070 drv = NULL;
1073 return drv;
1077 const struct wpa_driver_ops wpa_driver_sana2_ops = {
1078 .name = "sana2",
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,