void HCI_Process(void) { uint8_t data_len; uint8_t buffer[HCI_READ_PACKET_SIZE]; tHciDataPacket * hciReadPacket = NULL; Disable_SPI_IRQ(); uint8_t list_empty = list_is_empty(&hciReadPktRxQueue); /* process any pending events read */ while(list_empty == FALSE) { list_remove_head (&hciReadPktRxQueue, (tListNode **)&hciReadPacket); Enable_SPI_IRQ(); HCI_Event_CB(hciReadPacket->dataBuff); Disable_SPI_IRQ(); list_insert_tail(&hciReadPktPool, (tListNode *)hciReadPacket); list_empty = list_is_empty(&hciReadPktRxQueue); } if (readPacketListFull) { while(BlueNRG_DataPresent()) { data_len = BlueNRG_SPI_Read_All(&SpiHandle, buffer, HCI_READ_PACKET_SIZE); if(data_len > 0) HCI_Event_CB(buffer); } readPacketListFull = FALSE; } Enable_SPI_IRQ(); }
int HCI_Process(void) { uint8_t data_len; tHciDataPacket * hciReadPacket = NULL; uint8_t retries = 0; uint8_t list_empty = list_is_empty(&hciReadPktRxQueue); /* process any pending events read */ //events are added to tail in ISR while(list_empty == FALSE) { list_remove_head (&hciReadPktRxQueue, (tListNode **)&hciReadPacket); HCI_Event_CB(hciReadPacket->dataBuff); list_insert_tail(&hciReadPktPool, (tListNode *)hciReadPacket); list_empty = list_is_empty(&hciReadPktRxQueue); } if (readPacketListFull) //readPacketListFull is set in interrupt context { while(BlueNRG_DataPresent()) { __debug_hci("Data too fast"); data_len = BlueNRG_SPI_Read_All(HCI_Process_buffer, HCI_READ_PACKET_SIZE); if(data_len > 0) { HCI_Event_CB(hciReadPacket->dataBuff); retries = 0; } else { retries++; if(retries > 1) { return -1; break; } } } readPacketListFull = FALSE; //check if we ever get here } if(ISRDevice_busy == TRUE) { ISRDevice_busy = FALSE; return -2; } return 1; }
void HCI_recv_packet(unsigned char* packet_buffer, unsigned int packet_length) { tHciDataPacket * hciReadPacket = NULL; if (!list_is_empty ((tListNode*)&hciReadPktPool)){ if(packet_length > 0) { /* enqueueing a packet for read */ list_remove_head ((tListNode*)&hciReadPktPool, (tListNode **)&hciReadPacket); Osal_MemCpy(hciReadPacket->dataBuff, packet_buffer, MIN(HCI_READ_PACKET_SIZE, packet_length)); hciReadPacket->data_len = packet_length; switch(HCI_verify(hciReadPacket)) { case 0: list_insert_tail((tListNode*)&hciReadPktRxQueue, (tListNode *)hciReadPacket); break; default: case 1: case 2: list_insert_head((tListNode*)&hciReadPktPool, (tListNode *)hciReadPacket); break; } } } else{ // HCI Read Packet Pool is empty, wait for a free packet. readPacketListFull = TRUE; return; } // process incoming packet // don't process when hci_send_req is undergoing if (hciAwaitReply) { return; } /* process any pending events read */ while(!list_is_empty((tListNode*)&hciReadPktRxQueue)) { list_remove_head ((tListNode*)&hciReadPktRxQueue, (tListNode **)&hciReadPacket); //Enable_SPI_IRQ(); HCI_Event_CB(hciReadPacket->dataBuff); //Disable_SPI_IRQ(); list_insert_tail((tListNode*)&hciReadPktPool, (tListNode *)hciReadPacket); } }
int hci_send_req(struct hci_request *r, BOOL async) { uint8_t *ptr; uint16_t opcode = htobs(cmd_opcode_pack(r->ogf, r->ocf)); hci_event_pckt *event_pckt; hci_uart_pckt *hci_hdr; int to = /*1;*/ DEFAULT_TIMEOUT; struct timer t; tHciDataPacket * hciReadPacket = NULL; tListNode hciTempQueue; list_init_head((tListNode*)&hciTempQueue); // cannot be processed, due to reentrancy if (hciAwaitReply) { return -1; } hciAwaitReply = TRUE; hci_send_cmd(r->ogf, r->ocf, r->clen, r->cparam); if(async){ goto done; } /* Minimum timeout is 1. */ if(to == 0) to = 1; Timer_Set(&t, to); while(1) { evt_cmd_complete *cc; evt_cmd_status *cs; evt_le_meta_event *me; int len; // we're done with the sending, wait for a reply from the bluenrg io_seproxyhal_general_status(); // perform io_event based loop to wait for BLUENRG_RECV_EVENT for (;;) { io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); // check if event is a ticker event unsigned int ticker_event = G_io_seproxyhal_spi_buffer[0] == SEPROXYHAL_TAG_TICKER_EVENT; // process IOs, and BLE fetch, ble queue is updated through common code io_seproxyhal_handle_event(); // don't ack the BLUENRG_RECV_EVENT as we would require to reply another command to it. if(!list_is_empty((tListNode*)&hciReadPktRxQueue)){ /* Extract packet from HCI event queue. */ //Disable_SPI_IRQ(); list_remove_head((tListNode*)&hciReadPktRxQueue, (tListNode **)&hciReadPacket); list_insert_tail((tListNode*)&hciTempQueue, (tListNode *)hciReadPacket); hci_hdr = (void *)hciReadPacket->dataBuff; if(hci_hdr->type != HCI_EVENT_PKT){ move_list((tListNode*)&hciReadPktPool, (tListNode*)&hciTempQueue); //list_insert_tail((tListNode*)&hciTempQueue, (tListNode *)hciReadPacket); // See comment below //Enable_SPI_IRQ(); goto case_USER_PROCESS; } event_pckt = (void *) (hci_hdr->data); ptr = hciReadPacket->dataBuff + (1 + HCI_EVENT_HDR_SIZE); len = hciReadPacket->data_len - (1 + HCI_EVENT_HDR_SIZE); /* In the meantime there could be other events from the controller. In this case, insert the packet in a different queue. These packets will be inserted back in the main queue just before exiting from send_req(). */ event_pckt = (void *) (hci_hdr->data); switch (event_pckt->evt) { case EVT_CMD_STATUS: cs = (void *) ptr; if (cs->opcode != opcode) { goto case_USER_PROCESS; } if (r->event != EVT_CMD_STATUS) { goto case_USER_PROCESS; } r->rlen = MIN(len, r->rlen); Osal_MemCpy(r->rparam, ptr, r->rlen); goto done; case EVT_CMD_COMPLETE: cc = (void *) ptr; if (cc->opcode != opcode) { goto case_USER_PROCESS; } ptr += EVT_CMD_COMPLETE_SIZE; len -= EVT_CMD_COMPLETE_SIZE; r->rlen = MIN(len, r->rlen); Osal_MemCpy(r->rparam, ptr, r->rlen); goto done; case EVT_LE_META_EVENT: me = (void *) ptr; if (me->subevent != r->event) { goto case_USER_PROCESS; } len -= 1; r->rlen = MIN(len, r->rlen); Osal_MemCpy(r->rparam, me->data, r->rlen); goto done; case EVT_HARDWARE_ERROR: return -1; default: case_USER_PROCESS: HCI_Event_CB(hciReadPacket->dataBuff); break; } } // timeout if (ticker_event) { if (to) { to--; } // don't signal timeout if the event has been closed by handle event to avoid sending commands after a status has been issued else if (!io_seproxyhal_spi_is_status_sent()) { return -1; } } // ack the received event we have processed io_seproxyhal_general_status(); } //Enable_SPI_IRQ(); } failed: move_list((tListNode*)&hciReadPktPool, (tListNode*)&hciTempQueue); hciAwaitReply = FALSE; //Enable_SPI_IRQ(); return -1; done: // Insert the packet back into the pool. /* if (hciReadPacket) { list_insert_head((tListNode*)&hciReadPktPool, (tListNode *)hciReadPacket); } */ move_list((tListNode*)&hciReadPktPool, (tListNode*)&hciTempQueue); hciAwaitReply = FALSE; //Enable_SPI_IRQ(); return 0; }