Программа считывает показания датчиков и управляет сервомашинками.

Dependencies:   mbed-src

Fork of NUCLEO_BLUENRG by Ostap Ostapsky

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