BLE UART example

Fork of Nucleo_BLE_BlueNRG by ST Americas mbed Team

Committer:
sjallouli
Date:
Sun Jan 03 16:05:38 2016 +0000
Revision:
3:104f1bba39ca
Parent:
0:a948f5f3904c
test

Who changed what in which revision?

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