From 3e9d510274d6560e026c76dc3ecf415db0dd7e68 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 14 Nov 2005 12:18:09 +0000 Subject: Add initial fake HID support --- hidd/Makefile.am | 2 +- hidd/fakehid.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ hidd/hidd.h | 4 ++++ hidd/main.c | 52 +++++++++++++++++++++++++++++++++++++++++++++------- hidd/sdp.c | 19 +++++++++++++++++++ 5 files changed, 118 insertions(+), 8 deletions(-) create mode 100644 hidd/fakehid.c diff --git a/hidd/Makefile.am b/hidd/Makefile.am index 4dfbb56e..cc043457 100644 --- a/hidd/Makefile.am +++ b/hidd/Makefile.am @@ -1,7 +1,7 @@ bin_PROGRAMS = hidd -hidd_SOURCES = main.c hidd.h sdp.c +hidd_SOURCES = main.c hidd.h sdp.c fakehid.c hidd_LDADD = @BLUEZ_LIBS@ $(top_builddir)/common/libtextfile.a AM_CFLAGS = @BLUEZ_CFLAGS@ diff --git a/hidd/fakehid.c b/hidd/fakehid.c new file mode 100644 index 00000000..1483f022 --- /dev/null +++ b/hidd/fakehid.c @@ -0,0 +1,49 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2003-2005 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include +#include + +#include "hidd.h" + +#include +#include + +#include + +void epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) +{ +} + +void headset_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) +{ +} diff --git a/hidd/hidd.h b/hidd/hidd.h index c8103281..ca9712aa 100644 --- a/hidd/hidd.h +++ b/hidd/hidd.h @@ -26,3 +26,7 @@ int get_stored_device_info(const bdaddr_t *src, const bdaddr_t *dst, struct hidp_connadd_req *req); int get_sdp_device_info(const bdaddr_t *src, const bdaddr_t *dst, struct hidp_connadd_req *req); +int get_alternate_device_info(const bdaddr_t *src, const bdaddr_t *dst, uint16_t *uuid, uint8_t *channel); + +void epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel); +void headset_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel); diff --git a/hidd/main.c b/hidd/main.c index be50bf7a..ebb9b745 100644 --- a/hidd/main.c +++ b/hidd/main.c @@ -406,19 +406,42 @@ static void do_show(int ctl) } } -static void do_connect(int ctl, bdaddr_t *src, bdaddr_t *dst, uint8_t subclass, int nosdp, int encrypt, int timeout) +static void do_connect(int ctl, bdaddr_t *src, bdaddr_t *dst, uint8_t subclass, int fakehid, int encrypt, int timeout) { struct hidp_connadd_req req; + uint16_t uuid = HID_SVCLASS_ID; + uint8_t channel = 0; int csk, isk, err; memset(&req, 0, sizeof(req)); - if (get_sdp_device_info(src, dst, &req) < 0) { + err = get_sdp_device_info(src, dst, &req); + if (err < 0 && fakehid) + err = get_alternate_device_info(src, dst, &uuid, &channel); + + if (err < 0) { perror("Can't get device information"); close(ctl); exit(1); } + switch (uuid) { + case HID_SVCLASS_ID: + goto connect; + + case SERIAL_PORT_SVCLASS_ID: + epox_presenter(src, dst, channel); + break; + + case HEADSET_SVCLASS_ID: + case HANDSFREE_SVCLASS_ID: + headset_presenter(src, dst, channel); + break; + } + + return; + +connect: csk = l2cap_connect(src, dst, L2CAP_PSM_HIDP_CTRL); if (csk < 0) { perror("Can't create HID control channel"); @@ -446,7 +469,7 @@ static void do_connect(int ctl, bdaddr_t *src, bdaddr_t *dst, uint8_t subclass, } } -static void do_search(int ctl, bdaddr_t *bdaddr, uint8_t subclass, int nosdp, int encrypt, int timeout) +static void do_search(int ctl, bdaddr_t *bdaddr, uint8_t subclass, int fakehid, int encrypt, int timeout) { inquiry_info *info = NULL; bdaddr_t src, dst; @@ -477,10 +500,25 @@ static void do_search(int ctl, bdaddr_t *bdaddr, uint8_t subclass, int nosdp, in ba2str(&dst, addr); printf("\tConnecting to device %s\n", addr); - do_connect(ctl, &src, &dst, subclass, nosdp, encrypt, timeout); + do_connect(ctl, &src, &dst, subclass, fakehid, encrypt, timeout); + } + } + + if (!fakehid) + goto done; + + for (i = 0; i < num_rsp; i++) { + memcpy(class, (info+i)->dev_class, 3); + if (class[0] == 0x00 && class[1] == 0x40 && class[2] == 0x00) { + bacpy(&dst, &(info+i)->bdaddr); + ba2str(&dst, addr); + + printf("\tConnecting to device %s\n", addr); + do_connect(ctl, &src, &dst, subclass, 1, 0, timeout); } } +done: bt_free(info); if (!num_rsp) { @@ -591,7 +629,7 @@ int main(int argc, char *argv[]) char addr[18]; int log_option = LOG_NDELAY | LOG_PID; int opt, fd, ctl, csk, isk; - int mode = SHOW, daemon = 1, nosdp = 0, encrypt = 0, timeout = 30, lm = 0; + int mode = SHOW, daemon = 1, nosdp = 0, fakehid = 1, encrypt = 0, timeout = 30, lm = 0; bacpy(&bdaddr, BDADDR_ANY); @@ -685,12 +723,12 @@ int main(int argc, char *argv[]) break; case SEARCH: - do_search(ctl, &bdaddr, subclass, nosdp, encrypt, timeout); + do_search(ctl, &bdaddr, subclass, fakehid, encrypt, timeout); close(ctl); exit(0); case CONNECT: - do_connect(ctl, &bdaddr, &dev, subclass, nosdp, encrypt, timeout); + do_connect(ctl, &bdaddr, &dev, subclass, fakehid, encrypt, timeout); close(ctl); exit(0); diff --git a/hidd/sdp.c b/hidd/sdp.c index 6ed5d2dc..285438e8 100644 --- a/hidd/sdp.c +++ b/hidd/sdp.c @@ -267,3 +267,22 @@ int get_sdp_device_info(const bdaddr_t *src, const bdaddr_t *dst, struct hidp_co return 0; } + +int get_alternate_device_info(const bdaddr_t *src, const bdaddr_t *dst, uint16_t *uuid, uint8_t *channel) +{ + sdp_session_t *s; + + s = sdp_connect(src, dst, SDP_RETRY_IF_BUSY | SDP_WAIT_ON_CLOSE); + if (!s) + return -1; + + sdp_close(s); + + if (uuid) + *uuid = 0x0000; + + if (channel) + *channel = 0; + + return 0; +} -- cgit