project

Fork of X_NUCLEO_IDB0XA1 by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers hci_dma_lp.c Source File

hci_dma_lp.c

Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    hci_dma_lp.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 // ANDREA -- FIXME: to exclude from building when DMA is disabled
00020 #ifdef __DMA_LP__
00021 
00022 #include "hal_types.h"
00023 #include "osal.h"
00024 #include "ble_status.h"
00025 #include "hal.h"
00026 #include "hci_const.h"
00027 #include "gp_timer.h"
00028 
00029 #include "bluenrg_interface.h"
00030 #include "stm32xx_timerserver.h"
00031 
00032 extern SPI_HandleTypeDef SpiHandle;
00033 
00034 #if BLE_CONFIG_DBG_ENABLE
00035 #define PRINTF(...) printf(__VA_ARGS__)
00036 #else
00037 #define PRINTF(...)
00038 #endif
00039 
00040 #define HCI_LOG_ON 0
00041 
00042 #define HCI_READ_PACKET_NUM_MAX          (5)
00043 
00044 #define MIN(a,b)            ((a) < (b) )? (a) : (b)
00045 #define MAX(a,b)            ((a) > (b) )? (a) : (b)
00046 
00047 static void enqueue_packet(tHciDataPacket * hciReadPacket);
00048 static void hci_timeout_callback(void);
00049 
00050 tListNode hciReadPktPool;
00051 tListNode hciReadPktRxQueue;
00052 /* pool of hci read packets */
00053 static tHciDataPacket     hciReadPacketBuffer[HCI_READ_PACKET_NUM_MAX];
00054 
00055 static volatile uint8_t readPacketListFull=FALSE;
00056 
00057 static uint8_t *hci_buffer = NULL;
00058 static volatile uint16_t hci_pckt_len;
00059 static volatile uint8_t hci_timer_id;
00060 static volatile uint8_t hci_timeout;
00061 
00062 uint8_t header[HCI_HDR_SIZE + HCI_COMMAND_HDR_SIZE];
00063 
00064 void hci_timeout_callback(void)
00065 {
00066     hci_timeout = 1;
00067 
00068     return;
00069 }
00070 
00071 void HCI_Init(void)
00072 {
00073     uint8_t index;
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     }
00084 }
00085 
00086 #define HCI_PCK_TYPE_OFFSET                 0
00087 #define  EVENT_PARAMETER_TOT_LEN_OFFSET     2
00088 
00089 void Hal_Init_Event_Request(void)
00090 {  
00091   tHciDataPacket * hciReadPacket = NULL;
00092   
00093   list_remove_head (&hciReadPktPool, (tListNode **)&hciReadPacket);
00094   
00095   Hal_Event_Request ((uint8_t*)hciReadPacket, HCI_READ_PACKET_SIZE);
00096 }
00097 
00098 static volatile hci_packet_complete_callback packet_complete_callback = NULL;
00099 
00100 static void hci_set_packet_complete_callback(hci_packet_complete_callback cb)
00101 {
00102     packet_complete_callback = cb;
00103 }
00104 
00105 void HCI_Input(tHciDataPacket * hciReadPacket)
00106 {
00107     uint8_t byte;
00108     hci_acl_hdr *acl_hdr;
00109 
00110     static hci_state state = WAITING_TYPE;
00111 
00112         uint16_t collected_payload_len = 0;
00113     uint16_t payload_len;
00114     
00115     hci_buffer = hciReadPacket->dataBuff;
00116     
00117     if(state == WAITING_TYPE)
00118         hci_pckt_len = 0;
00119     
00120     while(hci_pckt_len < HCI_READ_PACKET_SIZE){
00121 
00122         byte = hci_buffer[hci_pckt_len++];
00123 
00124         if(state == WAITING_TYPE){
00125             /* Only ACL Data and Events packets are accepted. */
00126             if(byte == HCI_EVENT_PKT){
00127                  state = WAITING_EVENT_CODE;
00128             }
00129 //            else if(byte == HCI_ACLDATA_PKT){
00130 //                state = WAITING_HANDLE;
00131 //            }
00132             else{
00133                 /* Incorrect type. Reset state machine. */
00134                 state = WAITING_TYPE;
00135                 break;
00136             }
00137         }
00138         else if(state == WAITING_EVENT_CODE)
00139             state = WAITING_PARAM_LEN;
00140         else if(state == WAITING_HANDLE)
00141             state = WAITING_HANDLE_FLAG;
00142         else if(state == WAITING_HANDLE_FLAG)
00143             state = WAITING_DATA_LEN1;
00144         else if(state == WAITING_DATA_LEN1)
00145             state = WAITING_DATA_LEN2;
00146 
00147         else if(state == WAITING_DATA_LEN2){
00148             acl_hdr = (void *)&hci_buffer[HCI_HDR_SIZE];
00149             payload_len = acl_hdr->dlen;
00150             collected_payload_len = 0;
00151             state = WAITING_PAYLOAD;
00152         }
00153         else if(state == WAITING_PARAM_LEN){
00154              payload_len = byte;
00155              collected_payload_len = 0;
00156              state = WAITING_PAYLOAD;
00157         }
00158         else if(state == WAITING_PAYLOAD){
00159             collected_payload_len += 1;
00160             if(collected_payload_len >= payload_len){
00161                 /* Reset state machine. */
00162                 state = WAITING_TYPE;
00163                 enqueue_packet(hciReadPacket);
00164                 
00165                 if(packet_complete_callback){
00166                   uint16_t len = hci_pckt_len;
00167                   packet_complete_callback(hci_buffer, len);
00168                 }
00169                 break;
00170             }
00171         }
00172     }        
00173 }
00174 
00175 void enqueue_packet(tHciDataPacket * hciReadPacket)
00176 {
00177     hci_uart_pckt *hci_pckt = (void*)hciReadPacket->dataBuff;
00178     hci_event_pckt *event_pckt = (void*)hci_pckt->data;
00179     
00180     // Do not enqueue Command Complete or Command Status events
00181     
00182     if((hci_pckt->type != HCI_EVENT_PKT) ||
00183        event_pckt->evt == EVT_CMD_COMPLETE ||
00184            event_pckt->evt == EVT_CMD_STATUS){
00185         // Insert the packet back into the pool.
00186         list_insert_tail(&hciReadPktPool, (tListNode *)hciReadPacket);
00187     }
00188     else {    
00189         // Insert the packet into the queue of events to be processed.
00190         list_insert_tail(&hciReadPktRxQueue, (tListNode *)hciReadPacket);
00191         HCI_Process_Notification_Request();
00192     }
00193 }
00194 
00195 void HCI_Process(void)
00196 {
00197     //uint8_t data_len;
00198     //uint8_t buffer[HCI_PACKET_SIZE];
00199     tHciDataPacket * hciReadPacket = NULL;
00200 
00201     uint8_t list_empty = list_is_empty(&hciReadPktRxQueue);        
00202     /* process any pending events read */
00203     while(list_empty == FALSE)
00204     {
00205         list_remove_head (&hciReadPktRxQueue, (tListNode **)&hciReadPacket);
00206         HCI_Event_CB(hciReadPacket->dataBuff);
00207         list_insert_tail(&hciReadPktPool, (tListNode *)hciReadPacket);
00208         list_empty = list_is_empty(&hciReadPktRxQueue);
00209     }
00210 }
00211 
00212 BOOL HCI_Queue_Empty(void)
00213 {
00214   return list_is_empty(&hciReadPktRxQueue);
00215 }
00216 
00217 void HCI_Isr(uint8_t *buffer, uint8_t event_payload_len)
00218 {
00219   tHciDataPacket * hciReadPacket = NULL;
00220   
00221   if (list_is_empty (&hciReadPktPool) == FALSE){
00222     
00223     list_remove_head (&hciReadPktPool, (tListNode **)&hciReadPacket);
00224     
00225     Hal_Event_Request ((uint8_t*)hciReadPacket, HCI_READ_PACKET_SIZE);
00226   }
00227   
00228   if(event_payload_len > 0){
00229     
00230     HCI_Input((tHciDataPacket*)buffer);
00231     // Packet will be inserted to te correct queue by 
00232   }
00233   else {
00234     // Insert the packet back into the pool.
00235     list_insert_head(&hciReadPktPool, (tListNode*)buffer);
00236   }
00237 }
00238 
00239 void hci_write(const void* data1, const void* data2, uint16_t n_bytes1, uint16_t n_bytes2){
00240 #if  HCI_LOG_ON
00241   PRINTF("HCI <- ");
00242   for(int i=0; i < n_bytes1; i++)
00243     PRINTF("%02X ", *((uint8_t*)data1 + i));
00244   for(int i=0; i < n_bytes2; i++)
00245     PRINTF("%02X ", *((uint8_t*)data2 + i));
00246   PRINTF("\n");    
00247 #endif
00248   
00249   Hal_Write_Serial(data1, data2, n_bytes1, n_bytes2);
00250 }
00251 
00252 void hci_send_cmd(uint16_t ogf, uint16_t ocf, uint8_t plen, void *param)
00253 {
00254   hci_command_hdr hc;
00255   
00256   hc.opcode = htobs(cmd_opcode_pack(ogf, ocf));
00257   hc.plen= plen;
00258   
00259   //uint8_t header[HCI_HDR_SIZE + HCI_COMMAND_HDR_SIZE];
00260   header[0] = HCI_COMMAND_PKT;
00261   Osal_MemCpy(header+1, &hc, sizeof(hc));
00262   
00263   hci_write(header, param, sizeof(header), plen);
00264 }
00265 
00266 static uint8_t new_packet;
00267 
00268 void new_hci_event(void *pckt, uint16_t len)
00269 {
00270   
00271   new_packet = TRUE;
00272 }
00273 
00274 /**
00275  * FIXME: Param async is unused, it has been introduced to align the interface
00276  * to DK 1.6.0 HCI stack
00277  */
00278 /* 'to' is timeout in system clock ticks.  */
00279 int hci_send_req(struct hci_request *r, BOOL async)
00280 {
00281   uint8_t *ptr;
00282   uint16_t opcode = htobs(cmd_opcode_pack(r->ogf, r->ocf));
00283   hci_event_pckt *event_pckt;
00284   hci_uart_pckt *hci_hdr;
00285   int try;
00286   uint32_t to = DEFAULT_TIMEOUT;
00287   
00288   new_packet = FALSE;
00289   HCI_Cmd_Status(BUSY);
00290   hci_set_packet_complete_callback(new_hci_event);
00291   hci_send_cmd(r->ogf, r->ocf, r->clen, r->cparam);
00292   
00293   try = 10;
00294   while (try--) {
00295     evt_cmd_complete *cc;
00296     evt_cmd_status *cs;
00297     evt_le_meta_event *me;
00298     int len;
00299     
00300     /* Minimum timeout is 1. */
00301     if(to == 0)
00302       to = 1;
00303     
00304     hci_timeout = 0;
00305     Blue_NRG_HCI_Timer_Start(to, hci_timeout_callback, (uint8_t*)&hci_timer_id);
00306     
00307     while(1){
00308       if(hci_timeout){
00309         Blue_NRG_HCI_Timer_Stop(hci_timer_id);
00310         goto failed;
00311       }
00312       if(new_packet){
00313         Blue_NRG_HCI_Timer_Stop(hci_timer_id);
00314         break;
00315       }
00316       HCI_Wait_For_Response();
00317     }
00318     
00319     hci_hdr = (void *)hci_buffer;
00320     if(hci_hdr->type != HCI_EVENT_PKT){
00321       new_packet = FALSE;
00322       continue;
00323     }
00324     
00325     event_pckt = (void *) (hci_hdr->data);
00326     
00327     ptr = hci_buffer + (1 + HCI_EVENT_HDR_SIZE);
00328     len = hci_pckt_len - (1 + HCI_EVENT_HDR_SIZE);
00329     
00330     switch (event_pckt->evt) {
00331       
00332     case EVT_CMD_STATUS:
00333       cs = (void *) ptr;
00334       
00335       if (cs->opcode != opcode)
00336         break;
00337       
00338       if (r->event != EVT_CMD_STATUS) {
00339         if (cs->status) {
00340           goto failed;
00341         }
00342         break;
00343       }
00344       
00345       r->rlen = MIN(len, r->rlen);
00346       Osal_MemCpy(r->rparam, ptr, r->rlen);
00347       goto done;
00348       
00349     case EVT_CMD_COMPLETE:
00350       cc = (void *) ptr;
00351       
00352       if (cc->opcode != opcode)
00353         break;
00354       
00355       ptr += EVT_CMD_COMPLETE_SIZE;
00356       len -= EVT_CMD_COMPLETE_SIZE;
00357       
00358       r->rlen = MIN(len, r->rlen);
00359       Osal_MemCpy(r->rparam, ptr, r->rlen);
00360       goto done;
00361       
00362     case EVT_LE_META_EVENT:
00363       me = (void *) ptr;
00364       
00365       if (me->subevent != r->event)
00366         break;
00367       
00368       len -= 1;
00369       r->rlen = MIN(len, r->rlen);
00370       Osal_MemCpy(r->rparam, me->data, r->rlen);
00371       goto done;
00372       
00373     case EVT_HARDWARE_ERROR:            
00374       goto failed;
00375       
00376     default:
00377       break; // In the meantime there could be other events from the controller.
00378     }
00379     
00380     new_packet = FALSE;
00381     
00382   }
00383   
00384 failed:
00385   hci_set_packet_complete_callback(NULL);
00386   return -1;
00387   
00388 done:
00389   hci_set_packet_complete_callback(NULL);
00390   HCI_Cmd_Status(AVAILABLE);
00391   return 0;
00392 }
00393 
00394 int hci_reset()
00395 {
00396   struct hci_request rq;
00397   uint8_t status;
00398   
00399   Osal_MemSet(&rq, 0, sizeof(rq));
00400   rq.ogf = OGF_HOST_CTL;
00401   rq.ocf = OCF_RESET;
00402   rq.rparam = &status;
00403   rq.rlen = 1;
00404   
00405   if (hci_send_req(&rq, FALSE) < 0)
00406     return -1;
00407   
00408   if (status) {
00409     return -1;
00410   }
00411   
00412   return 0;  
00413 }
00414 
00415 int hci_disconnect(uint16_t handle, uint8_t reason)
00416 {
00417   struct hci_request rq;
00418   disconnect_cp cp;
00419   uint8_t status;
00420   
00421   cp.handle = handle;
00422   cp.reason = reason;
00423   
00424   Osal_MemSet(&rq, 0, sizeof(rq));
00425   rq.ogf = OGF_LINK_CTL;
00426   rq.ocf = OCF_DISCONNECT;
00427   rq.cparam = &cp;
00428   rq.clen = DISCONNECT_CP_SIZE;
00429   rq.event = EVT_CMD_STATUS;
00430   rq.rparam = &status;
00431   rq.rlen = 1;
00432   
00433   if (hci_send_req(&rq, FALSE) < 0)
00434     return -1;
00435   
00436   if (status) {
00437     return -1;
00438   }
00439   
00440   return 0;  
00441 }
00442 
00443 int hci_le_read_local_version(uint8_t *hci_version, uint16_t *hci_revision, uint8_t *lmp_pal_version, 
00444                   uint16_t *manufacturer_name, uint16_t *lmp_pal_subversion)
00445 {
00446   struct hci_request rq;
00447   read_local_version_rp resp;
00448   
00449   Osal_MemSet(&resp, 0, sizeof(resp));
00450   
00451   Osal_MemSet(&rq, 0, sizeof(rq));
00452   rq.ogf = OGF_INFO_PARAM;
00453   rq.ocf = OCF_READ_LOCAL_VERSION;
00454   rq.cparam = NULL;
00455   rq.clen = 0;
00456   rq.rparam = &resp;
00457   rq.rlen = READ_LOCAL_VERSION_RP_SIZE;
00458   
00459   if (hci_send_req(&rq, FALSE) < 0)
00460     return -1;
00461   
00462   if (resp.status) {
00463     return -1;
00464   }
00465   
00466   
00467   *hci_version = resp.hci_version;
00468   *hci_revision =  btohs(resp.hci_revision);
00469   *lmp_pal_version = resp.lmp_pal_version;
00470   *manufacturer_name = btohs(resp.manufacturer_name);
00471   *lmp_pal_subversion = btohs(resp.lmp_pal_subversion);
00472   
00473   return 0;
00474 }
00475 
00476 int hci_le_read_buffer_size(uint16_t *pkt_len, uint8_t *max_pkt)
00477 {
00478   struct hci_request rq;
00479   le_read_buffer_size_rp resp;
00480   
00481   Osal_MemSet(&resp, 0, sizeof(resp));
00482   
00483   Osal_MemSet(&rq, 0, sizeof(rq));
00484   rq.ogf = OGF_LE_CTL;
00485   rq.ocf = OCF_LE_READ_BUFFER_SIZE;
00486   rq.cparam = NULL;
00487   rq.clen = 0;
00488   rq.rparam = &resp;
00489   rq.rlen = LE_READ_BUFFER_SIZE_RP_SIZE;
00490   
00491   if (hci_send_req(&rq, FALSE) < 0)
00492     return -1;
00493   
00494   if (resp.status) {
00495     return -1;
00496   }
00497   
00498   *pkt_len = resp.pkt_len;
00499   *max_pkt = resp.max_pkt;
00500   
00501   return 0;
00502 }
00503 
00504 int hci_le_set_advertising_parameters(uint16_t min_interval, uint16_t max_interval, uint8_t advtype,
00505                                       uint8_t own_bdaddr_type, uint8_t direct_bdaddr_type, const tBDAddr direct_bdaddr, uint8_t chan_map,
00506                                       uint8_t filter)
00507 {
00508   struct hci_request rq;
00509   le_set_adv_parameters_cp adv_cp;
00510   uint8_t status;
00511   
00512   Osal_MemSet(&adv_cp, 0, sizeof(adv_cp));
00513   adv_cp.min_interval = min_interval;
00514   adv_cp.max_interval = max_interval;
00515   adv_cp.advtype = advtype;
00516   adv_cp.own_bdaddr_type = own_bdaddr_type;
00517   adv_cp.direct_bdaddr_type = direct_bdaddr_type;
00518   Osal_MemCpy(adv_cp.direct_bdaddr,direct_bdaddr,sizeof(adv_cp.direct_bdaddr));
00519   adv_cp.chan_map = chan_map;
00520   adv_cp.filter = filter;
00521   
00522   Osal_MemSet(&rq, 0, sizeof(rq));
00523   rq.ogf = OGF_LE_CTL;
00524   rq.ocf = OCF_LE_SET_ADV_PARAMETERS;
00525   rq.cparam = &adv_cp;
00526   rq.clen = LE_SET_ADV_PARAMETERS_CP_SIZE;
00527   rq.rparam = &status;
00528   rq.rlen = 1;
00529   
00530   if (hci_send_req(&rq, FALSE) < 0)
00531     return -1;
00532   
00533   if (status) {
00534     return -1;
00535   }
00536   
00537   return 0;
00538 }
00539 
00540 int hci_le_set_advertising_data(uint8_t length, const uint8_t data[])
00541 {
00542   struct hci_request rq;
00543   le_set_adv_data_cp adv_cp;
00544   uint8_t status;
00545   
00546   Osal_MemSet(&adv_cp, 0, sizeof(adv_cp));
00547   adv_cp.length = length;
00548   Osal_MemCpy(adv_cp.data, data, MIN(31,length));
00549   
00550   Osal_MemSet(&rq, 0, sizeof(rq));
00551   rq.ogf = OGF_LE_CTL;
00552   rq.ocf = OCF_LE_SET_ADV_DATA;
00553   rq.cparam = &adv_cp;
00554   rq.clen = LE_SET_ADV_DATA_CP_SIZE;
00555   rq.rparam = &status;
00556   rq.rlen = 1;
00557   
00558   if (hci_send_req(&rq, FALSE) < 0)
00559     return -1;
00560   
00561   if (status) {
00562     return -1;
00563   }
00564   
00565   return 0;
00566 }
00567 
00568 int hci_le_set_advertise_enable(uint8_t enable)
00569 {
00570   struct hci_request rq;
00571   le_set_advertise_enable_cp adv_cp;
00572   uint8_t status;
00573   
00574   Osal_MemSet(&adv_cp, 0, sizeof(adv_cp));
00575   adv_cp.enable = enable?1:0;
00576   
00577   Osal_MemSet(&rq, 0, sizeof(rq));
00578   rq.ogf = OGF_LE_CTL;
00579   rq.ocf = OCF_LE_SET_ADVERTISE_ENABLE;
00580   rq.cparam = &adv_cp;
00581   rq.clen = LE_SET_ADVERTISE_ENABLE_CP_SIZE;
00582   rq.rparam = &status;
00583   rq.rlen = 1;
00584   
00585   if (hci_send_req(&rq, FALSE) < 0)
00586     return -1;
00587   
00588   if (status) {
00589     return -1;
00590   }
00591   
00592   return 0;
00593 }
00594 
00595 int hci_le_rand(uint8_t random_number[8])
00596 {
00597   struct hci_request rq;
00598   le_rand_rp resp;
00599   
00600   Osal_MemSet(&resp, 0, sizeof(resp));
00601   
00602   Osal_MemSet(&rq, 0, sizeof(rq));
00603   rq.ogf = OGF_LE_CTL;
00604   rq.ocf = OCF_LE_RAND;
00605   rq.cparam = NULL;
00606   rq.clen = 0;
00607   rq.rparam = &resp;
00608   rq.rlen = LE_RAND_RP_SIZE;
00609   
00610   if (hci_send_req(&rq, FALSE) < 0)
00611     return -1;
00612   
00613   if (resp.status) {
00614     return -1;
00615   }
00616   
00617   Osal_MemCpy(random_number, resp.random, 8);
00618   
00619   return 0;
00620 }
00621 
00622 int hci_le_set_scan_resp_data(uint8_t length, const uint8_t data[])
00623 {
00624   struct hci_request rq;
00625   le_set_scan_response_data_cp scan_resp_cp;
00626   uint8_t status;
00627   
00628   Osal_MemSet(&scan_resp_cp, 0, sizeof(scan_resp_cp));
00629   scan_resp_cp.length = length;
00630   Osal_MemCpy(scan_resp_cp.data, data, MIN(31,length));
00631   
00632   Osal_MemSet(&rq, 0, sizeof(rq));
00633   rq.ogf = OGF_LE_CTL;
00634   rq.ocf = OCF_LE_SET_SCAN_RESPONSE_DATA;
00635   rq.cparam = &scan_resp_cp;
00636   rq.clen = LE_SET_SCAN_RESPONSE_DATA_CP_SIZE;
00637   rq.rparam = &status;
00638   rq.rlen = 1;
00639   
00640   if (hci_send_req(&rq, FALSE) < 0)
00641     return -1;
00642   
00643   if (status) {
00644     return -1;
00645   }
00646   
00647   return 0;
00648 }
00649 
00650 int hci_le_read_advertising_channel_tx_power(int8_t *tx_power_level)
00651 {
00652   struct hci_request rq;
00653   le_read_adv_channel_tx_power_rp resp;
00654   
00655   Osal_MemSet(&resp, 0, sizeof(resp));
00656   
00657   Osal_MemSet(&rq, 0, sizeof(rq));
00658   rq.ogf = OGF_LE_CTL;
00659   rq.ocf = OCF_LE_READ_ADV_CHANNEL_TX_POWER;
00660   rq.cparam = NULL;
00661   rq.clen = 0;
00662   rq.rparam = &resp;
00663   rq.rlen = LE_RAND_RP_SIZE;
00664   
00665   if (hci_send_req(&rq, FALSE) < 0)
00666     return -1;
00667   
00668   if (resp.status) {
00669     return -1;
00670   }
00671   
00672   *tx_power_level = resp.level;
00673   
00674   return 0;
00675 }
00676 
00677 int hci_le_set_random_address(tBDAddr bdaddr)
00678 {
00679   struct hci_request rq;
00680   le_set_random_address_cp set_rand_addr_cp;
00681   uint8_t status;
00682   
00683   Osal_MemSet(&set_rand_addr_cp, 0, sizeof(set_rand_addr_cp));
00684   Osal_MemCpy(set_rand_addr_cp.bdaddr, bdaddr, sizeof(tBDAddr));
00685   
00686   Osal_MemSet(&rq, 0, sizeof(rq));
00687   rq.ogf = OGF_LE_CTL;
00688   rq.ocf = OCF_LE_SET_RANDOM_ADDRESS;
00689   rq.cparam = &set_rand_addr_cp;
00690   rq.clen = LE_SET_RANDOM_ADDRESS_CP_SIZE;
00691   rq.rparam = &status;
00692   rq.rlen = 1;
00693   
00694   if (hci_send_req(&rq, FALSE) < 0)
00695     return -1;
00696   
00697   if (status) {
00698     return -1;
00699   }
00700   
00701   return 0;
00702 }
00703 
00704 int hci_read_bd_addr(tBDAddr bdaddr)
00705 {
00706   struct hci_request rq;
00707   read_bd_addr_rp resp;
00708   
00709   Osal_MemSet(&resp, 0, sizeof(resp));
00710   
00711   Osal_MemSet(&rq, 0, sizeof(rq));
00712   rq.ogf = OGF_INFO_PARAM;
00713   rq.ocf = OCF_READ_BD_ADDR;
00714   rq.cparam = NULL;
00715   rq.clen = 0;
00716   rq.rparam = &resp;
00717   rq.rlen = READ_BD_ADDR_RP_SIZE;
00718   
00719   if (hci_send_req(&rq, FALSE) < 0)
00720     return -1;
00721   
00722   if (resp.status) {
00723     return -1;
00724   }
00725   Osal_MemCpy(bdaddr, resp.bdaddr, sizeof(tBDAddr));
00726   
00727   return 0;
00728 }
00729 
00730 int hci_le_create_connection(uint16_t interval, uint16_t window, uint8_t initiator_filter, uint8_t peer_bdaddr_type,
00731                              const tBDAddr peer_bdaddr, uint8_t own_bdaddr_type, uint16_t min_interval, uint16_t max_interval,
00732                              uint16_t latency,  uint16_t supervision_timeout, uint16_t min_ce_length, uint16_t max_ce_length)
00733 {
00734   struct hci_request rq;
00735   le_create_connection_cp create_cp;
00736   uint8_t status;
00737   
00738   Osal_MemSet(&create_cp, 0, sizeof(create_cp));
00739   create_cp.interval = interval;
00740   create_cp.window =  window;
00741   create_cp.initiator_filter = initiator_filter;
00742   create_cp.peer_bdaddr_type = peer_bdaddr_type;
00743   Osal_MemCpy(create_cp.peer_bdaddr, peer_bdaddr, sizeof(tBDAddr));
00744   create_cp.own_bdaddr_type = own_bdaddr_type;
00745   create_cp.min_interval=min_interval;
00746   create_cp.max_interval=max_interval;
00747   create_cp.latency = latency;
00748   create_cp.supervision_timeout=supervision_timeout;
00749   create_cp.min_ce_length=min_ce_length;
00750   create_cp.max_ce_length=max_ce_length;
00751   
00752   Osal_MemSet(&rq, 0, sizeof(rq));
00753   rq.ogf = OGF_LE_CTL;
00754   rq.ocf = OCF_LE_CREATE_CONN;
00755   rq.cparam = &create_cp;
00756   rq.clen = LE_CREATE_CONN_CP_SIZE;
00757   rq.event = EVT_CMD_STATUS;
00758   rq.rparam = &status;
00759   rq.rlen = 1;
00760   
00761   if (hci_send_req(&rq, FALSE) < 0)
00762     return -1;
00763   
00764   if (status) {
00765     return -1;
00766   }
00767   
00768   return 0;
00769 }
00770 
00771 int hci_le_encrypt(uint8_t key[16], uint8_t plaintextData[16], uint8_t encryptedData[16])
00772 {
00773   struct hci_request rq;
00774   le_encrypt_cp params;
00775   le_encrypt_rp resp;
00776   
00777   Osal_MemSet(&resp, 0, sizeof(resp));
00778   
00779   Osal_MemCpy(params.key, key, 16);
00780   Osal_MemCpy(params.plaintext, plaintextData, 16);
00781   
00782   Osal_MemSet(&rq, 0, sizeof(rq));
00783   rq.ogf = OGF_LE_CTL;
00784   rq.ocf = OCF_LE_ENCRYPT;
00785   rq.cparam = &params;
00786   rq.clen = LE_ENCRYPT_CP_SIZE;
00787   rq.rparam = &resp;
00788   rq.rlen = LE_ENCRYPT_RP_SIZE;
00789   
00790   if (hci_send_req(&rq, FALSE) < 0){
00791     return -1;
00792   }
00793   
00794   if (resp.status) {
00795     return -1;
00796   }
00797   
00798   Osal_MemCpy(encryptedData, resp.encdata, 16);
00799   
00800   return 0;
00801 }
00802 
00803 int hci_le_ltk_request_reply(uint8_t key[16])
00804 {
00805   struct hci_request rq;
00806   le_ltk_reply_cp params;
00807   le_ltk_reply_rp resp;
00808   
00809   Osal_MemSet(&resp, 0, sizeof(resp));
00810   
00811   params.handle = 1;
00812   Osal_MemCpy(params.key, key, 16);
00813   
00814   Osal_MemSet(&rq, 0, sizeof(rq));
00815   rq.ogf = OGF_LE_CTL;
00816   rq.ocf = OCF_LE_LTK_REPLY;
00817   rq.cparam = &params;
00818   rq.clen = LE_LTK_REPLY_CP_SIZE;
00819   rq.rparam = &resp;
00820   rq.rlen = LE_LTK_REPLY_RP_SIZE;
00821   
00822   if (hci_send_req(&rq, FALSE) < 0)
00823     return -1;
00824   
00825   if (resp.status) {
00826     return -1;
00827   }
00828   
00829   return 0;
00830 }
00831 
00832 int hci_le_ltk_request_neg_reply()
00833 {
00834   struct hci_request rq;
00835   le_ltk_neg_reply_cp params;
00836   le_ltk_neg_reply_rp resp;
00837   
00838   Osal_MemSet(&resp, 0, sizeof(resp));
00839   
00840   params.handle = 1;
00841   
00842   Osal_MemSet(&rq, 0, sizeof(rq));
00843   rq.ogf = OGF_LE_CTL;
00844   rq.ocf = OCF_LE_LTK_NEG_REPLY;
00845   rq.cparam = &params;
00846   rq.clen = LE_LTK_NEG_REPLY_CP_SIZE;
00847   rq.rparam = &resp;
00848   rq.rlen = LE_LTK_NEG_REPLY_RP_SIZE;
00849   
00850   if (hci_send_req(&rq, FALSE) < 0)
00851     return -1;
00852   
00853   if (resp.status) {
00854     return -1;
00855   }
00856   
00857   return 0;
00858 }
00859 
00860 int hci_le_read_white_list_size(uint8_t *size)
00861 {
00862   struct hci_request rq;
00863   le_read_white_list_size_rp resp;
00864   
00865   Osal_MemSet(&resp, 0, sizeof(resp));
00866   
00867   Osal_MemSet(&rq, 0, sizeof(rq));
00868   rq.ogf = OGF_LE_CTL;
00869   rq.ocf = OCF_LE_READ_WHITE_LIST_SIZE;
00870   rq.rparam = &resp;
00871   rq.rlen = LE_READ_WHITE_LIST_SIZE_RP_SIZE;
00872   
00873   if (hci_send_req(&rq, FALSE) < 0){
00874     return -1;
00875   }
00876   
00877   if (resp.status) {
00878     return -1;
00879   }
00880   
00881   *size = resp.size;
00882   
00883   return 0;
00884 }
00885 
00886 int hci_le_clear_white_list()
00887 {
00888   struct hci_request rq;
00889   uint8_t status;
00890   
00891   Osal_MemSet(&rq, 0, sizeof(rq));
00892   rq.ogf = OGF_LE_CTL;
00893   rq.ocf = OCF_LE_CLEAR_WHITE_LIST;
00894   rq.rparam = &status;
00895   rq.rlen = 1;
00896   
00897   if (hci_send_req(&rq, FALSE) < 0){
00898     return -1;
00899   }
00900   
00901   if (status) {
00902     return -1;
00903   }
00904   
00905   return 0;
00906 }
00907 
00908 int hci_le_add_device_to_white_list(uint8_t bdaddr_type, tBDAddr bdaddr)
00909 {
00910   struct hci_request rq;
00911   le_add_device_to_white_list_cp params;
00912   uint8_t status;
00913   
00914   params.bdaddr_type = bdaddr_type;
00915   Osal_MemCpy(params.bdaddr, bdaddr, 6);
00916   
00917   Osal_MemSet(&rq, 0, sizeof(rq));
00918   rq.ogf = OGF_LE_CTL;
00919   rq.ocf = OCF_LE_ADD_DEVICE_TO_WHITE_LIST;
00920   rq.cparam = &params;
00921   rq.clen = LE_ADD_DEVICE_TO_WHITE_LIST_CP_SIZE;
00922   rq.rparam = &status;
00923   rq.rlen = 1;
00924   
00925   if (hci_send_req(&rq, FALSE) < 0){
00926     return -1;
00927   }
00928   
00929   if (status) {
00930     return -1;
00931   }
00932   
00933   return 0;
00934 }
00935 
00936 int hci_le_remove_device_from_white_list(uint8_t bdaddr_type, tBDAddr bdaddr)
00937 {
00938   struct hci_request rq;
00939   le_remove_device_from_white_list_cp params;
00940   uint8_t status;
00941   
00942   params.bdaddr_type = bdaddr_type;
00943   Osal_MemCpy(params.bdaddr, bdaddr, 6);
00944   
00945   Osal_MemSet(&rq, 0, sizeof(rq));
00946   rq.ogf = OGF_LE_CTL;
00947   rq.ocf = OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST;
00948   rq.cparam = &params;
00949   rq.clen = LE_REMOVE_DEVICE_FROM_WHITE_LIST_CP_SIZE;
00950   rq.rparam = &status;
00951   rq.rlen = 1;
00952   
00953   if (hci_send_req(&rq, FALSE) < 0){
00954     return -1;
00955   }
00956   
00957   if (status) {
00958     return -1;
00959   }
00960   
00961   return 0;
00962 }
00963 
00964 int hci_read_transmit_power_level(uint16_t *conn_handle, uint8_t type, int8_t * tx_level)
00965 {
00966   struct hci_request rq;
00967   read_transmit_power_level_cp params;
00968   read_transmit_power_level_rp resp;
00969   
00970   Osal_MemSet(&resp, 0, sizeof(resp));
00971   
00972   params.handle = *conn_handle;
00973   params.type = type;
00974   
00975   Osal_MemSet(&rq, 0, sizeof(rq));
00976   rq.ogf = OGF_HOST_CTL;
00977   rq.ocf = OCF_READ_TRANSMIT_POWER_LEVEL;
00978   rq.cparam = &params;
00979   rq.clen = READ_TRANSMIT_POWER_LEVEL_CP_SIZE;
00980   rq.rparam = &resp;
00981   rq.rlen = READ_TRANSMIT_POWER_LEVEL_RP_SIZE;
00982   
00983   if (hci_send_req(&rq, FALSE) < 0){
00984     return -1;
00985   }
00986   
00987   if (resp.status) {
00988     return -1;
00989   }
00990   
00991   *conn_handle = resp.handle;
00992   *tx_level = resp.level;
00993   
00994   return 0;
00995 }
00996 
00997 int hci_read_rssi(uint16_t *conn_handle, int8_t * rssi)
00998 {
00999   struct hci_request rq;
01000   read_rssi_cp params;
01001   read_rssi_rp resp;
01002   
01003   Osal_MemSet(&resp, 0, sizeof(resp));
01004   
01005   params.handle = *conn_handle;
01006   
01007   Osal_MemSet(&rq, 0, sizeof(rq));
01008   rq.ogf = OGF_STATUS_PARAM;
01009   rq.ocf = OCF_READ_RSSI;
01010   rq.cparam = &params;
01011   rq.clen = READ_RSSI_CP_SIZE;
01012   rq.rparam = &resp;
01013   rq.rlen = READ_RSSI_RP_SIZE;
01014   
01015   if (hci_send_req(&rq, FALSE) < 0){
01016     return -1;
01017   }
01018   
01019   if (resp.status) {
01020     return -1;
01021   }
01022   
01023   *conn_handle = resp.handle;
01024   *rssi = resp.rssi;
01025   
01026   return 0;
01027 }
01028 
01029 int hci_le_read_local_supported_features(uint8_t *features)
01030 {
01031   struct hci_request rq;
01032   le_read_local_supported_features_rp resp;
01033   
01034   Osal_MemSet(&resp, 0, sizeof(resp));
01035   
01036   Osal_MemSet(&rq, 0, sizeof(rq));
01037   rq.ogf = OGF_LE_CTL;
01038   rq.ocf = OCF_LE_READ_LOCAL_SUPPORTED_FEATURES;
01039   rq.rparam = &resp;
01040   rq.rlen = LE_READ_LOCAL_SUPPORTED_FEATURES_RP_SIZE;
01041   
01042   if (hci_send_req(&rq, FALSE) < 0){
01043     return -1;
01044   }
01045   
01046   if (resp.status) {
01047     return -1;
01048   }
01049   
01050   Osal_MemCpy(features, resp.features, sizeof(resp.features));
01051   
01052   return 0;
01053 }
01054 
01055 int hci_le_read_channel_map(uint16_t conn_handle, uint8_t ch_map[5])
01056 {
01057   struct hci_request rq;
01058   le_read_channel_map_cp params;
01059   le_read_channel_map_rp resp;
01060   
01061   Osal_MemSet(&resp, 0, sizeof(resp));
01062   
01063   params.handle = conn_handle;
01064   
01065   Osal_MemSet(&rq, 0, sizeof(rq));
01066   rq.ogf = OGF_LE_CTL;
01067   rq.ocf = OCF_LE_READ_CHANNEL_MAP;
01068   rq.cparam = &params;
01069   rq.clen = LE_READ_CHANNEL_MAP_CP_SIZE;
01070   rq.rparam = &resp;
01071   rq.rlen = LE_READ_CHANNEL_MAP_RP_SIZE;
01072   
01073   if (hci_send_req(&rq, FALSE) < 0){
01074     return -1;
01075   }
01076   
01077   if (resp.status) {
01078     return -1;
01079   }
01080   
01081   Osal_MemCpy(ch_map, resp.map, 5);
01082   
01083   return 0;
01084 }
01085 
01086 int hci_le_read_supported_states(uint8_t states[8])
01087 {
01088   struct hci_request rq;
01089   le_read_supported_states_rp resp;
01090   
01091   Osal_MemSet(&resp, 0, sizeof(resp));
01092   
01093   Osal_MemSet(&rq, 0, sizeof(rq));
01094   rq.ogf = OGF_LE_CTL;
01095   rq.ocf = OCF_LE_READ_SUPPORTED_STATES;
01096   rq.rparam = &resp;
01097   rq.rlen = LE_READ_SUPPORTED_STATES_RP_SIZE;
01098   
01099   if (hci_send_req(&rq, FALSE) < 0){
01100     return -1;
01101   }
01102   
01103   if (resp.status) {
01104     return -1;
01105   }
01106   
01107   Osal_MemCpy(states, resp.states, 8);
01108   
01109   return 0;
01110 }
01111 
01112 int hci_le_receiver_test(uint8_t frequency)
01113 {
01114   struct hci_request rq;
01115   le_receiver_test_cp params;
01116   uint8_t status;
01117   
01118   params.frequency = frequency;
01119   
01120   Osal_MemSet(&rq, 0, sizeof(rq));
01121   rq.ogf = OGF_LE_CTL;
01122   rq.ocf = OCF_LE_RECEIVER_TEST;
01123   rq.cparam = &params;
01124   rq.clen = LE_RECEIVER_TEST_CP_SIZE;
01125   rq.rparam = &status;
01126   rq.rlen = 1;
01127   
01128   if (hci_send_req(&rq, FALSE) < 0){
01129     return -1;
01130   }
01131   
01132   if (status) {
01133     return -1;
01134   }
01135   
01136   return 0;
01137 }
01138 
01139 int hci_le_transmitter_test(uint8_t frequency, uint8_t length, uint8_t payload)
01140 {
01141   struct hci_request rq;
01142   le_transmitter_test_cp params;
01143   uint8_t status;
01144   
01145   params.frequency = frequency;
01146   params.length = length;
01147   params.payload = payload;
01148   
01149   Osal_MemSet(&rq, 0, sizeof(rq));
01150   rq.ogf = OGF_LE_CTL;
01151   rq.ocf = OCF_LE_TRANSMITTER_TEST;
01152   rq.cparam = &params;
01153   rq.clen = LE_TRANSMITTER_TEST_CP_SIZE;
01154   rq.rparam = &status;
01155   rq.rlen = 1;
01156   
01157   if (hci_send_req(&rq, FALSE) < 0){
01158     return -1;
01159   }
01160   
01161   if (status) {
01162     return -1;
01163   }
01164   
01165   return 0;
01166 }
01167 
01168 int hci_le_test_end(uint16_t *num_pkts)
01169 {
01170   struct hci_request rq;
01171   le_test_end_rp resp;
01172   
01173   Osal_MemSet(&resp, 0, sizeof(resp));
01174   
01175   Osal_MemSet(&rq, 0, sizeof(rq));
01176   rq.ogf = OGF_LE_CTL;
01177   rq.ocf = OCF_LE_TEST_END;
01178   rq.rparam = &resp;
01179   rq.rlen = LE_TEST_END_RP_SIZE;
01180   
01181   if (hci_send_req(&rq, FALSE) < 0){
01182     return -1;
01183   }
01184   
01185   if (resp.status) {
01186     return -1;
01187   }
01188   
01189   *num_pkts = resp.num_pkts;
01190   
01191   return 0;
01192 }
01193 
01194 #endif /* __DMA_LP__ */