gjhn

Dependents:   BLE_GENERALE

Fork of X_NUCLEO_IDB0XA1 by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ble_hci.c Source File

ble_hci.c

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