13.4 Scan Code Example

The following code example illustrates the Request/Response flow on a Wi-Fi Scan request.

Note: For more details on example codes, refer to the Wi-Fi Network Controller Software Programming Guide.
  • The application requests a Wi-Fi scan.
{
	m2m_wifi_request_scan(M2M_WIFI_CH_ALL);
}
  • The host driver Wi-Fi layer formats the request and forward it to HIF (Host Interface) layer.
    sint8 m2m_wifi_request_scan(uint8 ch)
    {
    	tstrM2MScan strtmp;
    	sint8 s8Ret = M2M_ERR_SCAN_IN_PROGRESS;
    	strtmp.u8ChNum = ch;
    	s8Ret = hif_send(M2M_REQ_GRP_WIFI, M2M_WIFI_REQ_SCAN, (uint8*)&strtmp, sizeof(tstrM2MScan),NULL, 0,0);
    	return s8Ret;
    }
  • The HIF layer sends the request to the WINC chip.
sint8 hif_send(uint8 u8Gid,uint8 u8Opcode,uint8 *pu8CtrlBuf,uint16 u16CtrlBufSize,
				uint8 *pu8DataBuf,uint16 u16DataSize, uint16 u16DataOffset)
{
	sint8 ret = M2M_ERR_SEND;
	volatile tstrHifHdr	strHif;

	strHif.u8Opcode = u8Opcode&(~NBIT7);
	strHif.u8Gid = u8Gid;
	strHif.u16Length = M2M_HIF_HDR_OFFSET;
	if(pu8DataBuf != NULL)
	{
		strHif.u16Length += u16DataOffset + u16DataSize;
	}
	else
	{
		strHif.u16Length += u16CtrlBufSize;
	}
      /* TX STEP (1) */
	ret = hif_chip_wake();
	if(ret == M2M_SUCCESS)
	{
		volatile uint32 reg, dma_addr = 0;
		volatile uint16 cnt = 0;
		
		reg = 0UL;
		reg |= (uint32)u8Gid;
		reg |= ((uint32)u8Opcode<<8);
		reg |= ((uint32)strHif.u16Length<<16);
		ret = nm_write_reg(NMI_STATE_REG,reg);
		if(M2M_SUCCESS != ret) goto ERR1;
		reg = 0;
      /* TX STEP (2) */
		reg |= (1<<1);
		ret = nm_write_reg(WIFI_HOST_RCV_CTRL_2, reg);
		if(M2M_SUCCESS != ret) goto ERR1;
		dma_addr = 0;
		for(cnt = 0; cnt < 1000; cnt ++)
		{
			ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_2,(uint32 *)&reg);
			if(ret != M2M_SUCCESS) break;		
			if (!(reg & 0x2))
			{
      /* TX STEP (3) */
				ret = nm_read_reg_with_ret(0x150400,(uint32 *)&dma_addr);
				if(ret != M2M_SUCCESS) {
			/*in case of read error clear the dma address and return error*/
					dma_addr = 0;
				}
				/*in case of success break */
                                                  break;
			} 
		}
		if (dma_addr != 0) 
		{
			volatile uint32	u32CurrAddr;
			u32CurrAddr = dma_addr;
			strHif.u16Length=NM_BSP_B_L_16(strHif.u16Length);
      /* TX STEP (4) */
			ret = nm_write_block(u32CurrAddr, (uint8*)&strHif, M2M_HIF_HDR_OFFSET);
			if(M2M_SUCCESS != ret) goto ERR1;
			u32CurrAddr += M2M_HIF_HDR_OFFSET;
			if(pu8CtrlBuf != NULL)
			{
				ret = nm_write_block(u32CurrAddr, pu8CtrlBuf, u16CtrlBufSize);
				if(M2M_SUCCESS != ret) goto ERR1;
				u32CurrAddr += u16CtrlBufSize;
			}
			if(pu8DataBuf != NULL)
			{
				u32CurrAddr += (u16DataOffset - u16CtrlBufSize);
				ret = nm_write_block(u32CurrAddr, pu8DataBuf, u16DataSize);
				if(M2M_SUCCESS != ret) goto ERR1;
				u32CurrAddr += u16DataSize;
			}
			reg = dma_addr << 2;
			reg |= (1 << 1);
      /* TX STEP (5) */
			ret = nm_write_reg(WIFI_HOST_RCV_CTRL_3, reg);
			if(M2M_SUCCESS != ret) goto ERR1;
		}
		else
		{
      /* ERROR STATE */
			M2M_DBG("Failed to alloc rx size\r");
			ret =  M2M_ERR_MEM_ALLOC;
			goto ERR1;
		}
	}
	else
	{
		M2M_ERR("(HIF)Fail to wakup the chip\n");
		goto ERR1;
	}
      /* TX STEP (6) */
	ret = hif_chip_sleep(); 
ERR1:
	return ret;
}
  • The WINC chip processes the request and interrupts the host after finishing the operation.
  • The HIF layer then receives the response.
