Your message dated Fri, 16 Nov 2018 14:57:25 -0800
with message-id <[email protected]>
and subject line Re: hostapd: no support for rtl871xdrv
has caused the Debian Bug report #825676,
regarding hostapd: no support for rtl871xdrv
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
825676: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=825676
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: hostapd
Severity: wishlist
Tags: patch upstream

Dear Maintainer,

It seems that hostapd is lacking support for rtl871xdrv (example RTL8188CUS) , 
few years ago Realtek released the code under GPLv2.

The attached patched is based on that code and it is taken from 
https://github.com/pritambaral/hostapd-rtl871xdrv.git


-- System Information:
Debian Release: stretch/sid
  APT prefers unstable
  APT policy: (901, 'unstable'), (900, 'testing'), (200, 'stable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.4.0-1-amd64 (SMP w/2 CPU cores)
Locale: LANG=he_IL.UTF-8, LC_CTYPE=he_IL.UTF-8 (charmap=locale: Cannot set 
LC_ALL to default locale: No such file or directory
UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
diff --git a/hostapd/main.c b/hostapd/main.c
index 6c7406a..07dda78 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -422,7 +422,7 @@ static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
 static void show_version(void)
 {
 	fprintf(stderr,
-		"hostapd v" VERSION_STR "\n"
+		"hostapd v" VERSION_STR " for Realtek rtl871xdrv\n"
 		"User space daemon for IEEE 802.11 AP management,\n"
 		"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
 		"Copyright (c) 2002-2015, Jouni Malinen <[email protected]> "
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 5fe8fd5..5f7c077 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -1007,6 +1007,11 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
 #ifdef CONFIG_IEEE80211N
 	tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
 	tailpos = hostapd_eid_ht_operation(hapd, tailpos);
+
+	//DRIVER_RTW ADD
+	if(hapd->iconf->ieee80211n)
+		hapd->conf->wmm_enabled = 1;
+
 #endif /* CONFIG_IEEE80211N */
 
 	tailpos = hostapd_eid_ext_capab(hapd, tailpos);
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index fc8786d..efd3841 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -494,7 +494,10 @@ static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
 		iface->num_ht40_scan_tries = 1;
 		eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL);
 		eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL);
-		return 1;
+
+		//DRIVER_RTW Modify
+		//return -1;
+		return 0;//ignore this error
 	}
 
 	if (ret < 0) {
diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c
index bab1f03..555d0d8 100644
--- a/src/drivers/driver_bsd.c
+++ b/src/drivers/driver_bsd.c
@@ -47,6 +47,12 @@
 
 #include "l2_packet/l2_packet.h"
 
+#ifdef HOSTAPD
+#ifdef CONFIG_SUPPORT_RTW_DRIVER
+#define RTW_BSD_HOSTAPD_SET_BEACON (1100)
+#endif
+#endif
+
 struct bsd_driver_data {
 	struct hostapd_data *hapd;	/* back pointer */
 
@@ -800,6 +806,296 @@ handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
 	drv_event_eapol_rx(drv->hapd, src_addr, buf, len);
 }
 
+#ifdef CONFIG_SUPPORT_RTW_DRIVER
+static int rtw_set_beacon_ops(void *priv, const u8 *head, size_t head_len,
+			  const u8 *tail, size_t tail_len, int dtim_period,
+			  int beacon_int)
+{
+	int ret=0;
+	u8 *pbuf;
+	size_t sz;
+	struct bsd_driver_data *drv = priv;
+
+	if((head_len<24) ||(!head))
+		return -1;
+
+	sz = head_len+tail_len - 24; // 24 = wlan hdr
+
+	printf("%s, beacon_sz=%d\n", __func__, sz);
+
+	pbuf = os_zalloc(sz);
+	if (pbuf == NULL) {
+		return -ENOMEM;
+	}
+
+	os_memcpy(pbuf, (head+24), (head_len-24));// 24=beacon header len.
+
+	os_memcpy(&pbuf[head_len-24], tail, tail_len);
+
+	ret = set80211var(drv, RTW_BSD_HOSTAPD_SET_BEACON, pbuf, sz);
+
+	os_free(pbuf);
+
+	return ret;
+
+}
+
+static struct hostapd_hw_modes *rtw_get_hw_feature_data_ops(
+	void *priv, u16 *num_modes, u16 *flags)
+{
+
+#define MAX_NUM_CHANNEL (14)
+#define MAX_NUM_CHANNEL_5G (24)
+
+	struct hostapd_hw_modes *modes;
+	size_t i;
+	int k;
+
+	printf("%s\n", __func__);
+
+	*num_modes = 3;
+	*flags = 0;
+
+	modes = os_zalloc(*num_modes * sizeof(struct hostapd_hw_modes));
+	if (modes == NULL)
+		return NULL;
+
+	//.1
+	modes[0].mode = HOSTAPD_MODE_IEEE80211G;
+	modes[0].num_channels = MAX_NUM_CHANNEL;
+	modes[0].num_rates = 12;
+	modes[0].channels =
+		os_zalloc(MAX_NUM_CHANNEL * sizeof(struct hostapd_channel_data));
+	modes[0].rates = os_zalloc(modes[0].num_rates * sizeof(int));
+	if (modes[0].channels == NULL || modes[0].rates == NULL)
+		goto fail;
+	for (i = 0; i < MAX_NUM_CHANNEL; i++) {
+		modes[0].channels[i].chan = i + 1;
+		modes[0].channels[i].freq = 2412 + 5 * i;
+		modes[0].channels[i].flag = 0;
+		if (i >= 13)
+			modes[0].channels[i].flag = HOSTAPD_CHAN_DISABLED;
+	}
+	modes[0].rates[0] = 10;
+	modes[0].rates[1] = 20;
+	modes[0].rates[2] = 55;
+	modes[0].rates[3] = 110;
+	modes[0].rates[4] = 60;
+	modes[0].rates[5] = 90;
+	modes[0].rates[6] = 120;
+	modes[0].rates[7] = 180;
+	modes[0].rates[8] = 240;
+	modes[0].rates[9] = 360;
+	modes[0].rates[10] = 480;
+	modes[0].rates[11] = 540;
+
+
+	//.2
+	modes[1].mode = HOSTAPD_MODE_IEEE80211B;
+	modes[1].num_channels = MAX_NUM_CHANNEL;
+	modes[1].num_rates = 4;
+	modes[1].channels =
+		os_zalloc(MAX_NUM_CHANNEL * sizeof(struct hostapd_channel_data));
+	modes[1].rates = os_zalloc(modes[1].num_rates * sizeof(int));
+	if (modes[1].channels == NULL || modes[1].rates == NULL)
+		goto fail;
+	for (i = 0; i < MAX_NUM_CHANNEL; i++) {
+		modes[1].channels[i].chan = i + 1;
+		modes[1].channels[i].freq = 2412 + 5 * i;
+		modes[1].channels[i].flag = 0;
+		if (i >= 11)
+			modes[1].channels[i].flag = HOSTAPD_CHAN_DISABLED;
+	}
+	modes[1].rates[0] = 10;
+	modes[1].rates[1] = 20;
+	modes[1].rates[2] = 55;
+	modes[1].rates[3] = 110;
+
+
+	//.3
+	modes[2].mode = HOSTAPD_MODE_IEEE80211A;
+#ifdef CONFIG_DRIVER_RTL_DFS
+	modes[2].num_channels = MAX_NUM_CHANNEL_5G;
+#else /* CONFIG_DRIVER_RTL_DFS */
+	modes[2].num_channels = 9;
+#endif /* CONFIG_DRIVER_RTL_DFS */
+
+	modes[2].num_rates = 8;
+	modes[2].channels = os_zalloc(modes[2].num_channels * sizeof(struct hostapd_channel_data));
+	modes[2].rates = os_zalloc(modes[2].num_rates * sizeof(int));
+	if (modes[2].channels == NULL || modes[2].rates == NULL)
+		goto fail;
+
+
+	k = 0;
+	// 5G band1 Channel: 36, 40, 44, 48
+	for (i=0; i < 4; i++) {
+		modes[2].channels[k].chan = 36+(i*4);
+		modes[2].channels[k].freq = 5180+(i*20);
+		modes[2].channels[k].flag = 0;
+		k++;
+	}
+
+#ifdef CONFIG_DRIVER_RTL_DFS
+	// 5G band2 Channel: 52, 56, 60, 64
+	for (i=0; i < 4; i++) {
+		modes[2].channels[k].chan = 52+(i*4);
+		modes[2].channels[k].freq = 5260+(i*20);
+		modes[2].channels[k].flag = 0;
+		k++;
+	}
+
+	// 5G band3 Channel: 100, 104, 108. 112, 116, 120, 124, 128, 132, 136, 140
+	for (i=0; i < 11; i++) {
+		modes[2].channels[k].chan = 100+(i*4);
+		modes[2].channels[k].freq = 5500+(i*20);
+		modes[2].channels[k].flag = 0;
+		k++;
+	}
+#endif /* CONFIG_DRIVER_RTL_DFS */
+
+	// 5G band4 Channel: 149, 153, 157, 161, 165
+	for (i=0; i < 5; i++) {
+		modes[2].channels[k].chan = 149+(i*4);
+		modes[2].channels[k].freq = 5745+(i*20);
+		modes[2].channels[k].flag = 0;
+		k++;
+	}
+
+	modes[2].rates[0] = 60;
+	modes[2].rates[1] = 90;
+	modes[2].rates[2] = 120;
+	modes[2].rates[3] = 180;
+	modes[2].rates[4] = 240;
+	modes[2].rates[5] = 360;
+	modes[2].rates[6] = 480;
+	modes[2].rates[7] = 540;
+
+
+	//
+#if 0
+#define HT_CAP_INFO_LDPC_CODING_CAP		((u16) BIT(0))
+#define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET	((u16) BIT(1))
+#define HT_CAP_INFO_SMPS_MASK			((u16) (BIT(2) | BIT(3)))
+#define HT_CAP_INFO_SMPS_STATIC			((u16) 0)
+#define HT_CAP_INFO_SMPS_DYNAMIC		((u16) BIT(2))
+#define HT_CAP_INFO_SMPS_DISABLED		((u16) (BIT(2) | BIT(3)))
+#define HT_CAP_INFO_GREEN_FIELD			((u16) BIT(4))
+#define HT_CAP_INFO_SHORT_GI20MHZ		((u16) BIT(5))
+#define HT_CAP_INFO_SHORT_GI40MHZ		((u16) BIT(6))
+#define HT_CAP_INFO_TX_STBC			((u16) BIT(7))
+#define HT_CAP_INFO_RX_STBC_MASK		((u16) (BIT(8) | BIT(9)))
+#define HT_CAP_INFO_RX_STBC_1			((u16) BIT(8))
+#define HT_CAP_INFO_RX_STBC_12			((u16) BIT(9))
+#define HT_CAP_INFO_RX_STBC_123			((u16) (BIT(8) | BIT(9)))
+#define HT_CAP_INFO_DELAYED_BA			((u16) BIT(10))
+#define HT_CAP_INFO_MAX_AMSDU_SIZE		((u16) BIT(11))
+#define HT_CAP_INFO_DSSS_CCK40MHZ		((u16) BIT(12))
+#define HT_CAP_INFO_PSMP_SUPP			((u16) BIT(13))
+#define HT_CAP_INFO_40MHZ_INTOLERANT		((u16) BIT(14))
+#define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT	((u16) BIT(15))
+#endif
+
+	//HOSTAPD_MODE_IEEE80211G
+	modes[0].ht_capab = HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET|HT_CAP_INFO_SHORT_GI20MHZ|
+			HT_CAP_INFO_SHORT_GI40MHZ|HT_CAP_INFO_MAX_AMSDU_SIZE|HT_CAP_INFO_DSSS_CCK40MHZ;
+
+	modes[0].mcs_set[0]= 0xff;
+	modes[0].mcs_set[1]= 0xff;
+
+	//HOSTAPD_MODE_IEEE80211B
+	modes[1].ht_capab = 0;
+
+	//HOSTAPD_MODE_IEEE80211A
+	modes[2].ht_capab = modes[0].ht_capab;
+
+	modes[2].mcs_set[0]= 0xff;
+	modes[2].mcs_set[1]= 0xff;
+
+	return modes;
+
+fail:
+	if (modes) {
+		for (i = 0; i < *num_modes; i++) {
+			os_free(modes[i].channels);
+			os_free(modes[i].rates);
+		}
+		os_free(modes);
+	}
+
+	return NULL;
+
+}
+
+#if 0
+#define 	IEEE80211_FC0_TYPE_MASK   0x0c
+#define 	IEEE80211_FC0_TYPE_SHIFT   2
+#define 	IEEE80211_FC0_TYPE_MGT   0x00
+#define 	IEEE80211_FC0_TYPE_CTL   0x04
+#define 	IEEE80211_FC0_TYPE_DATA   0x08
+#define 	IEEE80211_FC0_SUBTYPE_MASK   0xf0
+#define 	IEEE80211_FC0_SUBTYPE_SHIFT   4
+#define 	IEEE80211_FC0_SUBTYPE_ASSOC_REQ   0x00
+#define 	IEEE80211_FC0_SUBTYPE_ASSOC_RESP   0x10
+#define 	IEEE80211_FC0_SUBTYPE_REASSOC_REQ   0x20
+#define 	IEEE80211_FC0_SUBTYPE_REASSOC_RESP   0x30
+#define 	IEEE80211_FC0_SUBTYPE_PROBE_REQ   0x40
+#define 	IEEE80211_FC0_SUBTYPE_PROBE_RESP   0x50
+#define 	IEEE80211_FC0_SUBTYPE_BEACON   0x80
+#define 	IEEE80211_FC0_SUBTYPE_ATIM   0x90
+#define 	IEEE80211_FC0_SUBTYPE_DISASSOC   0xa0
+#define 	IEEE80211_FC0_SUBTYPE_AUTH   0xb0
+#define 	IEEE80211_FC0_SUBTYPE_DEAUTH   0xc0
+#define 	IEEE80211_FC0_SUBTYPE_ACTION   0xd0
+#define 	IEEE80211_FC0_SUBTYPE_ACTION_NOACK   0xe0
+
+#define IEEE80211_APPIE_WPA (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_BEACON | \
+         IEEE80211_FC0_SUBTYPE_PROBE_RESP)
+
+#endif
+
+#define RTW_IEEE80211_APPIE_BEACON (IEEE80211_FC0_TYPE_MGT|IEEE80211_FC0_SUBTYPE_BEACON)
+#define RTW_IEEE80211_APPIE_PROBE_RESP (IEEE80211_FC0_TYPE_MGT|IEEE80211_FC0_SUBTYPE_PROBE_RESP)
+#define RTW_IEEE80211_APPIE_ASSOC_RESP (IEEE80211_FC0_TYPE_MGT|IEEE80211_FC0_SUBTYPE_ASSOC_RESP)
+
+
+static int rtw_set_wps_assoc_resp_ie(void *priv, const void *ie, size_t len)
+{
+	return bsd_set80211(priv, IEEE80211_IOC_APPIE, RTW_IEEE80211_APPIE_ASSOC_RESP,
+			    ie, len);
+}
+
+static int rtw_set_wps_beacon_ie(void *priv, const void *ie, size_t len)
+{
+	return bsd_set80211(priv, IEEE80211_IOC_APPIE, RTW_IEEE80211_APPIE_BEACON,
+			    ie, len);	
+}
+
+static int rtw_set_wps_probe_resp_ie(void *priv, const void *ie, size_t len)
+{
+	return bsd_set80211(priv, IEEE80211_IOC_APPIE, RTW_IEEE80211_APPIE_PROBE_RESP,
+			    ie, len);	
+}
+
+static int rtw_set_ap_wps_ie_ops(void *priv, const struct wpabuf *beacon,
+		      const struct wpabuf *proberesp, const struct wpabuf *assocresp)
+{
+	if (rtw_set_wps_assoc_resp_ie(priv, assocresp ? wpabuf_head(assocresp) : NULL,
+			       assocresp ? wpabuf_len(assocresp) : 0))
+		return -1;
+
+	if (rtw_set_wps_beacon_ie(priv, beacon ? wpabuf_head(beacon) : NULL,
+			       beacon ? wpabuf_len(beacon) : 0))
+		return -1;
+
+	return rtw_set_wps_probe_resp_ie(priv,
+				  proberesp ? wpabuf_head(proberesp) : NULL,
+				  proberesp ? wpabuf_len(proberesp): 0);
+
+}
+#endif
+
+
 static void *
 bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
 {
@@ -854,6 +1150,12 @@ bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
 		goto bad;
 	}
 
+#ifdef CONFIG_SUPPORT_RTW_DRIVER
+	/* mark up after init */
+	if (bsd_ctrl_iface(drv, 1) < 0)
+		goto bad;
+#endif
+
 	return drv;
 bad:
 	if (drv->sock_xmit != NULL)
@@ -1292,6 +1594,15 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
 				   event.interface_status.ifname);
 			wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
 		}
