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