HW layer for the Nucleo board, it only work with old BLE_API
Dependents: Hello_BLE F446RE-BLE
Fork of X_NUCLEO_IDB0XA1 by
BlueNRG_HCI/hci/hci.c@103:12684d94c3a6, 2015-07-27 (annotated)
- Committer:
- Wolfgang Betz
- Date:
- Mon Jul 27 11:39:32 2015 +0200
- Revision:
- 103:12684d94c3a6
- Parent:
- 102:a6f233cb1fed
- Child:
- 105:332f93cd06b7
Revert back to 520e8aa0afa103e88dd3c65caa8866f964b37cde
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Wolfgang Betz |
90:26c0c9807ab4 | 1 | /** |
Wolfgang Betz |
90:26c0c9807ab4 | 2 | ****************************************************************************** |
Wolfgang Betz |
103:12684d94c3a6 | 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>© COPYRIGHT 2013 STMicroelectronics</center></h2> |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 53 | hci_timeout = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 59 | uint8_t index; |
Wolfgang Betz |
103:12684d94c3a6 | 60 | |
Wolfgang Betz |
103:12684d94c3a6 | 61 | /* Initialize list heads of ready and free hci data packet queues */ |
Wolfgang Betz |
103:12684d94c3a6 | 62 | list_init_head (&hciReadPktPool); |
Wolfgang Betz |
103:12684d94c3a6 | 63 | list_init_head (&hciReadPktRxQueue); |
Wolfgang Betz |
103:12684d94c3a6 | 64 | |
Wolfgang Betz |
103:12684d94c3a6 | 65 | /* Initialize the queue of free hci data packets */ |
Wolfgang Betz |
103:12684d94c3a6 | 66 | for (index = 0; index < HCI_READ_PACKET_NUM_MAX; index++) |
Wolfgang Betz |
103:12684d94c3a6 | 67 | { |
Wolfgang Betz |
103:12684d94c3a6 | 68 | list_insert_tail(&hciReadPktPool, (tListNode *)&hciReadPacketBuffer[index]); |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 83 | const uint8_t *hci_pckt = hciReadPacket->dataBuff; |
Wolfgang Betz |
103:12684d94c3a6 | 84 | |
Wolfgang Betz |
103:12684d94c3a6 | 85 | if(hci_pckt[HCI_PCK_TYPE_OFFSET] != HCI_EVENT_PKT) |
Wolfgang Betz |
103:12684d94c3a6 | 86 | return 1; /* Incorrect type. */ |
Wolfgang Betz |
103:12684d94c3a6 | 87 | |
Wolfgang Betz |
103:12684d94c3a6 | 88 | if(hci_pckt[EVENT_PARAMETER_TOT_LEN_OFFSET] != hciReadPacket->data_len - (1+HCI_EVENT_HDR_SIZE)) |
Wolfgang Betz |
103:12684d94c3a6 | 89 | return 2; /* Wrong length (packet truncated or too long). */ |
Wolfgang Betz |
103:12684d94c3a6 | 90 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 96 | uint8_t data_len; |
Wolfgang Betz |
103:12684d94c3a6 | 97 | uint8_t buffer[HCI_READ_PACKET_SIZE]; |
Wolfgang Betz |
103:12684d94c3a6 | 98 | tHciDataPacket * hciReadPacket = NULL; |
Wolfgang Betz |
103:12684d94c3a6 | 99 | |
Wolfgang Betz |
90:26c0c9807ab4 | 100 | Disable_SPI_IRQ(); |
Wolfgang Betz |
103:12684d94c3a6 | 101 | uint8_t list_empty = list_is_empty(&hciReadPktRxQueue); |
Wolfgang Betz |
103:12684d94c3a6 | 102 | /* process any pending events read */ |
Wolfgang Betz |
103:12684d94c3a6 | 103 | while(list_empty == FALSE) |
Wolfgang Betz |
103:12684d94c3a6 | 104 | { |
Wolfgang Betz |
103:12684d94c3a6 | 105 | list_remove_head (&hciReadPktRxQueue, (tListNode **)&hciReadPacket); |
Wolfgang Betz |
103:12684d94c3a6 | 106 | Enable_SPI_IRQ(); |
Wolfgang Betz |
103:12684d94c3a6 | 107 | HCI_Event_CB(hciReadPacket->dataBuff); |
Wolfgang Betz |
103:12684d94c3a6 | 108 | Disable_SPI_IRQ(); |
Wolfgang Betz |
103:12684d94c3a6 | 109 | list_insert_tail(&hciReadPktPool, (tListNode *)hciReadPacket); |
Wolfgang Betz |
103:12684d94c3a6 | 110 | list_empty = list_is_empty(&hciReadPktRxQueue); |
Wolfgang Betz |
90:26c0c9807ab4 | 111 | } |
Wolfgang Betz |
103:12684d94c3a6 | 112 | if (readPacketListFull) { |
Wolfgang Betz |
103:12684d94c3a6 | 113 | while(BlueNRG_DataPresent()) { |
Wolfgang Betz |
103:12684d94c3a6 | 114 | data_len = BlueNRG_SPI_Read_All(buffer, HCI_READ_PACKET_SIZE); |
Wolfgang Betz |
103:12684d94c3a6 | 115 | if(data_len > 0) |
Wolfgang Betz |
103:12684d94c3a6 | 116 | HCI_Event_CB(buffer); |
Wolfgang Betz |
103:12684d94c3a6 | 117 | } |
Wolfgang Betz |
103:12684d94c3a6 | 118 | readPacketListFull = FALSE; |
Wolfgang Betz |
103:12684d94c3a6 | 119 | } |
Wolfgang Betz |
103:12684d94c3a6 | 120 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 131 | tHciDataPacket * hciReadPacket = NULL; |
Wolfgang Betz |
103:12684d94c3a6 | 132 | uint8_t data_len; |
Wolfgang Betz |
103:12684d94c3a6 | 133 | |
Wolfgang Betz |
103:12684d94c3a6 | 134 | Clear_SPI_EXTI_Flag(); |
Wolfgang Betz |
103:12684d94c3a6 | 135 | while(BlueNRG_DataPresent()){ |
Wolfgang Betz |
103:12684d94c3a6 | 136 | if (list_is_empty (&hciReadPktPool) == FALSE){ |
Wolfgang Betz |
103:12684d94c3a6 | 137 | |
Wolfgang Betz |
103:12684d94c3a6 | 138 | /* enqueueing a packet for read */ |
Wolfgang Betz |
103:12684d94c3a6 | 139 | list_remove_head (&hciReadPktPool, (tListNode **)&hciReadPacket); |
Wolfgang Betz |
103:12684d94c3a6 | 140 | |
Wolfgang Betz |
103:12684d94c3a6 | 141 | data_len = BlueNRG_SPI_Read_All(hciReadPacket->dataBuff, HCI_READ_PACKET_SIZE); |
Wolfgang Betz |
103:12684d94c3a6 | 142 | if(data_len > 0){ |
Wolfgang Betz |
103:12684d94c3a6 | 143 | hciReadPacket->data_len = data_len; |
Wolfgang Betz |
103:12684d94c3a6 | 144 | if(HCI_verify(hciReadPacket) == 0) |
Wolfgang Betz |
103:12684d94c3a6 | 145 | list_insert_tail(&hciReadPktRxQueue, (tListNode *)hciReadPacket); |
Wolfgang Betz |
103:12684d94c3a6 | 146 | else |
Wolfgang Betz |
103:12684d94c3a6 | 147 | list_insert_head(&hciReadPktPool, (tListNode *)hciReadPacket); |
Wolfgang Betz |
103:12684d94c3a6 | 148 | } |
Wolfgang Betz |
103:12684d94c3a6 | 149 | else { |
Wolfgang Betz |
103:12684d94c3a6 | 150 | // Insert the packet back into the pool. |
Wolfgang Betz |
103:12684d94c3a6 | 151 | list_insert_head(&hciReadPktPool, (tListNode *)hciReadPacket); |
Wolfgang Betz |
103:12684d94c3a6 | 152 | } |
Wolfgang Betz |
103:12684d94c3a6 | 153 | |
Wolfgang Betz |
103:12684d94c3a6 | 154 | } |
Wolfgang Betz |
103:12684d94c3a6 | 155 | else{ |
Wolfgang Betz |
103:12684d94c3a6 | 156 | // HCI Read Packet Pool is empty, wait for a free packet. |
Wolfgang Betz |
103:12684d94c3a6 | 157 | readPacketListFull = TRUE; |
Wolfgang Betz |
103:12684d94c3a6 | 158 | Clear_SPI_EXTI_Flag(); |
Wolfgang Betz |
103:12684d94c3a6 | 159 | return; |
Wolfgang Betz |
103:12684d94c3a6 | 160 | } |
Wolfgang Betz |
103:12684d94c3a6 | 161 | |
Wolfgang Betz |
103:12684d94c3a6 | 162 | Clear_SPI_EXTI_Flag(); |
Wolfgang Betz |
102:a6f233cb1fed | 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 |
Wolfgang Betz |
103:12684d94c3a6 | 168 | PRINTF("HCI <- "); |
Wolfgang Betz |
103:12684d94c3a6 | 169 | for(int i=0; i < n_bytes1; i++) |
Wolfgang Betz |
103:12684d94c3a6 | 170 | PRINTF("%02X ", *((uint8_t*)data1 + i)); |
Wolfgang Betz |
103:12684d94c3a6 | 171 | for(int i=0; i < n_bytes2; i++) |
Wolfgang Betz |
103:12684d94c3a6 | 172 | PRINTF("%02X ", *((uint8_t*)data2 + i)); |
Wolfgang Betz |
103:12684d94c3a6 | 173 | PRINTF("\n"); |
Wolfgang Betz |
90:26c0c9807ab4 | 174 | #endif |
Wolfgang Betz |
103:12684d94c3a6 | 175 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 181 | hci_command_hdr hc; |
Wolfgang Betz |
103:12684d94c3a6 | 182 | |
Wolfgang Betz |
103:12684d94c3a6 | 183 | hc.opcode = htobs(cmd_opcode_pack(ogf, ocf)); |
Wolfgang Betz |
103:12684d94c3a6 | 184 | hc.plen= plen; |
Wolfgang Betz |
103:12684d94c3a6 | 185 | |
Wolfgang Betz |
103:12684d94c3a6 | 186 | uint8_t header[HCI_HDR_SIZE + HCI_COMMAND_HDR_SIZE]; |
Wolfgang Betz |
103:12684d94c3a6 | 187 | header[0] = HCI_COMMAND_PKT; |
Wolfgang Betz |
103:12684d94c3a6 | 188 | Osal_MemCpy(header+1, &hc, sizeof(hc)); |
Wolfgang Betz |
103:12684d94c3a6 | 189 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 195 | pListNode tmp_node; |
Wolfgang Betz |
103:12684d94c3a6 | 196 | |
Wolfgang Betz |
103:12684d94c3a6 | 197 | while(!list_is_empty(src_list)){ |
Wolfgang Betz |
103:12684d94c3a6 | 198 | list_remove_head(src_list, &tmp_node); |
Wolfgang Betz |
103:12684d94c3a6 | 199 | list_insert_tail(dest_list, tmp_node); |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 205 | uint8_t *ptr; |
Wolfgang Betz |
103:12684d94c3a6 | 206 | uint16_t opcode = htobs(cmd_opcode_pack(r->ogf, r->ocf)); |
Wolfgang Betz |
103:12684d94c3a6 | 207 | hci_event_pckt *event_pckt; |
Wolfgang Betz |
103:12684d94c3a6 | 208 | hci_uart_pckt *hci_hdr; |
Wolfgang Betz |
103:12684d94c3a6 | 209 | int to = DEFAULT_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 210 | struct timer t; |
Wolfgang Betz |
103:12684d94c3a6 | 211 | tHciDataPacket * hciReadPacket = NULL; |
Wolfgang Betz |
103:12684d94c3a6 | 212 | tListNode hciTempQueue; |
Wolfgang Betz |
103:12684d94c3a6 | 213 | |
Wolfgang Betz |
103:12684d94c3a6 | 214 | list_init_head(&hciTempQueue); |
Wolfgang Betz |
103:12684d94c3a6 | 215 | |
Wolfgang Betz |
103:12684d94c3a6 | 216 | hci_send_cmd(r->ogf, r->ocf, r->clen, r->cparam); |
Wolfgang Betz |
103:12684d94c3a6 | 217 | |
Wolfgang Betz |
103:12684d94c3a6 | 218 | if(async){ |
Wolfgang Betz |
103:12684d94c3a6 | 219 | goto done; |
Wolfgang Betz |
103:12684d94c3a6 | 220 | } |
Wolfgang Betz |
103:12684d94c3a6 | 221 | |
Wolfgang Betz |
103:12684d94c3a6 | 222 | /* Minimum timeout is 1. */ |
Wolfgang Betz |
103:12684d94c3a6 | 223 | if(to == 0) |
Wolfgang Betz |
103:12684d94c3a6 | 224 | to = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 225 | |
Wolfgang Betz |
103:12684d94c3a6 | 226 | Timer_Set(&t, to); |
Wolfgang Betz |
103:12684d94c3a6 | 227 | |
Wolfgang Betz |
103:12684d94c3a6 | 228 | while(1) { |
Wolfgang Betz |
103:12684d94c3a6 | 229 | evt_cmd_complete *cc; |
Wolfgang Betz |
103:12684d94c3a6 | 230 | evt_cmd_status *cs; |
Wolfgang Betz |
103:12684d94c3a6 | 231 | evt_le_meta_event *me; |
Wolfgang Betz |
103:12684d94c3a6 | 232 | int len; |
Wolfgang Betz |
103:12684d94c3a6 | 233 | |
Wolfgang Betz |
102:a6f233cb1fed | 234 | #if ENABLE_MICRO_SLEEP |
Wolfgang Betz |
103:12684d94c3a6 | 235 | while(1){ |
Wolfgang Betz |
103:12684d94c3a6 | 236 | ATOMIC_SECTION_BEGIN(); |
Wolfgang Betz |
103:12684d94c3a6 | 237 | if(Timer_Expired(&t)){ |
Wolfgang Betz |
103:12684d94c3a6 | 238 | ATOMIC_SECTION_END(); |
Wolfgang Betz |
103:12684d94c3a6 | 239 | goto failed; |
Wolfgang Betz |
103:12684d94c3a6 | 240 | } |
Wolfgang Betz |
103:12684d94c3a6 | 241 | if(!HCI_Queue_Empty()){ |
Wolfgang Betz |
103:12684d94c3a6 | 242 | ATOMIC_SECTION_END(); |
Wolfgang Betz |
103:12684d94c3a6 | 243 | break; |
Wolfgang Betz |
103:12684d94c3a6 | 244 | } |
Wolfgang Betz |
103:12684d94c3a6 | 245 | Enter_Sleep_Mode(); |
Wolfgang Betz |
103:12684d94c3a6 | 246 | ATOMIC_SECTION_END(); |
Wolfgang Betz |
103:12684d94c3a6 | 247 | } |
Wolfgang Betz |
90:26c0c9807ab4 | 248 | #else |
Wolfgang Betz |
103:12684d94c3a6 | 249 | while(1){ |
Wolfgang Betz |
103:12684d94c3a6 | 250 | if(Timer_Expired(&t)){ |
Wolfgang Betz |
103:12684d94c3a6 | 251 | goto failed; |
Wolfgang Betz |
103:12684d94c3a6 | 252 | } |
Wolfgang Betz |
103:12684d94c3a6 | 253 | if(!HCI_Queue_Empty()){ |
Wolfgang Betz |
103:12684d94c3a6 | 254 | break; |
Wolfgang Betz |
103:12684d94c3a6 | 255 | } |
Wolfgang Betz |
103:12684d94c3a6 | 256 | } |
Wolfgang Betz |
90:26c0c9807ab4 | 257 | #endif |
Wolfgang Betz |
103:12684d94c3a6 | 258 | |
Wolfgang Betz |
103:12684d94c3a6 | 259 | /* Extract packet from HCI event queue. */ |
Wolfgang Betz |
103:12684d94c3a6 | 260 | Disable_SPI_IRQ(); |
Wolfgang Betz |
103:12684d94c3a6 | 261 | list_remove_head(&hciReadPktRxQueue, (tListNode **)&hciReadPacket); |
Wolfgang Betz |
103:12684d94c3a6 | 262 | |
Wolfgang Betz |
103:12684d94c3a6 | 263 | hci_hdr = (void *)hciReadPacket->dataBuff; |
Wolfgang Betz |
103:12684d94c3a6 | 264 | if(hci_hdr->type != HCI_EVENT_PKT){ |
Wolfgang Betz |
103:12684d94c3a6 | 265 | list_insert_tail(&hciTempQueue, (tListNode *)hciReadPacket); // See comment below |
Wolfgang Betz |
103:12684d94c3a6 | 266 | Enable_SPI_IRQ(); |
Wolfgang Betz |
103:12684d94c3a6 | 267 | continue; |
Wolfgang Betz |
90:26c0c9807ab4 | 268 | } |
Wolfgang Betz |
103:12684d94c3a6 | 269 | |
Wolfgang Betz |
103:12684d94c3a6 | 270 | event_pckt = (void *) (hci_hdr->data); |
Wolfgang Betz |
103:12684d94c3a6 | 271 | |
Wolfgang Betz |
103:12684d94c3a6 | 272 | ptr = hciReadPacket->dataBuff + (1 + HCI_EVENT_HDR_SIZE); |
Wolfgang Betz |
103:12684d94c3a6 | 273 | len = hciReadPacket->data_len - (1 + HCI_EVENT_HDR_SIZE); |
Wolfgang Betz |
103:12684d94c3a6 | 274 | |
Wolfgang Betz |
103:12684d94c3a6 | 275 | switch (event_pckt->evt) { |
Wolfgang Betz |
103:12684d94c3a6 | 276 | |
Wolfgang Betz |
103:12684d94c3a6 | 277 | case EVT_CMD_STATUS: |
Wolfgang Betz |
103:12684d94c3a6 | 278 | cs = (void *) ptr; |
Wolfgang Betz |
103:12684d94c3a6 | 279 | |
Wolfgang Betz |
103:12684d94c3a6 | 280 | if (cs->opcode != opcode) |
Wolfgang Betz |
103:12684d94c3a6 | 281 | goto failed; |
Wolfgang Betz |
103:12684d94c3a6 | 282 | |
Wolfgang Betz |
103:12684d94c3a6 | 283 | if (r->event != EVT_CMD_STATUS) { |
Wolfgang Betz |
103:12684d94c3a6 | 284 | if (cs->status) { |
Wolfgang Betz |
103:12684d94c3a6 | 285 | goto failed; |
Wolfgang Betz |
103:12684d94c3a6 | 286 | } |
Wolfgang Betz |
103:12684d94c3a6 | 287 | break; |
Wolfgang Betz |
103:12684d94c3a6 | 288 | } |
Wolfgang Betz |
103:12684d94c3a6 | 289 | |
Wolfgang Betz |
103:12684d94c3a6 | 290 | r->rlen = MIN(len, r->rlen); |
Wolfgang Betz |
103:12684d94c3a6 | 291 | Osal_MemCpy(r->rparam, ptr, r->rlen); |
Wolfgang Betz |
103:12684d94c3a6 | 292 | goto done; |
Wolfgang Betz |
103:12684d94c3a6 | 293 | |
Wolfgang Betz |
103:12684d94c3a6 | 294 | case EVT_CMD_COMPLETE: |
Wolfgang Betz |
103:12684d94c3a6 | 295 | cc = (void *) ptr; |
Wolfgang Betz |
103:12684d94c3a6 | 296 | |
Wolfgang Betz |
103:12684d94c3a6 | 297 | if (cc->opcode != opcode) |
Wolfgang Betz |
103:12684d94c3a6 | 298 | goto failed; |
Wolfgang Betz |
103:12684d94c3a6 | 299 | |
Wolfgang Betz |
103:12684d94c3a6 | 300 | ptr += EVT_CMD_COMPLETE_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 301 | len -= EVT_CMD_COMPLETE_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 302 | |
Wolfgang Betz |
103:12684d94c3a6 | 303 | r->rlen = MIN(len, r->rlen); |
Wolfgang Betz |
103:12684d94c3a6 | 304 | Osal_MemCpy(r->rparam, ptr, r->rlen); |
Wolfgang Betz |
103:12684d94c3a6 | 305 | goto done; |
Wolfgang Betz |
103:12684d94c3a6 | 306 | |
Wolfgang Betz |
103:12684d94c3a6 | 307 | case EVT_LE_META_EVENT: |
Wolfgang Betz |
103:12684d94c3a6 | 308 | me = (void *) ptr; |
Wolfgang Betz |
103:12684d94c3a6 | 309 | |
Wolfgang Betz |
103:12684d94c3a6 | 310 | if (me->subevent != r->event) |
Wolfgang Betz |
103:12684d94c3a6 | 311 | break; |
Wolfgang Betz |
103:12684d94c3a6 | 312 | |
Wolfgang Betz |
103:12684d94c3a6 | 313 | len -= 1; |
Wolfgang Betz |
103:12684d94c3a6 | 314 | r->rlen = MIN(len, r->rlen); |
Wolfgang Betz |
103:12684d94c3a6 | 315 | Osal_MemCpy(r->rparam, me->data, r->rlen); |
Wolfgang Betz |
103:12684d94c3a6 | 316 | goto done; |
Wolfgang Betz |
103:12684d94c3a6 | 317 | |
Wolfgang Betz |
103:12684d94c3a6 | 318 | case EVT_HARDWARE_ERROR: |
Wolfgang Betz |
103:12684d94c3a6 | 319 | goto failed; |
Wolfgang Betz |
103:12684d94c3a6 | 320 | |
Wolfgang Betz |
103:12684d94c3a6 | 321 | default: |
Wolfgang Betz |
103:12684d94c3a6 | 322 | break; |
Wolfgang Betz |
103:12684d94c3a6 | 323 | } |
Wolfgang Betz |
103:12684d94c3a6 | 324 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | */ |
Wolfgang Betz |
103:12684d94c3a6 | 329 | list_insert_tail(&hciTempQueue, (tListNode *)hciReadPacket); |
Wolfgang Betz |
103:12684d94c3a6 | 330 | /* Be sure there is at list one packet in the pool to process the expected event. */ |
Wolfgang Betz |
103:12684d94c3a6 | 331 | if(list_is_empty(&hciReadPktPool)){ |
Wolfgang Betz |
103:12684d94c3a6 | 332 | pListNode tmp_node; |
Wolfgang Betz |
103:12684d94c3a6 | 333 | list_remove_head(&hciReadPktRxQueue, &tmp_node); |
Wolfgang Betz |
103:12684d94c3a6 | 334 | list_insert_tail(&hciReadPktPool, tmp_node); |
Wolfgang Betz |
103:12684d94c3a6 | 335 | } |
Wolfgang Betz |
103:12684d94c3a6 | 336 | |
Wolfgang Betz |
103:12684d94c3a6 | 337 | Enable_SPI_IRQ(); |
Wolfgang Betz |
103:12684d94c3a6 | 338 | |
Wolfgang Betz |
90:26c0c9807ab4 | 339 | } |
Wolfgang Betz |
103:12684d94c3a6 | 340 | |
Wolfgang Betz |
103:12684d94c3a6 | 341 | failed: |
Wolfgang Betz |
103:12684d94c3a6 | 342 | move_list(&hciReadPktRxQueue, &hciTempQueue); |
Wolfgang Betz |
102:a6f233cb1fed | 343 | Enable_SPI_IRQ(); |
Wolfgang Betz |
103:12684d94c3a6 | 344 | return -1; |
Wolfgang Betz |
103:12684d94c3a6 | 345 | |
Wolfgang Betz |
90:26c0c9807ab4 | 346 | done: |
Wolfgang Betz |
103:12684d94c3a6 | 347 | // Insert the packet back into the pool. |
Wolfgang Betz |
103:12684d94c3a6 | 348 | list_insert_head(&hciReadPktPool, (tListNode *)hciReadPacket); |
Wolfgang Betz |
103:12684d94c3a6 | 349 | move_list(&hciReadPktRxQueue, &hciTempQueue); |
Wolfgang Betz |
103:12684d94c3a6 | 350 | |
Wolfgang Betz |
103:12684d94c3a6 | 351 | Enable_SPI_IRQ(); |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 357 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 358 | uint8_t status; |
Wolfgang Betz |
103:12684d94c3a6 | 359 | |
Wolfgang Betz |
103:12684d94c3a6 | 360 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 361 | rq.ogf = OGF_HOST_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 362 | rq.ocf = OCF_RESET; |
Wolfgang Betz |
103:12684d94c3a6 | 363 | rq.rparam = &status; |
Wolfgang Betz |
103:12684d94c3a6 | 364 | rq.rlen = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 365 | |
Wolfgang Betz |
103:12684d94c3a6 | 366 | if (hci_send_req(&rq, FALSE) < 0) |
Wolfgang Betz |
103:12684d94c3a6 | 367 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 368 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 374 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 375 | disconnect_cp cp; |
Wolfgang Betz |
103:12684d94c3a6 | 376 | uint8_t status; |
Wolfgang Betz |
103:12684d94c3a6 | 377 | |
Wolfgang Betz |
103:12684d94c3a6 | 378 | cp.handle = handle; |
Wolfgang Betz |
103:12684d94c3a6 | 379 | cp.reason = reason; |
Wolfgang Betz |
103:12684d94c3a6 | 380 | |
Wolfgang Betz |
103:12684d94c3a6 | 381 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 382 | rq.ogf = OGF_LINK_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 383 | rq.ocf = OCF_DISCONNECT; |
Wolfgang Betz |
103:12684d94c3a6 | 384 | rq.cparam = &cp; |
Wolfgang Betz |
103:12684d94c3a6 | 385 | rq.clen = DISCONNECT_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 386 | rq.event = EVT_CMD_STATUS; |
Wolfgang Betz |
103:12684d94c3a6 | 387 | rq.rparam = &status; |
Wolfgang Betz |
103:12684d94c3a6 | 388 | rq.rlen = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 389 | |
Wolfgang Betz |
103:12684d94c3a6 | 390 | if (hci_send_req(&rq, FALSE) < 0) |
Wolfgang Betz |
103:12684d94c3a6 | 391 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 392 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 399 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 400 | read_local_version_rp resp; |
Wolfgang Betz |
103:12684d94c3a6 | 401 | |
Wolfgang Betz |
103:12684d94c3a6 | 402 | Osal_MemSet(&resp, 0, sizeof(resp)); |
Wolfgang Betz |
103:12684d94c3a6 | 403 | |
Wolfgang Betz |
103:12684d94c3a6 | 404 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 405 | rq.ogf = OGF_INFO_PARAM; |
Wolfgang Betz |
103:12684d94c3a6 | 406 | rq.ocf = OCF_READ_LOCAL_VERSION; |
Wolfgang Betz |
103:12684d94c3a6 | 407 | rq.cparam = NULL; |
Wolfgang Betz |
103:12684d94c3a6 | 408 | rq.clen = 0; |
Wolfgang Betz |
103:12684d94c3a6 | 409 | rq.rparam = &resp; |
Wolfgang Betz |
103:12684d94c3a6 | 410 | rq.rlen = READ_LOCAL_VERSION_RP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 411 | |
Wolfgang Betz |
103:12684d94c3a6 | 412 | if (hci_send_req(&rq, FALSE) < 0) |
Wolfgang Betz |
103:12684d94c3a6 | 413 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 414 | |
Wolfgang Betz |
103:12684d94c3a6 | 415 | if (resp.status) { |
Wolfgang Betz |
103:12684d94c3a6 | 416 | return resp.status; |
Wolfgang Betz |
103:12684d94c3a6 | 417 | } |
Wolfgang Betz |
103:12684d94c3a6 | 418 | |
Wolfgang Betz |
103:12684d94c3a6 | 419 | |
Wolfgang Betz |
103:12684d94c3a6 | 420 | *hci_version = resp.hci_version; |
Wolfgang Betz |
103:12684d94c3a6 | 421 | *hci_revision = btohs(resp.hci_revision); |
Wolfgang Betz |
103:12684d94c3a6 | 422 | *lmp_pal_version = resp.lmp_pal_version; |
Wolfgang Betz |
103:12684d94c3a6 | 423 | *manufacturer_name = btohs(resp.manufacturer_name); |
Wolfgang Betz |
103:12684d94c3a6 | 424 | *lmp_pal_subversion = btohs(resp.lmp_pal_subversion); |
Wolfgang Betz |
103:12684d94c3a6 | 425 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 431 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 432 | le_read_buffer_size_rp resp; |
Wolfgang Betz |
103:12684d94c3a6 | 433 | |
Wolfgang Betz |
103:12684d94c3a6 | 434 | Osal_MemSet(&resp, 0, sizeof(resp)); |
Wolfgang Betz |
103:12684d94c3a6 | 435 | |
Wolfgang Betz |
103:12684d94c3a6 | 436 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 437 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 438 | rq.ocf = OCF_LE_READ_BUFFER_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 439 | rq.cparam = NULL; |
Wolfgang Betz |
103:12684d94c3a6 | 440 | rq.clen = 0; |
Wolfgang Betz |
103:12684d94c3a6 | 441 | rq.rparam = &resp; |
Wolfgang Betz |
103:12684d94c3a6 | 442 | rq.rlen = LE_READ_BUFFER_SIZE_RP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 443 | |
Wolfgang Betz |
103:12684d94c3a6 | 444 | if (hci_send_req(&rq, FALSE) < 0) |
Wolfgang Betz |
103:12684d94c3a6 | 445 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 446 | |
Wolfgang Betz |
103:12684d94c3a6 | 447 | if (resp.status) { |
Wolfgang Betz |
103:12684d94c3a6 | 448 | return resp.status; |
Wolfgang Betz |
103:12684d94c3a6 | 449 | } |
Wolfgang Betz |
103:12684d94c3a6 | 450 | |
Wolfgang Betz |
103:12684d94c3a6 | 451 | *pkt_len = resp.pkt_len; |
Wolfgang Betz |
103:12684d94c3a6 | 452 | *max_pkt = resp.max_pkt; |
Wolfgang Betz |
103:12684d94c3a6 | 453 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 461 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 462 | le_set_adv_parameters_cp adv_cp; |
Wolfgang Betz |
103:12684d94c3a6 | 463 | uint8_t status; |
Wolfgang Betz |
103:12684d94c3a6 | 464 | |
Wolfgang Betz |
103:12684d94c3a6 | 465 | Osal_MemSet(&adv_cp, 0, sizeof(adv_cp)); |
Wolfgang Betz |
103:12684d94c3a6 | 466 | adv_cp.min_interval = min_interval; |
Wolfgang Betz |
103:12684d94c3a6 | 467 | adv_cp.max_interval = max_interval; |
Wolfgang Betz |
103:12684d94c3a6 | 468 | adv_cp.advtype = advtype; |
Wolfgang Betz |
103:12684d94c3a6 | 469 | adv_cp.own_bdaddr_type = own_bdaddr_type; |
Wolfgang Betz |
103:12684d94c3a6 | 470 | adv_cp.direct_bdaddr_type = direct_bdaddr_type; |
Wolfgang Betz |
103:12684d94c3a6 | 471 | Osal_MemCpy(adv_cp.direct_bdaddr,direct_bdaddr,sizeof(adv_cp.direct_bdaddr)); |
Wolfgang Betz |
103:12684d94c3a6 | 472 | adv_cp.chan_map = chan_map; |
Wolfgang Betz |
103:12684d94c3a6 | 473 | adv_cp.filter = filter; |
Wolfgang Betz |
103:12684d94c3a6 | 474 | |
Wolfgang Betz |
103:12684d94c3a6 | 475 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 476 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 477 | rq.ocf = OCF_LE_SET_ADV_PARAMETERS; |
Wolfgang Betz |
103:12684d94c3a6 | 478 | rq.cparam = &adv_cp; |
Wolfgang Betz |
103:12684d94c3a6 | 479 | rq.clen = LE_SET_ADV_PARAMETERS_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 480 | rq.rparam = &status; |
Wolfgang Betz |
103:12684d94c3a6 | 481 | rq.rlen = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 482 | |
Wolfgang Betz |
103:12684d94c3a6 | 483 | if (hci_send_req(&rq, FALSE) < 0) |
Wolfgang Betz |
103:12684d94c3a6 | 484 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 485 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 491 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 492 | le_set_adv_data_cp adv_cp; |
Wolfgang Betz |
103:12684d94c3a6 | 493 | uint8_t status; |
Wolfgang Betz |
103:12684d94c3a6 | 494 | |
Wolfgang Betz |
103:12684d94c3a6 | 495 | Osal_MemSet(&adv_cp, 0, sizeof(adv_cp)); |
Wolfgang Betz |
103:12684d94c3a6 | 496 | adv_cp.length = length; |
Wolfgang Betz |
103:12684d94c3a6 | 497 | Osal_MemCpy(adv_cp.data, data, MIN(31,length)); |
Wolfgang Betz |
103:12684d94c3a6 | 498 | |
Wolfgang Betz |
103:12684d94c3a6 | 499 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 500 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 501 | rq.ocf = OCF_LE_SET_ADV_DATA; |
Wolfgang Betz |
103:12684d94c3a6 | 502 | rq.cparam = &adv_cp; |
Wolfgang Betz |
103:12684d94c3a6 | 503 | rq.clen = LE_SET_ADV_DATA_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 504 | rq.rparam = &status; |
Wolfgang Betz |
103:12684d94c3a6 | 505 | rq.rlen = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 506 | |
Wolfgang Betz |
103:12684d94c3a6 | 507 | if (hci_send_req(&rq, FALSE) < 0) |
Wolfgang Betz |
103:12684d94c3a6 | 508 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 509 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 515 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 516 | le_set_advertise_enable_cp adv_cp; |
Wolfgang Betz |
103:12684d94c3a6 | 517 | uint8_t status; |
Wolfgang Betz |
103:12684d94c3a6 | 518 | |
Wolfgang Betz |
103:12684d94c3a6 | 519 | Osal_MemSet(&adv_cp, 0, sizeof(adv_cp)); |
Wolfgang Betz |
103:12684d94c3a6 | 520 | adv_cp.enable = enable?1:0; |
Wolfgang Betz |
103:12684d94c3a6 | 521 | |
Wolfgang Betz |
103:12684d94c3a6 | 522 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 523 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 524 | rq.ocf = OCF_LE_SET_ADVERTISE_ENABLE; |
Wolfgang Betz |
103:12684d94c3a6 | 525 | rq.cparam = &adv_cp; |
Wolfgang Betz |
103:12684d94c3a6 | 526 | rq.clen = LE_SET_ADVERTISE_ENABLE_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 527 | rq.rparam = &status; |
Wolfgang Betz |
103:12684d94c3a6 | 528 | rq.rlen = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 529 | |
Wolfgang Betz |
103:12684d94c3a6 | 530 | if (hci_send_req(&rq, FALSE) < 0) |
Wolfgang Betz |
103:12684d94c3a6 | 531 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 532 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 540 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 541 | le_set_scan_parameters_cp scan_cp; |
Wolfgang Betz |
103:12684d94c3a6 | 542 | uint8_t status; |
Wolfgang Betz |
103:12684d94c3a6 | 543 | |
Wolfgang Betz |
103:12684d94c3a6 | 544 | Osal_MemSet(&scan_cp, 0, sizeof(scan_cp)); |
Wolfgang Betz |
103:12684d94c3a6 | 545 | scan_cp.type = type; |
Wolfgang Betz |
103:12684d94c3a6 | 546 | scan_cp.interval = interval; |
Wolfgang Betz |
103:12684d94c3a6 | 547 | scan_cp.window = window; |
Wolfgang Betz |
103:12684d94c3a6 | 548 | scan_cp.own_bdaddr_type = own_bdaddr_type; |
Wolfgang Betz |
103:12684d94c3a6 | 549 | scan_cp.filter = filter; |
Wolfgang Betz |
103:12684d94c3a6 | 550 | |
Wolfgang Betz |
103:12684d94c3a6 | 551 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 552 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 553 | rq.ocf = OCF_LE_SET_SCAN_PARAMETERS; |
Wolfgang Betz |
103:12684d94c3a6 | 554 | rq.cparam = &scan_cp; |
Wolfgang Betz |
103:12684d94c3a6 | 555 | rq.clen = LE_SET_SCAN_PARAMETERS_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 556 | rq.rparam = &status; |
Wolfgang Betz |
103:12684d94c3a6 | 557 | rq.rlen = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 558 | |
Wolfgang Betz |
103:12684d94c3a6 | 559 | if (hci_send_req(&rq, FALSE) < 0) |
Wolfgang Betz |
103:12684d94c3a6 | 560 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 561 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 567 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 568 | le_set_scan_enable_cp scan_cp; |
Wolfgang Betz |
103:12684d94c3a6 | 569 | uint8_t status; |
Wolfgang Betz |
103:12684d94c3a6 | 570 | |
Wolfgang Betz |
103:12684d94c3a6 | 571 | Osal_MemSet(&scan_cp, 0, sizeof(scan_cp)); |
Wolfgang Betz |
103:12684d94c3a6 | 572 | scan_cp.enable = enable?1:0; |
Wolfgang Betz |
103:12684d94c3a6 | 573 | scan_cp.filter_dup = filter_dup; |
Wolfgang Betz |
103:12684d94c3a6 | 574 | |
Wolfgang Betz |
103:12684d94c3a6 | 575 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 576 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 577 | rq.ocf = OCF_LE_SET_SCAN_ENABLE; |
Wolfgang Betz |
103:12684d94c3a6 | 578 | rq.cparam = &scan_cp; |
Wolfgang Betz |
103:12684d94c3a6 | 579 | rq.clen = LE_SET_SCAN_ENABLE_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 580 | rq.rparam = &status; |
Wolfgang Betz |
103:12684d94c3a6 | 581 | rq.rlen = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 582 | |
Wolfgang Betz |
103:12684d94c3a6 | 583 | if (hci_send_req(&rq, FALSE) < 0) |
Wolfgang Betz |
103:12684d94c3a6 | 584 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 585 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 591 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 592 | le_rand_rp resp; |
Wolfgang Betz |
103:12684d94c3a6 | 593 | |
Wolfgang Betz |
103:12684d94c3a6 | 594 | Osal_MemSet(&resp, 0, sizeof(resp)); |
Wolfgang Betz |
103:12684d94c3a6 | 595 | |
Wolfgang Betz |
103:12684d94c3a6 | 596 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 597 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 598 | rq.ocf = OCF_LE_RAND; |
Wolfgang Betz |
103:12684d94c3a6 | 599 | rq.cparam = NULL; |
Wolfgang Betz |
103:12684d94c3a6 | 600 | rq.clen = 0; |
Wolfgang Betz |
103:12684d94c3a6 | 601 | rq.rparam = &resp; |
Wolfgang Betz |
103:12684d94c3a6 | 602 | rq.rlen = LE_RAND_RP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 603 | |
Wolfgang Betz |
103:12684d94c3a6 | 604 | if (hci_send_req(&rq, FALSE) < 0) |
Wolfgang Betz |
103:12684d94c3a6 | 605 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 606 | |
Wolfgang Betz |
103:12684d94c3a6 | 607 | if (resp.status) { |
Wolfgang Betz |
103:12684d94c3a6 | 608 | return resp.status; |
Wolfgang Betz |
103:12684d94c3a6 | 609 | } |
Wolfgang Betz |
103:12684d94c3a6 | 610 | |
Wolfgang Betz |
103:12684d94c3a6 | 611 | Osal_MemCpy(random_number, resp.random, 8); |
Wolfgang Betz |
103:12684d94c3a6 | 612 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 618 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 619 | le_set_scan_response_data_cp scan_resp_cp; |
Wolfgang Betz |
103:12684d94c3a6 | 620 | uint8_t status; |
Wolfgang Betz |
103:12684d94c3a6 | 621 | |
Wolfgang Betz |
103:12684d94c3a6 | 622 | Osal_MemSet(&scan_resp_cp, 0, sizeof(scan_resp_cp)); |
Wolfgang Betz |
103:12684d94c3a6 | 623 | scan_resp_cp.length = length; |
Wolfgang Betz |
103:12684d94c3a6 | 624 | Osal_MemCpy(scan_resp_cp.data, data, MIN(31,length)); |
Wolfgang Betz |
103:12684d94c3a6 | 625 | |
Wolfgang Betz |
103:12684d94c3a6 | 626 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 627 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 628 | rq.ocf = OCF_LE_SET_SCAN_RESPONSE_DATA; |
Wolfgang Betz |
103:12684d94c3a6 | 629 | rq.cparam = &scan_resp_cp; |
Wolfgang Betz |
103:12684d94c3a6 | 630 | rq.clen = LE_SET_SCAN_RESPONSE_DATA_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 631 | rq.rparam = &status; |
Wolfgang Betz |
103:12684d94c3a6 | 632 | rq.rlen = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 633 | |
Wolfgang Betz |
103:12684d94c3a6 | 634 | if (hci_send_req(&rq, FALSE) < 0) |
Wolfgang Betz |
103:12684d94c3a6 | 635 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 636 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 642 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 643 | le_read_adv_channel_tx_power_rp resp; |
Wolfgang Betz |
103:12684d94c3a6 | 644 | |
Wolfgang Betz |
103:12684d94c3a6 | 645 | Osal_MemSet(&resp, 0, sizeof(resp)); |
Wolfgang Betz |
103:12684d94c3a6 | 646 | |
Wolfgang Betz |
103:12684d94c3a6 | 647 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 648 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 649 | rq.ocf = OCF_LE_READ_ADV_CHANNEL_TX_POWER; |
Wolfgang Betz |
103:12684d94c3a6 | 650 | rq.cparam = NULL; |
Wolfgang Betz |
103:12684d94c3a6 | 651 | rq.clen = 0; |
Wolfgang Betz |
103:12684d94c3a6 | 652 | rq.rparam = &resp; |
Wolfgang Betz |
103:12684d94c3a6 | 653 | rq.rlen = LE_RAND_RP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 654 | |
Wolfgang Betz |
103:12684d94c3a6 | 655 | if (hci_send_req(&rq, FALSE) < 0) |
Wolfgang Betz |
103:12684d94c3a6 | 656 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 657 | |
Wolfgang Betz |
103:12684d94c3a6 | 658 | if (resp.status) { |
Wolfgang Betz |
103:12684d94c3a6 | 659 | return resp.status; |
Wolfgang Betz |
103:12684d94c3a6 | 660 | } |
Wolfgang Betz |
103:12684d94c3a6 | 661 | |
Wolfgang Betz |
103:12684d94c3a6 | 662 | *tx_power_level = resp.level; |
Wolfgang Betz |
103:12684d94c3a6 | 663 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 669 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 670 | le_set_random_address_cp set_rand_addr_cp; |
Wolfgang Betz |
103:12684d94c3a6 | 671 | uint8_t status; |
Wolfgang Betz |
103:12684d94c3a6 | 672 | |
Wolfgang Betz |
103:12684d94c3a6 | 673 | Osal_MemSet(&set_rand_addr_cp, 0, sizeof(set_rand_addr_cp)); |
Wolfgang Betz |
103:12684d94c3a6 | 674 | Osal_MemCpy(set_rand_addr_cp.bdaddr, bdaddr, sizeof(tBDAddr)); |
Wolfgang Betz |
103:12684d94c3a6 | 675 | |
Wolfgang Betz |
103:12684d94c3a6 | 676 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 677 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 678 | rq.ocf = OCF_LE_SET_RANDOM_ADDRESS; |
Wolfgang Betz |
103:12684d94c3a6 | 679 | rq.cparam = &set_rand_addr_cp; |
Wolfgang Betz |
103:12684d94c3a6 | 680 | rq.clen = LE_SET_RANDOM_ADDRESS_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 681 | rq.rparam = &status; |
Wolfgang Betz |
103:12684d94c3a6 | 682 | rq.rlen = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 683 | |
Wolfgang Betz |
103:12684d94c3a6 | 684 | if (hci_send_req(&rq, FALSE) < 0) |
Wolfgang Betz |
103:12684d94c3a6 | 685 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 686 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 692 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 693 | read_bd_addr_rp resp; |
Wolfgang Betz |
103:12684d94c3a6 | 694 | |
Wolfgang Betz |
103:12684d94c3a6 | 695 | Osal_MemSet(&resp, 0, sizeof(resp)); |
Wolfgang Betz |
103:12684d94c3a6 | 696 | |
Wolfgang Betz |
103:12684d94c3a6 | 697 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 698 | rq.ogf = OGF_INFO_PARAM; |
Wolfgang Betz |
103:12684d94c3a6 | 699 | rq.ocf = OCF_READ_BD_ADDR; |
Wolfgang Betz |
103:12684d94c3a6 | 700 | rq.cparam = NULL; |
Wolfgang Betz |
103:12684d94c3a6 | 701 | rq.clen = 0; |
Wolfgang Betz |
103:12684d94c3a6 | 702 | rq.rparam = &resp; |
Wolfgang Betz |
103:12684d94c3a6 | 703 | rq.rlen = READ_BD_ADDR_RP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 704 | |
Wolfgang Betz |
103:12684d94c3a6 | 705 | if (hci_send_req(&rq, FALSE) < 0) |
Wolfgang Betz |
103:12684d94c3a6 | 706 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 707 | |
Wolfgang Betz |
103:12684d94c3a6 | 708 | if (resp.status) { |
Wolfgang Betz |
103:12684d94c3a6 | 709 | return resp.status; |
Wolfgang Betz |
103:12684d94c3a6 | 710 | } |
Wolfgang Betz |
103:12684d94c3a6 | 711 | Osal_MemCpy(bdaddr, resp.bdaddr, sizeof(tBDAddr)); |
Wolfgang Betz |
103:12684d94c3a6 | 712 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 720 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 721 | le_create_connection_cp create_cp; |
Wolfgang Betz |
103:12684d94c3a6 | 722 | uint8_t status; |
Wolfgang Betz |
103:12684d94c3a6 | 723 | |
Wolfgang Betz |
103:12684d94c3a6 | 724 | Osal_MemSet(&create_cp, 0, sizeof(create_cp)); |
Wolfgang Betz |
103:12684d94c3a6 | 725 | create_cp.interval = interval; |
Wolfgang Betz |
103:12684d94c3a6 | 726 | create_cp.window = window; |
Wolfgang Betz |
103:12684d94c3a6 | 727 | create_cp.initiator_filter = initiator_filter; |
Wolfgang Betz |
103:12684d94c3a6 | 728 | create_cp.peer_bdaddr_type = peer_bdaddr_type; |
Wolfgang Betz |
103:12684d94c3a6 | 729 | Osal_MemCpy(create_cp.peer_bdaddr, peer_bdaddr, sizeof(tBDAddr)); |
Wolfgang Betz |
103:12684d94c3a6 | 730 | create_cp.own_bdaddr_type = own_bdaddr_type; |
Wolfgang Betz |
103:12684d94c3a6 | 731 | create_cp.min_interval=min_interval; |
Wolfgang Betz |
103:12684d94c3a6 | 732 | create_cp.max_interval=max_interval; |
Wolfgang Betz |
103:12684d94c3a6 | 733 | create_cp.latency = latency; |
Wolfgang Betz |
103:12684d94c3a6 | 734 | create_cp.supervision_timeout=supervision_timeout; |
Wolfgang Betz |
103:12684d94c3a6 | 735 | create_cp.min_ce_length=min_ce_length; |
Wolfgang Betz |
103:12684d94c3a6 | 736 | create_cp.max_ce_length=max_ce_length; |
Wolfgang Betz |
103:12684d94c3a6 | 737 | |
Wolfgang Betz |
103:12684d94c3a6 | 738 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 739 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 740 | rq.ocf = OCF_LE_CREATE_CONN; |
Wolfgang Betz |
103:12684d94c3a6 | 741 | rq.cparam = &create_cp; |
Wolfgang Betz |
103:12684d94c3a6 | 742 | rq.clen = LE_CREATE_CONN_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 743 | rq.event = EVT_CMD_STATUS; |
Wolfgang Betz |
103:12684d94c3a6 | 744 | rq.rparam = &status; |
Wolfgang Betz |
103:12684d94c3a6 | 745 | rq.rlen = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 746 | |
Wolfgang Betz |
103:12684d94c3a6 | 747 | if (hci_send_req(&rq, FALSE) < 0) |
Wolfgang Betz |
103:12684d94c3a6 | 748 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 749 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 755 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 756 | le_encrypt_cp params; |
Wolfgang Betz |
103:12684d94c3a6 | 757 | le_encrypt_rp resp; |
Wolfgang Betz |
103:12684d94c3a6 | 758 | |
Wolfgang Betz |
103:12684d94c3a6 | 759 | Osal_MemSet(&resp, 0, sizeof(resp)); |
Wolfgang Betz |
103:12684d94c3a6 | 760 | |
Wolfgang Betz |
103:12684d94c3a6 | 761 | Osal_MemCpy(params.key, key, 16); |
Wolfgang Betz |
103:12684d94c3a6 | 762 | Osal_MemCpy(params.plaintext, plaintextData, 16); |
Wolfgang Betz |
103:12684d94c3a6 | 763 | |
Wolfgang Betz |
103:12684d94c3a6 | 764 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 765 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 766 | rq.ocf = OCF_LE_ENCRYPT; |
Wolfgang Betz |
103:12684d94c3a6 | 767 | rq.cparam = ¶ms; |
Wolfgang Betz |
103:12684d94c3a6 | 768 | rq.clen = LE_ENCRYPT_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 769 | rq.rparam = &resp; |
Wolfgang Betz |
103:12684d94c3a6 | 770 | rq.rlen = LE_ENCRYPT_RP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 771 | |
Wolfgang Betz |
103:12684d94c3a6 | 772 | if (hci_send_req(&rq, FALSE) < 0){ |
Wolfgang Betz |
103:12684d94c3a6 | 773 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 774 | } |
Wolfgang Betz |
103:12684d94c3a6 | 775 | |
Wolfgang Betz |
103:12684d94c3a6 | 776 | if (resp.status) { |
Wolfgang Betz |
103:12684d94c3a6 | 777 | return resp.status; |
Wolfgang Betz |
103:12684d94c3a6 | 778 | } |
Wolfgang Betz |
103:12684d94c3a6 | 779 | |
Wolfgang Betz |
103:12684d94c3a6 | 780 | Osal_MemCpy(encryptedData, resp.encdata, 16); |
Wolfgang Betz |
103:12684d94c3a6 | 781 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 787 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 788 | le_ltk_reply_cp params; |
Wolfgang Betz |
103:12684d94c3a6 | 789 | le_ltk_reply_rp resp; |
Wolfgang Betz |
103:12684d94c3a6 | 790 | |
Wolfgang Betz |
103:12684d94c3a6 | 791 | Osal_MemSet(&resp, 0, sizeof(resp)); |
Wolfgang Betz |
103:12684d94c3a6 | 792 | |
Wolfgang Betz |
103:12684d94c3a6 | 793 | params.handle = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 794 | Osal_MemCpy(params.key, key, 16); |
Wolfgang Betz |
103:12684d94c3a6 | 795 | |
Wolfgang Betz |
103:12684d94c3a6 | 796 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 797 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 798 | rq.ocf = OCF_LE_LTK_REPLY; |
Wolfgang Betz |
103:12684d94c3a6 | 799 | rq.cparam = ¶ms; |
Wolfgang Betz |
103:12684d94c3a6 | 800 | rq.clen = LE_LTK_REPLY_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 801 | rq.rparam = &resp; |
Wolfgang Betz |
103:12684d94c3a6 | 802 | rq.rlen = LE_LTK_REPLY_RP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 803 | |
Wolfgang Betz |
103:12684d94c3a6 | 804 | if (hci_send_req(&rq, FALSE) < 0) |
Wolfgang Betz |
103:12684d94c3a6 | 805 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 806 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 812 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 813 | le_ltk_neg_reply_cp params; |
Wolfgang Betz |
103:12684d94c3a6 | 814 | le_ltk_neg_reply_rp resp; |
Wolfgang Betz |
103:12684d94c3a6 | 815 | |
Wolfgang Betz |
103:12684d94c3a6 | 816 | Osal_MemSet(&resp, 0, sizeof(resp)); |
Wolfgang Betz |
103:12684d94c3a6 | 817 | |
Wolfgang Betz |
103:12684d94c3a6 | 818 | params.handle = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 819 | |
Wolfgang Betz |
103:12684d94c3a6 | 820 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 821 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 822 | rq.ocf = OCF_LE_LTK_NEG_REPLY; |
Wolfgang Betz |
103:12684d94c3a6 | 823 | rq.cparam = ¶ms; |
Wolfgang Betz |
103:12684d94c3a6 | 824 | rq.clen = LE_LTK_NEG_REPLY_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 825 | rq.rparam = &resp; |
Wolfgang Betz |
103:12684d94c3a6 | 826 | rq.rlen = LE_LTK_NEG_REPLY_RP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 827 | |
Wolfgang Betz |
103:12684d94c3a6 | 828 | if (hci_send_req(&rq, FALSE) < 0) |
Wolfgang Betz |
103:12684d94c3a6 | 829 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 830 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 836 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 837 | le_read_white_list_size_rp resp; |
Wolfgang Betz |
103:12684d94c3a6 | 838 | |
Wolfgang Betz |
103:12684d94c3a6 | 839 | Osal_MemSet(&resp, 0, sizeof(resp)); |
Wolfgang Betz |
103:12684d94c3a6 | 840 | |
Wolfgang Betz |
103:12684d94c3a6 | 841 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 842 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 843 | rq.ocf = OCF_LE_READ_WHITE_LIST_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 844 | rq.rparam = &resp; |
Wolfgang Betz |
103:12684d94c3a6 | 845 | rq.rlen = LE_READ_WHITE_LIST_SIZE_RP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 846 | |
Wolfgang Betz |
103:12684d94c3a6 | 847 | if (hci_send_req(&rq, FALSE) < 0){ |
Wolfgang Betz |
103:12684d94c3a6 | 848 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 849 | } |
Wolfgang Betz |
103:12684d94c3a6 | 850 | |
Wolfgang Betz |
103:12684d94c3a6 | 851 | if (resp.status) { |
Wolfgang Betz |
103:12684d94c3a6 | 852 | return resp.status; |
Wolfgang Betz |
103:12684d94c3a6 | 853 | } |
Wolfgang Betz |
103:12684d94c3a6 | 854 | |
Wolfgang Betz |
103:12684d94c3a6 | 855 | *size = resp.size; |
Wolfgang Betz |
103:12684d94c3a6 | 856 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 862 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 863 | uint8_t status; |
Wolfgang Betz |
103:12684d94c3a6 | 864 | |
Wolfgang Betz |
103:12684d94c3a6 | 865 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 866 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 867 | rq.ocf = OCF_LE_CLEAR_WHITE_LIST; |
Wolfgang Betz |
103:12684d94c3a6 | 868 | rq.rparam = &status; |
Wolfgang Betz |
103:12684d94c3a6 | 869 | rq.rlen = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 870 | |
Wolfgang Betz |
103:12684d94c3a6 | 871 | if (hci_send_req(&rq, FALSE) < 0){ |
Wolfgang Betz |
103:12684d94c3a6 | 872 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 873 | } |
Wolfgang Betz |
103:12684d94c3a6 | 874 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 880 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 881 | le_add_device_to_white_list_cp params; |
Wolfgang Betz |
103:12684d94c3a6 | 882 | uint8_t status; |
Wolfgang Betz |
103:12684d94c3a6 | 883 | |
Wolfgang Betz |
103:12684d94c3a6 | 884 | params.bdaddr_type = bdaddr_type; |
Wolfgang Betz |
103:12684d94c3a6 | 885 | Osal_MemCpy(params.bdaddr, bdaddr, 6); |
Wolfgang Betz |
103:12684d94c3a6 | 886 | |
Wolfgang Betz |
103:12684d94c3a6 | 887 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 888 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 889 | rq.ocf = OCF_LE_ADD_DEVICE_TO_WHITE_LIST; |
Wolfgang Betz |
103:12684d94c3a6 | 890 | rq.cparam = ¶ms; |
Wolfgang Betz |
103:12684d94c3a6 | 891 | rq.clen = LE_ADD_DEVICE_TO_WHITE_LIST_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 892 | rq.rparam = &status; |
Wolfgang Betz |
103:12684d94c3a6 | 893 | rq.rlen = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 894 | |
Wolfgang Betz |
103:12684d94c3a6 | 895 | if (hci_send_req(&rq, FALSE) < 0){ |
Wolfgang Betz |
103:12684d94c3a6 | 896 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 897 | } |
Wolfgang Betz |
103:12684d94c3a6 | 898 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 904 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 905 | le_remove_device_from_white_list_cp params; |
Wolfgang Betz |
103:12684d94c3a6 | 906 | uint8_t status; |
Wolfgang Betz |
103:12684d94c3a6 | 907 | |
Wolfgang Betz |
103:12684d94c3a6 | 908 | params.bdaddr_type = bdaddr_type; |
Wolfgang Betz |
103:12684d94c3a6 | 909 | Osal_MemCpy(params.bdaddr, bdaddr, 6); |
Wolfgang Betz |
103:12684d94c3a6 | 910 | |
Wolfgang Betz |
103:12684d94c3a6 | 911 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 912 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 913 | rq.ocf = OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST; |
Wolfgang Betz |
103:12684d94c3a6 | 914 | rq.cparam = ¶ms; |
Wolfgang Betz |
103:12684d94c3a6 | 915 | rq.clen = LE_REMOVE_DEVICE_FROM_WHITE_LIST_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 916 | rq.rparam = &status; |
Wolfgang Betz |
103:12684d94c3a6 | 917 | rq.rlen = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 918 | |
Wolfgang Betz |
103:12684d94c3a6 | 919 | if (hci_send_req(&rq, FALSE) < 0){ |
Wolfgang Betz |
103:12684d94c3a6 | 920 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 921 | } |
Wolfgang Betz |
103:12684d94c3a6 | 922 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 928 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 929 | read_transmit_power_level_cp params; |
Wolfgang Betz |
103:12684d94c3a6 | 930 | read_transmit_power_level_rp resp; |
Wolfgang Betz |
103:12684d94c3a6 | 931 | |
Wolfgang Betz |
103:12684d94c3a6 | 932 | Osal_MemSet(&resp, 0, sizeof(resp)); |
Wolfgang Betz |
103:12684d94c3a6 | 933 | |
Wolfgang Betz |
103:12684d94c3a6 | 934 | params.handle = *conn_handle; |
Wolfgang Betz |
103:12684d94c3a6 | 935 | params.type = type; |
Wolfgang Betz |
103:12684d94c3a6 | 936 | |
Wolfgang Betz |
103:12684d94c3a6 | 937 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 938 | rq.ogf = OGF_HOST_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 939 | rq.ocf = OCF_READ_TRANSMIT_POWER_LEVEL; |
Wolfgang Betz |
103:12684d94c3a6 | 940 | rq.cparam = ¶ms; |
Wolfgang Betz |
103:12684d94c3a6 | 941 | rq.clen = READ_TRANSMIT_POWER_LEVEL_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 942 | rq.rparam = &resp; |
Wolfgang Betz |
103:12684d94c3a6 | 943 | rq.rlen = READ_TRANSMIT_POWER_LEVEL_RP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 944 | |
Wolfgang Betz |
103:12684d94c3a6 | 945 | if (hci_send_req(&rq, FALSE) < 0){ |
Wolfgang Betz |
103:12684d94c3a6 | 946 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 947 | } |
Wolfgang Betz |
103:12684d94c3a6 | 948 | |
Wolfgang Betz |
103:12684d94c3a6 | 949 | if (resp.status) { |
Wolfgang Betz |
103:12684d94c3a6 | 950 | return resp.status; |
Wolfgang Betz |
103:12684d94c3a6 | 951 | } |
Wolfgang Betz |
103:12684d94c3a6 | 952 | |
Wolfgang Betz |
103:12684d94c3a6 | 953 | *conn_handle = resp.handle; |
Wolfgang Betz |
103:12684d94c3a6 | 954 | *tx_level = resp.level; |
Wolfgang Betz |
103:12684d94c3a6 | 955 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 961 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 962 | read_rssi_cp params; |
Wolfgang Betz |
103:12684d94c3a6 | 963 | read_rssi_rp resp; |
Wolfgang Betz |
103:12684d94c3a6 | 964 | |
Wolfgang Betz |
103:12684d94c3a6 | 965 | Osal_MemSet(&resp, 0, sizeof(resp)); |
Wolfgang Betz |
103:12684d94c3a6 | 966 | |
Wolfgang Betz |
103:12684d94c3a6 | 967 | params.handle = *conn_handle; |
Wolfgang Betz |
103:12684d94c3a6 | 968 | |
Wolfgang Betz |
103:12684d94c3a6 | 969 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 970 | rq.ogf = OGF_STATUS_PARAM; |
Wolfgang Betz |
103:12684d94c3a6 | 971 | rq.ocf = OCF_READ_RSSI; |
Wolfgang Betz |
103:12684d94c3a6 | 972 | rq.cparam = ¶ms; |
Wolfgang Betz |
103:12684d94c3a6 | 973 | rq.clen = READ_RSSI_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 974 | rq.rparam = &resp; |
Wolfgang Betz |
103:12684d94c3a6 | 975 | rq.rlen = READ_RSSI_RP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 976 | |
Wolfgang Betz |
103:12684d94c3a6 | 977 | if (hci_send_req(&rq, FALSE) < 0){ |
Wolfgang Betz |
103:12684d94c3a6 | 978 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 979 | } |
Wolfgang Betz |
103:12684d94c3a6 | 980 | |
Wolfgang Betz |
103:12684d94c3a6 | 981 | if (resp.status) { |
Wolfgang Betz |
103:12684d94c3a6 | 982 | return resp.status; |
Wolfgang Betz |
103:12684d94c3a6 | 983 | } |
Wolfgang Betz |
103:12684d94c3a6 | 984 | |
Wolfgang Betz |
103:12684d94c3a6 | 985 | *conn_handle = resp.handle; |
Wolfgang Betz |
103:12684d94c3a6 | 986 | *rssi = resp.rssi; |
Wolfgang Betz |
103:12684d94c3a6 | 987 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 993 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 994 | le_read_local_supported_features_rp resp; |
Wolfgang Betz |
103:12684d94c3a6 | 995 | |
Wolfgang Betz |
103:12684d94c3a6 | 996 | Osal_MemSet(&resp, 0, sizeof(resp)); |
Wolfgang Betz |
103:12684d94c3a6 | 997 | |
Wolfgang Betz |
103:12684d94c3a6 | 998 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 999 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 1000 | rq.ocf = OCF_LE_READ_LOCAL_SUPPORTED_FEATURES; |
Wolfgang Betz |
103:12684d94c3a6 | 1001 | rq.rparam = &resp; |
Wolfgang Betz |
103:12684d94c3a6 | 1002 | rq.rlen = LE_READ_LOCAL_SUPPORTED_FEATURES_RP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 1003 | |
Wolfgang Betz |
103:12684d94c3a6 | 1004 | if (hci_send_req(&rq, FALSE) < 0){ |
Wolfgang Betz |
103:12684d94c3a6 | 1005 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 1006 | } |
Wolfgang Betz |
103:12684d94c3a6 | 1007 | |
Wolfgang Betz |
103:12684d94c3a6 | 1008 | if (resp.status) { |
Wolfgang Betz |
103:12684d94c3a6 | 1009 | return resp.status; |
Wolfgang Betz |
103:12684d94c3a6 | 1010 | } |
Wolfgang Betz |
103:12684d94c3a6 | 1011 | |
Wolfgang Betz |
103:12684d94c3a6 | 1012 | Osal_MemCpy(features, resp.features, sizeof(resp.features)); |
Wolfgang Betz |
103:12684d94c3a6 | 1013 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 1019 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 1020 | le_read_channel_map_cp params; |
Wolfgang Betz |
103:12684d94c3a6 | 1021 | le_read_channel_map_rp resp; |
Wolfgang Betz |
103:12684d94c3a6 | 1022 | |
Wolfgang Betz |
103:12684d94c3a6 | 1023 | Osal_MemSet(&resp, 0, sizeof(resp)); |
Wolfgang Betz |
103:12684d94c3a6 | 1024 | |
Wolfgang Betz |
103:12684d94c3a6 | 1025 | params.handle = conn_handle; |
Wolfgang Betz |
103:12684d94c3a6 | 1026 | |
Wolfgang Betz |
103:12684d94c3a6 | 1027 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 1028 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 1029 | rq.ocf = OCF_LE_READ_CHANNEL_MAP; |
Wolfgang Betz |
103:12684d94c3a6 | 1030 | rq.cparam = ¶ms; |
Wolfgang Betz |
103:12684d94c3a6 | 1031 | rq.clen = LE_READ_CHANNEL_MAP_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 1032 | rq.rparam = &resp; |
Wolfgang Betz |
103:12684d94c3a6 | 1033 | rq.rlen = LE_READ_CHANNEL_MAP_RP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 1034 | |
Wolfgang Betz |
103:12684d94c3a6 | 1035 | if (hci_send_req(&rq, FALSE) < 0){ |
Wolfgang Betz |
103:12684d94c3a6 | 1036 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 1037 | } |
Wolfgang Betz |
103:12684d94c3a6 | 1038 | |
Wolfgang Betz |
103:12684d94c3a6 | 1039 | if (resp.status) { |
Wolfgang Betz |
103:12684d94c3a6 | 1040 | return resp.status; |
Wolfgang Betz |
103:12684d94c3a6 | 1041 | } |
Wolfgang Betz |
103:12684d94c3a6 | 1042 | |
Wolfgang Betz |
103:12684d94c3a6 | 1043 | Osal_MemCpy(ch_map, resp.map, 5); |
Wolfgang Betz |
103:12684d94c3a6 | 1044 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 1050 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 1051 | le_read_supported_states_rp resp; |
Wolfgang Betz |
103:12684d94c3a6 | 1052 | |
Wolfgang Betz |
103:12684d94c3a6 | 1053 | Osal_MemSet(&resp, 0, sizeof(resp)); |
Wolfgang Betz |
103:12684d94c3a6 | 1054 | |
Wolfgang Betz |
103:12684d94c3a6 | 1055 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 1056 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 1057 | rq.ocf = OCF_LE_READ_SUPPORTED_STATES; |
Wolfgang Betz |
103:12684d94c3a6 | 1058 | rq.rparam = &resp; |
Wolfgang Betz |
103:12684d94c3a6 | 1059 | rq.rlen = LE_READ_SUPPORTED_STATES_RP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 1060 | |
Wolfgang Betz |
103:12684d94c3a6 | 1061 | if (hci_send_req(&rq, FALSE) < 0){ |
Wolfgang Betz |
103:12684d94c3a6 | 1062 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 1063 | } |
Wolfgang Betz |
103:12684d94c3a6 | 1064 | |
Wolfgang Betz |
103:12684d94c3a6 | 1065 | if (resp.status) { |
Wolfgang Betz |
103:12684d94c3a6 | 1066 | return resp.status; |
Wolfgang Betz |
103:12684d94c3a6 | 1067 | } |
Wolfgang Betz |
103:12684d94c3a6 | 1068 | |
Wolfgang Betz |
103:12684d94c3a6 | 1069 | Osal_MemCpy(states, resp.states, 8); |
Wolfgang Betz |
103:12684d94c3a6 | 1070 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 1076 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 1077 | le_receiver_test_cp params; |
Wolfgang Betz |
103:12684d94c3a6 | 1078 | uint8_t status; |
Wolfgang Betz |
103:12684d94c3a6 | 1079 | |
Wolfgang Betz |
103:12684d94c3a6 | 1080 | params.frequency = frequency; |
Wolfgang Betz |
103:12684d94c3a6 | 1081 | |
Wolfgang Betz |
103:12684d94c3a6 | 1082 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 1083 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 1084 | rq.ocf = OCF_LE_RECEIVER_TEST; |
Wolfgang Betz |
103:12684d94c3a6 | 1085 | rq.cparam = ¶ms; |
Wolfgang Betz |
103:12684d94c3a6 | 1086 | rq.clen = LE_RECEIVER_TEST_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 1087 | rq.rparam = &status; |
Wolfgang Betz |
103:12684d94c3a6 | 1088 | rq.rlen = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 1089 | |
Wolfgang Betz |
103:12684d94c3a6 | 1090 | if (hci_send_req(&rq, FALSE) < 0){ |
Wolfgang Betz |
103:12684d94c3a6 | 1091 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 1092 | } |
Wolfgang Betz |
103:12684d94c3a6 | 1093 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 1099 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 1100 | le_transmitter_test_cp params; |
Wolfgang Betz |
103:12684d94c3a6 | 1101 | uint8_t status; |
Wolfgang Betz |
103:12684d94c3a6 | 1102 | |
Wolfgang Betz |
103:12684d94c3a6 | 1103 | params.frequency = frequency; |
Wolfgang Betz |
103:12684d94c3a6 | 1104 | params.length = length; |
Wolfgang Betz |
103:12684d94c3a6 | 1105 | params.payload = payload; |
Wolfgang Betz |
103:12684d94c3a6 | 1106 | |
Wolfgang Betz |
103:12684d94c3a6 | 1107 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 1108 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 1109 | rq.ocf = OCF_LE_TRANSMITTER_TEST; |
Wolfgang Betz |
103:12684d94c3a6 | 1110 | rq.cparam = ¶ms; |
Wolfgang Betz |
103:12684d94c3a6 | 1111 | rq.clen = LE_TRANSMITTER_TEST_CP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 1112 | rq.rparam = &status; |
Wolfgang Betz |
103:12684d94c3a6 | 1113 | rq.rlen = 1; |
Wolfgang Betz |
103:12684d94c3a6 | 1114 | |
Wolfgang Betz |
103:12684d94c3a6 | 1115 | if (hci_send_req(&rq, FALSE) < 0){ |
Wolfgang Betz |
103:12684d94c3a6 | 1116 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 1117 | } |
Wolfgang Betz |
103:12684d94c3a6 | 1118 | |
Wolfgang Betz |
103:12684d94c3a6 | 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 | { |
Wolfgang Betz |
103:12684d94c3a6 | 1124 | struct hci_request rq; |
Wolfgang Betz |
103:12684d94c3a6 | 1125 | le_test_end_rp resp; |
Wolfgang Betz |
103:12684d94c3a6 | 1126 | |
Wolfgang Betz |
103:12684d94c3a6 | 1127 | Osal_MemSet(&resp, 0, sizeof(resp)); |
Wolfgang Betz |
103:12684d94c3a6 | 1128 | |
Wolfgang Betz |
103:12684d94c3a6 | 1129 | Osal_MemSet(&rq, 0, sizeof(rq)); |
Wolfgang Betz |
103:12684d94c3a6 | 1130 | rq.ogf = OGF_LE_CTL; |
Wolfgang Betz |
103:12684d94c3a6 | 1131 | rq.ocf = OCF_LE_TEST_END; |
Wolfgang Betz |
103:12684d94c3a6 | 1132 | rq.rparam = &resp; |
Wolfgang Betz |
103:12684d94c3a6 | 1133 | rq.rlen = LE_TEST_END_RP_SIZE; |
Wolfgang Betz |
103:12684d94c3a6 | 1134 | |
Wolfgang Betz |
103:12684d94c3a6 | 1135 | if (hci_send_req(&rq, FALSE) < 0){ |
Wolfgang Betz |
103:12684d94c3a6 | 1136 | return BLE_STATUS_TIMEOUT; |
Wolfgang Betz |
103:12684d94c3a6 | 1137 | } |
Wolfgang Betz |
103:12684d94c3a6 | 1138 | |
Wolfgang Betz |
103:12684d94c3a6 | 1139 | if (resp.status) { |
Wolfgang Betz |
103:12684d94c3a6 | 1140 | return resp.status; |
Wolfgang Betz |
103:12684d94c3a6 | 1141 | } |
Wolfgang Betz |
103:12684d94c3a6 | 1142 | |
Wolfgang Betz |
103:12684d94c3a6 | 1143 | *num_pkts = resp.num_pkts; |
Wolfgang Betz |
103:12684d94c3a6 | 1144 | |
Wolfgang Betz |
103:12684d94c3a6 | 1145 | return 0; |
Wolfgang Betz |
90:26c0c9807ab4 | 1146 | } |
Wolfgang Betz |
90:26c0c9807ab4 | 1147 |