BLE shield

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