+		else{
+			os_strlcpy(event.interface_status.ifname, drv->ifname,
+				   sizeof(event.interface_status.ifname));
+			event.interface_status.ievent = EVENT_INTERFACE_ADDED;
+			wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' UP",
+				   event.interface_status.ifname);
+			wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
+		}
+
 		break;
 	}
 }
@@ -1609,7 +1920,52 @@ wpa_driver_bsd_get_capa(void *priv, struct wpa_driver_capa *capa)
 }
 #endif /* HOSTAPD */
 
-
+#ifdef CONFIG_SUPPORT_RTW_DRIVER
+const struct wpa_driver_ops wpa_driver_bsd_ops = {
+	.name			= "bsd",
+	.desc			= "BSD 802.11 support",
+#ifdef HOSTAPD
+	.hapd_init		= bsd_init,
+	.hapd_deinit		= bsd_deinit,
+	.set_privacy		= bsd_set_privacy,//del ?
+	.get_seqnum		= bsd_get_seqnum,//del ?
+	.flush			= bsd_flush,
+	.read_sta_data	= bsd_read_sta_driver_data,//del ?
+	.sta_disassoc		= bsd_sta_disassoc,
+	.sta_deauth		= bsd_sta_deauth,
+	.get_hw_feature_data = rtw_get_hw_feature_data_ops,//add
+	//.sta_remove = rtl871x_sta_remove_ops,//add
+	.set_beacon = rtw_set_beacon_ops,	//add
+	.set_ap_wps_ie = rtw_set_ap_wps_ie_ops,//add
+#else /* HOSTAPD */
+	.init			= wpa_driver_bsd_init,
+	.deinit			= wpa_driver_bsd_deinit,
+	.get_bssid		= wpa_driver_bsd_get_bssid,
+	.get_ssid		= wpa_driver_bsd_get_ssid,
+	.set_countermeasures	= wpa_driver_bsd_set_countermeasures,
+	.scan2			= wpa_driver_bsd_scan,
+	.get_scan_results2	= wpa_driver_bsd_get_scan_results2,
+	.deauthenticate		= wpa_driver_bsd_deauthenticate,
+	.disassociate		= wpa_driver_bsd_disassociate,
+	.associate		= wpa_driver_bsd_associate,
+	.get_capa		= wpa_driver_bsd_get_capa,
+	.set_freq		= bsd_set_freq, //only for wpa_supplicant
+	.set_ieee8021x		= bsd_set_ieee8021x,//only for wpa_supplicant
+	.hapd_set_ssid		= bsd_set_ssid,//only for wpa_supplicant
+	.hapd_get_ssid		= bsd_get_ssid,//only for wpa_supplicant
+	.sta_set_flags		= bsd_set_sta_authorized, //only for wpa_supplicant
+	.set_generic_elem	= bsd_set_opt_ie, //only for wpa_supplicant
+#endif /* HOSTAPD */
+	//.set_freq		= bsd_set_freq, //only for wpa_supplicant
+	.set_key		= bsd_set_key,
+	//.set_ieee8021x		= bsd_set_ieee8021x, //only for wpa_supplicant
+	//.hapd_set_ssid		= bsd_set_ssid, //only for wpa_supplicant
+	//.hapd_get_ssid		= bsd_get_ssid, //only for wpa_supplicant
+	.hapd_send_eapol	= bsd_send_eapol, //only for wpa_supplicant
+	//.sta_set_flags		= bsd_set_sta_authorized, //only for wpa_supplicant
+	//.set_generic_elem	= bsd_set_opt_ie, //only for wpa_supplicant
+};
+#else
 const struct wpa_driver_ops wpa_driver_bsd_ops = {
 	.name			= "bsd",
 	.desc			= "BSD 802.11 support",
@@ -1644,3 +2000,4 @@ const struct wpa_driver_ops wpa_driver_bsd_ops = {
 	.hapd_send_eapol	= bsd_send_eapol,
 	.set_generic_elem	= bsd_set_opt_ie,
 };
+#endif
diff --git a/src/drivers/driver_rtl.h b/src/drivers/driver_rtl.h
new file mode 100644
index 0000000..c5ee335
--- /dev/null
+++ b/src/drivers/driver_rtl.h
@@ -0,0 +1,114 @@
+
+#ifndef _DRIVER_RTL_H_
+#define _DRIVER_RTL_H_
+
+
+#define RTL_IOCTL_HOSTAPD (SIOCIWFIRSTPRIV + 28)
+
+#define	IEEE_CRYPT_ALG_NAME_LEN (16)
+
+/* RTL871X_IOCTL_HOSTAPD ioctl() cmd: */
+enum {
+	RTL871X_HOSTAPD_FLUSH = 1,
+	RTL871X_HOSTAPD_ADD_STA = 2,
+	RTL871X_HOSTAPD_REMOVE_STA = 3,
+	RTL871X_HOSTAPD_GET_INFO_STA = 4,
+	/* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */
+	RTL871X_HOSTAPD_GET_WPAIE_STA = 5,
+	RTL871X_SET_ENCRYPTION = 6,
+	RTL871X_GET_ENCRYPTION = 7,
+	RTL871X_HOSTAPD_SET_FLAGS_STA = 8,
+	RTL871X_HOSTAPD_GET_RID = 9,
+	RTL871X_HOSTAPD_SET_RID = 10,
+	RTL871X_HOSTAPD_SET_ASSOC_AP_ADDR = 11,
+	RTL871X_HOSTAPD_SET_GENERIC_ELEMENT = 12,
+	RTL871X_HOSTAPD_MLME = 13,
+	RTL871X_HOSTAPD_SCAN_REQ = 14,
+	RTL871X_HOSTAPD_STA_CLEAR_STATS = 15,
+	RTL871X_HOSTAPD_SET_BEACON = 16,
+	RTL871X_HOSTAPD_SET_WPS_BEACON = 17,
+	RTL871X_HOSTAPD_SET_WPS_PROBE_RESP = 18,
+	RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP = 19,
+	RTL871X_HOSTAPD_SET_HIDDEN_SSID = 20,
+};
+
+typedef struct ieee_param {
+	u32 cmd;
+	u8 sta_addr[ETH_ALEN];
+       union {
+		struct {
+			u8 name;
+			u32 value;
+		} wpa_param;
+		struct {
+			u32 len;
+			u8 reserved[32];
+			u8 data[0];
+		} wpa_ie;
+	        struct{
+			int command;
+    			int reason_code;
+		} mlme;
+		struct {
+			u8 alg[IEEE_CRYPT_ALG_NAME_LEN];
+			u8 set_tx;
+			u32 err;
+			u8 idx;
+			u8 seq[8]; /* sequence counter (set: RX, get: TX) */
+			u16 key_len;
+			u8 key[0];
+		} crypt;
+		struct {
+			u16 aid;
+			u16 capability;
+			int flags;
+			u8 tx_supp_rates[16];			
+			//struct ieee80211_ht_capability ht_cap;
+			struct ieee80211_ht_capabilities ht_cap;
+		} add_sta;
+		struct {
+			u8	reserved[2];//for set max_num_sta
+			u8	buf[0];
+		} bcn_ie;
+
+	} u;
+	   
+} ieee_param;
+	   
+
+
+#define IEEE80211_CCK_RATE_LEN  		4
+#define IEEE80211_OFDM_RATE_LEN 		8
+
+#define IEEE80211_CCK_RATE_1MB		        0x02
+#define IEEE80211_CCK_RATE_2MB		        0x04
+#define IEEE80211_CCK_RATE_5MB		        0x0B
+#define IEEE80211_CCK_RATE_11MB		        0x16
+#define IEEE80211_OFDM_RATE_6MB		        0x0C
+#define IEEE80211_OFDM_RATE_9MB		        0x12
+#define IEEE80211_OFDM_RATE_12MB		0x18
+#define IEEE80211_OFDM_RATE_18MB		0x24
+#define IEEE80211_OFDM_RATE_24MB		0x30
+#define IEEE80211_OFDM_RATE_36MB		0x48
+#define IEEE80211_OFDM_RATE_48MB		0x60
+#define IEEE80211_OFDM_RATE_54MB		0x6C
+#define IEEE80211_BASIC_RATE_MASK		0x80
+
+#define IEEE80211_CCK_RATE_1MB_MASK		(1<<0)
+#define IEEE80211_CCK_RATE_2MB_MASK		(1<<1)
+#define IEEE80211_CCK_RATE_5MB_MASK		(1<<2)
+#define IEEE80211_CCK_RATE_11MB_MASK		(1<<3)
+#define IEEE80211_OFDM_RATE_6MB_MASK		(1<<4)
+#define IEEE80211_OFDM_RATE_9MB_MASK		(1<<5)
+#define IEEE80211_OFDM_RATE_12MB_MASK		(1<<6)
+#define IEEE80211_OFDM_RATE_18MB_MASK		(1<<7)
+#define IEEE80211_OFDM_RATE_24MB_MASK		(1<<8)
+#define IEEE80211_OFDM_RATE_36MB_MASK		(1<<9)
+#define IEEE80211_OFDM_RATE_48MB_MASK		(1<<10)
+#define IEEE80211_OFDM_RATE_54MB_MASK		(1<<11)
+
+#define IEEE80211_CCK_RATES_MASK	        0x0000000F
+#define IEEE80211_OFDM_RATES_MASK		0x00000FF0
+
+#endif
+
diff --git a/src/drivers/driver_rtw.c b/src/drivers/driver_rtw.c
new file mode 100644
index 0000000..cbee5d2
--- /dev/null
+++ b/src/drivers/driver_rtw.c
@@ -0,0 +1,1993 @@
+/*
+ * hostapd / Driver interface for rtl871x driver
+ * Copyright (c) 2010,
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+//#define CONFIG_MGNT_L2SOCK 1
+#define CONFIG_MLME_OFFLOAD 1
+
+
+#include "includes.h"
+#include <net/if.h>
+#include <sys/ioctl.h>
+
+#include "common.h"
+
+/*#include "wireless_copy.h"*/
+#include "linux_wext.h"
+
+#include "driver.h"
+#include "eloop.h"
+#include "priv_netlink.h"
+#include "l2_packet/l2_packet.h"
+#include "common/ieee802_11_defs.h"
+#include "netlink.h"
+#include "linux_ioctl.h"
+
+//#include "../src/ap/hostapd.h"
+//#include "../src/ap/ap_config.h"
+#include "ap/hostapd.h"
+#include "ap/ap_config.h"
+
+#ifdef USE_KERNEL_HEADERS
+/* compat-wireless does not include linux/compiler.h to define __user, so
+ * define it here */
+#ifndef __user
+#define __user
+#endif /* __user */
+#include <asm/types.h>
+#include <linux/if_packet.h>
+#include <linux/if_ether.h>   /* The L2 protocols */
+#include <linux/if_arp.h>
+#include <linux/wireless.h>
+#else /* USE_KERNEL_HEADERS */
+#include <net/if_arp.h>
+#include <netpacket/packet.h>
+//#include "wireless_copy.h"
+#endif /* USE_KERNEL_HEADERS */
+
+//#include <net/if.h>
+
+
+#ifndef ETH_P_80211_RAW
+#define ETH_P_80211_RAW 0x0019
+#endif
+
+#if 0
+#include "hostapd.h"
+#include "driver.h"
+#include "ieee802_1x.h"
+#include "eloop.h"
+#include "priv_netlink.h"
+#include "sta_info.h"
+#include "l2_packet/l2_packet.h"
+
+#include "wpa.h"
+#include "accounting.h"
+#include "ieee802_11.h"
+#include "hw_features.h"
+#include "radius/radius.h"
+#endif
+
+#include "driver_rtl.h"
+
+
+//static int rtl871x_sta_remove_ops(void *priv, const u8 *addr);
+
+struct rtl871x_driver_data {
+	struct hostapd_data *hapd;
+	
+	char	iface[IFNAMSIZ + 1];
+	int     ifindex;
+	struct l2_packet_data *l2_sock;/* socket for sending eapol frames*/
+	struct l2_packet_data *l2_sock_recv;/* raw packet recv socket from bridge interface*/
+#ifdef CONFIG_MGNT_L2SOCK	
+	struct l2_packet_data *mgnt_l2_sock; /* socket for tx/rx management frames*/
+#else
+	int	mgnt_sock;/* socket for tx/rx management frames*/
+#endif
+	int	ioctl_sock;			/* socket for ioctl() use */
+	int	wext_sock;			/* socket for wireless events */
+
+	struct netlink_data *netlink;
+	
+	int	we_version;
+
+	u8	hw_mac[ETH_ALEN];
+	
+	u8	acct_mac[ETH_ALEN];
+	
+	struct hostap_sta_driver_data acct_data;
+	
+};
+
+/*
+static const char *ether_sprintf(const u8 *addr)
+{
+	static char buf[sizeof(MACSTR)];
+
+	if (addr != NULL)
+		snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
+	else
+		snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0);
+	
+	return buf;
+}
+*/
+
+#ifndef CONFIG_MLME_OFFLOAD
+static int rtl871x_set_iface_flags(void *priv, int dev_up)
+{
+	struct rtl871x_driver_data *drv = priv;
+	struct ifreq ifr;
+
+	wpa_printf(MSG_DEBUG, "%s: dev_up=%d", __func__, dev_up);
+
+	if (drv->mgnt_sock < 0)
+		return -1;
+
+	memset(&ifr, 0, sizeof(ifr));
+	//os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ);
+	//os_strlcpy(ifr.ifr_name, "mgnt.wlan", IFNAMSIZ);
+	snprintf(ifr.ifr_name, IFNAMSIZ, "mgnt.%s", "wlan0");
+
+	if (ioctl(drv->mgnt_sock, SIOCGIFFLAGS, &ifr) != 0) {
+		perror("ioctl[SIOCGIFFLAGS]");
+		return -1;
+	}
+
+	if (dev_up)
+		ifr.ifr_flags |= IFF_UP;
+	else
+		ifr.ifr_flags &= ~IFF_UP;
+
+	if (ioctl(drv->mgnt_sock, SIOCSIFFLAGS, &ifr) != 0) {
+		perror("ioctl[SIOCSIFFLAGS]");
+		return -1;
+	}
+
+#if 0
+	if (dev_up) {
+		memset(&ifr, 0, sizeof(ifr));
+		os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ);
+		ifr.ifr_mtu = HOSTAPD_MTU;
+		if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) {
+			perror("ioctl[SIOCSIFMTU]");
+			printf("Setting MTU failed - trying to survive with "
+			       "current value\n");
+		}
+	}
+#endif
+
+	return 0;
+}
+#endif
+
+static int rtl871x_hostapd_ioctl(struct rtl871x_driver_data *drv, ieee_param *param, int len)
+{	
+	struct iwreq iwr;
+
+	memset(&iwr, 0, sizeof(iwr));
+	os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
+	iwr.u.data.pointer = (caddr_t) param;
+	iwr.u.data.length = len;
+
+	if (ioctl(drv->ioctl_sock, RTL_IOCTL_HOSTAPD, &iwr) < 0) {
+		perror("ioctl[RTL_IOCTL_HOSTAPD]");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int rtl871x_set_mode(struct rtl871x_driver_data *drv, u32 mode)
+{
+	struct iwreq iwr;
+
+	if (drv->ioctl_sock < 0)
+		return -1;
+	
+	memset(&iwr, 0, sizeof(iwr));
+
+	os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
+
+	//iwr.u.mode = IW_MODE_MASTER;
+	iwr.u.mode = mode;
+	
+	if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) {
+		perror("ioctl[SIOCSIWMODE]");
+		printf("Could not set interface to mode(%d)!\n", mode);
+		return -1;
+	}
+
+	return 0;
+	
+}
+
+/*
+static int rtl871x_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
+			       const u8 *ie, size_t ielen)
+{
+	struct sta_info *sta;
+	int new_assoc, res;
+
+	//hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
+	//	       HOSTAPD_LEVEL_INFO, "associated");
+
+	sta = ap_get_sta(hapd, addr);
+	if (sta) {
+		accounting_sta_stop(hapd, sta);
+	} else {
+		sta = ap_sta_add(hapd, addr);
+		if (sta == NULL)
+		{
+			rtl871x_sta_remove_ops(hapd->drv_priv, addr);		
+			return -1;
+		}	
+	}
+	sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
+
+	if (hapd->conf->wpa) {
+		if (ie == NULL || ielen == 0) {
+			if (hapd->conf->wps_state) {
+				wpa_printf(MSG_DEBUG, "STA did not include "
+					   "WPA/RSN IE in (Re)Association "
+					   "Request - possible WPS use");
+				sta->flags |= WLAN_STA_MAYBE_WPS;
+				goto skip_wpa_check;
+			}
+
+			wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
+			return -1;
+		}
+		if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
+		    os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
+			sta->flags |= WLAN_STA_WPS;
+			goto skip_wpa_check;
+		}
+
+		if (sta->wpa_sm == NULL)
+			sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
+							sta->addr);
+		if (sta->wpa_sm == NULL) {
+			wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
+				   "machine");
+			return -1;
+		}
+		res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
+					  ie, ielen, NULL, 0);
+		if (res != WPA_IE_OK) {
+			wpa_printf(MSG_DEBUG, "WPA/RSN information element "
+				   "rejected? (res %u)", res);
+			wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
+			return -1;
+		}
+	} else if (hapd->conf->wps_state) {
+		if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 &&
+		    os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
+			sta->flags |= WLAN_STA_WPS;
+		} else
+			sta->flags |= WLAN_STA_MAYBE_WPS;
+	}
+skip_wpa_check:
+
+	new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
+	sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
+	wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
+
+	hostapd_new_assoc_sta(hapd, sta, !new_assoc);
+
+	ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
+
+	return 0;
+}
+*/
+
+static int rtl871x_get_sta_wpaie(struct rtl871x_driver_data *drv, u8 *iebuf, u8 *addr)
+{	
+	struct ieee_param param;
+
+	printf("+%s, " MACSTR " is sta's address\n", __func__, MAC2STR(addr));
+
+	memset(&param, 0, sizeof(param));
+
+	param.cmd = RTL871X_HOSTAPD_GET_WPAIE_STA;
+	
+	memcpy(param.sta_addr, addr, ETH_ALEN);
+	
+	if (rtl871x_hostapd_ioctl(drv, &param, sizeof(param))) {
+		printf("Could not get sta wpaie from kernel driver.\n");
+		return -1;
+	}
+
+
+	if(param.u.wpa_ie.len > 32)
+		return -1;
+
+	memcpy(iebuf, param.u.wpa_ie.reserved, param.u.wpa_ie.len);
+	
+	return 0;	
+
+}
+
+static int rtl871x_del_sta(struct rtl871x_driver_data *drv, u8 *addr)
+{
+	struct hostapd_data *hapd = drv->hapd;
+	
+#if 1
+
+	//union wpa_event_data event;
+	//os_memset(&event, 0, sizeof(event));
+	//event.disassoc_info.addr = addr;
+	//wpa_supplicant_event(hapd, EVENT_DISASSOC, &event);
+
+	drv_event_disassoc(hapd, addr);
+	
+#else
+
+	struct sta_info *sta;
+
+	//hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
+	//	       HOSTAPD_LEVEL_INFO, "disassociated");
+
+	sta = ap_get_sta(hapd, addr);
+	if (sta != NULL) 
+	{
+		sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
+		wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
+		sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
+		ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
+		ap_free_sta(hapd, sta);
+	}
+	else
+	{
+		wpa_printf(MSG_DEBUG, "Disassociation notification for "
+			   "unknown STA " MACSTR, MAC2STR(addr));
+	}
+#endif
+
+	return 0;
+	
+}
+
+static int rtl871x_new_sta(struct rtl871x_driver_data *drv, u8 *addr)
+{
+	struct hostapd_data *hapd = drv->hapd;
+	//struct ieee80211req_wpaie ie;
+	int ielen = 0, res=0;
+	//u8 *iebuf = NULL;
+	u8 iebuf[32], *piebuf=NULL;
+
+	/*
+	 * Fetch negotiated WPA/RSN parameters from the driver.
+	 */
+	//memset(&ie, 0, sizeof(ie));
+	//memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN);
+	memset(iebuf, 0 , sizeof(iebuf));
+	if (rtl871x_get_sta_wpaie(drv, iebuf, addr)) {
+	//if (set80211priv(drv, IEEE80211_IOCTL_GETWPAIE, &ie, sizeof(ie))) {
+		
+		wpa_printf(MSG_DEBUG, "%s: Failed to get WPA/RSN IE: %s",
+			   __func__, strerror(errno));
+		goto no_ie;
+	}
+	
+	//wpa_hexdump(MSG_MSGDUMP, "req WPA IE",
+	//	    ie.wpa_ie, IEEE80211_MAX_OPT_IE);
+	
+	//wpa_hexdump(MSG_MSGDUMP, "req RSN IE",
+	//	    ie.rsn_ie, IEEE80211_MAX_OPT_IE);
+	
+	//iebuf = ie.wpa_ie;
+	
+/*	
+	if (iebuf[0] != WLAN_EID_VENDOR_SPECIFIC)
+		iebuf[1] = 0;
+	if (iebuf[1] == 0 && ie.rsn_ie[1] > 0) {
+		iebuf = ie.rsn_ie;
+		if (iebuf[0] != WLAN_EID_RSN)
+			iebuf[1] = 0;
+	}
+*/
+
+	if ((iebuf[0] == WLAN_EID_VENDOR_SPECIFIC) || (iebuf[0] == WLAN_EID_RSN) )
+	{
+		piebuf = iebuf;
+		ielen = iebuf[1];
+		
+		if (ielen == 0)
+			piebuf = NULL;
+		else
+			ielen += 2;	
+	}
+
+no_ie:
+	
+	//res = rtl871x_notif_assoc(hapd, addr, piebuf, ielen);
+	//drv_event_assoc(hapd, addr, piebuf, ielen);
+	drv_event_assoc(hapd, addr, piebuf, ielen, 0);
+
+	if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) {
+		/* Cached accounting data is not valid anymore. */
+		memset(drv->acct_mac, 0, ETH_ALEN);
+		memset(&drv->acct_data, 0, sizeof(drv->acct_data));
+	}
+
+	return res;
+	
+}
+
+static void rtl871x_wireless_event_wireless(struct rtl871x_driver_data *drv,
+					    char *data, int len)
+{
+	struct iw_event iwe_buf, *iwe = &iwe_buf;
+	char *pos, *end, *custom, *buf;
+
+	pos = data;
+	end = data + len;
+
+	while (pos + IW_EV_LCP_LEN <= end) {
+		/* Event data may be unaligned, so make a local, aligned copy
+		 * before processing. */
+		memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
+		wpa_printf(MSG_MSGDUMP, "Wireless event: cmd=0x%x len=%d",
+			   iwe->cmd, iwe->len);
+		if (iwe->len <= IW_EV_LCP_LEN)
+			return;
+
+		custom = pos + IW_EV_POINT_LEN;
+		if (drv->we_version > 18 &&
+		    (iwe->cmd == IWEVMICHAELMICFAILURE ||
+		     iwe->cmd == IWEVCUSTOM)) {
+			/* WE-19 removed the pointer from struct iw_point */
+			char *dpos = (char *) &iwe_buf.u.data.length;
+			int dlen = dpos - (char *) &iwe_buf;
+			memcpy(dpos, pos + IW_EV_LCP_LEN,
+			       sizeof(struct iw_event) - dlen);
+		} else {
+			memcpy(&iwe_buf, pos, sizeof(struct iw_event));
+			custom += IW_EV_POINT_OFF;
+		}
+
+		//printf("got wireless event, iwe->cmd=%d\n", iwe->cmd);
+
+		switch (iwe->cmd) {
+		case IWEVEXPIRED:
+			rtl871x_del_sta(drv, (u8 *)iwe->u.addr.sa_data);
+			break;
+		case IWEVREGISTERED:
+			if(rtl871x_new_sta(drv, (u8 *)iwe->u.addr.sa_data))
+			{
+				printf("Failed to add new sta: "MACSTR" \n", MAC2STR((u8 *)iwe->u.addr.sa_data));
+			}
+			break;
+		case IWEVCUSTOM:
+			if (custom + iwe->u.data.length > end)
+				return;
+			buf = malloc(iwe->u.data.length + 1);
+			if (buf == NULL)
+				return;		/* XXX */
+			memcpy(buf, custom, iwe->u.data.length);
+			buf[iwe->u.data.length] = '\0';
+			//madwifi_wireless_event_wireless_custom(drv, buf);			
+			free(buf);
+			break;
+		}
+
+		pos += iwe->len;
+	}
+	
+}
+
+#if 1
+static void rtl871x_wireless_event_rtm_newlink(void *ctx,
+				   struct ifinfomsg *ifi, u8 *buf, size_t len)
+{
+	struct rtl871x_driver_data *drv = ctx;
+	int attrlen, rta_len;
+	struct rtattr *attr;
+
+	if (ifi->ifi_index != drv->ifindex)
+		return;
+
+	attrlen = len;
+	attr = (struct rtattr *) buf;
+
+	rta_len = RTA_ALIGN(sizeof(struct rtattr));
+	while (RTA_OK(attr, attrlen)) {
+		if (attr->rta_type == IFLA_WIRELESS) {
+			rtl871x_wireless_event_wireless(
+				drv, ((char *) attr) + rta_len,
+				attr->rta_len - rta_len);
+		}
+		attr = RTA_NEXT(attr, attrlen);
+	}
+}
+
+#else
+static void rtl871x_wireless_event_rtm_newlink(struct rtl871x_driver_data *drv,
+					       struct nlmsghdr *h, int len)
+{
+	struct ifinfomsg *ifi;
+	int attrlen, nlmsg_len, rta_len;
+	struct rtattr * attr;
+
+	if (len < (int) sizeof(*ifi))
+		return;
+
+	ifi = NLMSG_DATA(h);
+
+	if (ifi->ifi_index != drv->ifindex)
+		return;
+
+	nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
+
+	attrlen = h->nlmsg_len - nlmsg_len;
+	if (attrlen < 0)
+		return;
+
+	attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
+
+	rta_len = RTA_ALIGN(sizeof(struct rtattr));
+	while (RTA_OK(attr, attrlen)) {
+		if (attr->rta_type == IFLA_WIRELESS) {
+			rtl871x_wireless_event_wireless(
+				drv, ((char *) attr) + rta_len,
+				attr->rta_len - rta_len);
+		}
+		attr = RTA_NEXT(attr, attrlen);
+	}
+}
+#endif
+
+/*
+static void rtl871x_wireless_event_receive(int sock, void *eloop_ctx, void *sock_ctx)
+{
+	char buf[256];//!!!
+	int left;
+	struct sockaddr_nl from;
+	socklen_t fromlen;
+	struct nlmsghdr *h;
+	struct rtl871x_driver_data *drv = eloop_ctx;
+
+	//printf("+rtl871x_wireless_event_receive\n");
+
+	fromlen = sizeof(from);
+	left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
+			(struct sockaddr *) &from, &fromlen);
+	if (left < 0) {
+		if (errno != EINTR && errno != EAGAIN)
+			perror("recvfrom(netlink)");
+		return;
+	}
+
+	h = (struct nlmsghdr *)buf;
+	while (left >= (int) sizeof(*h)) {
+		int len, plen;
+
+		len = h->nlmsg_len;
+		plen = len - sizeof(*h);//payload len
+		if (len > left || plen < 0) {
+			printf("Malformed netlink message: "
+			       "len=%d left=%d plen=%d\n",
+			       len, left, plen);
+			break;
+		}
+
+		switch (h->nlmsg_type) {
+		case RTM_NEWLINK:
+			rtl871x_wireless_event_rtm_newlink(drv, h, plen);
+			break;
+		}
+
+		len = NLMSG_ALIGN(len);
+		left -= len;
+		h = (struct nlmsghdr *) ((char *) h + len);
+	}
+
+	if (left > 0) {
+		printf("%d extra bytes in the end of netlink message\n", left);
+	}
+	
+}
+*/
+
+static int rtl871x_wireless_event_init(struct rtl871x_driver_data *drv)
+{
+	struct netlink_config *cfg;
+
+	//madwifi_get_we_version(drv);
+
+	cfg = os_zalloc(sizeof(*cfg));
+	if (cfg == NULL)
+		return -1;
+	cfg->ctx = drv;
+	cfg->newlink_cb = rtl871x_wireless_event_rtm_newlink;
+	drv->netlink = netlink_init(cfg);
+	if (drv->netlink == NULL) {
+		os_free(cfg);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+static int rtl871x_wireless_event_init_ops(void *priv)
+{
+	int s;
+	struct sockaddr_nl local;
+	struct rtl871x_driver_data *drv = priv;
+	
+	//madwifi_get_we_version(drv);
+
+	drv->wext_sock = -1;
+
+	s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+	if (s < 0) {
+		perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
+		return -1;
+	}
+
+	memset(&local, 0, sizeof(local));
+	local.nl_family = AF_NETLINK;
+	local.nl_groups = RTMGRP_LINK;
+	if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
+		perror("bind(netlink)");
+		close(s);
+		return -1;
+	}
+
+	eloop_register_read_sock(s, rtl871x_wireless_event_receive, drv, NULL);
+	drv->wext_sock = s;
+
+	return 0;
+	
+}
+
+static void rtl871x_wireless_event_deinit_ops(void *priv)
+{
+	struct rtl871x_driver_data *drv = priv;
+
+	if (drv != NULL) {
+		if (drv->wext_sock < 0)
+			return;
+		eloop_unregister_read_sock(drv->wext_sock);
+		close(drv->wext_sock);
+	}
+}
+*/
+
+#if 1
+static void rtl871x_handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
+{
+	struct rtl871x_driver_data *drv = ctx;
+	drv_event_eapol_rx(drv->hapd, src_addr, buf + sizeof(struct l2_ethhdr),
+			   len - sizeof(struct l2_ethhdr));
+}
+#else
+static void rtl871x_handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
+{
+	struct rtl871x_driver_data *drv = ctx;
+	struct hostapd_data *hapd = drv->hapd;
+	struct sta_info *sta;
+
+	sta = ap_get_sta(hapd, src_addr);
+	if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
+		printf("Data frame from not associated STA %s\n",
+		       ether_sprintf(src_addr));
+		/* XXX cannot happen */
+		return;
+	}
+	ieee802_1x_receive(hapd, src_addr, buf + sizeof(struct l2_ethhdr),
+			   len - sizeof(struct l2_ethhdr));
+}
+#endif
+
+static int rtl871x_send_eapol_ops(void *priv, const u8 *addr, const u8 *data, size_t data_len,
+		   int encrypt, const u8 *own_addr, u32 flags)
+{
+	struct rtl871x_driver_data *drv = priv;
+	unsigned char buf[3000];
+	unsigned char *bp = buf;
+	struct l2_ethhdr *eth;
+	size_t len;
+	int status;
+
+	printf("+rtl871x_send_eapol\n");
+
+	/*
+	 * Prepend the Ethernet header.  If the caller left us
+	 * space at the front we could just insert it but since
+	 * we don't know we copy to a local buffer.  Given the frequency
+	 * and size of frames this probably doesn't matter.
+	 */
+	len = data_len + sizeof(struct l2_ethhdr);
+	if (len > sizeof(buf)) {
+		bp = malloc(len);
+		if (bp == NULL) {
+			printf("EAPOL frame discarded, cannot malloc temp "
+			       "buffer of size %lu!\n", (unsigned long) len);
+			return -1;
+		}
+	}
+	
+	eth = (struct l2_ethhdr *) bp;
+	memcpy(eth->h_dest, addr, ETH_ALEN);
+	memcpy(eth->h_source, own_addr, ETH_ALEN);
+	eth->h_proto = htons(ETH_P_EAPOL);
+	memcpy(eth+1, data, data_len);
+
+	wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len);
+
+	status = l2_packet_send(drv->l2_sock, addr, ETH_P_EAPOL, bp, len);
+
+	if (bp != buf)
+		free(bp);
+	
+	return status;
+	
+}
+
+#ifndef CONFIG_MLME_OFFLOAD
+static void rtl871x_receive_mgnt(struct rtl871x_driver_data *drv , const u8 *buf, size_t len)
+{
+	const struct ieee80211_mgmt *mgmt;
+	//const u8 *end, *ie;
+	u16 fc, type, stype;
+	//size_t ie_len;
+	struct hostapd_data *hapd = drv->hapd;
+
+	//printf("+rtl871x_receive_mgnt, " MACSTR " is our address\n", MAC2STR(hapd->own_addr));
+
+	
+#if 0
+	{
+		int i;
+		for(i=0; i<len; i+=8)
+		{
+			printf("%x:%x:%x:%x:%x:%x:%x:%x\n", buf[i], buf[i+1], buf[i+2], buf[i+3], buf[i+4], buf[i+5], buf[i+6], buf[i+7]);
+		}	
+
+	}
+#endif
+
+	if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
+		return;
+
+	mgmt = (const struct ieee80211_mgmt *)buf;
+
+	fc = le_to_host16(mgmt->frame_control);
+	type = WLAN_FC_GET_TYPE(fc);
+	stype = WLAN_FC_GET_STYPE(fc);
+
+#if 1
+	if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
+	    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP)
+	{
+		//printf("MGNT Frame - PROBE_RESP Frame\n");
+	}
+#endif
+
+	//end = buf + len;
+	//ie = mgmt->u.probe_req.variable;
+	//ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
+	//hostapd_wps_probe_req_rx(drv->hapd, mgmt->sa, ie, ie_len);
+
+	switch (type) {
+	case WLAN_FC_TYPE_MGMT:
+		if (stype != WLAN_FC_STYPE_BEACON)
+			wpa_printf(MSG_MSGDUMP, "MGMT");
+
+		
+
+		if (stype == WLAN_FC_STYPE_PROBE_REQ)
+		{
+		
+		}
+		else
+		{
+			//printf("rtl871x_receive_mgnt, type=0x%x, stype=0x%x\n", type, stype);
+		}
+
+
+		//ieee802_11_mgmt(hapd, (u8 *)buf, len, stype, NULL);
+		
+		break;
+	case WLAN_FC_TYPE_CTRL:
+		printf("rtl871x_receive_mgnt, CTRL\n");
+		break;
+	case WLAN_FC_TYPE_DATA:
+		printf("rtl871x_receive_mgnt, DATA\n");
+		//handle_data(hapd, buf, data_len, stype);
+		break;
+	default:
+		printf("unknown frame type %d\n", type);
+		break;
+	}
+
+	
+}
+
+#ifdef CONFIG_MGNT_L2SOCK
+static void rtl871x_recvive_mgmt_frame(void *ctx, const u8 *src_addr, const u8 *buf,
+				size_t len)
+{
+	struct rtl871x_driver_data *drv = ctx;
+
+	rtl871x_receive_mgnt(drv, buf, len);
+}
+#else
+static void rtl871x_recvive_mgmt_frame(int sock, void *eloop_ctx, void *sock_ctx)
+{
+#if 0
+	int len;
+	unsigned char buf[1024];
+	struct hostapd_data *hapd = (struct hostapd_data *)eloop_ctx;
+	struct rtl871x_driver_data *drv = (struct rtl871x_driver_data *)hapd->drv_priv;
+
+	len = recv(sock, buf, sizeof(buf), 0);
+	if (len < 0) {
+		perror("recv");
+		return;
+	}
+	
+	rtl871x_receive_mgnt(drv, buf, len);
+#endif
+}
+
+static int rtl871x_mgnt_sock_init(struct rtl871x_driver_data *drv, const char *name)
+{
+	int sock;
+	struct ifreq ifr;
+	struct sockaddr_ll addr;
+
+	sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+	if (sock < 0) {
+		perror("socket[PF_PACKET,SOCK_RAW]");
+		return -1;
+	}
+
+	if (eloop_register_read_sock(sock, rtl871x_recvive_mgmt_frame, drv->hapd, NULL))
+	{
+		printf("Could not register read socket\n");
+		return -1;
+	}
+
+	memset(&ifr, 0, sizeof(ifr));
+	//snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%sap", drv->iface);
+	os_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+        if (ioctl(sock, SIOCGIFINDEX, &ifr) != 0) {
+		perror("ioctl(SIOCGIFINDEX)");
+		return -1;
+        }
+
+	//if (rtl871x_set_iface_flags(drv, 1)) {
+	//	return -1;
+	//}
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sll_family = AF_PACKET;
+	addr.sll_ifindex = ifr.ifr_ifindex;
+	wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
+		   addr.sll_ifindex);
+
+	if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		perror("bind");
+		return -1;
+	}
+
+        memset(&ifr, 0, sizeof(ifr));
+        os_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+        if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0) {
+		perror("ioctl(SIOCGIFHWADDR)");
+		return -1;
+        }
+
+
+	if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
+		printf("Invalid HW-addr family 0x%04x\n",
+		       ifr.ifr_hwaddr.sa_family);
+		return -1;
+	}
+	
+	//memcpy(drv->hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+
+	return sock;
+	
+}
+#endif
+#endif
+
+static void rtl871x_handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len,
+			       int ok)
+{
+#if 0
+	struct ieee80211_hdr *hdr;
+	u16 fc, type, stype;
+	struct sta_info *sta;
+
+	//printf("%s\n", __func__);
+
+	hdr = (struct ieee80211_hdr *) buf;
+	fc = le_to_host16(hdr->frame_control);
+
+	type = WLAN_FC_GET_TYPE(fc);
+	stype = WLAN_FC_GET_STYPE(fc);
+
+	switch (type) {
+	case WLAN_FC_TYPE_MGMT:
+		//printf("MGMT (TX callback) %s\n",
+		//	   ok ? "ACK" : "fail");
+		ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
+		break;
+	case WLAN_FC_TYPE_CTRL:
+		printf("CTRL (TX callback) %s\n",
+			   ok ? "ACK" : "fail");
+		break;
+	case WLAN_FC_TYPE_DATA:
+		printf("DATA (TX callback) %s\n",
+			   ok ? "ACK" : "fail");
+		sta = ap_get_sta(hapd, hdr->addr1);
+		if (sta && sta->flags & WLAN_STA_PENDING_POLL) {
+			wpa_printf(MSG_DEBUG, "STA " MACSTR
+				   " %s pending activity poll",
+				   MAC2STR(sta->addr),
+				   ok ? "ACKed" : "did not ACK");
+			if (ok)
+				sta->flags &= ~WLAN_STA_PENDING_POLL;
+		}
+		if (sta)
+			ieee802_1x_tx_status(hapd, sta, buf, len, ok);
+		break;
+	default:
+		printf("unknown TX callback frame type %d\n", type);
+		break;
+	}
+#endif	
+}	
+
+static int rtl871x_send_mgnt(struct rtl871x_driver_data *drv, const void *msg, size_t len)
+{
+	int res=0;
+
+	return res;
+}
+
+static int rtl871x_send_mgmt_frame_ops(void *priv, const void *msg, size_t len,
+				  int flags)
+{
+	struct rtl871x_driver_data *drv = priv;
+	//struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msg;
+	int res=0;
+
+	//printf("%s\n", __func__);
+
+	
+	//hdr->frame_control |= host_to_le16(BIT(1));/* Request TX callback */
+#ifdef CONFIG_MGNT_L2SOCK
+	//res = send(drv->mgnt_l2_sock, msg, len, flags);
+	//res = l2_packet_send(drv->mgnt_l2_sock, addr, ETH_P_EAPOL, msg, len);
+	if(drv->mgnt_l2_sock == NULL)
+		return res;
+		
+	res = l2_packet_send(drv->mgnt_l2_sock, NULL, ETH_P_80211_RAW, msg, len);
+#else
+
+	if(drv->mgnt_sock < 0)
+		return res;
+
+	res = send(drv->mgnt_sock, msg, len, flags);
+#endif
+	//hdr->frame_control &= ~host_to_le16(BIT(1));
+	
+
+	rtl871x_send_mgnt(drv, msg, len);
+
+	rtl871x_handle_tx_callback(drv->hapd, (u8*)msg, len, 1);
+
+	return res;
+	
+}
+
+/*
+static int rtl871x_driver_send_ether_ops(void *priv, const u8 *dst, const u8 *src,
+				  u16 proto, const u8 *data, size_t data_len)
+{
+	return 0;
+}
+*/
+
+static struct hostapd_hw_modes *rtl871x_get_hw_feature_data_ops(void *priv,
+							    u16 *num_modes,
+							    u16 *flags)
+{
+
+#define MAX_NUM_CHANNEL (14)
+#define MAX_NUM_CHANNEL_5G (24)
+
+	struct hostapd_hw_modes *modes;
+	size_t i;
+        int k;
+
+	*num_modes = 3;
+	*flags = 0;
+	
+	modes = os_zalloc(*num_modes * sizeof(struct hostapd_hw_modes));
+	if (modes == NULL)
+		return NULL;
+
+	//.1
+	modes[0].mode = HOSTAPD_MODE_IEEE80211G;
+	modes[0].num_channels = MAX_NUM_CHANNEL;
+	modes[0].num_rates = 12;
+	modes[0].channels =
+		os_zalloc(MAX_NUM_CHANNEL * sizeof(struct hostapd_channel_data));
+	modes[0].rates = os_zalloc(modes[0].num_rates * sizeof(int));
+	if (modes[0].channels == NULL || modes[0].rates == NULL)
+		goto fail;
+	for (i = 0; i < MAX_NUM_CHANNEL; i++) {
+		modes[0].channels[i].chan = i + 1;
+		modes[0].channels[i].freq = 2412 + 5 * i;
+		modes[0].channels[i].flag = 0;
+		if (i >= 13)
+			modes[0].channels[i].flag = HOSTAPD_CHAN_DISABLED;
+	}
+	modes[0].rates[0] = 10;
+	modes[0].rates[1] = 20;
+	modes[0].rates[2] = 55;
+	modes[0].rates[3] = 110;
+	modes[0].rates[4] = 60;
+	modes[0].rates[5] = 90;
+	modes[0].rates[6] = 120;
+	modes[0].rates[7] = 180;
+	modes[0].rates[8] = 240;
+	modes[0].rates[9] = 360;
+	modes[0].rates[10] = 480;
+	modes[0].rates[11] = 540;
+
+
+	//.2
+	modes[1].mode = HOSTAPD_MODE_IEEE80211B;
+	modes[1].num_channels = MAX_NUM_CHANNEL;
+	modes[1].num_rates = 4;
+	modes[1].channels =
+		os_zalloc(MAX_NUM_CHANNEL * sizeof(struct hostapd_channel_data));
+	modes[1].rates = os_zalloc(modes[1].num_rates * sizeof(int));
+	if (modes[1].channels == NULL || modes[1].rates == NULL)
+		goto fail;
+	for (i = 0; i < MAX_NUM_CHANNEL; i++) {
+		modes[1].channels[i].chan = i + 1;
+		modes[1].channels[i].freq = 2412 + 5 * i;
+		modes[1].channels[i].flag = 0;
+		if (i >= 11)
+			modes[1].channels[i].flag = HOSTAPD_CHAN_DISABLED;
+	}
+	modes[1].rates[0] = 10;
+	modes[1].rates[1] = 20;
+	modes[1].rates[2] = 55;
+	modes[1].rates[3] = 110;
+
+
+	//.3
+	modes[2].mode = HOSTAPD_MODE_IEEE80211A;
+#ifdef CONFIG_DRIVER_RTL_DFS
+	modes[2].num_channels = MAX_NUM_CHANNEL_5G;
+#else /* CONFIG_DRIVER_RTL_DFS */
+	modes[2].num_channels = 9;
+#endif /* CONFIG_DRIVER_RTL_DFS */	
+	
+	modes[2].num_rates = 8;
+	modes[2].channels = os_zalloc(modes[2].num_channels * sizeof(struct hostapd_channel_data));
+	modes[2].rates = os_zalloc(modes[2].num_rates * sizeof(int));
+	if (modes[2].channels == NULL || modes[2].rates == NULL)
+		goto fail;
+
+
+	k = 0;
+	// 5G band1 Channel: 36, 40, 44, 48
+	for (i=0; i < 4; i++) {
+		modes[2].channels[k].chan = 36+(i*4);
+		modes[2].channels[k].freq = 5180+(i*20);
+		modes[2].channels[k].flag = 0;
+		k++;
+	}
+
+#ifdef CONFIG_DRIVER_RTL_DFS
+	// 5G band2 Channel: 52, 56, 60, 64
+	for (i=0; i < 4; i++) {
+		modes[2].channels[k].chan = 52+(i*4);
+		modes[2].channels[k].freq = 5260+(i*20);
+		modes[2].channels[k].flag = 0;
+		k++;
+	}
+
+	// 5G band3 Channel: 100, 104, 108. 112, 116, 120, 124, 128, 132, 136, 140
+	for (i=0; i < 11; i++) {
+		modes[2].channels[k].chan = 100+(i*4);
+		modes[2].channels[k].freq = 5500+(i*20);
+		modes[2].channels[k].flag = 0;
+		k++;
+	}
+#endif /* CONFIG_DRIVER_RTL_DFS */
+
+	// 5G band4 Channel: 149, 153, 157, 161, 165
+	for (i=0; i < 5; i++) {
+		modes[2].channels[k].chan = 149+(i*4);
+		modes[2].channels[k].freq = 5745+(i*20);
+		modes[2].channels[k].flag = 0;
+		k++;
+	}
+	
+	modes[2].rates[0] = 60;
+	modes[2].rates[1] = 90;
+	modes[2].rates[2] = 120;
+	modes[2].rates[3] = 180;
+	modes[2].rates[4] = 240;
+	modes[2].rates[5] = 360;
+	modes[2].rates[6] = 480;
+	modes[2].rates[7] = 540;
+
+	
+	//
+#if 0	
+#define HT_CAP_INFO_LDPC_CODING_CAP		((u16) BIT(0))
+#define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET	((u16) BIT(1))
+#define HT_CAP_INFO_SMPS_MASK			((u16) (BIT(2) | BIT(3)))
+#define HT_CAP_INFO_SMPS_STATIC			((u16) 0)
+#define HT_CAP_INFO_SMPS_DYNAMIC		((u16) BIT(2))
+#define HT_CAP_INFO_SMPS_DISABLED		((u16) (BIT(2) | BIT(3)))
+#define HT_CAP_INFO_GREEN_FIELD			((u16) BIT(4))
+#define HT_CAP_INFO_SHORT_GI20MHZ		((u16) BIT(5))
+#define HT_CAP_INFO_SHORT_GI40MHZ		((u16) BIT(6))
+#define HT_CAP_INFO_TX_STBC			((u16) BIT(7))
+#define HT_CAP_INFO_RX_STBC_MASK		((u16) (BIT(8) | BIT(9)))
+#define HT_CAP_INFO_RX_STBC_1			((u16) BIT(8))
+#define HT_CAP_INFO_RX_STBC_12			((u16) BIT(9))
+#define HT_CAP_INFO_RX_STBC_123			((u16) (BIT(8) | BIT(9)))
+#define HT_CAP_INFO_DELAYED_BA			((u16) BIT(10))
+#define HT_CAP_INFO_MAX_AMSDU_SIZE		((u16) BIT(11))
+#define HT_CAP_INFO_DSSS_CCK40MHZ		((u16) BIT(12))
+#define HT_CAP_INFO_PSMP_SUPP			((u16) BIT(13))
+#define HT_CAP_INFO_40MHZ_INTOLERANT		((u16) BIT(14))
+#define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT	((u16) BIT(15))
+#endif
+
+	//HOSTAPD_MODE_IEEE80211G
+	modes[0].ht_capab = HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET|HT_CAP_INFO_SHORT_GI20MHZ|
+			HT_CAP_INFO_SHORT_GI40MHZ|HT_CAP_INFO_MAX_AMSDU_SIZE|HT_CAP_INFO_DSSS_CCK40MHZ;
+	
+	modes[0].mcs_set[0]= 0xff;
+	modes[0].mcs_set[1]= 0xff;
+		
+	//HOSTAPD_MODE_IEEE80211B
+	modes[1].ht_capab = 0;
+	
+	//HOSTAPD_MODE_IEEE80211A
+	modes[2].ht_capab = modes[0].ht_capab;
+	
+	modes[2].mcs_set[0]= 0xff;
+	modes[2].mcs_set[1]= 0xff;
+	
+	return modes;
+
+fail:
+	if (modes) {
+		for (i = 0; i < *num_modes; i++) {
+			os_free(modes[i].channels);
+			os_free(modes[i].rates);
+		}
+		os_free(modes);
+	}
+	
+	return NULL;	
+	
+}
+
+#if 0
+static int rtl871x_sta_add_ops(const char *ifname, void *priv, const u8 *addr,
+			  u16 aid, u16 capability, u8 *supp_rates,
+			  size_t supp_rates_len, int flags,
+			  u16 listen_interval)
+{
+
+#if 1
+	printf("+%s, " MACSTR " is new sta address added\n", __func__, MAC2STR(addr));
+	return 0;
+#else	
+	struct hostap_driver_data *drv = priv;
+	struct prism2_hostapd_param param;
+	int tx_supp_rates = 0;
+	size_t i;
+
+#define WLAN_RATE_1M BIT(0)
+#define WLAN_RATE_2M BIT(1)
+#define WLAN_RATE_5M5 BIT(2)
+#define WLAN_RATE_11M BIT(3)
+
+	for (i = 0; i < supp_rates_len; i++) {
+		if ((supp_rates[i] & 0x7f) == 2)
+			tx_supp_rates |= WLAN_RATE_1M;
+		if ((supp_rates[i] & 0x7f) == 4)
+			tx_supp_rates |= WLAN_RATE_2M;
+		if ((supp_rates[i] & 0x7f) == 11)
+			tx_supp_rates |= WLAN_RATE_5M5;
+		if ((supp_rates[i] & 0x7f) == 22)
+			tx_supp_rates |= WLAN_RATE_11M;
+	}
+
+	memset(&param, 0, sizeof(param));
+	param.cmd = PRISM2_HOSTAPD_ADD_STA;
+	memcpy(param.sta_addr, addr, ETH_ALEN);
+	param.u.add_sta.aid = aid;
+	param.u.add_sta.capability = capability;
+	param.u.add_sta.tx_supp_rates = tx_supp_rates;
+	return hostapd_ioctl(drv, &param, sizeof(param));
+#endif	
+}
+
+static int rtl871x_sta_add2_ops(const char *ifname, void *priv,
+			 struct hostapd_sta_add_params *params)
+{
+#if 0
+	ieee_param param;
+	//int i, tx_supp_rates = 0;
+	struct rtl871x_driver_data *drv = priv;
+	
+	printf("%s\n", __func__);
+
+	memset(&param, 0, sizeof(param));
+	param.cmd = RTL871X_HOSTAPD_ADD_STA;
+	memcpy(param.sta_addr, params->addr, ETH_ALEN);
+	param.u.add_sta.aid = params->aid;
+	param.u.add_sta.capability = params->capability;
+	param.u.add_sta.flags = params->flags;
+
+	memcpy(param.u.add_sta.tx_supp_rates, params->supp_rates, params->supp_rates_len);
+
+/*	
+	for (i = 0; i < params->supp_rates_len; i++)
+	{		
+		if ((params->supp_rates[i] & 0x7f) == IEEE80211_CCK_RATE_1MB)
+			tx_supp_rates |= IEEE80211_CCK_RATE_1MB_MASK;
+		if ((params->supp_rates[i] & 0x7f) == IEEE80211_CCK_RATE_2MB)
+			tx_supp_rates |= IEEE80211_CCK_RATE_2MB_MASK;
+		if ((params->supp_rates[i] & 0x7f) == IEEE80211_CCK_RATE_5MB)
+			tx_supp_rates |= IEEE80211_CCK_RATE_5MB_MASK;
+		if ((params->supp_rates[i] & 0x7f) == IEEE80211_CCK_RATE_11MB)
+			tx_supp_rates |= IEEE80211_CCK_RATE_11MB_MASK;
+
+		if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_6MB)
+			tx_supp_rates |= IEEE80211_OFDM_RATE_6MB_MASK;
+		if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_9MB)
+			tx_supp_rates |= IEEE80211_OFDM_RATE_9MB_MASK;
+		if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_12MB)
+			tx_supp_rates |= IEEE80211_OFDM_RATE_12MB_MASK;
+		if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_18MB)
+			tx_supp_rates |= IEEE80211_OFDM_RATE_18MB_MASK;
+
+		if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_24MB)
+			tx_supp_rates |= IEEE80211_OFDM_RATE_24MB_MASK;
+		if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_36MB)
+			tx_supp_rates |= IEEE80211_OFDM_RATE_36MB_MASK;
+		if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_48MB)
+			tx_supp_rates |= IEEE80211_OFDM_RATE_48MB_MASK;
+		if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_54MB)
+			tx_supp_rates |= IEEE80211_OFDM_RATE_54MB_MASK;
+		
+	}
+
+	param.u.add_sta.tx_supp_rates = tx_supp_rates;
+*/	
+	
+#ifdef CONFIG_IEEE80211N
+	if (params->ht_capabilities && params->ht_capabilities->length>0) 
+	{
+		struct ieee80211_ht_capability *pht_cap = (struct ieee80211_ht_capability *)&params->ht_capabilities->data;
+		memcpy((u8*)&param.u.add_sta.ht_cap, (u8*)pht_cap, sizeof(struct ieee80211_ht_capability));
+		
+	}
+#endif /* CONFIG_IEEE80211N */
+	
+	return rtl871x_hostapd_ioctl(drv, &param, sizeof(param));
+#else
+	return 0;
+#endif
+}
+#endif
+
+static int rtl871x_sta_remove_ops(void *priv, const u8 *addr)
+{
+	struct rtl871x_driver_data *drv = priv;
+	struct ieee_param param;
+
+	printf("+%s, " MACSTR " is sta address removed\n", __func__, MAC2STR(addr));
+
+	//hostap_sta_set_flags(drv, addr, 0, 0, ~WLAN_STA_AUTHORIZED);
+
+	memset(&param, 0, sizeof(param));
+	param.cmd = RTL871X_HOSTAPD_REMOVE_STA;
+	memcpy(param.sta_addr, addr, ETH_ALEN);
+	if (rtl871x_hostapd_ioctl(drv, &param, sizeof(param))) {
+		printf("Could not remove station from kernel driver.\n");
+		return -1;
+	}
+	
+	return 0;	
+
+}
+
+#define RTL871X_HIDDEN_SSID_SUPPORT
+#ifdef RTL871X_HIDDEN_SSID_SUPPORT
+static int rtl871x_set_hidden_ssid_ops(const char *iface, void *priv, u8 value)
+{
+	int ret;
+	ieee_param pparam;	
+	struct rtl871x_driver_data *drv = priv;
+	struct hostapd_data *hapd = drv->hapd;
+
+	printf("%s\n", __func__);
+
+	pparam.cmd = RTL871X_HOSTAPD_SET_HIDDEN_SSID;
+	pparam.u.wpa_param.name = 0;
+	pparam.u.wpa_param.value = value;
+
+	ret = rtl871x_hostapd_ioctl(drv, &pparam, sizeof(ieee_param));
+
+	return ret;	
+}
+
+static const u8 * get_ie(u8 *ies, size_t ies_len, u8 id)
+{
+	const u8 *end, *pos;
+
+	pos = ies;
+	end = pos + ies_len;
+
+	while (pos + 1 < end) {
+		if (pos + 2 + pos[1] > end)
+			break;
+
+		//printf("id:%u, clen:%u\n", pos[0], pos[1]);
+		
+		if (pos[0] == id)
+			return pos;
+		pos += 2 + pos[1];
+	}
+
+	return NULL;
+}
+#endif //RTL871X_HIDDEN_SSID_SUPPORT
+
+static int rtl871x_set_beacon_ops(void *priv, struct wpa_driver_ap_params *params)
+{
+	int ret;
+	size_t sz;
+	ieee_param *pparam;
+	struct rtl871x_driver_data *drv = priv;
+	struct hostapd_data *hapd = drv->hapd;
+
+	u8 *ssid_ie;
+	u8 ssid_len;
+	u8 expend_len = 0;
+	
+	if((params->head_len<24) ||(!params->head))
+		return -1;
+
+	printf("%s\n", __func__);
+
+
+#ifdef RTL871X_HIDDEN_SSID_SUPPORT
+	rtl871x_set_hidden_ssid_ops(drv->iface, priv, hapd->conf->ignore_broadcast_ssid);
+
+	ssid_ie = get_ie((params->head+24+12), (params->head_len-24-12), WLAN_EID_SSID);
+	
+	if(hapd->conf->ignore_broadcast_ssid == 2)
+	{
+		ssid_len = ssid_ie[1];
+		
+		//confirm the ssid_len
+		if(ssid_len != hapd->conf->ssid.ssid_len) 
+		{
+			printf("%s ssid_len(%u) != hapd->conf->ssid.ssid_len(%u)!!\n", __func__
+				, ssid_len, hapd->conf->ssid.ssid_len
+			);
+		}
+
+		memcpy(ssid_ie+2, hapd->conf->ssid.ssid, ssid_len);
+	}
+	else if(hapd->conf->ignore_broadcast_ssid == 1)
+	{
+		expend_len = hapd->conf->ssid.ssid_len;
+		printf("%s ignore_broadcast_ssid:%d, %s,%d, expend_len:%u\n", __func__
+			, hapd->conf->ignore_broadcast_ssid
+			, hapd->conf->ssid.ssid
+			, hapd->conf->ssid.ssid_len
+			, expend_len
+		);		
+	}
+#endif //RTL871X_HIDDEN_SSID_SUPPORT
+
+	sz = params->head_len+params->tail_len+12-24 + 2 + expend_len;// 12+2 = cmd+sta_addr+reserved, sizeof(ieee_param)=64, no packed
+	pparam = os_zalloc(sz);
+	if (pparam == NULL) {
+		return -ENOMEM;
+	}
+
+	pparam->cmd = RTL871X_HOSTAPD_SET_BEACON;
+
+	memcpy(pparam->u.bcn_ie.reserved, &hapd->conf->max_num_sta, 2);//for set max_num_sta
+
+#ifdef RTL871X_HIDDEN_SSID_SUPPORT
+	if(hapd->conf->ignore_broadcast_ssid == 1)
+	{
+		u8 *ssid_ie_next = params->head+24+12+2;
+		size_t head_remain_len = params->head_len-24-12-2;
+
+		memcpy(pparam->u.bcn_ie.buf, (params->head+24), 12); 
+		
+		pparam->u.bcn_ie.buf[12] = WLAN_EID_SSID;
+		pparam->u.bcn_ie.buf[13] = expend_len;
+		memcpy(pparam->u.bcn_ie.buf+12+2, hapd->conf->ssid.ssid, expend_len);
+		
+		memcpy(pparam->u.bcn_ie.buf+12+2+expend_len, ssid_ie_next, head_remain_len);// 24=beacon header len.	
+		memcpy(&pparam->u.bcn_ie.buf[params->head_len-24+expend_len], params->tail, params->tail_len);
+	}
+	else
+#endif //RTL871X_HIDDEN_SSID_SUPPORT
+	{
+		memcpy(pparam->u.bcn_ie.buf, (params->head+24), (params->head_len-24));// 24=beacon header len.
+		memcpy(&pparam->u.bcn_ie.buf[params->head_len-24], params->tail, params->tail_len);
+	}
+	
+	ret = rtl871x_hostapd_ioctl(drv, pparam, sz);
+
+	os_free(pparam);
+
+	//rtl871x_set_max_num_sta(drv);
+	
+	return ret;
+	
+}
+
+/*
+enum wpa_alg {
+	WPA_ALG_NONE,
+	WPA_ALG_WEP,
+	WPA_ALG_TKIP,
+	WPA_ALG_CCMP,
+	WPA_ALG_IGTK,
+	WPA_ALG_PMK
+};
+*/
+static int rtl871x_set_key_ops(const char *ifname, void *priv, enum wpa_alg alg,
+		const u8 *addr, int idx, int txkey, const u8 *seq,
+		size_t seq_len, const u8 *key, size_t key_len)
+{
+	ieee_param *param;	
+	u8 *buf;
+	char *alg_str;
+	size_t blen;
+	int ret = 0;
+	struct rtl871x_driver_data *drv = priv;
+
+	printf("%s\n", __func__);
+
+	blen = sizeof(*param) + key_len;
+	buf = os_zalloc(blen);
+	if (buf == NULL)
+		return -1;
+
+	param = (ieee_param *)buf;
+	param->cmd = RTL871X_SET_ENCRYPTION;
+	if (addr == NULL)
+		memset(param->sta_addr, 0xff, ETH_ALEN);
+	else
+		memcpy(param->sta_addr, addr, ETH_ALEN);
+
+
+	switch (alg) {
+	case WPA_ALG_NONE:
+		alg_str = "none";
+		break;
+	case WPA_ALG_WEP:
+		//cipher = IEEE80211_CIPHER_WEP;
+		alg_str = "WEP";
+		break;
+	case WPA_ALG_TKIP:
+		//cipher = IEEE80211_CIPHER_TKIP;
+		alg_str = "TKIP";
+		break;
+	case WPA_ALG_CCMP:
+		//cipher = IEEE80211_CIPHER_AES_CCM;
+		alg_str = "CCMP";
+		break;
+	default:
+		printf("%s: unknown/unsupported algorithm %d\n",
+			__func__, alg);
+		return -1;
+	}	
+	
+	os_strlcpy((char *) param->u.crypt.alg, alg_str,
+		   IEEE_CRYPT_ALG_NAME_LEN);
+	
+	//param->u.crypt.flags = txkey ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
+	param->u.crypt.set_tx = txkey ? 1 : 0;
+	param->u.crypt.idx = idx;
+	param->u.crypt.key_len = key_len;
+	
+	//memcpy((u8 *) (param + 1), key, key_len);
+	memcpy(param->u.crypt.key, key, key_len);
+
+	if (rtl871x_hostapd_ioctl(drv, param, blen)) {
+		printf("Failed to set encryption.\n");
+		ret = -1;
+	}
+	
+	os_free(buf);
+
+	return ret;
+
+}
+
+/*
+static int rtl871x_set_encryption_ops(const char *ifname, void *priv,
+				 const char *alg, const u8 *addr,
+				 int idx, const u8 *key, size_t key_len,
+				 int txkey)
+{
+	ieee_param *param;	
+	u8 *buf;
+	size_t blen;
+	int ret = 0;
+	struct rtl871x_driver_data *drv = priv;
+
+	printf("%s\n", __func__);
+#if 0
+	blen = sizeof(*param) + key_len;
+	buf = os_zalloc(blen);
+	if (buf == NULL)
+		return -1;
+
+	param = (ieee_param *)buf;
+	param->cmd = RTL871X_SET_ENCRYPTION;
+	if (addr == NULL)
+		memset(param->sta_addr, 0xff, ETH_ALEN);
+	else
+		memcpy(param->sta_addr, addr, ETH_ALEN);
+	
+	os_strlcpy((char *) param->u.crypt.alg, alg,
+		   IEEE_CRYPT_ALG_NAME_LEN);
+	
+	//param->u.crypt.flags = txkey ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
+	param->u.crypt.set_tx = txkey ? 1 : 0;
+	param->u.crypt.idx = idx;
+	param->u.crypt.key_len = key_len;
+	
+	//memcpy((u8 *) (param + 1), key, key_len);
+	memcpy(param->u.crypt.key, key, key_len);
+
+	if (rtl871x_hostapd_ioctl(drv, param, blen)) {
+		printf("Failed to set encryption.\n");
+		ret = -1;
+	}
+	
+	os_free(buf);
+#endif
+	return ret;
+	
+}
+*/
+
+//static int rtl871x_sta_deauth_ops(void *priv, const u8 *addr, int reason)
+static int rtl871x_sta_deauth_ops(void *priv, const u8 *own_addr, const u8 *addr,
+		   int reason)
+{
+	printf("+%s, " MACSTR " is deauth, reason=%d\n", __func__, MAC2STR(addr), reason);
+
+	//struct hostap_driver_data *drv = priv;
+	struct rtl871x_driver_data *drv = priv;
+	struct ieee80211_mgmt mgmt;
+
+	memset(&mgmt, 0, sizeof(mgmt));
+	mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+					  WLAN_FC_STYPE_DEAUTH);
+	
+	memcpy(mgmt.da, addr, ETH_ALEN);
+	//memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN);
+	//memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN);
+	memcpy(mgmt.sa, own_addr, ETH_ALEN);
+	memcpy(mgmt.bssid, own_addr, ETH_ALEN);
+	mgmt.u.deauth.reason_code = host_to_le16(reason);
+
+	return rtl871x_send_mgmt_frame_ops(drv, &mgmt, IEEE80211_HDRLEN +
+				      sizeof(mgmt.u.deauth), 0);
+	
+}
+
+
+//static int rtl871x_sta_disassoc_ops(void *priv, const u8 *addr, int reason)
+static int rtl871x_sta_disassoc_ops(void *priv, const u8 *own_addr, const u8 *addr,
+		     int reason)
+{
+	printf("+%s, " MACSTR " is disassoc, reason=%d\n", __func__, MAC2STR(addr), reason);
+
+	struct rtl871x_driver_data *drv = priv;
+	struct ieee80211_mgmt mgmt;
+
+	memset(&mgmt, 0, sizeof(mgmt));
+	mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+					  WLAN_FC_STYPE_DISASSOC);
+	
+	memcpy(mgmt.da, addr, ETH_ALEN);
+	//memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN);
+	//memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN);
+	memcpy(mgmt.sa, own_addr, ETH_ALEN);
+	memcpy(mgmt.bssid, own_addr, ETH_ALEN);
+	
+	mgmt.u.disassoc.reason_code = host_to_le16(reason);
+	
+	return  rtl871x_send_mgmt_frame_ops(drv, &mgmt, IEEE80211_HDRLEN +
+				       sizeof(mgmt.u.disassoc), 0);
+
+}
+
+static int rtl871x_set_wps_assoc_resp_ie(struct rtl871x_driver_data *drv, const void *ie, size_t len)
+{
+	int ret;
+	size_t sz;
+	ieee_param *pparam;
+
+	
+	printf("%s\n", __func__);
+
+	sz = len + 12 + 2;// 12+2 = cmd+sta_addr+reserved, sizeof(ieee_param)=64, no packed
+	pparam = os_zalloc(sz);
+	if (pparam == NULL) {
+		return -ENOMEM;
+	}
+
+	pparam->cmd = RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP;	
+		
+	if(ie && len>0)
+	{
+		memcpy(pparam->u.bcn_ie.buf, ie, len);
+	}
+
+	ret = rtl871x_hostapd_ioctl(drv, pparam, sz);
+
+	os_free(pparam);
+
+	return ret;
+	
+}
+
+static int rtl871x_set_wps_beacon_ie(struct rtl871x_driver_data *drv, const void *ie, size_t len)
+{
+	int ret;
+	size_t sz;
+	ieee_param *pparam;
+
+	
+	printf("%s\n", __func__);
+
+	sz = len + 12 + 2;// 12+2 = cmd+sta_addr+reserved, sizeof(ieee_param)=64, no packed
+	pparam = os_zalloc(sz);
+	if (pparam == NULL) {
+		return -ENOMEM;
+	}
+
+	pparam->cmd = RTL871X_HOSTAPD_SET_WPS_BEACON;	
+		
+	if(ie && len>0)
+	{
+		memcpy(pparam->u.bcn_ie.buf, ie, len);
+	}
+
+	ret = rtl871x_hostapd_ioctl(drv, pparam, sz);
+
+	os_free(pparam);
+
+	return ret;
+	
+}
+
+static int rtl871x_set_wps_probe_resp_ie(struct rtl871x_driver_data *drv, const void *ie, size_t len)
+{
+	int ret;
+	size_t sz;
+	ieee_param *pparam;
+	
+	
+	printf("%s\n", __func__);
+
+	sz = len + 12 + 2;// 12+2 = cmd+sta_addr+reserved, sizeof(ieee_param)=64, no packed
+	pparam = os_zalloc(sz);
+	if (pparam == NULL) {
+		return -ENOMEM;
+	}
+
+	pparam->cmd = RTL871X_HOSTAPD_SET_WPS_PROBE_RESP;	
+		
+	if(ie && len>0)
+	{
+		memcpy(pparam->u.bcn_ie.buf, ie, len);
+	}
+
+	ret = rtl871x_hostapd_ioctl(drv, pparam, sz);
+
+	os_free(pparam);
+
+	return ret;
+	
+}
+
+static int rtl871x_set_ap_wps_ie(void *priv, const struct wpabuf *beacon,
+		      const struct wpabuf *proberesp, const struct wpabuf *assocresp)
+{
+	struct rtl871x_driver_data *drv = priv;	
+
+	if (rtl871x_set_wps_assoc_resp_ie(drv, assocresp ? wpabuf_head(assocresp) : NULL,
+			       assocresp ? wpabuf_len(assocresp) : 0))
+		return -1;
+
+	if (rtl871x_set_wps_beacon_ie(drv, beacon ? wpabuf_head(beacon) : NULL,
+			       beacon ? wpabuf_len(beacon) : 0))
+		return -1;
+
+	return rtl871x_set_wps_probe_resp_ie(drv,
+				  proberesp ? wpabuf_head(proberesp) : NULL,
+				  proberesp ? wpabuf_len(proberesp): 0);	
+
+}
+
+static int rtl871x_sta_flush_ops(void *priv)
+{
+	ieee_param param;
+	struct rtl871x_driver_data *drv = priv;	
+
+	memset(&param, 0, sizeof(param));
+	
+	param.cmd = RTL871X_HOSTAPD_FLUSH;	
+	
+	return rtl871x_hostapd_ioctl(drv, &param, sizeof(param));
+}
+
+static void *rtl871x_driver_init_ops(struct hostapd_data *hapd, struct wpa_init_params *params)
+{
+	struct rtl871x_driver_data *drv;
+	struct ifreq ifr;
+	//struct iwreq iwr;
+	char	ifrn_name[IFNAMSIZ + 1];//for mgnt_l2_sock/mgnt_sock
+	char brname[IFNAMSIZ];
+
+	drv = os_zalloc(sizeof(struct rtl871x_driver_data));
+	if (drv == NULL) {
+		printf("Could not allocate memory for rtl871x driver data\n");
+		return NULL;
+	}
+
+	drv->hapd = hapd;
+	drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
+	if (drv->ioctl_sock < 0) {
+		perror("socket[PF_INET,SOCK_DGRAM]");
+		goto bad;
+	}
+	os_memcpy(drv->iface, params->ifname, sizeof(drv->iface));
+
+	linux_set_iface_flags(drv->ioctl_sock, drv->iface, 1);/*set interface up*/
+
+	os_memset(&ifr, 0, sizeof(ifr));
+	os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
+	if (ioctl(drv->ioctl_sock, SIOCGIFINDEX, &ifr) != 0) {
+		perror("ioctl(SIOCGIFINDEX)");
+		goto bad;
+	}
+	drv->ifindex = ifr.ifr_ifindex;
+	printf("drv->ifindex=%d\n", drv->ifindex);
+
+	drv->l2_sock = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL,
+					rtl871x_handle_read, drv, 1);
+
+	if (drv->l2_sock == NULL)
+		goto bad;
+
+	if (l2_packet_get_own_addr(drv->l2_sock, params->own_addr))
+		goto bad;
+
+
+	if (params->bridge[0]) {
+		wpa_printf(MSG_DEBUG, "Configure bridge %s for EAPOL traffic.",
+			   params->bridge[0]);
+		drv->l2_sock_recv = l2_packet_init(params->bridge[0], NULL,
+						ETH_P_EAPOL, rtl871x_handle_read, drv,
+						1);
+		if (drv->l2_sock_recv == NULL)
+		{
+			//goto bad;			
+			drv->l2_sock_recv = drv->l2_sock;
+			printf("no br0 interface , let l2_sock_recv==l2_sock_xmit=0x%p\n", drv->l2_sock);	
+		}
+		
+	} else if (linux_br_get(brname, drv->iface) == 0) {
+		wpa_printf(MSG_DEBUG, "Interface in bridge %s; configure for "
+			   "EAPOL receive", brname);
+		drv->l2_sock_recv = l2_packet_init(brname, NULL, ETH_P_EAPOL,
+						rtl871x_handle_read, drv, 1);
+		if (drv->l2_sock_recv == NULL)
+			goto bad;
+	}
+	else
+	{
+		drv->l2_sock_recv = drv->l2_sock;
+		printf("l2_sock_recv==l2_sock_xmit=0x%p\n", drv->l2_sock);	
+	}
+
+
+	os_memset(ifrn_name, 0, sizeof(ifrn_name));
+	//snprintf(ifrn_name, sizeof(ifrn_name), "mgnt.%s_rena", drv->iface);
+	snprintf(ifrn_name, sizeof(ifrn_name), "mgnt.%s", "wlan0"/*drv->iface*/);
+#ifdef CONFIG_MGNT_L2SOCK	
+	drv->mgnt_l2_sock = NULL;
+	drv->mgnt_l2_sock = l2_packet_init(ifrn_name, NULL, ETH_P_80211_RAW,
+				       rtl871x_recvive_mgmt_frame, drv, 1);
+	if (drv->mgnt_l2_sock == NULL)
+		goto bad;
+	
+#else
+
+#ifdef CONFIG_MLME_OFFLOAD
+	drv->mgnt_sock = -1;
+#else
+	drv->mgnt_sock = rtl871x_mgnt_sock_init(drv, ifrn_name);
+	if (drv->mgnt_sock < 0) {		
+		goto bad;
+	}
+#endif
+
+#endif
+
+
+	//madwifi_set_iface_flags(drv, 0);	/* mark down during setup */
+	//madwifi_set_privacy(drv->iface, drv, 0); /* default to no privacy */
+
+
+	//linux_set_iface_flags(drv->ioctl_sock, drv->iface, 1);/*set interface up*/
+
+	
+	//enter MASTER MODE when init.
+	if(rtl871x_set_mode(drv, IW_MODE_MASTER)<0)
+	{
+		printf("Could not set interface to master mode!\n");
+		goto bad;
+	}
+
+/*
+	memset(&iwr, 0, sizeof(iwr));
+	os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
+	iwr.u.mode = IW_MODE_MASTER;
+	if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) {
+		perror("ioctl[SIOCSIWMODE]");
+		printf("Could not set interface to master mode!\n");
+		goto bad;
+	}
+*/	
+
+#ifndef CONFIG_MLME_OFFLOAD
+	rtl871x_set_iface_flags(drv, 1);	/*set mgnt interface up*/
+#endif
+
+	
+	if (rtl871x_wireless_event_init(drv))
+		goto bad;
+
+
+	os_memcpy(drv->hw_mac, params->own_addr, ETH_ALEN);
+
+	return drv;
+	
+bad:
+
+	if (drv->l2_sock_recv != NULL && drv->l2_sock_recv != drv->l2_sock)
+		l2_packet_deinit(drv->l2_sock_recv);
+	
+	if (drv->l2_sock != NULL)
+		l2_packet_deinit(drv->l2_sock);
+	
+	if (drv->ioctl_sock >= 0)
+		close(drv->ioctl_sock);
+
+#ifdef CONFIG_MGNT_L2SOCK
+	if ( drv->mgnt_l2_sock != NULL)
+		l2_packet_deinit(drv->mgnt_l2_sock);
+#else
+	if (drv->mgnt_sock >= 0)
+		close(drv->mgnt_sock);
+#endif
+	
+	if (drv != NULL)
+		free(drv);
+	
+	return NULL;
+	
+}
+
+static void rtl871x_driver_deinit_ops(void *priv)
+{
+	//struct iwreq iwr;
+	struct rtl871x_driver_data *drv = priv;
+
+	//back to INFRA MODE when exit.
+/*	
+	memset(&iwr, 0, sizeof(iwr));
+	os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
+	iwr.u.mode = IW_MODE_INFRA;
+	if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) {
+		perror("ioctl[SIOCSIWMODE]");
+	}
+*/	
+	rtl871x_set_mode(drv, IW_MODE_INFRA);
+	
+
+	if (drv->ioctl_sock >= 0)
+		close(drv->ioctl_sock);
+
+	
+	if (drv->l2_sock_recv != NULL && drv->l2_sock_recv != drv->l2_sock)
+		l2_packet_deinit(drv->l2_sock_recv);
+
+	if(drv->l2_sock)
+		l2_packet_deinit(drv->l2_sock);	
+	
+	//if (drv->sock_xmit != NULL)
+	//	l2_packet_deinit(drv->sock_xmit);
+
+#ifdef CONFIG_MGNT_L2SOCK	
+	if (drv->mgnt_l2_sock)
+		l2_packet_deinit(drv->mgnt_l2_sock);
+#else
+	if (drv->mgnt_sock >= 0)
+		close(drv->mgnt_sock);
+#endif
+
+	os_free(drv);
+	
+}
+
+
+const struct wpa_driver_ops wpa_driver_rtw_ops = {
+	.name = "rtl871xdrv",
+	//.init = rtl871x_driver_init_ops,
+	//.deinit = rtl871x_driver_deinit_ops,
+	.hapd_init		= rtl871x_driver_init_ops,
+	.hapd_deinit		= rtl871x_driver_deinit_ops,
+	//.wireless_event_init	= rtl871x_wireless_event_init_ops,
+	//.wireless_event_deinit	= rtl871x_wireless_event_deinit_ops,
+	//.send_eapol		= rtl871x_send_eapol_ops,
+	.hapd_send_eapol	= rtl871x_send_eapol_ops,
+	//.send_ether = rtl871x_driver_send_ether_ops,
+	//.send_mgmt_frame = rtl871x_send_mgmt_frame_ops,
+	.get_hw_feature_data = rtl871x_get_hw_feature_data_ops,
+	//.sta_add = rtl871x_sta_add_ops,
+	//.sta_add2 = rtl871x_sta_add2_ops,
+	.sta_remove = rtl871x_sta_remove_ops,
+	.set_ap = rtl871x_set_beacon_ops,
+	//.set_encryption = rtl871x_set_encryption_ops,
+	.set_key = rtl871x_set_key_ops,
+	.sta_deauth = rtl871x_sta_deauth_ops,
+	.sta_disassoc = rtl871x_sta_disassoc_ops,
+	//.set_wps_beacon_ie = rtl871x_set_wps_beacon_ie_ops,
+	//.set_wps_probe_resp_ie = rtl871x_set_wps_probe_resp_ie_ops,
+	.set_ap_wps_ie = rtl871x_set_ap_wps_ie,
+	.flush			= rtl871x_sta_flush_ops,
+};
+
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index 01defdf..1091108 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -1081,6 +1081,38 @@ void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx)
 	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
 }
 