static sint8 hif_isr(void)
{
	sint8 ret = M2M_ERR_BUS_FAIL;
	uint32 reg;
	volatile tstrHifHdr strHif;
	/* RX STEP (1) */
	ret = hif_chip_wake();
	if(ret == M2M_SUCCESS)
	{
	/* RX STEP (2) */
		ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_0, &reg);
		if(M2M_SUCCESS == ret)
		{
			/* New interrupt has been received */
			if(reg & 0x1)	
			{
				uint16 size;
				nm_bsp_interrupt_ctrl(0);
				/*Clearing RX interrupt*/
				ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_0,&reg);
				if(ret != M2M_SUCCESS)goto ERR1;
				reg &= ~(1<<0);
	/* RX STEP (3) */
				ret=nm_write_reg(WIFI_HOST_RCV_CTRL_0,reg);
				if(ret != M2M_SUCCESS)goto ERR1;
				/* read the rx size */
				ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_0, &reg);
				if(M2M_SUCCESS != ret)
				{
					M2M_ERR("(hif) WIFI_HOST_RCV_CTRL_0 bus fail\n");
					nm_bsp_interrupt_ctrl(1);
					goto ERR1;
				}
				gu8HifSizeDone = 0;
				size = (uint16)((reg >> 2) & 0xfff);
				if (size > 0)
				{
					uint32 address = 0;
					/** start bus transfer **/
	/* RX STEP (4) */
					ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_1, &address);
					if(M2M_SUCCESS != ret)
					{
						M2M_ERR("(hif) WIFI_HOST_RCV_CTRL_1 bus fail\n");
						nm_bsp_interrupt_ctrl(1);
						goto ERR1;
					}
					ret = nm_read_block(address, (uint8*)&strHif, sizeof(tstrHifHdr));
					strHif.u16Length = NM_BSP_B_L_16(strHif.u16Length);
					if(M2M_SUCCESS != ret)
					{
						M2M_ERR("(hif) address bus fail\n");
						nm_bsp_interrupt_ctrl(1);
						goto ERR1;
					}
					if(strHif.u16Length != size)
					{
						if((size - strHif.u16Length) > 4)
						{
							M2M_ERR("(hif) Corrupted packet Size = %u <L = %u, G = %u, OP = %02X>\n",
								size, strHif.u16Length, strHif.u8Gid, strHif.u8Opcode);
							nm_bsp_interrupt_ctrl(1);
							ret = M2M_ERR_BUS_FAIL;
							goto ERR1;
						}
					}

	/* RX STEP (5) */
					if(M2M_REQ_GRP_WIFI == strHif.u8Gid)
					{
						if(pfWifiCb)
						{
							pfWifiCb(strHif.u8Opcode,strHif.u16Length - M2M_HIF_HDR_OFFSET,
									address + M2M_HIF_HDR_OFFSET);
						}
					
					} 
					else if(M2M_REQ_GRP_IP == strHif.u8Gid)
					{
						if(pfIpCb)
						{
							pfIpCb(strHif.u8Opcode,strHif.u16Length - M2M_HIF_HDR_OFFSET,
									address + M2M_HIF_HDR_OFFSET);
						}
					}
					else if(M2M_REQ_GRP_OTA == strHif.u8Gid)
					{
						if(pfOtaCb)
						{
							pfOtaCb(strHif.u8Opcode,strHif.u16Length - M2M_HIF_HDR_OFFSET,
									address + M2M_HIF_HDR_OFFSET);
						}
					}
					else
					{
						M2M_ERR("(hif) invalid group ID\n");
						ret = M2M_ERR_BUS_FAIL;
						goto ERR1;
					}
	/* RX STEP (6) */
					if(!gu8HifSizeDone)
					{
						M2M_ERR("(hif) host app didn't set RX Done\n");
						ret = hif_set_rx_done();
					}
				}
				else
				{
					ret = M2M_ERR_RCV;
					M2M_ERR("(hif) Wrong Size\n");
					goto ERR1;
				}
			}
			else
			{
#ifndef WIN32
				M2M_ERR("(hif) False interrupt %lx",reg);
#endif
			}
		}
		else
		{
			M2M_ERR("(hif) Fail to Read interrupt reg\n");
			goto ERR1;
		}
	}
	else
	{
		M2M_ERR("(hif) FAIL to wakeup the chip\n");
		goto ERR1;
	}
	/* RX STEP (7) */
	ret = hif_chip_sleep();
ERR1:
	return ret;
}
  • The appropriate handler in the Wi-Fi layer (called from the HIF layer).
static void m2m_wifi_cb(uint8 u8OpCode, uint16 u16DataSize, uint32 u32Addr)
{	// …code eliminated…
	else if (u8OpCode == M2M_WIFI_RESP_SCAN_DONE)
	{
		tstrM2mScanDone strState;
		gu8scanInProgress = 0;
		if(hif_receive(u32Addr, (uint8*)&strState, sizeof(tstrM2mScanDone), 0) == M2M_SUCCESS)
		{
			gu8ChNum = strState.u8NumofCh;
			if (gpfAppWifiCb)
				gpfAppWifiCb(M2M_WIFI_RESP_SCAN_DONE, &strState);
		}
	}
     // …code eliminated…
}
  • The Wi-Fi layer sends the response to the application through its callback function.
if (u8MsgType == M2M_WIFI_RESP_SCAN_DONE)
{
	tstrM2mScanDone *pstrInfo = (tstrM2mScanDone*) pvMsg;
	if(   (gu8IsWiFiConnected == M2M_WIFI_DISCONNECTED) &&
			(gu8WPS == WPS_DISABLED) && (gu8Prov == PROV_DISABLED)  )
	{
		gu8Index = 0;
		gu8Sleep = PS_WAKE;
		if (pstrInfo->u8NumofCh >= 1)
		{
			m2m_wifi_req_scan_result(gu8Index);
			gu8Index++;
		}
		else
		{
			m2m_wifi_request_scan(M2M_WIFI_CH_ALL);	
		}
	}
}