BLE_API wrapper library for STMicroelectronics' BlueNRG Bluetooth Low Energy expansion board shield (Component)
Dependents: Nucleo_Zumo_BLE_IDB04A1 contest_IOT5 contest_IOT6 contest_IOT_10 ... more
Fork of X_NUCLEO_IDB0XA1 by
ble_hci.c
00001 /** 00002 ****************************************************************************** 00003 * @file ble_hci.c 00004 * @author AMS/HESA Application Team 00005 * @brief Function for managing HCI interface. 00006 ****************************************************************************** 00007 * 00008 * 00009 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 00010 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 00011 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY 00012 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 00013 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 00014 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 00015 * 00016 * <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2> 00017 */ 00018 00019 #include "ble_hal_types.h" 00020 #include "ble_osal.h" 00021 #include "ble_status.h" 00022 #include "ble_hal.h" 00023 #include "ble_hci_const.h" 00024 #include "ble_gp_timer.h" 00025 #include "ble_debug.h" 00026 00027 #include "stm32_bluenrg_ble.h " 00028 00029 #if BLE_CONFIG_DBG_ENABLE 00030 #undef PRINTF 00031 #endif 00032 00033 #define HCI_LOG_ON 0 00034 00035 #define HCI_READ_PACKET_NUM_MAX (0x40) 00036 00037 #define MIN(a,b) ((a) < (b) )? (a) : (b) 00038 #define MAX(a,b) ((a) > (b) )? (a) : (b) 00039 00040 tListNode hciReadPktPool; 00041 tListNode hciReadPktRxQueue; 00042 00043 // betzw - DEBUG: 00044 //#define POOL_CNT 00045 #ifdef POOL_CNT 00046 #include <stdio.h> 00047 static unsigned int nr_hciReadPktPool; 00048 static unsigned int lowest_nr_hciReadPktPool; 00049 #endif // POOL_CNT 00050 00051 /* pool of hci read packets */ 00052 static tHciDataPacket hciReadPacketBuffer[HCI_READ_PACKET_NUM_MAX]; 00053 00054 static volatile uint8_t readPacketListFull=FALSE; 00055 00056 static volatile uint8_t hci_timer_id; 00057 static volatile uint8_t hci_timeout; 00058 00059 void hci_timeout_callback(void) 00060 { 00061 hci_timeout = 1; 00062 return; 00063 } 00064 00065 void HCI_Init(void) 00066 { 00067 uint8_t index; 00068 00069 Disable_SPI_IRQ(); 00070 00071 #ifdef POOL_CNT 00072 nr_hciReadPktPool = 0; 00073 #endif // POOL_CNT 00074 00075 /* Initialize list heads of ready and free hci data packet queues */ 00076 list_init_head (&hciReadPktPool); 00077 list_init_head (&hciReadPktRxQueue); 00078 00079 /* Initialize the queue of free hci data packets */ 00080 for (index = 0; index < HCI_READ_PACKET_NUM_MAX; index++) 00081 { 00082 list_insert_tail(&hciReadPktPool, (tListNode *)&hciReadPacketBuffer[index]); 00083 #ifdef POOL_CNT 00084 nr_hciReadPktPool++; 00085 #endif // POOL_CNT 00086 } 00087 00088 #ifdef POOL_CNT 00089 lowest_nr_hciReadPktPool = nr_hciReadPktPool; 00090 #endif // POOL_CNT 00091 00092 Enable_SPI_IRQ(); 00093 } 00094 00095 #define HCI_PCK_TYPE_OFFSET 0 00096 #define EVENT_PARAMETER_TOT_LEN_OFFSET 2 00097 00098 /** 00099 * Verify if HCI packet is correctly formatted.. 00100 * 00101 * @param[in] hciReadPacket The packet that is received from HCI interface. 00102 * @return 0 if HCI packet is as expected 00103 */ 00104 int HCI_verify(const tHciDataPacket * hciReadPacket) 00105 { 00106 const uint8_t *hci_pckt = hciReadPacket->dataBuff; 00107 00108 if(hci_pckt[HCI_PCK_TYPE_OFFSET] != HCI_EVENT_PKT) 00109 return 1; /* Incorrect type. */ 00110 00111 if(hci_pckt[EVENT_PARAMETER_TOT_LEN_OFFSET] != hciReadPacket->data_len - (1+HCI_EVENT_HDR_SIZE)) 00112 return 2; /* Wrong length (packet truncated or too long). */ 00113 00114 return 0; 00115 } 00116 00117 void HCI_Process(void) 00118 { 00119 uint8_t data_len; 00120 uint8_t buffer[HCI_READ_PACKET_SIZE]; 00121 tHciDataPacket * hciReadPacket = NULL; 00122 00123 #ifdef POOL_CNT 00124 printf("betzw(%s, %d): nr_hciReadPktPool = %u (lowest = %u)\r\n", __func__, __LINE__, 00125 nr_hciReadPktPool, lowest_nr_hciReadPktPool); 00126 #endif // POOL_CNT 00127 00128 Disable_SPI_IRQ(); 00129 uint8_t list_empty = list_is_empty(&hciReadPktRxQueue); 00130 /* process any pending events read */ 00131 while(list_empty == FALSE) 00132 { 00133 list_remove_head (&hciReadPktRxQueue, (tListNode **)&hciReadPacket); 00134 Enable_SPI_IRQ(); 00135 HCI_Event_CB(hciReadPacket->dataBuff); 00136 Disable_SPI_IRQ(); 00137 list_insert_tail(&hciReadPktPool, (tListNode *)hciReadPacket); 00138 #ifdef POOL_CNT 00139 nr_hciReadPktPool++; 00140 #endif 00141 list_empty = list_is_empty(&hciReadPktRxQueue); 00142 } 00143 if (readPacketListFull) { 00144 while(BlueNRG_DataPresent()) { 00145 data_len = BlueNRG_SPI_Read_All(buffer, HCI_READ_PACKET_SIZE); 00146 if(data_len > 0) 00147 HCI_Event_CB(buffer); 00148 } 00149 readPacketListFull = FALSE; 00150 } 00151 00152 Enable_SPI_IRQ(); 00153 } 00154 00155 BOOL HCI_Queue_Empty(void) 00156 { 00157 return list_is_empty(&hciReadPktRxQueue); 00158 } 00159 00160 void HCI_Isr(void) 00161 { 00162 tHciDataPacket * hciReadPacket = NULL; 00163 uint8_t data_len; 00164 00165 Clear_SPI_EXTI_Flag(); 00166 while(BlueNRG_DataPresent()){ 00167 if (list_is_empty (&hciReadPktPool) == FALSE){ 00168 00169 /* enqueueing a packet for read */ 00170 list_remove_head (&hciReadPktPool, (tListNode **)&hciReadPacket); 00171 #ifdef POOL_CNT 00172 nr_hciReadPktPool--; 00173 if(nr_hciReadPktPool < lowest_nr_hciReadPktPool) 00174 lowest_nr_hciReadPktPool = nr_hciReadPktPool; 00175 #endif 00176 00177 data_len = BlueNRG_SPI_Read_All(hciReadPacket->dataBuff, HCI_READ_PACKET_SIZE); 00178 if(data_len > 0){ 00179 hciReadPacket->data_len = data_len; 00180 if(HCI_verify(hciReadPacket) == 0) { 00181 list_insert_tail(&hciReadPktRxQueue, (tListNode *)hciReadPacket); 00182 signalEventsToProcess(); 00183 } else { 00184 list_insert_head(&hciReadPktPool, (tListNode *)hciReadPacket); 00185 #ifdef POOL_CNT 00186 nr_hciReadPktPool++; 00187 #endif 00188 } 00189 } 00190 else { 00191 // Insert the packet back into the pool. 00192 list_insert_head(&hciReadPktPool, (tListNode *)hciReadPacket); 00193 #ifdef POOL_CNT 00194 nr_hciReadPktPool++; 00195 #endif 00196 } 00197 } 00198 else{ 00199 // HCI Read Packet Pool is empty, wait for a free packet. 00200 signalEventsToProcess(); 00201 readPacketListFull = TRUE; 00202 Clear_SPI_EXTI_Flag(); 00203 return; 00204 } 00205 Clear_SPI_EXTI_Flag(); 00206 } 00207 } 00208 00209 void hci_write(const void* data1, const void* data2, uint8_t n_bytes1, uint8_t n_bytes2){ 00210 #if HCI_LOG_ON 00211 PRINTF("HCI <- "); 00212 for(int i=0; i < n_bytes1; i++) 00213 PRINTF("%02X ", *((uint8_t*)data1 + i)); 00214 for(int i=0; i < n_bytes2; i++) 00215 PRINTF("%02X ", *((uint8_t*)data2 + i)); 00216 PRINTF("\n"); 00217 #endif 00218 00219 Hal_Write_Serial(data1, data2, n_bytes1, n_bytes2); 00220 } 00221 00222 void hci_send_cmd(uint16_t ogf, uint16_t ocf, uint8_t plen, void *param) 00223 { 00224 hci_command_hdr hc; 00225 00226 hc.opcode = htobs(cmd_opcode_pack(ogf, ocf)); 00227 hc.plen= plen; 00228 00229 uint8_t header[HCI_HDR_SIZE + HCI_COMMAND_HDR_SIZE]; 00230 header[0] = HCI_COMMAND_PKT; 00231 Osal_MemCpy(header+1, &hc, sizeof(hc)); 00232 00233 hci_write(header, param, sizeof(header), plen); 00234 } 00235 00236 static void move_list(tListNode * dest_list, tListNode * src_list) 00237 { 00238 pListNode tmp_node; 00239 00240 while(!list_is_empty(src_list)){ 00241 list_remove_head(src_list, &tmp_node); 00242 list_insert_tail(dest_list, tmp_node); 00243 } 00244 } 00245 00246 int hci_send_req(struct hci_request *r, BOOL async) 00247 { 00248 uint8_t *ptr; 00249 uint16_t opcode = htobs(cmd_opcode_pack(r->ogf, r->ocf)); 00250 hci_event_pckt *event_pckt; 00251 hci_uart_pckt *hci_hdr; 00252 int to = DEFAULT_TIMEOUT; 00253 struct timer t; 00254 tHciDataPacket * hciReadPacket = NULL; 00255 tListNode hciTempQueue; 00256 00257 list_init_head(&hciTempQueue); 00258 00259 hci_send_cmd(r->ogf, r->ocf, r->clen, r->cparam); 00260 00261 if(async){ 00262 goto done; 00263 } 00264 00265 /* Minimum timeout is 1. */ 00266 if(to == 0) 00267 to = 1; 00268 00269 Timer_Set(&t, to); 00270 00271 while(1) { 00272 evt_cmd_complete *cc; 00273 evt_cmd_status *cs; 00274 evt_le_meta_event *me; 00275 int len; 00276 00277 #if ENABLE_MICRO_SLEEP 00278 while(1){ 00279 ATOMIC_SECTION_BEGIN(); 00280 if(Timer_Expired(&t)){ 00281 ATOMIC_SECTION_END(); 00282 goto failed; 00283 } 00284 if(!HCI_Queue_Empty()){ 00285 ATOMIC_SECTION_END(); 00286 break; 00287 } 00288 Enter_Sleep_Mode(); 00289 ATOMIC_SECTION_END(); 00290 } 00291 #else 00292 while(1){ 00293 if(Timer_Expired(&t)){ 00294 goto failed; 00295 } 00296 if(!HCI_Queue_Empty()){ 00297 break; 00298 } 00299 } 00300 #endif 00301 00302 /* Extract packet from HCI event queue. */ 00303 Disable_SPI_IRQ(); 00304 list_remove_head(&hciReadPktRxQueue, (tListNode **)&hciReadPacket); 00305 00306 hci_hdr = (void *)hciReadPacket->dataBuff; 00307 if(hci_hdr->type != HCI_EVENT_PKT){ 00308 list_insert_tail(&hciTempQueue, (tListNode *)hciReadPacket); // See comment below 00309 Enable_SPI_IRQ(); 00310 continue; 00311 } 00312 00313 event_pckt = (void *) (hci_hdr->data); 00314 00315 ptr = hciReadPacket->dataBuff + (1 + HCI_EVENT_HDR_SIZE); 00316 len = hciReadPacket->data_len - (1 + HCI_EVENT_HDR_SIZE); 00317 00318 switch (event_pckt->evt) { 00319 00320 case EVT_CMD_STATUS: 00321 cs = (void *) ptr; 00322 00323 if (cs->opcode != opcode) 00324 goto failed; 00325 00326 if (r->event != EVT_CMD_STATUS) { 00327 if (cs->status) { 00328 goto failed; 00329 } 00330 break; 00331 } 00332 00333 r->rlen = MIN(len, r->rlen); 00334 Osal_MemCpy(r->rparam, ptr, r->rlen); 00335 goto done; 00336 00337 case EVT_CMD_COMPLETE: 00338 cc = (void *) ptr; 00339 00340 if (cc->opcode != opcode) 00341 goto failed; 00342 00343 ptr += EVT_CMD_COMPLETE_SIZE; 00344 len -= EVT_CMD_COMPLETE_SIZE; 00345 00346 r->rlen = MIN(len, r->rlen); 00347 Osal_MemCpy(r->rparam, ptr, r->rlen); 00348 goto done; 00349 00350 case EVT_LE_META_EVENT: 00351 me = (void *) ptr; 00352 00353 if (me->subevent != r->event) 00354 break; 00355 00356 len -= 1; 00357 r->rlen = MIN(len, r->rlen); 00358 Osal_MemCpy(r->rparam, me->data, r->rlen); 00359 goto done; 00360 00361 case EVT_HARDWARE_ERROR: 00362 goto failed; 00363 00364 default: 00365 break; 00366 } 00367 00368 /* In the meantime there could be other events from the controller. 00369 In this case, insert the packet in a different queue. These packets will be 00370 inserted back in the main queue just before exiting from send_req(). 00371 */ 00372 if(hciReadPacket != NULL) { 00373 list_insert_tail(&hciTempQueue, (tListNode *)hciReadPacket); 00374 hciReadPacket = NULL; 00375 } 00376 /* Be sure there is at list one packet in the pool to process the expected event. */ 00377 if(list_is_empty(&hciReadPktPool)){ // betzw: this is a kind of steeling (should never happen?!?) 00378 pListNode tmp_node; 00379 list_remove_head(&hciReadPktRxQueue, &tmp_node); 00380 list_insert_tail(&hciReadPktPool, tmp_node); 00381 #ifdef POOL_CNT 00382 nr_hciReadPktPool++; 00383 #endif 00384 } 00385 00386 Enable_SPI_IRQ(); 00387 00388 } 00389 00390 failed: 00391 // Insert the packet back into the pool. 00392 if(hciReadPacket != NULL) { 00393 list_insert_head(&hciReadPktPool, (tListNode *)hciReadPacket); 00394 #ifdef POOL_CNT 00395 nr_hciReadPktPool++; 00396 #endif 00397 hciReadPacket = NULL; 00398 } 00399 move_list(&hciReadPktRxQueue, &hciTempQueue); 00400 Enable_SPI_IRQ(); 00401 return -1; 00402 00403 done: 00404 // Insert the packet back into the pool. 00405 if(hciReadPacket != NULL) { 00406 list_insert_head(&hciReadPktPool, (tListNode *)hciReadPacket); 00407 #ifdef POOL_CNT 00408 nr_hciReadPktPool++; 00409 #endif 00410 hciReadPacket = NULL; 00411 } 00412 move_list(&hciReadPktRxQueue, &hciTempQueue); 00413 00414 Enable_SPI_IRQ(); 00415 return 0; 00416 } 00417 00418 int hci_reset() 00419 { 00420 struct hci_request rq; 00421 uint8_t status; 00422 00423 Osal_MemSet(&rq, 0, sizeof(rq)); 00424 rq.ogf = OGF_HOST_CTL; 00425 rq.ocf = OCF_RESET; 00426 rq.rparam = &status; 00427 rq.rlen = 1; 00428 00429 if (hci_send_req(&rq, FALSE) < 0) 00430 return BLE_STATUS_TIMEOUT; 00431 00432 return status; 00433 } 00434 00435 int hci_disconnect(uint16_t handle, uint8_t reason) 00436 { 00437 struct hci_request rq; 00438 disconnect_cp cp; 00439 uint8_t status; 00440 00441 cp.handle = handle; 00442 cp.reason = reason; 00443 00444 Osal_MemSet(&rq, 0, sizeof(rq)); 00445 rq.ogf = OGF_LINK_CTL; 00446 rq.ocf = OCF_DISCONNECT; 00447 rq.cparam = &cp; 00448 rq.clen = DISCONNECT_CP_SIZE; 00449 rq.event = EVT_CMD_STATUS; 00450 rq.rparam = &status; 00451 rq.rlen = 1; 00452 00453 if (hci_send_req(&rq, FALSE) < 0) 00454 return BLE_STATUS_TIMEOUT; 00455 00456 return status; 00457 } 00458 00459 int hci_le_read_local_version(uint8_t *hci_version, uint16_t *hci_revision, uint8_t *lmp_pal_version, 00460 uint16_t *manufacturer_name, uint16_t *lmp_pal_subversion) 00461 { 00462 struct hci_request rq; 00463 read_local_version_rp resp; 00464 00465 Osal_MemSet(&resp, 0, sizeof(resp)); 00466 00467 Osal_MemSet(&rq, 0, sizeof(rq)); 00468 rq.ogf = OGF_INFO_PARAM; 00469 rq.ocf = OCF_READ_LOCAL_VERSION; 00470 rq.cparam = NULL; 00471 rq.clen = 0; 00472 rq.rparam = &resp; 00473 rq.rlen = READ_LOCAL_VERSION_RP_SIZE; 00474 00475 if (hci_send_req(&rq, FALSE) < 0) 00476 return BLE_STATUS_TIMEOUT; 00477 00478 if (resp.status) { 00479 return resp.status; 00480 } 00481 00482 00483 *hci_version = resp.hci_version; 00484 *hci_revision = btohs(resp.hci_revision); 00485 *lmp_pal_version = resp.lmp_pal_version; 00486 *manufacturer_name = btohs(resp.manufacturer_name); 00487 *lmp_pal_subversion = btohs(resp.lmp_pal_subversion); 00488 00489 return 0; 00490 } 00491 00492 int hci_le_read_buffer_size(uint16_t *pkt_len, uint8_t *max_pkt) 00493 { 00494 struct hci_request rq; 00495 le_read_buffer_size_rp resp; 00496 00497 Osal_MemSet(&resp, 0, sizeof(resp)); 00498 00499 Osal_MemSet(&rq, 0, sizeof(rq)); 00500 rq.ogf = OGF_LE_CTL; 00501 rq.ocf = OCF_LE_READ_BUFFER_SIZE; 00502 rq.cparam = NULL; 00503 rq.clen = 0; 00504 rq.rparam = &resp; 00505 rq.rlen = LE_READ_BUFFER_SIZE_RP_SIZE; 00506 00507 if (hci_send_req(&rq, FALSE) < 0) 00508 return BLE_STATUS_TIMEOUT; 00509 00510 if (resp.status) { 00511 return resp.status; 00512 } 00513 00514 *pkt_len = resp.pkt_len; 00515 *max_pkt = resp.max_pkt; 00516 00517 return 0; 00518 } 00519 00520 int hci_le_set_advertising_parameters(uint16_t min_interval, uint16_t max_interval, uint8_t advtype, 00521 uint8_t own_bdaddr_type, uint8_t direct_bdaddr_type, const tBDAddr direct_bdaddr, uint8_t chan_map, 00522 uint8_t filter) 00523 { 00524 struct hci_request rq; 00525 le_set_adv_parameters_cp adv_cp; 00526 uint8_t status; 00527 00528 Osal_MemSet(&adv_cp, 0, sizeof(adv_cp)); 00529 adv_cp.min_interval = min_interval; 00530 adv_cp.max_interval = max_interval; 00531 adv_cp.advtype = advtype; 00532 adv_cp.own_bdaddr_type = own_bdaddr_type; 00533 adv_cp.direct_bdaddr_type = direct_bdaddr_type; 00534 if(direct_bdaddr != NULL) 00535 Osal_MemCpy(adv_cp.direct_bdaddr,direct_bdaddr,sizeof(adv_cp.direct_bdaddr)); 00536 adv_cp.chan_map = chan_map; 00537 adv_cp.filter = filter; 00538 00539 Osal_MemSet(&rq, 0, sizeof(rq)); 00540 rq.ogf = OGF_LE_CTL; 00541 rq.ocf = OCF_LE_SET_ADV_PARAMETERS; 00542 rq.cparam = &adv_cp; 00543 rq.clen = LE_SET_ADV_PARAMETERS_CP_SIZE; 00544 rq.rparam = &status; 00545 rq.rlen = 1; 00546 00547 if (hci_send_req(&rq, FALSE) < 0) 00548 return BLE_STATUS_TIMEOUT; 00549 00550 return status; 00551 } 00552 00553 int hci_le_set_advertising_data(uint8_t length, const uint8_t data[]) 00554 { 00555 struct hci_request rq; 00556 le_set_adv_data_cp adv_cp; 00557 uint8_t status; 00558 00559 Osal_MemSet(&adv_cp, 0, sizeof(adv_cp)); 00560 adv_cp.length = length; 00561 Osal_MemCpy(adv_cp.data, data, MIN(31,length)); 00562 00563 Osal_MemSet(&rq, 0, sizeof(rq)); 00564 rq.ogf = OGF_LE_CTL; 00565 rq.ocf = OCF_LE_SET_ADV_DATA; 00566 rq.cparam = &adv_cp; 00567 rq.clen = LE_SET_ADV_DATA_CP_SIZE; 00568 rq.rparam = &status; 00569 rq.rlen = 1; 00570 00571 if (hci_send_req(&rq, FALSE) < 0) 00572 return BLE_STATUS_TIMEOUT; 00573 00574 return status; 00575 } 00576 00577 int hci_le_set_advertise_enable(uint8_t enable) 00578 { 00579 struct hci_request rq; 00580 le_set_advertise_enable_cp adv_cp; 00581 uint8_t status; 00582 00583 Osal_MemSet(&adv_cp, 0, sizeof(adv_cp)); 00584 adv_cp.enable = enable?1:0; 00585 00586 Osal_MemSet(&rq, 0, sizeof(rq)); 00587 rq.ogf = OGF_LE_CTL; 00588 rq.ocf = OCF_LE_SET_ADVERTISE_ENABLE; 00589 rq.cparam = &adv_cp; 00590 rq.clen = LE_SET_ADVERTISE_ENABLE_CP_SIZE; 00591 rq.rparam = &status; 00592 rq.rlen = 1; 00593 00594 if (hci_send_req(&rq, FALSE) < 0) 00595 return BLE_STATUS_TIMEOUT; 00596 00597 return status; 00598 } 00599 00600 int hci_le_set_scan_parameters(uint8_t type, uint16_t interval, 00601 uint16_t window, uint8_t own_bdaddr_type, 00602 uint8_t filter) 00603 { 00604 struct hci_request rq; 00605 le_set_scan_parameters_cp scan_cp; 00606 uint8_t status; 00607 00608 Osal_MemSet(&scan_cp, 0, sizeof(scan_cp)); 00609 scan_cp.type = type; 00610 scan_cp.interval = interval; 00611 scan_cp.window = window; 00612 scan_cp.own_bdaddr_type = own_bdaddr_type; 00613 scan_cp.filter = filter; 00614 00615 Osal_MemSet(&rq, 0, sizeof(rq)); 00616 rq.ogf = OGF_LE_CTL; 00617 rq.ocf = OCF_LE_SET_SCAN_PARAMETERS; 00618 rq.cparam = &scan_cp; 00619 rq.clen = LE_SET_SCAN_PARAMETERS_CP_SIZE; 00620 rq.rparam = &status; 00621 rq.rlen = 1; 00622 00623 if (hci_send_req(&rq, FALSE) < 0) 00624 return BLE_STATUS_TIMEOUT; 00625 00626 return status; 00627 } 00628 00629 int hci_le_set_scan_enable(uint8_t enable, uint8_t filter_dup) 00630 { 00631 struct hci_request rq; 00632 le_set_scan_enable_cp scan_cp; 00633 uint8_t status; 00634 00635 Osal_MemSet(&scan_cp, 0, sizeof(scan_cp)); 00636 scan_cp.enable = enable?1:0; 00637 scan_cp.filter_dup = filter_dup; 00638 00639 Osal_MemSet(&rq, 0, sizeof(rq)); 00640 rq.ogf = OGF_LE_CTL; 00641 rq.ocf = OCF_LE_SET_SCAN_ENABLE; 00642 rq.cparam = &scan_cp; 00643 rq.clen = LE_SET_SCAN_ENABLE_CP_SIZE; 00644 rq.rparam = &status; 00645 rq.rlen = 1; 00646 00647 if (hci_send_req(&rq, FALSE) < 0) 00648 return BLE_STATUS_TIMEOUT; 00649 00650 return status; 00651 } 00652 00653 int hci_le_rand(uint8_t random_number[8]) 00654 { 00655 struct hci_request rq; 00656 le_rand_rp resp; 00657 00658 Osal_MemSet(&resp, 0, sizeof(resp)); 00659 00660 Osal_MemSet(&rq, 0, sizeof(rq)); 00661 rq.ogf = OGF_LE_CTL; 00662 rq.ocf = OCF_LE_RAND; 00663 rq.cparam = NULL; 00664 rq.clen = 0; 00665 rq.rparam = &resp; 00666 rq.rlen = LE_RAND_RP_SIZE; 00667 00668 if (hci_send_req(&rq, FALSE) < 0) 00669 return BLE_STATUS_TIMEOUT; 00670 00671 if (resp.status) { 00672 return resp.status; 00673 } 00674 00675 Osal_MemCpy(random_number, resp.random, 8); 00676 00677 return 0; 00678 } 00679 00680 int hci_le_set_scan_resp_data(uint8_t length, const uint8_t data[]) 00681 { 00682 struct hci_request rq; 00683 le_set_scan_response_data_cp scan_resp_cp; 00684 uint8_t status; 00685 00686 Osal_MemSet(&scan_resp_cp, 0, sizeof(scan_resp_cp)); 00687 scan_resp_cp.length = length; 00688 Osal_MemCpy(scan_resp_cp.data, data, MIN(31,length)); 00689 00690 Osal_MemSet(&rq, 0, sizeof(rq)); 00691 rq.ogf = OGF_LE_CTL; 00692 rq.ocf = OCF_LE_SET_SCAN_RESPONSE_DATA; 00693 rq.cparam = &scan_resp_cp; 00694 rq.clen = LE_SET_SCAN_RESPONSE_DATA_CP_SIZE; 00695 rq.rparam = &status; 00696 rq.rlen = 1; 00697 00698 if (hci_send_req(&rq, FALSE) < 0) 00699 return BLE_STATUS_TIMEOUT; 00700 00701 return status; 00702 } 00703 00704 int hci_le_read_advertising_channel_tx_power(int8_t *tx_power_level) 00705 { 00706 struct hci_request rq; 00707 le_read_adv_channel_tx_power_rp resp; 00708 00709 Osal_MemSet(&resp, 0, sizeof(resp)); 00710 00711 Osal_MemSet(&rq, 0, sizeof(rq)); 00712 rq.ogf = OGF_LE_CTL; 00713 rq.ocf = OCF_LE_READ_ADV_CHANNEL_TX_POWER; 00714 rq.cparam = NULL; 00715 rq.clen = 0; 00716 rq.rparam = &resp; 00717 rq.rlen = LE_RAND_RP_SIZE; 00718 00719 if (hci_send_req(&rq, FALSE) < 0) 00720 return BLE_STATUS_TIMEOUT; 00721 00722 if (resp.status) { 00723 return resp.status; 00724 } 00725 00726 *tx_power_level = resp.level; 00727 00728 return 0; 00729 } 00730 00731 int hci_le_set_random_address(tBDAddr bdaddr) 00732 { 00733 struct hci_request rq; 00734 le_set_random_address_cp set_rand_addr_cp; 00735 uint8_t status; 00736 00737 Osal_MemSet(&set_rand_addr_cp, 0, sizeof(set_rand_addr_cp)); 00738 Osal_MemCpy(set_rand_addr_cp.bdaddr, bdaddr, sizeof(tBDAddr)); 00739 00740 Osal_MemSet(&rq, 0, sizeof(rq)); 00741 rq.ogf = OGF_LE_CTL; 00742 rq.ocf = OCF_LE_SET_RANDOM_ADDRESS; 00743 rq.cparam = &set_rand_addr_cp; 00744 rq.clen = LE_SET_RANDOM_ADDRESS_CP_SIZE; 00745 rq.rparam = &status; 00746 rq.rlen = 1; 00747 00748 if (hci_send_req(&rq, FALSE) < 0) 00749 return BLE_STATUS_TIMEOUT; 00750 00751 return status; 00752 } 00753 00754 int hci_read_bd_addr(tBDAddr bdaddr) 00755 { 00756 struct hci_request rq; 00757 read_bd_addr_rp resp; 00758 00759 Osal_MemSet(&resp, 0, sizeof(resp)); 00760 00761 Osal_MemSet(&rq, 0, sizeof(rq)); 00762 rq.ogf = OGF_INFO_PARAM; 00763 rq.ocf = OCF_READ_BD_ADDR; 00764 rq.cparam = NULL; 00765 rq.clen = 0; 00766 rq.rparam = &resp; 00767 rq.rlen = READ_BD_ADDR_RP_SIZE; 00768 00769 if (hci_send_req(&rq, FALSE) < 0) 00770 return BLE_STATUS_TIMEOUT; 00771 00772 if (resp.status) { 00773 return resp.status; 00774 } 00775 Osal_MemCpy(bdaddr, resp.bdaddr, sizeof(tBDAddr)); 00776 00777 return 0; 00778 } 00779 00780 int hci_le_create_connection(uint16_t interval, uint16_t window, uint8_t initiator_filter, uint8_t peer_bdaddr_type, 00781 const tBDAddr peer_bdaddr, uint8_t own_bdaddr_type, uint16_t min_interval, uint16_t max_interval, 00782 uint16_t latency, uint16_t supervision_timeout, uint16_t min_ce_length, uint16_t max_ce_length) 00783 { 00784 struct hci_request rq; 00785 le_create_connection_cp create_cp; 00786 uint8_t status; 00787 00788 Osal_MemSet(&create_cp, 0, sizeof(create_cp)); 00789 create_cp.interval = interval; 00790 create_cp.window = window; 00791 create_cp.initiator_filter = initiator_filter; 00792 create_cp.peer_bdaddr_type = peer_bdaddr_type; 00793 Osal_MemCpy(create_cp.peer_bdaddr, peer_bdaddr, sizeof(tBDAddr)); 00794 create_cp.own_bdaddr_type = own_bdaddr_type; 00795 create_cp.min_interval=min_interval; 00796 create_cp.max_interval=max_interval; 00797 create_cp.latency = latency; 00798 create_cp.supervision_timeout=supervision_timeout; 00799 create_cp.min_ce_length=min_ce_length; 00800 create_cp.max_ce_length=max_ce_length; 00801 00802 Osal_MemSet(&rq, 0, sizeof(rq)); 00803 rq.ogf = OGF_LE_CTL; 00804 rq.ocf = OCF_LE_CREATE_CONN; 00805 rq.cparam = &create_cp; 00806 rq.clen = LE_CREATE_CONN_CP_SIZE; 00807 rq.event = EVT_CMD_STATUS; 00808 rq.rparam = &status; 00809 rq.rlen = 1; 00810 00811 if (hci_send_req(&rq, FALSE) < 0) 00812 return BLE_STATUS_TIMEOUT; 00813 00814 return status; 00815 } 00816 00817 int hci_le_create_connection_cancel(void) 00818 { 00819 struct hci_request rq; 00820 uint8_t status; 00821 00822 Osal_MemSet(&rq, 0, sizeof(rq)); 00823 rq.ogf = OGF_LE_CTL; 00824 rq.ocf = OCF_LE_CREATE_CONN_CANCEL; 00825 rq.rparam = &status; 00826 rq.rlen = 1; 00827 00828 if (hci_send_req(&rq, FALSE) < 0) 00829 return BLE_STATUS_TIMEOUT; 00830 00831 return status; 00832 } 00833 00834 int hci_le_encrypt(uint8_t key[16], uint8_t plaintextData[16], uint8_t encryptedData[16]) 00835 { 00836 struct hci_request rq; 00837 le_encrypt_cp params; 00838 le_encrypt_rp resp; 00839 00840 Osal_MemSet(&resp, 0, sizeof(resp)); 00841 00842 Osal_MemCpy(params.key, key, 16); 00843 Osal_MemCpy(params.plaintext, plaintextData, 16); 00844 00845 Osal_MemSet(&rq, 0, sizeof(rq)); 00846 rq.ogf = OGF_LE_CTL; 00847 rq.ocf = OCF_LE_ENCRYPT; 00848 rq.cparam = ¶ms; 00849 rq.clen = LE_ENCRYPT_CP_SIZE; 00850 rq.rparam = &resp; 00851 rq.rlen = LE_ENCRYPT_RP_SIZE; 00852 00853 if (hci_send_req(&rq, FALSE) < 0){ 00854 return BLE_STATUS_TIMEOUT; 00855 } 00856 00857 if (resp.status) { 00858 return resp.status; 00859 } 00860 00861 Osal_MemCpy(encryptedData, resp.encdata, 16); 00862 00863 return 0; 00864 } 00865 00866 int hci_le_ltk_request_reply(uint8_t key[16]) 00867 { 00868 struct hci_request rq; 00869 le_ltk_reply_cp params; 00870 le_ltk_reply_rp resp; 00871 00872 Osal_MemSet(&resp, 0, sizeof(resp)); 00873 00874 params.handle = 1; 00875 Osal_MemCpy(params.key, key, 16); 00876 00877 Osal_MemSet(&rq, 0, sizeof(rq)); 00878 rq.ogf = OGF_LE_CTL; 00879 rq.ocf = OCF_LE_LTK_REPLY; 00880 rq.cparam = ¶ms; 00881 rq.clen = LE_LTK_REPLY_CP_SIZE; 00882 rq.rparam = &resp; 00883 rq.rlen = LE_LTK_REPLY_RP_SIZE; 00884 00885 if (hci_send_req(&rq, FALSE) < 0) 00886 return BLE_STATUS_TIMEOUT; 00887 00888 return resp.status; 00889 } 00890 00891 int hci_le_ltk_request_neg_reply() 00892 { 00893 struct hci_request rq; 00894 le_ltk_neg_reply_cp params; 00895 le_ltk_neg_reply_rp resp; 00896 00897 Osal_MemSet(&resp, 0, sizeof(resp)); 00898 00899 params.handle = 1; 00900 00901 Osal_MemSet(&rq, 0, sizeof(rq)); 00902 rq.ogf = OGF_LE_CTL; 00903 rq.ocf = OCF_LE_LTK_NEG_REPLY; 00904 rq.cparam = ¶ms; 00905 rq.clen = LE_LTK_NEG_REPLY_CP_SIZE; 00906 rq.rparam = &resp; 00907 rq.rlen = LE_LTK_NEG_REPLY_RP_SIZE; 00908 00909 if (hci_send_req(&rq, FALSE) < 0) 00910 return BLE_STATUS_TIMEOUT; 00911 00912 return resp.status; 00913 } 00914 00915 int hci_le_read_white_list_size(uint8_t *size) 00916 { 00917 struct hci_request rq; 00918 le_read_white_list_size_rp resp; 00919 00920 Osal_MemSet(&resp, 0, sizeof(resp)); 00921 00922 Osal_MemSet(&rq, 0, sizeof(rq)); 00923 rq.ogf = OGF_LE_CTL; 00924 rq.ocf = OCF_LE_READ_WHITE_LIST_SIZE; 00925 rq.rparam = &resp; 00926 rq.rlen = LE_READ_WHITE_LIST_SIZE_RP_SIZE; 00927 00928 if (hci_send_req(&rq, FALSE) < 0){ 00929 return BLE_STATUS_TIMEOUT; 00930 } 00931 00932 if (resp.status) { 00933 return resp.status; 00934 } 00935 00936 *size = resp.size; 00937 00938 return 0; 00939 } 00940 00941 int hci_le_clear_white_list() 00942 { 00943 struct hci_request rq; 00944 uint8_t status; 00945 00946 Osal_MemSet(&rq, 0, sizeof(rq)); 00947 rq.ogf = OGF_LE_CTL; 00948 rq.ocf = OCF_LE_CLEAR_WHITE_LIST; 00949 rq.rparam = &status; 00950 rq.rlen = 1; 00951 00952 if (hci_send_req(&rq, FALSE) < 0){ 00953 return BLE_STATUS_TIMEOUT; 00954 } 00955 00956 return status; 00957 } 00958 00959 int hci_le_add_device_to_white_list(uint8_t bdaddr_type, tBDAddr bdaddr) 00960 { 00961 struct hci_request rq; 00962 le_add_device_to_white_list_cp params; 00963 uint8_t status; 00964 00965 params.bdaddr_type = bdaddr_type; 00966 Osal_MemCpy(params.bdaddr, bdaddr, 6); 00967 00968 Osal_MemSet(&rq, 0, sizeof(rq)); 00969 rq.ogf = OGF_LE_CTL; 00970 rq.ocf = OCF_LE_ADD_DEVICE_TO_WHITE_LIST; 00971 rq.cparam = ¶ms; 00972 rq.clen = LE_ADD_DEVICE_TO_WHITE_LIST_CP_SIZE; 00973 rq.rparam = &status; 00974 rq.rlen = 1; 00975 00976 if (hci_send_req(&rq, FALSE) < 0){ 00977 return BLE_STATUS_TIMEOUT; 00978 } 00979 00980 return status; 00981 } 00982 00983 int hci_le_remove_device_from_white_list(uint8_t bdaddr_type, tBDAddr bdaddr) 00984 { 00985 struct hci_request rq; 00986 le_remove_device_from_white_list_cp params; 00987 uint8_t status; 00988 00989 params.bdaddr_type = bdaddr_type; 00990 Osal_MemCpy(params.bdaddr, bdaddr, 6); 00991 00992 Osal_MemSet(&rq, 0, sizeof(rq)); 00993 rq.ogf = OGF_LE_CTL; 00994 rq.ocf = OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST; 00995 rq.cparam = ¶ms; 00996 rq.clen = LE_REMOVE_DEVICE_FROM_WHITE_LIST_CP_SIZE; 00997 rq.rparam = &status; 00998 rq.rlen = 1; 00999 01000 if (hci_send_req(&rq, FALSE) < 0){ 01001 return BLE_STATUS_TIMEOUT; 01002 } 01003 01004 return status; 01005 } 01006 01007 int hci_read_transmit_power_level(uint16_t *conn_handle, uint8_t type, int8_t * tx_level) 01008 { 01009 struct hci_request rq; 01010 read_transmit_power_level_cp params; 01011 read_transmit_power_level_rp resp; 01012 01013 Osal_MemSet(&resp, 0, sizeof(resp)); 01014 01015 params.handle = *conn_handle; 01016 params.type = type; 01017 01018 Osal_MemSet(&rq, 0, sizeof(rq)); 01019 rq.ogf = OGF_HOST_CTL; 01020 rq.ocf = OCF_READ_TRANSMIT_POWER_LEVEL; 01021 rq.cparam = ¶ms; 01022 rq.clen = READ_TRANSMIT_POWER_LEVEL_CP_SIZE; 01023 rq.rparam = &resp; 01024 rq.rlen = READ_TRANSMIT_POWER_LEVEL_RP_SIZE; 01025 01026 if (hci_send_req(&rq, FALSE) < 0){ 01027 return BLE_STATUS_TIMEOUT; 01028 } 01029 01030 if (resp.status) { 01031 return resp.status; 01032 } 01033 01034 *conn_handle = resp.handle; 01035 *tx_level = resp.level; 01036 01037 return 0; 01038 } 01039 01040 int hci_read_rssi(uint16_t *conn_handle, int8_t * rssi) 01041 { 01042 struct hci_request rq; 01043 read_rssi_cp params; 01044 read_rssi_rp resp; 01045 01046 Osal_MemSet(&resp, 0, sizeof(resp)); 01047 01048 params.handle = *conn_handle; 01049 01050 Osal_MemSet(&rq, 0, sizeof(rq)); 01051 rq.ogf = OGF_STATUS_PARAM; 01052 rq.ocf = OCF_READ_RSSI; 01053 rq.cparam = ¶ms; 01054 rq.clen = READ_RSSI_CP_SIZE; 01055 rq.rparam = &resp; 01056 rq.rlen = READ_RSSI_RP_SIZE; 01057 01058 if (hci_send_req(&rq, FALSE) < 0){ 01059 return BLE_STATUS_TIMEOUT; 01060 } 01061 01062 if (resp.status) { 01063 return resp.status; 01064 } 01065 01066 *conn_handle = resp.handle; 01067 *rssi = resp.rssi; 01068 01069 return 0; 01070 } 01071 01072 int hci_le_read_local_supported_features(uint8_t *features) 01073 { 01074 struct hci_request rq; 01075 le_read_local_supported_features_rp resp; 01076 01077 Osal_MemSet(&resp, 0, sizeof(resp)); 01078 01079 Osal_MemSet(&rq, 0, sizeof(rq)); 01080 rq.ogf = OGF_LE_CTL; 01081 rq.ocf = OCF_LE_READ_LOCAL_SUPPORTED_FEATURES; 01082 rq.rparam = &resp; 01083 rq.rlen = LE_READ_LOCAL_SUPPORTED_FEATURES_RP_SIZE; 01084 01085 if (hci_send_req(&rq, FALSE) < 0){ 01086 return BLE_STATUS_TIMEOUT; 01087 } 01088 01089 if (resp.status) { 01090 return resp.status; 01091 } 01092 01093 Osal_MemCpy(features, resp.features, sizeof(resp.features)); 01094 01095 return 0; 01096 } 01097 01098 int hci_le_read_channel_map(uint16_t conn_handle, uint8_t ch_map[5]) 01099 { 01100 struct hci_request rq; 01101 le_read_channel_map_cp params; 01102 le_read_channel_map_rp resp; 01103 01104 Osal_MemSet(&resp, 0, sizeof(resp)); 01105 01106 params.handle = conn_handle; 01107 01108 Osal_MemSet(&rq, 0, sizeof(rq)); 01109 rq.ogf = OGF_LE_CTL; 01110 rq.ocf = OCF_LE_READ_CHANNEL_MAP; 01111 rq.cparam = ¶ms; 01112 rq.clen = LE_READ_CHANNEL_MAP_CP_SIZE; 01113 rq.rparam = &resp; 01114 rq.rlen = LE_READ_CHANNEL_MAP_RP_SIZE; 01115 01116 if (hci_send_req(&rq, FALSE) < 0){ 01117 return BLE_STATUS_TIMEOUT; 01118 } 01119 01120 if (resp.status) { 01121 return resp.status; 01122 } 01123 01124 Osal_MemCpy(ch_map, resp.map, 5); 01125 01126 return 0; 01127 } 01128 01129 int hci_le_read_supported_states(uint8_t states[8]) 01130 { 01131 struct hci_request rq; 01132 le_read_supported_states_rp resp; 01133 01134 Osal_MemSet(&resp, 0, sizeof(resp)); 01135 01136 Osal_MemSet(&rq, 0, sizeof(rq)); 01137 rq.ogf = OGF_LE_CTL; 01138 rq.ocf = OCF_LE_READ_SUPPORTED_STATES; 01139 rq.rparam = &resp; 01140 rq.rlen = LE_READ_SUPPORTED_STATES_RP_SIZE; 01141 01142 if (hci_send_req(&rq, FALSE) < 0){ 01143 return BLE_STATUS_TIMEOUT; 01144 } 01145 01146 if (resp.status) { 01147 return resp.status; 01148 } 01149 01150 Osal_MemCpy(states, resp.states, 8); 01151 01152 return 0; 01153 } 01154 01155 int hci_le_receiver_test(uint8_t frequency) 01156 { 01157 struct hci_request rq; 01158 le_receiver_test_cp params; 01159 uint8_t status; 01160 01161 params.frequency = frequency; 01162 01163 Osal_MemSet(&rq, 0, sizeof(rq)); 01164 rq.ogf = OGF_LE_CTL; 01165 rq.ocf = OCF_LE_RECEIVER_TEST; 01166 rq.cparam = ¶ms; 01167 rq.clen = LE_RECEIVER_TEST_CP_SIZE; 01168 rq.rparam = &status; 01169 rq.rlen = 1; 01170 01171 if (hci_send_req(&rq, FALSE) < 0){ 01172 return BLE_STATUS_TIMEOUT; 01173 } 01174 01175 return status; 01176 } 01177 01178 int hci_le_transmitter_test(uint8_t frequency, uint8_t length, uint8_t payload) 01179 { 01180 struct hci_request rq; 01181 le_transmitter_test_cp params; 01182 uint8_t status; 01183 01184 params.frequency = frequency; 01185 params.length = length; 01186 params.payload = payload; 01187 01188 Osal_MemSet(&rq, 0, sizeof(rq)); 01189 rq.ogf = OGF_LE_CTL; 01190 rq.ocf = OCF_LE_TRANSMITTER_TEST; 01191 rq.cparam = ¶ms; 01192 rq.clen = LE_TRANSMITTER_TEST_CP_SIZE; 01193 rq.rparam = &status; 01194 rq.rlen = 1; 01195 01196 if (hci_send_req(&rq, FALSE) < 0){ 01197 return BLE_STATUS_TIMEOUT; 01198 } 01199 01200 return status; 01201 } 01202 01203 int hci_le_test_end(uint16_t *num_pkts) 01204 { 01205 struct hci_request rq; 01206 le_test_end_rp resp; 01207 01208 Osal_MemSet(&resp, 0, sizeof(resp)); 01209 01210 Osal_MemSet(&rq, 0, sizeof(rq)); 01211 rq.ogf = OGF_LE_CTL; 01212 rq.ocf = OCF_LE_TEST_END; 01213 rq.rparam = &resp; 01214 rq.rlen = LE_TEST_END_RP_SIZE; 01215 01216 if (hci_send_req(&rq, FALSE) < 0){ 01217 return BLE_STATUS_TIMEOUT; 01218 } 01219 01220 if (resp.status) { 01221 return resp.status; 01222 } 01223 01224 *num_pkts = resp.num_pkts; 01225 01226 return 0; 01227 }
Generated on Tue Jul 12 2022 18:15:59 by 1.7.2