Devchannel Team / X_NUCLEO_IDB0XA1

Dependents:   Hello_BLE F446RE-BLE

Fork of X_NUCLEO_IDB0XA1 by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers hci.c Source File

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>&copy; 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 = &params;
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 = &params;
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 = &params;
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 = &params;
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 = &params;
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 = &params;
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 = &params;
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 = &params;
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 = &params;
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 = &params;
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