---help---
This option tells whether enhanced packet stats collection
is enabled or not.
+config SCSC_WIFI_NAN_ENABLE
+ bool "Enable WiFi NAN"
+ default n
+ ---help---
+ This option tells whether WiFi NAN is enabled or not.
scsc_wlan-$(CONFIG_SCSC_WLAN) += nl80211_vendor.o
ccflags-y += -DCONFIG_SCSC_WLAN_GSCAN_ENABLE
endif
+ifeq ($(CONFIG_SCSC_WIFI_NAN_ENABLE),y)
+scsc_wlan-$(CONFIG_SCSC_WLAN) += nl80211_vendor_nan.o
+scsc_wlan-$(CONFIG_SCSC_WLAN) += mlme_nan.o
+endif
ifeq ($(CONFIG_SCSC_WLAN_KEY_MGMT_OFFLOAD),y)
ccflags-y += -DCONFIG_SCSC_WLAN_KEY_MGMT_OFFLOAD
return r;
}
-static void slsi_mlme_nan_enable_fapi_data(struct sk_buff *req, struct slsi_hal_nan_enable_req *hal_req)
-{
- u8 nan_config_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x01};
- u8 *header_ptr;
- u16 attribute;
- u8 band_usage = BIT(0) | BIT(1);
- u8 scan_param[] = {0, 0, 0};
- int len = 0;
-
- header_ptr = fapi_append_data(req, nan_config_fields_header, sizeof(nan_config_fields_header));
- len += sizeof(nan_config_fields_header);
-
- if (hal_req->config_2dot4g_beacons && !hal_req->beacon_2dot4g_val)
- band_usage &= ~BIT(0);
- if (hal_req->config_2dot4g_sdf && !hal_req->sdf_2dot4g_val)
- band_usage &= ~BIT(1);
- if (hal_req->config_5g_beacons && hal_req->beacon_5g_val)
- band_usage |= BIT(2);
- if (hal_req->config_5g_sdf && hal_req->sdf_5g_val)
- band_usage |= BIT(3);
-
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_BAND_USAGE;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, band_usage);
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_MASTER_PREFERENCE;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_U16(req, attribute, hal_req->master_pref);
- len += 11; /* 5 for band_usage, 6 for master preference */
-
- if (hal_req->config_sid_beacon) {
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SID_BEACON;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->sid_beacon_val);
- len += 5;
- }
-
- if (hal_req->config_2dot4g_rssi_close) {
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_CLOSE;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_close_2dot4g_val);
- len += 5;
- }
-
- if (hal_req->config_2dot4g_rssi_middle) {
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_MIDDLE;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_middle_2dot4g_val);
- len += 5;
- }
-
- if (hal_req->config_2dot4g_rssi_proximity) {
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_PROXIMITY;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_proximity_2dot4g_val);
- len += 5;
- }
-
- if (hal_req->config_5g_rssi_close) {
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_CLOSE;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_close_5g_val);
- len += 5;
- }
-
- if (hal_req->config_5g_rssi_middle) {
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_MIDDLE;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_middle_5g_val);
- len += 5;
- }
-
- if (hal_req->config_5g_rssi_close_proximity) {
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_PROXIMITY;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_close_proximity_5g_val);
- len += 5;
- }
-
- if (hal_req->config_hop_count_limit) {
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_HOP_COUNT_LIMIT;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->hop_count_limit_val);
- len += 5;
- }
-
- if (hal_req->config_rssi_window_size) {
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_RSSI_WINDOW_SIZE;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_window_size_val);
- len += 5;
- }
-
- if (hal_req->config_scan_params) {
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_2_4;
- scan_param[0] = hal_req->scan_params_val.dwell_time[0];
- scan_param[1] = hal_req->scan_params_val.scan_period[0] & 0x00FF;
- scan_param[2] = (hal_req->scan_params_val.scan_period[0] & 0xFF00) >> 8;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, scan_param, 3);
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_5;
- scan_param[0] = hal_req->scan_params_val.dwell_time[1];
- scan_param[1] = hal_req->scan_params_val.scan_period[1] & 0x00FF;
- scan_param[2] = (hal_req->scan_params_val.scan_period[1] & 0xFF00) >> 8;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, scan_param, 3);
- len += 7 * 2;
- }
-
- /* update len */
- header_ptr[1] = len - 2;
-}
-
-int slsi_mlme_nan_enable(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_enable_req *hal_req)
-{
- struct netdev_vif *ndev_vif = netdev_priv(dev);
- struct sk_buff *req;
- struct sk_buff *cfm;
- int r = 0;
- u16 nan_oper_ctrl = 0;
-
- SLSI_NET_DBG3(dev, SLSI_MLME, "\n");
-
- /* max mbulk data for mlme-nan-start.req is about 87 bytes but
- * allocate 100 bytes
- */
- req = fapi_alloc(mlme_nan_start_req, MLME_NAN_START_REQ, ndev_vif->ifnum, 100);
- if (!req) {
- SLSI_NET_ERR(dev, "fapi alloc failure\n");
- return -ENOMEM;
- }
-
- if (hal_req->config_cluster_attribute_val)
- nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_CLUSTER_SDF;
- nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_MAC_ADDRESS_EVENT | FAPI_NANOPERATIONCONTROL_START_CLUSTER_EVENT |
- FAPI_NANOPERATIONCONTROL_JOINED_CLUSTER_EVENT;
-
- fapi_set_u16(req, u.mlme_nan_start_req.cluster_low, hal_req->cluster_low);
- fapi_set_u16(req, u.mlme_nan_start_req.cluster_high, hal_req->cluster_high);
- fapi_set_u16(req, u.mlme_nan_start_req.nan_operation_control_flags, nan_oper_ctrl);
-
- slsi_mlme_nan_enable_fapi_data(req, hal_req);
-
- cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_START_CFM);
- if (!cfm)
- return -EIO;
-
- if (fapi_get_u16(cfm, u.mlme_nan_start_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
- SLSI_NET_ERR(dev, "MLME_NAN_START_CFM(result:0x%04x) ERROR\n",
- fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code));
- r = -EINVAL;
- }
-
- slsi_kfree_skb(cfm);
- return r;
-}
-
-static void slsi_mlme_nan_append_tlv(struct sk_buff *req, __le16 tlv_t, __le16 tlv_l, u8 *tlv_v, u8 **header_ptr,
- u8 header_ie_generic_len, u8 **end_ptr)
-{
- u8 tmp_buf[255 + 4];
- u8 *tmp_buf_pos;
- int tmp_buf_len, len1, ip_ie_len;
-
- memcpy(tmp_buf, &tlv_t, 2);
- memcpy(tmp_buf + 2, &tlv_l, 2);
- memcpy(tmp_buf + 4, tlv_v, tlv_l);
- tmp_buf_len = 4 + tlv_l;
- ip_ie_len = *end_ptr - *header_ptr - 2;
- tmp_buf_pos = tmp_buf;
-
- while (tmp_buf_len + ip_ie_len > 255) {
- len1 = 255 - ip_ie_len;
- fapi_append_data(req, tmp_buf_pos, len1);
- (*header_ptr)[1] = 255;
- tmp_buf_len -= len1;
- tmp_buf_pos += len1;
- ip_ie_len = 0;
- if (tmp_buf_len) {
- *header_ptr = fapi_append_data(req, *header_ptr, header_ie_generic_len);
- *end_ptr = *header_ptr + header_ie_generic_len;
- } else {
- *end_ptr = *header_ptr + header_ie_generic_len + 255;
- }
- }
- if (tmp_buf_len) {
- fapi_append_data(req, tmp_buf, tmp_buf_len);
- *end_ptr += tmp_buf_len;
- }
-}
-
-static void slsi_mlme_nan_publish_fapi_data(struct sk_buff *req, struct slsi_hal_nan_publish_req *hal_req)
-{
- u8 nan_publish_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x02};
- u8 *header_ptr, *end_ptr;
- __le16 le16val;
- u32 binding_mask = 0;
-
- header_ptr = fapi_append_data(req, nan_publish_fields_header, sizeof(nan_publish_fields_header));
- le16val = cpu_to_le16(hal_req->ttl);
- fapi_append_data(req, (u8 *)&le16val, 2);
- le16val = cpu_to_le16(hal_req->period);
- fapi_append_data(req, (u8 *)&le16val, 2);
- fapi_append_data(req, &hal_req->publish_type, 1);
- fapi_append_data(req, &hal_req->tx_type, 1);
- fapi_append_data(req, &hal_req->publish_count, 1);
- fapi_append_data(req, &hal_req->publish_match_indicator, 1);
- fapi_append_data(req, &hal_req->rssi_threshold_flag, 1);
- end_ptr = fapi_append_data(req, (u8 *)&binding_mask, 4);
- end_ptr += 4;
-
- if (hal_req->service_name_len)
- slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_NAME),
- cpu_to_le16 (hal_req->service_name_len), hal_req->service_name, &header_ptr,
- sizeof(nan_publish_fields_header), &end_ptr);
-
- if (hal_req->service_specific_info_len)
- slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO),
- cpu_to_le16 (hal_req->service_specific_info_len),
- hal_req->service_specific_info, &header_ptr,
- sizeof(nan_publish_fields_header), &end_ptr);
-
- if (hal_req->rx_match_filter_len)
- slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_RX_MATCH_FILTER),
- cpu_to_le16 (hal_req->rx_match_filter_len), hal_req->rx_match_filter,
- &header_ptr, sizeof(nan_publish_fields_header), &end_ptr);
-
- if (hal_req->tx_match_filter_len)
- slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_TX_MATCH_FILTER),
- cpu_to_le16 (hal_req->tx_match_filter_len), hal_req->tx_match_filter,
- &header_ptr, sizeof(nan_publish_fields_header), &end_ptr);
-
- /* update len */
- header_ptr[1] = end_ptr - header_ptr - 2;
-}
-
-int slsi_mlme_nan_publish(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_publish_req *hal_req,
- u16 publish_id)
-{
- struct netdev_vif *ndev_vif = netdev_priv(dev);
- struct sk_buff *req;
- struct sk_buff *cfm;
- int r = 0;
- u16 nan_sdf_flags = 0;
-
- SLSI_NET_DBG3(dev, SLSI_MLME, "\n");
- if (hal_req) {
- /* max possible length for publish attributes : 8*255 */
- req = fapi_alloc(mlme_nan_publish_req, MLME_NAN_PUBLISH_REQ, ndev_vif->ifnum, 8 * 255);
- if (!req) {
- SLSI_NET_ERR(dev, "fapi alloc failure\n");
- return -ENOMEM;
- }
-
- /* Set/Enable corresponding bits to disable any indications
- * that follow a publish.
- * BIT0 - Disable publish termination indication.
- * BIT1 - Disable match expired indication.
- * BIT2 - Disable followUp indication received (OTA).
- */
- if (hal_req->recv_indication_cfg & BIT(0))
- nan_sdf_flags |= FAPI_NANSDFCONTROL_PUBLISH_END_EVENT;
- if (hal_req->recv_indication_cfg & BIT(1))
- nan_sdf_flags |= FAPI_NANSDFCONTROL_MATCH_EXPIRED_EVENT;
- if (hal_req->recv_indication_cfg & BIT(2))
- nan_sdf_flags |= FAPI_NANSDFCONTROL_RECEIVED_FOLLOWUP_EVENT;
- } else {
- req = fapi_alloc(mlme_nan_publish_req, MLME_NAN_PUBLISH_REQ, ndev_vif->ifnum, 0);
- if (!req) {
- SLSI_NET_ERR(dev, "fapi alloc failure\n");
- return -ENOMEM;
- }
- }
-
- fapi_set_u16(req, u.mlme_nan_publish_req.publish_id, publish_id);
- fapi_set_u16(req, u.mlme_nan_publish_req.nan_sdf_flags, nan_sdf_flags);
-
- if (hal_req)
- slsi_mlme_nan_publish_fapi_data(req, hal_req);
-
- cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_PUBLISH_CFM);
- if (!cfm)
- return -EIO;
-
- if (fapi_get_u16(cfm, u.mlme_nan_publish_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
- SLSI_NET_ERR(dev, "MLME_NAN_PUBLISH_CFM(result:0x%04x) ERROR\n",
- fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code));
- r = -EINVAL;
- }
-
- if (hal_req && !r)
- ndev_vif->nan.publish_id_map |= BIT(publish_id);
- else
- ndev_vif->nan.publish_id_map &= ~BIT(publish_id);
- slsi_kfree_skb(cfm);
- return r;
-}
-
-static void slsi_mlme_nan_subscribe_fapi_data(struct sk_buff *req, struct slsi_hal_nan_subscribe_req *hal_req)
-{
- u8 nan_subscribe_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x03};
- u8 *header_ptr, *end_ptr;
- __le16 le16val;
- u32 binding_mask = 0;
-
- header_ptr = fapi_append_data(req, nan_subscribe_fields_header, sizeof(nan_subscribe_fields_header));
- le16val = cpu_to_le16(hal_req->ttl);
- fapi_append_data(req, (u8 *)&le16val, 2);
- le16val = cpu_to_le16(hal_req->period);
- fapi_append_data(req, (u8 *)&le16val, 2);
- fapi_append_data(req, &hal_req->subscribe_type, 1);
- fapi_append_data(req, &hal_req->service_response_filter, 1);
- fapi_append_data(req, &hal_req->service_response_include, 1);
- fapi_append_data(req, &hal_req->use_service_response_filter, 1);
- fapi_append_data(req, &hal_req->ssi_required_for_match_indication, 1);
- fapi_append_data(req, &hal_req->subscribe_match_indicator, 1);
- fapi_append_data(req, &hal_req->subscribe_count, 1);
- fapi_append_data(req, &hal_req->rssi_threshold_flag, 1);
- end_ptr = fapi_append_data(req, (u8 *)&binding_mask, 4);
- end_ptr += 4;
-
- if (hal_req->service_name_len)
- slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_NAME),
- cpu_to_le16 (hal_req->service_name_len), hal_req->service_name, &header_ptr,
- sizeof(nan_subscribe_fields_header), &end_ptr);
-
- if (hal_req->service_specific_info_len)
- slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO),
- cpu_to_le16 (hal_req->service_specific_info_len),
- hal_req->service_specific_info, &header_ptr,
- sizeof(nan_subscribe_fields_header), &end_ptr);
-
- if (hal_req->rx_match_filter_len)
- slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_RX_MATCH_FILTER),
- cpu_to_le16 (hal_req->rx_match_filter_len), hal_req->rx_match_filter,
- &header_ptr, sizeof(nan_subscribe_fields_header), &end_ptr);
-
- if (hal_req->tx_match_filter_len)
- slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_TX_MATCH_FILTER),
- cpu_to_le16 (hal_req->tx_match_filter_len), hal_req->tx_match_filter,
- &header_ptr, sizeof(nan_subscribe_fields_header), &end_ptr);
-
- /* update len */
- header_ptr[1] = end_ptr - header_ptr - 2;
-}
-
-int slsi_mlme_nan_subscribe(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_subscribe_req *hal_req,
- u16 subscribe_id)
-{
- struct netdev_vif *ndev_vif = netdev_priv(dev);
- struct sk_buff *req;
- struct sk_buff *cfm;
- int r = 0;
- u16 nan_sdf_flags = 0;
-
- SLSI_NET_DBG3(dev, SLSI_MLME, "\n");
- if (hal_req) {
- /*max possible length for publish attributes: 8*255 */
- req = fapi_alloc(mlme_nan_subscribe_req, MLME_NAN_SUBSCRIBE_REQ, ndev_vif->ifnum, 8 * 255);
- if (!req) {
- SLSI_NET_ERR(dev, "fapi alloc failure\n");
- return -ENOMEM;
- }
- /* Set/Enable corresponding bits to disable
- * indications that follow a subscribe.
- * BIT0 - Disable subscribe termination indication.
- * BIT1 - Disable match expired indication.
- * BIT2 - Disable followUp indication received (OTA).
- */
- if (hal_req->recv_indication_cfg & BIT(0))
- nan_sdf_flags |= FAPI_NANSDFCONTROL_SUBSCRIBE_END_EVENT;
- if (hal_req->recv_indication_cfg & BIT(1))
- nan_sdf_flags |= FAPI_NANSDFCONTROL_MATCH_EXPIRED_EVENT;
- if (hal_req->recv_indication_cfg & BIT(2))
- nan_sdf_flags |= FAPI_NANSDFCONTROL_RECEIVED_FOLLOWUP_EVENT;
- } else {
- req = fapi_alloc(mlme_nan_subscribe_req, MLME_NAN_SUBSCRIBE_REQ, ndev_vif->ifnum, 0);
- if (!req) {
- SLSI_NET_ERR(dev, "fapi alloc failure\n");
- return -ENOMEM;
- }
- }
-
- fapi_set_u16(req, u.mlme_nan_subscribe_req.subscribe_id, subscribe_id);
- fapi_set_u16(req, u.mlme_nan_subscribe_req.nan_sdf_flags, nan_sdf_flags);
-
- if (hal_req)
- slsi_mlme_nan_subscribe_fapi_data(req, hal_req);
-
- cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_SUBSCRIBE_CFM);
- if (!cfm)
- return -EIO;
-
- if (fapi_get_u16(cfm, u.mlme_nan_subscribe_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
- SLSI_NET_ERR(dev, "MLME_NAN_SUBSCRIBE_CFM(res:0x%04x)\n",
- fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code));
- r = -EINVAL;
- }
-
- if (hal_req && !r)
- ndev_vif->nan.subscribe_id_map |= BIT(subscribe_id);
- else
- ndev_vif->nan.subscribe_id_map &= ~BIT(subscribe_id);
- slsi_kfree_skb(cfm);
- return r;
-}
-
-static void slsi_mlme_nan_followup_fapi_data(struct sk_buff *req, struct slsi_hal_nan_transmit_followup_req *hal_req)
-{
- u8 nan_followup_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x05};
- u8 *header_ptr, *end_ptr;
-
- header_ptr = fapi_append_data(req, nan_followup_fields_header, sizeof(nan_followup_fields_header));
- fapi_append_data(req, hal_req->addr, ETH_ALEN);
- fapi_append_data(req, &hal_req->priority, 1);
- end_ptr = fapi_append_data(req, &hal_req->dw_or_faw, 1);
- end_ptr += 1;
-
- if (hal_req->service_specific_info_len)
- slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO),
- cpu_to_le16 (hal_req->service_specific_info_len),
- hal_req->service_specific_info, &header_ptr,
- sizeof(nan_followup_fields_header), &end_ptr);
-
- /* update len */
- header_ptr[1] = end_ptr - header_ptr - 2;
-}
-
-int slsi_mlme_nan_tx_followup(struct slsi_dev *sdev, struct net_device *dev,
- struct slsi_hal_nan_transmit_followup_req *hal_req)
-{
- struct netdev_vif *ndev_vif = netdev_priv(dev);
- struct sk_buff *req;
- struct sk_buff *cfm;
- int r = 0;
- u16 nan_sdf_flags = 0;
-
- SLSI_NET_DBG3(dev, SLSI_MLME, "\n");
-
- /* max possible length for publish attributes: 5*255 */
- req = fapi_alloc(mlme_nan_followup_req, MLME_NAN_FOLLOWUP_REQ, ndev_vif->ifnum, 5 * 255);
- if (!req) {
- SLSI_NET_ERR(dev, "fapi alloc failure\n");
- return -ENOMEM;
- }
-
- /* Set/Enable corresponding bits to disable responses after followUp.
- * BIT0 - Disable followUp response from FW.
- */
- if (hal_req->recv_indication_cfg & BIT(0))
- nan_sdf_flags |= FAPI_NANSDFCONTROL_DISABLE_RESPONSES_AFTER_FOLLOWUP;
-
- fapi_set_u16(req, u.mlme_nan_followup_req.requestor_instance_id, hal_req->publish_subscribe_id);
- fapi_set_u16(req, u.mlme_nan_followup_req.requestor_instance_id, hal_req->requestor_instance_id);
- fapi_set_u16(req, u.mlme_nan_subscribe_req.nan_sdf_flags, nan_sdf_flags);
-
- slsi_mlme_nan_followup_fapi_data(req, hal_req);
-
- cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_FOLLOWUP_CFM);
- if (!cfm)
- return -EIO;
-
- if (fapi_get_u16(cfm, u.mlme_nan_followup_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
- SLSI_NET_ERR(dev, "MLME_NAN_FOLLOWUP_CFM(res:0x%04x)\n",
- fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code));
- r = -EINVAL;
- }
-
- slsi_kfree_skb(cfm);
- return r;
-}
-
-static void slsi_mlme_nan_config_fapi_data(struct sk_buff *req, struct slsi_hal_nan_config_req *hal_req)
-{
- u8 nan_config_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x01};
- u8 *header_ptr;
- u16 attribute;
- u8 scan_param[] = {0, 0, 0};
- int len = 0;
-
- header_ptr = fapi_append_data(req, nan_config_fields_header, sizeof(nan_config_fields_header));
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_MASTER_PREFERENCE;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_U16(req, attribute, hal_req->master_pref);
- len += sizeof(nan_config_fields_header) + 5;
-
- if (hal_req->config_sid_beacon) {
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SID_BEACON;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->sid_beacon);
- len += 5;
- }
-
- if (hal_req->config_rssi_proximity) {
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_PROXIMITY;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_proximity);
- len += 5;
- }
-
- if (hal_req->config_5g_rssi_close_proximity) {
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_PROXIMITY;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_close_proximity_5g_val);
- len += 5;
- }
-
- if (hal_req->config_rssi_window_size) {
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_RSSI_WINDOW_SIZE;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_window_size_val);
- len += 5;
- }
-
- if (hal_req->config_scan_params) {
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_2_4;
- scan_param[0] = hal_req->scan_params_val.dwell_time[0];
- scan_param[1] = hal_req->scan_params_val.scan_period[0] & 0x00FF;
- scan_param[2] = (hal_req->scan_params_val.scan_period[0] & 0xFF00) >> 8;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, scan_param, 3);
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_5;
- scan_param[0] = hal_req->scan_params_val.dwell_time[1];
- scan_param[1] = hal_req->scan_params_val.scan_period[1] & 0x00FF;
- scan_param[2] = (hal_req->scan_params_val.scan_period[1] & 0xFF00) >> 8;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, scan_param, 3);
- len += 7 * 2;
- }
-
- if (hal_req->config_conn_capability) {
- u8 con_cap = 0;
-
- if (hal_req->conn_capability_val.is_wfd_supported)
- con_cap |= BIT(0);
- if (hal_req->conn_capability_val.is_wfds_supported)
- con_cap |= BIT(1);
- if (hal_req->conn_capability_val.is_tdls_supported)
- con_cap |= BIT(2);
- if (hal_req->conn_capability_val.wlan_infra_field)
- con_cap |= BIT(3);
- attribute = SLSI_FAPI_NAN_CONFIG_PARAM_CONNECTION_CAPAB;
- SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_window_size_val);
- len += 5;
- }
- /* update len */
- header_ptr[1] = len - 2;
-}
-
-int slsi_mlme_nan_set_config(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_config_req *hal_req)
-{
- struct netdev_vif *ndev_vif = netdev_priv(dev);
- struct sk_buff *req;
- struct sk_buff *cfm;
- int r = 0;
- u16 nan_oper_ctrl = 0;
-
- SLSI_NET_DBG3(dev, SLSI_MLME, "\n");
- /* max possible length for publish attributes 5*255 */
- req = fapi_alloc(mlme_nan_config_req, MLME_NAN_CONFIG_REQ, ndev_vif->ifnum, 5 * 255);
- if (!req) {
- SLSI_NET_ERR(dev, "fapi alloc failure\n");
- return -ENOMEM;
- }
-
- if (hal_req->config_cluster_attribute_val)
- nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_CLUSTER_SDF;
- nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_MAC_ADDRESS_EVENT | FAPI_NANOPERATIONCONTROL_START_CLUSTER_EVENT |
- FAPI_NANOPERATIONCONTROL_JOINED_CLUSTER_EVENT;
- fapi_set_u16(req, u.mlme_nan_config_req.nan_operation_control_flags, nan_oper_ctrl);
-
- slsi_mlme_nan_config_fapi_data(req, hal_req);
-
- cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_FOLLOWUP_CFM);
- if (!cfm)
- return -EIO;
-
- if (fapi_get_u16(cfm, u.mlme_nan_followup_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
- SLSI_NET_ERR(dev, "MLME_NAN_FOLLOWUP_CFM(res:0x%04x)\n",
- fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code));
- r = -EINVAL;
- }
-
- slsi_kfree_skb(cfm);
- return r;
-}
-
#ifdef CONFIG_SCSC_WLAN_DEBUG
#define SLSI_TEST_CONFIG_MONITOR_MODE_DESCRIPTOR_SIZE (12)
int slsi_test_sap_configure_monitor_mode(struct slsi_dev *sdev, struct net_device *dev, struct cfg80211_chan_def *chandef)
/****************************************************************************
*
- * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved
+ * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved
*
****************************************************************************/
void slsi_fw_tx_rate_calc(u16 fw_rate, struct rate_info *tx_rate, unsigned long *data_rate_mbps);
int slsi_test_sap_configure_monitor_mode(struct slsi_dev *sdev, struct net_device *dev, struct cfg80211_chan_def *chandef);
+struct sk_buff *slsi_mlme_req_cfm(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, u16 cfm_id);
+
#endif /*__SLSI_MLME_H__*/
--- /dev/null
+/*****************************************************************************
+ *
+ * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved
+ *
+ ****************************************************************************/
+
+#include "debug.h"
+#include "mlme.h"
+
+#define SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, val) \
+ { \
+ u16 attribute_len = 1; \
+ struct sk_buff *req_p = req; \
+ fapi_append_data((req_p), (u8 *)&(attribute), 2); \
+ fapi_append_data((req_p), (u8 *)&attribute_len, 2); \
+ fapi_append_data((req_p), (u8 *)&(val), 1); \
+ }
+
+#define SLSI_FAPI_NAN_ATTRIBUTE_PUT_U16(req, attribute, val) \
+ { \
+ u16 attribute_len = 2; \
+ __le16 le16val = cpu_to_le16(val); \
+ struct sk_buff *req_p = req; \
+ fapi_append_data((req_p), (u8 *)&(attribute), 2); \
+ fapi_append_data((req_p), (u8 *)&attribute_len, 2); \
+ fapi_append_data((req_p), (u8 *)&le16val, 2); \
+ }
+
+#define SLSI_FAPI_NAN_ATTRIBUTE_PUT_U32(req, attribute, val) \
+ { \
+ u16 attribute_len = 4; \
+ __le32 le32val = cpu_to_le32(val);\
+ struct sk_buff *req_p = req; \
+ fapi_append_data((req_p), (u8 *)&(attribute), 2); \
+ fapi_append_data((req_p), (u8 *)&attribute_len, 2); \
+ fapi_append_data((req_p), (u8 *)&le32val, 4); \
+ }
+
+#define SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, val, val_len) \
+ { \
+ u16 attribute_len = (val_len); \
+ struct sk_buff *req_p = req; \
+ fapi_append_data((req_p), (u8 *)&(attribute), 2); \
+ fapi_append_data((req_p), (u8 *)&attribute_len, 2); \
+ fapi_append_data((req_p), (val), (attribute_len)); \
+ }
+
+static void slsi_mlme_nan_enable_fapi_data(struct sk_buff *req, struct slsi_hal_nan_enable_req *hal_req)
+{
+ u8 nan_config_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x01};
+ u8 *header_ptr;
+ u16 attribute;
+ u8 band_usage = BIT(0) | BIT(1);
+ u8 scan_param[] = {0, 0, 0};
+ int len = 0;
+
+ header_ptr = fapi_append_data(req, nan_config_fields_header, sizeof(nan_config_fields_header));
+ len += sizeof(nan_config_fields_header);
+
+ if (hal_req->config_2dot4g_beacons && !hal_req->beacon_2dot4g_val)
+ band_usage &= ~BIT(0);
+ if (hal_req->config_2dot4g_sdf && !hal_req->sdf_2dot4g_val)
+ band_usage &= ~BIT(1);
+ if (hal_req->config_5g_beacons && hal_req->beacon_5g_val)
+ band_usage |= BIT(2);
+ if (hal_req->config_5g_sdf && hal_req->sdf_5g_val)
+ band_usage |= BIT(3);
+
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_BAND_USAGE;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, band_usage);
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_MASTER_PREFERENCE;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_U16(req, attribute, hal_req->master_pref);
+ len += 11; /* 5 for band_usage, 6 for master preference */
+
+ if (hal_req->config_sid_beacon) {
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SID_BEACON;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->sid_beacon_val);
+ len += 5;
+ }
+
+ if (hal_req->config_2dot4g_rssi_close) {
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_CLOSE;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_close_2dot4g_val);
+ len += 5;
+ }
+
+ if (hal_req->config_2dot4g_rssi_middle) {
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_MIDDLE;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_middle_2dot4g_val);
+ len += 5;
+ }
+
+ if (hal_req->config_2dot4g_rssi_proximity) {
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_PROXIMITY;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_proximity_2dot4g_val);
+ len += 5;
+ }
+
+ if (hal_req->config_5g_rssi_close) {
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_CLOSE;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_close_5g_val);
+ len += 5;
+ }
+
+ if (hal_req->config_5g_rssi_middle) {
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_MIDDLE;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_middle_5g_val);
+ len += 5;
+ }
+
+ if (hal_req->config_5g_rssi_close_proximity) {
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_PROXIMITY;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_close_proximity_5g_val);
+ len += 5;
+ }
+
+ if (hal_req->config_hop_count_limit) {
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_HOP_COUNT_LIMIT;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->hop_count_limit_val);
+ len += 5;
+ }
+
+ if (hal_req->config_rssi_window_size) {
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_RSSI_WINDOW_SIZE;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_window_size_val);
+ len += 5;
+ }
+
+ if (hal_req->config_scan_params) {
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_2_4;
+ scan_param[0] = hal_req->scan_params_val.dwell_time[0];
+ scan_param[1] = hal_req->scan_params_val.scan_period[0] & 0x00FF;
+ scan_param[2] = (hal_req->scan_params_val.scan_period[0] & 0xFF00) >> 8;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, scan_param, 3);
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_5;
+ scan_param[0] = hal_req->scan_params_val.dwell_time[1];
+ scan_param[1] = hal_req->scan_params_val.scan_period[1] & 0x00FF;
+ scan_param[2] = (hal_req->scan_params_val.scan_period[1] & 0xFF00) >> 8;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, scan_param, 3);
+ len += 7 * 2;
+ }
+
+ /* update len */
+ header_ptr[1] = len - 2;
+}
+
+int slsi_mlme_nan_enable(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_enable_req *hal_req)
+{
+ struct netdev_vif *ndev_vif = netdev_priv(dev);
+ struct sk_buff *req;
+ struct sk_buff *cfm;
+ int r = 0;
+ u16 nan_oper_ctrl = 0;
+
+ SLSI_NET_DBG3(dev, SLSI_MLME, "\n");
+
+ /* max mbulk data for mlme-nan-start.req is about 87 bytes but
+ * allocate 100 bytes
+ */
+ req = fapi_alloc(mlme_nan_start_req, MLME_NAN_START_REQ, ndev_vif->ifnum, 100);
+ if (!req) {
+ SLSI_NET_ERR(dev, "fapi alloc failure\n");
+ return -ENOMEM;
+ }
+
+ if (hal_req->config_cluster_attribute_val)
+ nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_CLUSTER_SDF;
+ nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_MAC_ADDRESS_EVENT | FAPI_NANOPERATIONCONTROL_START_CLUSTER_EVENT |
+ FAPI_NANOPERATIONCONTROL_JOINED_CLUSTER_EVENT;
+
+ fapi_set_u16(req, u.mlme_nan_start_req.cluster_low, hal_req->cluster_low);
+ fapi_set_u16(req, u.mlme_nan_start_req.cluster_high, hal_req->cluster_high);
+ fapi_set_u16(req, u.mlme_nan_start_req.nan_operation_control_flags, nan_oper_ctrl);
+
+ slsi_mlme_nan_enable_fapi_data(req, hal_req);
+
+ cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_START_CFM);
+ if (!cfm)
+ return -EIO;
+
+ if (fapi_get_u16(cfm, u.mlme_nan_start_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
+ SLSI_NET_ERR(dev, "MLME_NAN_START_CFM(result:0x%04x) ERROR\n",
+ fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code));
+ r = -EINVAL;
+ }
+
+ slsi_kfree_skb(cfm);
+ return r;
+}
+
+static void slsi_mlme_nan_append_tlv(struct sk_buff *req, __le16 tlv_t, __le16 tlv_l, u8 *tlv_v, u8 **header_ptr,
+ u8 header_ie_generic_len, u8 **end_ptr)
+{
+ u8 tmp_buf[255 + 4];
+ u8 *tmp_buf_pos;
+ int tmp_buf_len, len1, ip_ie_len;
+
+ memcpy(tmp_buf, &tlv_t, 2);
+ memcpy(tmp_buf + 2, &tlv_l, 2);
+ memcpy(tmp_buf + 4, tlv_v, tlv_l);
+ tmp_buf_len = 4 + tlv_l;
+ ip_ie_len = *end_ptr - *header_ptr - 2;
+ tmp_buf_pos = tmp_buf;
+
+ while (tmp_buf_len + ip_ie_len > 255) {
+ len1 = 255 - ip_ie_len;
+ fapi_append_data(req, tmp_buf_pos, len1);
+ (*header_ptr)[1] = 255;
+ tmp_buf_len -= len1;
+ tmp_buf_pos += len1;
+ ip_ie_len = 0;
+ if (tmp_buf_len) {
+ *header_ptr = fapi_append_data(req, *header_ptr, header_ie_generic_len);
+ *end_ptr = *header_ptr + header_ie_generic_len;
+ } else {
+ *end_ptr = *header_ptr + header_ie_generic_len + 255;
+ }
+ }
+ if (tmp_buf_len) {
+ fapi_append_data(req, tmp_buf, tmp_buf_len);
+ *end_ptr += tmp_buf_len;
+ }
+}
+
+static void slsi_mlme_nan_publish_fapi_data(struct sk_buff *req, struct slsi_hal_nan_publish_req *hal_req)
+{
+ u8 nan_publish_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x02};
+ u8 *header_ptr, *end_ptr;
+ __le16 le16val;
+ u32 binding_mask = 0;
+
+ header_ptr = fapi_append_data(req, nan_publish_fields_header, sizeof(nan_publish_fields_header));
+ le16val = cpu_to_le16(hal_req->ttl);
+ fapi_append_data(req, (u8 *)&le16val, 2);
+ le16val = cpu_to_le16(hal_req->period);
+ fapi_append_data(req, (u8 *)&le16val, 2);
+ fapi_append_data(req, &hal_req->publish_type, 1);
+ fapi_append_data(req, &hal_req->tx_type, 1);
+ fapi_append_data(req, &hal_req->publish_count, 1);
+ fapi_append_data(req, &hal_req->publish_match_indicator, 1);
+ fapi_append_data(req, &hal_req->rssi_threshold_flag, 1);
+ end_ptr = fapi_append_data(req, (u8 *)&binding_mask, 4);
+ end_ptr += 4;
+
+ if (hal_req->service_name_len)
+ slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_NAME),
+ cpu_to_le16 (hal_req->service_name_len), hal_req->service_name, &header_ptr,
+ sizeof(nan_publish_fields_header), &end_ptr);
+
+ if (hal_req->service_specific_info_len)
+ slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO),
+ cpu_to_le16 (hal_req->service_specific_info_len),
+ hal_req->service_specific_info, &header_ptr,
+ sizeof(nan_publish_fields_header), &end_ptr);
+
+ if (hal_req->rx_match_filter_len)
+ slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_RX_MATCH_FILTER),
+ cpu_to_le16 (hal_req->rx_match_filter_len), hal_req->rx_match_filter,
+ &header_ptr, sizeof(nan_publish_fields_header), &end_ptr);
+
+ if (hal_req->tx_match_filter_len)
+ slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_TX_MATCH_FILTER),
+ cpu_to_le16 (hal_req->tx_match_filter_len), hal_req->tx_match_filter,
+ &header_ptr, sizeof(nan_publish_fields_header), &end_ptr);
+
+ /* update len */
+ header_ptr[1] = end_ptr - header_ptr - 2;
+}
+
+int slsi_mlme_nan_publish(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_publish_req *hal_req,
+ u16 publish_id)
+{
+ struct netdev_vif *ndev_vif = netdev_priv(dev);
+ struct sk_buff *req;
+ struct sk_buff *cfm;
+ int r = 0;
+ u16 nan_sdf_flags = 0;
+
+ SLSI_NET_DBG3(dev, SLSI_MLME, "\n");
+ if (hal_req) {
+ /* max possible length for publish attributes : 8*255 */
+ req = fapi_alloc(mlme_nan_publish_req, MLME_NAN_PUBLISH_REQ, ndev_vif->ifnum, 8 * 255);
+ if (!req) {
+ SLSI_NET_ERR(dev, "fapi alloc failure\n");
+ return -ENOMEM;
+ }
+
+ /* Set/Enable corresponding bits to disable any indications
+ * that follow a publish.
+ * BIT0 - Disable publish termination indication.
+ * BIT1 - Disable match expired indication.
+ * BIT2 - Disable followUp indication received (OTA).
+ */
+ if (hal_req->recv_indication_cfg & BIT(0))
+ nan_sdf_flags |= FAPI_NANSDFCONTROL_PUBLISH_END_EVENT;
+ if (hal_req->recv_indication_cfg & BIT(1))
+ nan_sdf_flags |= FAPI_NANSDFCONTROL_MATCH_EXPIRED_EVENT;
+ if (hal_req->recv_indication_cfg & BIT(2))
+ nan_sdf_flags |= FAPI_NANSDFCONTROL_RECEIVED_FOLLOWUP_EVENT;
+ } else {
+ req = fapi_alloc(mlme_nan_publish_req, MLME_NAN_PUBLISH_REQ, ndev_vif->ifnum, 0);
+ if (!req) {
+ SLSI_NET_ERR(dev, "fapi alloc failure\n");
+ return -ENOMEM;
+ }
+ }
+
+ fapi_set_u16(req, u.mlme_nan_publish_req.publish_id, publish_id);
+ fapi_set_u16(req, u.mlme_nan_publish_req.nan_sdf_flags, nan_sdf_flags);
+
+ if (hal_req)
+ slsi_mlme_nan_publish_fapi_data(req, hal_req);
+
+ cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_PUBLISH_CFM);
+ if (!cfm)
+ return -EIO;
+
+ if (fapi_get_u16(cfm, u.mlme_nan_publish_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
+ SLSI_NET_ERR(dev, "MLME_NAN_PUBLISH_CFM(result:0x%04x) ERROR\n",
+ fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code));
+ r = -EINVAL;
+ }
+
+ if (hal_req && !r)
+ ndev_vif->nan.publish_id_map |= BIT(publish_id);
+ else
+ ndev_vif->nan.publish_id_map &= ~BIT(publish_id);
+ slsi_kfree_skb(cfm);
+ return r;
+}
+
+static void slsi_mlme_nan_subscribe_fapi_data(struct sk_buff *req, struct slsi_hal_nan_subscribe_req *hal_req)
+{
+ u8 nan_subscribe_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x03};
+ u8 *header_ptr, *end_ptr;
+ __le16 le16val;
+ u32 binding_mask = 0;
+
+ header_ptr = fapi_append_data(req, nan_subscribe_fields_header, sizeof(nan_subscribe_fields_header));
+ le16val = cpu_to_le16(hal_req->ttl);
+ fapi_append_data(req, (u8 *)&le16val, 2);
+ le16val = cpu_to_le16(hal_req->period);
+ fapi_append_data(req, (u8 *)&le16val, 2);
+ fapi_append_data(req, &hal_req->subscribe_type, 1);
+ fapi_append_data(req, &hal_req->service_response_filter, 1);
+ fapi_append_data(req, &hal_req->service_response_include, 1);
+ fapi_append_data(req, &hal_req->use_service_response_filter, 1);
+ fapi_append_data(req, &hal_req->ssi_required_for_match_indication, 1);
+ fapi_append_data(req, &hal_req->subscribe_match_indicator, 1);
+ fapi_append_data(req, &hal_req->subscribe_count, 1);
+ fapi_append_data(req, &hal_req->rssi_threshold_flag, 1);
+ end_ptr = fapi_append_data(req, (u8 *)&binding_mask, 4);
+ end_ptr += 4;
+
+ if (hal_req->service_name_len)
+ slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_NAME),
+ cpu_to_le16 (hal_req->service_name_len), hal_req->service_name, &header_ptr,
+ sizeof(nan_subscribe_fields_header), &end_ptr);
+
+ if (hal_req->service_specific_info_len)
+ slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO),
+ cpu_to_le16 (hal_req->service_specific_info_len),
+ hal_req->service_specific_info, &header_ptr,
+ sizeof(nan_subscribe_fields_header), &end_ptr);
+
+ if (hal_req->rx_match_filter_len)
+ slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_RX_MATCH_FILTER),
+ cpu_to_le16 (hal_req->rx_match_filter_len), hal_req->rx_match_filter,
+ &header_ptr, sizeof(nan_subscribe_fields_header), &end_ptr);
+
+ if (hal_req->tx_match_filter_len)
+ slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_TX_MATCH_FILTER),
+ cpu_to_le16 (hal_req->tx_match_filter_len), hal_req->tx_match_filter,
+ &header_ptr, sizeof(nan_subscribe_fields_header), &end_ptr);
+
+ /* update len */
+ header_ptr[1] = end_ptr - header_ptr - 2;
+}
+
+int slsi_mlme_nan_subscribe(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_subscribe_req *hal_req,
+ u16 subscribe_id)
+{
+ struct netdev_vif *ndev_vif = netdev_priv(dev);
+ struct sk_buff *req;
+ struct sk_buff *cfm;
+ int r = 0;
+ u16 nan_sdf_flags = 0;
+
+ SLSI_NET_DBG3(dev, SLSI_MLME, "\n");
+ if (hal_req) {
+ /*max possible length for publish attributes: 8*255 */
+ req = fapi_alloc(mlme_nan_subscribe_req, MLME_NAN_SUBSCRIBE_REQ, ndev_vif->ifnum, 8 * 255);
+ if (!req) {
+ SLSI_NET_ERR(dev, "fapi alloc failure\n");
+ return -ENOMEM;
+ }
+ /* Set/Enable corresponding bits to disable
+ * indications that follow a subscribe.
+ * BIT0 - Disable subscribe termination indication.
+ * BIT1 - Disable match expired indication.
+ * BIT2 - Disable followUp indication received (OTA).
+ */
+ if (hal_req->recv_indication_cfg & BIT(0))
+ nan_sdf_flags |= FAPI_NANSDFCONTROL_SUBSCRIBE_END_EVENT;
+ if (hal_req->recv_indication_cfg & BIT(1))
+ nan_sdf_flags |= FAPI_NANSDFCONTROL_MATCH_EXPIRED_EVENT;
+ if (hal_req->recv_indication_cfg & BIT(2))
+ nan_sdf_flags |= FAPI_NANSDFCONTROL_RECEIVED_FOLLOWUP_EVENT;
+ } else {
+ req = fapi_alloc(mlme_nan_subscribe_req, MLME_NAN_SUBSCRIBE_REQ, ndev_vif->ifnum, 0);
+ if (!req) {
+ SLSI_NET_ERR(dev, "fapi alloc failure\n");
+ return -ENOMEM;
+ }
+ }
+
+ fapi_set_u16(req, u.mlme_nan_subscribe_req.subscribe_id, subscribe_id);
+ fapi_set_u16(req, u.mlme_nan_subscribe_req.nan_sdf_flags, nan_sdf_flags);
+
+ if (hal_req)
+ slsi_mlme_nan_subscribe_fapi_data(req, hal_req);
+
+ cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_SUBSCRIBE_CFM);
+ if (!cfm)
+ return -EIO;
+
+ if (fapi_get_u16(cfm, u.mlme_nan_subscribe_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
+ SLSI_NET_ERR(dev, "MLME_NAN_SUBSCRIBE_CFM(res:0x%04x)\n",
+ fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code));
+ r = -EINVAL;
+ }
+
+ if (hal_req && !r)
+ ndev_vif->nan.subscribe_id_map |= BIT(subscribe_id);
+ else
+ ndev_vif->nan.subscribe_id_map &= ~BIT(subscribe_id);
+ slsi_kfree_skb(cfm);
+ return r;
+}
+
+static void slsi_mlme_nan_followup_fapi_data(struct sk_buff *req, struct slsi_hal_nan_transmit_followup_req *hal_req)
+{
+ u8 nan_followup_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x05};
+ u8 *header_ptr, *end_ptr;
+
+ header_ptr = fapi_append_data(req, nan_followup_fields_header, sizeof(nan_followup_fields_header));
+ fapi_append_data(req, hal_req->addr, ETH_ALEN);
+ fapi_append_data(req, &hal_req->priority, 1);
+ end_ptr = fapi_append_data(req, &hal_req->dw_or_faw, 1);
+ end_ptr += 1;
+
+ if (hal_req->service_specific_info_len)
+ slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO),
+ cpu_to_le16 (hal_req->service_specific_info_len),
+ hal_req->service_specific_info, &header_ptr,
+ sizeof(nan_followup_fields_header), &end_ptr);
+
+ /* update len */
+ header_ptr[1] = end_ptr - header_ptr - 2;
+}
+
+int slsi_mlme_nan_tx_followup(struct slsi_dev *sdev, struct net_device *dev,
+ struct slsi_hal_nan_transmit_followup_req *hal_req)
+{
+ struct netdev_vif *ndev_vif = netdev_priv(dev);
+ struct sk_buff *req;
+ struct sk_buff *cfm;
+ int r = 0;
+ u16 nan_sdf_flags = 0;
+
+ SLSI_NET_DBG3(dev, SLSI_MLME, "\n");
+
+ /* max possible length for publish attributes: 5*255 */
+ req = fapi_alloc(mlme_nan_followup_req, MLME_NAN_FOLLOWUP_REQ, ndev_vif->ifnum, 5 * 255);
+ if (!req) {
+ SLSI_NET_ERR(dev, "fapi alloc failure\n");
+ return -ENOMEM;
+ }
+
+ /* Set/Enable corresponding bits to disable responses after followUp.
+ * BIT0 - Disable followUp response from FW.
+ */
+ if (hal_req->recv_indication_cfg & BIT(0))
+ nan_sdf_flags |= FAPI_NANSDFCONTROL_DISABLE_RESPONSES_AFTER_FOLLOWUP;
+
+ fapi_set_u16(req, u.mlme_nan_followup_req.requestor_instance_id, hal_req->publish_subscribe_id);
+ fapi_set_u16(req, u.mlme_nan_followup_req.requestor_instance_id, hal_req->requestor_instance_id);
+ fapi_set_u16(req, u.mlme_nan_subscribe_req.nan_sdf_flags, nan_sdf_flags);
+
+ slsi_mlme_nan_followup_fapi_data(req, hal_req);
+
+ cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_FOLLOWUP_CFM);
+ if (!cfm)
+ return -EIO;
+
+ if (fapi_get_u16(cfm, u.mlme_nan_followup_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
+ SLSI_NET_ERR(dev, "MLME_NAN_FOLLOWUP_CFM(res:0x%04x)\n",
+ fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code));
+ r = -EINVAL;
+ }
+
+ slsi_kfree_skb(cfm);
+ return r;
+}
+
+static void slsi_mlme_nan_config_fapi_data(struct sk_buff *req, struct slsi_hal_nan_config_req *hal_req)
+{
+ u8 nan_config_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x01};
+ u8 *header_ptr;
+ u16 attribute;
+ u8 scan_param[] = {0, 0, 0};
+ int len = 0;
+
+ header_ptr = fapi_append_data(req, nan_config_fields_header, sizeof(nan_config_fields_header));
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_MASTER_PREFERENCE;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_U16(req, attribute, hal_req->master_pref);
+ len += sizeof(nan_config_fields_header) + 5;
+
+ if (hal_req->config_sid_beacon) {
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SID_BEACON;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->sid_beacon);
+ len += 5;
+ }
+
+ if (hal_req->config_rssi_proximity) {
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_PROXIMITY;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_proximity);
+ len += 5;
+ }
+
+ if (hal_req->config_5g_rssi_close_proximity) {
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_PROXIMITY;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_close_proximity_5g_val);
+ len += 5;
+ }
+
+ if (hal_req->config_rssi_window_size) {
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_RSSI_WINDOW_SIZE;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_window_size_val);
+ len += 5;
+ }
+
+ if (hal_req->config_scan_params) {
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_2_4;
+ scan_param[0] = hal_req->scan_params_val.dwell_time[0];
+ scan_param[1] = hal_req->scan_params_val.scan_period[0] & 0x00FF;
+ scan_param[2] = (hal_req->scan_params_val.scan_period[0] & 0xFF00) >> 8;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, scan_param, 3);
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_5;
+ scan_param[0] = hal_req->scan_params_val.dwell_time[1];
+ scan_param[1] = hal_req->scan_params_val.scan_period[1] & 0x00FF;
+ scan_param[2] = (hal_req->scan_params_val.scan_period[1] & 0xFF00) >> 8;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, scan_param, 3);
+ len += 7 * 2;
+ }
+
+ if (hal_req->config_conn_capability) {
+ u8 con_cap = 0;
+
+ if (hal_req->conn_capability_val.is_wfd_supported)
+ con_cap |= BIT(0);
+ if (hal_req->conn_capability_val.is_wfds_supported)
+ con_cap |= BIT(1);
+ if (hal_req->conn_capability_val.is_tdls_supported)
+ con_cap |= BIT(2);
+ if (hal_req->conn_capability_val.wlan_infra_field)
+ con_cap |= BIT(3);
+ attribute = SLSI_FAPI_NAN_CONFIG_PARAM_CONNECTION_CAPAB;
+ SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_window_size_val);
+ len += 5;
+ }
+ /* update len */
+ header_ptr[1] = len - 2;
+}
+
+int slsi_mlme_nan_set_config(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_config_req *hal_req)
+{
+ struct netdev_vif *ndev_vif = netdev_priv(dev);
+ struct sk_buff *req;
+ struct sk_buff *cfm;
+ int r = 0;
+ u16 nan_oper_ctrl = 0;
+
+ SLSI_NET_DBG3(dev, SLSI_MLME, "\n");
+ /* max possible length for publish attributes 5*255 */
+ req = fapi_alloc(mlme_nan_config_req, MLME_NAN_CONFIG_REQ, ndev_vif->ifnum, 5 * 255);
+ if (!req) {
+ SLSI_NET_ERR(dev, "fapi alloc failure\n");
+ return -ENOMEM;
+ }
+
+ if (hal_req->config_cluster_attribute_val)
+ nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_CLUSTER_SDF;
+ nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_MAC_ADDRESS_EVENT | FAPI_NANOPERATIONCONTROL_START_CLUSTER_EVENT |
+ FAPI_NANOPERATIONCONTROL_JOINED_CLUSTER_EVENT;
+ fapi_set_u16(req, u.mlme_nan_config_req.nan_operation_control_flags, nan_oper_ctrl);
+
+ slsi_mlme_nan_config_fapi_data(req, hal_req);
+
+ cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_FOLLOWUP_CFM);
+ if (!cfm)
+ return -EIO;
+
+ if (fapi_get_u16(cfm, u.mlme_nan_followup_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
+ SLSI_NET_ERR(dev, "MLME_NAN_FOLLOWUP_CFM(res:0x%04x)\n",
+ fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code));
+ r = -EINVAL;
+ }
+
+ slsi_kfree_skb(cfm);
+ return r;
+}
return slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN);
}
-static struct net_device *slsi_nan_get_netdev(struct slsi_dev *sdev)
-{
-#if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4
- return slsi_get_netdev(sdev, SLSI_NET_INDEX_NAN);
-#else
- return NULL;
-#endif
-}
-
static struct netdev_vif *slsi_gscan_get_vif(struct slsi_dev *sdev)
{
struct net_device *dev;
{
int r, type, j = 0;
struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
struct net_device *dev = slsi_nan_get_netdev(sdev);
struct netdev_vif *ndev_vif;
+#endif
struct slsi_rtt_config *nl_rtt_params;
const struct nlattr *iter, *outer, *inner;
int tmp, tmp1, tmp2;
if (rtt_peer == SLSI_RTT_PEER_AP) {
vif_idx = 0;
} else if (rtt_peer == SLSI_RTT_PEER_NAN) {
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
if (!slsi_dev_nan_supported(sdev)) {
SLSI_ERR(sdev, "NAN not supported(mib:%d)\n", sdev->nan_enabled);
kfree(nl_rtt_params);
kfree(nl_rtt_params);
return -EINVAL;
}
+#else
+ SLSI_ERR(sdev, "NAN not enabled\n");
+ return -ENOTSUPP;
+#endif
}
r = slsi_mlme_add_range_req(sdev, num_devices, nl_rtt_params, rtt_id, vif_idx);
if (r) {
return r;
}
-static int slsi_nan_get_new_id(u32 id_map, int max_ids)
-{
- int i;
-
- for (i = 1; i <= max_ids; i++) {
- if (!(id_map & BIT(i)))
- return i;
- }
- return 0;
-}
-
-static int slsi_nan_get_new_publish_id(struct netdev_vif *ndev_vif)
-{
- return slsi_nan_get_new_id(ndev_vif->nan.publish_id_map, SLSI_NAN_MAX_PUBLISH_ID);
-}
-
-static int slsi_nan_get_new_subscribe_id(struct netdev_vif *ndev_vif)
-{
- return slsi_nan_get_new_id(ndev_vif->nan.subscribe_id_map, SLSI_NAN_MAX_SUBSCRIBE_ID);
-}
-
-static bool slsi_nan_is_publish_id_active(struct netdev_vif *ndev_vif, u32 id)
-{
- return ndev_vif->nan.publish_id_map & BIT(id);
-}
-
-static bool slsi_nan_is_subscribe_id_active(struct netdev_vif *ndev_vif, u32 id)
-{
- return ndev_vif->nan.subscribe_id_map & BIT(id);
-}
-
-void slsi_nan_get_mac(struct slsi_dev *sdev, char *nan_mac_addr)
+static int slsi_configure_nd_offload(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
{
- memset(nan_mac_addr, 0, ETH_ALEN);
-#if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4
- if (slsi_dev_nan_supported(sdev))
- ether_addr_copy(nan_mac_addr, sdev->netdev_addresses[SLSI_NET_INDEX_NAN]);
-#endif
-}
+ struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+ struct net_device *dev = wdev->netdev;
+ struct netdev_vif *ndev_vif;
+ int ret = 0;
+ int temp;
+ int type;
+ const struct nlattr *attr;
+ u8 nd_offload_enabled = 0;
-static void slsi_vendor_nan_command_reply(struct wiphy *wiphy, u32 status, u32 error, u32 response_type,
- u16 publish_subscribe_id, struct slsi_hal_nan_capabilities *capabilities)
-{
- int reply_len;
- struct sk_buff *reply;
+ SLSI_DBG3(sdev, SLSI_GSCAN, "Received nd_offload command\n");
- reply_len = SLSI_NL_VENDOR_REPLY_OVERHEAD + SLSI_NL_ATTRIBUTE_U32_LEN *
- (3 + sizeof(struct slsi_hal_nan_capabilities));
- reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, reply_len);
- if (!reply) {
- SLSI_WARN_NODEV("SKB alloc failed for vendor_cmd reply\n");
- return;
+ if (!dev) {
+ SLSI_ERR(sdev, "dev is NULL!!\n");
+ return -EINVAL;
}
- nla_put_u32(reply, NAN_REPLY_ATTR_STATUS_TYPE, status);
- nla_put_u32(reply, NAN_REPLY_ATTR_VALUE, error);
- nla_put_u32(reply, NAN_REPLY_ATTR_RESPONSE_TYPE, response_type);
-
- if (capabilities) {
- nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_CONCURRENT_CLUSTER,
- capabilities->max_concurrent_nan_clusters);
- nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_PUBLISHES, capabilities->max_publishes);
- nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_SUBSCRIBES, capabilities->max_subscribes);
- nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_SERVICE_NAME_LEN, capabilities->max_service_name_len);
- nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_MATCH_FILTER_LEN, capabilities->max_match_filter_len);
- nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_TOTAL_MATCH_FILTER_LEN,
- capabilities->max_total_match_filter_len);
- nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_SERVICE_SPECIFIC_INFO_LEN,
- capabilities->max_service_specific_info_len);
- nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_VSA_DATA_LEN, capabilities->max_vsa_data_len);
- nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_MESH_DATA_LEN, capabilities->max_mesh_data_len);
- nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_NDI_INTERFACES, capabilities->max_ndi_interfaces);
- nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_NDP_SESSIONS, capabilities->max_ndp_sessions);
- nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_APP_INFO_LEN, capabilities->max_app_info_len);
- } else if (publish_subscribe_id) {
- nla_put_u16(reply, NAN_REPLY_ATTR_PUBLISH_SUBSCRIBE_TYPE, publish_subscribe_id);
- }
-
- if (cfg80211_vendor_cmd_reply(reply))
- SLSI_ERR_NODEV("FAILED to reply nan coammnd. response_type:%d\n", response_type);
-}
+ ndev_vif = netdev_priv(dev);
+ SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
-static int slsi_nan_enable_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_enable_req *hal_req,
- const void *data, int len)
-{
- int type, tmp;
- const struct nlattr *iter;
+ if (!ndev_vif->activated || (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) ||
+ (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED)) {
+ SLSI_DBG3(sdev, SLSI_GSCAN, "vif error\n");
+ ret = -EPERM;
+ goto exit;
+ }
- memset(hal_req, 0, sizeof(*hal_req));
- nla_for_each_attr(iter, data, len, tmp) {
- type = nla_type(iter);
+ nla_for_each_attr(attr, data, len, temp) {
+ type = nla_type(attr);
switch (type) {
- case NAN_REQ_ATTR_MASTER_PREF:
- hal_req->master_pref = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_CLUSTER_LOW:
- hal_req->cluster_low = nla_get_u16(iter);
- break;
-
- case NAN_REQ_ATTR_CLUSTER_HIGH:
- hal_req->cluster_high = nla_get_u16(iter);
- break;
-
- case NAN_REQ_ATTR_SUPPORT_5G_VAL:
- hal_req->support_5g_val = nla_get_u8(iter);
- hal_req->config_support_5g = 1;
- break;
-
- case NAN_REQ_ATTR_SID_BEACON_VAL:
- hal_req->sid_beacon_val = nla_get_u8(iter);
- hal_req->config_sid_beacon = 1;
- break;
-
- case NAN_REQ_ATTR_RSSI_CLOSE_2G4_VAL:
- hal_req->rssi_close_2dot4g_val = nla_get_u8(iter);
- hal_req->config_2dot4g_rssi_close = 1;
- break;
-
- case NAN_REQ_ATTR_RSSI_MIDDLE_2G4_VAL:
- hal_req->rssi_middle_2dot4g_val = nla_get_u8(iter);
- hal_req->config_2dot4g_rssi_middle = 1;
- break;
-
- case NAN_REQ_ATTR_RSSI_PROXIMITY_2G4_VAL:
- hal_req->rssi_proximity_2dot4g_val = nla_get_u8(iter);
- hal_req->rssi_proximity_2dot4g_val = 1;
- break;
-
- case NAN_REQ_ATTR_HOP_COUNT_LIMIT_VAL:
- hal_req->hop_count_limit_val = nla_get_u8(iter);
- hal_req->config_hop_count_limit = 1;
- break;
-
- case NAN_REQ_ATTR_SUPPORT_2G4_VAL:
- hal_req->support_2dot4g_val = nla_get_u8(iter);
- hal_req->config_2dot4g_support = 1;
- break;
-
- case NAN_REQ_ATTR_BEACONS_2G4_VAL:
- hal_req->beacon_2dot4g_val = nla_get_u8(iter);
- hal_req->config_2dot4g_beacons = 1;
- break;
-
- case NAN_REQ_ATTR_SDF_2G4_VAL:
- hal_req->sdf_2dot4g_val = nla_get_u8(iter);
- hal_req->config_2dot4g_sdf = 1;
- break;
-
- case NAN_REQ_ATTR_BEACON_5G_VAL:
- hal_req->beacon_5g_val = nla_get_u8(iter);
- hal_req->config_5g_beacons = 1;
- break;
-
- case NAN_REQ_ATTR_SDF_5G_VAL:
- hal_req->sdf_5g_val = nla_get_u8(iter);
- hal_req->config_5g_sdf = 1;
- break;
-
- case NAN_REQ_ATTR_RSSI_CLOSE_5G_VAL:
- hal_req->rssi_close_5g_val = nla_get_u8(iter);
- hal_req->config_5g_rssi_close = 1;
- break;
-
- case NAN_REQ_ATTR_RSSI_MIDDLE_5G_VAL:
- hal_req->rssi_middle_5g_val = nla_get_u8(iter);
- hal_req->config_5g_rssi_middle = 1;
- break;
-
- case NAN_REQ_ATTR_RSSI_CLOSE_PROXIMITY_5G_VAL:
- hal_req->rssi_close_proximity_5g_val = nla_get_u8(iter);
- hal_req->config_5g_rssi_close_proximity = 1;
- break;
-
- case NAN_REQ_ATTR_RSSI_WINDOW_SIZE_VAL:
- hal_req->rssi_window_size_val = nla_get_u8(iter);
- hal_req->config_rssi_window_size = 1;
- break;
-
- case NAN_REQ_ATTR_OUI_VAL:
- hal_req->oui_val = nla_get_u32(iter);
- hal_req->config_oui = 1;
- break;
-
- case NAN_REQ_ATTR_MAC_ADDR_VAL:
- memcpy(hal_req->intf_addr_val, nla_data(iter), ETH_ALEN);
- hal_req->config_intf_addr = 1;
- break;
-
- case NAN_REQ_ATTR_CLUSTER_VAL:
- hal_req->config_cluster_attribute_val = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_SOCIAL_CH_SCAN_DWELL_TIME:
- memcpy(hal_req->scan_params_val.dwell_time, nla_data(iter),
- sizeof(hal_req->scan_params_val.dwell_time));
- hal_req->config_scan_params = 1;
- break;
-
- case NAN_REQ_ATTR_SOCIAL_CH_SCAN_PERIOD:
- memcpy(hal_req->scan_params_val.scan_period, nla_data(iter),
- sizeof(hal_req->scan_params_val.scan_period));
- hal_req->config_scan_params = 1;
- break;
-
- case NAN_REQ_ATTR_RANDOM_FACTOR_FORCE_VAL:
- hal_req->random_factor_force_val = nla_get_u8(iter);
- hal_req->config_random_factor_force = 1;
- break;
-
- case NAN_REQ_ATTR_HOP_COUNT_FORCE_VAL:
- hal_req->hop_count_force_val = nla_get_u8(iter);
- hal_req->config_hop_count_force = 1;
- break;
-
- case NAN_REQ_ATTR_CHANNEL_2G4_MHZ_VAL:
- hal_req->channel_24g_val = nla_get_u32(iter);
- hal_req->config_24g_channel = 1;
- break;
-
- case NAN_REQ_ATTR_CHANNEL_5G_MHZ_VAL:
- hal_req->channel_5g_val = nla_get_u8(iter);
- hal_req->config_5g_channel = 1;
+ case SLSI_NL_ATTRIBUTE_ND_OFFLOAD_VALUE:
+ {
+ nd_offload_enabled = nla_get_u8(attr);
break;
-
+ }
default:
- SLSI_ERR(sdev, "Unexpected NAN enable attribute TYPE:%d\n", type);
- return SLSI_HAL_NAN_STATUS_INVALID_PARAM;
+ SLSI_ERR(sdev, "Invalid type : %d\n", type);
+ ret = -EINVAL;
+ goto exit;
}
}
- return SLSI_HAL_NAN_STATUS_SUCCESS;
+
+ ndev_vif->sta.nd_offload_enabled = nd_offload_enabled;
+ ret = slsi_mlme_set_ipv6_address(sdev, dev);
+ if (ret < 0) {
+ SLSI_ERR(sdev, "Configure nd_offload failed ret:%d nd_offload_enabled: %d\n", ret, nd_offload_enabled);
+ ret = -EINVAL;
+ goto exit;
+ }
+exit:
+ SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+ return ret;
}
-static int slsi_nan_enable(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
+static int slsi_get_roaming_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
{
- struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
- struct slsi_hal_nan_enable_req hal_req;
- int ret;
- struct net_device *dev = slsi_nan_get_netdev(sdev);
+ struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+ struct net_device *dev = wdev->netdev;
struct netdev_vif *ndev_vif;
- u8 nan_vif_mac_address[ETH_ALEN];
- u8 broadcast_mac[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
- u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
+ int ret = 0;
+ struct slsi_mib_value *values = NULL;
+ struct slsi_mib_data mibrsp = { 0, NULL };
+ struct slsi_mib_get_entry get_values[] = {{ SLSI_PSID_UNIFI_ROAM_BLACKLIST_SIZE, { 0, 0 } } };
+ u32 max_blacklist_size = 0;
+ u32 max_whitelist_size = 0;
+ struct sk_buff *nl_skb;
+ struct nlattr *nlattr_start;
if (!dev) {
- SLSI_ERR(sdev, "No NAN interface\n");
- ret = -ENOTSUPP;
- reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
- goto exit;
- }
-
- if (!slsi_dev_nan_supported(sdev)) {
- SLSI_ERR(sdev, "NAN not allowed(mib:%d)\n", sdev->nan_enabled);
- ret = WIFI_HAL_ERROR_NOT_SUPPORTED;
- reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
- goto exit;
+ SLSI_ERR(sdev, "dev is NULL!!\n");
+ return -EINVAL;
}
ndev_vif = netdev_priv(dev);
- reply_status = slsi_nan_enable_get_nl_params(sdev, &hal_req, data, len);
- if (reply_status != SLSI_HAL_NAN_STATUS_SUCCESS) {
- ret = -EINVAL;
+ SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+
+ mibrsp.dataLength = 10;
+ mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL);
+ if (!mibrsp.data) {
+ SLSI_ERR(sdev, "Cannot kmalloc %d bytes\n", mibrsp.dataLength);
+ ret = -ENOMEM;
goto exit;
}
+ values = slsi_read_mibs(sdev, NULL, get_values, ARRAY_SIZE(get_values), &mibrsp);
+ if (values && (values[0].type == SLSI_MIB_TYPE_UINT || values[0].type == SLSI_MIB_TYPE_INT))
+ max_blacklist_size = values[0].u.uintValue;
+ nl_skb = cfg80211_vendor_cmd_alloc_reply_skb(sdev->wiphy, NLMSG_DEFAULT_SIZE);
+ if (!nl_skb) {
+ SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n");
+ ret = -ENOMEM;
+ goto exit_with_mib_resp;
+ }
- SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
- if (ndev_vif->activated) {
+ nlattr_start = nla_nest_start(nl_skb, NL80211_ATTR_VENDOR_DATA);
+ if (!nlattr_start) {
+ SLSI_ERR(sdev, "failed to put NL80211_ATTR_VENDOR_DATA\n");
+ /* Dont use slsi skb wrapper for this free */
+ kfree_skb(nl_skb);
ret = -EINVAL;
- SLSI_DBG1_NODEV(SLSI_GSCAN, "NAN opearations in progress. Reject new req\n");
- goto exit_with_mutex;
+ goto exit_with_mib_resp;
}
- ndev_vif->vif_type = FAPI_VIFTYPE_NAN;
-
- if (hal_req.config_intf_addr)
- ether_addr_copy(nan_vif_mac_address, hal_req.intf_addr_val);
- else
- slsi_nan_get_mac(sdev, nan_vif_mac_address);
- ret = slsi_mlme_add_vif(sdev, dev, nan_vif_mac_address, broadcast_mac);
+ ret = nla_put_u32(nl_skb, SLSI_NL_ATTR_MAX_BLACKLIST_SIZE, max_blacklist_size);
+ ret |= nla_put_u32(nl_skb, SLSI_NL_ATTR_MAX_WHITELIST_SIZE, max_whitelist_size);
if (ret) {
- reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
- SLSI_ERR(sdev, "failed to set unsync vif. Cannot start NAN\n");
- } else {
- ret = slsi_mlme_nan_enable(sdev, dev, &hal_req);
- if (ret) {
- SLSI_ERR(sdev, "failed to enable NAN.\n");
- reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
- slsi_mlme_del_vif(sdev, dev);
- ndev_vif->activated = false;
- ndev_vif->nan.subscribe_id_map = 0;
- ndev_vif->nan.publish_id_map = 0;
- } else {
- slsi_vif_activated(sdev, dev);
- }
+ SLSI_ERR(sdev, "Error in nla_put*:%x\n", ret);
+ /* Dont use slsi skb wrapper for this free */
+ kfree_skb(nl_skb);
+ goto exit_with_mib_resp;
}
-exit_with_mutex:
- SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+ ret = cfg80211_vendor_cmd_reply(nl_skb);
+ if (ret)
+ SLSI_ERR(sdev, "cfg80211_vendor_cmd_reply failed :%d\n", ret);
+exit_with_mib_resp:
+ kfree(mibrsp.data);
+ kfree(values);
exit:
- slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_ENABLED, 0, NULL);
+ SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
return ret;
}
-static int slsi_nan_disable(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
+static int slsi_set_roaming_state(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
{
- struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
- struct net_device *dev = slsi_nan_get_netdev(sdev);
- struct netdev_vif *ndev_vif;
+ struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+ struct net_device *dev = wdev->netdev;
+ int temp = 0;
+ int type = 0;
+ const struct nlattr *attr;
+ int ret = 0;
+ int roam_state = 0;
- if (dev) {
- ndev_vif = netdev_priv(dev);
- SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
- if (ndev_vif->activated) {
- slsi_mlme_del_vif(sdev, dev);
- ndev_vif->activated = false;
- ndev_vif->nan.subscribe_id_map = 0;
- ndev_vif->nan.publish_id_map = 0;
- } else {
- SLSI_WARN(sdev, "NAN FWif not active!!");
- }
- SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
- } else {
- SLSI_WARN(sdev, "No NAN interface!!");
+ if (!dev) {
+ SLSI_WARN_NODEV("net_dev is NULL\n");
+ return -EINVAL;
}
- slsi_vendor_nan_command_reply(wiphy, SLSI_HAL_NAN_STATUS_SUCCESS, 0, NAN_RESPONSE_DISABLED, 0, NULL);
-
- return 0;
-}
-
-static int slsi_nan_publish_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_publish_req *hal_req,
- const void *data, int len)
-{
- int type, tmp;
- const struct nlattr *iter;
-
- memset(hal_req, 0, sizeof(*hal_req));
- nla_for_each_attr(iter, data, len, tmp) {
- type = nla_type(iter);
+ nla_for_each_attr(attr, data, len, temp) {
+ type = nla_type(attr);
switch (type) {
- case NAN_REQ_ATTR_PUBLISH_ID:
- hal_req->publish_id = nla_get_u16(iter);
- break;
- case NAN_REQ_ATTR_PUBLISH_TTL:
- hal_req->ttl = nla_get_u16(iter);
- break;
-
- case NAN_REQ_ATTR_PUBLISH_PERIOD:
- hal_req->period = nla_get_u16(iter);
- break;
-
- case NAN_REQ_ATTR_PUBLISH_TYPE:
- hal_req->publish_type = nla_get_u16(iter);
+ case SLSI_NL_ATTR_ROAM_STATE:
+ roam_state = nla_get_u8(attr);
break;
+ default:
+ SLSI_ERR_NODEV("Unknown attribute: %d\n", type);
+ ret = -EINVAL;
+ goto exit;
+ }
+ }
- case NAN_REQ_ATTR_PUBLISH_TX_TYPE:
- hal_req->tx_type = nla_get_u16(iter);
- break;
+ SLSI_DBG1_NODEV(SLSI_GSCAN, "SUBCMD_SET_ROAMING_STATE roam_state = %d\n", roam_state);
+ ret = slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAMING_ENABLED, roam_state);
+ if (ret < 0)
+ SLSI_ERR_NODEV("Failed to set roaming state\n");
- case NAN_REQ_ATTR_PUBLISH_COUNT:
- hal_req->publish_count = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_PUBLISH_SERVICE_NAME_LEN:
- hal_req->service_name_len = nla_get_u16(iter);
- break;
-
- case NAN_REQ_ATTR_PUBLISH_SERVICE_NAME:
- memcpy(hal_req->service_name, nla_data(iter), hal_req->service_name_len);
- break;
-
- case NAN_REQ_ATTR_PUBLISH_MATCH_ALGO:
- hal_req->publish_match_indicator = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_PUBLISH_SERVICE_INFO_LEN:
- hal_req->service_specific_info_len = nla_get_u16(iter);
- break;
-
- case NAN_REQ_ATTR_PUBLISH_SERVICE_INFO:
- memcpy(hal_req->service_specific_info, nla_data(iter), hal_req->service_specific_info_len);
- break;
-
- case NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER_LEN:
- hal_req->rx_match_filter_len = nla_get_u16(iter);
- break;
-
- case NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER:
- memcpy(hal_req->rx_match_filter, nla_data(iter), hal_req->rx_match_filter_len);
- break;
-
- case NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER_LEN:
- hal_req->tx_match_filter_len = nla_get_u16(iter);
- break;
-
- case NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER:
- memcpy(hal_req->tx_match_filter, nla_data(iter), hal_req->tx_match_filter_len);
- break;
-
- case NAN_REQ_ATTR_PUBLISH_RSSI_THRESHOLD_FLAG:
- hal_req->rssi_threshold_flag = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_PUBLISH_CONN_MAP:
- hal_req->connmap = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_PUBLISH_RECV_IND_CFG:
- hal_req->recv_indication_cfg = nla_get_u8(iter);
- break;
-
- default:
- SLSI_ERR(sdev, "Unexpected NAN publish attribute TYPE:%d\n", type);
- return SLSI_HAL_NAN_STATUS_INVALID_PARAM;
- }
- }
- return SLSI_HAL_NAN_STATUS_SUCCESS;
-}
-
-static int slsi_nan_publish(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
-{
- struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
- struct slsi_hal_nan_publish_req hal_req;
- struct net_device *dev = slsi_nan_get_netdev(sdev);
- struct netdev_vif *ndev_vif;
- int ret;
- u32 reply_status;
- u32 publish_id = 0;
-
- if (!dev) {
- SLSI_ERR(sdev, "NAN netif not active!!");
- ret = -EINVAL;
- reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
- goto exit;
- }
-
- ndev_vif = netdev_priv(dev);
- reply_status = slsi_nan_publish_get_nl_params(sdev, &hal_req, data, len);
- if (reply_status != SLSI_HAL_NAN_STATUS_SUCCESS) {
- ret = -EINVAL;
- goto exit;
- }
-
- SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
-
- if (!ndev_vif->activated) {
- SLSI_WARN(sdev, "NAN vif not activated\n");
- reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
- ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
- goto exit_with_lock;
- }
-
- if (!hal_req.publish_id) {
- hal_req.publish_id = slsi_nan_get_new_publish_id(ndev_vif);
- } else if (!slsi_nan_is_publish_id_active(ndev_vif, hal_req.publish_id)) {
- SLSI_WARN(sdev, "Publish id %d not found. map:%x\n", hal_req.publish_id,
- ndev_vif->nan.publish_id_map);
- reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
- ret = -EINVAL;
- goto exit_with_lock;
- }
-
- if (hal_req.publish_id) {
- ret = slsi_mlme_nan_publish(sdev, dev, &hal_req, hal_req.publish_id);
- if (ret)
- reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
- else
- publish_id = hal_req.publish_id;
- } else {
- reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
- SLSI_WARN(sdev, "Too Many concurrent PUBLISH REQ(map:%x)\n",
- ndev_vif->nan.publish_id_map);
- ret = -ENOTSUPP;
- }
-exit_with_lock:
- SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
-exit:
- slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_PUBLISH, publish_id, NULL);
- return ret;
-}
-
-static int slsi_nan_publish_cancel(struct wiphy *wiphy, struct wireless_dev *wdev,
- const void *data, int len)
-{
- struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
- struct net_device *dev = slsi_nan_get_netdev(sdev);
- struct netdev_vif *ndev_vif;
- int type, tmp, ret = 0;
- u16 publish_id = 0;
- const struct nlattr *iter;
- u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
-
- if (!dev) {
- SLSI_ERR(sdev, "NAN netif not active!!");
- reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
- ret = -EINVAL;
- goto exit;
- }
-
- ndev_vif = netdev_priv(dev);
- nla_for_each_attr(iter, data, len, tmp) {
- type = nla_type(iter);
- switch (type) {
- case NAN_REQ_ATTR_PUBLISH_ID:
- publish_id = nla_get_u16(iter);
- break;
- default:
- SLSI_ERR(sdev, "Unexpected NAN publishcancel attribute TYPE:%d\n", type);
- }
- }
-
- SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
- if (!ndev_vif->activated) {
- reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
- ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
- goto exit_with_lock;
- }
- if (!publish_id || !slsi_nan_is_publish_id_active(ndev_vif, publish_id)) {
- reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
- SLSI_WARN(sdev, "Publish_id(%d) not active. map:%x\n",
- publish_id, ndev_vif->nan.publish_id_map);
- } else {
- ret = slsi_mlme_nan_publish(sdev, dev, NULL, publish_id);
- if (ret)
- reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
- }
-exit_with_lock:
- SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
-exit:
- slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_PUBLISH_CANCEL, publish_id, NULL);
- return ret;
-}
-
-static int slsi_nan_subscribe_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_subscribe_req *hal_req,
- const void *data, int len)
-{
- int type, tmp;
- const struct nlattr *iter;
-
- memset(hal_req, 0, sizeof(*hal_req));
- nla_for_each_attr(iter, data, len, tmp) {
- type = nla_type(iter);
- switch (type) {
- case NAN_REQ_ATTR_SUBSCRIBE_ID:
- hal_req->subscribe_id = nla_get_u16(iter);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_TTL:
- hal_req->ttl = nla_get_u16(iter);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_PERIOD:
- hal_req->period = nla_get_u16(iter);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_TYPE:
- hal_req->subscribe_type = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_RESP_FILTER_TYPE:
- hal_req->service_response_filter = nla_get_u16(iter);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_RESP_INCLUDE:
- hal_req->service_response_include = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_USE_RESP_FILTER:
- hal_req->use_service_response_filter = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_SSI_REQUIRED:
- hal_req->ssi_required_for_match_indication = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_MATCH_INDICATOR:
- hal_req->subscribe_match_indicator = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_COUNT:
- hal_req->subscribe_count = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME_LEN:
- hal_req->service_name_len = nla_get_u16(iter);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME:
- memcpy(hal_req->service_name, nla_data(iter), hal_req->service_name_len);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO_LEN:
- hal_req->service_specific_info_len = nla_get_u16(iter);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO:
- memcpy(hal_req->service_specific_info, nla_data(iter), hal_req->service_specific_info_len);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER_LEN:
- hal_req->rx_match_filter_len = nla_get_u16(iter);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER:
- memcpy(hal_req->rx_match_filter, nla_data(iter), hal_req->rx_match_filter_len);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER_LEN:
- hal_req->tx_match_filter_len = nla_get_u16(iter);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER:
- memcpy(hal_req->tx_match_filter, nla_data(iter), hal_req->tx_match_filter_len);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_RSSI_THRESHOLD_FLAG:
- hal_req->rssi_threshold_flag = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_CONN_MAP:
- hal_req->connmap = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_NUM_INTF_ADDR_PRESENT:
- hal_req->num_intf_addr_present = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_INTF_ADDR:
- memcpy(hal_req->intf_addr, nla_data(iter), hal_req->num_intf_addr_present * ETH_ALEN);
- break;
-
- case NAN_REQ_ATTR_SUBSCRIBE_RECV_IND_CFG:
- hal_req->recv_indication_cfg = nla_get_u8(iter);
- break;
-
- default:
- SLSI_ERR(sdev, "Unexpected NAN subscribe attribute TYPE:%d\n", type);
- return SLSI_HAL_NAN_STATUS_INVALID_PARAM;
- }
- }
- return SLSI_HAL_NAN_STATUS_SUCCESS;
-}
-
-static int slsi_nan_subscribe(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
-{
- struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
- struct net_device *dev = slsi_nan_get_netdev(sdev);
- struct netdev_vif *ndev_vif;
- struct slsi_hal_nan_subscribe_req *hal_req;
- int ret;
- u32 reply_status;
- u32 subscribe_id = 0;
-
- if (!dev) {
- SLSI_ERR(sdev, "NAN netif not active!!\n");
- reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
- ret = -EINVAL;
- goto exit;
- }
-
- hal_req = kmalloc(sizeof(*hal_req), GFP_KERNEL);
- if (!hal_req) {
- SLSI_ERR(sdev, "Failed to alloc hal_req structure!!!\n");
- reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE;
- ret = -ENOMEM;
- goto exit;
- }
-
- ndev_vif = netdev_priv(dev);
- reply_status = slsi_nan_subscribe_get_nl_params(sdev, hal_req, data, len);
- if (reply_status != SLSI_HAL_NAN_STATUS_SUCCESS) {
- kfree(hal_req);
- ret = -EINVAL;
- goto exit;
- }
-
- SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
- if (!ndev_vif->activated) {
- SLSI_WARN(sdev, "NAN vif not activated\n");
- reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
- ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
- goto exit_with_lock;
- }
-
- if (!hal_req->subscribe_id) {
- hal_req->subscribe_id = slsi_nan_get_new_subscribe_id(ndev_vif);
- } else if (!slsi_nan_is_subscribe_id_active(ndev_vif, hal_req->subscribe_id)) {
- SLSI_WARN(sdev, "Subscribe id %d not found. map:%x\n", hal_req->subscribe_id,
- ndev_vif->nan.subscribe_id_map);
- reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
- ret = -EINVAL;
- goto exit_with_lock;
- }
-
- ret = slsi_mlme_nan_subscribe(sdev, dev, hal_req, hal_req->subscribe_id);
- if (ret)
- reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
- else
- subscribe_id = hal_req->subscribe_id;
-
-exit_with_lock:
- SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
- kfree(hal_req);
-exit:
- slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_SUBSCRIBE, subscribe_id, NULL);
- return ret;
-}
-
-static int slsi_nan_subscribe_cancel(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
-{
- struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
- struct net_device *dev = slsi_nan_get_netdev(sdev);
- struct netdev_vif *ndev_vif;
- int type, tmp, ret = WIFI_HAL_ERROR_UNKNOWN;
- u16 subscribe_id = 0;
- const struct nlattr *iter;
- u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
-
- if (!dev) {
- SLSI_ERR(sdev, "NAN netif not active!!");
- reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
- ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
- goto exit;
- }
-
- ndev_vif = netdev_priv(dev);
-
- nla_for_each_attr(iter, data, len, tmp) {
- type = nla_type(iter);
- switch (type) {
- case NAN_REQ_ATTR_SUBSCRIBE_ID:
- subscribe_id = nla_get_u16(iter);
- break;
- default:
- SLSI_ERR(sdev, "Unexpected NAN subscribecancel attribute TYPE:%d\n", type);
- reply_status = SLSI_HAL_NAN_STATUS_INVALID_PARAM;
- goto exit;
- }
- }
-
- SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
- if (ndev_vif->activated) {
- if (!subscribe_id || !slsi_nan_is_subscribe_id_active(ndev_vif, subscribe_id)) {
- SLSI_WARN(sdev, "subscribe_id(%d) not active. map:%x\n",
- subscribe_id, ndev_vif->nan.subscribe_id_map);
- reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
- } else {
- ret = slsi_mlme_nan_subscribe(sdev, dev, NULL, subscribe_id);
- if (ret)
- reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
- }
- } else {
- SLSI_ERR(sdev, "vif not activated\n");
- reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
- ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
- }
- SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
-exit:
- slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_SUBSCRIBE_CANCEL, subscribe_id, NULL);
- return ret;
-}
-
-static int slsi_nan_followup_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_transmit_followup_req *hal_req,
- const void *data, int len)
-{
- int type, tmp;
- const struct nlattr *iter;
-
- memset(hal_req, 0, sizeof(*hal_req));
- nla_for_each_attr(iter, data, len, tmp) {
- type = nla_type(iter);
- switch (type) {
- case NAN_REQ_ATTR_FOLLOWUP_ID:
- hal_req->publish_subscribe_id = nla_get_u16(iter);
- break;
-
- case NAN_REQ_ATTR_FOLLOWUP_REQUESTOR_ID:
- hal_req->requestor_instance_id = nla_get_u32(iter);
- break;
-
- case NAN_REQ_ATTR_FOLLOWUP_ADDR:
- memcpy(hal_req->addr, nla_data(iter), ETH_ALEN);
- break;
-
- case NAN_REQ_ATTR_FOLLOWUP_PRIORITY:
- hal_req->priority = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_FOLLOWUP_TX_WINDOW:
- hal_req->dw_or_faw = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME_LEN:
- hal_req->service_specific_info_len = nla_get_u16(iter);
- break;
-
- case NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME:
- memcpy(hal_req->service_specific_info, nla_data(iter), hal_req->service_specific_info_len);
- break;
-
- case NAN_REQ_ATTR_FOLLOWUP_RECV_IND_CFG:
- hal_req->recv_indication_cfg = nla_get_u8(iter);
- break;
-
- default:
- SLSI_ERR(sdev, "Unexpected NAN followup attribute TYPE:%d\n", type);
- return SLSI_HAL_NAN_STATUS_INVALID_PARAM;
- }
- }
- return SLSI_HAL_NAN_STATUS_SUCCESS;
-}
-
-static int slsi_nan_transmit_followup(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
-{
- struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
- struct net_device *dev = slsi_nan_get_netdev(sdev);
- struct netdev_vif *ndev_vif;
- struct slsi_hal_nan_transmit_followup_req hal_req;
- int ret;
- u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
-
- if (!dev) {
- SLSI_ERR(sdev, "NAN netif not active!!");
- ret = -EINVAL;
- reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
- goto exit;
- }
-
- ndev_vif = netdev_priv(dev);
- reply_status = slsi_nan_followup_get_nl_params(sdev, &hal_req, data, len);
- if (reply_status) {
- ret = -EINVAL;
- goto exit;
- }
-
- SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
- if (!ndev_vif->activated) {
- SLSI_WARN(sdev, "NAN vif not activated\n");
- reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
- ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
- goto exit_with_lock;
- }
-
- if (!hal_req.publish_subscribe_id ||
- !(slsi_nan_is_subscribe_id_active(ndev_vif, hal_req.publish_subscribe_id) ||
- slsi_nan_is_publish_id_active(ndev_vif, hal_req.publish_subscribe_id))) {
- SLSI_WARN(sdev, "publish/Subscribe id %d not found. map:%x\n", hal_req.publish_subscribe_id,
- ndev_vif->nan.subscribe_id_map);
- reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
- ret = -EINVAL;
- goto exit_with_lock;
- }
-
- ret = slsi_mlme_nan_tx_followup(sdev, dev, &hal_req);
- if (ret)
- reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
-
-exit_with_lock:
- SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
-exit:
- slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_TRANSMIT_FOLLOWUP, 0, NULL);
- return ret;
-}
-
-static int slsi_nan_config_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_config_req *hal_req,
- const void *data, int len)
-{
- int type, type1, tmp, tmp1, disc_attr_idx = 0, famchan_idx = 0;
- const struct nlattr *iter, *iter1;
- struct slsi_hal_nan_post_discovery_param *disc_attr;
- struct slsi_hal_nan_further_availability_channel *famchan;
-
- memset(hal_req, 0, sizeof(*hal_req));
- nla_for_each_attr(iter, data, len, tmp) {
- type = nla_type(iter);
- switch (type) {
- case NAN_REQ_ATTR_SID_BEACON_VAL:
- hal_req->sid_beacon = nla_get_u8(iter);
- hal_req->config_sid_beacon = 1;
- break;
-
- case NAN_REQ_ATTR_RSSI_PROXIMITY_2G4_VAL:
- hal_req->rssi_proximity = nla_get_u8(iter);
- hal_req->config_rssi_proximity = 1;
- break;
-
- case NAN_REQ_ATTR_MASTER_PREF:
- hal_req->master_pref = nla_get_u8(iter);
- hal_req->config_master_pref = 1;
- break;
-
- case NAN_REQ_ATTR_RSSI_CLOSE_PROXIMITY_5G_VAL:
- hal_req->rssi_close_proximity_5g_val = nla_get_u8(iter);
- hal_req->config_5g_rssi_close_proximity = 1;
- break;
-
- case NAN_REQ_ATTR_RSSI_WINDOW_SIZE_VAL:
- hal_req->rssi_window_size_val = nla_get_u8(iter);
- hal_req->config_rssi_window_size = 1;
- break;
-
- case NAN_REQ_ATTR_CLUSTER_VAL:
- hal_req->config_cluster_attribute_val = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_SOCIAL_CH_SCAN_DWELL_TIME:
- memcpy(hal_req->scan_params_val.dwell_time, nla_data(iter),
- sizeof(hal_req->scan_params_val.dwell_time));
- hal_req->config_scan_params = 1;
- break;
-
- case NAN_REQ_ATTR_SOCIAL_CH_SCAN_PERIOD:
- memcpy(hal_req->scan_params_val.scan_period, nla_data(iter),
- sizeof(hal_req->scan_params_val.scan_period));
- hal_req->config_scan_params = 1;
- break;
-
- case NAN_REQ_ATTR_RANDOM_FACTOR_FORCE_VAL:
- hal_req->random_factor_force_val = nla_get_u8(iter);
- hal_req->config_random_factor_force = 1;
- break;
-
- case NAN_REQ_ATTR_HOP_COUNT_FORCE_VAL:
- hal_req->hop_count_force_val = nla_get_u8(iter);
- hal_req->config_hop_count_force = 1;
- break;
-
- case NAN_REQ_ATTR_CONN_CAPABILITY_PAYLOAD_TX:
- hal_req->conn_capability_val.payload_transmit_flag = nla_get_u8(iter);
- hal_req->config_conn_capability = 1;
- break;
-
- case NAN_REQ_ATTR_CONN_CAPABILITY_WFD:
- hal_req->conn_capability_val.is_wfd_supported = nla_get_u8(iter);
- hal_req->config_conn_capability = 1;
- break;
-
- case NAN_REQ_ATTR_CONN_CAPABILITY_WFDS:
- hal_req->conn_capability_val.is_wfds_supported = nla_get_u8(iter);
- hal_req->config_conn_capability = 1;
- break;
-
- case NAN_REQ_ATTR_CONN_CAPABILITY_TDLS:
- hal_req->conn_capability_val.is_tdls_supported = nla_get_u8(iter);
- hal_req->config_conn_capability = 1;
- break;
-
- case NAN_REQ_ATTR_CONN_CAPABILITY_MESH:
- hal_req->conn_capability_val.is_mesh_supported = nla_get_u8(iter);
- hal_req->config_conn_capability = 1;
- break;
-
- case NAN_REQ_ATTR_CONN_CAPABILITY_IBSS:
- hal_req->conn_capability_val.is_ibss_supported = nla_get_u8(iter);
- hal_req->config_conn_capability = 1;
- break;
-
- case NAN_REQ_ATTR_CONN_CAPABILITY_WLAN_INFRA:
- hal_req->conn_capability_val.wlan_infra_field = nla_get_u8(iter);
- hal_req->config_conn_capability = 1;
- break;
-
- case NAN_REQ_ATTR_DISCOVERY_ATTR_NUM_ENTRIES:
- hal_req->num_config_discovery_attr = nla_get_u8(iter);
- break;
-
- case NAN_REQ_ATTR_DISCOVERY_ATTR_VAL:
- if (disc_attr_idx >= hal_req->num_config_discovery_attr) {
- SLSI_ERR(sdev,
- "disc attr(%d) > num disc attr(%d)\n",
- disc_attr_idx + 1, hal_req->num_config_discovery_attr);
- return -EINVAL;
- }
- disc_attr = &hal_req->discovery_attr_val[disc_attr_idx];
- disc_attr_idx++;
- nla_for_each_nested(iter1, iter, tmp1) {
- type1 = nla_type(iter1);
- switch (type1) {
- case NAN_REQ_ATTR_CONN_TYPE:
- disc_attr->type = nla_get_u8(iter1);
- break;
-
- case NAN_REQ_ATTR_NAN_ROLE:
- disc_attr->role = nla_get_u8(iter1);
- break;
-
- case NAN_REQ_ATTR_TRANSMIT_FREQ:
- disc_attr->transmit_freq = nla_get_u8(iter1);
- break;
-
- case NAN_REQ_ATTR_AVAILABILITY_DURATION:
- disc_attr->duration = nla_get_u8(iter1);
- break;
-
- case NAN_REQ_ATTR_AVAILABILITY_INTERVAL:
- disc_attr->avail_interval_bitmap = nla_get_u32(iter1);
- break;
-
- case NAN_REQ_ATTR_MAC_ADDR_VAL:
- memcpy(disc_attr->addr, nla_data(iter1), ETH_ALEN);
- break;
-
- case NAN_REQ_ATTR_MESH_ID_LEN:
- disc_attr->mesh_id_len = nla_get_u16(iter1);
- break;
-
- case NAN_REQ_ATTR_MESH_ID:
- memcpy(disc_attr->mesh_id, nla_data(iter1), disc_attr->mesh_id_len);
- break;
-
- case NAN_REQ_ATTR_INFRASTRUCTURE_SSID_LEN:
- disc_attr->infrastructure_ssid_len = nla_get_u16(iter1);
- break;
-
- case NAN_REQ_ATTR_INFRASTRUCTURE_SSID:
- memcpy(disc_attr->infrastructure_ssid_val, nla_data(iter1),
- disc_attr->infrastructure_ssid_len);
- break;
- }
- }
- break;
-
- case NAN_REQ_ATTR_FURTHER_AVAIL_NUM_ENTRIES:
- hal_req->fam_val.numchans = nla_get_u8(iter);
- hal_req->config_fam = 1;
- break;
-
- case NAN_REQ_ATTR_FURTHER_AVAIL_VAL:
- hal_req->config_fam = 1;
- if (famchan_idx >= hal_req->fam_val.numchans) {
- SLSI_ERR(sdev,
- "famchan attr(%d) > numchans(%d)\n",
- famchan_idx + 1, hal_req->fam_val.numchans);
- return -EINVAL;
- }
- famchan = &hal_req->fam_val.famchan[famchan_idx];
- famchan_idx++;
- nla_for_each_nested(iter1, iter, tmp1) {
- type1 = nla_type(iter1);
- switch (type1) {
- case NAN_REQ_ATTR_FURTHER_AVAIL_ENTRY_CTRL:
- famchan->entry_control = nla_get_u8(iter1);
- break;
-
- case NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_CLASS:
- famchan->class_val = nla_get_u8(iter1);
- break;
-
- case NAN_REQ_ATTR_FURTHER_AVAIL_CHAN:
- famchan->channel = nla_get_u8(iter1);
- break;
-
- case NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_MAPID:
- famchan->mapid = nla_get_u8(iter1);
- break;
-
- case NAN_REQ_ATTR_FURTHER_AVAIL_INTERVAL_BITMAP:
- famchan->avail_interval_bitmap = nla_get_u32(iter1);
- break;
- }
- }
- break;
- default:
- SLSI_ERR(sdev, "Unexpected NAN config attribute TYPE:%d\n", type);
- return SLSI_HAL_NAN_STATUS_INVALID_PARAM;
- }
- }
- return SLSI_HAL_NAN_STATUS_SUCCESS;
-}
-
-static int slsi_nan_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
-{
- struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
- struct net_device *dev = slsi_nan_get_netdev(sdev);
- struct netdev_vif *ndev_vif;
- struct slsi_hal_nan_config_req hal_req;
- int ret;
- u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
-
- if (!dev) {
- SLSI_ERR(sdev, "NAN netif not active!!");
- ret = -EINVAL;
- reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
- goto exit;
- }
-
- ndev_vif = netdev_priv(dev);
- reply_status = slsi_nan_config_get_nl_params(sdev, &hal_req, data, len);
- if (reply_status) {
- ret = -EINVAL;
- goto exit;
- }
-
- SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
- if (!ndev_vif->activated) {
- SLSI_WARN(sdev, "NAN vif not activated\n");
- reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
- ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
- } else {
- ret = slsi_mlme_nan_set_config(sdev, dev, &hal_req);
- if (ret)
- reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
- }
- SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
-exit:
- slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_CONFIG, 0, NULL);
- return ret;
-}
-
-static int slsi_nan_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data,
- int len)
-{
- struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
- struct net_device *dev = slsi_nan_get_netdev(sdev);
- struct netdev_vif *ndev_vif;
- u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
- struct slsi_hal_nan_capabilities nan_capabilities;
- int ret = 0, i;
- struct slsi_mib_value *values = NULL;
- struct slsi_mib_data mibrsp = { 0, NULL };
- struct slsi_mib_get_entry get_values[] = {{ SLSI_PSID_UNIFI_NAN_MAX_CONCURRENT_CLUSTERS, { 0, 0 } },
- { SLSI_PSID_UNIFI_NAN_MAX_CONCURRENT_PUBLISHES, { 0, 0 } },
- { SLSI_PSID_UNIFI_NAN_MAX_CONCURRENT_SUBSCRIBES, { 0, 0 } },
- { SLSI_PSID_UNIFI_NAN_MAX_SERVICE_NAME_LENGTH, { 0, 0 } },
- { SLSI_PSID_UNIFI_NAN_MAX_MATCH_FILTER_LENGTH, { 0, 0 } },
- { SLSI_PSID_UNIFI_NAN_MAX_TOTAL_MATCH_FILTER_LENGTH, { 0, 0 } },
- { SLSI_PSID_UNIFI_NAN_MAX_SERVICE_SPECIFIC_INFO_LENGTH, { 0, 0 } },
- { SLSI_PSID_UNIFI_NAN_MAX_VSA_DATA_LENGTH, { 0, 0 } },
- { SLSI_PSID_UNIFI_NAN_MAX_MESH_DATA_LENGTH, { 0, 0 } },
- { SLSI_PSID_UNIFI_NAN_MAX_NDI_INTERFACES, { 0, 0 } },
- { SLSI_PSID_UNIFI_NAN_MAX_NDP_SESSIONS, { 0, 0 } },
- { SLSI_PSID_UNIFI_NAN_MAX_APP_INFO_LENGTH, { 0, 0 } } };
- u32 *capabilities_mib_val[] = { &nan_capabilities.max_concurrent_nan_clusters,
- &nan_capabilities.max_publishes,
- &nan_capabilities.max_subscribes,
- &nan_capabilities.max_service_name_len,
- &nan_capabilities.max_match_filter_len,
- &nan_capabilities.max_total_match_filter_len,
- &nan_capabilities.max_service_specific_info_len,
- &nan_capabilities.max_vsa_data_len,
- &nan_capabilities.max_mesh_data_len,
- &nan_capabilities.max_ndi_interfaces,
- &nan_capabilities.max_ndp_sessions,
- &nan_capabilities.max_app_info_len };
-
- if (!dev) {
- SLSI_ERR(sdev, "NAN netif not active!!");
- reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
- ret = -EINVAL;
- goto exit;
- }
-
- ndev_vif = netdev_priv(dev);
-
- /* Expect each mib length in response is 11 */
- mibrsp.dataLength = 11 * ARRAY_SIZE(get_values);
- mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL);
- if (!mibrsp.data) {
- SLSI_ERR(sdev, "Cannot kmalloc %d bytes\n", mibrsp.dataLength);
- reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE;
- ret = -ENOMEM;
- goto exit;
- }
-
- SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
-
- values = slsi_read_mibs(sdev, NULL, get_values, ARRAY_SIZE(get_values), &mibrsp);
- if (!values) {
- ret = 0xFFFFFFFF;
- reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
- goto exit_with_mibrsp;
- }
-
- for (i = 0; i < ARRAY_SIZE(get_values); i++) {
- if (values[i].type == SLSI_MIB_TYPE_UINT) {
- *capabilities_mib_val[i] = values[i].u.uintValue;
- SLSI_DBG2(sdev, SLSI_GSCAN, "MIB value = %ud\n", *capabilities_mib_val[i]);
- } else {
- SLSI_ERR(sdev, "invalid type(%d). iter:%d\n", values[i].type, i);
- ret = 0xFFFFFFFF;
- reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
- *capabilities_mib_val[i] = 0;
- }
- }
-
- kfree(values);
-exit_with_mibrsp:
- kfree(mibrsp.data);
- SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
-exit:
- slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_GET_CAPABILITIES, 0, &nan_capabilities);
- return ret;
-}
-
-void slsi_nan_event(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb)
-{
- struct sk_buff *nl_skb = NULL;
- int res = 0;
- u16 event, identifier, evt_reason;
- u8 *mac_addr;
- u16 hal_event;
- struct nlattr *nlattr_start;
- struct netdev_vif *ndev_vif;
- enum slsi_nan_disc_event_type disc_event_type = 0;
-
- ndev_vif = netdev_priv(dev);
- event = fapi_get_u16(skb, u.mlme_nan_event_ind.event);
- identifier = fapi_get_u16(skb, u.mlme_nan_event_ind.identifier);
- mac_addr = fapi_get_buff(skb, u.mlme_nan_event_ind.address_or_identifier);
- evt_reason = fapi_get_u16(skb, u.mlme_nan_event_ind.reason_code);
-
- switch (event) {
- case FAPI_EVENT_WIFI_EVENT_NAN_PUBLISH_TERMINATED:
- hal_event = SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT;
- break;
- case FAPI_EVENT_WIFI_EVENT_NAN_MATCH_EXPIRED:
- hal_event = SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT;
- break;
- case FAPI_EVENT_WIFI_EVENT_NAN_SUBSCRIBE_TERMINATED:
- hal_event = SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT;
- break;
- case FAPI_EVENT_WIFI_EVENT_NAN_ADDRESS_CHANGED:
- disc_event_type = NAN_EVENT_ID_DISC_MAC_ADDR;
- hal_event = SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT;
- break;
- case FAPI_EVENT_WIFI_EVENT_NAN_CLUSTER_STARTED:
- disc_event_type = NAN_EVENT_ID_STARTED_CLUSTER;
- hal_event = SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT;
- break;
- case FAPI_EVENT_WIFI_EVENT_NAN_CLUSTER_JOINED:
- disc_event_type = NAN_EVENT_ID_JOINED_CLUSTER;
- hal_event = SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT;
- break;
- default:
- return;
- }
-
-#ifdef CONFIG_SCSC_WLAN_DEBUG
- SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n",
- slsi_print_event_name(hal_event), hal_event);
-#endif
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
- nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, hal_event, GFP_KERNEL);
-#else
- nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, hal_event, GFP_KERNEL);
-#endif
- if (!nl_skb) {
- SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n");
- return;
- }
-
- nlattr_start = nla_nest_start(nl_skb, NL80211_ATTR_VENDOR_DATA);
- if (!nlattr_start) {
- SLSI_ERR(sdev, "failed to put NL80211_ATTR_VENDOR_DATA\n");
- /* Dont use slsi skb wrapper for this free */
- kfree_skb(nl_skb);
- return;
- }
-
- switch (hal_event) {
- case SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT:
- res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_PUBLISH_ID, identifier);
- res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_PUBLISH_ID, evt_reason);
- ndev_vif->nan.publish_id_map &= ~BIT(identifier);
- break;
- case SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT:
- res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID, identifier);
- res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_MATCH_REQUESTOR_INSTANCE_ID, evt_reason);
- break;
- case SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT:
- res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_SUBSCRIBE_ID, identifier);
- res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_SUBSCRIBE_REASON, evt_reason);
- ndev_vif->nan.subscribe_id_map &= ~BIT(identifier);
- break;
- case SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT:
- res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_DISCOVERY_ENGINE_EVT_TYPE, disc_event_type);
- res |= nla_put(nl_skb, NAN_EVT_ATTR_DISCOVERY_ENGINE_MAC_ADDR, ETH_ALEN, mac_addr);
- break;
- }
-
- if (res) {
- SLSI_ERR(sdev, "Error in nla_put*:%x\n", res);
- /* Dont use slsi skb wrapper for this free */
- kfree_skb(nl_skb);
- return;
- }
-
- nla_nest_end(nl_skb, nlattr_start);
-
- cfg80211_vendor_event(nl_skb, GFP_KERNEL);
-}
-
-void slsi_nan_followup_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb)
-{
- u16 tag_id, tag_len;
- u8 *fapi_data_p, *ptr;
- u8 followup_ie_header[] = {0xdd, 0, 0, 0x16, 0x32, 0x0b, 0x05};
- int fapi_data_len;
- struct slsi_hal_nan_followup_ind *hal_evt;
- struct sk_buff *nl_skb;
- int res;
- struct nlattr *nlattr_start;
-
- hal_evt = kmalloc(sizeof(*hal_evt), GFP_KERNEL);
- if (!hal_evt) {
- SLSI_ERR(sdev, "No memory for service_ind\n");
- return;
- }
- hal_evt->publish_subscribe_id = fapi_get_u16(skb, u.mlme_nan_followup_ind.publish_subscribe_id);
- hal_evt->requestor_instance_id = fapi_get_u16(skb, u.mlme_nan_followup_ind.requestor_instance_id);
- fapi_data_p = fapi_get_data(skb);
- fapi_data_len = fapi_get_datalen(skb);
- if (!fapi_data_len) {
- SLSI_ERR(sdev, "mlme_nan_followup_ind no mbulk data\n");
- kfree(hal_evt);
- return;
- }
-
- memset(&hal_evt, 0, sizeof(hal_evt));
-
- while (fapi_data_len) {
- ptr = fapi_data_p;
- if (fapi_data_len < ptr[1] + 2) {
- SLSI_ERR(sdev, "len err[avail:%d,ie:%d]\n", fapi_data_len, fapi_data_p[1] + 2);
- kfree(hal_evt);
- return;
- }
- if (ptr[1] < sizeof(followup_ie_header) - 2 + 6 + 1 + 1) {
- SLSI_ERR(sdev, "len err[min:%d,ie:%d]\n", (u32)sizeof(followup_ie_header) - 2 + 6 + 1 + 1,
- fapi_data_p[1] + 2);
- kfree(hal_evt);
- return;
- }
- if (followup_ie_header[0] != ptr[0] || followup_ie_header[2] != ptr[2] ||
- followup_ie_header[3] != ptr[3] || followup_ie_header[4] != ptr[4] ||
- followup_ie_header[5] != ptr[5] || followup_ie_header[6] != ptr[6]) {
- SLSI_ERR(sdev, "unknown IE:%x-%d\n", fapi_data_p[0], fapi_data_p[1] + 2);
- kfree(hal_evt);
- return;
- }
-
- ptr += sizeof(followup_ie_header);
-
- ether_addr_copy(hal_evt->addr, ptr);
- ptr += ETH_ALEN;
- ptr += 1; /* skip priority */
- hal_evt->dw_or_faw = *ptr;
- ptr += 1;
- while (fapi_data_p[1] + 2 > (ptr - fapi_data_p) + 4) {
- tag_id = *(u16 *)ptr;
- ptr += 2;
- tag_len = *(u16 *)ptr;
- ptr += 2;
- if (fapi_data_p[1] + 2 < (ptr - fapi_data_p) + tag_len) {
- SLSI_ERR(sdev, "TLV error\n");
- kfree(hal_evt);
- return;
- }
- if (tag_id == SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO) {
- hal_evt->service_specific_info_len = tag_len;
- memcpy(hal_evt->service_specific_info, ptr, tag_len);
- }
- ptr += tag_len;
- }
-
- fapi_data_p += fapi_data_p[1] + 2;
- fapi_data_len -= fapi_data_p[1] + 2;
- }
-
-#ifdef CONFIG_SCSC_WLAN_DEBUG
- SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n",
- slsi_print_event_name(SLSI_NL80211_NAN_FOLLOWUP_EVENT), SLSI_NL80211_NAN_FOLLOWUP_EVENT);
-#endif
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
- nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_FOLLOWUP_EVENT,
- GFP_KERNEL);
-#else
- nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_FOLLOWUP_EVENT,
- GFP_KERNEL);
-#endif
-
- if (!nl_skb) {
- SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n");
- kfree(hal_evt);
- return;
- }
-
- nlattr_start = nla_nest_start(nl_skb, NL80211_ATTR_VENDOR_DATA);
- if (!nlattr_start) {
- SLSI_ERR(sdev, "failed to put NL80211_ATTR_VENDOR_DATA\n");
- kfree(hal_evt);
- /* Dont use slsi skb wrapper for this free */
- kfree_skb(nl_skb);
- return;
- }
-
- res = nla_put_be16(nl_skb, NAN_EVT_ATTR_FOLLOWUP_PUBLISH_SUBSCRIBE_ID,
- cpu_to_le16(hal_evt->publish_subscribe_id));
- res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_FOLLOWUP_REQUESTOR_INSTANCE_ID,
- cpu_to_le16(hal_evt->requestor_instance_id));
- res |= nla_put(nl_skb, NAN_EVT_ATTR_FOLLOWUP_ADDR, ETH_ALEN, hal_evt->addr);
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_FOLLOWUP_DW_OR_FAW, hal_evt->dw_or_faw);
- res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO_LEN, hal_evt->service_specific_info_len);
- if (hal_evt->service_specific_info_len)
- res |= nla_put(nl_skb, NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO, hal_evt->service_specific_info_len,
- hal_evt->service_specific_info);
-
- if (res) {
- SLSI_ERR(sdev, "Error in nla_put*:%x\n", res);
- kfree(hal_evt);
- /* Dont use slsi skb wrapper for this free */
- kfree_skb(nl_skb);
- return;
- }
-
- nla_nest_end(nl_skb, nlattr_start);
-
- cfg80211_vendor_event(nl_skb, GFP_KERNEL);
- kfree(hal_evt);
-}
-
-void slsi_nan_service_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb)
-{
- u16 tag_id, tag_len;
- u8 *fapi_data_p, *ptr;
- u8 match_ie_header[] = {0xdd, 0, 0, 0x16, 0x32, 0x0b, 0x04};
- int fapi_data_len;
- struct slsi_hal_nan_match_ind *hal_evt;
- struct sk_buff *nl_skb;
- int res, i;
- struct slsi_hal_nan_receive_post_discovery *discovery_attr;
- struct slsi_hal_nan_further_availability_channel *famchan;
- struct nlattr *nlattr_start, *nlattr_nested;
-
- SLSI_DBG3(sdev, SLSI_GSCAN, "\n");
-
- hal_evt = kmalloc(sizeof(*hal_evt), GFP_KERNEL);
- if (!hal_evt) {
- SLSI_ERR(sdev, "No memory for service_ind\n");
- return;
- }
-
- hal_evt->publish_subscribe_id = fapi_get_u16(skb, u.mlme_nan_service_ind.publish_subscribe_id);
- hal_evt->requestor_instance_id = fapi_get_u32(skb, u.mlme_nan_service_ind.requestor_instance_id);
- fapi_data_p = fapi_get_data(skb);
- fapi_data_len = fapi_get_datalen(skb);
- if (!fapi_data_len) {
- SLSI_ERR(sdev, "mlme_nan_followup_ind no mbulk data\n");
- kfree(hal_evt);
- return;
- }
-
- memset(hal_evt, 0, sizeof(*hal_evt));
-
- while (fapi_data_len) {
- ptr = fapi_data_p;
- if (fapi_data_len < ptr[1] + 2) {
- SLSI_ERR(sdev, "len err[avail:%d,ie:%d]\n", fapi_data_len, fapi_data_p[1] + 2);
- kfree(hal_evt);
- return;
- }
- if (ptr[1] < sizeof(match_ie_header) - 2 + 6 + 1 + 1 + 1) {
- SLSI_ERR(sdev, "len err[min:%d,ie:%d]\n", (u32)sizeof(match_ie_header) - 2 + 6 + 1 + 1,
- fapi_data_p[1] + 2);
- kfree(hal_evt);
- return;
- }
- if (match_ie_header[0] != ptr[0] || match_ie_header[2] != ptr[2] ||
- match_ie_header[3] != ptr[3] || match_ie_header[4] != ptr[4] ||
- match_ie_header[5] != ptr[5] || match_ie_header[6] != ptr[6]) {
- SLSI_ERR(sdev, "unknown IE:%x-%d\n", fapi_data_p[0], fapi_data_p[1] + 2);
- kfree(hal_evt);
- return;
- }
-
- ptr += sizeof(match_ie_header);
-
- ether_addr_copy(hal_evt->addr, ptr);
- ptr += ETH_ALEN;
- hal_evt->match_occurred_flag = *ptr;
- ptr += 1;
- hal_evt->out_of_resource_flag = *ptr;
- ptr += 1;
- hal_evt->rssi_value = *ptr;
- ptr += 1;
- while (fapi_data_p[1] + 2 > (ptr - fapi_data_p) + 4) {
- tag_id = *(u16 *)ptr;
- ptr += 2;
- tag_len = *(u16 *)ptr;
- ptr += 2;
- if (fapi_data_p[1] + 2 < (ptr - fapi_data_p) + tag_len) {
- SLSI_ERR(sdev, "TLV error\n");
- kfree(hal_evt);
- return;
- }
- switch (tag_id) {
- case SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO:
- hal_evt->service_specific_info_len = tag_len;
- memcpy(hal_evt->service_specific_info, ptr, tag_len);
- break;
- case SLSI_FAPI_NAN_CONFIG_PARAM_CONNECTION_CAPAB:
- hal_evt->is_conn_capability_valid = 1;
- if (*ptr & BIT(0))
- hal_evt->conn_capability.is_wfd_supported = 1;
- if (*ptr & BIT(1))
- hal_evt->conn_capability.is_wfds_supported = 1;
- if (*ptr & BIT(2))
- hal_evt->conn_capability.is_tdls_supported = 1;
- if (*ptr & BIT(3))
- hal_evt->conn_capability.wlan_infra_field = 1;
- break;
- case SLSI_FAPI_NAN_CONFIG_PARAM_POST_DISCOVER_PARAM:
- discovery_attr = &hal_evt->discovery_attr[hal_evt->num_rx_discovery_attr];
- discovery_attr->type = ptr[0];
- discovery_attr->role = ptr[1];
- discovery_attr->duration = ptr[2];
- discovery_attr->avail_interval_bitmap = le32_to_cpu(*(__le32 *)&ptr[3]);
- ether_addr_copy(discovery_attr->addr, &ptr[7]);
- discovery_attr->infrastructure_ssid_len = ptr[13];
- if (discovery_attr->infrastructure_ssid_len)
- memcpy(discovery_attr->infrastructure_ssid_val, &ptr[14],
- discovery_attr->infrastructure_ssid_len);
- hal_evt->num_rx_discovery_attr++;
- break;
- case SLSI_FAPI_NAN_CONFIG_PARAM_FURTHER_AVAIL_CHANNEL_MAP:
- famchan = &hal_evt->famchan[hal_evt->num_chans];
- famchan->entry_control = ptr[0];
- famchan->class_val = ptr[1];
- famchan->channel = ptr[2];
- famchan->mapid = ptr[3];
- famchan->avail_interval_bitmap = le32_to_cpu(*(__le32 *)&ptr[4]);
- hal_evt->num_chans++;
- break;
- case SLSI_FAPI_NAN_CLUSTER_ATTRIBUTE:
- break;
- }
- ptr += tag_len;
- }
-
- fapi_data_p += fapi_data_p[1] + 2;
- fapi_data_len -= fapi_data_p[1] + 2;
- }
-
-#ifdef CONFIG_SCSC_WLAN_DEBUG
- SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n",
- slsi_print_event_name(SLSI_NL80211_NAN_MATCH_EVENT), SLSI_NL80211_NAN_MATCH_EVENT);
-#endif
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
- nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_MATCH_EVENT,
- GFP_KERNEL);
-#else
- nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_MATCH_EVENT, GFP_KERNEL);
-#endif
- if (!nl_skb) {
- SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n");
- kfree(hal_evt);
- return;
- }
-
- nlattr_start = nla_nest_start(nl_skb, NL80211_ATTR_VENDOR_DATA);
- if (!nlattr_start) {
- SLSI_ERR(sdev, "failed to put NL80211_ATTR_VENDOR_DATA\n");
- kfree(hal_evt);
- /* Dont use slsi skb wrapper for this free */
- kfree_skb(nl_skb);
- return;
- }
-
- res = nla_put_u16(nl_skb, NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID, hal_evt->publish_subscribe_id);
- res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_MATCH_REQUESTOR_INSTANCE_ID, hal_evt->requestor_instance_id);
- res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_ADDR, ETH_ALEN, hal_evt->addr);
- res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO_LEN, hal_evt->service_specific_info_len);
- if (hal_evt->service_specific_info_len)
- res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO, hal_evt->service_specific_info_len,
- hal_evt->service_specific_info);
- res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER_LEN, hal_evt->sdf_match_filter_len);
- if (hal_evt->sdf_match_filter_len)
- res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER, hal_evt->sdf_match_filter_len,
- hal_evt->sdf_match_filter);
-
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_MATCH_OCCURRED_FLAG, hal_evt->match_occurred_flag);
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_OUT_OF_RESOURCE_FLAG, hal_evt->out_of_resource_flag);
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_RSSI_VALUE, hal_evt->rssi_value);
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_IBSS_SUPPORTED,
- hal_evt->is_conn_capability_valid);
- if (hal_evt->is_conn_capability_valid) {
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_IBSS_SUPPORTED,
- hal_evt->conn_capability.is_ibss_supported);
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFD_SUPPORTED,
- hal_evt->conn_capability.is_wfd_supported);
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFDS_SUPPORTED,
- hal_evt->conn_capability.is_wfds_supported);
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_TDLS_SUPPORTED,
- hal_evt->conn_capability.is_tdls_supported);
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_MESH_SUPPORTED,
- hal_evt->conn_capability.is_mesh_supported);
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_WLAN_INFRA_FIELD,
- hal_evt->conn_capability.wlan_infra_field);
- }
-
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_NUM_RX_DISCOVERY_ATTR, hal_evt->num_rx_discovery_attr);
- for (i = 0; i < hal_evt->num_rx_discovery_attr; i++) {
- nlattr_nested = nla_nest_start(nl_skb, NAN_EVT_ATTR_MATCH_RX_DISCOVERY_ATTR);
- if (!nlattr_nested) {
- SLSI_ERR(sdev, "Error in nla_nest_start\n");
- /* Dont use slsi skb wrapper for this free */
- kfree_skb(nl_skb);
- kfree(hal_evt);
- return;
- }
- discovery_attr = &hal_evt->discovery_attr[i];
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_TYPE, discovery_attr->type);
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_ROLE, discovery_attr->role);
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_DURATION, discovery_attr->duration);
- res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_AVAIL_INTERVAL_BITMAP,
- discovery_attr->avail_interval_bitmap);
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_MAPID, discovery_attr->mapid);
- res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_ADDR, ETH_ALEN, discovery_attr->addr);
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID_LEN, discovery_attr->mesh_id_len);
- if (discovery_attr->mesh_id_len)
- res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID, discovery_attr->mesh_id_len,
- discovery_attr->mesh_id);
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_LEN,
- discovery_attr->infrastructure_ssid_len);
- if (discovery_attr->infrastructure_ssid_len)
- res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_VAL,
- discovery_attr->infrastructure_ssid_len, discovery_attr->infrastructure_ssid_val);
- nla_nest_end(nl_skb, nlattr_nested);
- }
-
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_NUM_CHANS, hal_evt->num_chans);
- for (i = 0; i < hal_evt->num_chans; i++) {
- nlattr_nested = nla_nest_start(nl_skb, NAN_EVT_ATTR_MATCH_FAMCHAN);
- if (!nlattr_nested) {
- SLSI_ERR(sdev, "Error in nla_nest_start\n");
- /* Dont use slsi skb wrapper for this free */
- kfree_skb(nl_skb);
- kfree(hal_evt);
- return;
- }
- famchan = &hal_evt->famchan[i];
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_FAM_ENTRY_CONTROL, famchan->entry_control);
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_FAM_CLASS_VAL, famchan->class_val);
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_FAM_CHANNEL, famchan->channel);
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_FAM_MAPID, famchan->mapid);
- res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_MATCH_FAM_AVAIL_INTERVAL_BITMAP,
- famchan->avail_interval_bitmap);
- }
-
- res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE_LEN, hal_evt->cluster_attribute_len);
- if (hal_evt->cluster_attribute_len)
- res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE, hal_evt->cluster_attribute_len,
- hal_evt->cluster_attribute);
-
- if (res) {
- SLSI_ERR(sdev, "Error in nla_put*:%x\n", res);
- /* Dont use slsi skb wrapper for this free */
- kfree_skb(nl_skb);
- kfree(hal_evt);
- return;
- }
-
- nla_nest_end(nl_skb, nlattr_start);
-
- cfg80211_vendor_event(nl_skb, GFP_KERNEL);
- kfree(hal_evt);
-}
-
-static int slsi_configure_nd_offload(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
-{
- struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
- struct net_device *dev = wdev->netdev;
- struct netdev_vif *ndev_vif;
- int ret = 0;
- int temp;
- int type;
- const struct nlattr *attr;
- u8 nd_offload_enabled = 0;
-
- SLSI_DBG3(sdev, SLSI_GSCAN, "Received nd_offload command\n");
-
- if (!dev) {
- SLSI_ERR(sdev, "dev is NULL!!\n");
- return -EINVAL;
- }
-
- ndev_vif = netdev_priv(dev);
- SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
-
- if (!ndev_vif->activated || (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) ||
- (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED)) {
- SLSI_DBG3(sdev, SLSI_GSCAN, "vif error\n");
- ret = -EPERM;
- goto exit;
- }
-
- nla_for_each_attr(attr, data, len, temp) {
- type = nla_type(attr);
- switch (type) {
- case SLSI_NL_ATTRIBUTE_ND_OFFLOAD_VALUE:
- {
- nd_offload_enabled = nla_get_u8(attr);
- break;
- }
- default:
- SLSI_ERR(sdev, "Invalid type : %d\n", type);
- ret = -EINVAL;
- goto exit;
- }
- }
-
- ndev_vif->sta.nd_offload_enabled = nd_offload_enabled;
- ret = slsi_mlme_set_ipv6_address(sdev, dev);
- if (ret < 0) {
- SLSI_ERR(sdev, "Configure nd_offload failed ret:%d nd_offload_enabled: %d\n", ret, nd_offload_enabled);
- ret = -EINVAL;
- goto exit;
- }
-exit:
- SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
- return ret;
-}
-
-static int slsi_get_roaming_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
-{
- struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
- struct net_device *dev = wdev->netdev;
- struct netdev_vif *ndev_vif;
- int ret = 0;
- struct slsi_mib_value *values = NULL;
- struct slsi_mib_data mibrsp = { 0, NULL };
- struct slsi_mib_get_entry get_values[] = {{ SLSI_PSID_UNIFI_ROAM_BLACKLIST_SIZE, { 0, 0 } } };
- u32 max_blacklist_size = 0;
- u32 max_whitelist_size = 0;
- struct sk_buff *nl_skb;
- struct nlattr *nlattr_start;
-
- if (!dev) {
- SLSI_ERR(sdev, "dev is NULL!!\n");
- return -EINVAL;
- }
-
- ndev_vif = netdev_priv(dev);
-
- SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
-
- mibrsp.dataLength = 10;
- mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL);
- if (!mibrsp.data) {
- SLSI_ERR(sdev, "Cannot kmalloc %d bytes\n", mibrsp.dataLength);
- ret = -ENOMEM;
- goto exit;
- }
- values = slsi_read_mibs(sdev, NULL, get_values, ARRAY_SIZE(get_values), &mibrsp);
- if (values && (values[0].type == SLSI_MIB_TYPE_UINT || values[0].type == SLSI_MIB_TYPE_INT))
- max_blacklist_size = values[0].u.uintValue;
- nl_skb = cfg80211_vendor_cmd_alloc_reply_skb(sdev->wiphy, NLMSG_DEFAULT_SIZE);
- if (!nl_skb) {
- SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n");
- ret = -ENOMEM;
- goto exit_with_mib_resp;
- }
-
- nlattr_start = nla_nest_start(nl_skb, NL80211_ATTR_VENDOR_DATA);
- if (!nlattr_start) {
- SLSI_ERR(sdev, "failed to put NL80211_ATTR_VENDOR_DATA\n");
- /* Dont use slsi skb wrapper for this free */
- kfree_skb(nl_skb);
- ret = -EINVAL;
- goto exit_with_mib_resp;
- }
-
- ret = nla_put_u32(nl_skb, SLSI_NL_ATTR_MAX_BLACKLIST_SIZE, max_blacklist_size);
- ret |= nla_put_u32(nl_skb, SLSI_NL_ATTR_MAX_WHITELIST_SIZE, max_whitelist_size);
- if (ret) {
- SLSI_ERR(sdev, "Error in nla_put*:%x\n", ret);
- /* Dont use slsi skb wrapper for this free */
- kfree_skb(nl_skb);
- goto exit_with_mib_resp;
- }
-
- ret = cfg80211_vendor_cmd_reply(nl_skb);
- if (ret)
- SLSI_ERR(sdev, "cfg80211_vendor_cmd_reply failed :%d\n", ret);
-exit_with_mib_resp:
- kfree(mibrsp.data);
- kfree(values);
-exit:
- SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
- return ret;
-}
-
-static int slsi_set_roaming_state(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
-{
- struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
- struct net_device *dev = wdev->netdev;
- int temp = 0;
- int type = 0;
- const struct nlattr *attr;
- int ret = 0;
- int roam_state = 0;
-
- if (!dev) {
- SLSI_WARN_NODEV("net_dev is NULL\n");
- return -EINVAL;
- }
-
- nla_for_each_attr(attr, data, len, temp) {
- type = nla_type(attr);
- switch (type) {
- case SLSI_NL_ATTR_ROAM_STATE:
- roam_state = nla_get_u8(attr);
- break;
- default:
- SLSI_ERR_NODEV("Unknown attribute: %d\n", type);
- ret = -EINVAL;
- goto exit;
- }
- }
-
- SLSI_DBG1_NODEV(SLSI_GSCAN, "SUBCMD_SET_ROAMING_STATE roam_state = %d\n", roam_state);
- ret = slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAMING_ENABLED, roam_state);
- if (ret < 0)
- SLSI_ERR_NODEV("Failed to set roaming state\n");
-
-exit:
- return ret;
-}
+exit:
+ return ret;
+}
char *slsi_get_roam_reason_str(int roam_reason)
{
.doit = slsi_get_wake_reason_stats
},
#endif /* CONFIG_SCSC_WLAN_ENHANCED_LOGGING */
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
{
{
.vendor_id = OUI_GOOGLE,
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = slsi_nan_get_capabilities
},
+#endif
{
{
.vendor_id = OUI_GOOGLE,
* Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved
*
****************************************************************************/
+
+#include "nl80211_vendor_nan.h"
+
#ifndef __SLSI_NL80211_VENDOR_H_
#define __SLSI_NL80211_VENDOR_H_
SLSI_ACS_MODE_IEEE80211ANY,
};
-enum SLSI_NAN_REPLY_ATTRIBUTES {
- NAN_REPLY_ATTR_STATUS_TYPE,
- NAN_REPLY_ATTR_VALUE,
- NAN_REPLY_ATTR_RESPONSE_TYPE,
- NAN_REPLY_ATTR_PUBLISH_SUBSCRIBE_TYPE,
- NAN_REPLY_ATTR_CAP_MAX_CONCURRENT_CLUSTER,
- NAN_REPLY_ATTR_CAP_MAX_PUBLISHES,
- NAN_REPLY_ATTR_CAP_MAX_SUBSCRIBES,
- NAN_REPLY_ATTR_CAP_MAX_SERVICE_NAME_LEN,
- NAN_REPLY_ATTR_CAP_MAX_MATCH_FILTER_LEN,
- NAN_REPLY_ATTR_CAP_MAX_TOTAL_MATCH_FILTER_LEN,
- NAN_REPLY_ATTR_CAP_MAX_SERVICE_SPECIFIC_INFO_LEN,
- NAN_REPLY_ATTR_CAP_MAX_VSA_DATA_LEN,
- NAN_REPLY_ATTR_CAP_MAX_MESH_DATA_LEN,
- NAN_REPLY_ATTR_CAP_MAX_NDI_INTERFACES,
- NAN_REPLY_ATTR_CAP_MAX_NDP_SESSIONS,
- NAN_REPLY_ATTR_CAP_MAX_APP_INFO_LEN
-};
-
-enum SLSI_NAN_REQ_ATTRIBUTES {
- NAN_REQ_ATTR_MASTER_PREF,
- NAN_REQ_ATTR_CLUSTER_LOW,
- NAN_REQ_ATTR_CLUSTER_HIGH,
- NAN_REQ_ATTR_HOP_COUNT_LIMIT_VAL,
- NAN_REQ_ATTR_SID_BEACON_VAL,
- NAN_REQ_ATTR_SUPPORT_2G4_VAL,
- NAN_REQ_ATTR_SUPPORT_5G_VAL,
- NAN_REQ_ATTR_RSSI_CLOSE_2G4_VAL,
- NAN_REQ_ATTR_RSSI_MIDDLE_2G4_VAL,
- NAN_REQ_ATTR_RSSI_PROXIMITY_2G4_VAL,
- NAN_REQ_ATTR_BEACONS_2G4_VAL,
- NAN_REQ_ATTR_SDF_2G4_VAL,
- NAN_REQ_ATTR_CHANNEL_2G4_MHZ_VAL,
- NAN_REQ_ATTR_RSSI_PROXIMITY_VAL,
- NAN_REQ_ATTR_RSSI_CLOSE_5G_VAL,
- NAN_REQ_ATTR_RSSI_CLOSE_PROXIMITY_5G_VAL,
- NAN_REQ_ATTR_RSSI_MIDDLE_5G_VAL,
- NAN_REQ_ATTR_RSSI_PROXIMITY_5G_VAL,
- NAN_REQ_ATTR_BEACON_5G_VAL,
- NAN_REQ_ATTR_SDF_5G_VAL,
- NAN_REQ_ATTR_CHANNEL_5G_MHZ_VAL,
- NAN_REQ_ATTR_RSSI_WINDOW_SIZE_VAL,
- NAN_REQ_ATTR_OUI_VAL,
- NAN_REQ_ATTR_MAC_ADDR_VAL,
- NAN_REQ_ATTR_CLUSTER_VAL,
- NAN_REQ_ATTR_SOCIAL_CH_SCAN_DWELL_TIME,
- NAN_REQ_ATTR_SOCIAL_CH_SCAN_PERIOD,
- NAN_REQ_ATTR_RANDOM_FACTOR_FORCE_VAL,
- NAN_REQ_ATTR_HOP_COUNT_FORCE_VAL,
- NAN_REQ_ATTR_CONN_CAPABILITY_PAYLOAD_TX,
- NAN_REQ_ATTR_CONN_CAPABILITY_IBSS,
- NAN_REQ_ATTR_CONN_CAPABILITY_WFD,
- NAN_REQ_ATTR_CONN_CAPABILITY_WFDS,
- NAN_REQ_ATTR_CONN_CAPABILITY_TDLS,
- NAN_REQ_ATTR_CONN_CAPABILITY_MESH,
- NAN_REQ_ATTR_CONN_CAPABILITY_WLAN_INFRA,
- NAN_REQ_ATTR_DISCOVERY_ATTR_NUM_ENTRIES,
- NAN_REQ_ATTR_DISCOVERY_ATTR_VAL,
- NAN_REQ_ATTR_CONN_TYPE,
- NAN_REQ_ATTR_NAN_ROLE,
- NAN_REQ_ATTR_TRANSMIT_FREQ,
- NAN_REQ_ATTR_AVAILABILITY_DURATION,
- NAN_REQ_ATTR_AVAILABILITY_INTERVAL,
- NAN_REQ_ATTR_MESH_ID_LEN,
- NAN_REQ_ATTR_MESH_ID,
- NAN_REQ_ATTR_INFRASTRUCTURE_SSID_LEN,
- NAN_REQ_ATTR_INFRASTRUCTURE_SSID,
- NAN_REQ_ATTR_FURTHER_AVAIL_NUM_ENTRIES,
- NAN_REQ_ATTR_FURTHER_AVAIL_VAL,
- NAN_REQ_ATTR_FURTHER_AVAIL_ENTRY_CTRL,
- NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_CLASS,
- NAN_REQ_ATTR_FURTHER_AVAIL_CHAN,
- NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_MAPID,
- NAN_REQ_ATTR_FURTHER_AVAIL_INTERVAL_BITMAP,
- NAN_REQ_ATTR_PUBLISH_ID,
- NAN_REQ_ATTR_PUBLISH_TTL,
- NAN_REQ_ATTR_PUBLISH_PERIOD,
- NAN_REQ_ATTR_PUBLISH_TYPE,
- NAN_REQ_ATTR_PUBLISH_TX_TYPE,
- NAN_REQ_ATTR_PUBLISH_COUNT,
- NAN_REQ_ATTR_PUBLISH_SERVICE_NAME_LEN,
- NAN_REQ_ATTR_PUBLISH_SERVICE_NAME,
- NAN_REQ_ATTR_PUBLISH_MATCH_ALGO,
- NAN_REQ_ATTR_PUBLISH_SERVICE_INFO_LEN,
- NAN_REQ_ATTR_PUBLISH_SERVICE_INFO,
- NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER_LEN,
- NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER,
- NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER_LEN,
- NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER,
- NAN_REQ_ATTR_PUBLISH_RSSI_THRESHOLD_FLAG,
- NAN_REQ_ATTR_PUBLISH_CONN_MAP,
- NAN_REQ_ATTR_PUBLISH_RECV_IND_CFG,
- NAN_REQ_ATTR_SUBSCRIBE_ID,
- NAN_REQ_ATTR_SUBSCRIBE_TTL,
- NAN_REQ_ATTR_SUBSCRIBE_PERIOD,
- NAN_REQ_ATTR_SUBSCRIBE_TYPE,
- NAN_REQ_ATTR_SUBSCRIBE_RESP_FILTER_TYPE,
- NAN_REQ_ATTR_SUBSCRIBE_RESP_INCLUDE,
- NAN_REQ_ATTR_SUBSCRIBE_USE_RESP_FILTER,
- NAN_REQ_ATTR_SUBSCRIBE_SSI_REQUIRED,
- NAN_REQ_ATTR_SUBSCRIBE_MATCH_INDICATOR,
- NAN_REQ_ATTR_SUBSCRIBE_COUNT,
- NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME_LEN,
- NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME,
- NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO_LEN,
- NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO,
- NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER_LEN,
- NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER,
- NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER_LEN,
- NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER,
- NAN_REQ_ATTR_SUBSCRIBE_RSSI_THRESHOLD_FLAG,
- NAN_REQ_ATTR_SUBSCRIBE_CONN_MAP,
- NAN_REQ_ATTR_SUBSCRIBE_NUM_INTF_ADDR_PRESENT,
- NAN_REQ_ATTR_SUBSCRIBE_INTF_ADDR,
- NAN_REQ_ATTR_SUBSCRIBE_RECV_IND_CFG,
- NAN_REQ_ATTR_FOLLOWUP_ID,
- NAN_REQ_ATTR_FOLLOWUP_REQUESTOR_ID,
- NAN_REQ_ATTR_FOLLOWUP_ADDR,
- NAN_REQ_ATTR_FOLLOWUP_PRIORITY,
- NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME_LEN,
- NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME,
- NAN_REQ_ATTR_FOLLOWUP_TX_WINDOW,
- NAN_REQ_ATTR_FOLLOWUP_RECV_IND_CFG
-};
-
-enum SLSI_NAN_RESP_ATTRIBUTES {
- NAN_RESP_ATTR_MAX_CONCURRENT_NAN_CLUSTERS,
- NAN_RESP_ATTR_MAX_PUBLISHES,
- NAN_RESP_ATTR_MAX_SUBSCRIBES,
- NAN_RESP_ATTR_MAX_SERVICE_NAME_LEN,
- NAN_RESP_ATTR_MAX_MATCH_FILTER_LEN,
- NAN_RESP_ATTR_MAX_TOTAL_MATCH_FILTER_LEN,
- NAN_RESP_ATTR_MAX_SERVICE_SPECIFIC_INFO_LEN,
- NAN_RESP_ATTR_MAX_VSA_DATA_LEN,
- NAN_RESP_ATTR_MAX_MESH_DATA_LEN,
- NAN_RESP_ATTR_MAX_NDI_INTERFACES,
- NAN_RESP_ATTR_MAX_NDP_SESSIONS,
- NAN_RESP_ATTR_MAX_APP_INFO_LEN,
- NAN_RESP_ATTR_SUBSCRIBE_ID,
- NAN_RESP_ATTR_PUBLISH_ID
-};
-
-enum SLSI_NAN_EVT_ATTRIBUTES {
- NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID,
- NAN_EVT_ATTR_MATCH_REQUESTOR_INSTANCE_ID,
- NAN_EVT_ATTR_MATCH_ADDR,
- NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO_LEN,
- NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO,
- NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER_LEN,
- NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER,
- NAN_EVT_ATTR_MATCH_MATCH_OCCURRED_FLAG,
- NAN_EVT_ATTR_MATCH_OUT_OF_RESOURCE_FLAG,
- NAN_EVT_ATTR_MATCH_RSSI_VALUE,
- /*CONN_CAPABILITY*/
- NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFD_SUPPORTED,
- NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFDS_SUPPORTED,
- NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_TDLS_SUPPORTED,
- NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_IBSS_SUPPORTED,
- NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_MESH_SUPPORTED,
- NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_WLAN_INFRA_FIELD,
- NAN_EVT_ATTR_MATCH_NUM_RX_DISCOVERY_ATTR,
- NAN_EVT_ATTR_MATCH_RX_DISCOVERY_ATTR,
- /*NANRECEIVEPOSTDISCOVERY DISCOVERY_ATTR,*/
- NAN_EVT_ATTR_MATCH_DISC_ATTR_TYPE,
- NAN_EVT_ATTR_MATCH_DISC_ATTR_ROLE,
- NAN_EVT_ATTR_MATCH_DISC_ATTR_DURATION,
- NAN_EVT_ATTR_MATCH_DISC_ATTR_AVAIL_INTERVAL_BITMAP,
- NAN_EVT_ATTR_MATCH_DISC_ATTR_MAPID,
- NAN_EVT_ATTR_MATCH_DISC_ATTR_ADDR,
- NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID_LEN,
- NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID,
- NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_LEN,
- NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_VAL,
- NAN_EVT_ATTR_MATCH_NUM_CHANS,
- NAN_EVT_ATTR_MATCH_FAMCHAN,
- /*FAMCHAN[32],*/
- NAN_EVT_ATTR_MATCH_FAM_ENTRY_CONTROL,
- NAN_EVT_ATTR_MATCH_FAM_CLASS_VAL,
- NAN_EVT_ATTR_MATCH_FAM_CHANNEL,
- NAN_EVT_ATTR_MATCH_FAM_MAPID,
- NAN_EVT_ATTR_MATCH_FAM_AVAIL_INTERVAL_BITMAP,
- NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE_LEN,
- NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE,
- NAN_EVT_ATTR_PUBLISH_ID,
- NAN_EVT_ATTR_PUBLISH_REASON,
- NAN_EVT_ATTR_SUBSCRIBE_ID,
- NAN_EVT_ATTR_SUBSCRIBE_REASON,
- NAN_EVT_ATTR_DISABLED_REASON,
- NAN_EVT_ATTR_FOLLOWUP_PUBLISH_SUBSCRIBE_ID,
- NAN_EVT_ATTR_FOLLOWUP_REQUESTOR_INSTANCE_ID,
- NAN_EVT_ATTR_FOLLOWUP_ADDR,
- NAN_EVT_ATTR_FOLLOWUP_DW_OR_FAW,
- NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO_LEN,
- NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO,
- NAN_EVT_ATTR_DISCOVERY_ENGINE_EVT_TYPE,
- NAN_EVT_ATTR_DISCOVERY_ENGINE_MAC_ADDR,
- NAN_EVT_ATTR_DISCOVERY_ENGINE_CLUSTER
-};
-
enum GSCAN_ATTRIBUTE {
GSCAN_ATTRIBUTE_NUM_BUCKETS = 10,
GSCAN_ATTRIBUTE_BASE_PERIOD,
struct slsi_lls_peer_info peer_info[]; /* per peer statistics*/
};
-#define SLSI_FAPI_NAN_CONFIG_PARAM_SID_BEACON 0X0003
-#define SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_CLOSE 0X0004
-#define SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_MIDDLE 0X0005
-#define SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_PROXIMITY 0X0006
-#define SLSI_FAPI_NAN_CONFIG_PARAM_BAND_USAGE 0X0007
-#define SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_CLOSE 0X0008
-#define SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_MIDDLE 0X0009
-#define SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_PROXIMITY 0X000A
-#define SLSI_FAPI_NAN_CONFIG_PARAM_HOP_COUNT_LIMIT 0X000B
-#define SLSI_FAPI_NAN_CONFIG_PARAM_RSSI_WINDOW_SIZE 0X000C
-#define SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_2_4 0X000D
-#define SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_5 0X000E
-#define SLSI_FAPI_NAN_CONFIG_PARAM_MASTER_PREFERENCE 0X000F
-#define SLSI_FAPI_NAN_CONFIG_PARAM_CONNECTION_CAPAB 0X0010
-#define SLSI_FAPI_NAN_CONFIG_PARAM_POST_DISCOVER_PARAM 0X0011
-#define SLSI_FAPI_NAN_CONFIG_PARAM_FURTHER_AVAIL_CHANNEL_MAP 0X0012
-#define SLSI_FAPI_NAN_CONFIG_PARAM_ADDR_RANDOM_INTERVAL 0X0013
-#define SLSI_FAPI_NAN_SERVICE_NAME 0X0020
-#define SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO 0X0021
-#define SLSI_FAPI_NAN_RX_MATCH_FILTER 0X0022
-#define SLSI_FAPI_NAN_TX_MATCH_FILTER 0X0023
-#define SLSI_FAPI_NAN_SDF_MATCH_FILTER 0X0024
-#define SLSI_FAPI_NAN_CLUSTER_ATTRIBUTE 0X0025
-
-#define SLSI_HAL_NAN_MAX_SOCIAL_CHANNELS 3
-#define SLSI_HAL_NAN_MAX_SERVICE_NAME_LEN 255
-#define SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN 1024
-#define SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN 255
-#define SLSI_HAL_NAN_MAX_SUBSCRIBE_MAX_ADDRESS 42
-#define SLSI_HAL_NAN_MAX_POSTDISCOVERY_LEN 5
-
enum slsi_wifi_hal_api_return_types {
WIFI_HAL_SUCCESS = 0,
WIFI_HAL_ERROR_NONE = 0,
WIFI_HAL_ERROR_OUT_OF_MEMORY = -9
};
-enum slsi_wifi_hal_nan_status_type {
- /* NAN Protocol Response Codes */
- SLSI_HAL_NAN_STATUS_SUCCESS = 0,
- /* NAN Discovery Engine/Host driver failures */
- SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE = 1,
- /* NAN OTA failures */
- SLSI_HAL_NAN_STATUS_PROTOCOL_FAILURE = 2,
- /* if the publish/subscribe id is invalid */
- SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID = 3,
- /* If we run out of resources allocated */
- SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE = 4,
- /* if invalid params are passed */
- SLSI_HAL_NAN_STATUS_INVALID_PARAM = 5,
- /* if the requestor instance id is invalid */
- SLSI_HAL_NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID = 6,
- /* if the ndp id is invalid */
- SLSI_HAL_NAN_STATUS_INVALID_NDP_ID = 7,
- /* if NAN is enabled when wifi is turned off */
- SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED = 8,
- /* if over the air ack is not received */
- SLSI_HAL_NAN_STATUS_NO_OTA_ACK = 9,
- /* If NAN is already enabled and we are try to re-enable the same */
- SLSI_HAL_NAN_STATUS_ALREADY_ENABLED = 10,
- /* If followup message internal queue is full */
- SLSI_HAL_NAN_STATUS_FOLLOWUP_QUEUE_FULL = 11,
- /* Unsupported concurrency session enabled, NAN disabled notified */
- SLSI_HAL_NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED = 12
-};
-
-enum slsi_nan_status_type {
- /* NAN Protocol Response Codes */
- NAN_STATUS_SUCCESS = 0,
- NAN_STATUS_TIMEOUT = 1,
- NAN_STATUS_DE_FAILURE = 2,
- NAN_STATUS_INVALID_MSG_VERSION = 3,
- NAN_STATUS_INVALID_MSG_LEN = 4,
- NAN_STATUS_INVALID_MSG_ID = 5,
- NAN_STATUS_INVALID_HANDLE = 6,
- NAN_STATUS_NO_SPACE_AVAILABLE = 7,
- NAN_STATUS_INVALID_PUBLISH_TYPE = 8,
- NAN_STATUS_INVALID_TX_TYPE = 9,
- NAN_STATUS_INVALID_MATCH_ALGORITHM = 10,
- NAN_STATUS_DISABLE_IN_PROGRESS = 11,
- NAN_STATUS_INVALID_TLV_LEN = 12,
- NAN_STATUS_INVALID_TLV_TYPE = 13,
- NAN_STATUS_MISSING_TLV_TYPE = 14,
- NAN_STATUS_INVALID_TOTAL_TLVS_LEN = 15,
- NAN_STATUS_INVALID_MATCH_HANDLE = 16,
- NAN_STATUS_INVALID_TLV_VALUE = 17,
- NAN_STATUS_INVALID_TX_PRIORITY = 18,
- NAN_STATUS_INVALID_CONNECTION_MAP = 19,
- NAN_STATUS_INVALID_TCA_ID = 20,
- NAN_STATUS_INVALID_STATS_ID = 21,
- NAN_STATUS_NAN_NOT_ALLOWED = 22,
- NAN_STATUS_NO_OTA_ACK = 23,
- NAN_STATUS_TX_FAIL = 24,
- /* 25-4095 Reserved */
- /* NAN Configuration Response codes */
- NAN_STATUS_INVALID_RSSI_CLOSE_VALUE = 4096,
- NAN_STATUS_INVALID_RSSI_MIDDLE_VALUE = 4097,
- NAN_STATUS_INVALID_HOP_COUNT_LIMIT = 4098,
- NAN_STATUS_INVALID_MASTER_PREFERENCE_VALUE = 4099,
- NAN_STATUS_INVALID_LOW_CLUSTER_ID_VALUE = 4100,
- NAN_STATUS_INVALID_HIGH_CLUSTER_ID_VALUE = 4101,
- NAN_STATUS_INVALID_BACKGROUND_SCAN_PERIOD = 4102,
- NAN_STATUS_INVALID_RSSI_PROXIMITY_VALUE = 4103,
- NAN_STATUS_INVALID_SCAN_CHANNEL = 4104,
- NAN_STATUS_INVALID_POST_NAN_CONNECTIVITY_CAPABILITIES_BITMAP = 4105,
- NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_NUMCHAN_VALUE = 4106,
- NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_DURATION_VALUE = 4107,
- NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_CLASS_VALUE = 4108,
- NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_CHANNEL_VALUE = 4109,
- NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_AVAILABILITY_INTERVAL_BITMAP_VALUE = 4110,
- NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_MAP_ID = 4111,
- NAN_STATUS_INVALID_POST_NAN_DISCOVERY_CONN_TYPE_VALUE = 4112,
- NAN_STATUS_INVALID_POST_NAN_DISCOVERY_DEVICE_ROLE_VALUE = 4113,
- NAN_STATUS_INVALID_POST_NAN_DISCOVERY_DURATION_VALUE = 4114,
- NAN_STATUS_INVALID_POST_NAN_DISCOVERY_BITMAP_VALUE = 4115,
- NAN_STATUS_MISSING_FUTHER_AVAILABILITY_MAP = 4116,
- NAN_STATUS_INVALID_BAND_CONFIG_FLAGS = 4117,
- NAN_STATUS_INVALID_RANDOM_FACTOR_UPDATE_TIME_VALUE = 4118,
- NAN_STATUS_INVALID_ONGOING_SCAN_PERIOD = 4119,
- NAN_STATUS_INVALID_DW_INTERVAL_VALUE = 4120,
- NAN_STATUS_INVALID_DB_INTERVAL_VALUE = 4121,
- /* 4122-8191 RESERVED */
- NAN_TERMINATED_REASON_INVALID = 8192,
- NAN_TERMINATED_REASON_TIMEOUT = 8193,
- NAN_TERMINATED_REASON_USER_REQUEST = 8194,
- NAN_TERMINATED_REASON_FAILURE = 8195,
- NAN_TERMINATED_REASON_COUNT_REACHED = 8196,
- NAN_TERMINATED_REASON_DE_SHUTDOWN = 8197,
- NAN_TERMINATED_REASON_DISABLE_IN_PROGRESS = 8198,
- NAN_TERMINATED_REASON_POST_DISC_ATTR_EXPIRED = 8199,
- NAN_TERMINATED_REASON_POST_DISC_LEN_EXCEEDED = 8200,
- NAN_TERMINATED_REASON_FURTHER_AVAIL_MAP_EMPTY = 8201
-};
-
-enum slsi_nan_response_type {
- NAN_RESPONSE_ENABLED = 0,
- NAN_RESPONSE_DISABLED = 1,
- NAN_RESPONSE_PUBLISH = 2,
- NAN_RESPONSE_PUBLISH_CANCEL = 3,
- NAN_RESPONSE_TRANSMIT_FOLLOWUP = 4,
- NAN_RESPONSE_SUBSCRIBE = 5,
- NAN_RESPONSE_SUBSCRIBE_CANCEL = 6,
- NAN_RESPONSE_STATS = 7,
- NAN_RESPONSE_CONFIG = 8,
- NAN_RESPONSE_TCA = 9,
- NAN_RESPONSE_ERROR = 10,
- NAN_RESPONSE_BEACON_SDF_PAYLOAD = 11,
- NAN_RESPONSE_GET_CAPABILITIES = 12
-};
-
-enum slsi_nan_disc_event_type {
- NAN_EVENT_ID_DISC_MAC_ADDR = 0,
- NAN_EVENT_ID_STARTED_CLUSTER,
- NAN_EVENT_ID_JOINED_CLUSTER
-};
-
-struct slsi_hal_nan_social_channel_scan_params {
- u8 dwell_time[SLSI_HAL_NAN_MAX_SOCIAL_CHANNELS];
- u16 scan_period[SLSI_HAL_NAN_MAX_SOCIAL_CHANNELS];
-};
-
-struct slsi_hal_nan_connectivity_capability {
- u8 payload_transmit_flag;
- u8 is_wfd_supported;
- u8 is_wfds_supported;
- u8 is_tdls_supported;
- u8 is_ibss_supported;
- u8 is_mesh_supported;
- u8 wlan_infra_field;
-};
-
-struct slsi_hal_nan_post_discovery_param {
- u8 type; /* NanConnectionType */
- u8 role; /* NanDeviceRole */
- u8 transmit_freq;
- u8 duration; /* NanAvailDuration */
- u32 avail_interval_bitmap;
- u8 addr[ETH_ALEN];
- u16 mesh_id_len;
- u8 mesh_id[32];
- u16 infrastructure_ssid_len;
- u8 infrastructure_ssid_val[32];
-};
-
-struct slsi_hal_nan_further_availability_channel {
- /* struct slsi_hal_nan_further_availability_channel*/
- u8 entry_control;
- u8 class_val;
- u8 channel;
- u8 mapid;
- u32 avail_interval_bitmap;
-};
-
-struct slsi_hal_nan_further_availability_map {
- u8 numchans;
- struct slsi_hal_nan_further_availability_channel famchan[32];
-};
-
-struct slsi_hal_nan_receive_post_discovery {
- u8 type;
- u8 role;
- u8 duration;
- u32 avail_interval_bitmap;
- u8 mapid;
- u8 addr[ETH_ALEN];
- u16 mesh_id_len;
- u8 mesh_id[32];
- u16 infrastructure_ssid_len;
- u8 infrastructure_ssid_val[32];
-};
-
-struct slsi_hal_nan_enable_req {
- /* Mandatory parameters below */
- u8 master_pref;
- u16 cluster_low;
- u16 cluster_high;
-
- u8 config_support_5g;
- u8 support_5g_val;
- u8 config_sid_beacon;
- u8 sid_beacon_val;
- u8 config_2dot4g_rssi_close;
- u8 rssi_close_2dot4g_val;
-
- u8 config_2dot4g_rssi_middle;
- u8 rssi_middle_2dot4g_val;
-
- u8 config_2dot4g_rssi_proximity;
- u8 rssi_proximity_2dot4g_val;
-
- u8 config_hop_count_limit;
- u8 hop_count_limit_val;
-
- u8 config_2dot4g_support;
- u8 support_2dot4g_val;
-
- u8 config_2dot4g_beacons;
- u8 beacon_2dot4g_val;
- u8 config_2dot4g_sdf;
- u8 sdf_2dot4g_val;
- u8 config_5g_beacons;
- u8 beacon_5g_val;
- u8 config_5g_sdf;
- u8 sdf_5g_val;
- u8 config_5g_rssi_close;
- u8 rssi_close_5g_val;
- u8 config_5g_rssi_middle;
- u8 rssi_middle_5g_val;
- u8 config_5g_rssi_close_proximity;
- u8 rssi_close_proximity_5g_val;
- u8 config_rssi_window_size;
- u8 rssi_window_size_val;
- /* The 24 bit Organizationally Unique ID + the 8 bit Network Id. */
- u8 config_oui;
- u32 oui_val;
- u8 config_intf_addr;
- u8 intf_addr_val[ETH_ALEN];
-
- u8 config_cluster_attribute_val;
- u8 config_scan_params;
- struct slsi_hal_nan_social_channel_scan_params scan_params_val;
- u8 config_random_factor_force;
- u8 random_factor_force_val;
- u8 config_hop_count_force;
- u8 hop_count_force_val;
-
- /* channel frequency in MHz to enable Nan on */
- u8 config_24g_channel;
- u32 channel_24g_val;
-
- u8 config_5g_channel;
- int channel_5g_val;
-};
-
-struct slsi_hal_nan_publish_req {
- /* id 0 means new publish, any other id is existing publish */
- u16 publish_id;
- /* how many seconds to run for. 0 means forever until canceled */
- u16 ttl;
- /* periodicity of OTA unsolicited publish.
- * Specified in increments of 500 ms
- */
- u16 period;
- u8 publish_type;/* 0= unsolicited, solicited = 1, 2= both */
- u8 tx_type; /* 0 = broadcast, 1= unicast if solicited publish */
- /* number of OTA Publish, 0 means forever until canceled */
- u8 publish_count;
- u16 service_name_len;
- u8 service_name[SLSI_HAL_NAN_MAX_SERVICE_NAME_LEN];
- u8 publish_match_indicator;
-
- u16 service_specific_info_len;
- u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN];
-
- u16 rx_match_filter_len;
- u8 rx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN];
-
- u16 tx_match_filter_len;
- u8 tx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN];
-
- u8 rssi_threshold_flag;
-
- /* 8-bit bitmap which allows the Host to associate this publish
- * with a particular Post-NAN Connectivity attribute
- * which has been sent down in a NanConfigureRequest/NanEnableRequest
- * message. If the DE fails to find a configured Post-NAN
- * connectivity attributes referenced by the bitmap,
- * the DE will return an error code to the Host.
- * If the Publish is configured to use a Post-NAN Connectivity
- * attribute and the Host does not refresh the Post-NAN Connectivity
- * attribute the Publish will be canceled and the Host will be sent
- * a PublishTerminatedIndication message.
- */
- u8 connmap;
- /* Set/Enable corresponding bits to disable any
- * indications that follow a publish.
- * BIT0 - Disable publish termination indication.
- * BIT1 - Disable match expired indication.
- * BIT2 - Disable followUp indication received (OTA).
- */
- u8 recv_indication_cfg;
-};
-
-struct slsi_hal_nan_subscribe_req {
- /* id 0 means new subscribe, non zero is existing subscribe */
- u16 subscribe_id;
- /* how many seconds to run for. 0 means forever until canceled */
- u16 ttl;
- /* periodicity of OTA Active Subscribe. Units in increments
- * of 500 ms , 0 = attempt every DW
- */
- u16 period;
-
- /* Flag which specifies how the Subscribe request shall be processed. */
- u8 subscribe_type; /* 0 - PASSIVE , 1- ACTIVE */
-
- /* Flag which specifies on Active Subscribes how the Service Response
- * Filter attribute is populated.
- */
- u8 service_response_filter; /* 0 - Bloom Filter, 1 - MAC Addr */
-
- /* Flag which specifies how the Service Response Filter Include
- * bit is populated.
- * 0=Do not respond if in the Address Set, 1= Respond
- */
- u8 service_response_include;
-
- /* Flag which specifies if the Service Response Filter
- * should be used when creating Subscribes.
- * 0=Do not send the Service Response Filter,1= send
- */
- u8 use_service_response_filter;
-
- /* Flag which specifies if the Service Specific Info is needed in
- * the Publish message before creating the MatchIndication
- */
- u8 ssi_required_for_match_indication; /* 0=Not needed, 1= Required */
-
- /* Field which specifies how matching indication to host is controlled.
- * 0 - Match and Indicate Once
- * 1 - Match and Indicate continuous
- * 2 - Match and Indicate never. This means don't
- * indicate match to host.
- * 3 - Reserved
- */
- u8 subscribe_match_indicator;
-
- /* The number of Subscribe Matches which should occur
- * before the Subscribe request is automatically terminated.
- */
- /* If this value is 0 this field is not used by DE.*/
- u8 subscribe_count;
-
- /* length of service name */
- /* UTF-8 encoded string identifying the service */
- u16 service_name_len;
- u8 service_name[SLSI_HAL_NAN_MAX_SERVICE_NAME_LEN];
-
- /* Sequence of values which further specify the published service
- * beyond the service name
- */
- u16 service_specific_info_len;
- u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN];
-
- /* Ordered sequence of <length, value> pairs used to filter out
- * received publish discovery messages.
- * This can be sent both for a Passive or an Active Subscribe
- */
- u16 rx_match_filter_len;
- u8 rx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN];
-
- /* Ordered sequence of <length, value> pairs included in the
- * Discovery Frame when an Active Subscribe is used.
- */
- u16 tx_match_filter_len;
- u8 tx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN];
- u8 rssi_threshold_flag;
-
- u8 connmap;
- /* NAN Interface Address, conforming to the format as described in
- * 8.2.4.3.2 of IEEE Std. 802.11-2012.
- */
- u8 num_intf_addr_present;
- u8 intf_addr[SLSI_HAL_NAN_MAX_SUBSCRIBE_MAX_ADDRESS][ETH_ALEN];
- /* Set/Enable corresponding bits to disable
- * indications that follow a subscribe.
- * BIT0 - Disable subscribe termination indication.
- * BIT1 - Disable match expired indication.
- * BIT2 - Disable followUp indication received (OTA).
- */
- u8 recv_indication_cfg;
-};
-
-struct slsi_hal_nan_transmit_followup_req {
- /* Publish or Subscribe Id of an earlier Publish/Subscribe */
- u16 publish_subscribe_id;
-
- /* This Id is the Requestor Instance that is passed as
- * part of earlier MatchInd/FollowupInd message.
- */
- u32 requestor_instance_id;
- u8 addr[ETH_ALEN]; /* Unicast address */
- u8 priority; /* priority of the request 2=high */
- u8 dw_or_faw; /* 0= send in a DW, 1=send in FAW */
-
- /* Sequence of values which further specify the published service beyond
- * the service name.
- */
- u16 service_specific_info_len;
- u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN];
- /* Set/Enable corresponding bits to disable
- * responses after followUp.
- * BIT0 - Disable followUp response from FW.
- */
- u8 recv_indication_cfg;
-};
-
-struct slsi_hal_nan_config_req {
- u8 config_sid_beacon;
- u8 sid_beacon;
- u8 config_rssi_proximity;
- u8 rssi_proximity;
- u8 config_master_pref;
- u8 master_pref;
- /* 1 byte value which defines the RSSI filter threshold.
- * Any Service Descriptors received above this value
- * that are configured for RSSI filtering will be dropped.
- * The rssi values should be specified without sign.
- * For eg: -70dBm should be specified as 70.
- */
- u8 config_5g_rssi_close_proximity;
- u8 rssi_close_proximity_5g_val;
- u8 config_rssi_window_size;
- u16 rssi_window_size_val;
- /* If set to 1, the Discovery Engine will enclose the Cluster
- * Attribute only sent in Beacons in a Vendor Specific Attribute
- * and transmit in a Service Descriptor Frame.
- */
- u8 config_cluster_attribute_val;
- u8 config_scan_params;
- struct slsi_hal_nan_social_channel_scan_params scan_params_val;
- /* 1 byte quantity which forces the Random Factor to a particular
- * value for all transmitted Sync/Discovery beacons
- */
- u8 config_random_factor_force;
- u8 random_factor_force_val;
- /* 1 byte quantity which forces the HC for all transmitted Sync and
- * Discovery Beacon NO matter the real HC being received over the
- * air.
- */
- u8 config_hop_count_force;
- u8 hop_count_force_val;
- /* NAN Post Connectivity Capability */
- u8 config_conn_capability;
- struct slsi_hal_nan_connectivity_capability conn_capability_val;
- /* NAN Post Discover Capability */
- u8 num_config_discovery_attr;
- struct slsi_hal_nan_post_discovery_param discovery_attr_val[SLSI_HAL_NAN_MAX_POSTDISCOVERY_LEN];
- /* NAN Further availability Map */
- u8 config_fam;
- struct slsi_hal_nan_further_availability_map fam_val;
-};
-
-struct slsi_hal_nan_capabilities {
- u32 max_concurrent_nan_clusters;
- u32 max_publishes;
- u32 max_subscribes;
- u32 max_service_name_len;
- u32 max_match_filter_len;
- u32 max_total_match_filter_len;
- u32 max_service_specific_info_len;
- u32 max_vsa_data_len;
- u32 max_mesh_data_len;
- u32 max_ndi_interfaces;
- u32 max_ndp_sessions;
- u32 max_app_info_len;
-};
-
-struct slsi_hal_nan_followup_ind {
- u16 publish_subscribe_id;
- u32 requestor_instance_id;
- u8 addr[ETH_ALEN];
- u8 dw_or_faw;
- u16 service_specific_info_len;
- u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN];
-};
-
-struct slsi_hal_nan_match_ind {
- u16 publish_subscribe_id;
- u32 requestor_instance_id;
- u8 addr[ETH_ALEN];
- u16 service_specific_info_len;
- u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN];
- u16 sdf_match_filter_len;
- u8 sdf_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN];
- u8 match_occurred_flag;
- u8 out_of_resource_flag;
- u8 rssi_value;
- u8 is_conn_capability_valid;
- struct slsi_hal_nan_connectivity_capability conn_capability;
- u8 num_rx_discovery_attr;
- struct slsi_hal_nan_receive_post_discovery discovery_attr[SLSI_HAL_NAN_MAX_POSTDISCOVERY_LEN];
- u8 num_chans;
- struct slsi_hal_nan_further_availability_channel famchan[32];
- u8 cluster_attribute_len;
- u8 cluster_attribute[32];
-};
-
struct slsi_rtt_capabilities {
u8 rtt_one_sided_supported; /* if 1-sided rtt data collection is supported */
u8 rtt_ftm_supported; /* if ftm rtt data collection is supported */
int slsi_tx_rate_calc(struct sk_buff *nl_skb, u16 fw_rate, int res, bool tx_rate);
void slsi_check_num_radios(struct slsi_dev *sdev);
void slsi_rx_event_log_indication(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb);
-void slsi_nan_event(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb);
-void slsi_nan_followup_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb);
-void slsi_nan_service_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb);
-void slsi_nan_get_mac(struct slsi_dev *sdev, char *nan_mac_addr);
+#ifdef CONFIG_SCSC_WLAN_DEBUG
+char *slsi_print_event_name(int event_id);
+#endif
static inline bool slsi_is_gscan_id(u16 scan_id)
--- /dev/null
+/*****************************************************************************
+ *
+ * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved
+ *
+ ****************************************************************************/
+
+#include "cfg80211_ops.h"
+#include "debug.h"
+#include "mgt.h"
+#include "mlme.h"
+
+struct net_device *slsi_nan_get_netdev(struct slsi_dev *sdev)
+{
+#if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4
+ return slsi_get_netdev(sdev, SLSI_NET_INDEX_NAN);
+#else
+ return NULL;
+#endif
+}
+
+static int slsi_nan_get_new_id(u32 id_map, int max_ids)
+{
+ int i;
+
+ for (i = 1; i <= max_ids; i++) {
+ if (!(id_map & BIT(i)))
+ return i;
+ }
+ return 0;
+}
+
+static int slsi_nan_get_new_publish_id(struct netdev_vif *ndev_vif)
+{
+ return slsi_nan_get_new_id(ndev_vif->nan.publish_id_map, SLSI_NAN_MAX_PUBLISH_ID);
+}
+
+static int slsi_nan_get_new_subscribe_id(struct netdev_vif *ndev_vif)
+{
+ return slsi_nan_get_new_id(ndev_vif->nan.subscribe_id_map, SLSI_NAN_MAX_SUBSCRIBE_ID);
+}
+
+static bool slsi_nan_is_publish_id_active(struct netdev_vif *ndev_vif, u32 id)
+{
+ return ndev_vif->nan.publish_id_map & BIT(id);
+}
+
+static bool slsi_nan_is_subscribe_id_active(struct netdev_vif *ndev_vif, u32 id)
+{
+ return ndev_vif->nan.subscribe_id_map & BIT(id);
+}
+
+void slsi_nan_get_mac(struct slsi_dev *sdev, char *nan_mac_addr)
+{
+ memset(nan_mac_addr, 0, ETH_ALEN);
+#if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4
+ if (slsi_dev_nan_supported(sdev))
+ ether_addr_copy(nan_mac_addr, sdev->netdev_addresses[SLSI_NET_INDEX_NAN]);
+#endif
+}
+
+static void slsi_vendor_nan_command_reply(struct wiphy *wiphy, u32 status, u32 error, u32 response_type,
+ u16 publish_subscribe_id, struct slsi_hal_nan_capabilities *capabilities)
+{
+ int reply_len;
+ struct sk_buff *reply;
+
+ reply_len = SLSI_NL_VENDOR_REPLY_OVERHEAD + SLSI_NL_ATTRIBUTE_U32_LEN *
+ (3 + sizeof(struct slsi_hal_nan_capabilities));
+ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, reply_len);
+ if (!reply) {
+ SLSI_WARN_NODEV("SKB alloc failed for vendor_cmd reply\n");
+ return;
+ }
+
+ nla_put_u32(reply, NAN_REPLY_ATTR_STATUS_TYPE, status);
+ nla_put_u32(reply, NAN_REPLY_ATTR_VALUE, error);
+ nla_put_u32(reply, NAN_REPLY_ATTR_RESPONSE_TYPE, response_type);
+
+ if (capabilities) {
+ nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_CONCURRENT_CLUSTER,
+ capabilities->max_concurrent_nan_clusters);
+ nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_PUBLISHES, capabilities->max_publishes);
+ nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_SUBSCRIBES, capabilities->max_subscribes);
+ nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_SERVICE_NAME_LEN, capabilities->max_service_name_len);
+ nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_MATCH_FILTER_LEN, capabilities->max_match_filter_len);
+ nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_TOTAL_MATCH_FILTER_LEN,
+ capabilities->max_total_match_filter_len);
+ nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_SERVICE_SPECIFIC_INFO_LEN,
+ capabilities->max_service_specific_info_len);
+ nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_VSA_DATA_LEN, capabilities->max_vsa_data_len);
+ nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_MESH_DATA_LEN, capabilities->max_mesh_data_len);
+ nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_NDI_INTERFACES, capabilities->max_ndi_interfaces);
+ nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_NDP_SESSIONS, capabilities->max_ndp_sessions);
+ nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_APP_INFO_LEN, capabilities->max_app_info_len);
+ } else if (publish_subscribe_id) {
+ nla_put_u16(reply, NAN_REPLY_ATTR_PUBLISH_SUBSCRIBE_TYPE, publish_subscribe_id);
+ }
+
+ if (cfg80211_vendor_cmd_reply(reply))
+ SLSI_ERR_NODEV("FAILED to reply nan coammnd. response_type:%d\n", response_type);
+}
+
+static int slsi_nan_enable_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_enable_req *hal_req,
+ const void *data, int len)
+{
+ int type, tmp;
+ const struct nlattr *iter;
+
+ memset(hal_req, 0, sizeof(*hal_req));
+ nla_for_each_attr(iter, data, len, tmp) {
+ type = nla_type(iter);
+ switch (type) {
+ case NAN_REQ_ATTR_MASTER_PREF:
+ hal_req->master_pref = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_CLUSTER_LOW:
+ hal_req->cluster_low = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_CLUSTER_HIGH:
+ hal_req->cluster_high = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_SUPPORT_5G_VAL:
+ hal_req->support_5g_val = nla_get_u8(iter);
+ hal_req->config_support_5g = 1;
+ break;
+
+ case NAN_REQ_ATTR_SID_BEACON_VAL:
+ hal_req->sid_beacon_val = nla_get_u8(iter);
+ hal_req->config_sid_beacon = 1;
+ break;
+
+ case NAN_REQ_ATTR_RSSI_CLOSE_2G4_VAL:
+ hal_req->rssi_close_2dot4g_val = nla_get_u8(iter);
+ hal_req->config_2dot4g_rssi_close = 1;
+ break;
+
+ case NAN_REQ_ATTR_RSSI_MIDDLE_2G4_VAL:
+ hal_req->rssi_middle_2dot4g_val = nla_get_u8(iter);
+ hal_req->config_2dot4g_rssi_middle = 1;
+ break;
+
+ case NAN_REQ_ATTR_RSSI_PROXIMITY_2G4_VAL:
+ hal_req->rssi_proximity_2dot4g_val = nla_get_u8(iter);
+ hal_req->rssi_proximity_2dot4g_val = 1;
+ break;
+
+ case NAN_REQ_ATTR_HOP_COUNT_LIMIT_VAL:
+ hal_req->hop_count_limit_val = nla_get_u8(iter);
+ hal_req->config_hop_count_limit = 1;
+ break;
+
+ case NAN_REQ_ATTR_SUPPORT_2G4_VAL:
+ hal_req->support_2dot4g_val = nla_get_u8(iter);
+ hal_req->config_2dot4g_support = 1;
+ break;
+
+ case NAN_REQ_ATTR_BEACONS_2G4_VAL:
+ hal_req->beacon_2dot4g_val = nla_get_u8(iter);
+ hal_req->config_2dot4g_beacons = 1;
+ break;
+
+ case NAN_REQ_ATTR_SDF_2G4_VAL:
+ hal_req->sdf_2dot4g_val = nla_get_u8(iter);
+ hal_req->config_2dot4g_sdf = 1;
+ break;
+
+ case NAN_REQ_ATTR_BEACON_5G_VAL:
+ hal_req->beacon_5g_val = nla_get_u8(iter);
+ hal_req->config_5g_beacons = 1;
+ break;
+
+ case NAN_REQ_ATTR_SDF_5G_VAL:
+ hal_req->sdf_5g_val = nla_get_u8(iter);
+ hal_req->config_5g_sdf = 1;
+ break;
+
+ case NAN_REQ_ATTR_RSSI_CLOSE_5G_VAL:
+ hal_req->rssi_close_5g_val = nla_get_u8(iter);
+ hal_req->config_5g_rssi_close = 1;
+ break;
+
+ case NAN_REQ_ATTR_RSSI_MIDDLE_5G_VAL:
+ hal_req->rssi_middle_5g_val = nla_get_u8(iter);
+ hal_req->config_5g_rssi_middle = 1;
+ break;
+
+ case NAN_REQ_ATTR_RSSI_CLOSE_PROXIMITY_5G_VAL:
+ hal_req->rssi_close_proximity_5g_val = nla_get_u8(iter);
+ hal_req->config_5g_rssi_close_proximity = 1;
+ break;
+
+ case NAN_REQ_ATTR_RSSI_WINDOW_SIZE_VAL:
+ hal_req->rssi_window_size_val = nla_get_u8(iter);
+ hal_req->config_rssi_window_size = 1;
+ break;
+
+ case NAN_REQ_ATTR_OUI_VAL:
+ hal_req->oui_val = nla_get_u32(iter);
+ hal_req->config_oui = 1;
+ break;
+
+ case NAN_REQ_ATTR_MAC_ADDR_VAL:
+ memcpy(hal_req->intf_addr_val, nla_data(iter), ETH_ALEN);
+ hal_req->config_intf_addr = 1;
+ break;
+
+ case NAN_REQ_ATTR_CLUSTER_VAL:
+ hal_req->config_cluster_attribute_val = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_SOCIAL_CH_SCAN_DWELL_TIME:
+ memcpy(hal_req->scan_params_val.dwell_time, nla_data(iter),
+ sizeof(hal_req->scan_params_val.dwell_time));
+ hal_req->config_scan_params = 1;
+ break;
+
+ case NAN_REQ_ATTR_SOCIAL_CH_SCAN_PERIOD:
+ memcpy(hal_req->scan_params_val.scan_period, nla_data(iter),
+ sizeof(hal_req->scan_params_val.scan_period));
+ hal_req->config_scan_params = 1;
+ break;
+
+ case NAN_REQ_ATTR_RANDOM_FACTOR_FORCE_VAL:
+ hal_req->random_factor_force_val = nla_get_u8(iter);
+ hal_req->config_random_factor_force = 1;
+ break;
+
+ case NAN_REQ_ATTR_HOP_COUNT_FORCE_VAL:
+ hal_req->hop_count_force_val = nla_get_u8(iter);
+ hal_req->config_hop_count_force = 1;
+ break;
+
+ case NAN_REQ_ATTR_CHANNEL_2G4_MHZ_VAL:
+ hal_req->channel_24g_val = nla_get_u32(iter);
+ hal_req->config_24g_channel = 1;
+ break;
+
+ case NAN_REQ_ATTR_CHANNEL_5G_MHZ_VAL:
+ hal_req->channel_5g_val = nla_get_u8(iter);
+ hal_req->config_5g_channel = 1;
+ break;
+
+ default:
+ SLSI_ERR(sdev, "Unexpected NAN enable attribute TYPE:%d\n", type);
+ return SLSI_HAL_NAN_STATUS_INVALID_PARAM;
+ }
+ }
+ return SLSI_HAL_NAN_STATUS_SUCCESS;
+}
+
+int slsi_nan_enable(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
+{
+ struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+ struct slsi_hal_nan_enable_req hal_req;
+ int ret;
+ struct net_device *dev = slsi_nan_get_netdev(sdev);
+ struct netdev_vif *ndev_vif;
+ u8 nan_vif_mac_address[ETH_ALEN];
+ u8 broadcast_mac[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+ u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
+
+ if (!dev) {
+ SLSI_ERR(sdev, "No NAN interface\n");
+ ret = -ENOTSUPP;
+ reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+ goto exit;
+ }
+
+ if (!slsi_dev_nan_supported(sdev)) {
+ SLSI_ERR(sdev, "NAN not allowed(mib:%d)\n", sdev->nan_enabled);
+ ret = WIFI_HAL_ERROR_NOT_SUPPORTED;
+ reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+ goto exit;
+ }
+
+ ndev_vif = netdev_priv(dev);
+
+ reply_status = slsi_nan_enable_get_nl_params(sdev, &hal_req, data, len);
+ if (reply_status != SLSI_HAL_NAN_STATUS_SUCCESS) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+ if (ndev_vif->activated) {
+ ret = -EINVAL;
+ SLSI_DBG1(sdev, SLSI_GSCAN, "Already Enabled. Req Rejected\n");
+ goto exit_with_mutex;
+ }
+ ndev_vif->vif_type = FAPI_VIFTYPE_NAN;
+
+ if (hal_req.config_intf_addr)
+ ether_addr_copy(nan_vif_mac_address, hal_req.intf_addr_val);
+ else
+ slsi_nan_get_mac(sdev, nan_vif_mac_address);
+
+ ret = slsi_mlme_add_vif(sdev, dev, nan_vif_mac_address, broadcast_mac);
+ if (ret) {
+ reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+ SLSI_ERR(sdev, "failed to set unsync vif. Cannot start NAN\n");
+ } else {
+ ret = slsi_mlme_nan_enable(sdev, dev, &hal_req);
+ if (ret) {
+ SLSI_ERR(sdev, "failed to enable NAN.\n");
+ reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+ slsi_mlme_del_vif(sdev, dev);
+ ndev_vif->activated = false;
+ ndev_vif->nan.subscribe_id_map = 0;
+ ndev_vif->nan.publish_id_map = 0;
+ } else {
+ slsi_vif_activated(sdev, dev);
+ }
+ }
+
+exit_with_mutex:
+ SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+exit:
+ slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_ENABLED, 0, NULL);
+ return ret;
+}
+
+int slsi_nan_disable(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
+{
+ struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+ struct net_device *dev = slsi_nan_get_netdev(sdev);
+ struct netdev_vif *ndev_vif;
+
+ if (dev) {
+ ndev_vif = netdev_priv(dev);
+ SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+ if (ndev_vif->activated) {
+ slsi_mlme_del_vif(sdev, dev);
+ ndev_vif->activated = false;
+ ndev_vif->nan.subscribe_id_map = 0;
+ ndev_vif->nan.publish_id_map = 0;
+ } else {
+ SLSI_WARN(sdev, "NAN FWif not active!!");
+ }
+ SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+ } else {
+ SLSI_WARN(sdev, "No NAN interface!!");
+ }
+
+ slsi_vendor_nan_command_reply(wiphy, SLSI_HAL_NAN_STATUS_SUCCESS, 0, NAN_RESPONSE_DISABLED, 0, NULL);
+
+ return 0;
+}
+
+static int slsi_nan_publish_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_publish_req *hal_req,
+ const void *data, int len)
+{
+ int type, tmp;
+ const struct nlattr *iter;
+
+ memset(hal_req, 0, sizeof(*hal_req));
+ nla_for_each_attr(iter, data, len, tmp) {
+ type = nla_type(iter);
+ switch (type) {
+ case NAN_REQ_ATTR_PUBLISH_ID:
+ hal_req->publish_id = nla_get_u16(iter);
+ break;
+ case NAN_REQ_ATTR_PUBLISH_TTL:
+ hal_req->ttl = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_PUBLISH_PERIOD:
+ hal_req->period = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_PUBLISH_TYPE:
+ hal_req->publish_type = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_PUBLISH_TX_TYPE:
+ hal_req->tx_type = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_PUBLISH_COUNT:
+ hal_req->publish_count = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_PUBLISH_SERVICE_NAME_LEN:
+ hal_req->service_name_len = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_PUBLISH_SERVICE_NAME:
+ memcpy(hal_req->service_name, nla_data(iter), hal_req->service_name_len);
+ break;
+
+ case NAN_REQ_ATTR_PUBLISH_MATCH_ALGO:
+ hal_req->publish_match_indicator = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_PUBLISH_SERVICE_INFO_LEN:
+ hal_req->service_specific_info_len = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_PUBLISH_SERVICE_INFO:
+ memcpy(hal_req->service_specific_info, nla_data(iter), hal_req->service_specific_info_len);
+ break;
+
+ case NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER_LEN:
+ hal_req->rx_match_filter_len = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER:
+ memcpy(hal_req->rx_match_filter, nla_data(iter), hal_req->rx_match_filter_len);
+ break;
+
+ case NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER_LEN:
+ hal_req->tx_match_filter_len = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER:
+ memcpy(hal_req->tx_match_filter, nla_data(iter), hal_req->tx_match_filter_len);
+ break;
+
+ case NAN_REQ_ATTR_PUBLISH_RSSI_THRESHOLD_FLAG:
+ hal_req->rssi_threshold_flag = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_PUBLISH_CONN_MAP:
+ hal_req->connmap = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_PUBLISH_RECV_IND_CFG:
+ hal_req->recv_indication_cfg = nla_get_u8(iter);
+ break;
+
+ default:
+ SLSI_ERR(sdev, "Unexpected NAN publish attribute TYPE:%d\n", type);
+ return SLSI_HAL_NAN_STATUS_INVALID_PARAM;
+ }
+ }
+ return SLSI_HAL_NAN_STATUS_SUCCESS;
+}
+
+int slsi_nan_publish(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
+{
+ struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+ struct slsi_hal_nan_publish_req hal_req;
+ struct net_device *dev = slsi_nan_get_netdev(sdev);
+ struct netdev_vif *ndev_vif;
+ int ret;
+ u32 reply_status;
+ u32 publish_id = 0;
+
+ if (!dev) {
+ SLSI_ERR(sdev, "NAN netif not active!!");
+ ret = -EINVAL;
+ reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+ goto exit;
+ }
+
+ ndev_vif = netdev_priv(dev);
+ reply_status = slsi_nan_publish_get_nl_params(sdev, &hal_req, data, len);
+ if (reply_status != SLSI_HAL_NAN_STATUS_SUCCESS) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+
+ if (!ndev_vif->activated) {
+ SLSI_WARN(sdev, "NAN vif not activated\n");
+ reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+ ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
+ goto exit_with_lock;
+ }
+
+ if (!hal_req.publish_id) {
+ hal_req.publish_id = slsi_nan_get_new_publish_id(ndev_vif);
+ } else if (!slsi_nan_is_publish_id_active(ndev_vif, hal_req.publish_id)) {
+ SLSI_WARN(sdev, "Publish id %d not found. map:%x\n", hal_req.publish_id,
+ ndev_vif->nan.publish_id_map);
+ reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
+ ret = -EINVAL;
+ goto exit_with_lock;
+ }
+
+ if (hal_req.publish_id) {
+ ret = slsi_mlme_nan_publish(sdev, dev, &hal_req, hal_req.publish_id);
+ if (ret)
+ reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+ else
+ publish_id = hal_req.publish_id;
+ } else {
+ reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
+ SLSI_WARN(sdev, "Too Many concurrent PUBLISH REQ(map:%x)\n",
+ ndev_vif->nan.publish_id_map);
+ ret = -ENOTSUPP;
+ }
+exit_with_lock:
+ SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+exit:
+ slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_PUBLISH, publish_id, NULL);
+ return ret;
+}
+
+int slsi_nan_publish_cancel(struct wiphy *wiphy, struct wireless_dev *wdev,
+ const void *data, int len)
+{
+ struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+ struct net_device *dev = slsi_nan_get_netdev(sdev);
+ struct netdev_vif *ndev_vif;
+ int type, tmp, ret = 0;
+ u16 publish_id = 0;
+ const struct nlattr *iter;
+ u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
+
+ if (!dev) {
+ SLSI_ERR(sdev, "NAN netif not active!!");
+ reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ ndev_vif = netdev_priv(dev);
+ nla_for_each_attr(iter, data, len, tmp) {
+ type = nla_type(iter);
+ switch (type) {
+ case NAN_REQ_ATTR_PUBLISH_ID:
+ publish_id = nla_get_u16(iter);
+ break;
+ default:
+ SLSI_ERR(sdev, "Unexpected NAN publishcancel attribute TYPE:%d\n", type);
+ }
+ }
+
+ SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+ if (!ndev_vif->activated) {
+ reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+ ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
+ goto exit_with_lock;
+ }
+ if (!publish_id || !slsi_nan_is_publish_id_active(ndev_vif, publish_id)) {
+ reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
+ SLSI_WARN(sdev, "Publish_id(%d) not active. map:%x\n",
+ publish_id, ndev_vif->nan.publish_id_map);
+ } else {
+ ret = slsi_mlme_nan_publish(sdev, dev, NULL, publish_id);
+ if (ret)
+ reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+ }
+exit_with_lock:
+ SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+exit:
+ slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_PUBLISH_CANCEL, publish_id, NULL);
+ return ret;
+}
+
+static int slsi_nan_subscribe_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_subscribe_req *hal_req,
+ const void *data, int len)
+{
+ int type, tmp;
+ const struct nlattr *iter;
+
+ memset(hal_req, 0, sizeof(*hal_req));
+ nla_for_each_attr(iter, data, len, tmp) {
+ type = nla_type(iter);
+ switch (type) {
+ case NAN_REQ_ATTR_SUBSCRIBE_ID:
+ hal_req->subscribe_id = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_TTL:
+ hal_req->ttl = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_PERIOD:
+ hal_req->period = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_TYPE:
+ hal_req->subscribe_type = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_RESP_FILTER_TYPE:
+ hal_req->service_response_filter = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_RESP_INCLUDE:
+ hal_req->service_response_include = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_USE_RESP_FILTER:
+ hal_req->use_service_response_filter = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_SSI_REQUIRED:
+ hal_req->ssi_required_for_match_indication = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_MATCH_INDICATOR:
+ hal_req->subscribe_match_indicator = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_COUNT:
+ hal_req->subscribe_count = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME_LEN:
+ hal_req->service_name_len = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME:
+ memcpy(hal_req->service_name, nla_data(iter), hal_req->service_name_len);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO_LEN:
+ hal_req->service_specific_info_len = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO:
+ memcpy(hal_req->service_specific_info, nla_data(iter), hal_req->service_specific_info_len);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER_LEN:
+ hal_req->rx_match_filter_len = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER:
+ memcpy(hal_req->rx_match_filter, nla_data(iter), hal_req->rx_match_filter_len);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER_LEN:
+ hal_req->tx_match_filter_len = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER:
+ memcpy(hal_req->tx_match_filter, nla_data(iter), hal_req->tx_match_filter_len);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_RSSI_THRESHOLD_FLAG:
+ hal_req->rssi_threshold_flag = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_CONN_MAP:
+ hal_req->connmap = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_NUM_INTF_ADDR_PRESENT:
+ hal_req->num_intf_addr_present = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_INTF_ADDR:
+ memcpy(hal_req->intf_addr, nla_data(iter), hal_req->num_intf_addr_present * ETH_ALEN);
+ break;
+
+ case NAN_REQ_ATTR_SUBSCRIBE_RECV_IND_CFG:
+ hal_req->recv_indication_cfg = nla_get_u8(iter);
+ break;
+
+ default:
+ SLSI_ERR(sdev, "Unexpected NAN subscribe attribute TYPE:%d\n", type);
+ return SLSI_HAL_NAN_STATUS_INVALID_PARAM;
+ }
+ }
+ return SLSI_HAL_NAN_STATUS_SUCCESS;
+}
+
+int slsi_nan_subscribe(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
+{
+ struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+ struct net_device *dev = slsi_nan_get_netdev(sdev);
+ struct netdev_vif *ndev_vif;
+ struct slsi_hal_nan_subscribe_req *hal_req;
+ int ret;
+ u32 reply_status;
+ u32 subscribe_id = 0;
+
+ if (!dev) {
+ SLSI_ERR(sdev, "NAN netif not active!!\n");
+ reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ hal_req = kmalloc(sizeof(*hal_req), GFP_KERNEL);
+ if (!hal_req) {
+ SLSI_ERR(sdev, "Failed to alloc hal_req structure!!!\n");
+ reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE;
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ ndev_vif = netdev_priv(dev);
+ reply_status = slsi_nan_subscribe_get_nl_params(sdev, hal_req, data, len);
+ if (reply_status != SLSI_HAL_NAN_STATUS_SUCCESS) {
+ kfree(hal_req);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+ if (!ndev_vif->activated) {
+ SLSI_WARN(sdev, "NAN vif not activated\n");
+ reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+ ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
+ goto exit_with_lock;
+ }
+
+ if (!hal_req->subscribe_id) {
+ hal_req->subscribe_id = slsi_nan_get_new_subscribe_id(ndev_vif);
+ } else if (!slsi_nan_is_subscribe_id_active(ndev_vif, hal_req->subscribe_id)) {
+ SLSI_WARN(sdev, "Subscribe id %d not found. map:%x\n", hal_req->subscribe_id,
+ ndev_vif->nan.subscribe_id_map);
+ reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
+ ret = -EINVAL;
+ goto exit_with_lock;
+ }
+
+ ret = slsi_mlme_nan_subscribe(sdev, dev, hal_req, hal_req->subscribe_id);
+ if (ret)
+ reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+ else
+ subscribe_id = hal_req->subscribe_id;
+
+exit_with_lock:
+ SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+ kfree(hal_req);
+exit:
+ slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_SUBSCRIBE, subscribe_id, NULL);
+ return ret;
+}
+
+int slsi_nan_subscribe_cancel(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
+{
+ struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+ struct net_device *dev = slsi_nan_get_netdev(sdev);
+ struct netdev_vif *ndev_vif;
+ int type, tmp, ret = WIFI_HAL_ERROR_UNKNOWN;
+ u16 subscribe_id = 0;
+ const struct nlattr *iter;
+ u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
+
+ if (!dev) {
+ SLSI_ERR(sdev, "NAN netif not active!!");
+ reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+ ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
+ goto exit;
+ }
+
+ ndev_vif = netdev_priv(dev);
+
+ nla_for_each_attr(iter, data, len, tmp) {
+ type = nla_type(iter);
+ switch (type) {
+ case NAN_REQ_ATTR_SUBSCRIBE_ID:
+ subscribe_id = nla_get_u16(iter);
+ break;
+ default:
+ SLSI_ERR(sdev, "Unexpected NAN subscribecancel attribute TYPE:%d\n", type);
+ reply_status = SLSI_HAL_NAN_STATUS_INVALID_PARAM;
+ goto exit;
+ }
+ }
+
+ SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+ if (ndev_vif->activated) {
+ if (!subscribe_id || !slsi_nan_is_subscribe_id_active(ndev_vif, subscribe_id)) {
+ SLSI_WARN(sdev, "subscribe_id(%d) not active. map:%x\n",
+ subscribe_id, ndev_vif->nan.subscribe_id_map);
+ reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
+ } else {
+ ret = slsi_mlme_nan_subscribe(sdev, dev, NULL, subscribe_id);
+ if (ret)
+ reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+ }
+ } else {
+ SLSI_ERR(sdev, "vif not activated\n");
+ reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+ ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
+ }
+ SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+exit:
+ slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_SUBSCRIBE_CANCEL, subscribe_id, NULL);
+ return ret;
+}
+
+static int slsi_nan_followup_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_transmit_followup_req *hal_req,
+ const void *data, int len)
+{
+ int type, tmp;
+ const struct nlattr *iter;
+
+ memset(hal_req, 0, sizeof(*hal_req));
+ nla_for_each_attr(iter, data, len, tmp) {
+ type = nla_type(iter);
+ switch (type) {
+ case NAN_REQ_ATTR_FOLLOWUP_ID:
+ hal_req->publish_subscribe_id = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_FOLLOWUP_REQUESTOR_ID:
+ hal_req->requestor_instance_id = nla_get_u32(iter);
+ break;
+
+ case NAN_REQ_ATTR_FOLLOWUP_ADDR:
+ memcpy(hal_req->addr, nla_data(iter), ETH_ALEN);
+ break;
+
+ case NAN_REQ_ATTR_FOLLOWUP_PRIORITY:
+ hal_req->priority = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_FOLLOWUP_TX_WINDOW:
+ hal_req->dw_or_faw = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME_LEN:
+ hal_req->service_specific_info_len = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME:
+ memcpy(hal_req->service_specific_info, nla_data(iter), hal_req->service_specific_info_len);
+ break;
+
+ case NAN_REQ_ATTR_FOLLOWUP_RECV_IND_CFG:
+ hal_req->recv_indication_cfg = nla_get_u8(iter);
+ break;
+
+ default:
+ SLSI_ERR(sdev, "Unexpected NAN followup attribute TYPE:%d\n", type);
+ return SLSI_HAL_NAN_STATUS_INVALID_PARAM;
+ }
+ }
+ return SLSI_HAL_NAN_STATUS_SUCCESS;
+}
+
+int slsi_nan_transmit_followup(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
+{
+ struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+ struct net_device *dev = slsi_nan_get_netdev(sdev);
+ struct netdev_vif *ndev_vif;
+ struct slsi_hal_nan_transmit_followup_req hal_req;
+ int ret;
+ u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
+
+ if (!dev) {
+ SLSI_ERR(sdev, "NAN netif not active!!");
+ ret = -EINVAL;
+ reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+ goto exit;
+ }
+
+ ndev_vif = netdev_priv(dev);
+ reply_status = slsi_nan_followup_get_nl_params(sdev, &hal_req, data, len);
+ if (reply_status) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+ if (!ndev_vif->activated) {
+ SLSI_WARN(sdev, "NAN vif not activated\n");
+ reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+ ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
+ goto exit_with_lock;
+ }
+
+ if (!hal_req.publish_subscribe_id ||
+ !(slsi_nan_is_subscribe_id_active(ndev_vif, hal_req.publish_subscribe_id) ||
+ slsi_nan_is_publish_id_active(ndev_vif, hal_req.publish_subscribe_id))) {
+ SLSI_WARN(sdev, "publish/Subscribe id %d not found. map:%x\n", hal_req.publish_subscribe_id,
+ ndev_vif->nan.subscribe_id_map);
+ reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
+ ret = -EINVAL;
+ goto exit_with_lock;
+ }
+
+ ret = slsi_mlme_nan_tx_followup(sdev, dev, &hal_req);
+ if (ret)
+ reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+
+exit_with_lock:
+ SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+exit:
+ slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_TRANSMIT_FOLLOWUP, 0, NULL);
+ return ret;
+}
+
+static int slsi_nan_config_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_config_req *hal_req,
+ const void *data, int len)
+{
+ int type, type1, tmp, tmp1, disc_attr_idx = 0, famchan_idx = 0;
+ const struct nlattr *iter, *iter1;
+ struct slsi_hal_nan_post_discovery_param *disc_attr;
+ struct slsi_hal_nan_further_availability_channel *famchan;
+
+ memset(hal_req, 0, sizeof(*hal_req));
+ nla_for_each_attr(iter, data, len, tmp) {
+ type = nla_type(iter);
+ switch (type) {
+ case NAN_REQ_ATTR_SID_BEACON_VAL:
+ hal_req->sid_beacon = nla_get_u8(iter);
+ hal_req->config_sid_beacon = 1;
+ break;
+
+ case NAN_REQ_ATTR_RSSI_PROXIMITY_2G4_VAL:
+ hal_req->rssi_proximity = nla_get_u8(iter);
+ hal_req->config_rssi_proximity = 1;
+ break;
+
+ case NAN_REQ_ATTR_MASTER_PREF:
+ hal_req->master_pref = nla_get_u8(iter);
+ hal_req->config_master_pref = 1;
+ break;
+
+ case NAN_REQ_ATTR_RSSI_CLOSE_PROXIMITY_5G_VAL:
+ hal_req->rssi_close_proximity_5g_val = nla_get_u8(iter);
+ hal_req->config_5g_rssi_close_proximity = 1;
+ break;
+
+ case NAN_REQ_ATTR_RSSI_WINDOW_SIZE_VAL:
+ hal_req->rssi_window_size_val = nla_get_u8(iter);
+ hal_req->config_rssi_window_size = 1;
+ break;
+
+ case NAN_REQ_ATTR_CLUSTER_VAL:
+ hal_req->config_cluster_attribute_val = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_SOCIAL_CH_SCAN_DWELL_TIME:
+ memcpy(hal_req->scan_params_val.dwell_time, nla_data(iter),
+ sizeof(hal_req->scan_params_val.dwell_time));
+ hal_req->config_scan_params = 1;
+ break;
+
+ case NAN_REQ_ATTR_SOCIAL_CH_SCAN_PERIOD:
+ memcpy(hal_req->scan_params_val.scan_period, nla_data(iter),
+ sizeof(hal_req->scan_params_val.scan_period));
+ hal_req->config_scan_params = 1;
+ break;
+
+ case NAN_REQ_ATTR_RANDOM_FACTOR_FORCE_VAL:
+ hal_req->random_factor_force_val = nla_get_u8(iter);
+ hal_req->config_random_factor_force = 1;
+ break;
+
+ case NAN_REQ_ATTR_HOP_COUNT_FORCE_VAL:
+ hal_req->hop_count_force_val = nla_get_u8(iter);
+ hal_req->config_hop_count_force = 1;
+ break;
+
+ case NAN_REQ_ATTR_CONN_CAPABILITY_PAYLOAD_TX:
+ hal_req->conn_capability_val.payload_transmit_flag = nla_get_u8(iter);
+ hal_req->config_conn_capability = 1;
+ break;
+
+ case NAN_REQ_ATTR_CONN_CAPABILITY_WFD:
+ hal_req->conn_capability_val.is_wfd_supported = nla_get_u8(iter);
+ hal_req->config_conn_capability = 1;
+ break;
+
+ case NAN_REQ_ATTR_CONN_CAPABILITY_WFDS:
+ hal_req->conn_capability_val.is_wfds_supported = nla_get_u8(iter);
+ hal_req->config_conn_capability = 1;
+ break;
+
+ case NAN_REQ_ATTR_CONN_CAPABILITY_TDLS:
+ hal_req->conn_capability_val.is_tdls_supported = nla_get_u8(iter);
+ hal_req->config_conn_capability = 1;
+ break;
+
+ case NAN_REQ_ATTR_CONN_CAPABILITY_MESH:
+ hal_req->conn_capability_val.is_mesh_supported = nla_get_u8(iter);
+ hal_req->config_conn_capability = 1;
+ break;
+
+ case NAN_REQ_ATTR_CONN_CAPABILITY_IBSS:
+ hal_req->conn_capability_val.is_ibss_supported = nla_get_u8(iter);
+ hal_req->config_conn_capability = 1;
+ break;
+
+ case NAN_REQ_ATTR_CONN_CAPABILITY_WLAN_INFRA:
+ hal_req->conn_capability_val.wlan_infra_field = nla_get_u8(iter);
+ hal_req->config_conn_capability = 1;
+ break;
+
+ case NAN_REQ_ATTR_DISCOVERY_ATTR_NUM_ENTRIES:
+ hal_req->num_config_discovery_attr = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_DISCOVERY_ATTR_VAL:
+ if (disc_attr_idx >= hal_req->num_config_discovery_attr) {
+ SLSI_ERR(sdev,
+ "disc attr(%d) > num disc attr(%d)\n",
+ disc_attr_idx + 1, hal_req->num_config_discovery_attr);
+ return -EINVAL;
+ }
+ disc_attr = &hal_req->discovery_attr_val[disc_attr_idx];
+ disc_attr_idx++;
+ nla_for_each_nested(iter1, iter, tmp1) {
+ type1 = nla_type(iter1);
+ switch (type1) {
+ case NAN_REQ_ATTR_CONN_TYPE:
+ disc_attr->type = nla_get_u8(iter1);
+ break;
+
+ case NAN_REQ_ATTR_NAN_ROLE:
+ disc_attr->role = nla_get_u8(iter1);
+ break;
+
+ case NAN_REQ_ATTR_TRANSMIT_FREQ:
+ disc_attr->transmit_freq = nla_get_u8(iter1);
+ break;
+
+ case NAN_REQ_ATTR_AVAILABILITY_DURATION:
+ disc_attr->duration = nla_get_u8(iter1);
+ break;
+
+ case NAN_REQ_ATTR_AVAILABILITY_INTERVAL:
+ disc_attr->avail_interval_bitmap = nla_get_u32(iter1);
+ break;
+
+ case NAN_REQ_ATTR_MAC_ADDR_VAL:
+ memcpy(disc_attr->addr, nla_data(iter1), ETH_ALEN);
+ break;
+
+ case NAN_REQ_ATTR_MESH_ID_LEN:
+ disc_attr->mesh_id_len = nla_get_u16(iter1);
+ break;
+
+ case NAN_REQ_ATTR_MESH_ID:
+ memcpy(disc_attr->mesh_id, nla_data(iter1), disc_attr->mesh_id_len);
+ break;
+
+ case NAN_REQ_ATTR_INFRASTRUCTURE_SSID_LEN:
+ disc_attr->infrastructure_ssid_len = nla_get_u16(iter1);
+ break;
+
+ case NAN_REQ_ATTR_INFRASTRUCTURE_SSID:
+ memcpy(disc_attr->infrastructure_ssid_val, nla_data(iter1),
+ disc_attr->infrastructure_ssid_len);
+ break;
+ }
+ }
+ break;
+
+ case NAN_REQ_ATTR_FURTHER_AVAIL_NUM_ENTRIES:
+ hal_req->fam_val.numchans = nla_get_u8(iter);
+ hal_req->config_fam = 1;
+ break;
+
+ case NAN_REQ_ATTR_FURTHER_AVAIL_VAL:
+ hal_req->config_fam = 1;
+ if (famchan_idx >= hal_req->fam_val.numchans) {
+ SLSI_ERR(sdev,
+ "famchan attr(%d) > numchans(%d)\n",
+ famchan_idx + 1, hal_req->fam_val.numchans);
+ return -EINVAL;
+ }
+ famchan = &hal_req->fam_val.famchan[famchan_idx];
+ famchan_idx++;
+ nla_for_each_nested(iter1, iter, tmp1) {
+ type1 = nla_type(iter1);
+ switch (type1) {
+ case NAN_REQ_ATTR_FURTHER_AVAIL_ENTRY_CTRL:
+ famchan->entry_control = nla_get_u8(iter1);
+ break;
+
+ case NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_CLASS:
+ famchan->class_val = nla_get_u8(iter1);
+ break;
+
+ case NAN_REQ_ATTR_FURTHER_AVAIL_CHAN:
+ famchan->channel = nla_get_u8(iter1);
+ break;
+
+ case NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_MAPID:
+ famchan->mapid = nla_get_u8(iter1);
+ break;
+
+ case NAN_REQ_ATTR_FURTHER_AVAIL_INTERVAL_BITMAP:
+ famchan->avail_interval_bitmap = nla_get_u32(iter1);
+ break;
+ }
+ }
+ break;
+ default:
+ SLSI_ERR(sdev, "Unexpected NAN config attribute TYPE:%d\n", type);
+ return SLSI_HAL_NAN_STATUS_INVALID_PARAM;
+ }
+ }
+ return SLSI_HAL_NAN_STATUS_SUCCESS;
+}
+
+int slsi_nan_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
+{
+ struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+ struct net_device *dev = slsi_nan_get_netdev(sdev);
+ struct netdev_vif *ndev_vif;
+ struct slsi_hal_nan_config_req hal_req;
+ int ret;
+ u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
+
+ if (!dev) {
+ SLSI_ERR(sdev, "NAN netif not active!!");
+ ret = -EINVAL;
+ reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+ goto exit;
+ }
+
+ ndev_vif = netdev_priv(dev);
+ reply_status = slsi_nan_config_get_nl_params(sdev, &hal_req, data, len);
+ if (reply_status) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+ if (!ndev_vif->activated) {
+ SLSI_WARN(sdev, "NAN vif not activated\n");
+ reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+ ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
+ } else {
+ ret = slsi_mlme_nan_set_config(sdev, dev, &hal_req);
+ if (ret)
+ reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+ }
+ SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+exit:
+ slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_CONFIG, 0, NULL);
+ return ret;
+}
+
+int slsi_nan_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
+{
+ struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+ struct net_device *dev = slsi_nan_get_netdev(sdev);
+ struct netdev_vif *ndev_vif;
+ u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
+ struct slsi_hal_nan_capabilities nan_capabilities;
+ int ret = 0, i;
+ struct slsi_mib_value *values = NULL;
+ struct slsi_mib_data mibrsp = { 0, NULL };
+ struct slsi_mib_get_entry get_values[] = {{ SLSI_PSID_UNIFI_NAN_MAX_CONCURRENT_CLUSTERS, { 0, 0 } },
+ { SLSI_PSID_UNIFI_NAN_MAX_CONCURRENT_PUBLISHES, { 0, 0 } },
+ { SLSI_PSID_UNIFI_NAN_MAX_CONCURRENT_SUBSCRIBES, { 0, 0 } },
+ { SLSI_PSID_UNIFI_NAN_MAX_SERVICE_NAME_LENGTH, { 0, 0 } },
+ { SLSI_PSID_UNIFI_NAN_MAX_MATCH_FILTER_LENGTH, { 0, 0 } },
+ { SLSI_PSID_UNIFI_NAN_MAX_TOTAL_MATCH_FILTER_LENGTH, { 0, 0 } },
+ { SLSI_PSID_UNIFI_NAN_MAX_SERVICE_SPECIFIC_INFO_LENGTH, { 0, 0 } },
+ { SLSI_PSID_UNIFI_NAN_MAX_VSA_DATA_LENGTH, { 0, 0 } },
+ { SLSI_PSID_UNIFI_NAN_MAX_MESH_DATA_LENGTH, { 0, 0 } },
+ { SLSI_PSID_UNIFI_NAN_MAX_NDI_INTERFACES, { 0, 0 } },
+ { SLSI_PSID_UNIFI_NAN_MAX_NDP_SESSIONS, { 0, 0 } },
+ { SLSI_PSID_UNIFI_NAN_MAX_APP_INFO_LENGTH, { 0, 0 } } };
+ u32 *capabilities_mib_val[] = { &nan_capabilities.max_concurrent_nan_clusters,
+ &nan_capabilities.max_publishes,
+ &nan_capabilities.max_subscribes,
+ &nan_capabilities.max_service_name_len,
+ &nan_capabilities.max_match_filter_len,
+ &nan_capabilities.max_total_match_filter_len,
+ &nan_capabilities.max_service_specific_info_len,
+ &nan_capabilities.max_vsa_data_len,
+ &nan_capabilities.max_mesh_data_len,
+ &nan_capabilities.max_ndi_interfaces,
+ &nan_capabilities.max_ndp_sessions,
+ &nan_capabilities.max_app_info_len };
+
+ if (!dev) {
+ SLSI_ERR(sdev, "NAN netif not active!!");
+ reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ ndev_vif = netdev_priv(dev);
+
+ /* Expect each mib length in response is 11 */
+ mibrsp.dataLength = 11 * ARRAY_SIZE(get_values);
+ mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL);
+ if (!mibrsp.data) {
+ SLSI_ERR(sdev, "Cannot kmalloc %d bytes\n", mibrsp.dataLength);
+ reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE;
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+
+ values = slsi_read_mibs(sdev, NULL, get_values, ARRAY_SIZE(get_values), &mibrsp);
+ if (!values) {
+ ret = 0xFFFFFFFF;
+ reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+ goto exit_with_mibrsp;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(get_values); i++) {
+ if (values[i].type == SLSI_MIB_TYPE_UINT) {
+ *capabilities_mib_val[i] = values[i].u.uintValue;
+ SLSI_DBG2(sdev, SLSI_GSCAN, "MIB value = %ud\n", *capabilities_mib_val[i]);
+ } else {
+ SLSI_ERR(sdev, "invalid type(%d). iter:%d\n", values[i].type, i);
+ ret = 0xFFFFFFFF;
+ reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+ *capabilities_mib_val[i] = 0;
+ }
+ }
+
+ kfree(values);
+exit_with_mibrsp:
+ kfree(mibrsp.data);
+ SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+exit:
+ slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_GET_CAPABILITIES, 0, &nan_capabilities);
+ return ret;
+}
+
+void slsi_nan_event(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb)
+{
+ struct sk_buff *nl_skb = NULL;
+ int res = 0;
+ u16 event, identifier, evt_reason;
+ u8 *mac_addr;
+ u16 hal_event;
+ struct nlattr *nlattr_start;
+ struct netdev_vif *ndev_vif;
+ enum slsi_nan_disc_event_type disc_event_type = 0;
+
+ ndev_vif = netdev_priv(dev);
+ event = fapi_get_u16(skb, u.mlme_nan_event_ind.event);
+ identifier = fapi_get_u16(skb, u.mlme_nan_event_ind.identifier);
+ mac_addr = fapi_get_buff(skb, u.mlme_nan_event_ind.address_or_identifier);
+ evt_reason = fapi_get_u16(skb, u.mlme_nan_event_ind.reason_code);
+
+ switch (event) {
+ case FAPI_EVENT_WIFI_EVENT_NAN_PUBLISH_TERMINATED:
+ hal_event = SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT;
+ break;
+ case FAPI_EVENT_WIFI_EVENT_NAN_MATCH_EXPIRED:
+ hal_event = SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT;
+ break;
+ case FAPI_EVENT_WIFI_EVENT_NAN_SUBSCRIBE_TERMINATED:
+ hal_event = SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT;
+ break;
+ case FAPI_EVENT_WIFI_EVENT_NAN_ADDRESS_CHANGED:
+ disc_event_type = NAN_EVENT_ID_DISC_MAC_ADDR;
+ hal_event = SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT;
+ break;
+ case FAPI_EVENT_WIFI_EVENT_NAN_CLUSTER_STARTED:
+ disc_event_type = NAN_EVENT_ID_STARTED_CLUSTER;
+ hal_event = SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT;
+ break;
+ case FAPI_EVENT_WIFI_EVENT_NAN_CLUSTER_JOINED:
+ disc_event_type = NAN_EVENT_ID_JOINED_CLUSTER;
+ hal_event = SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT;
+ break;
+ default:
+ return;
+ }
+
+#ifdef CONFIG_SCSC_WLAN_DEBUG
+ SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n",
+ slsi_print_event_name(hal_event), hal_event);
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
+ nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, hal_event, GFP_KERNEL);
+#else
+ nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, hal_event, GFP_KERNEL);
+#endif
+ if (!nl_skb) {
+ SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n");
+ return;
+ }
+
+ nlattr_start = nla_nest_start(nl_skb, NL80211_ATTR_VENDOR_DATA);
+ if (!nlattr_start) {
+ SLSI_ERR(sdev, "failed to put NL80211_ATTR_VENDOR_DATA\n");
+ /* Dont use slsi skb wrapper for this free */
+ kfree_skb(nl_skb);
+ return;
+ }
+
+ switch (hal_event) {
+ case SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT:
+ res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_PUBLISH_ID, identifier);
+ res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_PUBLISH_ID, evt_reason);
+ ndev_vif->nan.publish_id_map &= ~BIT(identifier);
+ break;
+ case SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT:
+ res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID, identifier);
+ res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_MATCH_REQUESTOR_INSTANCE_ID, evt_reason);
+ break;
+ case SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT:
+ res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_SUBSCRIBE_ID, identifier);
+ res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_SUBSCRIBE_REASON, evt_reason);
+ ndev_vif->nan.subscribe_id_map &= ~BIT(identifier);
+ break;
+ case SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT:
+ res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_DISCOVERY_ENGINE_EVT_TYPE, disc_event_type);
+ res |= nla_put(nl_skb, NAN_EVT_ATTR_DISCOVERY_ENGINE_MAC_ADDR, ETH_ALEN, mac_addr);
+ break;
+ }
+
+ if (res) {
+ SLSI_ERR(sdev, "Error in nla_put*:%x\n", res);
+ /* Dont use slsi skb wrapper for this free */
+ kfree_skb(nl_skb);
+ return;
+ }
+
+ nla_nest_end(nl_skb, nlattr_start);
+
+ cfg80211_vendor_event(nl_skb, GFP_KERNEL);
+}
+
+void slsi_nan_followup_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb)
+{
+ u16 tag_id, tag_len;
+ u8 *fapi_data_p, *ptr;
+ u8 followup_ie_header[] = {0xdd, 0, 0, 0x16, 0x32, 0x0b, 0x05};
+ int fapi_data_len;
+ struct slsi_hal_nan_followup_ind *hal_evt;
+ struct sk_buff *nl_skb;
+ int res;
+ struct nlattr *nlattr_start;
+
+ hal_evt = kmalloc(sizeof(*hal_evt), GFP_KERNEL);
+ if (!hal_evt) {
+ SLSI_ERR(sdev, "No memory for service_ind\n");
+ return;
+ }
+ hal_evt->publish_subscribe_id = fapi_get_u16(skb, u.mlme_nan_followup_ind.publish_subscribe_id);
+ hal_evt->requestor_instance_id = fapi_get_u16(skb, u.mlme_nan_followup_ind.requestor_instance_id);
+ fapi_data_p = fapi_get_data(skb);
+ fapi_data_len = fapi_get_datalen(skb);
+ if (!fapi_data_len) {
+ SLSI_ERR(sdev, "mlme_nan_followup_ind no mbulk data\n");
+ kfree(hal_evt);
+ return;
+ }
+
+ memset(&hal_evt, 0, sizeof(hal_evt));
+
+ while (fapi_data_len) {
+ ptr = fapi_data_p;
+ if (fapi_data_len < ptr[1] + 2) {
+ SLSI_ERR(sdev, "len err[avail:%d,ie:%d]\n", fapi_data_len, fapi_data_p[1] + 2);
+ kfree(hal_evt);
+ return;
+ }
+ if (ptr[1] < sizeof(followup_ie_header) - 2 + 6 + 1 + 1) {
+ SLSI_ERR(sdev, "len err[min:%d,ie:%d]\n", (u32)sizeof(followup_ie_header) - 2 + 6 + 1 + 1,
+ fapi_data_p[1] + 2);
+ kfree(hal_evt);
+ return;
+ }
+ if (followup_ie_header[0] != ptr[0] || followup_ie_header[2] != ptr[2] ||
+ followup_ie_header[3] != ptr[3] || followup_ie_header[4] != ptr[4] ||
+ followup_ie_header[5] != ptr[5] || followup_ie_header[6] != ptr[6]) {
+ SLSI_ERR(sdev, "unknown IE:%x-%d\n", fapi_data_p[0], fapi_data_p[1] + 2);
+ kfree(hal_evt);
+ return;
+ }
+
+ ptr += sizeof(followup_ie_header);
+
+ ether_addr_copy(hal_evt->addr, ptr);
+ ptr += ETH_ALEN;
+ ptr += 1; /* skip priority */
+ hal_evt->dw_or_faw = *ptr;
+ ptr += 1;
+ while (fapi_data_p[1] + 2 > (ptr - fapi_data_p) + 4) {
+ tag_id = *(u16 *)ptr;
+ ptr += 2;
+ tag_len = *(u16 *)ptr;
+ ptr += 2;
+ if (fapi_data_p[1] + 2 < (ptr - fapi_data_p) + tag_len) {
+ SLSI_ERR(sdev, "TLV error\n");
+ kfree(hal_evt);
+ return;
+ }
+ if (tag_id == SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO) {
+ hal_evt->service_specific_info_len = tag_len;
+ memcpy(hal_evt->service_specific_info, ptr, tag_len);
+ }
+ ptr += tag_len;
+ }
+
+ fapi_data_p += fapi_data_p[1] + 2;
+ fapi_data_len -= fapi_data_p[1] + 2;
+ }
+
+#ifdef CONFIG_SCSC_WLAN_DEBUG
+ SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n",
+ slsi_print_event_name(SLSI_NL80211_NAN_FOLLOWUP_EVENT), SLSI_NL80211_NAN_FOLLOWUP_EVENT);
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
+ nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_FOLLOWUP_EVENT,
+ GFP_KERNEL);
+#else
+ nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_FOLLOWUP_EVENT,
+ GFP_KERNEL);
+#endif
+
+ if (!nl_skb) {
+ SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n");
+ kfree(hal_evt);
+ return;
+ }
+
+ nlattr_start = nla_nest_start(nl_skb, NL80211_ATTR_VENDOR_DATA);
+ if (!nlattr_start) {
+ SLSI_ERR(sdev, "failed to put NL80211_ATTR_VENDOR_DATA\n");
+ kfree(hal_evt);
+ /* Dont use slsi skb wrapper for this free */
+ kfree_skb(nl_skb);
+ return;
+ }
+
+ res = nla_put_be16(nl_skb, NAN_EVT_ATTR_FOLLOWUP_PUBLISH_SUBSCRIBE_ID,
+ cpu_to_le16(hal_evt->publish_subscribe_id));
+ res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_FOLLOWUP_REQUESTOR_INSTANCE_ID,
+ cpu_to_le16(hal_evt->requestor_instance_id));
+ res |= nla_put(nl_skb, NAN_EVT_ATTR_FOLLOWUP_ADDR, ETH_ALEN, hal_evt->addr);
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_FOLLOWUP_DW_OR_FAW, hal_evt->dw_or_faw);
+ res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO_LEN, hal_evt->service_specific_info_len);
+ if (hal_evt->service_specific_info_len)
+ res |= nla_put(nl_skb, NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO, hal_evt->service_specific_info_len,
+ hal_evt->service_specific_info);
+
+ if (res) {
+ SLSI_ERR(sdev, "Error in nla_put*:%x\n", res);
+ kfree(hal_evt);
+ /* Dont use slsi skb wrapper for this free */
+ kfree_skb(nl_skb);
+ return;
+ }
+
+ nla_nest_end(nl_skb, nlattr_start);
+
+ cfg80211_vendor_event(nl_skb, GFP_KERNEL);
+ kfree(hal_evt);
+}
+
+void slsi_nan_service_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb)
+{
+ u16 tag_id, tag_len;
+ u8 *fapi_data_p, *ptr;
+ u8 match_ie_header[] = {0xdd, 0, 0, 0x16, 0x32, 0x0b, 0x04};
+ int fapi_data_len;
+ struct slsi_hal_nan_match_ind *hal_evt;
+ struct sk_buff *nl_skb;
+ int res, i;
+ struct slsi_hal_nan_receive_post_discovery *discovery_attr;
+ struct slsi_hal_nan_further_availability_channel *famchan;
+ struct nlattr *nlattr_start, *nlattr_nested;
+
+ SLSI_DBG3(sdev, SLSI_GSCAN, "\n");
+
+ hal_evt = kmalloc(sizeof(*hal_evt), GFP_KERNEL);
+ if (!hal_evt) {
+ SLSI_ERR(sdev, "No memory for service_ind\n");
+ return;
+ }
+
+ hal_evt->publish_subscribe_id = fapi_get_u16(skb, u.mlme_nan_service_ind.publish_subscribe_id);
+ hal_evt->requestor_instance_id = fapi_get_u32(skb, u.mlme_nan_service_ind.requestor_instance_id);
+ fapi_data_p = fapi_get_data(skb);
+ fapi_data_len = fapi_get_datalen(skb);
+ if (!fapi_data_len) {
+ SLSI_ERR(sdev, "mlme_nan_followup_ind no mbulk data\n");
+ kfree(hal_evt);
+ return;
+ }
+
+ memset(hal_evt, 0, sizeof(*hal_evt));
+
+ while (fapi_data_len) {
+ ptr = fapi_data_p;
+ if (fapi_data_len < ptr[1] + 2) {
+ SLSI_ERR(sdev, "len err[avail:%d,ie:%d]\n", fapi_data_len, fapi_data_p[1] + 2);
+ kfree(hal_evt);
+ return;
+ }
+ if (ptr[1] < sizeof(match_ie_header) - 2 + 6 + 1 + 1 + 1) {
+ SLSI_ERR(sdev, "len err[min:%d,ie:%d]\n", (u32)sizeof(match_ie_header) - 2 + 6 + 1 + 1,
+ fapi_data_p[1] + 2);
+ kfree(hal_evt);
+ return;
+ }
+ if (match_ie_header[0] != ptr[0] || match_ie_header[2] != ptr[2] ||
+ match_ie_header[3] != ptr[3] || match_ie_header[4] != ptr[4] ||
+ match_ie_header[5] != ptr[5] || match_ie_header[6] != ptr[6]) {
+ SLSI_ERR(sdev, "unknown IE:%x-%d\n", fapi_data_p[0], fapi_data_p[1] + 2);
+ kfree(hal_evt);
+ return;
+ }
+
+ ptr += sizeof(match_ie_header);
+
+ ether_addr_copy(hal_evt->addr, ptr);
+ ptr += ETH_ALEN;
+ hal_evt->match_occurred_flag = *ptr;
+ ptr += 1;
+ hal_evt->out_of_resource_flag = *ptr;
+ ptr += 1;
+ hal_evt->rssi_value = *ptr;
+ ptr += 1;
+ while (fapi_data_p[1] + 2 > (ptr - fapi_data_p) + 4) {
+ tag_id = *(u16 *)ptr;
+ ptr += 2;
+ tag_len = *(u16 *)ptr;
+ ptr += 2;
+ if (fapi_data_p[1] + 2 < (ptr - fapi_data_p) + tag_len) {
+ SLSI_ERR(sdev, "TLV error\n");
+ kfree(hal_evt);
+ return;
+ }
+ switch (tag_id) {
+ case SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO:
+ hal_evt->service_specific_info_len = tag_len;
+ memcpy(hal_evt->service_specific_info, ptr, tag_len);
+ break;
+ case SLSI_FAPI_NAN_CONFIG_PARAM_CONNECTION_CAPAB:
+ hal_evt->is_conn_capability_valid = 1;
+ if (*ptr & BIT(0))
+ hal_evt->conn_capability.is_wfd_supported = 1;
+ if (*ptr & BIT(1))
+ hal_evt->conn_capability.is_wfds_supported = 1;
+ if (*ptr & BIT(2))
+ hal_evt->conn_capability.is_tdls_supported = 1;
+ if (*ptr & BIT(3))
+ hal_evt->conn_capability.wlan_infra_field = 1;
+ break;
+ case SLSI_FAPI_NAN_CONFIG_PARAM_POST_DISCOVER_PARAM:
+ discovery_attr = &hal_evt->discovery_attr[hal_evt->num_rx_discovery_attr];
+ discovery_attr->type = ptr[0];
+ discovery_attr->role = ptr[1];
+ discovery_attr->duration = ptr[2];
+ discovery_attr->avail_interval_bitmap = le32_to_cpu(*(__le32 *)&ptr[3]);
+ ether_addr_copy(discovery_attr->addr, &ptr[7]);
+ discovery_attr->infrastructure_ssid_len = ptr[13];
+ if (discovery_attr->infrastructure_ssid_len)
+ memcpy(discovery_attr->infrastructure_ssid_val, &ptr[14],
+ discovery_attr->infrastructure_ssid_len);
+ hal_evt->num_rx_discovery_attr++;
+ break;
+ case SLSI_FAPI_NAN_CONFIG_PARAM_FURTHER_AVAIL_CHANNEL_MAP:
+ famchan = &hal_evt->famchan[hal_evt->num_chans];
+ famchan->entry_control = ptr[0];
+ famchan->class_val = ptr[1];
+ famchan->channel = ptr[2];
+ famchan->mapid = ptr[3];
+ famchan->avail_interval_bitmap = le32_to_cpu(*(__le32 *)&ptr[4]);
+ hal_evt->num_chans++;
+ break;
+ case SLSI_FAPI_NAN_CLUSTER_ATTRIBUTE:
+ break;
+ }
+ ptr += tag_len;
+ }
+
+ fapi_data_p += fapi_data_p[1] + 2;
+ fapi_data_len -= fapi_data_p[1] + 2;
+ }
+
+#ifdef CONFIG_SCSC_WLAN_DEBUG
+ SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n",
+ slsi_print_event_name(SLSI_NL80211_NAN_MATCH_EVENT), SLSI_NL80211_NAN_MATCH_EVENT);
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
+ nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_MATCH_EVENT,
+ GFP_KERNEL);
+#else
+ nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_MATCH_EVENT, GFP_KERNEL);
+#endif
+ if (!nl_skb) {
+ SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n");
+ kfree(hal_evt);
+ return;
+ }
+
+ nlattr_start = nla_nest_start(nl_skb, NL80211_ATTR_VENDOR_DATA);
+ if (!nlattr_start) {
+ SLSI_ERR(sdev, "failed to put NL80211_ATTR_VENDOR_DATA\n");
+ kfree(hal_evt);
+ /* Dont use slsi skb wrapper for this free */
+ kfree_skb(nl_skb);
+ return;
+ }
+
+ res = nla_put_u16(nl_skb, NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID, hal_evt->publish_subscribe_id);
+ res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_MATCH_REQUESTOR_INSTANCE_ID, hal_evt->requestor_instance_id);
+ res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_ADDR, ETH_ALEN, hal_evt->addr);
+ res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO_LEN, hal_evt->service_specific_info_len);
+ if (hal_evt->service_specific_info_len)
+ res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO, hal_evt->service_specific_info_len,
+ hal_evt->service_specific_info);
+ res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER_LEN, hal_evt->sdf_match_filter_len);
+ if (hal_evt->sdf_match_filter_len)
+ res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER, hal_evt->sdf_match_filter_len,
+ hal_evt->sdf_match_filter);
+
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_MATCH_OCCURRED_FLAG, hal_evt->match_occurred_flag);
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_OUT_OF_RESOURCE_FLAG, hal_evt->out_of_resource_flag);
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_RSSI_VALUE, hal_evt->rssi_value);
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_IBSS_SUPPORTED,
+ hal_evt->is_conn_capability_valid);
+ if (hal_evt->is_conn_capability_valid) {
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_IBSS_SUPPORTED,
+ hal_evt->conn_capability.is_ibss_supported);
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFD_SUPPORTED,
+ hal_evt->conn_capability.is_wfd_supported);
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFDS_SUPPORTED,
+ hal_evt->conn_capability.is_wfds_supported);
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_TDLS_SUPPORTED,
+ hal_evt->conn_capability.is_tdls_supported);
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_MESH_SUPPORTED,
+ hal_evt->conn_capability.is_mesh_supported);
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_WLAN_INFRA_FIELD,
+ hal_evt->conn_capability.wlan_infra_field);
+ }
+
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_NUM_RX_DISCOVERY_ATTR, hal_evt->num_rx_discovery_attr);
+ for (i = 0; i < hal_evt->num_rx_discovery_attr; i++) {
+ nlattr_nested = nla_nest_start(nl_skb, NAN_EVT_ATTR_MATCH_RX_DISCOVERY_ATTR);
+ if (!nlattr_nested) {
+ SLSI_ERR(sdev, "Error in nla_nest_start\n");
+ /* Dont use slsi skb wrapper for this free */
+ kfree_skb(nl_skb);
+ kfree(hal_evt);
+ return;
+ }
+ discovery_attr = &hal_evt->discovery_attr[i];
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_TYPE, discovery_attr->type);
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_ROLE, discovery_attr->role);
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_DURATION, discovery_attr->duration);
+ res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_AVAIL_INTERVAL_BITMAP,
+ discovery_attr->avail_interval_bitmap);
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_MAPID, discovery_attr->mapid);
+ res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_ADDR, ETH_ALEN, discovery_attr->addr);
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID_LEN, discovery_attr->mesh_id_len);
+ if (discovery_attr->mesh_id_len)
+ res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID, discovery_attr->mesh_id_len,
+ discovery_attr->mesh_id);
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_LEN,
+ discovery_attr->infrastructure_ssid_len);
+ if (discovery_attr->infrastructure_ssid_len)
+ res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_VAL,
+ discovery_attr->infrastructure_ssid_len, discovery_attr->infrastructure_ssid_val);
+ nla_nest_end(nl_skb, nlattr_nested);
+ }
+
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_NUM_CHANS, hal_evt->num_chans);
+ for (i = 0; i < hal_evt->num_chans; i++) {
+ nlattr_nested = nla_nest_start(nl_skb, NAN_EVT_ATTR_MATCH_FAMCHAN);
+ if (!nlattr_nested) {
+ SLSI_ERR(sdev, "Error in nla_nest_start\n");
+ /* Dont use slsi skb wrapper for this free */
+ kfree_skb(nl_skb);
+ kfree(hal_evt);
+ return;
+ }
+ famchan = &hal_evt->famchan[i];
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_FAM_ENTRY_CONTROL, famchan->entry_control);
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_FAM_CLASS_VAL, famchan->class_val);
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_FAM_CHANNEL, famchan->channel);
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_FAM_MAPID, famchan->mapid);
+ res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_MATCH_FAM_AVAIL_INTERVAL_BITMAP,
+ famchan->avail_interval_bitmap);
+ }
+
+ res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE_LEN, hal_evt->cluster_attribute_len);
+ if (hal_evt->cluster_attribute_len)
+ res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE, hal_evt->cluster_attribute_len,
+ hal_evt->cluster_attribute);
+
+ if (res) {
+ SLSI_ERR(sdev, "Error in nla_put*:%x\n", res);
+ /* Dont use slsi skb wrapper for this free */
+ kfree_skb(nl_skb);
+ kfree(hal_evt);
+ return;
+ }
+
+ nla_nest_end(nl_skb, nlattr_start);
+
+ cfg80211_vendor_event(nl_skb, GFP_KERNEL);
+ kfree(hal_evt);
+}
--- /dev/null
+/*****************************************************************************
+ *
+ * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved
+ *
+ ****************************************************************************/
+#ifndef __SLSI_NL80211_VENDOR_NAN_H_
+#define __SLSI_NL80211_VENDOR_NAN_H_
+
+enum SLSI_NAN_REPLY_ATTRIBUTES {
+ NAN_REPLY_ATTR_STATUS_TYPE,
+ NAN_REPLY_ATTR_VALUE,
+ NAN_REPLY_ATTR_RESPONSE_TYPE,
+ NAN_REPLY_ATTR_PUBLISH_SUBSCRIBE_TYPE,
+ NAN_REPLY_ATTR_CAP_MAX_CONCURRENT_CLUSTER,
+ NAN_REPLY_ATTR_CAP_MAX_PUBLISHES,
+ NAN_REPLY_ATTR_CAP_MAX_SUBSCRIBES,
+ NAN_REPLY_ATTR_CAP_MAX_SERVICE_NAME_LEN,
+ NAN_REPLY_ATTR_CAP_MAX_MATCH_FILTER_LEN,
+ NAN_REPLY_ATTR_CAP_MAX_TOTAL_MATCH_FILTER_LEN,
+ NAN_REPLY_ATTR_CAP_MAX_SERVICE_SPECIFIC_INFO_LEN,
+ NAN_REPLY_ATTR_CAP_MAX_VSA_DATA_LEN,
+ NAN_REPLY_ATTR_CAP_MAX_MESH_DATA_LEN,
+ NAN_REPLY_ATTR_CAP_MAX_NDI_INTERFACES,
+ NAN_REPLY_ATTR_CAP_MAX_NDP_SESSIONS,
+ NAN_REPLY_ATTR_CAP_MAX_APP_INFO_LEN
+};
+
+enum SLSI_NAN_REQ_ATTRIBUTES {
+ NAN_REQ_ATTR_MASTER_PREF,
+ NAN_REQ_ATTR_CLUSTER_LOW,
+ NAN_REQ_ATTR_CLUSTER_HIGH,
+ NAN_REQ_ATTR_HOP_COUNT_LIMIT_VAL,
+ NAN_REQ_ATTR_SID_BEACON_VAL,
+ NAN_REQ_ATTR_SUPPORT_2G4_VAL,
+ NAN_REQ_ATTR_SUPPORT_5G_VAL,
+ NAN_REQ_ATTR_RSSI_CLOSE_2G4_VAL,
+ NAN_REQ_ATTR_RSSI_MIDDLE_2G4_VAL,
+ NAN_REQ_ATTR_RSSI_PROXIMITY_2G4_VAL,
+ NAN_REQ_ATTR_BEACONS_2G4_VAL,
+ NAN_REQ_ATTR_SDF_2G4_VAL,
+ NAN_REQ_ATTR_CHANNEL_2G4_MHZ_VAL,
+ NAN_REQ_ATTR_RSSI_PROXIMITY_VAL,
+ NAN_REQ_ATTR_RSSI_CLOSE_5G_VAL,
+ NAN_REQ_ATTR_RSSI_CLOSE_PROXIMITY_5G_VAL,
+ NAN_REQ_ATTR_RSSI_MIDDLE_5G_VAL,
+ NAN_REQ_ATTR_RSSI_PROXIMITY_5G_VAL,
+ NAN_REQ_ATTR_BEACON_5G_VAL,
+ NAN_REQ_ATTR_SDF_5G_VAL,
+ NAN_REQ_ATTR_CHANNEL_5G_MHZ_VAL,
+ NAN_REQ_ATTR_RSSI_WINDOW_SIZE_VAL,
+ NAN_REQ_ATTR_OUI_VAL,
+ NAN_REQ_ATTR_MAC_ADDR_VAL,
+ NAN_REQ_ATTR_CLUSTER_VAL,
+ NAN_REQ_ATTR_SOCIAL_CH_SCAN_DWELL_TIME,
+ NAN_REQ_ATTR_SOCIAL_CH_SCAN_PERIOD,
+ NAN_REQ_ATTR_RANDOM_FACTOR_FORCE_VAL,
+ NAN_REQ_ATTR_HOP_COUNT_FORCE_VAL,
+ NAN_REQ_ATTR_CONN_CAPABILITY_PAYLOAD_TX,
+ NAN_REQ_ATTR_CONN_CAPABILITY_IBSS,
+ NAN_REQ_ATTR_CONN_CAPABILITY_WFD,
+ NAN_REQ_ATTR_CONN_CAPABILITY_WFDS,
+ NAN_REQ_ATTR_CONN_CAPABILITY_TDLS,
+ NAN_REQ_ATTR_CONN_CAPABILITY_MESH,
+ NAN_REQ_ATTR_CONN_CAPABILITY_WLAN_INFRA,
+ NAN_REQ_ATTR_DISCOVERY_ATTR_NUM_ENTRIES,
+ NAN_REQ_ATTR_DISCOVERY_ATTR_VAL,
+ NAN_REQ_ATTR_CONN_TYPE,
+ NAN_REQ_ATTR_NAN_ROLE,
+ NAN_REQ_ATTR_TRANSMIT_FREQ,
+ NAN_REQ_ATTR_AVAILABILITY_DURATION,
+ NAN_REQ_ATTR_AVAILABILITY_INTERVAL,
+ NAN_REQ_ATTR_MESH_ID_LEN,
+ NAN_REQ_ATTR_MESH_ID,
+ NAN_REQ_ATTR_INFRASTRUCTURE_SSID_LEN,
+ NAN_REQ_ATTR_INFRASTRUCTURE_SSID,
+ NAN_REQ_ATTR_FURTHER_AVAIL_NUM_ENTRIES,
+ NAN_REQ_ATTR_FURTHER_AVAIL_VAL,
+ NAN_REQ_ATTR_FURTHER_AVAIL_ENTRY_CTRL,
+ NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_CLASS,
+ NAN_REQ_ATTR_FURTHER_AVAIL_CHAN,
+ NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_MAPID,
+ NAN_REQ_ATTR_FURTHER_AVAIL_INTERVAL_BITMAP,
+ NAN_REQ_ATTR_PUBLISH_ID,
+ NAN_REQ_ATTR_PUBLISH_TTL,
+ NAN_REQ_ATTR_PUBLISH_PERIOD,
+ NAN_REQ_ATTR_PUBLISH_TYPE,
+ NAN_REQ_ATTR_PUBLISH_TX_TYPE,
+ NAN_REQ_ATTR_PUBLISH_COUNT,
+ NAN_REQ_ATTR_PUBLISH_SERVICE_NAME_LEN,
+ NAN_REQ_ATTR_PUBLISH_SERVICE_NAME,
+ NAN_REQ_ATTR_PUBLISH_MATCH_ALGO,
+ NAN_REQ_ATTR_PUBLISH_SERVICE_INFO_LEN,
+ NAN_REQ_ATTR_PUBLISH_SERVICE_INFO,
+ NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER_LEN,
+ NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER,
+ NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER_LEN,
+ NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER,
+ NAN_REQ_ATTR_PUBLISH_RSSI_THRESHOLD_FLAG,
+ NAN_REQ_ATTR_PUBLISH_CONN_MAP,
+ NAN_REQ_ATTR_PUBLISH_RECV_IND_CFG,
+ NAN_REQ_ATTR_SUBSCRIBE_ID,
+ NAN_REQ_ATTR_SUBSCRIBE_TTL,
+ NAN_REQ_ATTR_SUBSCRIBE_PERIOD,
+ NAN_REQ_ATTR_SUBSCRIBE_TYPE,
+ NAN_REQ_ATTR_SUBSCRIBE_RESP_FILTER_TYPE,
+ NAN_REQ_ATTR_SUBSCRIBE_RESP_INCLUDE,
+ NAN_REQ_ATTR_SUBSCRIBE_USE_RESP_FILTER,
+ NAN_REQ_ATTR_SUBSCRIBE_SSI_REQUIRED,
+ NAN_REQ_ATTR_SUBSCRIBE_MATCH_INDICATOR,
+ NAN_REQ_ATTR_SUBSCRIBE_COUNT,
+ NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME_LEN,
+ NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME,
+ NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO_LEN,
+ NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO,
+ NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER_LEN,
+ NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER,
+ NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER_LEN,
+ NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER,
+ NAN_REQ_ATTR_SUBSCRIBE_RSSI_THRESHOLD_FLAG,
+ NAN_REQ_ATTR_SUBSCRIBE_CONN_MAP,
+ NAN_REQ_ATTR_SUBSCRIBE_NUM_INTF_ADDR_PRESENT,
+ NAN_REQ_ATTR_SUBSCRIBE_INTF_ADDR,
+ NAN_REQ_ATTR_SUBSCRIBE_RECV_IND_CFG,
+ NAN_REQ_ATTR_FOLLOWUP_ID,
+ NAN_REQ_ATTR_FOLLOWUP_REQUESTOR_ID,
+ NAN_REQ_ATTR_FOLLOWUP_ADDR,
+ NAN_REQ_ATTR_FOLLOWUP_PRIORITY,
+ NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME_LEN,
+ NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME,
+ NAN_REQ_ATTR_FOLLOWUP_TX_WINDOW,
+ NAN_REQ_ATTR_FOLLOWUP_RECV_IND_CFG
+};
+
+enum SLSI_NAN_RESP_ATTRIBUTES {
+ NAN_RESP_ATTR_MAX_CONCURRENT_NAN_CLUSTERS,
+ NAN_RESP_ATTR_MAX_PUBLISHES,
+ NAN_RESP_ATTR_MAX_SUBSCRIBES,
+ NAN_RESP_ATTR_MAX_SERVICE_NAME_LEN,
+ NAN_RESP_ATTR_MAX_MATCH_FILTER_LEN,
+ NAN_RESP_ATTR_MAX_TOTAL_MATCH_FILTER_LEN,
+ NAN_RESP_ATTR_MAX_SERVICE_SPECIFIC_INFO_LEN,
+ NAN_RESP_ATTR_MAX_VSA_DATA_LEN,
+ NAN_RESP_ATTR_MAX_MESH_DATA_LEN,
+ NAN_RESP_ATTR_MAX_NDI_INTERFACES,
+ NAN_RESP_ATTR_MAX_NDP_SESSIONS,
+ NAN_RESP_ATTR_MAX_APP_INFO_LEN,
+ NAN_RESP_ATTR_SUBSCRIBE_ID,
+ NAN_RESP_ATTR_PUBLISH_ID
+};
+
+enum SLSI_NAN_EVT_ATTRIBUTES {
+ NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID,
+ NAN_EVT_ATTR_MATCH_REQUESTOR_INSTANCE_ID,
+ NAN_EVT_ATTR_MATCH_ADDR,
+ NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO_LEN,
+ NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO,
+ NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER_LEN,
+ NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER,
+ NAN_EVT_ATTR_MATCH_MATCH_OCCURRED_FLAG,
+ NAN_EVT_ATTR_MATCH_OUT_OF_RESOURCE_FLAG,
+ NAN_EVT_ATTR_MATCH_RSSI_VALUE,
+ /*CONN_CAPABILITY*/
+ NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFD_SUPPORTED,
+ NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFDS_SUPPORTED,
+ NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_TDLS_SUPPORTED,
+ NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_IBSS_SUPPORTED,
+ NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_MESH_SUPPORTED,
+ NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_WLAN_INFRA_FIELD,
+ NAN_EVT_ATTR_MATCH_NUM_RX_DISCOVERY_ATTR,
+ NAN_EVT_ATTR_MATCH_RX_DISCOVERY_ATTR,
+ /*NANRECEIVEPOSTDISCOVERY DISCOVERY_ATTR,*/
+ NAN_EVT_ATTR_MATCH_DISC_ATTR_TYPE,
+ NAN_EVT_ATTR_MATCH_DISC_ATTR_ROLE,
+ NAN_EVT_ATTR_MATCH_DISC_ATTR_DURATION,
+ NAN_EVT_ATTR_MATCH_DISC_ATTR_AVAIL_INTERVAL_BITMAP,
+ NAN_EVT_ATTR_MATCH_DISC_ATTR_MAPID,
+ NAN_EVT_ATTR_MATCH_DISC_ATTR_ADDR,
+ NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID_LEN,
+ NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID,
+ NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_LEN,
+ NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_VAL,
+ NAN_EVT_ATTR_MATCH_NUM_CHANS,
+ NAN_EVT_ATTR_MATCH_FAMCHAN,
+ /*FAMCHAN[32],*/
+ NAN_EVT_ATTR_MATCH_FAM_ENTRY_CONTROL,
+ NAN_EVT_ATTR_MATCH_FAM_CLASS_VAL,
+ NAN_EVT_ATTR_MATCH_FAM_CHANNEL,
+ NAN_EVT_ATTR_MATCH_FAM_MAPID,
+ NAN_EVT_ATTR_MATCH_FAM_AVAIL_INTERVAL_BITMAP,
+ NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE_LEN,
+ NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE,
+ NAN_EVT_ATTR_PUBLISH_ID,
+ NAN_EVT_ATTR_PUBLISH_REASON,
+ NAN_EVT_ATTR_SUBSCRIBE_ID,
+ NAN_EVT_ATTR_SUBSCRIBE_REASON,
+ NAN_EVT_ATTR_DISABLED_REASON,
+ NAN_EVT_ATTR_FOLLOWUP_PUBLISH_SUBSCRIBE_ID,
+ NAN_EVT_ATTR_FOLLOWUP_REQUESTOR_INSTANCE_ID,
+ NAN_EVT_ATTR_FOLLOWUP_ADDR,
+ NAN_EVT_ATTR_FOLLOWUP_DW_OR_FAW,
+ NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO_LEN,
+ NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO,
+ NAN_EVT_ATTR_DISCOVERY_ENGINE_EVT_TYPE,
+ NAN_EVT_ATTR_DISCOVERY_ENGINE_MAC_ADDR,
+ NAN_EVT_ATTR_DISCOVERY_ENGINE_CLUSTER
+};
+
+#define SLSI_FAPI_NAN_CONFIG_PARAM_SID_BEACON 0X0003
+#define SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_CLOSE 0X0004
+#define SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_MIDDLE 0X0005
+#define SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_PROXIMITY 0X0006
+#define SLSI_FAPI_NAN_CONFIG_PARAM_BAND_USAGE 0X0007
+#define SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_CLOSE 0X0008
+#define SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_MIDDLE 0X0009
+#define SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_PROXIMITY 0X000A
+#define SLSI_FAPI_NAN_CONFIG_PARAM_HOP_COUNT_LIMIT 0X000B
+#define SLSI_FAPI_NAN_CONFIG_PARAM_RSSI_WINDOW_SIZE 0X000C
+#define SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_2_4 0X000D
+#define SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_5 0X000E
+#define SLSI_FAPI_NAN_CONFIG_PARAM_MASTER_PREFERENCE 0X000F
+#define SLSI_FAPI_NAN_CONFIG_PARAM_CONNECTION_CAPAB 0X0010
+#define SLSI_FAPI_NAN_CONFIG_PARAM_POST_DISCOVER_PARAM 0X0011
+#define SLSI_FAPI_NAN_CONFIG_PARAM_FURTHER_AVAIL_CHANNEL_MAP 0X0012
+#define SLSI_FAPI_NAN_CONFIG_PARAM_ADDR_RANDOM_INTERVAL 0X0013
+#define SLSI_FAPI_NAN_SERVICE_NAME 0X0020
+#define SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO 0X0021
+#define SLSI_FAPI_NAN_RX_MATCH_FILTER 0X0022
+#define SLSI_FAPI_NAN_TX_MATCH_FILTER 0X0023
+#define SLSI_FAPI_NAN_SDF_MATCH_FILTER 0X0024
+#define SLSI_FAPI_NAN_CLUSTER_ATTRIBUTE 0X0025
+
+#define SLSI_HAL_NAN_MAX_SOCIAL_CHANNELS 3
+#define SLSI_HAL_NAN_MAX_SERVICE_NAME_LEN 255
+#define SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN 1024
+#define SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN 255
+#define SLSI_HAL_NAN_MAX_SUBSCRIBE_MAX_ADDRESS 42
+#define SLSI_HAL_NAN_MAX_POSTDISCOVERY_LEN 5
+
+enum slsi_wifi_hal_nan_status_type {
+ /* NAN Protocol Response Codes */
+ SLSI_HAL_NAN_STATUS_SUCCESS = 0,
+ /* NAN Discovery Engine/Host driver failures */
+ SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE = 1,
+ /* NAN OTA failures */
+ SLSI_HAL_NAN_STATUS_PROTOCOL_FAILURE = 2,
+ /* if the publish/subscribe id is invalid */
+ SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID = 3,
+ /* If we run out of resources allocated */
+ SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE = 4,
+ /* if invalid params are passed */
+ SLSI_HAL_NAN_STATUS_INVALID_PARAM = 5,
+ /* if the requestor instance id is invalid */
+ SLSI_HAL_NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID = 6,
+ /* if the ndp id is invalid */
+ SLSI_HAL_NAN_STATUS_INVALID_NDP_ID = 7,
+ /* if NAN is enabled when wifi is turned off */
+ SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED = 8,
+ /* if over the air ack is not received */
+ SLSI_HAL_NAN_STATUS_NO_OTA_ACK = 9,
+ /* If NAN is already enabled and we are try to re-enable the same */
+ SLSI_HAL_NAN_STATUS_ALREADY_ENABLED = 10,
+ /* If followup message internal queue is full */
+ SLSI_HAL_NAN_STATUS_FOLLOWUP_QUEUE_FULL = 11,
+ /* Unsupported concurrency session enabled, NAN disabled notified */
+ SLSI_HAL_NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED = 12
+};
+
+enum slsi_nan_status_type {
+ /* NAN Protocol Response Codes */
+ NAN_STATUS_SUCCESS = 0,
+ NAN_STATUS_TIMEOUT = 1,
+ NAN_STATUS_DE_FAILURE = 2,
+ NAN_STATUS_INVALID_MSG_VERSION = 3,
+ NAN_STATUS_INVALID_MSG_LEN = 4,
+ NAN_STATUS_INVALID_MSG_ID = 5,
+ NAN_STATUS_INVALID_HANDLE = 6,
+ NAN_STATUS_NO_SPACE_AVAILABLE = 7,
+ NAN_STATUS_INVALID_PUBLISH_TYPE = 8,
+ NAN_STATUS_INVALID_TX_TYPE = 9,
+ NAN_STATUS_INVALID_MATCH_ALGORITHM = 10,
+ NAN_STATUS_DISABLE_IN_PROGRESS = 11,
+ NAN_STATUS_INVALID_TLV_LEN = 12,
+ NAN_STATUS_INVALID_TLV_TYPE = 13,
+ NAN_STATUS_MISSING_TLV_TYPE = 14,
+ NAN_STATUS_INVALID_TOTAL_TLVS_LEN = 15,
+ NAN_STATUS_INVALID_MATCH_HANDLE = 16,
+ NAN_STATUS_INVALID_TLV_VALUE = 17,
+ NAN_STATUS_INVALID_TX_PRIORITY = 18,
+ NAN_STATUS_INVALID_CONNECTION_MAP = 19,
+ NAN_STATUS_INVALID_TCA_ID = 20,
+ NAN_STATUS_INVALID_STATS_ID = 21,
+ NAN_STATUS_NAN_NOT_ALLOWED = 22,
+ NAN_STATUS_NO_OTA_ACK = 23,
+ NAN_STATUS_TX_FAIL = 24,
+ /* 25-4095 Reserved */
+ /* NAN Configuration Response codes */
+ NAN_STATUS_INVALID_RSSI_CLOSE_VALUE = 4096,
+ NAN_STATUS_INVALID_RSSI_MIDDLE_VALUE = 4097,
+ NAN_STATUS_INVALID_HOP_COUNT_LIMIT = 4098,
+ NAN_STATUS_INVALID_MASTER_PREFERENCE_VALUE = 4099,
+ NAN_STATUS_INVALID_LOW_CLUSTER_ID_VALUE = 4100,
+ NAN_STATUS_INVALID_HIGH_CLUSTER_ID_VALUE = 4101,
+ NAN_STATUS_INVALID_BACKGROUND_SCAN_PERIOD = 4102,
+ NAN_STATUS_INVALID_RSSI_PROXIMITY_VALUE = 4103,
+ NAN_STATUS_INVALID_SCAN_CHANNEL = 4104,
+ NAN_STATUS_INVALID_POST_NAN_CONNECTIVITY_CAPABILITIES_BITMAP = 4105,
+ NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_NUMCHAN_VALUE = 4106,
+ NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_DURATION_VALUE = 4107,
+ NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_CLASS_VALUE = 4108,
+ NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_CHANNEL_VALUE = 4109,
+ NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_AVAILABILITY_INTERVAL_BITMAP_VALUE = 4110,
+ NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_MAP_ID = 4111,
+ NAN_STATUS_INVALID_POST_NAN_DISCOVERY_CONN_TYPE_VALUE = 4112,
+ NAN_STATUS_INVALID_POST_NAN_DISCOVERY_DEVICE_ROLE_VALUE = 4113,
+ NAN_STATUS_INVALID_POST_NAN_DISCOVERY_DURATION_VALUE = 4114,
+ NAN_STATUS_INVALID_POST_NAN_DISCOVERY_BITMAP_VALUE = 4115,
+ NAN_STATUS_MISSING_FUTHER_AVAILABILITY_MAP = 4116,
+ NAN_STATUS_INVALID_BAND_CONFIG_FLAGS = 4117,
+ NAN_STATUS_INVALID_RANDOM_FACTOR_UPDATE_TIME_VALUE = 4118,
+ NAN_STATUS_INVALID_ONGOING_SCAN_PERIOD = 4119,
+ NAN_STATUS_INVALID_DW_INTERVAL_VALUE = 4120,
+ NAN_STATUS_INVALID_DB_INTERVAL_VALUE = 4121,
+ /* 4122-8191 RESERVED */
+ NAN_TERMINATED_REASON_INVALID = 8192,
+ NAN_TERMINATED_REASON_TIMEOUT = 8193,
+ NAN_TERMINATED_REASON_USER_REQUEST = 8194,
+ NAN_TERMINATED_REASON_FAILURE = 8195,
+ NAN_TERMINATED_REASON_COUNT_REACHED = 8196,
+ NAN_TERMINATED_REASON_DE_SHUTDOWN = 8197,
+ NAN_TERMINATED_REASON_DISABLE_IN_PROGRESS = 8198,
+ NAN_TERMINATED_REASON_POST_DISC_ATTR_EXPIRED = 8199,
+ NAN_TERMINATED_REASON_POST_DISC_LEN_EXCEEDED = 8200,
+ NAN_TERMINATED_REASON_FURTHER_AVAIL_MAP_EMPTY = 8201
+};
+
+enum slsi_nan_response_type {
+ NAN_RESPONSE_ENABLED = 0,
+ NAN_RESPONSE_DISABLED = 1,
+ NAN_RESPONSE_PUBLISH = 2,
+ NAN_RESPONSE_PUBLISH_CANCEL = 3,
+ NAN_RESPONSE_TRANSMIT_FOLLOWUP = 4,
+ NAN_RESPONSE_SUBSCRIBE = 5,
+ NAN_RESPONSE_SUBSCRIBE_CANCEL = 6,
+ NAN_RESPONSE_STATS = 7,
+ NAN_RESPONSE_CONFIG = 8,
+ NAN_RESPONSE_TCA = 9,
+ NAN_RESPONSE_ERROR = 10,
+ NAN_RESPONSE_BEACON_SDF_PAYLOAD = 11,
+ NAN_RESPONSE_GET_CAPABILITIES = 12
+};
+
+enum slsi_nan_disc_event_type {
+ NAN_EVENT_ID_DISC_MAC_ADDR = 0,
+ NAN_EVENT_ID_STARTED_CLUSTER,
+ NAN_EVENT_ID_JOINED_CLUSTER
+};
+
+struct slsi_hal_nan_social_channel_scan_params {
+ u8 dwell_time[SLSI_HAL_NAN_MAX_SOCIAL_CHANNELS];
+ u16 scan_period[SLSI_HAL_NAN_MAX_SOCIAL_CHANNELS];
+};
+
+struct slsi_hal_nan_connectivity_capability {
+ u8 payload_transmit_flag;
+ u8 is_wfd_supported;
+ u8 is_wfds_supported;
+ u8 is_tdls_supported;
+ u8 is_ibss_supported;
+ u8 is_mesh_supported;
+ u8 wlan_infra_field;
+};
+
+struct slsi_hal_nan_post_discovery_param {
+ u8 type; /* NanConnectionType */
+ u8 role; /* NanDeviceRole */
+ u8 transmit_freq;
+ u8 duration; /* NanAvailDuration */
+ u32 avail_interval_bitmap;
+ u8 addr[ETH_ALEN];
+ u16 mesh_id_len;
+ u8 mesh_id[32];
+ u16 infrastructure_ssid_len;
+ u8 infrastructure_ssid_val[32];
+};
+
+struct slsi_hal_nan_further_availability_channel {
+ /* struct slsi_hal_nan_further_availability_channel*/
+ u8 entry_control;
+ u8 class_val;
+ u8 channel;
+ u8 mapid;
+ u32 avail_interval_bitmap;
+};
+
+struct slsi_hal_nan_further_availability_map {
+ u8 numchans;
+ struct slsi_hal_nan_further_availability_channel famchan[32];
+};
+
+struct slsi_hal_nan_receive_post_discovery {
+ u8 type;
+ u8 role;
+ u8 duration;
+ u32 avail_interval_bitmap;
+ u8 mapid;
+ u8 addr[ETH_ALEN];
+ u16 mesh_id_len;
+ u8 mesh_id[32];
+ u16 infrastructure_ssid_len;
+ u8 infrastructure_ssid_val[32];
+};
+
+struct slsi_hal_nan_enable_req {
+ /* Mandatory parameters below */
+ u8 master_pref;
+ u16 cluster_low;
+ u16 cluster_high;
+
+ u8 config_support_5g;
+ u8 support_5g_val;
+ u8 config_sid_beacon;
+ u8 sid_beacon_val;
+ u8 config_2dot4g_rssi_close;
+ u8 rssi_close_2dot4g_val;
+
+ u8 config_2dot4g_rssi_middle;
+ u8 rssi_middle_2dot4g_val;
+
+ u8 config_2dot4g_rssi_proximity;
+ u8 rssi_proximity_2dot4g_val;
+
+ u8 config_hop_count_limit;
+ u8 hop_count_limit_val;
+
+ u8 config_2dot4g_support;
+ u8 support_2dot4g_val;
+
+ u8 config_2dot4g_beacons;
+ u8 beacon_2dot4g_val;
+ u8 config_2dot4g_sdf;
+ u8 sdf_2dot4g_val;
+ u8 config_5g_beacons;
+ u8 beacon_5g_val;
+ u8 config_5g_sdf;
+ u8 sdf_5g_val;
+ u8 config_5g_rssi_close;
+ u8 rssi_close_5g_val;
+ u8 config_5g_rssi_middle;
+ u8 rssi_middle_5g_val;
+ u8 config_5g_rssi_close_proximity;
+ u8 rssi_close_proximity_5g_val;
+ u8 config_rssi_window_size;
+ u8 rssi_window_size_val;
+ /* The 24 bit Organizationally Unique ID + the 8 bit Network Id. */
+ u8 config_oui;
+ u32 oui_val;
+ u8 config_intf_addr;
+ u8 intf_addr_val[ETH_ALEN];
+
+ u8 config_cluster_attribute_val;
+ u8 config_scan_params;
+ struct slsi_hal_nan_social_channel_scan_params scan_params_val;
+ u8 config_random_factor_force;
+ u8 random_factor_force_val;
+ u8 config_hop_count_force;
+ u8 hop_count_force_val;
+
+ /* channel frequency in MHz to enable Nan on */
+ u8 config_24g_channel;
+ u32 channel_24g_val;
+
+ u8 config_5g_channel;
+ int channel_5g_val;
+};
+
+struct slsi_hal_nan_publish_req {
+ /* id 0 means new publish, any other id is existing publish */
+ u16 publish_id;
+ /* how many seconds to run for. 0 means forever until canceled */
+ u16 ttl;
+ /* periodicity of OTA unsolicited publish.
+ * Specified in increments of 500 ms
+ */
+ u16 period;
+ u8 publish_type;/* 0= unsolicited, solicited = 1, 2= both */
+ u8 tx_type; /* 0 = broadcast, 1= unicast if solicited publish */
+ /* number of OTA Publish, 0 means forever until canceled */
+ u8 publish_count;
+ u16 service_name_len;
+ u8 service_name[SLSI_HAL_NAN_MAX_SERVICE_NAME_LEN];
+ u8 publish_match_indicator;
+
+ u16 service_specific_info_len;
+ u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN];
+
+ u16 rx_match_filter_len;
+ u8 rx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN];
+
+ u16 tx_match_filter_len;
+ u8 tx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN];
+
+ u8 rssi_threshold_flag;
+
+ /* 8-bit bitmap which allows the Host to associate this publish
+ * with a particular Post-NAN Connectivity attribute
+ * which has been sent down in a NanConfigureRequest/NanEnableRequest
+ * message. If the DE fails to find a configured Post-NAN
+ * connectivity attributes referenced by the bitmap,
+ * the DE will return an error code to the Host.
+ * If the Publish is configured to use a Post-NAN Connectivity
+ * attribute and the Host does not refresh the Post-NAN Connectivity
+ * attribute the Publish will be canceled and the Host will be sent
+ * a PublishTerminatedIndication message.
+ */
+ u8 connmap;
+ /* Set/Enable corresponding bits to disable any
+ * indications that follow a publish.
+ * BIT0 - Disable publish termination indication.
+ * BIT1 - Disable match expired indication.
+ * BIT2 - Disable followUp indication received (OTA).
+ */
+ u8 recv_indication_cfg;
+};
+
+struct slsi_hal_nan_subscribe_req {
+ /* id 0 means new subscribe, non zero is existing subscribe */
+ u16 subscribe_id;
+ /* how many seconds to run for. 0 means forever until canceled */
+ u16 ttl;
+ /* periodicity of OTA Active Subscribe. Units in increments
+ * of 500 ms , 0 = attempt every DW
+ */
+ u16 period;
+
+ /* Flag which specifies how the Subscribe request shall be processed. */
+ u8 subscribe_type; /* 0 - PASSIVE , 1- ACTIVE */
+
+ /* Flag which specifies on Active Subscribes how the Service Response
+ * Filter attribute is populated.
+ */
+ u8 service_response_filter; /* 0 - Bloom Filter, 1 - MAC Addr */
+
+ /* Flag which specifies how the Service Response Filter Include
+ * bit is populated.
+ * 0=Do not respond if in the Address Set, 1= Respond
+ */
+ u8 service_response_include;
+
+ /* Flag which specifies if the Service Response Filter
+ * should be used when creating Subscribes.
+ * 0=Do not send the Service Response Filter,1= send
+ */
+ u8 use_service_response_filter;
+
+ /* Flag which specifies if the Service Specific Info is needed in
+ * the Publish message before creating the MatchIndication
+ */
+ u8 ssi_required_for_match_indication; /* 0=Not needed, 1= Required */
+
+ /* Field which specifies how matching indication to host is controlled.
+ * 0 - Match and Indicate Once
+ * 1 - Match and Indicate continuous
+ * 2 - Match and Indicate never. This means don't
+ * indicate match to host.
+ * 3 - Reserved
+ */
+ u8 subscribe_match_indicator;
+
+ /* The number of Subscribe Matches which should occur
+ * before the Subscribe request is automatically terminated.
+ */
+ /* If this value is 0 this field is not used by DE.*/
+ u8 subscribe_count;
+
+ /* length of service name */
+ /* UTF-8 encoded string identifying the service */
+ u16 service_name_len;
+ u8 service_name[SLSI_HAL_NAN_MAX_SERVICE_NAME_LEN];
+
+ /* Sequence of values which further specify the published service
+ * beyond the service name
+ */
+ u16 service_specific_info_len;
+ u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN];
+
+ /* Ordered sequence of <length, value> pairs used to filter out
+ * received publish discovery messages.
+ * This can be sent both for a Passive or an Active Subscribe
+ */
+ u16 rx_match_filter_len;
+ u8 rx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN];
+
+ /* Ordered sequence of <length, value> pairs included in the
+ * Discovery Frame when an Active Subscribe is used.
+ */
+ u16 tx_match_filter_len;
+ u8 tx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN];
+ u8 rssi_threshold_flag;
+
+ u8 connmap;
+ /* NAN Interface Address, conforming to the format as described in
+ * 8.2.4.3.2 of IEEE Std. 802.11-2012.
+ */
+ u8 num_intf_addr_present;
+ u8 intf_addr[SLSI_HAL_NAN_MAX_SUBSCRIBE_MAX_ADDRESS][ETH_ALEN];
+ /* Set/Enable corresponding bits to disable
+ * indications that follow a subscribe.
+ * BIT0 - Disable subscribe termination indication.
+ * BIT1 - Disable match expired indication.
+ * BIT2 - Disable followUp indication received (OTA).
+ */
+ u8 recv_indication_cfg;
+};
+
+struct slsi_hal_nan_transmit_followup_req {
+ /* Publish or Subscribe Id of an earlier Publish/Subscribe */
+ u16 publish_subscribe_id;
+
+ /* This Id is the Requestor Instance that is passed as
+ * part of earlier MatchInd/FollowupInd message.
+ */
+ u32 requestor_instance_id;
+ u8 addr[ETH_ALEN]; /* Unicast address */
+ u8 priority; /* priority of the request 2=high */
+ u8 dw_or_faw; /* 0= send in a DW, 1=send in FAW */
+
+ /* Sequence of values which further specify the published service beyond
+ * the service name.
+ */
+ u16 service_specific_info_len;
+ u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN];
+ /* Set/Enable corresponding bits to disable
+ * responses after followUp.
+ * BIT0 - Disable followUp response from FW.
+ */
+ u8 recv_indication_cfg;
+};
+
+struct slsi_hal_nan_config_req {
+ u8 config_sid_beacon;
+ u8 sid_beacon;
+ u8 config_rssi_proximity;
+ u8 rssi_proximity;
+ u8 config_master_pref;
+ u8 master_pref;
+ /* 1 byte value which defines the RSSI filter threshold.
+ * Any Service Descriptors received above this value
+ * that are configured for RSSI filtering will be dropped.
+ * The rssi values should be specified without sign.
+ * For eg: -70dBm should be specified as 70.
+ */
+ u8 config_5g_rssi_close_proximity;
+ u8 rssi_close_proximity_5g_val;
+ u8 config_rssi_window_size;
+ u16 rssi_window_size_val;
+ /* If set to 1, the Discovery Engine will enclose the Cluster
+ * Attribute only sent in Beacons in a Vendor Specific Attribute
+ * and transmit in a Service Descriptor Frame.
+ */
+ u8 config_cluster_attribute_val;
+ u8 config_scan_params;
+ struct slsi_hal_nan_social_channel_scan_params scan_params_val;
+ /* 1 byte quantity which forces the Random Factor to a particular
+ * value for all transmitted Sync/Discovery beacons
+ */
+ u8 config_random_factor_force;
+ u8 random_factor_force_val;
+ /* 1 byte quantity which forces the HC for all transmitted Sync and
+ * Discovery Beacon NO matter the real HC being received over the
+ * air.
+ */
+ u8 config_hop_count_force;
+ u8 hop_count_force_val;
+ /* NAN Post Connectivity Capability */
+ u8 config_conn_capability;
+ struct slsi_hal_nan_connectivity_capability conn_capability_val;
+ /* NAN Post Discover Capability */
+ u8 num_config_discovery_attr;
+ struct slsi_hal_nan_post_discovery_param discovery_attr_val[SLSI_HAL_NAN_MAX_POSTDISCOVERY_LEN];
+ /* NAN Further availability Map */
+ u8 config_fam;
+ struct slsi_hal_nan_further_availability_map fam_val;
+};
+
+struct slsi_hal_nan_capabilities {
+ u32 max_concurrent_nan_clusters;
+ u32 max_publishes;
+ u32 max_subscribes;
+ u32 max_service_name_len;
+ u32 max_match_filter_len;
+ u32 max_total_match_filter_len;
+ u32 max_service_specific_info_len;
+ u32 max_vsa_data_len;
+ u32 max_mesh_data_len;
+ u32 max_ndi_interfaces;
+ u32 max_ndp_sessions;
+ u32 max_app_info_len;
+};
+
+struct slsi_hal_nan_followup_ind {
+ u16 publish_subscribe_id;
+ u32 requestor_instance_id;
+ u8 addr[ETH_ALEN];
+ u8 dw_or_faw;
+ u16 service_specific_info_len;
+ u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN];
+};
+
+struct slsi_hal_nan_match_ind {
+ u16 publish_subscribe_id;
+ u32 requestor_instance_id;
+ u8 addr[ETH_ALEN];
+ u16 service_specific_info_len;
+ u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN];
+ u16 sdf_match_filter_len;
+ u8 sdf_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN];
+ u8 match_occurred_flag;
+ u8 out_of_resource_flag;
+ u8 rssi_value;
+ u8 is_conn_capability_valid;
+ struct slsi_hal_nan_connectivity_capability conn_capability;
+ u8 num_rx_discovery_attr;
+ struct slsi_hal_nan_receive_post_discovery discovery_attr[SLSI_HAL_NAN_MAX_POSTDISCOVERY_LEN];
+ u8 num_chans;
+ struct slsi_hal_nan_further_availability_channel famchan[32];
+ u8 cluster_attribute_len;
+ u8 cluster_attribute[32];
+};
+
+void slsi_nan_event(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb);
+void slsi_nan_followup_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb);
+void slsi_nan_service_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb);
+void slsi_nan_get_mac(struct slsi_dev *sdev, char *nan_mac_addr);
+struct net_device *slsi_nan_get_netdev(struct slsi_dev *sdev);
+int slsi_nan_enable(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len);
+int slsi_nan_disable(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len);
+int slsi_nan_publish(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len);
+int slsi_nan_publish_cancel(struct wiphy *wiphy, struct wireless_dev *wdev,
+ const void *data, int len);
+int slsi_nan_subscribe(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len);
+int slsi_nan_subscribe_cancel(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len);
+int slsi_nan_transmit_followup(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len);
+int slsi_nan_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len);
+int slsi_nan_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len);
+#endif
#ifdef CONFIG_SCSC_AP_INTERFACE_NAME
seq_printf(m, "CONFIG_SCSC_AP_INTERFACE_NAME : %s\n", CONFIG_SCSC_AP_INTERFACE_NAME);
#endif
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
+ seq_puts(m, "CONFIG_SCSC_WIFI_NAN_ENABLE : y\n");
+#else
+ seq_puts(m, "CONFIG_SCSC_WIFI_NAN_ENABLE : n\n");
+#endif
return 0;
}
char buf[20];
char nan_mac[ETH_ALEN];
int pos = 0;
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
struct slsi_dev *sdev = (struct slsi_dev *)file->private_data;
- SLSI_UNUSED_PARAMETER(file);
slsi_nan_get_mac(sdev, nan_mac);
+#else
+
+ SLSI_UNUSED_PARAMETER(file);
+ memset(nan_mac, 0, ETH_ALEN);
+#endif
pos = scnprintf(buf, sizeof(buf), "%pM", nan_mac);
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
/****************************************************************************
*
- * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved
+ * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved
*
****************************************************************************/
#include <linux/types.h>
case MLME_EVENT_LOG_IND:
slsi_rx_event_log_indication(sdev, dev, skb);
break;
-#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE
+#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
case MLME_NAN_EVENT_IND:
slsi_nan_event(sdev, dev, skb);
slsi_kfree_skb(skb);