SDIO wifi Marvell8801/Marvell88w8801 介绍(八) ---- Marvell 8801实现STA功能/连接open热点/连接wpa热点/连接wpa2热点

代码工程的GITHUB连接:点进进入GITHUB仓库
https://github.com/sj15712795029/stm32f1_marvell88w8801_marvell8801_wifi

Marvell自己实现驱动系列文章分为几篇介绍:
SDIO wifi Marvell8801/Marvell88w8801 介绍(一) ---- 芯片介绍
SDIO wifi Marvell8801/Marvell88w8801 介绍(二) ---- SDIO协议介绍
SDIO wifi Marvell8801/Marvell88w8801 介绍(三) ---- 寄存器介绍
SDIO wifi Marvell8801/Marvell88w8801 介绍(四) ---- 命令/事件/数据格式
SDIO wifi Marvell8801/Marvell88w8801 介绍(五) ---- TLV
SDIO wifi Marvell8801/Marvell88w8801 介绍(六) ---- 实现初始化功能
SDIO wifi Marvell8801/Marvell88w8801 介绍(七) ---- 实现搜索功能
SDIO wifi Marvell8801/Marvell88w8801 介绍(八) ---- 实现STA功能
SDIO wifi Marvell8801/Marvell88w8801 介绍(九) ---- 实现AP功能
SDIO wifi Marvell8801/Marvell88w8801 介绍(十) ---- 移植TCP/IP协议栈LWIP
SDIO wifi Marvell8801/Marvell88w8801 介绍(十一) ---- 自己编写LWIP没有的DHCP server
SDIO wifi Marvell8801/Marvell88w8801 介绍(十二) ---- MQTT介绍
SDIO wifi Marvell8801/Marvell88w8801 介绍(十三) ---- 百度云操作说明
SDIO wifi Marvell8801/Marvell88w8801 介绍(十四) ---- 上位机STA操作/代码
SDIO wifi Marvell8801/Marvell88w8801 介绍(十五) ---- 上位机AP操作/代码
SDIO wifi Marvell8801/Marvell88w8801 介绍(十六) ---- 上位机UDP操作/代码
SDIO wifi Marvell8801/Marvell88w8801 介绍(十七) ---- 上位机TCP操作/代码
SDIO wifi Marvell8801/Marvell88w8801 介绍(十八) ---- 上位机PING操作/代码
SDIO wifi Marvell8801/Marvell88w8801 介绍(十九) ---- 上位机云服务器(百度云)操作/代码

每篇更新打开专栏可以看到打开Marvell8801/Marvell8801 专栏

在介绍SDIO wifi Marvell8801/Marvell88w8801之前先附上模块链接:点击购买Marvell8801模块 // 点击购买Marvell8801开发板

关于裸机STA模式操作介绍主要分为以下图示几部分
在这里插入图片描述
1)STA连接的命令说明,主要是对连接命令的格式做介绍
2)Marvell8801连接OPEN热点
3)Marvell8801连接WPA热点
4)Marvel8801连接WPA2热点
5)Marvell8801主动断开跟AP的连接
6)连接成功的AP关闭,Marvell8801的动作
另外,在写这个驱动之前我是假设平台的SDIO驱动已经调试OK,如果需要查看SDIO驱动方面,可以直接参照我的裸机代码,另外写这个驱动的目的是让你快速入门Marvell88w8801这颗wifi 芯片,其中没有复杂的802.11n的处理,如果你不想看Linux复杂的驱动,可以通过这个裸机快速入门。

1. STA连接的命令说明

首先说明下连接open wpa wpa2热点都是通过一个函数mrvl88w8801_connect来实现,只是入参不同而已,其中mrvl88w8801_connect函数实现都是这个模样,就是把一些入参信息保存下来,然后执行特定SSID的搜索(这个已经在搜索中介绍过了),然后再搜索返回的地方做连接的动作,mrvl88w8801_connect函数实现如下,另外,其中的TLV请参照文章最后
另外,我们在看下连接的cmd/cmd response的格式,方便对代码的理解
在这里插入图片描述
在这里插入图片描述
消息回应:
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. Marvell88w8801连接OPEN热点

不要被上面的一堆TLV吓到,我们就分别说下不同的连接方式用到的TLV
Open用到的TLV主要如下,以下都是我测过最精简的TLV
1)TLV_TYPE_SSID
2)TLV_TYPE_PHY_DS
3)TLV_TYPE_CF
4)TLV_TYPE_RATES
5)TLV_TYPE_AUTH_TYPE
6)TLV_TYPE_CHANLIST
OK,一共这些,看下代码

