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