]> rtime.felk.cvut.cz Git - mirosot.git/blob - bluez_test/hcitest.c
Baudrate for Bluetooth is wrong - we have to use RAW divider.
[mirosot.git] / bluez_test / hcitest.c
1 #include <stdlib.h>
2 #include <unistd.h>
3 #include <sys/poll.h>
4 #include <errno.h>
5 #include <sys/ioctl.h>
6
7 #include <bluetooth/bluetooth.h>
8 #include <bluetooth/hci.h>
9 #include <bluetooth/hci_lib.h>
10
11 int chosen_dev_id = -1;           /* BB device id*/
12
13 static int dev_info(int socket, int dev_id, long arg)
14 {
15     struct hci_dev_info di;
16     char addr[18];
17     int err;
18
19     /* Ziskej informace o BT zarizeni */
20     err = hci_devinfo(dev_id, &di);
21
22     if (err)  return err;
23
24     ba2str(&di.bdaddr, addr);
25     printf("\t%s\t%s", di.name, addr);
26     
27     printf(" flags: ");
28
29     if (hci_test_bit(HCI_RAW, &di.flags)) printf("RAW ");
30     else printf("~RAW");
31
32     if (chosen_dev_id == -1)  {
33         /* Uloz prvni nalezene dev_id */
34         chosen_dev_id = dev_id;
35         printf(" default");
36     }
37     printf("\n");
38
39     return err;
40 }
41
42
43 /* Projed vsechny lokalni BT zarizeni a pro kazde z nich zavolej fci
44  * dev_info() */
45 void najdi_zarizeni()
46 {
47     int ret;
48
49     printf("Nalezene lokalni BT zarizeni:\n");
50     ret = hci_for_each_dev(HCI_UP, dev_info, 0);
51
52     /* v knihovne je chyba - vraci to -1 i kdyz bylo volani uspesne) */
53     if (ret && chosen_dev_id == -1) {
54         perror("hledani zarizeni");
55         exit(1);
56     }
57 }
58
59 /* Otevri BT zarizeni */
60 int otevri_bt()
61 {
62     int dd;                     /* BT device descriptor se kterym
63                                  * budeme pracovat*/
64
65     dd = hci_open_dev(chosen_dev_id);
66     if (dd == -1) {
67         perror("hci_open_dev");
68         exit(1);
69     }
70
71     /* Nasta RAW rezim, aby data nebyly zpracovavany l2cap vrstvou. */
72     if (ioctl(dd, HCISETRAW, 1) < 0) {
73         perror("Can't set RAW mode");
74         exit(1);
75     }
76     return dd;
77 }
78
79
80 /* Najdi okolni zarizeni */
81 void scan(int dd)
82 {
83     uint8_t lap[3] = { 0x33, 0x8b, 0x9e };
84     int inq_length = 10;        /* sekund */
85     inquiry_info *info = NULL;  /* informace o zarizenich */
86     int num_rsp;
87     long flags = 0;
88     int i;
89     
90
91     //flags |= IREQ_CACHE_FLUSH;  /* Vycisti cache */
92
93     printf("Scanuji... (%d sekund)\n", inq_length);
94     num_rsp = hci_inquiry(chosen_dev_id, 
95                           (int)(inq_length / 1.28),
96                           0, /* Najdi vsechna zarizeni */
97                           lap,
98                           &info, /* sem uloz ukazatel na nalezena
99                                   * zarizeni */
100                           flags);
101     char addr[18], name[249];
102     
103     /* Zjisti jmena nalezenych zarizeni a vse vypis */
104     for (i = 0; i < num_rsp; i++) {
105         int ret;
106         ba2str(&info[i].bdaddr, addr);
107         
108         ret = hci_read_remote_name(dd,
109                                    &info[i].bdaddr,
110                                    sizeof(name), name, 
111                                    100000); /* timeout v milisekundach*/
112         if (ret < 0)
113             strcpy(name, "n/a"); /* Jmeno neexistuje */
114         
115         printf("\t%s\t%s\n", addr, name);
116     }
117     bt_free(info);              /* uvolni pamet */
118 }
119
120
121 /* Spoj se s protejskem */
122 uint16_t spojse(int dd, bdaddr_t bdaddr)
123 {
124     uint8_t allow_role_switch = 0x01;
125     uint16_t ptype = HCI_DM1 | HCI_DM3 | HCI_DM5 | HCI_DH1 | HCI_DH3 | HCI_DH5;
126     uint16_t handle;
127     struct hci_filter flt;
128     int ret;
129
130     /* Nastav filter, aby nam chodily vsechny HCI pakety */
131     hci_filter_clear(&flt);
132     hci_filter_all_ptypes(&flt);
133     hci_filter_all_events(&flt);
134     if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
135         perror("Can't set filter");
136         exit(1);
137     }
138
139
140
141     printf("Navazuji spojeni\n");
142     ret = hci_create_connection(dd,
143                                 &bdaddr,
144                                 ptype, htobs(0x0000), 
145                                 allow_role_switch, 
146                                 &handle, 
147                                 10000); /* timeout */
148     if (ret < 0) {
149         perror("Spojeni nelze navazat");
150         exit(1);
151     }
152     return handle;
153 }
154
155 /* Ukazka jak posilat HCI pakety. Paket je slozen ze 3 casti: typ paketu, hlavicka a data */
156 int sendstr(int dd, uint16_t handle, char *buf)
157 {
158     uint8_t type = HCI_ACLDATA_PKT;
159     hci_acl_hdr acl_hdr;
160     struct iovec iv[3];
161
162     acl_hdr.handle = htobs(handle);
163     acl_hdr.dlen = htobs(strlen(buf));
164
165     /* sloz paket ze tri casti (typ, hlavicka, data) */
166     iv[0].iov_base = &type;
167     iv[0].iov_len  = 1;
168     iv[1].iov_base = &acl_hdr;
169     iv[1].iov_len  = HCI_ACL_HDR_SIZE;
170         
171     iv[2].iov_base = buf;
172     iv[2].iov_len  = acl_hdr.dlen;
173     
174     printf("Sending %d\n", strlen(buf));
175     while (writev(dd, iv, 3) < 0) {
176         if (errno == EAGAIN || errno == EINTR)
177             continue;
178         return -1;
179     }
180     return 0;
181 }
182
183 static void hex_dump(char *pref, int width, unsigned char *buf, int len)
184 {
185     register int i,n;
186
187     for (i = 0, n = 1; i < len; i++, n++) {
188         if (n == 1)
189             printf("%s", pref);
190         printf("%2.2X ", buf[i]);
191         if (n == width) {
192             printf("\n");
193             n = 0;
194         }
195     }
196     if (i && n!=1)
197         printf("\n");
198 }
199
200
201
202 int recvstr(int dd, uint16_t handle, char *str, int len)
203 {
204     unsigned char buf[200];
205     struct hci_acl_hdr *acl_hdr;
206     
207     while ((len = read(dd, buf, sizeof(buf))) < 0) {
208         if (errno == EAGAIN || errno == EINTR)
209             continue;
210         goto failed;
211     }
212
213     switch (buf[0]) {
214         case HCI_ACLDATA_PKT:
215             printf("ACL DATA: ");
216             acl_hdr = (struct hci_acl_hdr *)(buf+1);
217             break;
218         case HCI_SCODATA_PKT:
219             printf("SCO DATA: ");
220             break;
221         case HCI_EVENT_PKT:
222             printf("EVENT: ");
223             break;
224     }
225
226     hex_dump("content: ", 16, &buf[1], len - 1);
227     return 0;
228 failed:
229     return -1;
230 }
231
232 void komunikuj(int dd, uint16_t handle)
233 {
234     int end = 0;
235     int ret;
236
237     struct pollfd p[2];
238
239     p[0].fd = fileno(stdin);
240     p[0].events = POLLIN;
241     p[1].fd = dd;
242     p[1].events = POLLIN;
243     
244     while (!end) {
245         ret = poll(p, 2, 1000);
246         if (ret > 0) {
247             char buf[100];
248             
249             if (p[0].revents & POLLIN) {
250                 if (fgets(buf, 99, stdin) != NULL)
251                     sendstr(dd, handle, buf); /* posli data */
252                 else end = 1; /* konec (Ctrl-D) */
253             }
254             if (p[1].revents & POLLIN) {
255                 recvstr(dd, handle, buf, 99);
256                 printf("%s", buf);
257             }
258         } else if (ret < 0) {
259             perror("poll");
260             exit(1);
261         }
262     }
263 }
264
265
266 int main(int argc, char *argv[])
267 {
268     int dd;
269
270     najdi_zarizeni();
271
272     dd = otevri_bt();
273
274     if (argc < 2) {
275         scan(dd);
276         printf("Ocekavam jako parametr BD adresu\n");
277     } else {
278         char bdstr[20];
279         bdaddr_t bdaddr;
280         uint16_t handle;
281
282         strncpy(bdstr, argv[1], sizeof(bdstr));
283         str2ba(bdstr, &bdaddr);
284
285         /* Navaz ACL spojeni */
286         handle = spojse(dd, bdaddr);
287
288         /* Posilej pakety - nefunguje to. Je potreba nastavit dalsi veci pomoci HCI prikazu */
289         komunikuj(dd, handle);
290
291         printf("Rusim spojeni\n");
292         hci_disconnect(dd, handle, HCI_OE_USER_ENDED_CONNECTION, 10000);
293     }
294
295     if (ioctl(dd, HCISETRAW, 0) < 0) {
296         perror("Can't reset RAW mode");
297         exit(1);
298     }
299
300     /* Zavri BT zarizeni */
301     hci_close_dev(dd);
302
303
304     return 0;
305 }