+//added for wps2.0 @20110519
+static int wpa_driver_wext_set_probe_req_ie(struct wpa_driver_wext_data *drv, const u8 *extra_ies,
+				size_t extra_ies_len)
+{
+	unsigned char *pbuf;
+	struct iwreq iwr;	
+	int ret = 0;
+
+	pbuf = os_malloc(extra_ies_len);
+	os_memset(pbuf, 0, extra_ies_len);
+
+	os_memset(&iwr, 0, sizeof(iwr));
+	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+
+	os_memcpy(pbuf, extra_ies, extra_ies_len);
+
+	iwr.u.data.pointer = (caddr_t)pbuf;
+	iwr.u.data.length = extra_ies_len;
+	iwr.u.data.flags = 0x8766;//magic number
+
+	if (ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr) < 0) {
+		perror("ioctl[SIOCSIWMLME]");
+		ret = -1;
+	}
+
+	if(pbuf)
+		os_free(pbuf);
+
+	return ret;
+
+}
+
 
 /**
  * wpa_driver_wext_scan - Request the driver to initiate scan
@@ -1103,6 +1135,10 @@ int wpa_driver_wext_scan(void *priv, struct wpa_driver_scan_params *params)
 		return -1;
 	}
 
+	//added for wps2.0 @20110519
+	wpa_driver_wext_set_probe_req_ie(drv, params->extra_ies,
+				params->extra_ies_len);
+
 	os_memset(&iwr, 0, sizeof(iwr));
 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
 
diff --git a/src/drivers/drivers.c b/src/drivers/drivers.c
index a98af9a..d7d9c5b 100644
--- a/src/drivers/drivers.c
+++ b/src/drivers/drivers.c
@@ -45,6 +45,9 @@ extern struct wpa_driver_ops wpa_driver_atheros_ops; /* driver_atheros.c */
 #ifdef CONFIG_DRIVER_NONE
 extern struct wpa_driver_ops wpa_driver_none_ops; /* driver_none.c */
 #endif /* CONFIG_DRIVER_NONE */
