Fork of ble-x-nucleo-idb0xa1 with changes required by BleStarMbed

Dependents:   ble-star-mbed

Committer:
lorevee
Date:
Tue Feb 20 11:07:16 2018 +0000
Revision:
0:ac0b0725c6fa
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
lorevee 0:ac0b0725c6fa 1 /**
lorevee 0:ac0b0725c6fa 2 ******************************************************************************
lorevee 0:ac0b0725c6fa 3 * @file ble_hci.c
lorevee 0:ac0b0725c6fa 4 * @author AMS/HESA Application Team
lorevee 0:ac0b0725c6fa 5 * @brief Function for managing HCI interface.
lorevee 0:ac0b0725c6fa 6 ******************************************************************************
lorevee 0:ac0b0725c6fa 7 *
lorevee 0:ac0b0725c6fa 8 *
lorevee 0:ac0b0725c6fa 9 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
lorevee 0:ac0b0725c6fa 10 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
lorevee 0:ac0b0725c6fa 11 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
lorevee 0:ac0b0725c6fa 12 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
lorevee 0:ac0b0725c6fa 13 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
lorevee 0:ac0b0725c6fa 14 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
lorevee 0:ac0b0725c6fa 15 *
lorevee 0:ac0b0725c6fa 16 * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
lorevee 0:ac0b0725c6fa 17 */
lorevee 0:ac0b0725c6fa 18
lorevee 0:ac0b0725c6fa 19 #include "ble_hal_types.h"
lorevee 0:ac0b0725c6fa 20 #include "ble_osal.h"
lorevee 0:ac0b0725c6fa 21 #include "ble_status.h"
lorevee 0:ac0b0725c6fa 22 #include "ble_hal.h"
lorevee 0:ac0b0725c6fa 23 #include "ble_hci_const.h"
lorevee 0:ac0b0725c6fa 24 #include "ble_gp_timer.h"
lorevee 0:ac0b0725c6fa 25 #include "ble_debug.h"
lorevee 0:ac0b0725c6fa 26
lorevee 0:ac0b0725c6fa 27 #include "stm32_bluenrg_ble.h"
lorevee 0:ac0b0725c6fa 28
lorevee 0:ac0b0725c6fa 29 #if BLE_CONFIG_DBG_ENABLE
lorevee 0:ac0b0725c6fa 30 #undef PRINTF
lorevee 0:ac0b0725c6fa 31 #endif
lorevee 0:ac0b0725c6fa 32
lorevee 0:ac0b0725c6fa 33 #define HCI_LOG_ON 0
lorevee 0:ac0b0725c6fa 34
lorevee 0:ac0b0725c6fa 35 #define HCI_READ_PACKET_NUM_MAX (0x40)
lorevee 0:ac0b0725c6fa 36
lorevee 0:ac0b0725c6fa 37 #define MIN(a,b) ((a) < (b) )? (a) : (b)
lorevee 0:ac0b0725c6fa 38 #define MAX(a,b) ((a) > (b) )? (a) : (b)
lorevee 0:ac0b0725c6fa 39
lorevee 0:ac0b0725c6fa 40 tListNode hciReadPktPool;
lorevee 0:ac0b0725c6fa 41 tListNode hciReadPktRxQueue;
lorevee 0:ac0b0725c6fa 42
lorevee 0:ac0b0725c6fa 43 // betzw - DEBUG:
lorevee 0:ac0b0725c6fa 44 //#define POOL_CNT
lorevee 0:ac0b0725c6fa 45 #ifdef POOL_CNT
lorevee 0:ac0b0725c6fa 46 #include <stdio.h>
lorevee 0:ac0b0725c6fa 47 static unsigned int nr_hciReadPktPool;
lorevee 0:ac0b0725c6fa 48 static unsigned int lowest_nr_hciReadPktPool;
lorevee 0:ac0b0725c6fa 49 #endif // POOL_CNT
lorevee 0:ac0b0725c6fa 50
lorevee 0:ac0b0725c6fa 51 /* pool of hci read packets */
lorevee 0:ac0b0725c6fa 52 static tHciDataPacket hciReadPacketBuffer[HCI_READ_PACKET_NUM_MAX];
lorevee 0:ac0b0725c6fa 53
lorevee 0:ac0b0725c6fa 54 static volatile uint8_t hci_timer_id;
lorevee 0:ac0b0725c6fa 55 static volatile uint8_t hci_timeout;
lorevee 0:ac0b0725c6fa 56
lorevee 0:ac0b0725c6fa 57 void hci_timeout_callback(void)
lorevee 0:ac0b0725c6fa 58 {
lorevee 0:ac0b0725c6fa 59 hci_timeout = 1;
lorevee 0:ac0b0725c6fa 60 return;
lorevee 0:ac0b0725c6fa 61 }
lorevee 0:ac0b0725c6fa 62
lorevee 0:ac0b0725c6fa 63 void HCI_Init(void)
lorevee 0:ac0b0725c6fa 64 {
lorevee 0:ac0b0725c6fa 65 uint8_t index;
lorevee 0:ac0b0725c6fa 66
lorevee 0:ac0b0725c6fa 67 #ifdef POOL_CNT
lorevee 0:ac0b0725c6fa 68 nr_hciReadPktPool = 0;
lorevee 0:ac0b0725c6fa 69 #endif // POOL_CNT
lorevee 0:ac0b0725c6fa 70
lorevee 0:ac0b0725c6fa 71 /* Initialize list heads of ready and free hci data packet queues */
lorevee 0:ac0b0725c6fa 72 list_init_head (&hciReadPktPool);
lorevee 0:ac0b0725c6fa 73 list_init_head (&hciReadPktRxQueue);
lorevee 0:ac0b0725c6fa 74
lorevee 0:ac0b0725c6fa 75 /* Initialize the queue of free hci data packets */
lorevee 0:ac0b0725c6fa 76 for (index = 0; index < HCI_READ_PACKET_NUM_MAX; index++)
lorevee 0:ac0b0725c6fa 77 {
lorevee 0:ac0b0725c6fa 78 list_insert_tail(&hciReadPktPool, (tListNode *)&hciReadPacketBuffer[index]);
lorevee 0:ac0b0725c6fa 79 #ifdef POOL_CNT
lorevee 0:ac0b0725c6fa 80 nr_hciReadPktPool++;
lorevee 0:ac0b0725c6fa 81 #endif // POOL_CNT
lorevee 0:ac0b0725c6fa 82 }
lorevee 0:ac0b0725c6fa 83
lorevee 0:ac0b0725c6fa 84 #ifdef POOL_CNT
lorevee 0:ac0b0725c6fa 85 lowest_nr_hciReadPktPool = nr_hciReadPktPool;
lorevee 0:ac0b0725c6fa 86 #endif // POOL_CNT
lorevee 0:ac0b0725c6fa 87 }
lorevee 0:ac0b0725c6fa 88
lorevee 0:ac0b0725c6fa 89 #define HCI_PCK_TYPE_OFFSET 0
lorevee 0:ac0b0725c6fa 90 #define EVENT_PARAMETER_TOT_LEN_OFFSET 2
lorevee 0:ac0b0725c6fa 91
lorevee 0:ac0b0725c6fa 92 /**
lorevee 0:ac0b0725c6fa 93 * Verify if HCI packet is correctly formatted.
lorevee 0:ac0b0725c6fa 94 *
lorevee 0:ac0b0725c6fa 95 * @param[in] hciReadPacket The packet that is received from HCI interface.
lorevee 0:ac0b0725c6fa 96 * @return 0 if HCI packet is as expected
lorevee 0:ac0b0725c6fa 97 */
lorevee 0:ac0b0725c6fa 98 int HCI_verify(const tHciDataPacket * hciReadPacket)
lorevee 0:ac0b0725c6fa 99 {
lorevee 0:ac0b0725c6fa 100 const uint8_t *hci_pckt = hciReadPacket->dataBuff;
lorevee 0:ac0b0725c6fa 101
lorevee 0:ac0b0725c6fa 102 if(hci_pckt[HCI_PCK_TYPE_OFFSET] != HCI_EVENT_PKT)
lorevee 0:ac0b0725c6fa 103 return 1; /* Incorrect type. */
lorevee 0:ac0b0725c6fa 104
lorevee 0:ac0b0725c6fa 105 if(hci_pckt[EVENT_PARAMETER_TOT_LEN_OFFSET] != hciReadPacket->data_len - (1+HCI_EVENT_HDR_SIZE))
lorevee 0:ac0b0725c6fa 106 return 2; /* Wrong length (packet truncated or too long). */
lorevee 0:ac0b0725c6fa 107
lorevee 0:ac0b0725c6fa 108 return 0;
lorevee 0:ac0b0725c6fa 109 }
lorevee 0:ac0b0725c6fa 110
lorevee 0:ac0b0725c6fa 111 void HCI_Process(void)
lorevee 0:ac0b0725c6fa 112 {
lorevee 0:ac0b0725c6fa 113 tHciDataPacket * hciReadPacket = NULL;
lorevee 0:ac0b0725c6fa 114
lorevee 0:ac0b0725c6fa 115 #ifdef POOL_CNT
lorevee 0:ac0b0725c6fa 116 printf("betzw(%s, %d): nr_hciReadPktPool = %u (lowest = %u)\r\n", __func__, __LINE__,
lorevee 0:ac0b0725c6fa 117 nr_hciReadPktPool, lowest_nr_hciReadPktPool);
lorevee 0:ac0b0725c6fa 118 #endif // POOL_CNT
lorevee 0:ac0b0725c6fa 119
lorevee 0:ac0b0725c6fa 120 Disable_SPI_IRQ();
lorevee 0:ac0b0725c6fa 121 uint8_t list_empty = list_is_empty(&hciReadPktRxQueue);
lorevee 0:ac0b0725c6fa 122 /* process any pending events read */
lorevee 0:ac0b0725c6fa 123 while(list_empty == FALSE)
lorevee 0:ac0b0725c6fa 124 {
lorevee 0:ac0b0725c6fa 125 list_remove_head (&hciReadPktRxQueue, (tListNode **)&hciReadPacket);
lorevee 0:ac0b0725c6fa 126 Enable_SPI_IRQ();
lorevee 0:ac0b0725c6fa 127 HCI_Event_CB(hciReadPacket->dataBuff);
lorevee 0:ac0b0725c6fa 128 Disable_SPI_IRQ();
lorevee 0:ac0b0725c6fa 129 list_insert_tail(&hciReadPktPool, (tListNode *)hciReadPacket);
lorevee 0:ac0b0725c6fa 130 #ifdef POOL_CNT
lorevee 0:ac0b0725c6fa 131 nr_hciReadPktPool++;
lorevee 0:ac0b0725c6fa 132 #endif
lorevee 0:ac0b0725c6fa 133 list_empty = list_is_empty(&hciReadPktRxQueue);
lorevee 0:ac0b0725c6fa 134 }
lorevee 0:ac0b0725c6fa 135 /* Explicit call to HCI_HandleSPI(), since it cannot be triggered by ISR if IRQ is kept high by
lorevee 0:ac0b0725c6fa 136 BlueNRG. */
lorevee 0:ac0b0725c6fa 137 HCI_HandleSPI();
lorevee 0:ac0b0725c6fa 138 Enable_SPI_IRQ();
lorevee 0:ac0b0725c6fa 139 }
lorevee 0:ac0b0725c6fa 140
lorevee 0:ac0b0725c6fa 141 BOOL HCI_Queue_Empty(void)
lorevee 0:ac0b0725c6fa 142 {
lorevee 0:ac0b0725c6fa 143 return list_is_empty(&hciReadPktRxQueue);
lorevee 0:ac0b0725c6fa 144 }
lorevee 0:ac0b0725c6fa 145
lorevee 0:ac0b0725c6fa 146 /**
lorevee 0:ac0b0725c6fa 147 * When an interrupt is raised by BlueNRG,
lorevee 0:ac0b0725c6fa 148 * just signal that a new event (availability of SPI data to be read)
lorevee 0:ac0b0725c6fa 149 * needs to be processed.
lorevee 0:ac0b0725c6fa 150 */
lorevee 0:ac0b0725c6fa 151 void HCI_Isr(void)
lorevee 0:ac0b0725c6fa 152 {
lorevee 0:ac0b0725c6fa 153 signalEventsToProcess();
lorevee 0:ac0b0725c6fa 154 }
lorevee 0:ac0b0725c6fa 155
lorevee 0:ac0b0725c6fa 156 /**
lorevee 0:ac0b0725c6fa 157 * Now, SPI Data are handled in user space.
lorevee 0:ac0b0725c6fa 158 * In case it has to be called in ISR, take care to
lorevee 0:ac0b0725c6fa 159 * call Disable_SPI_IRQ/Enable_SPI_IRQ in a proper way.
lorevee 0:ac0b0725c6fa 160 * The calls Disable_SPI_IRQ/Enable_SPI_IRQ have not been removed
lorevee 0:ac0b0725c6fa 161 * from this code for backward compatibility.
lorevee 0:ac0b0725c6fa 162 */
lorevee 0:ac0b0725c6fa 163 void HCI_HandleSPI(void)
lorevee 0:ac0b0725c6fa 164 {
lorevee 0:ac0b0725c6fa 165 tHciDataPacket * hciReadPacket = NULL;
lorevee 0:ac0b0725c6fa 166 uint8_t data_len;
lorevee 0:ac0b0725c6fa 167
lorevee 0:ac0b0725c6fa 168 Clear_SPI_EXTI_Flag();
lorevee 0:ac0b0725c6fa 169 while(BlueNRG_DataPresent()){
lorevee 0:ac0b0725c6fa 170 if (list_is_empty (&hciReadPktPool) == FALSE){
lorevee 0:ac0b0725c6fa 171
lorevee 0:ac0b0725c6fa 172 /* enqueueing a packet for read */
lorevee 0:ac0b0725c6fa 173 list_remove_head (&hciReadPktPool, (tListNode **)&hciReadPacket);
lorevee 0:ac0b0725c6fa 174 #ifdef POOL_CNT
lorevee 0:ac0b0725c6fa 175 nr_hciReadPktPool--;
lorevee 0:ac0b0725c6fa 176 if(nr_hciReadPktPool < lowest_nr_hciReadPktPool)
lorevee 0:ac0b0725c6fa 177 lowest_nr_hciReadPktPool = nr_hciReadPktPool;
lorevee 0:ac0b0725c6fa 178 #endif
lorevee 0:ac0b0725c6fa 179
lorevee 0:ac0b0725c6fa 180 data_len = BlueNRG_SPI_Read_All(hciReadPacket->dataBuff, HCI_READ_PACKET_SIZE);
lorevee 0:ac0b0725c6fa 181 if(data_len > 0){
lorevee 0:ac0b0725c6fa 182 hciReadPacket->data_len = data_len;
lorevee 0:ac0b0725c6fa 183 if(HCI_verify(hciReadPacket) == 0) {
lorevee 0:ac0b0725c6fa 184 list_insert_tail(&hciReadPktRxQueue, (tListNode *)hciReadPacket);
lorevee 0:ac0b0725c6fa 185 } else {
lorevee 0:ac0b0725c6fa 186 list_insert_head(&hciReadPktPool, (tListNode *)hciReadPacket);
lorevee 0:ac0b0725c6fa 187 #ifdef POOL_CNT
lorevee 0:ac0b0725c6fa 188 nr_hciReadPktPool++;
lorevee 0:ac0b0725c6fa 189 #endif
lorevee 0:ac0b0725c6fa 190 }
lorevee 0:ac0b0725c6fa 191 }
lorevee 0:ac0b0725c6fa 192 else {
lorevee 0:ac0b0725c6fa 193 // Insert the packet back into the pool.
lorevee 0:ac0b0725c6fa 194 list_insert_head(&hciReadPktPool, (tListNode *)hciReadPacket);
lorevee 0:ac0b0725c6fa 195 #ifdef POOL_CNT
lorevee 0:ac0b0725c6fa 196 nr_hciReadPktPool++;
lorevee 0:ac0b0725c6fa 197 #endif
lorevee 0:ac0b0725c6fa 198 }
lorevee 0:ac0b0725c6fa 199 }
lorevee 0:ac0b0725c6fa 200 else{
lorevee 0:ac0b0725c6fa 201 // HCI Read Packet Pool is empty, wait for a free packet.
lorevee 0:ac0b0725c6fa 202 Clear_SPI_EXTI_Flag();
lorevee 0:ac0b0725c6fa 203 return;
lorevee 0:ac0b0725c6fa 204 }
lorevee 0:ac0b0725c6fa 205
lorevee 0:ac0b0725c6fa 206 Clear_SPI_EXTI_Flag();
lorevee 0:ac0b0725c6fa 207 }
lorevee 0:ac0b0725c6fa 208 }
lorevee 0:ac0b0725c6fa 209
lorevee 0:ac0b0725c6fa 210 void hci_write(const void* data1, const void* data2, uint8_t n_bytes1, uint8_t n_bytes2){
lorevee 0:ac0b0725c6fa 211 #if HCI_LOG_ON
lorevee 0:ac0b0725c6fa 212 PRINTF("HCI <- ");
lorevee 0:ac0b0725c6fa 213 for(int i=0; i < n_bytes1; i++)
lorevee 0:ac0b0725c6fa 214 PRINTF("%02X ", *((uint8_t*)data1 + i));
lorevee 0:ac0b0725c6fa 215 for(int i=0; i < n_bytes2; i++)
lorevee 0:ac0b0725c6fa 216 PRINTF("%02X ", *((uint8_t*)data2 + i));
lorevee 0:ac0b0725c6fa 217 PRINTF("\n");
lorevee 0:ac0b0725c6fa 218 #endif
lorevee 0:ac0b0725c6fa 219
lorevee 0:ac0b0725c6fa 220 Hal_Write_Serial(data1, data2, n_bytes1, n_bytes2);
lorevee 0:ac0b0725c6fa 221 }
lorevee 0:ac0b0725c6fa 222
lorevee 0:ac0b0725c6fa 223 void hci_send_cmd(uint16_t ogf, uint16_t ocf, uint8_t plen, void *param)
lorevee 0:ac0b0725c6fa 224 {
lorevee 0:ac0b0725c6fa 225 hci_command_hdr hc;
lorevee 0:ac0b0725c6fa 226
lorevee 0:ac0b0725c6fa 227 hc.opcode = htobs(cmd_opcode_pack(ogf, ocf));
lorevee 0:ac0b0725c6fa 228 hc.plen= plen;
lorevee 0:ac0b0725c6fa 229
lorevee 0:ac0b0725c6fa 230 uint8_t header[HCI_HDR_SIZE + HCI_COMMAND_HDR_SIZE];
lorevee 0:ac0b0725c6fa 231 header[0] = HCI_COMMAND_PKT;
lorevee 0:ac0b0725c6fa 232 Osal_MemCpy(header+1, &hc, sizeof(hc));
lorevee 0:ac0b0725c6fa 233
lorevee 0:ac0b0725c6fa 234 hci_write(header, param, sizeof(header), plen);
lorevee 0:ac0b0725c6fa 235 }
lorevee 0:ac0b0725c6fa 236
lorevee 0:ac0b0725c6fa 237 static void move_list(tListNode * dest_list, tListNode * src_list)
lorevee 0:ac0b0725c6fa 238 {
lorevee 0:ac0b0725c6fa 239 pListNode tmp_node;
lorevee 0:ac0b0725c6fa 240
lorevee 0:ac0b0725c6fa 241 while(!list_is_empty(src_list)){
lorevee 0:ac0b0725c6fa 242 list_remove_tail(src_list, &tmp_node);
lorevee 0:ac0b0725c6fa 243 list_insert_head(dest_list, tmp_node);
lorevee 0:ac0b0725c6fa 244 }
lorevee 0:ac0b0725c6fa 245 }
lorevee 0:ac0b0725c6fa 246
lorevee 0:ac0b0725c6fa 247 /* It ensures that we have at least half of the free buffers in the pool. */
lorevee 0:ac0b0725c6fa 248 static void free_event_list(void)
lorevee 0:ac0b0725c6fa 249 {
lorevee 0:ac0b0725c6fa 250 tHciDataPacket * pckt;
lorevee 0:ac0b0725c6fa 251
lorevee 0:ac0b0725c6fa 252 Disable_SPI_IRQ();
lorevee 0:ac0b0725c6fa 253
lorevee 0:ac0b0725c6fa 254 while(list_get_size(&hciReadPktPool) < HCI_READ_PACKET_NUM_MAX/2){
lorevee 0:ac0b0725c6fa 255 list_remove_head(&hciReadPktRxQueue, (tListNode **)&pckt);
lorevee 0:ac0b0725c6fa 256 list_insert_tail(&hciReadPktPool, (tListNode *)pckt);
lorevee 0:ac0b0725c6fa 257 /* Explicit call to HCI_HandleSPI(), since it cannot be triggered by ISR if IRQ is kept high by
lorevee 0:ac0b0725c6fa 258 BlueNRG */
lorevee 0:ac0b0725c6fa 259 HCI_HandleSPI();
lorevee 0:ac0b0725c6fa 260 }
lorevee 0:ac0b0725c6fa 261
lorevee 0:ac0b0725c6fa 262 Enable_SPI_IRQ();
lorevee 0:ac0b0725c6fa 263 }
lorevee 0:ac0b0725c6fa 264
lorevee 0:ac0b0725c6fa 265 int hci_send_req(struct hci_request *r, BOOL async)
lorevee 0:ac0b0725c6fa 266 {
lorevee 0:ac0b0725c6fa 267 uint8_t *ptr;
lorevee 0:ac0b0725c6fa 268 uint16_t opcode = htobs(cmd_opcode_pack(r->ogf, r->ocf));
lorevee 0:ac0b0725c6fa 269 hci_event_pckt *event_pckt;
lorevee 0:ac0b0725c6fa 270 hci_uart_pckt *hci_hdr;
lorevee 0:ac0b0725c6fa 271 int to = DEFAULT_TIMEOUT;
lorevee 0:ac0b0725c6fa 272 struct timer t;
lorevee 0:ac0b0725c6fa 273 tHciDataPacket * hciReadPacket = NULL;
lorevee 0:ac0b0725c6fa 274 tListNode hciTempQueue;
lorevee 0:ac0b0725c6fa 275
lorevee 0:ac0b0725c6fa 276 list_init_head(&hciTempQueue);
lorevee 0:ac0b0725c6fa 277
lorevee 0:ac0b0725c6fa 278 free_event_list();
lorevee 0:ac0b0725c6fa 279
lorevee 0:ac0b0725c6fa 280 hci_send_cmd(r->ogf, r->ocf, r->clen, r->cparam);
lorevee 0:ac0b0725c6fa 281
lorevee 0:ac0b0725c6fa 282 if(async){
lorevee 0:ac0b0725c6fa 283 return 0;
lorevee 0:ac0b0725c6fa 284 }
lorevee 0:ac0b0725c6fa 285
lorevee 0:ac0b0725c6fa 286 /* Minimum timeout is 1. */
lorevee 0:ac0b0725c6fa 287 if(to == 0)
lorevee 0:ac0b0725c6fa 288 to = 1;
lorevee 0:ac0b0725c6fa 289
lorevee 0:ac0b0725c6fa 290 Timer_Set(&t, to);
lorevee 0:ac0b0725c6fa 291
lorevee 0:ac0b0725c6fa 292 while(1) {
lorevee 0:ac0b0725c6fa 293 evt_cmd_complete *cc;
lorevee 0:ac0b0725c6fa 294 evt_cmd_status *cs;
lorevee 0:ac0b0725c6fa 295 evt_le_meta_event *me;
lorevee 0:ac0b0725c6fa 296 int len;
lorevee 0:ac0b0725c6fa 297
lorevee 0:ac0b0725c6fa 298 while(1){
lorevee 0:ac0b0725c6fa 299
lorevee 0:ac0b0725c6fa 300 Disable_SPI_IRQ();
lorevee 0:ac0b0725c6fa 301 HCI_HandleSPI();
lorevee 0:ac0b0725c6fa 302 Enable_SPI_IRQ();
lorevee 0:ac0b0725c6fa 303
lorevee 0:ac0b0725c6fa 304 if(Timer_Expired(&t)){
lorevee 0:ac0b0725c6fa 305 goto failed;
lorevee 0:ac0b0725c6fa 306 }
lorevee 0:ac0b0725c6fa 307 if(!HCI_Queue_Empty()){
lorevee 0:ac0b0725c6fa 308 break;
lorevee 0:ac0b0725c6fa 309 }
lorevee 0:ac0b0725c6fa 310 }
lorevee 0:ac0b0725c6fa 311
lorevee 0:ac0b0725c6fa 312 /* Extract packet from HCI event queue. */
lorevee 0:ac0b0725c6fa 313 Disable_SPI_IRQ();
lorevee 0:ac0b0725c6fa 314 list_remove_head(&hciReadPktRxQueue, (tListNode **)&hciReadPacket);
lorevee 0:ac0b0725c6fa 315
lorevee 0:ac0b0725c6fa 316 hci_hdr = (void *)hciReadPacket->dataBuff;
lorevee 0:ac0b0725c6fa 317
lorevee 0:ac0b0725c6fa 318 if(hci_hdr->type == HCI_EVENT_PKT){
lorevee 0:ac0b0725c6fa 319
lorevee 0:ac0b0725c6fa 320 event_pckt = (void *) (hci_hdr->data);
lorevee 0:ac0b0725c6fa 321
lorevee 0:ac0b0725c6fa 322 ptr = hciReadPacket->dataBuff + (1 + HCI_EVENT_HDR_SIZE);
lorevee 0:ac0b0725c6fa 323 len = hciReadPacket->data_len - (1 + HCI_EVENT_HDR_SIZE);
lorevee 0:ac0b0725c6fa 324
lorevee 0:ac0b0725c6fa 325 switch (event_pckt->evt) {
lorevee 0:ac0b0725c6fa 326
lorevee 0:ac0b0725c6fa 327 case EVT_CMD_STATUS:
lorevee 0:ac0b0725c6fa 328 cs = (void *) ptr;
lorevee 0:ac0b0725c6fa 329
lorevee 0:ac0b0725c6fa 330 if (cs->opcode != opcode)
lorevee 0:ac0b0725c6fa 331 goto failed;
lorevee 0:ac0b0725c6fa 332
lorevee 0:ac0b0725c6fa 333 if (r->event != EVT_CMD_STATUS) {
lorevee 0:ac0b0725c6fa 334 if (cs->status) {
lorevee 0:ac0b0725c6fa 335 goto failed;
lorevee 0:ac0b0725c6fa 336 }
lorevee 0:ac0b0725c6fa 337 break;
lorevee 0:ac0b0725c6fa 338 }
lorevee 0:ac0b0725c6fa 339
lorevee 0:ac0b0725c6fa 340 r->rlen = MIN(len, r->rlen);
lorevee 0:ac0b0725c6fa 341 Osal_MemCpy(r->rparam, ptr, r->rlen);
lorevee 0:ac0b0725c6fa 342 goto done;
lorevee 0:ac0b0725c6fa 343
lorevee 0:ac0b0725c6fa 344 case EVT_CMD_COMPLETE:
lorevee 0:ac0b0725c6fa 345 cc = (void *) ptr;
lorevee 0:ac0b0725c6fa 346
lorevee 0:ac0b0725c6fa 347 if (cc->opcode != opcode)
lorevee 0:ac0b0725c6fa 348 goto failed;
lorevee 0:ac0b0725c6fa 349
lorevee 0:ac0b0725c6fa 350 ptr += EVT_CMD_COMPLETE_SIZE;
lorevee 0:ac0b0725c6fa 351 len -= EVT_CMD_COMPLETE_SIZE;
lorevee 0:ac0b0725c6fa 352
lorevee 0:ac0b0725c6fa 353 r->rlen = MIN(len, r->rlen);
lorevee 0:ac0b0725c6fa 354 Osal_MemCpy(r->rparam, ptr, r->rlen);
lorevee 0:ac0b0725c6fa 355 goto done;
lorevee 0:ac0b0725c6fa 356
lorevee 0:ac0b0725c6fa 357 case EVT_LE_META_EVENT:
lorevee 0:ac0b0725c6fa 358 me = (void *) ptr;
lorevee 0:ac0b0725c6fa 359
lorevee 0:ac0b0725c6fa 360 if (me->subevent != r->event)
lorevee 0:ac0b0725c6fa 361 break;
lorevee 0:ac0b0725c6fa 362
lorevee 0:ac0b0725c6fa 363 len -= 1;
lorevee 0:ac0b0725c6fa 364 r->rlen = MIN(len, r->rlen);
lorevee 0:ac0b0725c6fa 365 Osal_MemCpy(r->rparam, me->data, r->rlen);
lorevee 0:ac0b0725c6fa 366 goto done;
lorevee 0:ac0b0725c6fa 367
lorevee 0:ac0b0725c6fa 368 case EVT_HARDWARE_ERROR:
lorevee 0:ac0b0725c6fa 369 goto failed;
lorevee 0:ac0b0725c6fa 370
lorevee 0:ac0b0725c6fa 371 default:
lorevee 0:ac0b0725c6fa 372 break;
lorevee 0:ac0b0725c6fa 373 }
lorevee 0:ac0b0725c6fa 374 }
lorevee 0:ac0b0725c6fa 375
lorevee 0:ac0b0725c6fa 376 /* If there are no more packets to be processed, be sure there is at list one
lorevee 0:ac0b0725c6fa 377 packet in the pool to process the expected event.
lorevee 0:ac0b0725c6fa 378 If no free packets are available, discard the processed event and insert it
lorevee 0:ac0b0725c6fa 379 into the pool. */
lorevee 0:ac0b0725c6fa 380 if(list_is_empty(&hciReadPktPool) && list_is_empty(&hciReadPktRxQueue)){
lorevee 0:ac0b0725c6fa 381 list_insert_tail(&hciReadPktPool, (tListNode *)hciReadPacket);
lorevee 0:ac0b0725c6fa 382 hciReadPacket=NULL;
lorevee 0:ac0b0725c6fa 383 }
lorevee 0:ac0b0725c6fa 384 else {
lorevee 0:ac0b0725c6fa 385 /* Insert the packet in a different queue. These packets will be
lorevee 0:ac0b0725c6fa 386 inserted back in the main queue just before exiting from send_req(), so that
lorevee 0:ac0b0725c6fa 387 these events can be processed by the application.
lorevee 0:ac0b0725c6fa 388 */
lorevee 0:ac0b0725c6fa 389 list_insert_tail(&hciTempQueue, (tListNode *)hciReadPacket);
lorevee 0:ac0b0725c6fa 390 hciReadPacket = NULL;
lorevee 0:ac0b0725c6fa 391 }
lorevee 0:ac0b0725c6fa 392
lorevee 0:ac0b0725c6fa 393 HCI_HandleSPI();
lorevee 0:ac0b0725c6fa 394
lorevee 0:ac0b0725c6fa 395 Enable_SPI_IRQ();
lorevee 0:ac0b0725c6fa 396
lorevee 0:ac0b0725c6fa 397 }
lorevee 0:ac0b0725c6fa 398
lorevee 0:ac0b0725c6fa 399 failed:
lorevee 0:ac0b0725c6fa 400 if(hciReadPacket != NULL) {
lorevee 0:ac0b0725c6fa 401 list_insert_head(&hciReadPktPool, (tListNode *)hciReadPacket);
lorevee 0:ac0b0725c6fa 402 #ifdef POOL_CNT
lorevee 0:ac0b0725c6fa 403 nr_hciReadPktPool++;
lorevee 0:ac0b0725c6fa 404 #endif
lorevee 0:ac0b0725c6fa 405 }
lorevee 0:ac0b0725c6fa 406 move_list(&hciReadPktRxQueue, &hciTempQueue);
lorevee 0:ac0b0725c6fa 407 Enable_SPI_IRQ();
lorevee 0:ac0b0725c6fa 408 return -1;
lorevee 0:ac0b0725c6fa 409
lorevee 0:ac0b0725c6fa 410 done:
lorevee 0:ac0b0725c6fa 411 // Insert the packet back into the pool.
lorevee 0:ac0b0725c6fa 412 list_insert_head(&hciReadPktPool, (tListNode *)hciReadPacket);
lorevee 0:ac0b0725c6fa 413 #ifdef POOL_CNT
lorevee 0:ac0b0725c6fa 414 nr_hciReadPktPool++;
lorevee 0:ac0b0725c6fa 415 #endif
lorevee 0:ac0b0725c6fa 416 move_list(&hciReadPktRxQueue, &hciTempQueue);
lorevee 0:ac0b0725c6fa 417
lorevee 0:ac0b0725c6fa 418 Enable_SPI_IRQ();
lorevee 0:ac0b0725c6fa 419 return 0;
lorevee 0:ac0b0725c6fa 420 }
lorevee 0:ac0b0725c6fa 421