unsigned char * hci_event_handler(void *pRetParams, unsigned char *from, long *fromlen) { unsigned char *pucReceivedData, ucArgsize; unsigned short usLength; unsigned char *pucReceivedParams; unsigned short usReceivedEventOpcode = 0; unsigned long retValue32; unsigned char * RecvParams; unsigned char *RetParams; volatile system_tick_t start = GetSystem1MsTick(); while (1) { if (tSLInformation.usEventOrDataReceived == 0) { volatile system_tick_t now = GetSystem1MsTick(); volatile system_tick_t elapsed = now - start; if (elapsed < 0) { // Did we wrap elapsed = start + now; // yes now } if (cc3000__event_timeout_ms && (elapsed >= cc3000__event_timeout_ms)) { ERROR("Timeout now %ld start %ld elapsed %ld cc3000__event_timeout_ms %ld",now,start,elapsed,cc3000__event_timeout_ms); ERROR("Timeout waiting on tSLInformation.usRxEventOpcode 0x%04x",tSLInformation.usRxEventOpcode); // Timeout Return Error for requested Opcode // This sucks because callers should have initialized pucReceivedParams switch(tSLInformation.usRxEventOpcode) { default: INVALID_CASE(tSLInformation.usRxEventOpcode); break; case HCI_CMND_SIMPLE_LINK_START: case HCI_CMND_READ_BUFFER_SIZE: break; case HCI_CMND_WLAN_CONFIGURE_PATCH: case HCI_NETAPP_DHCP: case HCI_NETAPP_PING_SEND: case HCI_NETAPP_PING_STOP: case HCI_NETAPP_ARP_FLUSH: case HCI_NETAPP_SET_DEBUG_LEVEL: case HCI_NETAPP_SET_TIMERS: case HCI_EVNT_NVMEM_READ: case HCI_EVNT_NVMEM_CREATE_ENTRY: case HCI_CMND_NVMEM_WRITE_PATCH: case HCI_NETAPP_PING_REPORT: case HCI_EVNT_MDNS_ADVERTISE: case HCI_EVNT_READ_SP_VERSION: case HCI_EVNT_SELECT: *(unsigned char *)pRetParams = -1; break; case HCI_CMND_SETSOCKOPT: case HCI_CMND_WLAN_CONNECT: case HCI_CMND_WLAN_IOCTL_STATUSGET: case HCI_EVNT_WLAN_IOCTL_ADD_PROFILE: case HCI_CMND_WLAN_IOCTL_DEL_PROFILE: case HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY: case HCI_CMND_WLAN_IOCTL_SET_SCANPARAM: case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START: case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP: case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX: case HCI_CMND_EVENT_MASK: case HCI_EVNT_WLAN_DISCONNECT: case HCI_EVNT_SOCKET: case HCI_EVNT_BIND: case HCI_CMND_LISTEN: case HCI_EVNT_CLOSE_SOCKET: case HCI_EVNT_CONNECT: case HCI_EVNT_NVMEM_WRITE: case HCI_EVNT_BSD_GETHOSTBYNAME: *(int32_t *)pRetParams = -1; break; case HCI_EVNT_RECV: case HCI_EVNT_RECVFROM: case HCI_EVNT_ACCEPT: case HCI_EVNT_SEND: case HCI_EVNT_SENDTO: case HCI_CMND_GETSOCKOPT: *(int32_t *)pRetParams = -1; pRetParams += sizeof(int32_t ); *(int32_t *)pRetParams = -1; break; case HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS: *(int32_t *)pRetParams = 0; break; case HCI_NETAPP_IPCONFIG: memset(pRetParams,0,sizeof(tNetappIpconfigRetArgs)); break; } break; // Exit Loop } } else { pucReceivedData = (tSLInformation.pucReceivedData); if (*pucReceivedData == HCI_TYPE_EVNT) { // Event Received STREAM_TO_UINT16((char *)pucReceivedData, HCI_EVENT_OPCODE_OFFSET, usReceivedEventOpcode); pucReceivedParams = pucReceivedData + HCI_EVENT_HEADER_SIZE; RecvParams = pucReceivedParams; RetParams = pRetParams; // In case unsolicited event received - here the handling finished if (hci_unsol_event_handler((char *)pucReceivedData) == 0) { STREAM_TO_UINT8(pucReceivedData, HCI_DATA_LENGTH_OFFSET, usLength); switch(usReceivedEventOpcode) { case HCI_CMND_READ_BUFFER_SIZE: { STREAM_TO_UINT8((char *)pucReceivedParams, 0, tSLInformation.usNumberOfFreeBuffers); STREAM_TO_UINT16((char *)pucReceivedParams, 1, tSLInformation.usSlBufferLength); } break; case HCI_CMND_WLAN_CONFIGURE_PATCH: case HCI_NETAPP_DHCP: case HCI_NETAPP_PING_SEND: case HCI_NETAPP_PING_STOP: case HCI_NETAPP_ARP_FLUSH: case HCI_NETAPP_SET_DEBUG_LEVEL: case HCI_NETAPP_SET_TIMERS: case HCI_EVNT_NVMEM_READ: case HCI_EVNT_NVMEM_CREATE_ENTRY: case HCI_CMND_NVMEM_WRITE_PATCH: case HCI_NETAPP_PING_REPORT: case HCI_EVNT_MDNS_ADVERTISE: STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET,*(unsigned char *)pRetParams); break; case HCI_CMND_SETSOCKOPT: case HCI_CMND_WLAN_CONNECT: case HCI_CMND_WLAN_IOCTL_STATUSGET: case HCI_EVNT_WLAN_IOCTL_ADD_PROFILE: case HCI_CMND_WLAN_IOCTL_DEL_PROFILE: case HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY: case HCI_CMND_WLAN_IOCTL_SET_SCANPARAM: case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START: case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP: case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX: case HCI_CMND_EVENT_MASK: case HCI_EVNT_WLAN_DISCONNECT: case HCI_EVNT_SOCKET: case HCI_EVNT_BIND: case HCI_CMND_LISTEN: case HCI_EVNT_CLOSE_SOCKET: case HCI_EVNT_CONNECT: case HCI_EVNT_NVMEM_WRITE: STREAM_TO_UINT32((char *)pucReceivedParams, 0, *(unsigned long *)pRetParams); break; case HCI_EVNT_READ_SP_VERSION: STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET, *(unsigned char *)pRetParams); pRetParams = ((char *)pRetParams) + 1; STREAM_TO_UINT32((char *)pucReceivedParams, 0, retValue32); UINT32_TO_STREAM((unsigned char *)pRetParams, retValue32); break; case HCI_EVNT_BSD_GETHOSTBYNAME: STREAM_TO_UINT32((char *)pucReceivedParams,GET_HOST_BY_NAME_RETVAL_OFFSET,*(unsigned long *)pRetParams); pRetParams = ((char *)pRetParams) + 4; STREAM_TO_UINT32((char *)pucReceivedParams,GET_HOST_BY_NAME_ADDR_OFFSET,*(unsigned long *)pRetParams); break; case HCI_EVNT_ACCEPT: { STREAM_TO_UINT32((char *)pucReceivedParams,ACCEPT_SD_OFFSET,*(unsigned long *)pRetParams); pRetParams = ((char *)pRetParams) + 4; STREAM_TO_UINT32((char *)pucReceivedParams,ACCEPT_RETURN_STATUS_OFFSET,*(unsigned long *)pRetParams); pRetParams = ((char *)pRetParams) + 4; //This argument returns in network order memcpy((unsigned char *)pRetParams, pucReceivedParams + ACCEPT_ADDRESS__OFFSET, sizeof(sockaddr)); break; } case HCI_EVNT_RECV: case HCI_EVNT_RECVFROM: { STREAM_TO_UINT32((char *)pucReceivedParams,SL_RECEIVE_SD_OFFSET ,*(unsigned long *)pRetParams); pRetParams = ((char *)pRetParams) + 4; STREAM_TO_UINT32((char *)pucReceivedParams,SL_RECEIVE_NUM_BYTES_OFFSET,*(unsigned long *)pRetParams); pRetParams = ((char *)pRetParams) + 4; STREAM_TO_UINT32((char *)pucReceivedParams,SL_RECEIVE__FLAGS__OFFSET,*(unsigned long *)pRetParams); if(((tBsdReadReturnParams *)pRetParams)->iNumberOfBytes == ERROR_SOCKET_INACTIVE) { set_socket_active_status(((tBsdReadReturnParams *)pRetParams)->iSocketDescriptor,SOCKET_STATUS_INACTIVE); } break; } case HCI_EVNT_SEND: case HCI_EVNT_SENDTO: { STREAM_TO_UINT32((char *)pucReceivedParams,SL_RECEIVE_SD_OFFSET ,*(unsigned long *)pRetParams); pRetParams = ((char *)pRetParams) + 4; STREAM_TO_UINT32((char *)pucReceivedParams,SL_RECEIVE_NUM_BYTES_OFFSET,*(unsigned long *)pRetParams); pRetParams = ((char *)pRetParams) + 4; break; } case HCI_EVNT_SELECT: { STREAM_TO_UINT32((char *)pucReceivedParams,SELECT_STATUS_OFFSET,*(unsigned long *)pRetParams); pRetParams = ((char *)pRetParams) + 4; STREAM_TO_UINT32((char *)pucReceivedParams,SELECT_READFD_OFFSET,*(unsigned long *)pRetParams); pRetParams = ((char *)pRetParams) + 4; STREAM_TO_UINT32((char *)pucReceivedParams,SELECT_WRITEFD_OFFSET,*(unsigned long *)pRetParams); pRetParams = ((char *)pRetParams) + 4; STREAM_TO_UINT32((char *)pucReceivedParams,SELECT_EXFD_OFFSET,*(unsigned long *)pRetParams); break; } case HCI_CMND_GETSOCKOPT: STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET,((tBsdGetSockOptReturnParams *)pRetParams)->iStatus); //This argument returns in network order memcpy((unsigned char *)pRetParams, pucReceivedParams, 4); break; case HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS: STREAM_TO_UINT32((char *)pucReceivedParams,GET_SCAN_RESULTS_TABlE_COUNT_OFFSET,*(unsigned long *)pRetParams); pRetParams = ((char *)pRetParams) + 4; STREAM_TO_UINT32((char *)pucReceivedParams,GET_SCAN_RESULTS_SCANRESULT_STATUS_OFFSET,*(unsigned long *)pRetParams); pRetParams = ((char *)pRetParams) + 4; STREAM_TO_UINT16((char *)pucReceivedParams,GET_SCAN_RESULTS_ISVALID_TO_SSIDLEN_OFFSET,*(unsigned long *)pRetParams); pRetParams = ((char *)pRetParams) + 2; STREAM_TO_UINT16((char *)pucReceivedParams,GET_SCAN_RESULTS_FRAME_TIME_OFFSET,*(unsigned long *)pRetParams); pRetParams = ((char *)pRetParams) + 2; memcpy((unsigned char *)pRetParams, (char *)(pucReceivedParams + GET_SCAN_RESULTS_FRAME_TIME_OFFSET + 2), GET_SCAN_RESULTS_SSID_MAC_LENGTH); break; case HCI_CMND_SIMPLE_LINK_START: break; case HCI_NETAPP_IPCONFIG: //Read IP address STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); RecvParams += 4; //Read subnet STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); RecvParams += 4; //Read default GW STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); RecvParams += 4; //Read DHCP server STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); RecvParams += 4; //Read DNS server STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); RecvParams += 4; //Read Mac address STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_MAC_LENGTH); RecvParams += 6; //Read SSID STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_SSID_LENGTH); } } if (usReceivedEventOpcode == tSLInformation.usRxEventOpcode) { tSLInformation.usRxEventOpcode = 0; tSLInformation.solicitedResponse = 0; } } else { if (tSLInformation.usRxDataPending == 0) { ERROR("type != HCI_TYPE_EVNT is (%d) usRxDataPending=%d usRxEventOpcode=%u usReceivedEventOpcode=%u", *pucReceivedData, tSLInformation.usRxDataPending, tSLInformation.usRxEventOpcode, usReceivedEventOpcode); } else { pucReceivedParams = pucReceivedData; STREAM_TO_UINT8((char *)pucReceivedData, HCI_PACKET_ARGSIZE_OFFSET, ucArgsize); STREAM_TO_UINT16((char *)pucReceivedData, HCI_PACKET_LENGTH_OFFSET, usLength); // Data received: note that the only case where from and from length // are not null is in recv from, so fill the args accordingly if (from) { STREAM_TO_UINT32((char *)(pucReceivedData + HCI_DATA_HEADER_SIZE), BSD_RECV_FROM_FROMLEN_OFFSET, *(unsigned long *)fromlen); memcpy(from, (pucReceivedData + HCI_DATA_HEADER_SIZE + BSD_RECV_FROM_FROM_OFFSET) ,*fromlen); } // Let's vet length long length = usLength - ucArgsize; if (length <= 0 || length > arraySize(wlan_rx_buffer)) { // Not sane length = -1; } else { memcpy(pRetParams, pucReceivedParams + HCI_DATA_HEADER_SIZE + ucArgsize, length); } // fixes the Nvram read not returning length if (fromlen) { *fromlen = length; } tSLInformation.usRxDataPending = 0; } } tSLInformation.usEventOrDataReceived = 0; SpiResumeSpi(); // Since we are going to TX - we need to handle this event after the // ResumeSPi since we need interrupts if ((*pucReceivedData == HCI_TYPE_EVNT) && (usReceivedEventOpcode == HCI_EVNT_PATCHES_REQ)) { hci_unsol_handle_patch_request((char *)pucReceivedData); } if ((tSLInformation.usRxEventOpcode == 0) && (tSLInformation.usRxDataPending == 0)) { break; } } } return NULL; }
/** * @brief The handler for Interrupt that is generated on SPI at the end of DMA transfer. * @param None * @retval None */ void SPI_DMA_IntHandler(void) { unsigned long ucTxFinished, ucRxFinished; unsigned short data_to_recv = 0; ucTxFinished = DMA_GetFlagStatus(CC3000_SPI_TX_DMA_TCFLAG ); ucRxFinished = DMA_GetFlagStatus(CC3000_SPI_RX_DMA_TCFLAG ); switch(sSpiInformation.ulSpiState) { case eSPI_STATE_READ_IRQ: // Both Done if (ucTxFinished && ucRxFinished) { /* Clear SPI_DMA Interrupt Pending Flags */ DMA_ClearFlag(CC3000_SPI_TX_DMA_TCFLAG | CC3000_SPI_RX_DMA_TCFLAG); sSpiInformation.ulSpiState = eSPI_STATE_READ_PROCEED; uint16_t *pnetlen = (uint16_t *) &sSpiInformation.pRxPacket[READ_OFFSET_TO_LENGTH]; data_to_recv = ntohs(*pnetlen); if (data_to_recv) { /* We will read ARRAY_SIZE(spi_readCommand) + data_to_recv. is it odd? */ if ((data_to_recv + arraySize(spi_readCommand)) & 1) { /* Odd so make it even */ data_to_recv++; } /* Read the whole payload in at the beginning of the buffer * Will it fit? */ SPARK_ASSERT(data_to_recv <= arraySize(wlan_rx_buffer)); SpiIO(eRead,sSpiInformation.pRxPacket,data_to_recv, FALSE); } } break; case eSPI_STATE_READ_PROCEED: // // All the data was read - finalize handling by switching to the task // and calling from task Event Handler // if (ucRxFinished) { /* Clear SPI_DMA Interrupt Pending Flags */ DMA_ClearFlag(CC3000_SPI_TX_DMA_TCFLAG | CC3000_SPI_RX_DMA_TCFLAG); SpiPauseSpi(); SetState(eSPI_STATE_IDLE, eDeAssert); WARN("CC3000 DmaHandler release read spi bus"); // Call out to the Unsolicited handler // It will handle the event or leave it there for an outstanding opcode // It it handles it the it Will resume the SPI ISR // It it dose not handles it and there are not outstanding Opcodes the it Will resume the SPI ISR sSpiInformation.SPIRxHandler(sSpiInformation.pRxPacket); } break; case eSPI_STATE_FIRST_WRITE: case eSPI_STATE_WRITE_PROCEED: if (ucTxFinished) { /* Loop until SPI busy */ while (SPI_I2S_GetFlagStatus(CC3000_SPI, SPI_I2S_FLAG_BSY ) != RESET) { } /* Clear SPI_DMA Interrupt Pending Flags */ DMA_ClearFlag(CC3000_SPI_TX_DMA_TCFLAG | CC3000_SPI_RX_DMA_TCFLAG); if ( sSpiInformation.ulSpiState == eSPI_STATE_FIRST_WRITE) { sSpiInformation.ulSpiState = eSPI_STATE_WRITE_PROCEED; } else { SetState(eSPI_STATE_IDLE, eDeAssert); WARN("CC3000 DmaHandler release write spi bus"); } } break; default: INVALID_CASE(sSpiInformation.ulSpiState); break; } }