--- /dev/null
+#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;
+}
--- /dev/null
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/poll.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/l2cap.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+
+#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] [<server bdaddr>]\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;
+}