Filippo Casamassima / Nucleo_blueNRG

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers hci.c Source File

hci.c

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