]> rtime.felk.cvut.cz Git - tiny-bt.git/blobdiff - src/hcidriver.c
hcidriver.c:new non block cmd call.
[tiny-bt.git] / src / hcidriver.c
index 46833f0d23bc2baecd614c63ec940f9cd4eb9fb6..823a545f4677985fafce5c1c1c563eab57b33298 100644 (file)
@@ -4,6 +4,8 @@
 #include <string.h>
 #include <errno.h>
 #include <unistd.h>
+#include <stdint.h>
+#include <fcntl.h>
 #include <sys/poll.h>
 #include <sys/ioctl.h>
 #include "hcidriver.h"
 
 
 
+
 /************************** hci command functions**************************/
-int call_hci_inquiry_cmd(int dd, bt_address *p_addressarray,int timeout){
+int call_hci_inquiry_cmd(int dd, void *p_addressarray,__u16 *p_ocf_ogf){
        inquiry_cp cmdp,*p_cmdp=&cmdp;
        hci_request req,*p_req=&req;
        
-       //hci_inquiry_complete_ev com_ev,*p_com_ev=&com_ev;
-       __u16 OCF_OGF,*p_OCF_OGF=&OCF_OGF;
-       
        p_cmdp->lap[0]=0x33;
        p_cmdp->lap[1]=0x8b;
        p_cmdp->lap[2]=0x9e;
-       p_cmdp->length=5;
-       p_cmdp->num_rsp=5;
+       p_cmdp->length=INQ_TIME_14s40;
+       p_cmdp->num_rsp=NUM_RSP_20;
        memset(p_req,0,sizeof(req));
-       assemble_ocf_ogf(0x01,0x01,p_OCF_OGF);
-       p_req->p_OCF_OGF=p_OCF_OGF;
+       p_req->p_OCF_OGF=p_ocf_ogf;
        p_req->p_retcmdp=p_addressarray;
        p_req->p_cmdp=p_cmdp;
-       p_req->retcmdp_len=INQUIRY_INFO_SIZE;
+       p_req->retcmdp_len=0;
        p_req->cmdp_len=INQUIRY_CP_SIZE;
-       p_req->event=EVT_INQUIRY_RESULT;
+       p_req->event=EVT_INQUIRY_COMPLETE;
 
-       if(hci_send_request(dd,p_req,timeout)<0)
+       if(hci_send_request(dd,p_req,INQ_TIME_4s24*1280)<0)
                return -1;
-//     if(p_com_ev->status)
-//             return -1;
-       
-       
-       return 0;
+               
+
+       return p_req->retcmdp_len;
 }
 // fill up the input parameter address pointer by one address
-int call_hci_read_bd_addr_cmd(int dd,bt_address *p_address, int timeout){
-       read_bd_addr_rp cmdp,*p_cmdp;   //command parameters return/comand
-       hci_request req,*p_req;
-       __u16 OCF_OGF,*p_OCF_OGF;
-       p_OCF_OGF=&OCF_OGF;
-       p_cmdp=&cmdp;
-       p_req=&req;
-       
+int call_hci_read_bd_addr_cmd(int dd,bt_address *p_address,__u16 *p_ocf_ogf){
+       read_bd_addr_rp cmdp,*p_cmdp=&cmdp;   //command parameters return/comand
+       hci_request req,*p_req=&req;
        
        memset(p_req,0,sizeof(req));
-       assemble_ocf_ogf(0x09,0x04,p_OCF_OGF);
-       p_req->p_OCF_OGF=p_OCF_OGF;
+       p_req->p_OCF_OGF=p_ocf_ogf;
        p_req->p_retcmdp=p_cmdp;
        p_req->retcmdp_len=READ_BD_ADDR_RP_SIZE;
        p_req->cmdp_len=0;
        p_req->event=EVT_CMD_COMPLETE;
 
-       if(hci_send_request(dd,p_req,timeout)<0)
+       if(hci_send_request(dd,p_req,2000)<0)
                return -1;
        if(p_cmdp->status)
                return -1;
-
        bacpy(p_address, &cmdp.bdaddr);
+
        return 0;
 }
 
-int call_hci_create_connection_cmd(int dd, bt_address *p_address, int timeout){
+int call_hci_read_local_name_cmd(int dd, void *p_name,__u16 *p_ocf_ogf){
+       read_local_name_rp cmdp,*p_cmdp=&cmdp;
+       hci_request req,*p_req=&req;
+               
+       memset(p_req,0,sizeof(req));
+       p_req->p_OCF_OGF=p_ocf_ogf;
+       p_req->p_retcmdp=p_cmdp;
+       p_req->retcmdp_len=READ_LOCAL_NAME_RP_SIZE;
+       p_req->cmdp_len=0;
+       p_req->event=EVT_CMD_COMPLETE;
+
+       if(hci_send_request(dd,p_req,1000)<0)
+               return -1;
+       if(p_cmdp->status)
+               return -1;
+       memcpy(p_name, &p_cmdp->name, 8); //copy name
+       return 0;
+
+}
+
+int call_hci_create_connection_cmd(int dd, bt_address *p_address, __u16 *p_ocf_ogf){
        create_conn_cp cmdp,*p_cmdp=&cmdp;
        hci_request req,*p_req=&req;
-       __u16 OCF_OGF,*p_OCF_OGF=&OCF_OGF;
-       
+       evt_conn_complete cc_evp,*p_cc_evp=&cc_evp;
+               
        p_cmdp->bdaddr=*p_address;
        p_cmdp->pkt_type=0x0010;
        p_cmdp->pscan_rep_mode=0x01;
@@ -80,17 +91,35 @@ int call_hci_create_connection_cmd(int dd, bt_address *p_address, int timeout){
        p_cmdp->clock_offset=0xf000;
        p_cmdp->role_switch=0x00;
        memset(p_req,0,sizeof(req));
-       assemble_ocf_ogf(0x05,0x01,p_OCF_OGF);
-       p_req->p_OCF_OGF=p_OCF_OGF;
+       p_req->p_OCF_OGF=p_ocf_ogf;
        p_req->p_cmdp=p_cmdp;
        p_req->cmdp_len=CREATE_CONN_CP_SIZE;
+       p_req->p_retcmdp=p_cc_evp;
+       p_req->retcmdp_len=EVT_CONN_COMPLETE_SIZE;
        p_req->event=EVT_CONN_COMPLETE;
 
-       if(hci_send_request(dd,p_req,timeout)<0)
+       if(hci_send_request(dd,p_req,2000)<0)
                return -1;
-       //if(p_com_ev->status)
-       //      return -1;
-               
+       
+       return p_cc_evp->handle;        
+       
+}
+
+int call_hci_accept_conn_req_cmd(int dd, bt_address *p_address, __u16 *p_ocf_ogf){
+       accept_conn_req_cp cmdp, *p_cmdp=&cmdp;
+       hci_request req,*p_req=&req;
+       
+       p_cmdp->bdaddr=*p_address;
+       p_cmdp->role=0x01;
+       memset(p_req,0,sizeof(req));
+       p_req->p_OCF_OGF=p_ocf_ogf;
+       p_req->p_cmdp=p_cmdp;
+       p_req->cmdp_len=ACCEPT_CONN_REQ_CP_SIZE;
+       
+       if(hci_send_command(dd,p_req)<0){
+               printf("problem with command sending\n");
+               return -1;
+       }
        return 0;
 }
 
@@ -119,12 +148,40 @@ int hci_open_device(int dev_id){
        return dd;
 }
 
+int hci_open_device_nonblock(int dev_id){
+       struct sockaddr_hci address;
+       int dd;
+       int oldflag;
+
+       if((dd=socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI))<0){
+               perror("socket no created");
+                return dd; //it return -1 when socket isn't created
+       }
+       
+       oldflag=fcntl(dd, F_GETFL, 0);
+        if(fcntl(dd, F_SETFL, oldflag | O_NONBLOCK) < 0){
+            printf("problem with socket flag setting");
+            return -1;
+        }
+
+       memset(&address,0,sizeof(address));
+       address.hci_family=AF_BLUETOOTH;
+       address.hci_dev=dev_id;
+       if(bind(dd,(struct sockaddr *) &address, sizeof(address))<0){
+               perror("Socket not binded to hci device");
+               close(dd);
+               return -1;
+       }
+
+       return dd;
+}
+
 int hci_close_dev(int dd){
        return close(dd);
 }
 
 int hci_send_command(int dd, hci_request *p_req){
-       __u8 array[p_req->cmdp_len+4]; //type + OCF+OGF+plen
+       __u8 array[p_req->cmdp_len+4]; 
        int ii;
        array[0]=0x01;
        memcpy(&array[1],p_req->p_OCF_OGF,2);
@@ -147,49 +204,201 @@ int hci_send_command(int dd, hci_request *p_req){
        return 0;
 }
 
-int hci_send_request(int dd, hci_request *p_req,int timeout){
-       return 0;
-}
-
-/*void print_device_list(int ctl){
-       bt_device_req_list dlist,*p_dlist;
-       bt_device_req *p_dreq;
-       int i;
-       bt_device devi;
 
-       p_dlist=&dlist;
-       p_dlist->dev_num=HCI_MAX_DEV;
-       p_dreq=p_dlist->dev_req;
+int hci_send_request(int dd, hci_request *p_req,int timeout){
+       __u8 recbuf[HCI_MAX_EVENT_SIZE],*p_recbuf;
+       int j,count=0;
+       socklen_t len;
+       hci_event_hdr *p_hdr;
+       struct hci_filter nf, of;
+       int try_count;
        
-       if(ioctl(ctl, HCIGETDEVLIST, (void *) p_dlist)<0){
-               perror("Can't get device list");
-               exit(1);
+       len = sizeof(of);
+       if(getsockopt(dd, SOL_HCI, HCI_FILTER, &of, &len)<0){
+               printf("some problem with getsockopt: %d",dd);
+               return -1;
        }
        
-       for(i=0;i<p_dlist->dev_num;i++){
-               devi.dev_id=(p_dreq+i)->dev_id;
-               if(ioctl(ctl, HCIGETDEVINFO, (void *) &devi)<0)
-                       printf("No info");
-                       continue;
+       hci_filter_clear(&nf);
+       hci_filter_set_ptype(HCI_EVENT_PKT, &nf);
+       hci_filter_set_event(EVT_CMD_STATUS, &nf);
+       hci_filter_set_event(EVT_INQUIRY_RESULT_WITH_RSSI, &nf);
+       hci_filter_set_event(p_req->event, &nf);
+       hci_filter_set_opcode(*(p_req->p_OCF_OGF), &nf);
        
-       }       
-
-}
-
-
+       if(setsockopt(dd, SOL_HCI, HCI_FILTER, &nf, sizeof(nf))<0){
+               printf("some problem with setsockopt: %d",dd);
+               return -1;
+       }
+       
+       if(hci_send_command(dd, p_req)<0){
+               printf("some problems with sending command: %d",dd);
+               goto fail;
+       }
+       
+       try_count= 30;
+       
+       while(try_count--){
+               int sign=0;
+               printf("try %d \n",try_count);
+               evt_cmd_complete *cc;
+               evt_cmd_status *cs;
+               evt_remote_name_req_complete *rnrc;
+               remote_name_req_cp *cpar;
+               inquiry_info_with_rssi *p_res_ev;
+               bt_address *p_actual;
+                       
+               if(timeout){
+                       struct pollfd p;
+                       int n;
+
+                       p.fd = dd; p.events = POLLIN;
+                       while((n = poll(&p, 1, timeout)) < 0){  //pool return 1 when there are some incoming data
+                               if(errno == EAGAIN || errno == EINTR)
+                                       continue;
+                               perror("Problem with poll");
+                               goto fail;
+                       }
+
+                       if (!n) {  //time out pool return 0
+                               errno = ETIMEDOUT;
+                               perror("Poll return 0 timeout");
+                               printf("exited pool timeout \n ");
+                               goto fail;
+                       }
+
+                       timeout -= 10;
+                       if(timeout < 0) timeout = 0;
+
+               }
+               printf("Timeout after round is: %d \n",timeout);
+               
+               while((len=read(dd, recbuf, sizeof(recbuf)))<0){
+                       if(errno == EAGAIN || errno == EINTR)
+                               continue;
+                       perror("Problem with cmd reading");
+                       goto fail;
+               }
+               printf("Count of received bytes %d \n ",len);
+               for(j=0;j<len;j++){
+                       printf("%2.2X ",recbuf[j]);     
+               }
+               printf("\n");
+               p_hdr = (void *) (recbuf + 1);
+               p_recbuf = recbuf + (1 + HCI_EVENT_HDR_SIZE);   
+               len -= (1 + HCI_EVENT_HDR_SIZE);
+               
+               switch(p_hdr->evt){
+                       case EVT_CMD_STATUS:
+                               cs = (void *) p_recbuf;
+                               if(cs->opcode != *(p_req->p_OCF_OGF))
+                                       continue;
+                               if(p_req->event != EVT_CMD_STATUS){
+                                       if(cs->status){         // if there is something except 0 it is error   
+                                               errno = EIO;
+                                               perror("Some error state has occured on receive");
+                                               goto fail;
+                                       }
+                                       break;
+                               }
+                               p_req->retcmdp_len = min(len, p_req->retcmdp_len);
+                               memcpy(p_req->p_retcmdp, p_recbuf, p_req->retcmdp_len);
+                               goto succes;
+
+                       case EVT_CMD_COMPLETE:
+                               cc = (void *) p_recbuf;
+                               if(cc->opcode != *(p_req->p_OCF_OGF))
+                                       continue;
+                               p_recbuf += EVT_CMD_COMPLETE_SIZE;
+                               len -= EVT_CMD_COMPLETE_SIZE;
+                               
+                               p_req->retcmdp_len = min(len, p_req->retcmdp_len);
+                               memcpy(p_req->p_retcmdp, p_recbuf, p_req->retcmdp_len);
+                               printf("retcmdp lenght: %d \n",p_req->retcmdp_len);
+                               goto succes;
+                                                       
+                       case EVT_REMOTE_NAME_REQ_COMPLETE:
+                               if(p_hdr->evt != p_req->event)
+                                       break;
+                               rnrc = (void *) p_recbuf;
+                               cpar = p_req->p_cmdp;
+                               
+                               if(bacmp(&rnrc->bdaddr, &cpar->bdaddr))
+                                       continue;
+
+                               p_req->retcmdp_len = min(len, p_req->retcmdp_len);
+                               memcpy(p_req->p_retcmdp, p_recbuf, p_req->retcmdp_len);
+                               goto succes;
+                       
+                       case EVT_INQUIRY_RESULT_WITH_RSSI:
+                               printf("bingo inquiry result RSSI event \n");
+                               p_recbuf = recbuf + (1 + HCI_EVENT_HDR_SIZE + 1);// one byte set forward        
+                               p_res_ev = (void *) p_recbuf;
+                               p_actual = &(p_res_ev->bdaddr); 
+                               //todo:involve signal strength
+                               if(count==0){  //array  is empty
+                                       *(bt_address*)(p_req->p_retcmdp)= *p_actual;
+                                       count++;        
+                               }
+                               else{
+                                       for(j=0;j<count;j++){
+                                               if(compare_bda(p_actual,(bt_address *)(p_req->p_retcmdp+(j*sizeof(bt_address)))) == 1){
+                                                       sign=1; 
+                                               } //im looking for all array members  an compare with actual address
+                                       }
+                                       if(!sign){ // if in array address doesnt exist i will add it to array
+                                               *(bt_address*)(p_req->p_retcmdp+(count*sizeof(bt_address)))= *p_actual;
+                                               count++;
+                                       }
+                               }
+                               
+                               //printf("type %2.2X \n",((hci_inquiry_result_RSSI_ev *)p_req->p_retcmdp)->RSSI_array);
+                               break;
+                               //goto succes;
+
+                       case EVT_INQUIRY_COMPLETE:
+                               if(p_hdr->evt != p_req->event)
+                                       break;
+                               if(*p_recbuf != 0)
+                                       goto fail;
+                               printf("bingo inquiry complete event \n");
+                               p_req->retcmdp_len=count; //count of diferent remote decices
+                               
+                               goto succes;
+                       
+                       case EVT_CONN_COMPLETE:
+                               if(p_hdr->evt != p_req->event)
+                                       break;
+                               if(*p_recbuf != 0)
+                                       goto fail;
+                               printf("bingo two devices were connected");
+                               p_req->retcmdp_len = min(len, p_req->retcmdp_len);
+                               memcpy(p_req->p_retcmdp, p_recbuf, p_req->retcmdp_len);
+                               goto succes;
+                       
+                       default: 
+                               if(p_hdr->evt != p_req->event)
+                                       break;
+                               p_req->retcmdp_len = min(len, p_req->retcmdp_len);
+                               memcpy(p_req->p_retcmdp, p_recbuf, p_req->retcmdp_len);
+                               goto succes;
+               }
+               
 
-void assemble_hci_data(void *p_con_handle,void *p_data_size,void *p_data){
-       __u16 data_size=0;
-       data_size= *(__u16 *)p_data_size;
-       __u8 array[data_size+5];  //type + handle + flags + size 
-       array[0]=0x02;
-       memcpy(&array[1],p_con_handle,2);
-       memcpy(&array[3],p_data_size,2);
-       memcpy(&array[6],p_data,data_size);
-       //call send to socket/uart
+       }
+       errno = ETIMEDOUT;
+       return -1;
 
-} */
 
+fail:
+       setsockopt(dd, SOL_HCI, HCI_FILTER, &of, sizeof(of));
+       hci_close_dev(dd);
+       return -1;      
+succes:
+       setsockopt(dd, SOL_HCI, HCI_FILTER, &of, sizeof(of));
+       return 0; 
+       
+} 
 
 
 /*****************************HCI support functions*****************************/
@@ -198,10 +407,7 @@ void assemble_hci_data(void *p_con_handle,void *p_data_size,void *p_data){
 void assemble_ocf_ogf(__u8 ocf,__u8 ogf,__u16 *p_ocf_ogf){
        __u16 var1;
        __u16 result;
-       //result=ocf;
-       //result=(result<<8);
-       //var1=(ogf<<2);
-       //*p_ocf_ogf=(result|var1);
+       
        var1=(ogf<<10);
        result=ocf;
        *p_ocf_ogf=(result|var1);
@@ -236,6 +442,14 @@ void swap_addrbytes(bt_address *p_addr){
        }
        *p_addr=*p_help;
 }
+__u16 swap_2_bytes(__u16 twobytes){
+       __u16 first,second,result=0;
+       first=twobytes&255;
+       second=twobytes&65280;
+       result=result|(first<<8);
+       result=result|(second>>8);
+       return result;
+}
 
 __u8 swap8(__u8 byte1){
        __u8 i,mask=0,hvar1=0,resvar=0;