if(pmrvl88w8801_core->con_info.con_status == CON_STA_CONNECTING )
{
    /* 做连接的动作 */
    uint8_t rate_tlv[] = {0x01,0x00,0x0c,0x00,0x82,0x84,0x8b,0x8c,0x12,0x96,0x98,0x24,0xb0,0x48,0x60,0x6c};
    uint16_t associate_para_len = 0;
    uint8_t associate_para[256];
    MrvlIEtypes_SSIDParamSet_t *ssid_tlv;
    MrvlIETypes_PhyParamDSSet_t *phy_tlv;
    MrvlIETypes_CfParamSet_t *cf_tlv;
    MrvlIETypes_AuthType_t *auth_tlv;
    MrvlIEtypes_ChanListParamSet_t *channel_list;
    ChanScanParamSet_t *channel_list_para;

    ssid_tlv	=  (MrvlIEtypes_SSIDParamSet_t *)associate_para;
    ssid_tlv->header.type = TLV_TYPE_SSID;
    ssid_tlv->header.len = pmrvl88w8801_core->con_info.ssid_len;
    comp_memcpy(ssid_tlv->ssid,ssid,pmrvl88w8801_core->con_info.ssid_len);
    associate_para_len += sizeof(MrvlIEtypesHeader_t) + pmrvl88w8801_core->con_info.ssid_len;

    phy_tlv = (MrvlIETypes_PhyParamDSSet_t *)(associate_para+associate_para_len);
    phy_tlv->header.type = TLV_TYPE_PHY_DS;
    phy_tlv->header.len = 1;
    phy_tlv->channel = channel;
    associate_para_len +=sizeof(MrvlIETypes_PhyParamDSSet_t);


    cf_tlv = (MrvlIETypes_CfParamSet_t *)(associate_para+associate_para_len);
    comp_memset(cf_tlv,0,sizeof(MrvlIETypes_CfParamSet_t));
    cf_tlv->header.type = TLV_TYPE_CF;
    cf_tlv->header.len = sizeof(MrvlIETypes_CfParamSet_t) - sizeof(MrvlIEtypesHeader_t);
    associate_para_len +=sizeof(MrvlIETypes_CfParamSet_t);

    if(security == WIFI_SECURITYTYPE_NONE)
    {
        auth_tlv = (MrvlIETypes_AuthType_t *)(associate_para+associate_para_len);
        auth_tlv->header.type = TLV_TYPE_AUTH_TYPE;
        auth_tlv->header.len = sizeof(MrvlIETypes_AuthType_t) - sizeof(MrvlIEtypesHeader_t);
        auth_tlv->auth_type = WIFI_AUTH_MODE_OPEN;
        associate_para_len +=sizeof(MrvlIETypes_AuthType_t);
    }

    channel_list = (MrvlIEtypes_ChanListParamSet_t *)(associate_para+associate_para_len);
    channel_list_para = (ChanScanParamSet_t *)(associate_para+associate_para_len + sizeof(MrvlIEtypesHeader_t));
    channel_list->header.type = TLV_TYPE_CHANLIST;
    channel_list->header.len = sizeof(ChanScanParamSet_t);
    channel_list_para->radio_type = 0;
    channel_list_para->chan_number = channel;
    channel_list_para->chan_scan_mode = 0;
    channel_list_para->min_scan_time = 0;
    channel_list_para->max_scan_time = 200;
    associate_para_len +=sizeof(MrvlIEtypes_ChanListParamSet_t);

    comp_memcpy(associate_para+associate_para_len,rate_tlv,sizeof(rate_tlv));
    associate_para_len += sizeof(rate_tlv);

    if(security >= WIFI_SECURITYTYPE_WPA)
    {
        MrvlIETypes_Vendor_t *vendor_tlv;
        MrvlIETypes_RSN_t *rsn_tlv;
        mrvl88w8801_ass_supplicant_pmk_pkg(bss_desc_set->bssid);

        for(index = 0; index < vendor_tlv_count; index++)
        {
            vendor_tlv = (MrvlIETypes_Vendor_t *)(associate_para+associate_para_len);
            vendor_tlv->header.type = TLV_TYPE_VENDOR_SPECIFIC_IE;
            vendor_tlv->header.len = vendor_data_ptr[index]->header.length;
            comp_memcpy(vendor_tlv->vendor,vendor_data_ptr[index]->data,vendor_tlv->header.len);
            associate_para_len += sizeof(MrvlIEtypesHeader_t) + vendor_tlv->header.len;
        }

        if(security == WIFI_SECURITYTYPE_WPA2)
        {
            rsn_tlv = (MrvlIETypes_RSN_t *)(associate_para+associate_para_len);
            rsn_tlv->header.type = TLV_TYPE_RSN_PARAMSET;
            rsn_tlv->header.len = rsn_data_ptr->header.length;
            comp_memcpy(rsn_tlv->rsn,rsn_data_ptr->data,rsn_tlv->header.len);
            associate_para_len += sizeof(MrvlIEtypesHeader_t) + rsn_tlv->header.len;
        }
    }

    comp_memcpy(pmrvl88w8801_core->con_info.mac_address,bss_desc_set->bssid,MAC_ADDR_LENGTH);
    pmrvl88w8801_core->con_info.cap_info = bss_desc_set->cap_info;
    //hw_hex_dump((uint8_t *)&associate_para,associate_para_len);
    mrvl88w8801_prepare_cmd(HostCmd_CMD_802_11_ASSOCIATE,HostCmd_ACT_GEN_GET,&associate_para,associate_para_len);

}

