From 446c775515f7e209df2671c8457e86c469305647 Mon Sep 17 00:00:00 2001 From: Nguyen Hoang Date: Wed, 28 Jun 2006 13:36:00 +0000 Subject: [PATCH] Added bluez_test applications. darcs-hash:20060628133653-5a954-34d4719d6abbd1f04484af02d9c9d86d330f07db.gz --- bluez_test/Makefile | 10 ++ bluez_test/hcitest.c | 305 +++++++++++++++++++++++++++++++++++++++++ bluez_test/l2captest.c | 178 ++++++++++++++++++++++++ 3 files changed, 493 insertions(+) create mode 100644 bluez_test/Makefile create mode 100644 bluez_test/hcitest.c create mode 100644 bluez_test/l2captest.c diff --git a/bluez_test/Makefile b/bluez_test/Makefile new file mode 100644 index 0000000..13390e8 --- /dev/null +++ b/bluez_test/Makefile @@ -0,0 +1,10 @@ +CFLAGS=-Wall -g + +all: hcitest l2captest + +# Vymaz implicitni pravidlo +%: %.c + +%: %.o + gcc -o $@ $^ -lbluetooth +# scp $@ steelbar:/home/wsh/bin diff --git a/bluez_test/hcitest.c b/bluez_test/hcitest.c new file mode 100644 index 0000000..ae8cdb8 --- /dev/null +++ b/bluez_test/hcitest.c @@ -0,0 +1,305 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +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; +} diff --git a/bluez_test/l2captest.c b/bluez_test/l2captest.c new file mode 100644 index 0000000..03a7de1 --- /dev/null +++ b/bluez_test/l2captest.c @@ -0,0 +1,178 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define MY_PSM 0x1001 /* Protocol/Service Multiplexor */ + +static bdaddr_t bdaddr; /* Adresa lokalniho BT zarizeni */ + + +void komunikuj(int sk) +{ + int end = 0; + int ret; + + struct pollfd p[2]; + + p[0].fd = fileno(stdin); + p[0].events = POLLIN; + p[1].fd = sk; + 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) + send(sk, buf, strlen(buf), 0); /* posli data */ + else end = 1; /* konec (Ctrl-D) */ + } + if (p[1].revents & POLLIN) { + ret = recv(sk, buf, 99, 0); + if (ret >= 0) buf[ret] = '\0'; + printf("%s", buf); + } + } else if (ret < 0) { + perror("poll"); + exit(1); + } + } +} + + +static void klient(char *dest) +{ + struct sockaddr_l2 addr; + int sk; + + /* Create socket */ + sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + if (sk < 0) { + perror("Can't create socket"); + exit(1); + } + + /* Bind to local address */ + memset(&addr, 0, sizeof(addr)); + bacpy(&addr.l2_bdaddr, &bdaddr); + addr.l2_family = AF_BLUETOOTH; + + if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + perror("Can't bind socket"); + close(sk); + exit(1); + } + + /* Connect to remote device */ + memset(&addr, 0, sizeof(addr)); + addr.l2_family = AF_BLUETOOTH; + str2ba(dest, &addr.l2_bdaddr); + addr.l2_psm = htobs(MY_PSM); + + if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + perror("Can't connect"); + close(sk); + exit(1); + } + printf("Spojeno (Ctrl-D konec)\n"); + + /* Komunikace */ + komunikuj(sk); + + /* Uzavri spojeni */ + close(sk); + +} + +static void server() +{ + struct sockaddr_l2 addr, client_addr; + int sk, sk2; + socklen_t addr_len; + + /* Create socket */ + sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + if (sk < 0) { + perror("Can't create socket"); + exit(1); + } + + /* Bind to local address */ + memset(&addr, 0, sizeof(addr)); + addr.l2_family = AF_BLUETOOTH; + bacpy(&addr.l2_bdaddr, &bdaddr); + addr.l2_psm = htobs(MY_PSM); /* Protocol/Service Multiplexor */ + + if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + perror("Can't bind socket"); + close(sk); + exit(1); + } + + /* Pockej az se pripoji klient */ + if (listen(sk, 1) < 0) { + perror("listen"); + close(sk); + exit(1); + } + + + printf("Cekam na spojeni...\n"); + addr_len = sizeof(client_addr); + sk2 = accept(sk, (struct sockaddr*)&client_addr, &addr_len); + printf("Spojeno (Ctrl-D konec)\n"); + + /* Komunikace */ + komunikuj(sk2); + + /* Uzavri spojeni */ + close(sk2); + close(sk); + +} + +static void usage(void) +{ + printf("l2captest - L2CAP test\n"); + printf("Usage:\n"); + printf("\tl2captest [-i device] []\n"); +} + +int main(int argc, char *argv[]) +{ + int opt; + + /* Default options */ + bacpy(&bdaddr, BDADDR_ANY); + + while ((opt=getopt(argc,argv,"i:")) != EOF) { + switch(opt) { + case 'i': /* likalni BT zarizeni (hciX nebo BD addresa) */ + if (!strncasecmp(optarg, "hci", 3)) + hci_devba(atoi(optarg + 3), &bdaddr); + else + str2ba(optarg, &bdaddr); + break; + + default: + usage(); + exit(1); + } + } + + if (!(argc - optind)) { + server(); /* ceka na pripojeni libovolneho klienta */ + } else + klient(argv[optind]); + + return 0; +} -- 2.39.2