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 Osal_MemCpy(adv_cp.direct_bdaddr,direct_bdaddr,sizeof(adv_cp.direct_bdaddr)); 00539 adv_cp.chan_map = chan_map; 00540 adv_cp.filter = filter; 00541 00542 Osal_MemSet(&rq, 0, sizeof(rq)); 00543 rq.ogf = OGF_LE_CTL; 00544 rq.ocf = OCF_LE_SET_ADV_PARAMETERS; 00545 rq.cparam = &adv_cp; 00546 rq.clen = LE_SET_ADV_PARAMETERS_CP_SIZE; 00547 rq.rparam = &status; 00548 rq.rlen = 1; 00549 00550 if (hci_send_req(&rq, FALSE) < 0) 00551 return BLE_STATUS_TIMEOUT; 00552 00553 return status; 00554 } 00555 00556 int hci_le_set_advertising_data(uint8_t length, const uint8_t data[]) 00557 { 00558 struct hci_request rq; 00559 le_set_adv_data_cp adv_cp; 00560 uint8_t status; 00561 00562 Osal_MemSet(&adv_cp, 0, sizeof(adv_cp)); 00563 adv_cp.length = length; 00564 Osal_MemCpy(adv_cp.data, data, MIN(31,length)); 00565 00566 Osal_MemSet(&rq, 0, sizeof(rq)); 00567 rq.ogf = OGF_LE_CTL; 00568 rq.ocf = OCF_LE_SET_ADV_DATA; 00569 rq.cparam = &adv_cp; 00570 rq.clen = LE_SET_ADV_DATA_CP_SIZE; 00571 rq.rparam = &status; 00572 rq.rlen = 1; 00573 00574 if (hci_send_req(&rq, FALSE) < 0) 00575 return BLE_STATUS_TIMEOUT; 00576 00577 return status; 00578 } 00579 00580 int hci_le_set_advertise_enable(uint8_t enable) 00581 { 00582 struct hci_request rq; 00583 le_set_advertise_enable_cp adv_cp; 00584 uint8_t status; 00585 00586 Osal_MemSet(&adv_cp, 0, sizeof(adv_cp)); 00587 adv_cp.enable = enable?1:0; 00588 00589 Osal_MemSet(&rq, 0, sizeof(rq)); 00590 rq.ogf = OGF_LE_CTL; 00591 rq.ocf = OCF_LE_SET_ADVERTISE_ENABLE; 00592 rq.cparam = &adv_cp; 00593 rq.clen = LE_SET_ADVERTISE_ENABLE_CP_SIZE; 00594 rq.rparam = &status; 00595 rq.rlen = 1; 00596 00597 if (hci_send_req(&rq, FALSE) < 0) 00598 return BLE_STATUS_TIMEOUT; 00599 00600 return status; 00601 } 00602 00603 int hci_le_set_scan_parameters(uint8_t type, uint16_t interval, 00604 uint16_t window, uint8_t own_bdaddr_type, 00605 uint8_t filter) 00606 { 00607 struct hci_request rq; 00608 le_set_scan_parameters_cp scan_cp; 00609 uint8_t status; 00610 00611 Osal_MemSet(&scan_cp, 0, sizeof(scan_cp)); 00612 scan_cp.type = type; 00613 scan_cp.interval = interval; 00614 scan_cp.window = window; 00615 scan_cp.own_bdaddr_type = own_bdaddr_type; 00616 scan_cp.filter = filter; 00617 00618 Osal_MemSet(&rq, 0, sizeof(rq)); 00619 rq.ogf = OGF_LE_CTL; 00620 rq.ocf = OCF_LE_SET_SCAN_PARAMETERS; 00621 rq.cparam = &scan_cp; 00622 rq.clen = LE_SET_SCAN_PARAMETERS_CP_SIZE; 00623 rq.rparam = &status; 00624 rq.rlen = 1; 00625 00626 if (hci_send_req(&rq, FALSE) < 0) 00627 return BLE_STATUS_TIMEOUT; 00628 00629 return status; 00630 } 00631 00632 int hci_le_set_scan_enable(uint8_t enable, uint8_t filter_dup) 00633 { 00634 struct hci_request rq; 00635 le_set_scan_enable_cp scan_cp; 00636 uint8_t status; 00637 00638 Osal_MemSet(&scan_cp, 0, sizeof(scan_cp)); 00639 scan_cp.enable = enable?1:0; 00640 scan_cp.filter_dup = filter_dup; 00641 00642 Osal_MemSet(&rq, 0, sizeof(rq)); 00643 rq.ogf = OGF_LE_CTL; 00644 rq.ocf = OCF_LE_SET_SCAN_ENABLE; 00645 rq.cparam = &scan_cp; 00646 rq.clen = LE_SET_SCAN_ENABLE_CP_SIZE; 00647 rq.rparam = &status; 00648 rq.rlen = 1; 00649 00650 if (hci_send_req(&rq, FALSE) < 0) 00651 return BLE_STATUS_TIMEOUT; 00652 00653 return status; 00654 } 00655 00656 int hci_le_rand(uint8_t random_number[8]) 00657 { 00658 struct hci_request rq; 00659 le_rand_rp resp; 00660 00661 Osal_MemSet(&resp, 0, sizeof(resp)); 00662 00663 Osal_MemSet(&rq, 0, sizeof(rq)); 00664 rq.ogf = OGF_LE_CTL; 00665 rq.ocf = OCF_LE_RAND; 00666 rq.cparam = NULL; 00667 rq.clen = 0; 00668 rq.rparam = &resp; 00669 rq.rlen = LE_RAND_RP_SIZE; 00670 00671 if (hci_send_req(&rq, FALSE) < 0) 00672 return BLE_STATUS_TIMEOUT; 00673 00674 if (resp.status) { 00675 return resp.status; 00676 } 00677 00678 Osal_MemCpy(random_number, resp.random, 8); 00679 00680 return 0; 00681 } 00682 00683 int hci_le_set_scan_resp_data(uint8_t length, const uint8_t data[]) 00684 { 00685 struct hci_request rq; 00686 le_set_scan_response_data_cp scan_resp_cp; 00687 uint8_t status; 00688 00689 Osal_MemSet(&scan_resp_cp, 0, sizeof(scan_resp_cp)); 00690 scan_resp_cp.length = length; 00691 Osal_MemCpy(scan_resp_cp.data, data, MIN(31,length)); 00692 00693 Osal_MemSet(&rq, 0, sizeof(rq)); 00694 rq.ogf = OGF_LE_CTL; 00695 rq.ocf = OCF_LE_SET_SCAN_RESPONSE_DATA; 00696 rq.cparam = &scan_resp_cp; 00697 rq.clen = LE_SET_SCAN_RESPONSE_DATA_CP_SIZE; 00698 rq.rparam = &status; 00699 rq.rlen = 1; 00700 00701 if (hci_send_req(&rq, FALSE) < 0) 00702 return BLE_STATUS_TIMEOUT; 00703 00704 return status; 00705 } 00706 00707 int hci_le_read_advertising_channel_tx_power(int8_t *tx_power_level) 00708 { 00709 struct hci_request rq; 00710 le_read_adv_channel_tx_power_rp resp; 00711 00712 Osal_MemSet(&resp, 0, sizeof(resp)); 00713 00714 Osal_MemSet(&rq, 0, sizeof(rq)); 00715 rq.ogf = OGF_LE_CTL; 00716 rq.ocf = OCF_LE_READ_ADV_CHANNEL_TX_POWER; 00717 rq.cparam = NULL; 00718 rq.clen = 0; 00719 rq.rparam = &resp; 00720 rq.rlen = LE_RAND_RP_SIZE; 00721 00722 if (hci_send_req(&rq, FALSE) < 0) 00723 return BLE_STATUS_TIMEOUT; 00724 00725 if (resp.status) { 00726 return resp.status; 00727 } 00728 00729 *tx_power_level = resp.level; 00730 00731 return 0; 00732 } 00733 00734 int hci_le_set_random_address(tBDAddr bdaddr) 00735 { 00736 struct hci_request rq; 00737 le_set_random_address_cp set_rand_addr_cp; 00738 uint8_t status; 00739 00740 Osal_MemSet(&set_rand_addr_cp, 0, sizeof(set_rand_addr_cp)); 00741 Osal_MemCpy(set_rand_addr_cp.bdaddr, bdaddr, sizeof(tBDAddr)); 00742 00743 Osal_MemSet(&rq, 0, sizeof(rq)); 00744 rq.ogf = OGF_LE_CTL; 00745 rq.ocf = OCF_LE_SET_RANDOM_ADDRESS; 00746 rq.cparam = &set_rand_addr_cp; 00747 rq.clen = LE_SET_RANDOM_ADDRESS_CP_SIZE; 00748 rq.rparam = &status; 00749 rq.rlen = 1; 00750 00751 if (hci_send_req(&rq, FALSE) < 0) 00752 return BLE_STATUS_TIMEOUT; 00753 00754 return status; 00755 } 00756 00757 int hci_read_bd_addr(tBDAddr bdaddr) 00758 { 00759 struct hci_request rq; 00760 read_bd_addr_rp resp; 00761 00762 Osal_MemSet(&resp, 0, sizeof(resp)); 00763 00764 Osal_MemSet(&rq, 0, sizeof(rq)); 00765 rq.ogf = OGF_INFO_PARAM; 00766 rq.ocf = OCF_READ_BD_ADDR; 00767 rq.cparam = NULL; 00768 rq.clen = 0; 00769 rq.rparam = &resp; 00770 rq.rlen = READ_BD_ADDR_RP_SIZE; 00771 00772 if (hci_send_req(&rq, FALSE) < 0) 00773 return BLE_STATUS_TIMEOUT; 00774 00775 if (resp.status) { 00776 return resp.status; 00777 } 00778 Osal_MemCpy(bdaddr, resp.bdaddr, sizeof(tBDAddr)); 00779 00780 return 0; 00781 } 00782 00783 int hci_le_create_connection(uint16_t interval, uint16_t window, uint8_t initiator_filter, uint8_t peer_bdaddr_type, 00784 const tBDAddr peer_bdaddr, uint8_t own_bdaddr_type, uint16_t min_interval, uint16_t max_interval, 00785 uint16_t latency, uint16_t supervision_timeout, uint16_t min_ce_length, uint16_t max_ce_length) 00786 { 00787 struct hci_request rq; 00788 le_create_connection_cp create_cp; 00789 uint8_t status; 00790 00791 Osal_MemSet(&create_cp, 0, sizeof(create_cp)); 00792 create_cp.interval = interval; 00793 create_cp.window = window; 00794 create_cp.initiator_filter = initiator_filter; 00795 create_cp.peer_bdaddr_type = peer_bdaddr_type; 00796 Osal_MemCpy(create_cp.peer_bdaddr, peer_bdaddr, sizeof(tBDAddr)); 00797 create_cp.own_bdaddr_type = own_bdaddr_type; 00798 create_cp.min_interval=min_interval; 00799 create_cp.max_interval=max_interval; 00800 create_cp.latency = latency; 00801 create_cp.supervision_timeout=supervision_timeout; 00802 create_cp.min_ce_length=min_ce_length; 00803 create_cp.max_ce_length=max_ce_length; 00804 00805 Osal_MemSet(&rq, 0, sizeof(rq)); 00806 rq.ogf = OGF_LE_CTL; 00807 rq.ocf = OCF_LE_CREATE_CONN; 00808 rq.cparam = &create_cp; 00809 rq.clen = LE_CREATE_CONN_CP_SIZE; 00810 rq.event = EVT_CMD_STATUS; 00811 rq.rparam = &status; 00812 rq.rlen = 1; 00813 00814 if (hci_send_req(&rq, FALSE) < 0) 00815 return BLE_STATUS_TIMEOUT; 00816 00817 return status; 00818 } 00819 00820 int hci_le_encrypt(uint8_t key[16], uint8_t plaintextData[16], uint8_t encryptedData[16]) 00821 { 00822 struct hci_request rq; 00823 le_encrypt_cp params; 00824 le_encrypt_rp resp; 00825 00826 Osal_MemSet(&resp, 0, sizeof(resp)); 00827 00828 Osal_MemCpy(params.key, key, 16); 00829 Osal_MemCpy(params.plaintext, plaintextData, 16); 00830 00831 Osal_MemSet(&rq, 0, sizeof(rq)); 00832 rq.ogf = OGF_LE_CTL; 00833 rq.ocf = OCF_LE_ENCRYPT; 00834 rq.cparam = ¶ms; 00835 rq.clen = LE_ENCRYPT_CP_SIZE; 00836 rq.rparam = &resp; 00837 rq.rlen = LE_ENCRYPT_RP_SIZE; 00838 00839 if (hci_send_req(&rq, FALSE) < 0){ 00840 return BLE_STATUS_TIMEOUT; 00841 } 00842 00843 if (resp.status) { 00844 return resp.status; 00845 } 00846 00847 Osal_MemCpy(encryptedData, resp.encdata, 16); 00848 00849 return 0; 00850 } 00851 00852 int hci_le_ltk_request_reply(uint8_t key[16]) 00853 { 00854 struct hci_request rq; 00855 le_ltk_reply_cp params; 00856 le_ltk_reply_rp resp; 00857 00858 Osal_MemSet(&resp, 0, sizeof(resp)); 00859 00860 params.handle = 1; 00861 Osal_MemCpy(params.key, key, 16); 00862 00863 Osal_MemSet(&rq, 0, sizeof(rq)); 00864 rq.ogf = OGF_LE_CTL; 00865 rq.ocf = OCF_LE_LTK_REPLY; 00866 rq.cparam = ¶ms; 00867 rq.clen = LE_LTK_REPLY_CP_SIZE; 00868 rq.rparam = &resp; 00869 rq.rlen = LE_LTK_REPLY_RP_SIZE; 00870 00871 if (hci_send_req(&rq, FALSE) < 0) 00872 return BLE_STATUS_TIMEOUT; 00873 00874 return resp.status; 00875 } 00876 00877 int hci_le_ltk_request_neg_reply() 00878 { 00879 struct hci_request rq; 00880 le_ltk_neg_reply_cp params; 00881 le_ltk_neg_reply_rp resp; 00882 00883 Osal_MemSet(&resp, 0, sizeof(resp)); 00884 00885 params.handle = 1; 00886 00887 Osal_MemSet(&rq, 0, sizeof(rq)); 00888 rq.ogf = OGF_LE_CTL; 00889 rq.ocf = OCF_LE_LTK_NEG_REPLY; 00890 rq.cparam = ¶ms; 00891 rq.clen = LE_LTK_NEG_REPLY_CP_SIZE; 00892 rq.rparam = &resp; 00893 rq.rlen = LE_LTK_NEG_REPLY_RP_SIZE; 00894 00895 if (hci_send_req(&rq, FALSE) < 0) 00896 return BLE_STATUS_TIMEOUT; 00897 00898 return resp.status; 00899 } 00900 00901 int hci_le_read_white_list_size(uint8_t *size) 00902 { 00903 struct hci_request rq; 00904 le_read_white_list_size_rp resp; 00905 00906 Osal_MemSet(&resp, 0, sizeof(resp)); 00907 00908 Osal_MemSet(&rq, 0, sizeof(rq)); 00909 rq.ogf = OGF_LE_CTL; 00910 rq.ocf = OCF_LE_READ_WHITE_LIST_SIZE; 00911 rq.rparam = &resp; 00912 rq.rlen = LE_READ_WHITE_LIST_SIZE_RP_SIZE; 00913 00914 if (hci_send_req(&rq, FALSE) < 0){ 00915 return BLE_STATUS_TIMEOUT; 00916 } 00917 00918 if (resp.status) { 00919 return resp.status; 00920 } 00921 00922 *size = resp.size; 00923 00924 return 0; 00925 } 00926 00927 int hci_le_clear_white_list() 00928 { 00929 struct hci_request rq; 00930 uint8_t status; 00931 00932 Osal_MemSet(&rq, 0, sizeof(rq)); 00933 rq.ogf = OGF_LE_CTL; 00934 rq.ocf = OCF_LE_CLEAR_WHITE_LIST; 00935 rq.rparam = &status; 00936 rq.rlen = 1; 00937 00938 if (hci_send_req(&rq, FALSE) < 0){ 00939 return BLE_STATUS_TIMEOUT; 00940 } 00941 00942 return status; 00943 } 00944 00945 int hci_le_add_device_to_white_list(uint8_t bdaddr_type, tBDAddr bdaddr) 00946 { 00947 struct hci_request rq; 00948 le_add_device_to_white_list_cp params; 00949 uint8_t status; 00950 00951 params.bdaddr_type = bdaddr_type; 00952 Osal_MemCpy(params.bdaddr, bdaddr, 6); 00953 00954 Osal_MemSet(&rq, 0, sizeof(rq)); 00955 rq.ogf = OGF_LE_CTL; 00956 rq.ocf = OCF_LE_ADD_DEVICE_TO_WHITE_LIST; 00957 rq.cparam = ¶ms; 00958 rq.clen = LE_ADD_DEVICE_TO_WHITE_LIST_CP_SIZE; 00959 rq.rparam = &status; 00960 rq.rlen = 1; 00961 00962 if (hci_send_req(&rq, FALSE) < 0){ 00963 return BLE_STATUS_TIMEOUT; 00964 } 00965 00966 return status; 00967 } 00968 00969 int hci_le_remove_device_from_white_list(uint8_t bdaddr_type, tBDAddr bdaddr) 00970 { 00971 struct hci_request rq; 00972 le_remove_device_from_white_list_cp params; 00973 uint8_t status; 00974 00975 params.bdaddr_type = bdaddr_type; 00976 Osal_MemCpy(params.bdaddr, bdaddr, 6); 00977 00978 Osal_MemSet(&rq, 0, sizeof(rq)); 00979 rq.ogf = OGF_LE_CTL; 00980 rq.ocf = OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST; 00981 rq.cparam = ¶ms; 00982 rq.clen = LE_REMOVE_DEVICE_FROM_WHITE_LIST_CP_SIZE; 00983 rq.rparam = &status; 00984 rq.rlen = 1; 00985 00986 if (hci_send_req(&rq, FALSE) < 0){ 00987 return BLE_STATUS_TIMEOUT; 00988 } 00989 00990 return status; 00991 } 00992 00993 int hci_read_transmit_power_level(uint16_t *conn_handle, uint8_t type, int8_t * tx_level) 00994 { 00995 struct hci_request rq; 00996 read_transmit_power_level_cp params; 00997 read_transmit_power_level_rp resp; 00998 00999 Osal_MemSet(&resp, 0, sizeof(resp)); 01000 01001 params.handle = *conn_handle; 01002 params.type = type; 01003 01004 Osal_MemSet(&rq, 0, sizeof(rq)); 01005 rq.ogf = OGF_HOST_CTL; 01006 rq.ocf = OCF_READ_TRANSMIT_POWER_LEVEL; 01007 rq.cparam = ¶ms; 01008 rq.clen = READ_TRANSMIT_POWER_LEVEL_CP_SIZE; 01009 rq.rparam = &resp; 01010 rq.rlen = READ_TRANSMIT_POWER_LEVEL_RP_SIZE; 01011 01012 if (hci_send_req(&rq, FALSE) < 0){ 01013 return BLE_STATUS_TIMEOUT; 01014 } 01015 01016 if (resp.status) { 01017 return resp.status; 01018 } 01019 01020 *conn_handle = resp.handle; 01021 *tx_level = resp.level; 01022 01023 return 0; 01024 } 01025 01026 int hci_read_rssi(uint16_t *conn_handle, int8_t * rssi) 01027 { 01028 struct hci_request rq; 01029 read_rssi_cp params; 01030 read_rssi_rp resp; 01031 01032 Osal_MemSet(&resp, 0, sizeof(resp)); 01033 01034 params.handle = *conn_handle; 01035 01036 Osal_MemSet(&rq, 0, sizeof(rq)); 01037 rq.ogf = OGF_STATUS_PARAM; 01038 rq.ocf = OCF_READ_RSSI; 01039 rq.cparam = ¶ms; 01040 rq.clen = READ_RSSI_CP_SIZE; 01041 rq.rparam = &resp; 01042 rq.rlen = READ_RSSI_RP_SIZE; 01043 01044 if (hci_send_req(&rq, FALSE) < 0){ 01045 return BLE_STATUS_TIMEOUT; 01046 } 01047 01048 if (resp.status) { 01049 return resp.status; 01050 } 01051 01052 *conn_handle = resp.handle; 01053 *rssi = resp.rssi; 01054 01055 return 0; 01056 } 01057 01058 int hci_le_read_local_supported_features(uint8_t *features) 01059 { 01060 struct hci_request rq; 01061 le_read_local_supported_features_rp resp; 01062 01063 Osal_MemSet(&resp, 0, sizeof(resp)); 01064 01065 Osal_MemSet(&rq, 0, sizeof(rq)); 01066 rq.ogf = OGF_LE_CTL; 01067 rq.ocf = OCF_LE_READ_LOCAL_SUPPORTED_FEATURES; 01068 rq.rparam = &resp; 01069 rq.rlen = LE_READ_LOCAL_SUPPORTED_FEATURES_RP_SIZE; 01070 01071 if (hci_send_req(&rq, FALSE) < 0){ 01072 return BLE_STATUS_TIMEOUT; 01073 } 01074 01075 if (resp.status) { 01076 return resp.status; 01077 } 01078 01079 Osal_MemCpy(features, resp.features, sizeof(resp.features)); 01080 01081 return 0; 01082 } 01083 01084 int hci_le_read_channel_map(uint16_t conn_handle, uint8_t ch_map[5]) 01085 { 01086 struct hci_request rq; 01087 le_read_channel_map_cp params; 01088 le_read_channel_map_rp resp; 01089 01090 Osal_MemSet(&resp, 0, sizeof(resp)); 01091 01092 params.handle = conn_handle; 01093 01094 Osal_MemSet(&rq, 0, sizeof(rq)); 01095 rq.ogf = OGF_LE_CTL; 01096 rq.ocf = OCF_LE_READ_CHANNEL_MAP; 01097 rq.cparam = ¶ms; 01098 rq.clen = LE_READ_CHANNEL_MAP_CP_SIZE; 01099 rq.rparam = &resp; 01100 rq.rlen = LE_READ_CHANNEL_MAP_RP_SIZE; 01101 01102 if (hci_send_req(&rq, FALSE) < 0){ 01103 return BLE_STATUS_TIMEOUT; 01104 } 01105 01106 if (resp.status) { 01107 return resp.status; 01108 } 01109 01110 Osal_MemCpy(ch_map, resp.map, 5); 01111 01112 return 0; 01113 } 01114 01115 int hci_le_read_supported_states(uint8_t states[8]) 01116 { 01117 struct hci_request rq; 01118 le_read_supported_states_rp resp; 01119 01120 Osal_MemSet(&resp, 0, sizeof(resp)); 01121 01122 Osal_MemSet(&rq, 0, sizeof(rq)); 01123 rq.ogf = OGF_LE_CTL; 01124 rq.ocf = OCF_LE_READ_SUPPORTED_STATES; 01125 rq.rparam = &resp; 01126 rq.rlen = LE_READ_SUPPORTED_STATES_RP_SIZE; 01127 01128 if (hci_send_req(&rq, FALSE) < 0){ 01129 return BLE_STATUS_TIMEOUT; 01130 } 01131 01132 if (resp.status) { 01133 return resp.status; 01134 } 01135 01136 Osal_MemCpy(states, resp.states, 8); 01137 01138 return 0; 01139 } 01140 01141 int hci_le_receiver_test(uint8_t frequency) 01142 { 01143 struct hci_request rq; 01144 le_receiver_test_cp params; 01145 uint8_t status; 01146 01147 params.frequency = frequency; 01148 01149 Osal_MemSet(&rq, 0, sizeof(rq)); 01150 rq.ogf = OGF_LE_CTL; 01151 rq.ocf = OCF_LE_RECEIVER_TEST; 01152 rq.cparam = ¶ms; 01153 rq.clen = LE_RECEIVER_TEST_CP_SIZE; 01154 rq.rparam = &status; 01155 rq.rlen = 1; 01156 01157 if (hci_send_req(&rq, FALSE) < 0){ 01158 return BLE_STATUS_TIMEOUT; 01159 } 01160 01161 return status; 01162 } 01163 01164 int hci_le_transmitter_test(uint8_t frequency, uint8_t length, uint8_t payload) 01165 { 01166 struct hci_request rq; 01167 le_transmitter_test_cp params; 01168 uint8_t status; 01169 01170 params.frequency = frequency; 01171 params.length = length; 01172 params.payload = payload; 01173 01174 Osal_MemSet(&rq, 0, sizeof(rq)); 01175 rq.ogf = OGF_LE_CTL; 01176 rq.ocf = OCF_LE_TRANSMITTER_TEST; 01177 rq.cparam = ¶ms; 01178 rq.clen = LE_TRANSMITTER_TEST_CP_SIZE; 01179 rq.rparam = &status; 01180 rq.rlen = 1; 01181 01182 if (hci_send_req(&rq, FALSE) < 0){ 01183 return BLE_STATUS_TIMEOUT; 01184 } 01185 01186 return status; 01187 } 01188 01189 int hci_le_test_end(uint16_t *num_pkts) 01190 { 01191 struct hci_request rq; 01192 le_test_end_rp resp; 01193 01194 Osal_MemSet(&resp, 0, sizeof(resp)); 01195 01196 Osal_MemSet(&rq, 0, sizeof(rq)); 01197 rq.ogf = OGF_LE_CTL; 01198 rq.ocf = OCF_LE_TEST_END; 01199 rq.rparam = &resp; 01200 rq.rlen = LE_TEST_END_RP_SIZE; 01201 01202 if (hci_send_req(&rq, FALSE) < 0){ 01203 return BLE_STATUS_TIMEOUT; 01204 } 01205 01206 if (resp.status) { 01207 return resp.status; 01208 } 01209 01210 *num_pkts = resp.num_pkts; 01211 01212 return 0; 01213 } 01214
Generated on Tue Jul 12 2022 19:27:29 by
1.7.2