+#ifdef CONFIG_DRIVER_RTW
+extern struct wpa_driver_ops wpa_driver_rtw_ops; /* driver_rtw.c */
+#endif /* CONFIG_DRIVER_RTW */
 
 
 const struct wpa_driver_ops *const wpa_drivers[] =
@@ -82,5 +85,8 @@ const struct wpa_driver_ops *const wpa_drivers[] =
 #ifdef CONFIG_DRIVER_NONE
 	&wpa_driver_none_ops,
 #endif /* CONFIG_DRIVER_NONE */
+#ifdef CONFIG_DRIVER_RTW
+	&wpa_driver_rtw_ops,
+#endif /* CONFIG_DRIVER_RTW */
 	NULL
 };
diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak
index 3dd43c7..3e44fcb 100644
--- a/src/drivers/drivers.mak
+++ b/src/drivers/drivers.mak
@@ -74,6 +74,10 @@ DRV_CFLAGS += -DCONFIG_DRIVER_BSD
 DRV_OBJS += ../src/drivers/driver_bsd.o
 CONFIG_L2_FREEBSD=y
 CONFIG_DNET_PCAP=y
+ifdef CONFIG_SUPPORT_RTW_DRIVER
+DRV_CFLAGS += -DCONFIG_SUPPORT_RTW_DRIVER -DCONFIG_DRIVER_RTL_DFS
+NEED_AP_MLME=y
+endif
 endif
 
 ifdef CONFIG_DRIVER_OPENBSD
