mwifiex: add support for P2P client in interface type change
authorStone Piao <piaoyun@marvell.com>
Wed, 26 Sep 2012 03:23:41 +0000 (20:23 -0700)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 28 Sep 2012 17:54:05 +0000 (13:54 -0400)
When cfg80211 calls to change interface type for P2P client,
send P2P mode config commands to firmware.

Signed-off-by: Stone Piao <piaoyun@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/fw.h
drivers/net/wireless/mwifiex/sta_cmd.c
drivers/net/wireless/mwifiex/sta_cmdresp.c

index ece267a363804405c31ac8febda38397ba196c4f..499060304d1501aac5ea644590909463c92fd012 100644 (file)
@@ -674,6 +674,44 @@ mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
        return 0;
 }
 
+static int
+mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv)
+{
+       u16 mode = P2P_MODE_DISABLE;
+
+       if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG,
+                                 HostCmd_ACT_GEN_SET, 0, &mode))
+               return -1;
+
+       return 0;
+}
+
+/*
+ * This function initializes the functionalities for P2P client.
+ * The P2P client initialization sequence is:
+ * disable -> device -> client
+ */
+static int
+mwifiex_cfg80211_init_p2p_client(struct mwifiex_private *priv)
+{
+       u16 mode;
+
+       if (mwifiex_cfg80211_deinit_p2p(priv))
+               return -1;
+
+       mode = P2P_MODE_DEVICE;
+       if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG,
+                                 HostCmd_ACT_GEN_SET, 0, &mode))
+               return -1;
+
+       mode = P2P_MODE_CLIENT;
+       if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG,
+                                 HostCmd_ACT_GEN_SET, 0, &mode))
+               return -1;
+
+       return 0;
+}
+
 /*
  * CFG802.11 operation handler to change interface type.
  */
@@ -706,6 +744,11 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
                switch (type) {
                case NL80211_IFTYPE_ADHOC:
                        break;
+               case NL80211_IFTYPE_P2P_CLIENT:
+                       if (mwifiex_cfg80211_init_p2p_client(priv))
+                               return -EFAULT;
+                       dev->ieee80211_ptr->iftype = type;
+                       return 0;
                case NL80211_IFTYPE_UNSPECIFIED:
                        wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name);
                case NL80211_IFTYPE_STATION:    /* This shouldn't happen */
@@ -731,6 +774,17 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
                        return -EOPNOTSUPP;
                }
                break;
+       case NL80211_IFTYPE_P2P_CLIENT:
+               switch (type) {
+               case NL80211_IFTYPE_STATION:
+                       if (mwifiex_cfg80211_deinit_p2p(priv))
+                               return -EFAULT;
+                       dev->ieee80211_ptr->iftype = type;
+                       return 0;
+               default:
+                       return -EOPNOTSUPP;
+               }
+               break;
        default:
                wiphy_err(wiphy, "%s: unknown iftype: %d\n",
                          dev->name, dev->ieee80211_ptr->iftype);
index b8a07ade2e686c415ea5b535abd1107d00e1df8c..7887848448e995c4ac2c5f0b703d8383c7632e53 100644 (file)
@@ -261,6 +261,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define HostCmd_CMD_TX_RATE_CFG                       0x00d6
 #define HostCmd_CMD_802_11_PS_MODE_ENH                0x00e4
 #define HostCmd_CMD_802_11_HS_CFG_ENH                 0x00e5
+#define HostCmd_CMD_P2P_MODE_CFG                      0x00eb
 #define HostCmd_CMD_CAU_REG_ACCESS                    0x00ed
 #define HostCmd_CMD_SET_BSS_MODE                      0x00f7
 #define HostCmd_CMD_PCIE_DESC_DETAILS                 0x00fa
@@ -291,6 +292,13 @@ enum ENH_PS_MODES {
        DIS_AUTO_PS = 0xfe,
 };
 
+enum P2P_MODES {
+       P2P_MODE_DISABLE = 0,
+       P2P_MODE_DEVICE = 1,
+       P2P_MODE_GO = 2,
+       P2P_MODE_CLIENT = 3,
+};
+
 #define HostCmd_RET_BIT                       0x8000
 #define HostCmd_ACT_GEN_GET                   0x0000
 #define HostCmd_ACT_GEN_SET                   0x0001
@@ -1346,6 +1354,11 @@ struct host_cmd_ds_mgmt_frame_reg {
        __le32 mask;
 } __packed;
 
+struct host_cmd_ds_p2p_mode_cfg {
+       __le16 action;
+       __le16 mode;
+} __packed;
+
 struct host_cmd_ds_remain_on_chan {
        __le16 action;
        u8 status;
@@ -1465,6 +1478,7 @@ struct host_cmd_ds_command {
                struct host_cmd_ds_version_ext verext;
                struct host_cmd_ds_mgmt_frame_reg reg_mask;
                struct host_cmd_ds_remain_on_chan roc_cfg;
+               struct host_cmd_ds_p2p_mode_cfg mode_cfg;
                struct host_cmd_ds_802_11_ibss_status ibss_coalescing;
                struct host_cmd_ds_mac_reg_access mac_reg;
                struct host_cmd_ds_bbp_reg_access bbp_reg;
index c2198a798b9fde41958681650567f8374dcd57c6..704cfaaeba1488b77f56ab6b380800cc616d2501 100644 (file)
@@ -1184,6 +1184,14 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
                      cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) +
                                  S_DS_GEN);
                break;
+       case HostCmd_CMD_P2P_MODE_CFG:
+               cmd_ptr->command = cpu_to_le16(cmd_no);
+               cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action);
+               cmd_ptr->params.mode_cfg.mode = cpu_to_le16(*(u16 *)data_buf);
+               cmd_ptr->size =
+                       cpu_to_le16(sizeof(struct host_cmd_ds_p2p_mode_cfg) +
+                                   S_DS_GEN);
+               break;
        case HostCmd_CMD_FUNC_INIT:
                if (priv->adapter->hw_status == MWIFIEX_HW_STATUS_RESET)
                        priv->adapter->hw_status = MWIFIEX_HW_STATUS_READY;
index 621d36e437f55baa6a0b08cdb43b648c57e75402..e380171c4c5dd08918669863d4a756894e46a2e9 100644 (file)
@@ -669,6 +669,22 @@ mwifiex_ret_remain_on_chan(struct mwifiex_private *priv,
        return 0;
 }
 
+/*
+ * This function handles the command response of P2P mode cfg.
+ */
+static int
+mwifiex_ret_p2p_mode_cfg(struct mwifiex_private *priv,
+                        struct host_cmd_ds_command *resp,
+                        void *data_buf)
+{
+       struct host_cmd_ds_p2p_mode_cfg *mode_cfg = &resp->params.mode_cfg;
+
+       if (data_buf)
+               *((u16 *)data_buf) = le16_to_cpu(mode_cfg->mode);
+
+       return 0;
+}
+
 /*
  * This function handles the command response of register access.
  *
@@ -894,6 +910,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
        case HostCmd_CMD_REMAIN_ON_CHAN:
                ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf);
                break;
+       case HostCmd_CMD_P2P_MODE_CFG:
+               ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf);
+               break;
        case HostCmd_CMD_MGMT_FRAME_REG:
        case HostCmd_CMD_FUNC_INIT:
        case HostCmd_CMD_FUNC_SHUTDOWN: