BLE shield
Fork of X_NUCLEO_IDB0XA1 by
Embed:
(wiki syntax)
Show/hide line numbers
hci.c
Go to the documentation of this file.
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