@@ -84,6 +88,17 @@ DRV_CFLAGS += -DCONFIG_DRIVER_OPENBSD
 DRV_OBJS += ../src/drivers/driver_openbsd.o
 endif
 
+ifdef CONFIG_DRIVER_RTW
+#CFLAGS += -DCONFIG_DRIVER_RTL
+#OBJS += driver_rtl.o
+DRV_AP_CFLAGS += -DCONFIG_DRIVER_RTW -DCONFIG_DRIVER_RTL_DFS
+DRV_AP_OBJS += ../src/drivers/driver_rtw.o
+CONFIG_L2_PACKET=linux
+NEED_NETLINK=y
+NEED_LINUX_IOCTL=y
+NEED_AP_MLME=y
+endif
+
 ifdef CONFIG_DRIVER_NONE
 DRV_CFLAGS += -DCONFIG_DRIVER_NONE
 DRV_OBJS += ../src/drivers/driver_none.o
diff --git a/src/eap_peer/eap_wsc.c b/src/eap_peer/eap_wsc.c
index 7ac99c7..1f7697c 100644
--- a/src/eap_peer/eap_wsc.c
+++ b/src/eap_peer/eap_wsc.c
@@ -569,8 +569,13 @@ send_msg:
 	r = eap_wsc_build_msg(data, ret, id);
 	if (data->state == FAIL && ret->methodState == METHOD_DONE) {
 		/* Use reduced client timeout for WPS to avoid long wait */
+#if 0		/*	Aries add, 2012/06/12,  extend timeout for AP IOT 	*/
+		if (sm->ClientTimeout > 4)
+			sm->ClientTimeout = 4;
+#else
 		if (sm->ClientTimeout > 2)
 			sm->ClientTimeout = 2;
+#endif
 	}
 	return r;
 }
