]> rtime.felk.cvut.cz Git - tiny-bt.git/blob - src2/tiny_bt_hci_core.c
outgoing data packet was modified. Now I can send packet and receive it on second...
[tiny-bt.git] / src2 / tiny_bt_hci_core.c
1 /*
2 *  C Implementation: testovaci
3 *
4 * Description:
5 *
6 *
7 * Author: root <root@ubuntu>, (C) 2008
8 *
9 * Copyright: See COPYING file that comes with this distribution
10 *
11 */
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <sys/ioctl.h>
15 #include <errno.h>
16 #include <stdint.h>
17 #include "tiny_bt_hci_core.h"
18 #include "tiny_bt_hci_cmd.h"
19 #include "bt_hw.h"
20
21 static expect_evt evt_array[MAX_CMD_STATE_REQUEST];
22 static int evt_id;
23 static int global_index;
24 extern connection_hci connection;
25 /******************************HCI callback functions*********************/
26
27 static void callback_hci_all_commands(void *p_arg, void *p_recbuf) 
28 {
29         evt_cmd_status *p_rp;
30         p_rp = (void *) p_recbuf;
31
32         if (p_rp->status) {
33                 perror("command status error\n");
34                 tiny_bt_finish();
35                 //return -1;
36                 /*TODO call some app_callback and do something with error state */
37                 exit(1); // !!!!!!!!!!!!!!!!
38         }
39                 
40         printf("command status with opcode: %d\n",p_rp->opcode);
41         //return 0;
42 }
43
44 static void callback_hci_read_bd_addr(void *p_arg, void *p_recbuf)
45 {
46         read_bd_addr_data *p_data = p_arg;
47         read_bd_addr_rp *p_rp;
48                 
49         p_rp = (void *) (p_recbuf + 3); 
50         memcpy(p_data->p_address, &p_rp->bdaddr, 6);
51         p_data->callback_app_read_bd_addr(p_data->p_address);
52         free(p_data);
53 }
54
55 static void callback_hci_read_local_name(void *p_arg, void *p_recbuf)
56 {
57         read_local_name_data *p_data = p_arg;
58         read_local_name_rp *p_rp;
59
60         p_rp = (void *) (p_recbuf + 3);
61         memcpy(p_data->p_name, &p_rp->name, 248);
62         p_data->callback_app_read_local_name(p_data->p_name);
63         free(p_data);
64 }
65
66 static void callback_hci_inquiry_RSSI(void *p_arg, void *p_recbuf)
67 {
68         inquiry_RSSI_data *p_data = p_arg;
69         inquiry_info_with_rssi *p_rp;
70
71         p_rp = (void *) (p_recbuf + 1);
72         memcpy(p_data->p_address, &p_rp->bdaddr, 6);
73         p_data->callback_app_inquiry_RSSI(p_data->p_address);
74         free(p_data);
75 }
76
77 static void callback_hci_inquiry_comple(void *p_arg, void *p_recbuf)
78 {
79         inquiry_complete_data *p_data = p_arg;
80         __u8 *p_byte;
81
82         p_byte = (void *) p_recbuf;
83         if (*p_byte) {
84                 perror("inquiry complete status error\n");
85                 exit(-1); // !!!!!!!!
86         }
87                 
88         p_data->callback_app_inquiry_complete();
89         free(p_data);
90 }
91
92 static void callback_hci_create_connection(void *p_arg, void *p_recbuf)
93 {
94         connection_complete_data *p_data = p_arg;
95         evt_conn_complete *p_rp;
96
97         p_rp = (void *) (p_recbuf);
98         memcpy(p_data->p_handle, &p_rp->handle, 2);
99         //memcpy(p_data->p_address,&p_rp->bdaddr,6);
100         p_data->callback_app_connection_complete(p_data->p_handle);
101         free(p_data);
102 }
103
104 static void callback_hci_connection_request(void *p_arg, void *p_recbuf)
105 {
106         connection_request_data *p_data = p_arg;
107         evt_conn_request *p_rp;
108         
109         p_rp = (void *) (p_recbuf);
110         memcpy(p_data->p_address, &p_rp->bdaddr, 6);
111         p_data->callback_app_connection_request(p_data->p_address);
112         free(p_data);
113 }
114
115 static void callback_hci_disconnect(void *p_arg, void *p_recbuf)
116 {
117         disconnect_data *p_data = p_arg;
118         evt_disconn_complete *p_rp;
119
120         p_rp = (void *) (p_recbuf);
121         p_data->callback_app_disconnect(&p_rp->handle, &p_rp->reason);
122         free(p_data);   
123 }
124
125 /******************************array functions*********************/
126 /*fcn add the request at the end of array or replace the oldest request*/
127 void add_evt_toarray(expect_evt *p_evt)   
128 {
129         int i;
130         int sig = 0,index = 0;
131         expect_evt the_oldest = evt_array[0];
132
133         for (i = 0; i < MAX_EVT_COUNT; i++) {/*todo use constatns will be better*/
134                 if (evt_array[i].actual_status == 0 || evt_array[i].actual_status == 3) {
135                         evt_array[i] = *p_evt;
136                         sig=1;
137                         global_index=i;
138                         break;
139                 }
140                 /*the smallest id (oldest request) will stay here*/
141                 if (evt_array[i].id < the_oldest.id) {
142                         the_oldest = evt_array[i];
143                         index=i;
144
145                 }
146         }
147         if (!sig) {
148                 evt_array[index] = *p_evt;
149                 global_index = index;
150         }
151 }
152
153 int look_up_inarray(__u8 evt_type, __u16 opcode)
154 {
155         int i;
156         int index = -1, oldestid = 65535;
157
158         if (evt_array[global_index].evt_type == evt_type && evt_array[global_index].actual_status != DONE) {
159                 if (opcode != 0) {
160                         if(evt_array[global_index].req_opcode == opcode)
161                                 return global_index;    
162                 } else {
163                         return global_index;
164                 }
165                 
166         } else {
167                 for (i = 0; i < MAX_CMD_STATE_REQUEST; i++) {
168                         if (evt_array[i].evt_type == evt_type && evt_array[i].actual_status != DONE ) { 
169                                 if (opcode != 0) {
170                                         if (evt_array[i].req_opcode == opcode) {
171                                                 if (evt_array[i].id < oldestid) {
172                                                         oldestid = evt_array[i].id;
173                                                         index = i;
174                                                 }
175                                         }
176                                 } else {
177                                         if (evt_array[i].id < oldestid) {
178                                                 oldestid = evt_array[i].id;
179                                                 index = i;
180                                         }
181                                 }
182                         }
183                 }
184                 return index;
185         }
186         return -1;
187 }
188
189 /******************************tiny_bt_functions functions*********************/
190 int tiny_bt_init(__u8 dev_id)
191 {
192         struct hci_filter nf;
193         int dd;
194         expect_evt evt, *p_evt = &evt;
195         connection_hci *p_conn = &connection;
196         req_state status = PERMANENT;
197         connection_state con_state = DISCONNECT;
198         
199         memset(evt_array, 0, MAX_CMD_STATE_REQUEST * sizeof(expect_evt));
200         evt_id = 0;
201         global_index = 0;
202         p_conn->con_id = 0;
203         p_conn->con_state = con_state;
204
205         memset(p_evt, 0, sizeof(evt));
206         p_evt->actual_status = status;
207         p_evt->id = evt_id++;
208         p_evt->evt_type = EVT_CMD_STATUS;
209         p_evt->p_callback = callback_hci_all_commands;
210         p_evt->p_data = NULL;
211         add_evt_toarray(p_evt);
212         
213         if ((dd = hw_bt_open_device(dev_id)) < 0) {
214                 perror("device impossible to open\n");
215                 return -1;
216         }
217         
218         hci_filter_clear(&nf);
219         hci_filter_all_ptypes(&nf);
220         hci_filter_all_events(&nf);
221 //      hci_filter_set_opcode(swap_2_bytes(READ_BD_ADDR_CMD_OP),&nf);
222                 
223         if (setsockopt(dd, SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0) {
224                 perror("some problem with setsockopt\n");
225                 return -1;
226         }
227         printf("init was succesful dd:%d\n",dd);
228         return 0;
229 }
230
231 int tiny_bt_finish()
232 {       
233         int err;
234         
235         if ((err = hw_bt_close_dev()) < 0) {
236                 perror("Impossible to close filedes\n");
237                 return -1;
238         }
239         printf("filedescriptor was closed\n");
240         return 0;
241 }
242
243 int tiny_bt_process()
244 {
245         int len, j, index;
246         int err;
247         static int inqRSSI_index = -1;
248         hci_event_hdr *p_hdr;
249         __u8 recbuf[HCI_MAX_EVENT_SIZE], *p_recbuf;
250
251         len = hw_bt_read(recbuf);
252
253         if (len) {
254                 printf("Count of received bytes %d\n ", len);
255                 for (j = 0; j < len; j++) {
256                         printf(" %2.2X ",recbuf[j]);
257                 }
258                 printf("\n");
259                 if (recbuf[0] == HCI_EVENT_PKT) {
260                         p_hdr = (void *) (recbuf + 1);
261                         p_recbuf = (void *) (recbuf + (1 + HCI_EVENT_HDR_SIZE));
262                         if (p_hdr->evt == EVT_CMD_COMPLETE) {
263                                 evt_cmd_complete *p_ccevt;
264                                 p_ccevt = (void *) p_recbuf;
265                                 if ((index = look_up_inarray(p_hdr->evt, swap_2_bytes(p_ccevt->opcode))) < 0) {
266                                         err = -1;
267                                         goto no_evt_exit;
268                                 } else {
269                                         evt_array[index].p_callback(evt_array[index].p_data, p_recbuf);
270                                         if (evt_array[index].actual_status != PERMANENT)
271                                                 evt_array[index].actual_status = DONE;
272                                         
273                                 }
274                         } else if (p_hdr->evt == EVT_INQUIRY_RESULT_WITH_RSSI || p_hdr->evt == EVT_INQUIRY_RESULT) {
275                                 if ((index = look_up_inarray(EVT_INQUIRY_RESULT_WITH_RSSI, 0)) < 0) {
276                                         err = -1;
277                                         goto no_evt_exit;
278                                 } else {
279                                         evt_array[index].p_callback(evt_array[index].p_data, p_recbuf);
280                                         if (evt_array[index].actual_status != PERMANENT)
281                                                 evt_array[index].actual_status = DONE;
282                                 }
283
284                         } else if (p_hdr->evt == EVT_CONN_REQUEST) {
285                                 if ((index = look_up_inarray(EVT_CONN_REQUEST, 0)) < 0) {
286                                         err = -1;
287                                         goto no_evt_exit;
288                                 } else {
289                                         evt_array[index].p_callback(evt_array[index].p_data, p_recbuf);
290                                         if (evt_array[index].actual_status != PERMANENT)
291                                                 evt_array[index].actual_status = DONE;
292                                 }
293
294                         } else if (p_hdr->evt == EVT_MAX_SLOTS_CHANGE || p_hdr->evt == EVT_NUM_COMP_PKTS) {
295                                 /*TODO*/
296                                 return 0;
297                         } else if (p_hdr->evt == EVT_INQUIRY_COMPLETE) {
298                                 if ((index = look_up_inarray(p_hdr->evt, 0)) < 0) {
299                                         err = -1;
300                                         goto no_evt_exit;
301                                 }
302                                 if ((inqRSSI_index = look_up_inarray(EVT_INQUIRY_RESULT_WITH_RSSI, 0)) < 0) {
303                                         err = -1;
304                                         goto no_evt_exit;
305                                 } else {
306                                         evt_array[index].p_callback(evt_array[index].p_data, p_recbuf);
307                                         if (evt_array[index].actual_status != PERMANENT) {
308                                                 evt_array[index].actual_status = DONE;
309                                         }// mark inq result evt like a DONE
310                                         if (evt_array[inqRSSI_index].actual_status != PERMANENT) {
311                                                 free(evt_array[inqRSSI_index].p_data);
312                                                 evt_array[inqRSSI_index].actual_status = DONE;
313                                         }
314                                 }
315                         } else {
316                                 if ((index = look_up_inarray(p_hdr->evt, 0)) < 0) {
317                                         err = -1;
318                                         goto no_evt_exit;
319                                 } else {
320                                         evt_array[index].p_callback(evt_array[index].p_data, p_recbuf);
321                                         if (evt_array[index].actual_status != PERMANENT) 
322                                                 evt_array[index].actual_status = DONE;
323                                 }
324                         }
325                         goto evt_found_exit;
326                 } else if (recbuf[0] == HCI_ACLDATA_PKT) {
327                         printf("Incoming data:\n");
328                         printf("Count of received bytes %d\n ", len);
329                         for(j = 0; j < len; j++) {
330                                 printf("%2.2X ", recbuf[j]);
331                         }
332                         printf("\n");
333                         /*TODO call some data callback for process data*/
334                         return 1;
335                 } else 
336                         goto packet_wrong; 
337         } else 
338                 goto no_data;
339         
340         
341 no_evt_exit:
342         printf("There is no awaiting evt like this\n");
343         return err;
344         
345 evt_found_exit:
346         return 1;
347
348 packet_wrong:
349         printf("Packet have bad format\n");
350         return 0;
351
352 no_data:
353         /*printf("There is no data on socket");*/
354         return 0;
355 }
356
357 int tiny_bt_read_bd_addr(bt_address *p_dest, void(*callback_app_read_bd_addr)(bt_address *p_address))
358 {
359         expect_evt evt, *p_evt = &evt;
360         req_state status = ESTABLISHED;
361         read_bd_addr_data *p_data;
362
363         memset(p_evt, 0, sizeof(evt));
364         p_evt->actual_status = status;
365         p_evt->id = evt_id++;
366         p_evt->evt_type = EVT_CMD_COMPLETE;
367         p_evt->req_opcode = READ_BD_ADDR_CMD_OP;
368         p_evt->p_callback = &callback_hci_read_bd_addr;
369
370         p_data = malloc(sizeof(read_bd_addr_data));
371         p_data->p_address = p_dest;
372         p_data->callback_app_read_bd_addr = callback_app_read_bd_addr;
373         p_evt->p_data = (void *) p_data;
374         add_evt_toarray(p_evt);
375
376         if (send_hci_read_bd_addr_cmd() < 0) {
377                 perror("send_hci_cmd error\n");
378                 return -1;
379         }
380         return 0;
381 }
382
383 int tiny_bt_read_local_name(char *p_name, void(*callback_app_read_local_name)(char *p_name)) 
384 {
385         expect_evt evt, *p_evt = &evt;
386         req_state status = ESTABLISHED;
387         read_local_name_data *p_data;
388
389         memset (p_evt, 0, sizeof(evt));
390         p_evt->actual_status = status;
391         p_evt->id = evt_id++;
392         p_evt->evt_type = EVT_CMD_COMPLETE;
393         p_evt->req_opcode = READ_LOCAL_NAME_CMD_OP;
394         p_evt->p_callback = callback_hci_read_local_name;
395
396         p_data = malloc(sizeof(read_local_name_data));
397         p_data->p_name = p_name;
398         p_data->callback_app_read_local_name = callback_app_read_local_name;
399         p_evt->p_data = (void *) p_data;
400
401         add_evt_toarray(p_evt);
402         if(send_hci_read_local_name_cmd() < 0) {
403                 perror("send_hci_cmd error\n");
404                 return -1;
405         }
406         return 0;
407 }
408
409 int tiny_bt_inquiry(bt_address *p_dest_addr, void(*callback_app_inquiry_RSSI)(bt_address *p_address), void(*callback_app_inquiry_complete)(void))
410 {
411         expect_evt evt,*p_evt = &evt;
412         req_state status = ESTABLISHED;
413         req_state istatus = ESTABLISHED;
414         inquiry_RSSI_data *p_data;
415         inquiry_complete_data *p_idata;
416         
417         memset(p_evt, 0, sizeof(evt));
418         p_evt->actual_status = status;
419         p_evt->id = evt_id++;
420         p_evt->evt_type = EVT_INQUIRY_RESULT_WITH_RSSI;
421         p_evt->req_opcode = INQUIRY_CMD_OP;
422         p_evt->p_callback = callback_hci_inquiry_RSSI;
423
424         p_data = malloc(sizeof(inquiry_RSSI_data));
425         p_data->p_address = p_dest_addr;
426         p_data->callback_app_inquiry_RSSI = callback_app_inquiry_RSSI;
427         p_evt->p_data = (void *) p_data;
428         
429         add_evt_toarray(p_evt);
430
431         memset(p_evt, 0, sizeof(evt));
432         p_evt->actual_status = istatus;
433         p_evt->id = evt_id++;
434         p_evt->evt_type = EVT_INQUIRY_COMPLETE;
435         p_evt->req_opcode = INQUIRY_CMD_OP;
436         p_evt->p_callback = callback_hci_inquiry_comple;
437
438         p_idata = malloc(sizeof(inquiry_complete_data));
439         p_idata->callback_app_inquiry_complete = callback_app_inquiry_complete;
440         p_evt->p_data = (void *)p_idata;
441         
442         add_evt_toarray(p_evt);
443         
444         if(send_hci_inquiry_cmd()<0) {
445                 perror("send_hci_cmd error");
446                 return -1;
447         }
448         return 0;
449 }
450
451 void tiny_bt_inquiry_register_again(bt_address *p_dest_addr, void(*callback_app_inquiry_RSSI)(bt_address *p_address))
452 {
453         expect_evt evt, *p_evt = &evt;
454         req_state status = ESTABLISHED;
455         inquiry_RSSI_data *p_data;
456         
457         memset(p_evt, 0, sizeof(evt));
458         p_evt->actual_status = status;
459         p_evt->id = evt_id++;
460         p_evt->evt_type = EVT_INQUIRY_RESULT_WITH_RSSI;
461         p_evt->req_opcode = INQUIRY_CMD_OP;
462         p_evt->p_callback = callback_hci_inquiry_RSSI;
463
464         p_data = malloc(sizeof(inquiry_RSSI_data));
465         p_data->p_address = p_dest_addr;
466         p_data->callback_app_inquiry_RSSI = callback_app_inquiry_RSSI;
467         p_evt->p_data = (void *) p_data;
468         
469         add_evt_toarray(p_evt);
470 }
471
472 int tiny_bt_connect(bt_address *p_dest_addr, __u16 *p_handle, void( *callback_app_connection_complete)(__u16 *p_handle))
473 {
474         expect_evt evt, *p_evt = &evt;
475         req_state status = ESTABLISHED;
476         connection_complete_data *p_data;
477
478         memset(p_evt, 0, sizeof(evt));
479         p_evt->actual_status = status;
480         p_evt->id = evt_id++;
481         p_evt->evt_type = EVT_CONN_COMPLETE;
482         p_evt->req_opcode = CREATE_CONNECTION_CMD_OP;
483         p_evt->p_callback = callback_hci_create_connection;
484
485         p_data = malloc(sizeof(connection_complete_data));
486         p_data->p_handle = p_handle;
487         p_data->callback_app_connection_complete = callback_app_connection_complete;
488         p_evt->p_data = (void *) p_data;
489
490         add_evt_toarray (p_evt);
491         if (send_hci_create_connection_cmd(p_dest_addr) < 0) {
492                 perror("send_hci_cmd error\n");
493                 return -1;
494         }
495         return 0;
496
497 }
498
499 void tiny_bt_wait_for_connection(bt_address *p_dest_addr, void(*callback_app_conection_request)(bt_address *p_address)) 
500 {
501         expect_evt evt, *p_evt = &evt;
502         req_state status = ESTABLISHED;
503         connection_request_data *p_data;
504         
505         memset(p_evt, 0, sizeof(evt));
506         p_evt->actual_status = status;
507         p_evt->id = evt_id++;
508         p_evt->evt_type = EVT_CONN_REQUEST;
509         p_evt->p_callback = callback_hci_connection_request;
510         
511         p_data = malloc(sizeof(connection_request_data));
512         p_data->p_address = p_dest_addr;
513         p_data->callback_app_connection_request = callback_app_conection_request;
514         p_evt->p_data = (void*) p_data;
515
516         add_evt_toarray(p_evt);
517 }
518
519 int tiny_bt_accept_connection(bt_address *p_dest_addr, __u16 *p_handle, void(*callback_app_connection_complete)(__u16 *p_handle))
520 {
521         expect_evt evt, *p_evt = &evt;
522         req_state status = ESTABLISHED;
523         connection_complete_data *p_data;
524
525         memset(p_evt, 0, sizeof(evt));
526         p_evt->actual_status = status;
527         p_evt->id = evt_id++;
528         p_evt->evt_type = EVT_CONN_COMPLETE;
529         p_evt->req_opcode = ACCEPT_CONNECTION_REQ_OP;
530         p_evt->p_callback = callback_hci_create_connection;
531
532         p_data = malloc(sizeof(connection_complete_data));
533         p_data->p_handle = p_handle;
534         p_data->callback_app_connection_complete = callback_app_connection_complete;
535         p_evt->p_data = (void *) p_data;
536         
537         add_evt_toarray(p_evt);
538         // and register disconnect event
539         if (send_hci_accept_conn_req_cmd(p_dest_addr) < 0) {
540                 perror("send_hci_cmd error\n");
541                 return -1;
542         }
543         return 0;
544 }
545
546 void tiny_bt_disconnect_register(void(*callback_app_disconnect)(__u16 *p_handle, __u8 *p_reason))
547 {
548         expect_evt evt, *p_evt = &evt;
549         req_state status = ESTABLISHED;
550         disconnect_data *p_data;
551
552         memset(p_evt, 0, sizeof(evt));
553         p_evt->actual_status = status;
554         p_evt->id = evt_id++;
555         p_evt->evt_type = EVT_DISCONN_COMPLETE;
556         p_evt->p_callback = callback_hci_disconnect;
557
558         p_data = malloc(sizeof(disconnect_data));
559         p_data->callback_app_disconnect = callback_app_disconnect;
560         p_evt->p_data = (void *) p_data;
561         
562         add_evt_toarray(p_evt);
563 }
564
565 int tiny_bt_disconnect(__u16 *p_handle, void(*callback_app_disconnect)(__u16 *p_handle, __u8 *p_reason))
566 {
567         expect_evt evt, *p_evt = &evt;
568         req_state status = ESTABLISHED;
569         disconnect_data *p_data;
570
571         memset(p_evt, 0, sizeof(evt));
572         p_evt->actual_status = status;
573         p_evt->id = evt_id++;
574         p_evt->evt_type = EVT_DISCONN_COMPLETE;
575         p_evt->p_callback = callback_hci_disconnect;
576
577         p_data = malloc(sizeof(disconnect_data));
578         p_data->callback_app_disconnect = callback_app_disconnect;
579         p_evt->p_data = (void *) p_data;
580         
581         add_evt_toarray(p_evt);
582         
583         if (send_hci_disconnect_cmd(*p_handle) < 0) {
584                 perror ("send_hci_cmd error\n");
585                 return -1;
586         }
587         return 0;
588
589 }
590
591 int tiny_bt_send_data(char *p_data, __u16 lenght, __u16 *p_chandle, __u16 PB_flag, __u16 B_flag)
592 {       
593         if (send_hci_data(p_data, lenght, p_chandle, PB_flag, B_flag) < 0) {
594                 perror ("send_hci_cmd error\n");
595                 return -1;
596         }
597         return 0;
598 }
599
600