这就是cmd body的部分,在看下cmd header的部分


/******************************************************************************
 *	函数名:	mrvl88w8801_connect_prepare
 * 参数:  	tx(IN)				-->tx buffer
 			data_buff(IN)		-->搜索的cmd body,在这里就是channel list
 			data_len(IN)		-->搜索的cmd body len,在这里就是channel list长度
 * 返回值: 	返回执行结果
 * 描述:	组HostCmd_CMD_802_11_ASSOCIATE command的封包
******************************************************************************/
static uint8_t mrvl88w8801_connect_prepare(uint8_t* tx,void *data_buff,uint16_t data_len)
{
    HostCmd_DS_COMMAND *cmd = (HostCmd_DS_COMMAND *)tx;
    HostCmd_DS_802_11_ASSOCIATE *passociate = &cmd->params.associate;
    uint16_t tx_packet_len = CMD_HDR_SIZE + sizeof(HostCmd_DS_802_11_ASSOCIATE)+data_len-sizeof(passociate->tlv_buffer);

    cmd->pack_len = tx_packet_len;
    cmd->pack_type = TYPE_CMD_CMDRSP;
    cmd->command = HostCmd_CMD_802_11_ASSOCIATE;
    cmd->size = tx_packet_len - CMD_SDIO_HDR_SIZE;
    cmd->seq_num = 0;
    cmd->bss = 0;
    cmd->result = 0;
    comp_memcpy(passociate->peer_sta_addr,pmrvl88w8801_core->con_info.mac_address,MAC_ADDR_LENGTH);
    comp_memcpy(pmrvl88w8801_core->remote_mac_address,pmrvl88w8801_core->con_info.mac_address,MAC_ADDR_LENGTH);
    passociate->cap_info = pmrvl88w8801_core->con_info.cap_info;
    passociate->listen_interval = 0xa;
    passociate->beacon_period = 0x40;
    passociate->dtim_period = 0x0;

    comp_memcpy(passociate->tlv_buffer,data_buff,data_len);

    return COMP_ERR_OK;
}

详细看下代码就知道了,还是那句话,代码是用来看的,不是讲的

3. Marvell88w8801 连接WPA热点

如果你懂了上面部分,那么这部分也不再神秘,只是多了几个TLV和几个cmd而已
Wpa用到的TLV主要如下,以下都是我测过最精简的TLV
1)TLV_TYPE_SSID
2)TLV_TYPE_PHY_DS
3)TLV_TYPE_CF
4)TLV_TYPE_RATES
5)TLV_TYPE_CHANLIST
6)TLV_TYPE_VENDOR_SPECIFIC_IE
7)另外,额外加了一个cmd是HostCmd_CMD_SUPPLICANT_PMK
先介绍下cmd HostCmd_CMD_SUPPLICANT_PMK,这个命令说白了就是如果遇到连接的动作,让芯片做4方握手认证的动作
在这里插入图片描述
在这里插入图片描述
代码如下