diff --git a/src/wps/wps.c b/src/wps/wps.c
index fbaf85a..10a82e1 100644
--- a/src/wps/wps.c
+++ b/src/wps/wps.c
@@ -321,11 +321,15 @@ int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr,
 	if (wps_parse_msg(msg, &attr) < 0)
 		return 0;
 
+	return is_selected_pin_registrar(&attr);
+//	Marked by Albert 2011/11/17
+//	Some APs won't carry the AuthorizedMACs in the probe response.
+//	So, skip this check will speed up the process to find the current AP out for WPS handshake.
+/*	
 	if (!attr.version2 && ver1_compat) {
 		/*
 		 * Version 1.0 AP - AuthorizedMACs not used, so revert back to
 		 * old mechanism of using SelectedRegistrar.
-		 */
 		return is_selected_pin_registrar(&attr);
 	}
 
@@ -342,6 +346,7 @@ int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr,
 	}
 
 	return 0;
+*/
 }
 
 
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index 4ca3a42..f74b036 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -589,9 +589,10 @@ static int wps_build_probe_config_methods(struct wps_registrar *reg,
 	 * These are the methods that the AP supports as an Enrollee for adding
 	 * external Registrars.
 	 */
-	methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
-	methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON |
-		     WPS_CONFIG_PHY_PUSHBUTTON);
+	methods = reg->wps->config_methods;
+	//methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
+	//methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON |
+	//	     WPS_CONFIG_PHY_PUSHBUTTON);
 	wpa_printf(MSG_DEBUG, "WPS:  * Config Methods (%x)", methods);
 	wpabuf_put_be16(msg, ATTR_CONFIG_METHODS);
 	wpabuf_put_be16(msg, 2);
# include this file from your own hostapd.conf

driver=rtl871xdrv
ieee80211n=1
hw_mode=g
device_name=RTL8192CU
manufacturer=Realtek

--- End Message ---
--- Begin Message ---
Control: tag 825676 wontfix

On Sat, 28 May 2016 21:06:07 +0300 Boris Shtrasman
<[email protected]> wrote:
> Dear Maintainer,
> 
> It seems that hostapd is lacking support for rtl871xdrv (example RTL8188CUS) 
> , few years ago Realtek released the code under GPLv2.
> 
> The attached patched is based on that code and it is taken from 
> https://github.com/pritambaral/hostapd-rtl871xdrv.git

I’m sorry to say this, but I won’t apply this patch. This chip needs to
be supported by the kernel, patching it into hostapd is a very wrong
thing to do.

In general, I would recommend everyone to stay away from any hardware
manufactured by Realtek. It’s just not worth it.

-- 
Cheers,
  Andrej

--- End Message ---

Reply via email to