+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/poll.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+
+int chosen_dev_id = -1; /* BB device id*/
+
+static int dev_info(int socket, int dev_id, long arg)
+{
+ struct hci_dev_info di;
+ char addr[18];
+ int err;
+
+ /* Ziskej informace o BT zarizeni */
+ err = hci_devinfo(dev_id, &di);
+
+ if (err) return err;
+
+ ba2str(&di.bdaddr, addr);
+ printf("\t%s\t%s", di.name, addr);
+
+ printf(" flags: ");
+
+ if (hci_test_bit(HCI_RAW, &di.flags)) printf("RAW ");
+ else printf("~RAW");
+
+ if (chosen_dev_id == -1) {
+ /* Uloz prvni nalezene dev_id */
+ chosen_dev_id = dev_id;
+ printf(" default");
+ }
+ printf("\n");
+
+ return err;
+}
+
+
+/* Projed vsechny lokalni BT zarizeni a pro kazde z nich zavolej fci
+ * dev_info() */
+void najdi_zarizeni()
+{
+ int ret;
+
+ printf("Nalezene lokalni BT zarizeni:\n");
+ ret = hci_for_each_dev(HCI_UP, dev_info, 0);
+
+ /* v knihovne je chyba - vraci to -1 i kdyz bylo volani uspesne) */
+ if (ret && chosen_dev_id == -1) {
+ perror("hledani zarizeni");
+ exit(1);
+ }
+}
+
+/* Otevri BT zarizeni */
+int otevri_bt()
+{
+ int dd; /* BT device descriptor se kterym
+ * budeme pracovat*/
+
+ dd = hci_open_dev(chosen_dev_id);
+ if (dd == -1) {
+ perror("hci_open_dev");
+ exit(1);
+ }
+
+ /* Nasta RAW rezim, aby data nebyly zpracovavany l2cap vrstvou. */
+ if (ioctl(dd, HCISETRAW, 1) < 0) {
+ perror("Can't set RAW mode");
+ exit(1);
+ }
+ return dd;
+}
+
+
+/* Najdi okolni zarizeni */
+void scan(int dd)
+{
+ uint8_t lap[3] = { 0x33, 0x8b, 0x9e };
+ int inq_length = 10; /* sekund */
+ inquiry_info *info = NULL; /* informace o zarizenich */
+ int num_rsp;
+ long flags = 0;
+ int i;
+
+
+ //flags |= IREQ_CACHE_FLUSH; /* Vycisti cache */
+
+ printf("Scanuji... (%d sekund)\n", inq_length);
+ num_rsp = hci_inquiry(chosen_dev_id,
+ (int)(inq_length / 1.28),
+ 0, /* Najdi vsechna zarizeni */
+ lap,
+ &info, /* sem uloz ukazatel na nalezena
+ * zarizeni */
+ flags);
+ char addr[18], name[249];
+
+ /* Zjisti jmena nalezenych zarizeni a vse vypis */
+ for (i = 0; i < num_rsp; i++) {
+ int ret;
+ ba2str(&info[i].bdaddr, addr);
+
+ ret = hci_read_remote_name(dd,
+ &info[i].bdaddr,
+ sizeof(name), name,
+ 100000); /* timeout v milisekundach*/
+ if (ret < 0)
+ strcpy(name, "n/a"); /* Jmeno neexistuje */
+
+ printf("\t%s\t%s\n", addr, name);
+ }
+ bt_free(info); /* uvolni pamet */
+}
+
+
+/* Spoj se s protejskem */
+uint16_t spojse(int dd, bdaddr_t bdaddr)
+{
+ uint8_t allow_role_switch = 0x01;
+ uint16_t ptype = HCI_DM1 | HCI_DM3 | HCI_DM5 | HCI_DH1 | HCI_DH3 | HCI_DH5;
+ uint16_t handle;
+ struct hci_filter flt;
+ int ret;
+
+ /* Nastav filter, aby nam chodily vsechny HCI pakety */
+ hci_filter_clear(&flt);
+ hci_filter_all_ptypes(&flt);
+ hci_filter_all_events(&flt);
+ if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
+ perror("Can't set filter");
+ exit(1);
+ }
+
+
+
+ printf("Navazuji spojeni\n");
+ ret = hci_create_connection(dd,
+ &bdaddr,
+ ptype, htobs(0x0000),
+ allow_role_switch,
+ &handle,
+ 10000); /* timeout */
+ if (ret < 0) {
+ perror("Spojeni nelze navazat");
+ exit(1);
+ }
+ return handle;
+}
+
+/* Ukazka jak posilat HCI pakety. Paket je slozen ze 3 casti: typ paketu, hlavicka a data */
+int sendstr(int dd, uint16_t handle, char *buf)
+{
+ uint8_t type = HCI_ACLDATA_PKT;
+ hci_acl_hdr acl_hdr;
+ struct iovec iv[3];
+
+ acl_hdr.handle = htobs(handle);
+ acl_hdr.dlen = htobs(strlen(buf));
+
+ /* sloz paket ze tri casti (typ, hlavicka, data) */
+ iv[0].iov_base = &type;
+ iv[0].iov_len = 1;
+ iv[1].iov_base = &acl_hdr;
+ iv[1].iov_len = HCI_ACL_HDR_SIZE;
+
+ iv[2].iov_base = buf;
+ iv[2].iov_len = acl_hdr.dlen;
+
+ printf("Sending %d\n", strlen(buf));
+ while (writev(dd, iv, 3) < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ return -1;
+ }
+ return 0;
+}
+
+static void hex_dump(char *pref, int width, unsigned char *buf, int len)
+{
+ register int i,n;
+
+ for (i = 0, n = 1; i < len; i++, n++) {
+ if (n == 1)
+ printf("%s", pref);
+ printf("%2.2X ", buf[i]);
+ if (n == width) {
+ printf("\n");
+ n = 0;
+ }
+ }
+ if (i && n!=1)
+ printf("\n");
+}
+
+
+
+int recvstr(int dd, uint16_t handle, char *str, int len)
+{
+ unsigned char buf[200];
+ struct hci_acl_hdr *acl_hdr;
+
+ while ((len = read(dd, buf, sizeof(buf))) < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ goto failed;
+ }
+
+ switch (buf[0]) {
+ case HCI_ACLDATA_PKT:
+ printf("ACL DATA: ");
+ acl_hdr = (struct hci_acl_hdr *)(buf+1);
+ break;
+ case HCI_SCODATA_PKT:
+ printf("SCO DATA: ");
+ break;
+ case HCI_EVENT_PKT:
+ printf("EVENT: ");
+ break;
+ }
+
+ hex_dump("content: ", 16, &buf[1], len - 1);
+ return 0;
+failed:
+ return -1;
+}
+
+void komunikuj(int dd, uint16_t handle)
+{
+ int end = 0;
+ int ret;
+
+ struct pollfd p[2];
+
+ p[0].fd = fileno(stdin);
+ p[0].events = POLLIN;
+ p[1].fd = dd;
+ p[1].events = POLLIN;
+
+ while (!end) {
+ ret = poll(p, 2, 1000);
+ if (ret > 0) {
+ char buf[100];
+
+ if (p[0].revents & POLLIN) {
+ if (fgets(buf, 99, stdin) != NULL)
+ sendstr(dd, handle, buf); /* posli data */
+ else end = 1; /* konec (Ctrl-D) */
+ }
+ if (p[1].revents & POLLIN) {
+ recvstr(dd, handle, buf, 99);
+ printf("%s", buf);
+ }
+ } else if (ret < 0) {
+ perror("poll");
+ exit(1);
+ }
+ }
+}
+
+
+int main(int argc, char *argv[])
+{
+ int dd;
+
+ najdi_zarizeni();
+
+ dd = otevri_bt();
+
+ if (argc < 2) {
+ scan(dd);
+ printf("Ocekavam jako parametr BD adresu\n");
+ } else {
+ char bdstr[20];
+ bdaddr_t bdaddr;
+ uint16_t handle;
+
+ strncpy(bdstr, argv[1], sizeof(bdstr));
+ str2ba(bdstr, &bdaddr);
+
+ /* Navaz ACL spojeni */
+ handle = spojse(dd, bdaddr);
+
+ /* Posilej pakety - nefunguje to. Je potreba nastavit dalsi veci pomoci HCI prikazu */
+ komunikuj(dd, handle);
+
+ printf("Rusim spojeni\n");
+ hci_disconnect(dd, handle, HCI_OE_USER_ENDED_CONNECTION, 10000);
+ }
+
+ if (ioctl(dd, HCISETRAW, 0) < 0) {
+ perror("Can't reset RAW mode");
+ exit(1);
+ }
+
+ /* Zavri BT zarizeni */
+ hci_close_dev(dd);
+
+
+ return 0;
+}