Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 Thu Jul 14 2022 09:39:26 by
1.7.2
