HW layer for the Nucleo board, it only work with old BLE_API

Dependents:   Hello_BLE F446RE-BLE

Fork of X_NUCLEO_IDB0XA1 by ST

Committer:
apalmieri
Date:
Fri Jul 24 17:16:54 2015 +0000
Revision:
95:e1f7ce04e71b
Parent:
91:97c0c21046b4
Child:
103:12684d94c3a6
Restore previous version of HCI stack
;
; Also re-enable AD_TYPE_FLAGS within Advertising payload

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wolfgang Betz 90:26c0c9807ab4 1 /**
Wolfgang Betz 90:26c0c9807ab4 2 ******************************************************************************
apalmieri 95:e1f7ce04e71b 3 * @file hci.c
Wolfgang Betz 90:26c0c9807ab4 4 * @author AMS/HESA Application Team
Wolfgang Betz 90:26c0c9807ab4 5 * @brief Function for managing HCI interface.
Wolfgang Betz 90:26c0c9807ab4 6 ******************************************************************************
Wolfgang Betz 90:26c0c9807ab4 7 *
Wolfgang Betz 90:26c0c9807ab4 8 *
Wolfgang Betz 90:26c0c9807ab4 9 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
Wolfgang Betz 90:26c0c9807ab4 10 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
Wolfgang Betz 90:26c0c9807ab4 11 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
Wolfgang Betz 90:26c0c9807ab4 12 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
Wolfgang Betz 90:26c0c9807ab4 13 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
Wolfgang Betz 90:26c0c9807ab4 14 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
Wolfgang Betz 90:26c0c9807ab4 15 *
Wolfgang Betz 90:26c0c9807ab4 16 * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
apalmieri 95:e1f7ce04e71b 17 */
Wolfgang Betz 90:26c0c9807ab4 18
Wolfgang Betz 90:26c0c9807ab4 19 #include "hal_types.h"
Wolfgang Betz 90:26c0c9807ab4 20 #include "osal.h"
Wolfgang Betz 90:26c0c9807ab4 21 #include "ble_status.h"
Wolfgang Betz 90:26c0c9807ab4 22 #include "hal.h"
Wolfgang Betz 90:26c0c9807ab4 23 #include "hci_const.h"
Wolfgang Betz 90:26c0c9807ab4 24 #include "gp_timer.h"
Wolfgang Betz 90:26c0c9807ab4 25
Wolfgang Betz 90:26c0c9807ab4 26 #include "stm32_bluenrg_ble.h"
Wolfgang Betz 90:26c0c9807ab4 27
Wolfgang Betz 90:26c0c9807ab4 28 #if BLE_CONFIG_DBG_ENABLE
Wolfgang Betz 90:26c0c9807ab4 29 #define PRINTF(...) printf(__VA_ARGS__)
Wolfgang Betz 90:26c0c9807ab4 30 #else
Wolfgang Betz 90:26c0c9807ab4 31 #define PRINTF(...)
Wolfgang Betz 90:26c0c9807ab4 32 #endif
Wolfgang Betz 90:26c0c9807ab4 33
Wolfgang Betz 90:26c0c9807ab4 34 #define HCI_LOG_ON 0
Wolfgang Betz 90:26c0c9807ab4 35
Wolfgang Betz 90:26c0c9807ab4 36 #define HCI_READ_PACKET_NUM_MAX (5)
Wolfgang Betz 90:26c0c9807ab4 37
Wolfgang Betz 90:26c0c9807ab4 38 #define MIN(a,b) ((a) < (b) )? (a) : (b)
Wolfgang Betz 90:26c0c9807ab4 39 #define MAX(a,b) ((a) > (b) )? (a) : (b)
Wolfgang Betz 90:26c0c9807ab4 40
Wolfgang Betz 90:26c0c9807ab4 41 tListNode hciReadPktPool;
Wolfgang Betz 90:26c0c9807ab4 42 tListNode hciReadPktRxQueue;
Wolfgang Betz 90:26c0c9807ab4 43 /* pool of hci read packets */
Wolfgang Betz 90:26c0c9807ab4 44 static tHciDataPacket hciReadPacketBuffer[HCI_READ_PACKET_NUM_MAX];
Wolfgang Betz 90:26c0c9807ab4 45
Wolfgang Betz 90:26c0c9807ab4 46 static volatile uint8_t readPacketListFull=FALSE;
Wolfgang Betz 90:26c0c9807ab4 47
Wolfgang Betz 90:26c0c9807ab4 48 static volatile uint8_t hci_timer_id;
Wolfgang Betz 90:26c0c9807ab4 49 static volatile uint8_t hci_timeout;
Wolfgang Betz 90:26c0c9807ab4 50
Wolfgang Betz 90:26c0c9807ab4 51 void hci_timeout_callback(void)
Wolfgang Betz 90:26c0c9807ab4 52 {
apalmieri 95:e1f7ce04e71b 53 hci_timeout = 1;
apalmieri 95:e1f7ce04e71b 54 return;
Wolfgang Betz 90:26c0c9807ab4 55 }
Wolfgang Betz 90:26c0c9807ab4 56
Wolfgang Betz 90:26c0c9807ab4 57 void HCI_Init(void)
Wolfgang Betz 90:26c0c9807ab4 58 {
apalmieri 95:e1f7ce04e71b 59 uint8_t index;
apalmieri 95:e1f7ce04e71b 60
apalmieri 95:e1f7ce04e71b 61 /* Initialize list heads of ready and free hci data packet queues */
apalmieri 95:e1f7ce04e71b 62 list_init_head (&hciReadPktPool);
apalmieri 95:e1f7ce04e71b 63 list_init_head (&hciReadPktRxQueue);
apalmieri 95:e1f7ce04e71b 64
apalmieri 95:e1f7ce04e71b 65 /* Initialize the queue of free hci data packets */
apalmieri 95:e1f7ce04e71b 66 for (index = 0; index < HCI_READ_PACKET_NUM_MAX; index++)
apalmieri 95:e1f7ce04e71b 67 {
apalmieri 95:e1f7ce04e71b 68 list_insert_tail(&hciReadPktPool, (tListNode *)&hciReadPacketBuffer[index]);
apalmieri 95:e1f7ce04e71b 69 }
Wolfgang Betz 90:26c0c9807ab4 70 }
Wolfgang Betz 90:26c0c9807ab4 71
Wolfgang Betz 90:26c0c9807ab4 72 #define HCI_PCK_TYPE_OFFSET 0
Wolfgang Betz 90:26c0c9807ab4 73 #define EVENT_PARAMETER_TOT_LEN_OFFSET 2
Wolfgang Betz 90:26c0c9807ab4 74
Wolfgang Betz 90:26c0c9807ab4 75 /**
Wolfgang Betz 90:26c0c9807ab4 76 * Verify if HCI packet is correctly formatted..
Wolfgang Betz 90:26c0c9807ab4 77 *
Wolfgang Betz 90:26c0c9807ab4 78 * @param[in] hciReadPacket The packet that is received from HCI interface.
Wolfgang Betz 90:26c0c9807ab4 79 * @return 0 if HCI packet is as expected
Wolfgang Betz 90:26c0c9807ab4 80 */
Wolfgang Betz 90:26c0c9807ab4 81 int HCI_verify(const tHciDataPacket * hciReadPacket)
Wolfgang Betz 90:26c0c9807ab4 82 {
apalmieri 95:e1f7ce04e71b 83 const uint8_t *hci_pckt = hciReadPacket->dataBuff;
apalmieri 95:e1f7ce04e71b 84
apalmieri 95:e1f7ce04e71b 85 if(hci_pckt[HCI_PCK_TYPE_OFFSET] != HCI_EVENT_PKT)
apalmieri 95:e1f7ce04e71b 86 return 1; /* Incorrect type. */
apalmieri 95:e1f7ce04e71b 87
apalmieri 95:e1f7ce04e71b 88 if(hci_pckt[EVENT_PARAMETER_TOT_LEN_OFFSET] != hciReadPacket->data_len - (1+HCI_EVENT_HDR_SIZE))
apalmieri 95:e1f7ce04e71b 89 return 2; /* Wrong length (packet truncated or too long). */
apalmieri 95:e1f7ce04e71b 90
apalmieri 95:e1f7ce04e71b 91 return 0;
Wolfgang Betz 90:26c0c9807ab4 92 }
Wolfgang Betz 90:26c0c9807ab4 93
Wolfgang Betz 90:26c0c9807ab4 94 void HCI_Process(void)
Wolfgang Betz 90:26c0c9807ab4 95 {
apalmieri 95:e1f7ce04e71b 96 uint8_t data_len;
apalmieri 95:e1f7ce04e71b 97 uint8_t buffer[HCI_READ_PACKET_SIZE];
apalmieri 95:e1f7ce04e71b 98 tHciDataPacket * hciReadPacket = NULL;
apalmieri 95:e1f7ce04e71b 99
apalmieri 95:e1f7ce04e71b 100 Disable_SPI_IRQ();
apalmieri 95:e1f7ce04e71b 101 uint8_t list_empty = list_is_empty(&hciReadPktRxQueue);
apalmieri 95:e1f7ce04e71b 102 /* process any pending events read */
apalmieri 95:e1f7ce04e71b 103 while(list_empty == FALSE)
apalmieri 95:e1f7ce04e71b 104 {
apalmieri 95:e1f7ce04e71b 105 list_remove_head (&hciReadPktRxQueue, (tListNode **)&hciReadPacket);
apalmieri 95:e1f7ce04e71b 106 Enable_SPI_IRQ();
apalmieri 95:e1f7ce04e71b 107 HCI_Event_CB(hciReadPacket->dataBuff);
Wolfgang Betz 90:26c0c9807ab4 108 Disable_SPI_IRQ();
apalmieri 95:e1f7ce04e71b 109 list_insert_tail(&hciReadPktPool, (tListNode *)hciReadPacket);
apalmieri 95:e1f7ce04e71b 110 list_empty = list_is_empty(&hciReadPktRxQueue);
apalmieri 95:e1f7ce04e71b 111 }
apalmieri 95:e1f7ce04e71b 112 if (readPacketListFull) {
apalmieri 95:e1f7ce04e71b 113 while(BlueNRG_DataPresent()) {
apalmieri 95:e1f7ce04e71b 114 data_len = BlueNRG_SPI_Read_All(buffer, HCI_READ_PACKET_SIZE);
apalmieri 95:e1f7ce04e71b 115 if(data_len > 0)
apalmieri 95:e1f7ce04e71b 116 HCI_Event_CB(buffer);
Wolfgang Betz 90:26c0c9807ab4 117 }
apalmieri 95:e1f7ce04e71b 118 readPacketListFull = FALSE;
apalmieri 95:e1f7ce04e71b 119 }
apalmieri 95:e1f7ce04e71b 120
apalmieri 95:e1f7ce04e71b 121 Enable_SPI_IRQ();
Wolfgang Betz 90:26c0c9807ab4 122 }
Wolfgang Betz 90:26c0c9807ab4 123
Wolfgang Betz 90:26c0c9807ab4 124 BOOL HCI_Queue_Empty(void)
Wolfgang Betz 90:26c0c9807ab4 125 {
apalmieri 95:e1f7ce04e71b 126 return list_is_empty(&hciReadPktRxQueue);
Wolfgang Betz 90:26c0c9807ab4 127 }
Wolfgang Betz 90:26c0c9807ab4 128
Wolfgang Betz 90:26c0c9807ab4 129 void HCI_Isr(void)
Wolfgang Betz 90:26c0c9807ab4 130 {
apalmieri 95:e1f7ce04e71b 131 tHciDataPacket * hciReadPacket = NULL;
apalmieri 95:e1f7ce04e71b 132 uint8_t data_len;
apalmieri 95:e1f7ce04e71b 133
apalmieri 95:e1f7ce04e71b 134 Clear_SPI_EXTI_Flag();
apalmieri 95:e1f7ce04e71b 135 while(BlueNRG_DataPresent()){
apalmieri 95:e1f7ce04e71b 136 if (list_is_empty (&hciReadPktPool) == FALSE){
apalmieri 95:e1f7ce04e71b 137
apalmieri 95:e1f7ce04e71b 138 /* enqueueing a packet for read */
apalmieri 95:e1f7ce04e71b 139 list_remove_head (&hciReadPktPool, (tListNode **)&hciReadPacket);
apalmieri 95:e1f7ce04e71b 140
apalmieri 95:e1f7ce04e71b 141 data_len = BlueNRG_SPI_Read_All(hciReadPacket->dataBuff, HCI_READ_PACKET_SIZE);
apalmieri 95:e1f7ce04e71b 142 if(data_len > 0){
apalmieri 95:e1f7ce04e71b 143 hciReadPacket->data_len = data_len;
apalmieri 95:e1f7ce04e71b 144 if(HCI_verify(hciReadPacket) == 0)
apalmieri 95:e1f7ce04e71b 145 list_insert_tail(&hciReadPktRxQueue, (tListNode *)hciReadPacket);
apalmieri 95:e1f7ce04e71b 146 else
apalmieri 95:e1f7ce04e71b 147 list_insert_head(&hciReadPktPool, (tListNode *)hciReadPacket);
apalmieri 95:e1f7ce04e71b 148 }
apalmieri 95:e1f7ce04e71b 149 else {
apalmieri 95:e1f7ce04e71b 150 // Insert the packet back into the pool.
apalmieri 95:e1f7ce04e71b 151 list_insert_head(&hciReadPktPool, (tListNode *)hciReadPacket);
apalmieri 95:e1f7ce04e71b 152 }
apalmieri 95:e1f7ce04e71b 153
apalmieri 95:e1f7ce04e71b 154 }
apalmieri 95:e1f7ce04e71b 155 else{
apalmieri 95:e1f7ce04e71b 156 // HCI Read Packet Pool is empty, wait for a free packet.
apalmieri 95:e1f7ce04e71b 157 readPacketListFull = TRUE;
apalmieri 95:e1f7ce04e71b 158 Clear_SPI_EXTI_Flag();
apalmieri 95:e1f7ce04e71b 159 return;
apalmieri 95:e1f7ce04e71b 160 }
apalmieri 95:e1f7ce04e71b 161
Wolfgang Betz 91:97c0c21046b4 162 Clear_SPI_EXTI_Flag();
apalmieri 95:e1f7ce04e71b 163 }
Wolfgang Betz 90:26c0c9807ab4 164 }
Wolfgang Betz 90:26c0c9807ab4 165
Wolfgang Betz 90:26c0c9807ab4 166 void hci_write(const void* data1, const void* data2, uint8_t n_bytes1, uint8_t n_bytes2){
Wolfgang Betz 90:26c0c9807ab4 167 #if HCI_LOG_ON
apalmieri 95:e1f7ce04e71b 168 PRINTF("HCI <- ");
apalmieri 95:e1f7ce04e71b 169 for(int i=0; i < n_bytes1; i++)
apalmieri 95:e1f7ce04e71b 170 PRINTF("%02X ", *((uint8_t*)data1 + i));
apalmieri 95:e1f7ce04e71b 171 for(int i=0; i < n_bytes2; i++)
apalmieri 95:e1f7ce04e71b 172 PRINTF("%02X ", *((uint8_t*)data2 + i));
apalmieri 95:e1f7ce04e71b 173 PRINTF("\n");
Wolfgang Betz 90:26c0c9807ab4 174 #endif
apalmieri 95:e1f7ce04e71b 175
apalmieri 95:e1f7ce04e71b 176 Hal_Write_Serial(data1, data2, n_bytes1, n_bytes2);
Wolfgang Betz 90:26c0c9807ab4 177 }
Wolfgang Betz 90:26c0c9807ab4 178
Wolfgang Betz 90:26c0c9807ab4 179 void hci_send_cmd(uint16_t ogf, uint16_t ocf, uint8_t plen, void *param)
Wolfgang Betz 90:26c0c9807ab4 180 {
apalmieri 95:e1f7ce04e71b 181 hci_command_hdr hc;
apalmieri 95:e1f7ce04e71b 182
apalmieri 95:e1f7ce04e71b 183 hc.opcode = htobs(cmd_opcode_pack(ogf, ocf));
apalmieri 95:e1f7ce04e71b 184 hc.plen= plen;
apalmieri 95:e1f7ce04e71b 185
apalmieri 95:e1f7ce04e71b 186 uint8_t header[HCI_HDR_SIZE + HCI_COMMAND_HDR_SIZE];
apalmieri 95:e1f7ce04e71b 187 header[0] = HCI_COMMAND_PKT;
apalmieri 95:e1f7ce04e71b 188 Osal_MemCpy(header+1, &hc, sizeof(hc));
apalmieri 95:e1f7ce04e71b 189
apalmieri 95:e1f7ce04e71b 190 hci_write(header, param, sizeof(header), plen);
Wolfgang Betz 90:26c0c9807ab4 191 }
Wolfgang Betz 90:26c0c9807ab4 192
Wolfgang Betz 90:26c0c9807ab4 193 static void move_list(tListNode * dest_list, tListNode * src_list)
Wolfgang Betz 90:26c0c9807ab4 194 {
apalmieri 95:e1f7ce04e71b 195 pListNode tmp_node;
apalmieri 95:e1f7ce04e71b 196
apalmieri 95:e1f7ce04e71b 197 while(!list_is_empty(src_list)){
apalmieri 95:e1f7ce04e71b 198 list_remove_head(src_list, &tmp_node);
apalmieri 95:e1f7ce04e71b 199 list_insert_tail(dest_list, tmp_node);
apalmieri 95:e1f7ce04e71b 200 }
Wolfgang Betz 90:26c0c9807ab4 201 }
Wolfgang Betz 90:26c0c9807ab4 202
Wolfgang Betz 90:26c0c9807ab4 203 int hci_send_req(struct hci_request *r, BOOL async)
Wolfgang Betz 90:26c0c9807ab4 204 {
apalmieri 95:e1f7ce04e71b 205 uint8_t *ptr;
apalmieri 95:e1f7ce04e71b 206 uint16_t opcode = htobs(cmd_opcode_pack(r->ogf, r->ocf));
apalmieri 95:e1f7ce04e71b 207 hci_event_pckt *event_pckt;
apalmieri 95:e1f7ce04e71b 208 hci_uart_pckt *hci_hdr;
apalmieri 95:e1f7ce04e71b 209 int to = DEFAULT_TIMEOUT;
apalmieri 95:e1f7ce04e71b 210 struct timer t;
apalmieri 95:e1f7ce04e71b 211 tHciDataPacket * hciReadPacket = NULL;
apalmieri 95:e1f7ce04e71b 212 tListNode hciTempQueue;
apalmieri 95:e1f7ce04e71b 213
apalmieri 95:e1f7ce04e71b 214 list_init_head(&hciTempQueue);
apalmieri 95:e1f7ce04e71b 215
apalmieri 95:e1f7ce04e71b 216 hci_send_cmd(r->ogf, r->ocf, r->clen, r->cparam);
apalmieri 95:e1f7ce04e71b 217
apalmieri 95:e1f7ce04e71b 218 if(async){
apalmieri 95:e1f7ce04e71b 219 goto done;
apalmieri 95:e1f7ce04e71b 220 }
apalmieri 95:e1f7ce04e71b 221
apalmieri 95:e1f7ce04e71b 222 /* Minimum timeout is 1. */
apalmieri 95:e1f7ce04e71b 223 if(to == 0)
apalmieri 95:e1f7ce04e71b 224 to = 1;
apalmieri 95:e1f7ce04e71b 225
apalmieri 95:e1f7ce04e71b 226 Timer_Set(&t, to);
apalmieri 95:e1f7ce04e71b 227
apalmieri 95:e1f7ce04e71b 228 while(1) {
apalmieri 95:e1f7ce04e71b 229 evt_cmd_complete *cc;
apalmieri 95:e1f7ce04e71b 230 evt_cmd_status *cs;
apalmieri 95:e1f7ce04e71b 231 evt_le_meta_event *me;
apalmieri 95:e1f7ce04e71b 232 int len;
apalmieri 95:e1f7ce04e71b 233
apalmieri 95:e1f7ce04e71b 234 #if ENABLE_MICRO_SLEEP
apalmieri 95:e1f7ce04e71b 235 while(1){
apalmieri 95:e1f7ce04e71b 236 ATOMIC_SECTION_BEGIN();
apalmieri 95:e1f7ce04e71b 237 if(Timer_Expired(&t)){
apalmieri 95:e1f7ce04e71b 238 ATOMIC_SECTION_END();
apalmieri 95:e1f7ce04e71b 239 goto failed;
apalmieri 95:e1f7ce04e71b 240 }
apalmieri 95:e1f7ce04e71b 241 if(!HCI_Queue_Empty()){
apalmieri 95:e1f7ce04e71b 242 ATOMIC_SECTION_END();
apalmieri 95:e1f7ce04e71b 243 break;
apalmieri 95:e1f7ce04e71b 244 }
apalmieri 95:e1f7ce04e71b 245 Enter_Sleep_Mode();
apalmieri 95:e1f7ce04e71b 246 ATOMIC_SECTION_END();
Wolfgang Betz 91:97c0c21046b4 247 }
Wolfgang Betz 90:26c0c9807ab4 248 #else
apalmieri 95:e1f7ce04e71b 249 while(1){
apalmieri 95:e1f7ce04e71b 250 if(Timer_Expired(&t)){
apalmieri 95:e1f7ce04e71b 251 goto failed;
apalmieri 95:e1f7ce04e71b 252 }
apalmieri 95:e1f7ce04e71b 253 if(!HCI_Queue_Empty()){
apalmieri 95:e1f7ce04e71b 254 break;
apalmieri 95:e1f7ce04e71b 255 }
apalmieri 95:e1f7ce04e71b 256 }
Wolfgang Betz 90:26c0c9807ab4 257 #endif
apalmieri 95:e1f7ce04e71b 258
apalmieri 95:e1f7ce04e71b 259 /* Extract packet from HCI event queue. */
apalmieri 95:e1f7ce04e71b 260 Disable_SPI_IRQ();
apalmieri 95:e1f7ce04e71b 261 list_remove_head(&hciReadPktRxQueue, (tListNode **)&hciReadPacket);
apalmieri 95:e1f7ce04e71b 262
apalmieri 95:e1f7ce04e71b 263 hci_hdr = (void *)hciReadPacket->dataBuff;
apalmieri 95:e1f7ce04e71b 264 if(hci_hdr->type != HCI_EVENT_PKT){
apalmieri 95:e1f7ce04e71b 265 list_insert_tail(&hciTempQueue, (tListNode *)hciReadPacket); // See comment below
apalmieri 95:e1f7ce04e71b 266 Enable_SPI_IRQ();
apalmieri 95:e1f7ce04e71b 267 continue;
apalmieri 95:e1f7ce04e71b 268 }
apalmieri 95:e1f7ce04e71b 269
apalmieri 95:e1f7ce04e71b 270 event_pckt = (void *) (hci_hdr->data);
apalmieri 95:e1f7ce04e71b 271
apalmieri 95:e1f7ce04e71b 272 ptr = hciReadPacket->dataBuff + (1 + HCI_EVENT_HDR_SIZE);
apalmieri 95:e1f7ce04e71b 273 len = hciReadPacket->data_len - (1 + HCI_EVENT_HDR_SIZE);
apalmieri 95:e1f7ce04e71b 274
apalmieri 95:e1f7ce04e71b 275 switch (event_pckt->evt) {
apalmieri 95:e1f7ce04e71b 276
apalmieri 95:e1f7ce04e71b 277 case EVT_CMD_STATUS:
apalmieri 95:e1f7ce04e71b 278 cs = (void *) ptr;
apalmieri 95:e1f7ce04e71b 279
apalmieri 95:e1f7ce04e71b 280 if (cs->opcode != opcode)
apalmieri 95:e1f7ce04e71b 281 goto failed;
apalmieri 95:e1f7ce04e71b 282
apalmieri 95:e1f7ce04e71b 283 if (r->event != EVT_CMD_STATUS) {
apalmieri 95:e1f7ce04e71b 284 if (cs->status) {
apalmieri 95:e1f7ce04e71b 285 goto failed;
Wolfgang Betz 90:26c0c9807ab4 286 }
apalmieri 95:e1f7ce04e71b 287 break;
apalmieri 95:e1f7ce04e71b 288 }
apalmieri 95:e1f7ce04e71b 289
apalmieri 95:e1f7ce04e71b 290 r->rlen = MIN(len, r->rlen);
apalmieri 95:e1f7ce04e71b 291 Osal_MemCpy(r->rparam, ptr, r->rlen);
apalmieri 95:e1f7ce04e71b 292 goto done;
apalmieri 95:e1f7ce04e71b 293
apalmieri 95:e1f7ce04e71b 294 case EVT_CMD_COMPLETE:
apalmieri 95:e1f7ce04e71b 295 cc = (void *) ptr;
apalmieri 95:e1f7ce04e71b 296
apalmieri 95:e1f7ce04e71b 297 if (cc->opcode != opcode)
apalmieri 95:e1f7ce04e71b 298 goto failed;
apalmieri 95:e1f7ce04e71b 299
apalmieri 95:e1f7ce04e71b 300 ptr += EVT_CMD_COMPLETE_SIZE;
apalmieri 95:e1f7ce04e71b 301 len -= EVT_CMD_COMPLETE_SIZE;
apalmieri 95:e1f7ce04e71b 302
apalmieri 95:e1f7ce04e71b 303 r->rlen = MIN(len, r->rlen);
apalmieri 95:e1f7ce04e71b 304 Osal_MemCpy(r->rparam, ptr, r->rlen);
apalmieri 95:e1f7ce04e71b 305 goto done;
apalmieri 95:e1f7ce04e71b 306
apalmieri 95:e1f7ce04e71b 307 case EVT_LE_META_EVENT:
apalmieri 95:e1f7ce04e71b 308 me = (void *) ptr;
apalmieri 95:e1f7ce04e71b 309
apalmieri 95:e1f7ce04e71b 310 if (me->subevent != r->event)
apalmieri 95:e1f7ce04e71b 311 break;
apalmieri 95:e1f7ce04e71b 312
apalmieri 95:e1f7ce04e71b 313 len -= 1;
apalmieri 95:e1f7ce04e71b 314 r->rlen = MIN(len, r->rlen);
apalmieri 95:e1f7ce04e71b 315 Osal_MemCpy(r->rparam, me->data, r->rlen);
apalmieri 95:e1f7ce04e71b 316 goto done;
apalmieri 95:e1f7ce04e71b 317
apalmieri 95:e1f7ce04e71b 318 case EVT_HARDWARE_ERROR:
apalmieri 95:e1f7ce04e71b 319 goto failed;
apalmieri 95:e1f7ce04e71b 320
apalmieri 95:e1f7ce04e71b 321 default:
apalmieri 95:e1f7ce04e71b 322 break;
apalmieri 95:e1f7ce04e71b 323 }
apalmieri 95:e1f7ce04e71b 324
apalmieri 95:e1f7ce04e71b 325 /* In the meantime there could be other events from the controller.
Wolfgang Betz 90:26c0c9807ab4 326 In this case, insert the packet in a different queue. These packets will be
Wolfgang Betz 90:26c0c9807ab4 327 inserted back in the main queue just before exiting from send_req().
Wolfgang Betz 90:26c0c9807ab4 328 */
apalmieri 95:e1f7ce04e71b 329 list_insert_tail(&hciTempQueue, (tListNode *)hciReadPacket);
apalmieri 95:e1f7ce04e71b 330 /* Be sure there is at list one packet in the pool to process the expected event. */
apalmieri 95:e1f7ce04e71b 331 if(list_is_empty(&hciReadPktPool)){
apalmieri 95:e1f7ce04e71b 332 pListNode tmp_node;
apalmieri 95:e1f7ce04e71b 333 list_remove_head(&hciReadPktRxQueue, &tmp_node);
apalmieri 95:e1f7ce04e71b 334 list_insert_tail(&hciReadPktPool, tmp_node);
Wolfgang Betz 90:26c0c9807ab4 335 }
apalmieri 95:e1f7ce04e71b 336
apalmieri 95:e1f7ce04e71b 337 Enable_SPI_IRQ();
apalmieri 95:e1f7ce04e71b 338
apalmieri 95:e1f7ce04e71b 339 }
apalmieri 95:e1f7ce04e71b 340
Wolfgang Betz 91:97c0c21046b4 341 failed:
apalmieri 95:e1f7ce04e71b 342 move_list(&hciReadPktRxQueue, &hciTempQueue);
apalmieri 95:e1f7ce04e71b 343 Enable_SPI_IRQ();
apalmieri 95:e1f7ce04e71b 344 return -1;
apalmieri 95:e1f7ce04e71b 345
Wolfgang Betz 90:26c0c9807ab4 346 done:
apalmieri 95:e1f7ce04e71b 347 // Insert the packet back into the pool.
apalmieri 95:e1f7ce04e71b 348 list_insert_head(&hciReadPktPool, (tListNode *)hciReadPacket);
apalmieri 95:e1f7ce04e71b 349 move_list(&hciReadPktRxQueue, &hciTempQueue);
apalmieri 95:e1f7ce04e71b 350
apalmieri 95:e1f7ce04e71b 351 Enable_SPI_IRQ();
apalmieri 95:e1f7ce04e71b 352 return 0;
Wolfgang Betz 90:26c0c9807ab4 353 }
Wolfgang Betz 90:26c0c9807ab4 354
Wolfgang Betz 90:26c0c9807ab4 355 int hci_reset()
Wolfgang Betz 90:26c0c9807ab4 356 {
apalmieri 95:e1f7ce04e71b 357 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 358 uint8_t status;
apalmieri 95:e1f7ce04e71b 359
apalmieri 95:e1f7ce04e71b 360 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 361 rq.ogf = OGF_HOST_CTL;
apalmieri 95:e1f7ce04e71b 362 rq.ocf = OCF_RESET;
apalmieri 95:e1f7ce04e71b 363 rq.rparam = &status;
apalmieri 95:e1f7ce04e71b 364 rq.rlen = 1;
apalmieri 95:e1f7ce04e71b 365
apalmieri 95:e1f7ce04e71b 366 if (hci_send_req(&rq, FALSE) < 0)
apalmieri 95:e1f7ce04e71b 367 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 368
apalmieri 95:e1f7ce04e71b 369 return status;
Wolfgang Betz 90:26c0c9807ab4 370 }
Wolfgang Betz 90:26c0c9807ab4 371
Wolfgang Betz 90:26c0c9807ab4 372 int hci_disconnect(uint16_t handle, uint8_t reason)
Wolfgang Betz 90:26c0c9807ab4 373 {
apalmieri 95:e1f7ce04e71b 374 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 375 disconnect_cp cp;
apalmieri 95:e1f7ce04e71b 376 uint8_t status;
apalmieri 95:e1f7ce04e71b 377
apalmieri 95:e1f7ce04e71b 378 cp.handle = handle;
apalmieri 95:e1f7ce04e71b 379 cp.reason = reason;
apalmieri 95:e1f7ce04e71b 380
apalmieri 95:e1f7ce04e71b 381 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 382 rq.ogf = OGF_LINK_CTL;
apalmieri 95:e1f7ce04e71b 383 rq.ocf = OCF_DISCONNECT;
apalmieri 95:e1f7ce04e71b 384 rq.cparam = &cp;
apalmieri 95:e1f7ce04e71b 385 rq.clen = DISCONNECT_CP_SIZE;
apalmieri 95:e1f7ce04e71b 386 rq.event = EVT_CMD_STATUS;
apalmieri 95:e1f7ce04e71b 387 rq.rparam = &status;
apalmieri 95:e1f7ce04e71b 388 rq.rlen = 1;
apalmieri 95:e1f7ce04e71b 389
apalmieri 95:e1f7ce04e71b 390 if (hci_send_req(&rq, FALSE) < 0)
apalmieri 95:e1f7ce04e71b 391 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 392
apalmieri 95:e1f7ce04e71b 393 return status;
Wolfgang Betz 90:26c0c9807ab4 394 }
Wolfgang Betz 90:26c0c9807ab4 395
Wolfgang Betz 90:26c0c9807ab4 396 int hci_le_read_local_version(uint8_t *hci_version, uint16_t *hci_revision, uint8_t *lmp_pal_version,
Wolfgang Betz 90:26c0c9807ab4 397 uint16_t *manufacturer_name, uint16_t *lmp_pal_subversion)
Wolfgang Betz 90:26c0c9807ab4 398 {
apalmieri 95:e1f7ce04e71b 399 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 400 read_local_version_rp resp;
apalmieri 95:e1f7ce04e71b 401
apalmieri 95:e1f7ce04e71b 402 Osal_MemSet(&resp, 0, sizeof(resp));
apalmieri 95:e1f7ce04e71b 403
apalmieri 95:e1f7ce04e71b 404 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 405 rq.ogf = OGF_INFO_PARAM;
apalmieri 95:e1f7ce04e71b 406 rq.ocf = OCF_READ_LOCAL_VERSION;
apalmieri 95:e1f7ce04e71b 407 rq.cparam = NULL;
apalmieri 95:e1f7ce04e71b 408 rq.clen = 0;
apalmieri 95:e1f7ce04e71b 409 rq.rparam = &resp;
apalmieri 95:e1f7ce04e71b 410 rq.rlen = READ_LOCAL_VERSION_RP_SIZE;
apalmieri 95:e1f7ce04e71b 411
apalmieri 95:e1f7ce04e71b 412 if (hci_send_req(&rq, FALSE) < 0)
apalmieri 95:e1f7ce04e71b 413 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 414
apalmieri 95:e1f7ce04e71b 415 if (resp.status) {
apalmieri 95:e1f7ce04e71b 416 return resp.status;
apalmieri 95:e1f7ce04e71b 417 }
apalmieri 95:e1f7ce04e71b 418
apalmieri 95:e1f7ce04e71b 419
apalmieri 95:e1f7ce04e71b 420 *hci_version = resp.hci_version;
apalmieri 95:e1f7ce04e71b 421 *hci_revision = btohs(resp.hci_revision);
apalmieri 95:e1f7ce04e71b 422 *lmp_pal_version = resp.lmp_pal_version;
apalmieri 95:e1f7ce04e71b 423 *manufacturer_name = btohs(resp.manufacturer_name);
apalmieri 95:e1f7ce04e71b 424 *lmp_pal_subversion = btohs(resp.lmp_pal_subversion);
apalmieri 95:e1f7ce04e71b 425
apalmieri 95:e1f7ce04e71b 426 return 0;
Wolfgang Betz 90:26c0c9807ab4 427 }
Wolfgang Betz 90:26c0c9807ab4 428
Wolfgang Betz 90:26c0c9807ab4 429 int hci_le_read_buffer_size(uint16_t *pkt_len, uint8_t *max_pkt)
Wolfgang Betz 90:26c0c9807ab4 430 {
apalmieri 95:e1f7ce04e71b 431 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 432 le_read_buffer_size_rp resp;
apalmieri 95:e1f7ce04e71b 433
apalmieri 95:e1f7ce04e71b 434 Osal_MemSet(&resp, 0, sizeof(resp));
apalmieri 95:e1f7ce04e71b 435
apalmieri 95:e1f7ce04e71b 436 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 437 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 438 rq.ocf = OCF_LE_READ_BUFFER_SIZE;
apalmieri 95:e1f7ce04e71b 439 rq.cparam = NULL;
apalmieri 95:e1f7ce04e71b 440 rq.clen = 0;
apalmieri 95:e1f7ce04e71b 441 rq.rparam = &resp;
apalmieri 95:e1f7ce04e71b 442 rq.rlen = LE_READ_BUFFER_SIZE_RP_SIZE;
apalmieri 95:e1f7ce04e71b 443
apalmieri 95:e1f7ce04e71b 444 if (hci_send_req(&rq, FALSE) < 0)
apalmieri 95:e1f7ce04e71b 445 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 446
apalmieri 95:e1f7ce04e71b 447 if (resp.status) {
apalmieri 95:e1f7ce04e71b 448 return resp.status;
apalmieri 95:e1f7ce04e71b 449 }
apalmieri 95:e1f7ce04e71b 450
apalmieri 95:e1f7ce04e71b 451 *pkt_len = resp.pkt_len;
apalmieri 95:e1f7ce04e71b 452 *max_pkt = resp.max_pkt;
apalmieri 95:e1f7ce04e71b 453
apalmieri 95:e1f7ce04e71b 454 return 0;
Wolfgang Betz 90:26c0c9807ab4 455 }
Wolfgang Betz 90:26c0c9807ab4 456
Wolfgang Betz 90:26c0c9807ab4 457 int hci_le_set_advertising_parameters(uint16_t min_interval, uint16_t max_interval, uint8_t advtype,
Wolfgang Betz 90:26c0c9807ab4 458 uint8_t own_bdaddr_type, uint8_t direct_bdaddr_type, const tBDAddr direct_bdaddr, uint8_t chan_map,
Wolfgang Betz 90:26c0c9807ab4 459 uint8_t filter)
Wolfgang Betz 90:26c0c9807ab4 460 {
apalmieri 95:e1f7ce04e71b 461 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 462 le_set_adv_parameters_cp adv_cp;
apalmieri 95:e1f7ce04e71b 463 uint8_t status;
apalmieri 95:e1f7ce04e71b 464
apalmieri 95:e1f7ce04e71b 465 Osal_MemSet(&adv_cp, 0, sizeof(adv_cp));
apalmieri 95:e1f7ce04e71b 466 adv_cp.min_interval = min_interval;
apalmieri 95:e1f7ce04e71b 467 adv_cp.max_interval = max_interval;
apalmieri 95:e1f7ce04e71b 468 adv_cp.advtype = advtype;
apalmieri 95:e1f7ce04e71b 469 adv_cp.own_bdaddr_type = own_bdaddr_type;
apalmieri 95:e1f7ce04e71b 470 adv_cp.direct_bdaddr_type = direct_bdaddr_type;
apalmieri 95:e1f7ce04e71b 471 Osal_MemCpy(adv_cp.direct_bdaddr,direct_bdaddr,sizeof(adv_cp.direct_bdaddr));
apalmieri 95:e1f7ce04e71b 472 adv_cp.chan_map = chan_map;
apalmieri 95:e1f7ce04e71b 473 adv_cp.filter = filter;
apalmieri 95:e1f7ce04e71b 474
apalmieri 95:e1f7ce04e71b 475 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 476 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 477 rq.ocf = OCF_LE_SET_ADV_PARAMETERS;
apalmieri 95:e1f7ce04e71b 478 rq.cparam = &adv_cp;
apalmieri 95:e1f7ce04e71b 479 rq.clen = LE_SET_ADV_PARAMETERS_CP_SIZE;
apalmieri 95:e1f7ce04e71b 480 rq.rparam = &status;
apalmieri 95:e1f7ce04e71b 481 rq.rlen = 1;
apalmieri 95:e1f7ce04e71b 482
apalmieri 95:e1f7ce04e71b 483 if (hci_send_req(&rq, FALSE) < 0)
apalmieri 95:e1f7ce04e71b 484 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 485
apalmieri 95:e1f7ce04e71b 486 return status;
Wolfgang Betz 90:26c0c9807ab4 487 }
Wolfgang Betz 90:26c0c9807ab4 488
Wolfgang Betz 90:26c0c9807ab4 489 int hci_le_set_advertising_data(uint8_t length, const uint8_t data[])
Wolfgang Betz 90:26c0c9807ab4 490 {
apalmieri 95:e1f7ce04e71b 491 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 492 le_set_adv_data_cp adv_cp;
apalmieri 95:e1f7ce04e71b 493 uint8_t status;
apalmieri 95:e1f7ce04e71b 494
apalmieri 95:e1f7ce04e71b 495 Osal_MemSet(&adv_cp, 0, sizeof(adv_cp));
apalmieri 95:e1f7ce04e71b 496 adv_cp.length = length;
apalmieri 95:e1f7ce04e71b 497 Osal_MemCpy(adv_cp.data, data, MIN(31,length));
apalmieri 95:e1f7ce04e71b 498
apalmieri 95:e1f7ce04e71b 499 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 500 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 501 rq.ocf = OCF_LE_SET_ADV_DATA;
apalmieri 95:e1f7ce04e71b 502 rq.cparam = &adv_cp;
apalmieri 95:e1f7ce04e71b 503 rq.clen = LE_SET_ADV_DATA_CP_SIZE;
apalmieri 95:e1f7ce04e71b 504 rq.rparam = &status;
apalmieri 95:e1f7ce04e71b 505 rq.rlen = 1;
apalmieri 95:e1f7ce04e71b 506
apalmieri 95:e1f7ce04e71b 507 if (hci_send_req(&rq, FALSE) < 0)
apalmieri 95:e1f7ce04e71b 508 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 509
apalmieri 95:e1f7ce04e71b 510 return status;
Wolfgang Betz 90:26c0c9807ab4 511 }
Wolfgang Betz 90:26c0c9807ab4 512
Wolfgang Betz 90:26c0c9807ab4 513 int hci_le_set_advertise_enable(uint8_t enable)
Wolfgang Betz 90:26c0c9807ab4 514 {
apalmieri 95:e1f7ce04e71b 515 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 516 le_set_advertise_enable_cp adv_cp;
apalmieri 95:e1f7ce04e71b 517 uint8_t status;
apalmieri 95:e1f7ce04e71b 518
apalmieri 95:e1f7ce04e71b 519 Osal_MemSet(&adv_cp, 0, sizeof(adv_cp));
apalmieri 95:e1f7ce04e71b 520 adv_cp.enable = enable?1:0;
apalmieri 95:e1f7ce04e71b 521
apalmieri 95:e1f7ce04e71b 522 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 523 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 524 rq.ocf = OCF_LE_SET_ADVERTISE_ENABLE;
apalmieri 95:e1f7ce04e71b 525 rq.cparam = &adv_cp;
apalmieri 95:e1f7ce04e71b 526 rq.clen = LE_SET_ADVERTISE_ENABLE_CP_SIZE;
apalmieri 95:e1f7ce04e71b 527 rq.rparam = &status;
apalmieri 95:e1f7ce04e71b 528 rq.rlen = 1;
apalmieri 95:e1f7ce04e71b 529
apalmieri 95:e1f7ce04e71b 530 if (hci_send_req(&rq, FALSE) < 0)
apalmieri 95:e1f7ce04e71b 531 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 532
apalmieri 95:e1f7ce04e71b 533 return status;
Wolfgang Betz 90:26c0c9807ab4 534 }
Wolfgang Betz 90:26c0c9807ab4 535
Wolfgang Betz 90:26c0c9807ab4 536 int hci_le_set_scan_parameters(uint8_t type, uint16_t interval,
Wolfgang Betz 90:26c0c9807ab4 537 uint16_t window, uint8_t own_bdaddr_type,
Wolfgang Betz 90:26c0c9807ab4 538 uint8_t filter)
Wolfgang Betz 90:26c0c9807ab4 539 {
apalmieri 95:e1f7ce04e71b 540 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 541 le_set_scan_parameters_cp scan_cp;
apalmieri 95:e1f7ce04e71b 542 uint8_t status;
apalmieri 95:e1f7ce04e71b 543
apalmieri 95:e1f7ce04e71b 544 Osal_MemSet(&scan_cp, 0, sizeof(scan_cp));
apalmieri 95:e1f7ce04e71b 545 scan_cp.type = type;
apalmieri 95:e1f7ce04e71b 546 scan_cp.interval = interval;
apalmieri 95:e1f7ce04e71b 547 scan_cp.window = window;
apalmieri 95:e1f7ce04e71b 548 scan_cp.own_bdaddr_type = own_bdaddr_type;
apalmieri 95:e1f7ce04e71b 549 scan_cp.filter = filter;
apalmieri 95:e1f7ce04e71b 550
apalmieri 95:e1f7ce04e71b 551 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 552 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 553 rq.ocf = OCF_LE_SET_SCAN_PARAMETERS;
apalmieri 95:e1f7ce04e71b 554 rq.cparam = &scan_cp;
apalmieri 95:e1f7ce04e71b 555 rq.clen = LE_SET_SCAN_PARAMETERS_CP_SIZE;
apalmieri 95:e1f7ce04e71b 556 rq.rparam = &status;
apalmieri 95:e1f7ce04e71b 557 rq.rlen = 1;
apalmieri 95:e1f7ce04e71b 558
apalmieri 95:e1f7ce04e71b 559 if (hci_send_req(&rq, FALSE) < 0)
apalmieri 95:e1f7ce04e71b 560 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 561
apalmieri 95:e1f7ce04e71b 562 return status;
Wolfgang Betz 90:26c0c9807ab4 563 }
Wolfgang Betz 90:26c0c9807ab4 564
Wolfgang Betz 90:26c0c9807ab4 565 int hci_le_set_scan_enable(uint8_t enable, uint8_t filter_dup)
Wolfgang Betz 90:26c0c9807ab4 566 {
apalmieri 95:e1f7ce04e71b 567 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 568 le_set_scan_enable_cp scan_cp;
apalmieri 95:e1f7ce04e71b 569 uint8_t status;
apalmieri 95:e1f7ce04e71b 570
apalmieri 95:e1f7ce04e71b 571 Osal_MemSet(&scan_cp, 0, sizeof(scan_cp));
apalmieri 95:e1f7ce04e71b 572 scan_cp.enable = enable?1:0;
apalmieri 95:e1f7ce04e71b 573 scan_cp.filter_dup = filter_dup;
apalmieri 95:e1f7ce04e71b 574
apalmieri 95:e1f7ce04e71b 575 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 576 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 577 rq.ocf = OCF_LE_SET_SCAN_ENABLE;
apalmieri 95:e1f7ce04e71b 578 rq.cparam = &scan_cp;
apalmieri 95:e1f7ce04e71b 579 rq.clen = LE_SET_SCAN_ENABLE_CP_SIZE;
apalmieri 95:e1f7ce04e71b 580 rq.rparam = &status;
apalmieri 95:e1f7ce04e71b 581 rq.rlen = 1;
apalmieri 95:e1f7ce04e71b 582
apalmieri 95:e1f7ce04e71b 583 if (hci_send_req(&rq, FALSE) < 0)
apalmieri 95:e1f7ce04e71b 584 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 585
apalmieri 95:e1f7ce04e71b 586 return status;
Wolfgang Betz 90:26c0c9807ab4 587 }
Wolfgang Betz 90:26c0c9807ab4 588
Wolfgang Betz 90:26c0c9807ab4 589 int hci_le_rand(uint8_t random_number[8])
Wolfgang Betz 90:26c0c9807ab4 590 {
apalmieri 95:e1f7ce04e71b 591 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 592 le_rand_rp resp;
apalmieri 95:e1f7ce04e71b 593
apalmieri 95:e1f7ce04e71b 594 Osal_MemSet(&resp, 0, sizeof(resp));
apalmieri 95:e1f7ce04e71b 595
apalmieri 95:e1f7ce04e71b 596 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 597 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 598 rq.ocf = OCF_LE_RAND;
apalmieri 95:e1f7ce04e71b 599 rq.cparam = NULL;
apalmieri 95:e1f7ce04e71b 600 rq.clen = 0;
apalmieri 95:e1f7ce04e71b 601 rq.rparam = &resp;
apalmieri 95:e1f7ce04e71b 602 rq.rlen = LE_RAND_RP_SIZE;
apalmieri 95:e1f7ce04e71b 603
apalmieri 95:e1f7ce04e71b 604 if (hci_send_req(&rq, FALSE) < 0)
apalmieri 95:e1f7ce04e71b 605 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 606
apalmieri 95:e1f7ce04e71b 607 if (resp.status) {
apalmieri 95:e1f7ce04e71b 608 return resp.status;
apalmieri 95:e1f7ce04e71b 609 }
apalmieri 95:e1f7ce04e71b 610
apalmieri 95:e1f7ce04e71b 611 Osal_MemCpy(random_number, resp.random, 8);
apalmieri 95:e1f7ce04e71b 612
apalmieri 95:e1f7ce04e71b 613 return 0;
Wolfgang Betz 90:26c0c9807ab4 614 }
Wolfgang Betz 90:26c0c9807ab4 615
Wolfgang Betz 90:26c0c9807ab4 616 int hci_le_set_scan_resp_data(uint8_t length, const uint8_t data[])
Wolfgang Betz 90:26c0c9807ab4 617 {
apalmieri 95:e1f7ce04e71b 618 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 619 le_set_scan_response_data_cp scan_resp_cp;
apalmieri 95:e1f7ce04e71b 620 uint8_t status;
apalmieri 95:e1f7ce04e71b 621
apalmieri 95:e1f7ce04e71b 622 Osal_MemSet(&scan_resp_cp, 0, sizeof(scan_resp_cp));
apalmieri 95:e1f7ce04e71b 623 scan_resp_cp.length = length;
apalmieri 95:e1f7ce04e71b 624 Osal_MemCpy(scan_resp_cp.data, data, MIN(31,length));
apalmieri 95:e1f7ce04e71b 625
apalmieri 95:e1f7ce04e71b 626 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 627 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 628 rq.ocf = OCF_LE_SET_SCAN_RESPONSE_DATA;
apalmieri 95:e1f7ce04e71b 629 rq.cparam = &scan_resp_cp;
apalmieri 95:e1f7ce04e71b 630 rq.clen = LE_SET_SCAN_RESPONSE_DATA_CP_SIZE;
apalmieri 95:e1f7ce04e71b 631 rq.rparam = &status;
apalmieri 95:e1f7ce04e71b 632 rq.rlen = 1;
apalmieri 95:e1f7ce04e71b 633
apalmieri 95:e1f7ce04e71b 634 if (hci_send_req(&rq, FALSE) < 0)
apalmieri 95:e1f7ce04e71b 635 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 636
apalmieri 95:e1f7ce04e71b 637 return status;
Wolfgang Betz 90:26c0c9807ab4 638 }
Wolfgang Betz 90:26c0c9807ab4 639
Wolfgang Betz 90:26c0c9807ab4 640 int hci_le_read_advertising_channel_tx_power(int8_t *tx_power_level)
Wolfgang Betz 90:26c0c9807ab4 641 {
apalmieri 95:e1f7ce04e71b 642 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 643 le_read_adv_channel_tx_power_rp resp;
apalmieri 95:e1f7ce04e71b 644
apalmieri 95:e1f7ce04e71b 645 Osal_MemSet(&resp, 0, sizeof(resp));
apalmieri 95:e1f7ce04e71b 646
apalmieri 95:e1f7ce04e71b 647 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 648 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 649 rq.ocf = OCF_LE_READ_ADV_CHANNEL_TX_POWER;
apalmieri 95:e1f7ce04e71b 650 rq.cparam = NULL;
apalmieri 95:e1f7ce04e71b 651 rq.clen = 0;
apalmieri 95:e1f7ce04e71b 652 rq.rparam = &resp;
apalmieri 95:e1f7ce04e71b 653 rq.rlen = LE_RAND_RP_SIZE;
apalmieri 95:e1f7ce04e71b 654
apalmieri 95:e1f7ce04e71b 655 if (hci_send_req(&rq, FALSE) < 0)
apalmieri 95:e1f7ce04e71b 656 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 657
apalmieri 95:e1f7ce04e71b 658 if (resp.status) {
apalmieri 95:e1f7ce04e71b 659 return resp.status;
apalmieri 95:e1f7ce04e71b 660 }
apalmieri 95:e1f7ce04e71b 661
apalmieri 95:e1f7ce04e71b 662 *tx_power_level = resp.level;
apalmieri 95:e1f7ce04e71b 663
apalmieri 95:e1f7ce04e71b 664 return 0;
Wolfgang Betz 90:26c0c9807ab4 665 }
Wolfgang Betz 90:26c0c9807ab4 666
Wolfgang Betz 90:26c0c9807ab4 667 int hci_le_set_random_address(tBDAddr bdaddr)
Wolfgang Betz 90:26c0c9807ab4 668 {
apalmieri 95:e1f7ce04e71b 669 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 670 le_set_random_address_cp set_rand_addr_cp;
apalmieri 95:e1f7ce04e71b 671 uint8_t status;
apalmieri 95:e1f7ce04e71b 672
apalmieri 95:e1f7ce04e71b 673 Osal_MemSet(&set_rand_addr_cp, 0, sizeof(set_rand_addr_cp));
apalmieri 95:e1f7ce04e71b 674 Osal_MemCpy(set_rand_addr_cp.bdaddr, bdaddr, sizeof(tBDAddr));
apalmieri 95:e1f7ce04e71b 675
apalmieri 95:e1f7ce04e71b 676 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 677 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 678 rq.ocf = OCF_LE_SET_RANDOM_ADDRESS;
apalmieri 95:e1f7ce04e71b 679 rq.cparam = &set_rand_addr_cp;
apalmieri 95:e1f7ce04e71b 680 rq.clen = LE_SET_RANDOM_ADDRESS_CP_SIZE;
apalmieri 95:e1f7ce04e71b 681 rq.rparam = &status;
apalmieri 95:e1f7ce04e71b 682 rq.rlen = 1;
apalmieri 95:e1f7ce04e71b 683
apalmieri 95:e1f7ce04e71b 684 if (hci_send_req(&rq, FALSE) < 0)
apalmieri 95:e1f7ce04e71b 685 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 686
apalmieri 95:e1f7ce04e71b 687 return status;
Wolfgang Betz 90:26c0c9807ab4 688 }
Wolfgang Betz 90:26c0c9807ab4 689
Wolfgang Betz 90:26c0c9807ab4 690 int hci_read_bd_addr(tBDAddr bdaddr)
Wolfgang Betz 90:26c0c9807ab4 691 {
apalmieri 95:e1f7ce04e71b 692 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 693 read_bd_addr_rp resp;
apalmieri 95:e1f7ce04e71b 694
apalmieri 95:e1f7ce04e71b 695 Osal_MemSet(&resp, 0, sizeof(resp));
apalmieri 95:e1f7ce04e71b 696
apalmieri 95:e1f7ce04e71b 697 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 698 rq.ogf = OGF_INFO_PARAM;
apalmieri 95:e1f7ce04e71b 699 rq.ocf = OCF_READ_BD_ADDR;
apalmieri 95:e1f7ce04e71b 700 rq.cparam = NULL;
apalmieri 95:e1f7ce04e71b 701 rq.clen = 0;
apalmieri 95:e1f7ce04e71b 702 rq.rparam = &resp;
apalmieri 95:e1f7ce04e71b 703 rq.rlen = READ_BD_ADDR_RP_SIZE;
apalmieri 95:e1f7ce04e71b 704
apalmieri 95:e1f7ce04e71b 705 if (hci_send_req(&rq, FALSE) < 0)
apalmieri 95:e1f7ce04e71b 706 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 707
apalmieri 95:e1f7ce04e71b 708 if (resp.status) {
apalmieri 95:e1f7ce04e71b 709 return resp.status;
apalmieri 95:e1f7ce04e71b 710 }
apalmieri 95:e1f7ce04e71b 711 Osal_MemCpy(bdaddr, resp.bdaddr, sizeof(tBDAddr));
apalmieri 95:e1f7ce04e71b 712
apalmieri 95:e1f7ce04e71b 713 return 0;
Wolfgang Betz 90:26c0c9807ab4 714 }
Wolfgang Betz 90:26c0c9807ab4 715
Wolfgang Betz 90:26c0c9807ab4 716 int hci_le_create_connection(uint16_t interval, uint16_t window, uint8_t initiator_filter, uint8_t peer_bdaddr_type,
Wolfgang Betz 90:26c0c9807ab4 717 const tBDAddr peer_bdaddr, uint8_t own_bdaddr_type, uint16_t min_interval, uint16_t max_interval,
Wolfgang Betz 90:26c0c9807ab4 718 uint16_t latency, uint16_t supervision_timeout, uint16_t min_ce_length, uint16_t max_ce_length)
Wolfgang Betz 90:26c0c9807ab4 719 {
apalmieri 95:e1f7ce04e71b 720 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 721 le_create_connection_cp create_cp;
apalmieri 95:e1f7ce04e71b 722 uint8_t status;
apalmieri 95:e1f7ce04e71b 723
apalmieri 95:e1f7ce04e71b 724 Osal_MemSet(&create_cp, 0, sizeof(create_cp));
apalmieri 95:e1f7ce04e71b 725 create_cp.interval = interval;
apalmieri 95:e1f7ce04e71b 726 create_cp.window = window;
apalmieri 95:e1f7ce04e71b 727 create_cp.initiator_filter = initiator_filter;
apalmieri 95:e1f7ce04e71b 728 create_cp.peer_bdaddr_type = peer_bdaddr_type;
apalmieri 95:e1f7ce04e71b 729 Osal_MemCpy(create_cp.peer_bdaddr, peer_bdaddr, sizeof(tBDAddr));
apalmieri 95:e1f7ce04e71b 730 create_cp.own_bdaddr_type = own_bdaddr_type;
apalmieri 95:e1f7ce04e71b 731 create_cp.min_interval=min_interval;
apalmieri 95:e1f7ce04e71b 732 create_cp.max_interval=max_interval;
apalmieri 95:e1f7ce04e71b 733 create_cp.latency = latency;
apalmieri 95:e1f7ce04e71b 734 create_cp.supervision_timeout=supervision_timeout;
apalmieri 95:e1f7ce04e71b 735 create_cp.min_ce_length=min_ce_length;
apalmieri 95:e1f7ce04e71b 736 create_cp.max_ce_length=max_ce_length;
apalmieri 95:e1f7ce04e71b 737
apalmieri 95:e1f7ce04e71b 738 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 739 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 740 rq.ocf = OCF_LE_CREATE_CONN;
apalmieri 95:e1f7ce04e71b 741 rq.cparam = &create_cp;
apalmieri 95:e1f7ce04e71b 742 rq.clen = LE_CREATE_CONN_CP_SIZE;
apalmieri 95:e1f7ce04e71b 743 rq.event = EVT_CMD_STATUS;
apalmieri 95:e1f7ce04e71b 744 rq.rparam = &status;
apalmieri 95:e1f7ce04e71b 745 rq.rlen = 1;
apalmieri 95:e1f7ce04e71b 746
apalmieri 95:e1f7ce04e71b 747 if (hci_send_req(&rq, FALSE) < 0)
apalmieri 95:e1f7ce04e71b 748 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 749
apalmieri 95:e1f7ce04e71b 750 return status;
Wolfgang Betz 90:26c0c9807ab4 751 }
Wolfgang Betz 90:26c0c9807ab4 752
Wolfgang Betz 90:26c0c9807ab4 753 int hci_le_encrypt(uint8_t key[16], uint8_t plaintextData[16], uint8_t encryptedData[16])
Wolfgang Betz 90:26c0c9807ab4 754 {
apalmieri 95:e1f7ce04e71b 755 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 756 le_encrypt_cp params;
apalmieri 95:e1f7ce04e71b 757 le_encrypt_rp resp;
apalmieri 95:e1f7ce04e71b 758
apalmieri 95:e1f7ce04e71b 759 Osal_MemSet(&resp, 0, sizeof(resp));
apalmieri 95:e1f7ce04e71b 760
apalmieri 95:e1f7ce04e71b 761 Osal_MemCpy(params.key, key, 16);
apalmieri 95:e1f7ce04e71b 762 Osal_MemCpy(params.plaintext, plaintextData, 16);
apalmieri 95:e1f7ce04e71b 763
apalmieri 95:e1f7ce04e71b 764 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 765 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 766 rq.ocf = OCF_LE_ENCRYPT;
apalmieri 95:e1f7ce04e71b 767 rq.cparam = &params;
apalmieri 95:e1f7ce04e71b 768 rq.clen = LE_ENCRYPT_CP_SIZE;
apalmieri 95:e1f7ce04e71b 769 rq.rparam = &resp;
apalmieri 95:e1f7ce04e71b 770 rq.rlen = LE_ENCRYPT_RP_SIZE;
apalmieri 95:e1f7ce04e71b 771
apalmieri 95:e1f7ce04e71b 772 if (hci_send_req(&rq, FALSE) < 0){
apalmieri 95:e1f7ce04e71b 773 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 774 }
apalmieri 95:e1f7ce04e71b 775
apalmieri 95:e1f7ce04e71b 776 if (resp.status) {
apalmieri 95:e1f7ce04e71b 777 return resp.status;
apalmieri 95:e1f7ce04e71b 778 }
apalmieri 95:e1f7ce04e71b 779
apalmieri 95:e1f7ce04e71b 780 Osal_MemCpy(encryptedData, resp.encdata, 16);
apalmieri 95:e1f7ce04e71b 781
apalmieri 95:e1f7ce04e71b 782 return 0;
Wolfgang Betz 90:26c0c9807ab4 783 }
Wolfgang Betz 90:26c0c9807ab4 784
Wolfgang Betz 90:26c0c9807ab4 785 int hci_le_ltk_request_reply(uint8_t key[16])
Wolfgang Betz 90:26c0c9807ab4 786 {
apalmieri 95:e1f7ce04e71b 787 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 788 le_ltk_reply_cp params;
apalmieri 95:e1f7ce04e71b 789 le_ltk_reply_rp resp;
apalmieri 95:e1f7ce04e71b 790
apalmieri 95:e1f7ce04e71b 791 Osal_MemSet(&resp, 0, sizeof(resp));
apalmieri 95:e1f7ce04e71b 792
apalmieri 95:e1f7ce04e71b 793 params.handle = 1;
apalmieri 95:e1f7ce04e71b 794 Osal_MemCpy(params.key, key, 16);
apalmieri 95:e1f7ce04e71b 795
apalmieri 95:e1f7ce04e71b 796 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 797 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 798 rq.ocf = OCF_LE_LTK_REPLY;
apalmieri 95:e1f7ce04e71b 799 rq.cparam = &params;
apalmieri 95:e1f7ce04e71b 800 rq.clen = LE_LTK_REPLY_CP_SIZE;
apalmieri 95:e1f7ce04e71b 801 rq.rparam = &resp;
apalmieri 95:e1f7ce04e71b 802 rq.rlen = LE_LTK_REPLY_RP_SIZE;
apalmieri 95:e1f7ce04e71b 803
apalmieri 95:e1f7ce04e71b 804 if (hci_send_req(&rq, FALSE) < 0)
apalmieri 95:e1f7ce04e71b 805 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 806
apalmieri 95:e1f7ce04e71b 807 return resp.status;
Wolfgang Betz 90:26c0c9807ab4 808 }
Wolfgang Betz 90:26c0c9807ab4 809
Wolfgang Betz 90:26c0c9807ab4 810 int hci_le_ltk_request_neg_reply()
Wolfgang Betz 90:26c0c9807ab4 811 {
apalmieri 95:e1f7ce04e71b 812 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 813 le_ltk_neg_reply_cp params;
apalmieri 95:e1f7ce04e71b 814 le_ltk_neg_reply_rp resp;
apalmieri 95:e1f7ce04e71b 815
apalmieri 95:e1f7ce04e71b 816 Osal_MemSet(&resp, 0, sizeof(resp));
apalmieri 95:e1f7ce04e71b 817
apalmieri 95:e1f7ce04e71b 818 params.handle = 1;
apalmieri 95:e1f7ce04e71b 819
apalmieri 95:e1f7ce04e71b 820 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 821 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 822 rq.ocf = OCF_LE_LTK_NEG_REPLY;
apalmieri 95:e1f7ce04e71b 823 rq.cparam = &params;
apalmieri 95:e1f7ce04e71b 824 rq.clen = LE_LTK_NEG_REPLY_CP_SIZE;
apalmieri 95:e1f7ce04e71b 825 rq.rparam = &resp;
apalmieri 95:e1f7ce04e71b 826 rq.rlen = LE_LTK_NEG_REPLY_RP_SIZE;
apalmieri 95:e1f7ce04e71b 827
apalmieri 95:e1f7ce04e71b 828 if (hci_send_req(&rq, FALSE) < 0)
apalmieri 95:e1f7ce04e71b 829 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 830
apalmieri 95:e1f7ce04e71b 831 return resp.status;
Wolfgang Betz 90:26c0c9807ab4 832 }
Wolfgang Betz 90:26c0c9807ab4 833
Wolfgang Betz 90:26c0c9807ab4 834 int hci_le_read_white_list_size(uint8_t *size)
Wolfgang Betz 90:26c0c9807ab4 835 {
apalmieri 95:e1f7ce04e71b 836 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 837 le_read_white_list_size_rp resp;
apalmieri 95:e1f7ce04e71b 838
apalmieri 95:e1f7ce04e71b 839 Osal_MemSet(&resp, 0, sizeof(resp));
apalmieri 95:e1f7ce04e71b 840
apalmieri 95:e1f7ce04e71b 841 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 842 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 843 rq.ocf = OCF_LE_READ_WHITE_LIST_SIZE;
apalmieri 95:e1f7ce04e71b 844 rq.rparam = &resp;
apalmieri 95:e1f7ce04e71b 845 rq.rlen = LE_READ_WHITE_LIST_SIZE_RP_SIZE;
apalmieri 95:e1f7ce04e71b 846
apalmieri 95:e1f7ce04e71b 847 if (hci_send_req(&rq, FALSE) < 0){
apalmieri 95:e1f7ce04e71b 848 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 849 }
apalmieri 95:e1f7ce04e71b 850
apalmieri 95:e1f7ce04e71b 851 if (resp.status) {
apalmieri 95:e1f7ce04e71b 852 return resp.status;
apalmieri 95:e1f7ce04e71b 853 }
apalmieri 95:e1f7ce04e71b 854
apalmieri 95:e1f7ce04e71b 855 *size = resp.size;
apalmieri 95:e1f7ce04e71b 856
apalmieri 95:e1f7ce04e71b 857 return 0;
Wolfgang Betz 90:26c0c9807ab4 858 }
Wolfgang Betz 90:26c0c9807ab4 859
Wolfgang Betz 90:26c0c9807ab4 860 int hci_le_clear_white_list()
Wolfgang Betz 90:26c0c9807ab4 861 {
apalmieri 95:e1f7ce04e71b 862 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 863 uint8_t status;
apalmieri 95:e1f7ce04e71b 864
apalmieri 95:e1f7ce04e71b 865 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 866 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 867 rq.ocf = OCF_LE_CLEAR_WHITE_LIST;
apalmieri 95:e1f7ce04e71b 868 rq.rparam = &status;
apalmieri 95:e1f7ce04e71b 869 rq.rlen = 1;
apalmieri 95:e1f7ce04e71b 870
apalmieri 95:e1f7ce04e71b 871 if (hci_send_req(&rq, FALSE) < 0){
apalmieri 95:e1f7ce04e71b 872 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 873 }
apalmieri 95:e1f7ce04e71b 874
apalmieri 95:e1f7ce04e71b 875 return status;
Wolfgang Betz 90:26c0c9807ab4 876 }
Wolfgang Betz 90:26c0c9807ab4 877
Wolfgang Betz 90:26c0c9807ab4 878 int hci_le_add_device_to_white_list(uint8_t bdaddr_type, tBDAddr bdaddr)
Wolfgang Betz 90:26c0c9807ab4 879 {
apalmieri 95:e1f7ce04e71b 880 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 881 le_add_device_to_white_list_cp params;
apalmieri 95:e1f7ce04e71b 882 uint8_t status;
apalmieri 95:e1f7ce04e71b 883
apalmieri 95:e1f7ce04e71b 884 params.bdaddr_type = bdaddr_type;
apalmieri 95:e1f7ce04e71b 885 Osal_MemCpy(params.bdaddr, bdaddr, 6);
apalmieri 95:e1f7ce04e71b 886
apalmieri 95:e1f7ce04e71b 887 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 888 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 889 rq.ocf = OCF_LE_ADD_DEVICE_TO_WHITE_LIST;
apalmieri 95:e1f7ce04e71b 890 rq.cparam = &params;
apalmieri 95:e1f7ce04e71b 891 rq.clen = LE_ADD_DEVICE_TO_WHITE_LIST_CP_SIZE;
apalmieri 95:e1f7ce04e71b 892 rq.rparam = &status;
apalmieri 95:e1f7ce04e71b 893 rq.rlen = 1;
apalmieri 95:e1f7ce04e71b 894
apalmieri 95:e1f7ce04e71b 895 if (hci_send_req(&rq, FALSE) < 0){
apalmieri 95:e1f7ce04e71b 896 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 897 }
apalmieri 95:e1f7ce04e71b 898
apalmieri 95:e1f7ce04e71b 899 return status;
Wolfgang Betz 90:26c0c9807ab4 900 }
Wolfgang Betz 90:26c0c9807ab4 901
Wolfgang Betz 90:26c0c9807ab4 902 int hci_le_remove_device_from_white_list(uint8_t bdaddr_type, tBDAddr bdaddr)
Wolfgang Betz 90:26c0c9807ab4 903 {
apalmieri 95:e1f7ce04e71b 904 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 905 le_remove_device_from_white_list_cp params;
apalmieri 95:e1f7ce04e71b 906 uint8_t status;
apalmieri 95:e1f7ce04e71b 907
apalmieri 95:e1f7ce04e71b 908 params.bdaddr_type = bdaddr_type;
apalmieri 95:e1f7ce04e71b 909 Osal_MemCpy(params.bdaddr, bdaddr, 6);
apalmieri 95:e1f7ce04e71b 910
apalmieri 95:e1f7ce04e71b 911 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 912 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 913 rq.ocf = OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST;
apalmieri 95:e1f7ce04e71b 914 rq.cparam = &params;
apalmieri 95:e1f7ce04e71b 915 rq.clen = LE_REMOVE_DEVICE_FROM_WHITE_LIST_CP_SIZE;
apalmieri 95:e1f7ce04e71b 916 rq.rparam = &status;
apalmieri 95:e1f7ce04e71b 917 rq.rlen = 1;
apalmieri 95:e1f7ce04e71b 918
apalmieri 95:e1f7ce04e71b 919 if (hci_send_req(&rq, FALSE) < 0){
apalmieri 95:e1f7ce04e71b 920 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 921 }
apalmieri 95:e1f7ce04e71b 922
apalmieri 95:e1f7ce04e71b 923 return status;
Wolfgang Betz 90:26c0c9807ab4 924 }
Wolfgang Betz 90:26c0c9807ab4 925
Wolfgang Betz 90:26c0c9807ab4 926 int hci_read_transmit_power_level(uint16_t *conn_handle, uint8_t type, int8_t * tx_level)
Wolfgang Betz 90:26c0c9807ab4 927 {
apalmieri 95:e1f7ce04e71b 928 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 929 read_transmit_power_level_cp params;
apalmieri 95:e1f7ce04e71b 930 read_transmit_power_level_rp resp;
apalmieri 95:e1f7ce04e71b 931
apalmieri 95:e1f7ce04e71b 932 Osal_MemSet(&resp, 0, sizeof(resp));
apalmieri 95:e1f7ce04e71b 933
apalmieri 95:e1f7ce04e71b 934 params.handle = *conn_handle;
apalmieri 95:e1f7ce04e71b 935 params.type = type;
apalmieri 95:e1f7ce04e71b 936
apalmieri 95:e1f7ce04e71b 937 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 938 rq.ogf = OGF_HOST_CTL;
apalmieri 95:e1f7ce04e71b 939 rq.ocf = OCF_READ_TRANSMIT_POWER_LEVEL;
apalmieri 95:e1f7ce04e71b 940 rq.cparam = &params;
apalmieri 95:e1f7ce04e71b 941 rq.clen = READ_TRANSMIT_POWER_LEVEL_CP_SIZE;
apalmieri 95:e1f7ce04e71b 942 rq.rparam = &resp;
apalmieri 95:e1f7ce04e71b 943 rq.rlen = READ_TRANSMIT_POWER_LEVEL_RP_SIZE;
apalmieri 95:e1f7ce04e71b 944
apalmieri 95:e1f7ce04e71b 945 if (hci_send_req(&rq, FALSE) < 0){
apalmieri 95:e1f7ce04e71b 946 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 947 }
apalmieri 95:e1f7ce04e71b 948
apalmieri 95:e1f7ce04e71b 949 if (resp.status) {
apalmieri 95:e1f7ce04e71b 950 return resp.status;
apalmieri 95:e1f7ce04e71b 951 }
apalmieri 95:e1f7ce04e71b 952
apalmieri 95:e1f7ce04e71b 953 *conn_handle = resp.handle;
apalmieri 95:e1f7ce04e71b 954 *tx_level = resp.level;
apalmieri 95:e1f7ce04e71b 955
apalmieri 95:e1f7ce04e71b 956 return 0;
Wolfgang Betz 90:26c0c9807ab4 957 }
Wolfgang Betz 90:26c0c9807ab4 958
Wolfgang Betz 90:26c0c9807ab4 959 int hci_read_rssi(uint16_t *conn_handle, int8_t * rssi)
Wolfgang Betz 90:26c0c9807ab4 960 {
apalmieri 95:e1f7ce04e71b 961 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 962 read_rssi_cp params;
apalmieri 95:e1f7ce04e71b 963 read_rssi_rp resp;
apalmieri 95:e1f7ce04e71b 964
apalmieri 95:e1f7ce04e71b 965 Osal_MemSet(&resp, 0, sizeof(resp));
apalmieri 95:e1f7ce04e71b 966
apalmieri 95:e1f7ce04e71b 967 params.handle = *conn_handle;
apalmieri 95:e1f7ce04e71b 968
apalmieri 95:e1f7ce04e71b 969 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 970 rq.ogf = OGF_STATUS_PARAM;
apalmieri 95:e1f7ce04e71b 971 rq.ocf = OCF_READ_RSSI;
apalmieri 95:e1f7ce04e71b 972 rq.cparam = &params;
apalmieri 95:e1f7ce04e71b 973 rq.clen = READ_RSSI_CP_SIZE;
apalmieri 95:e1f7ce04e71b 974 rq.rparam = &resp;
apalmieri 95:e1f7ce04e71b 975 rq.rlen = READ_RSSI_RP_SIZE;
apalmieri 95:e1f7ce04e71b 976
apalmieri 95:e1f7ce04e71b 977 if (hci_send_req(&rq, FALSE) < 0){
apalmieri 95:e1f7ce04e71b 978 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 979 }
apalmieri 95:e1f7ce04e71b 980
apalmieri 95:e1f7ce04e71b 981 if (resp.status) {
apalmieri 95:e1f7ce04e71b 982 return resp.status;
apalmieri 95:e1f7ce04e71b 983 }
apalmieri 95:e1f7ce04e71b 984
apalmieri 95:e1f7ce04e71b 985 *conn_handle = resp.handle;
apalmieri 95:e1f7ce04e71b 986 *rssi = resp.rssi;
apalmieri 95:e1f7ce04e71b 987
apalmieri 95:e1f7ce04e71b 988 return 0;
Wolfgang Betz 90:26c0c9807ab4 989 }
Wolfgang Betz 90:26c0c9807ab4 990
Wolfgang Betz 90:26c0c9807ab4 991 int hci_le_read_local_supported_features(uint8_t *features)
Wolfgang Betz 90:26c0c9807ab4 992 {
apalmieri 95:e1f7ce04e71b 993 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 994 le_read_local_supported_features_rp resp;
apalmieri 95:e1f7ce04e71b 995
apalmieri 95:e1f7ce04e71b 996 Osal_MemSet(&resp, 0, sizeof(resp));
apalmieri 95:e1f7ce04e71b 997
apalmieri 95:e1f7ce04e71b 998 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 999 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 1000 rq.ocf = OCF_LE_READ_LOCAL_SUPPORTED_FEATURES;
apalmieri 95:e1f7ce04e71b 1001 rq.rparam = &resp;
apalmieri 95:e1f7ce04e71b 1002 rq.rlen = LE_READ_LOCAL_SUPPORTED_FEATURES_RP_SIZE;
apalmieri 95:e1f7ce04e71b 1003
apalmieri 95:e1f7ce04e71b 1004 if (hci_send_req(&rq, FALSE) < 0){
apalmieri 95:e1f7ce04e71b 1005 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 1006 }
apalmieri 95:e1f7ce04e71b 1007
apalmieri 95:e1f7ce04e71b 1008 if (resp.status) {
apalmieri 95:e1f7ce04e71b 1009 return resp.status;
apalmieri 95:e1f7ce04e71b 1010 }
apalmieri 95:e1f7ce04e71b 1011
apalmieri 95:e1f7ce04e71b 1012 Osal_MemCpy(features, resp.features, sizeof(resp.features));
apalmieri 95:e1f7ce04e71b 1013
apalmieri 95:e1f7ce04e71b 1014 return 0;
Wolfgang Betz 90:26c0c9807ab4 1015 }
Wolfgang Betz 90:26c0c9807ab4 1016
Wolfgang Betz 90:26c0c9807ab4 1017 int hci_le_read_channel_map(uint16_t conn_handle, uint8_t ch_map[5])
Wolfgang Betz 90:26c0c9807ab4 1018 {
apalmieri 95:e1f7ce04e71b 1019 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 1020 le_read_channel_map_cp params;
apalmieri 95:e1f7ce04e71b 1021 le_read_channel_map_rp resp;
apalmieri 95:e1f7ce04e71b 1022
apalmieri 95:e1f7ce04e71b 1023 Osal_MemSet(&resp, 0, sizeof(resp));
apalmieri 95:e1f7ce04e71b 1024
apalmieri 95:e1f7ce04e71b 1025 params.handle = conn_handle;
apalmieri 95:e1f7ce04e71b 1026
apalmieri 95:e1f7ce04e71b 1027 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 1028 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 1029 rq.ocf = OCF_LE_READ_CHANNEL_MAP;
apalmieri 95:e1f7ce04e71b 1030 rq.cparam = &params;
apalmieri 95:e1f7ce04e71b 1031 rq.clen = LE_READ_CHANNEL_MAP_CP_SIZE;
apalmieri 95:e1f7ce04e71b 1032 rq.rparam = &resp;
apalmieri 95:e1f7ce04e71b 1033 rq.rlen = LE_READ_CHANNEL_MAP_RP_SIZE;
apalmieri 95:e1f7ce04e71b 1034
apalmieri 95:e1f7ce04e71b 1035 if (hci_send_req(&rq, FALSE) < 0){
apalmieri 95:e1f7ce04e71b 1036 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 1037 }
apalmieri 95:e1f7ce04e71b 1038
apalmieri 95:e1f7ce04e71b 1039 if (resp.status) {
apalmieri 95:e1f7ce04e71b 1040 return resp.status;
apalmieri 95:e1f7ce04e71b 1041 }
apalmieri 95:e1f7ce04e71b 1042
apalmieri 95:e1f7ce04e71b 1043 Osal_MemCpy(ch_map, resp.map, 5);
apalmieri 95:e1f7ce04e71b 1044
apalmieri 95:e1f7ce04e71b 1045 return 0;
Wolfgang Betz 90:26c0c9807ab4 1046 }
Wolfgang Betz 90:26c0c9807ab4 1047
Wolfgang Betz 90:26c0c9807ab4 1048 int hci_le_read_supported_states(uint8_t states[8])
Wolfgang Betz 90:26c0c9807ab4 1049 {
apalmieri 95:e1f7ce04e71b 1050 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 1051 le_read_supported_states_rp resp;
apalmieri 95:e1f7ce04e71b 1052
apalmieri 95:e1f7ce04e71b 1053 Osal_MemSet(&resp, 0, sizeof(resp));
apalmieri 95:e1f7ce04e71b 1054
apalmieri 95:e1f7ce04e71b 1055 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 1056 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 1057 rq.ocf = OCF_LE_READ_SUPPORTED_STATES;
apalmieri 95:e1f7ce04e71b 1058 rq.rparam = &resp;
apalmieri 95:e1f7ce04e71b 1059 rq.rlen = LE_READ_SUPPORTED_STATES_RP_SIZE;
apalmieri 95:e1f7ce04e71b 1060
apalmieri 95:e1f7ce04e71b 1061 if (hci_send_req(&rq, FALSE) < 0){
apalmieri 95:e1f7ce04e71b 1062 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 1063 }
apalmieri 95:e1f7ce04e71b 1064
apalmieri 95:e1f7ce04e71b 1065 if (resp.status) {
apalmieri 95:e1f7ce04e71b 1066 return resp.status;
apalmieri 95:e1f7ce04e71b 1067 }
apalmieri 95:e1f7ce04e71b 1068
apalmieri 95:e1f7ce04e71b 1069 Osal_MemCpy(states, resp.states, 8);
apalmieri 95:e1f7ce04e71b 1070
apalmieri 95:e1f7ce04e71b 1071 return 0;
Wolfgang Betz 90:26c0c9807ab4 1072 }
Wolfgang Betz 90:26c0c9807ab4 1073
Wolfgang Betz 90:26c0c9807ab4 1074 int hci_le_receiver_test(uint8_t frequency)
Wolfgang Betz 90:26c0c9807ab4 1075 {
apalmieri 95:e1f7ce04e71b 1076 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 1077 le_receiver_test_cp params;
apalmieri 95:e1f7ce04e71b 1078 uint8_t status;
apalmieri 95:e1f7ce04e71b 1079
apalmieri 95:e1f7ce04e71b 1080 params.frequency = frequency;
apalmieri 95:e1f7ce04e71b 1081
apalmieri 95:e1f7ce04e71b 1082 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 1083 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 1084 rq.ocf = OCF_LE_RECEIVER_TEST;
apalmieri 95:e1f7ce04e71b 1085 rq.cparam = &params;
apalmieri 95:e1f7ce04e71b 1086 rq.clen = LE_RECEIVER_TEST_CP_SIZE;
apalmieri 95:e1f7ce04e71b 1087 rq.rparam = &status;
apalmieri 95:e1f7ce04e71b 1088 rq.rlen = 1;
apalmieri 95:e1f7ce04e71b 1089
apalmieri 95:e1f7ce04e71b 1090 if (hci_send_req(&rq, FALSE) < 0){
apalmieri 95:e1f7ce04e71b 1091 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 1092 }
apalmieri 95:e1f7ce04e71b 1093
apalmieri 95:e1f7ce04e71b 1094 return status;
Wolfgang Betz 90:26c0c9807ab4 1095 }
Wolfgang Betz 90:26c0c9807ab4 1096
Wolfgang Betz 90:26c0c9807ab4 1097 int hci_le_transmitter_test(uint8_t frequency, uint8_t length, uint8_t payload)
Wolfgang Betz 90:26c0c9807ab4 1098 {
apalmieri 95:e1f7ce04e71b 1099 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 1100 le_transmitter_test_cp params;
apalmieri 95:e1f7ce04e71b 1101 uint8_t status;
apalmieri 95:e1f7ce04e71b 1102
apalmieri 95:e1f7ce04e71b 1103 params.frequency = frequency;
apalmieri 95:e1f7ce04e71b 1104 params.length = length;
apalmieri 95:e1f7ce04e71b 1105 params.payload = payload;
apalmieri 95:e1f7ce04e71b 1106
apalmieri 95:e1f7ce04e71b 1107 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 1108 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 1109 rq.ocf = OCF_LE_TRANSMITTER_TEST;
apalmieri 95:e1f7ce04e71b 1110 rq.cparam = &params;
apalmieri 95:e1f7ce04e71b 1111 rq.clen = LE_TRANSMITTER_TEST_CP_SIZE;
apalmieri 95:e1f7ce04e71b 1112 rq.rparam = &status;
apalmieri 95:e1f7ce04e71b 1113 rq.rlen = 1;
apalmieri 95:e1f7ce04e71b 1114
apalmieri 95:e1f7ce04e71b 1115 if (hci_send_req(&rq, FALSE) < 0){
apalmieri 95:e1f7ce04e71b 1116 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 1117 }
apalmieri 95:e1f7ce04e71b 1118
apalmieri 95:e1f7ce04e71b 1119 return status;
Wolfgang Betz 90:26c0c9807ab4 1120 }
Wolfgang Betz 90:26c0c9807ab4 1121
Wolfgang Betz 90:26c0c9807ab4 1122 int hci_le_test_end(uint16_t *num_pkts)
Wolfgang Betz 90:26c0c9807ab4 1123 {
apalmieri 95:e1f7ce04e71b 1124 struct hci_request rq;
apalmieri 95:e1f7ce04e71b 1125 le_test_end_rp resp;
apalmieri 95:e1f7ce04e71b 1126
apalmieri 95:e1f7ce04e71b 1127 Osal_MemSet(&resp, 0, sizeof(resp));
apalmieri 95:e1f7ce04e71b 1128
apalmieri 95:e1f7ce04e71b 1129 Osal_MemSet(&rq, 0, sizeof(rq));
apalmieri 95:e1f7ce04e71b 1130 rq.ogf = OGF_LE_CTL;
apalmieri 95:e1f7ce04e71b 1131 rq.ocf = OCF_LE_TEST_END;
apalmieri 95:e1f7ce04e71b 1132 rq.rparam = &resp;
apalmieri 95:e1f7ce04e71b 1133 rq.rlen = LE_TEST_END_RP_SIZE;
apalmieri 95:e1f7ce04e71b 1134
apalmieri 95:e1f7ce04e71b 1135 if (hci_send_req(&rq, FALSE) < 0){
apalmieri 95:e1f7ce04e71b 1136 return BLE_STATUS_TIMEOUT;
apalmieri 95:e1f7ce04e71b 1137 }
apalmieri 95:e1f7ce04e71b 1138
apalmieri 95:e1f7ce04e71b 1139 if (resp.status) {
apalmieri 95:e1f7ce04e71b 1140 return resp.status;
apalmieri 95:e1f7ce04e71b 1141 }
apalmieri 95:e1f7ce04e71b 1142
apalmieri 95:e1f7ce04e71b 1143 *num_pkts = resp.num_pkts;
apalmieri 95:e1f7ce04e71b 1144
apalmieri 95:e1f7ce04e71b 1145 return 0;
Wolfgang Betz 90:26c0c9807ab4 1146 }
Wolfgang Betz 90:26c0c9807ab4 1147