/******************************************************************************
 *	函数名:	mrvl88w8801_ass_supplicant_pmk_pkg
 * 参数:  	bssid(IN)				-->mac address
 * 返回值: 	返回执行结果
 * 描述:	组合HostCmd_CMD_SUPPLICANT_PMK cmd封包的cmd body部分,
 			这个命令的主要作用是:
 			如果遇到连接的动作,让芯片做4方握手的认证
******************************************************************************/
static uint8_t mrvl88w8801_ass_supplicant_pmk_pkg(uint8_t *bssid)
{
    uint16_t pmk_len = 0;
    uint8_t pmk_tlv[64];
    MrvlIEtypes_SSIDParamSet_t *pmk_ssid_tlv;
    MrvlIETypes_BSSIDList_t *pmk_bssid_tlv;
    MrvlIEtypes_PASSPhrase_t *pmk_phrase_tlv;

    pmk_ssid_tlv	=  (MrvlIEtypes_SSIDParamSet_t *)pmk_tlv;
    pmk_ssid_tlv->header.type = TLV_TYPE_SSID;
    pmk_ssid_tlv->header.len = pmrvl88w8801_core->con_info.ssid_len;
    comp_memcpy(pmk_ssid_tlv->ssid,pmrvl88w8801_core->con_info.ssid,pmrvl88w8801_core->con_info.ssid_len);
    pmk_len += sizeof(MrvlIEtypesHeader_t) + pmrvl88w8801_core->con_info.ssid_len;

    pmk_bssid_tlv = (MrvlIETypes_BSSIDList_t *)(pmk_tlv+pmk_len);
    pmk_bssid_tlv->header.type = TLV_TYPE_BSSID;
    pmk_bssid_tlv->header.len = MAC_ADDR_LENGTH;
    comp_memcpy(pmk_bssid_tlv->mac_address,bssid,MAC_ADDR_LENGTH);
    pmk_len += sizeof(MrvlIETypes_BSSIDList_t);

    pmk_phrase_tlv = (MrvlIEtypes_PASSPhrase_t *)(pmk_tlv+pmk_len);
    pmk_phrase_tlv->header.type = TLV_TYPE_PASSPHRASE;
    pmk_phrase_tlv->header.len = pmrvl88w8801_core->con_info.pwd_len;
    comp_memcpy(pmk_phrase_tlv->phrase,pmrvl88w8801_core->con_info.pwd,pmrvl88w8801_core->con_info.pwd_len);
    pmk_len += sizeof(MrvlIEtypesHeader_t) + pmrvl88w8801_core->con_info.pwd_len;

    mrvl88w8801_prepare_cmd(HostCmd_CMD_SUPPLICANT_PMK,HostCmd_ACT_GEN_SET,&pmk_tlv,pmk_len);
    return COMP_ERR_OK;
}

收到这个cmd response后,因为我们已经把连接wpa的封包放到mrvl_tx_buffer buffer中去,所以只需要发送出去即可
在这里插入图片描述

4. Marvell88w8801 连接WPA2热点

WPA2和WPA基本一样,但是多了一个TLV_TYPE_RSN_PARAMSET的TLV

5. Marvell88w8801 主动断线

主动断线的命令比较容易,先看下命令组成
在这里插入图片描述
再来看下代码


/******************************************************************************
 *	函数名:	mrvl88w8801_connect_prepare
 * 参数:  	tx(IN)				-->tx buffer
 * 返回值: 	返回执行结果
 * 描述:	组HostCmd_CMD_802_11_DEAUTHENTICATE command的封包
******************************************************************************/
static uint8_t mrvl88w8801_disconnect_prepare(uint8_t* tx)
{
    HostCmd_DS_COMMAND *cmd = (HostCmd_DS_COMMAND *)tx;
    HostCmd_DS_802_11_DEAUTHENTICATE *pdeauth = &cmd->params.deauth;
    uint16_t tx_packet_len = CMD_HDR_SIZE + sizeof(HostCmd_DS_802_11_DEAUTHENTICATE);

    cmd->pack_len = tx_packet_len;
    cmd->pack_type = TYPE_CMD_CMDRSP;
    cmd->command = HostCmd_CMD_802_11_DEAUTHENTICATE;
    cmd->size = tx_packet_len - CMD_SDIO_HDR_SIZE;
    cmd->seq_num = 0;
    cmd->bss = 0;
    cmd->result = 0;
    comp_memcpy(pdeauth->mac_addr,pmrvl88w8801_core->remote_mac_address,MAC_ADDR_LENGTH);
    pdeauth->reason_code = 36;

    return COMP_ERR_OK;
}

完事,相信看了这个,看了代码,你会看懂

6. 连接成功的AP关闭marvell8801的动作

AP关闭,STA会收到一个EVENT EVENT_DEAUTHENTICATED
此部分我们做的处理如下,由于主要是做TCP/IP的link down部分,所以暂时不做解释,你只需要知道会收到这个event就好
在这里插入图片描述

另外,相信你看了上面对于一些TLV的value不是很了解,所以作为收尾,我们列下以上用到的TLV
1)SSID TLV
在这里插入图片描述
2)TLV_TYPE_PHY_DS
在这里插入图片描述
3)TLV_TYPE_CF
在这里插入图片描述
4)TLV_TYPE_AUTH_TYPE
在这里插入图片描述
5)TLV_TYPE_CHANLIST
在这里插入图片描述
6)TLV_TYPE_BSSID
在这里插入图片描述
7)TLV_TYPE_PASSPHRASE
在这里插入图片描述
8)TLV_TYPE_VENDOR_SPECIFIC_IE
在这里插入图片描述
9)TLV_TYPE_RSN_PARAMSET 此部分内容较多,自行查阅IEEE802.11
在这里插入图片描述
10)TLV_TYPE_RATES

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wireless_Link

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值