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