From 163d14a25cec4bbe7bf906a3a3487756a47e42cf Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 6 May 2005 22:18:11 +0000 Subject: Store HID information for later use --- hidd/Makefile.am | 4 ++- hidd/hidd.h | 3 +- hidd/main.c | 16 ++++++++- hidd/sdp.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 119 insertions(+), 4 deletions(-) diff --git a/hidd/Makefile.am b/hidd/Makefile.am index 0860d265..cd8b4878 100644 --- a/hidd/Makefile.am +++ b/hidd/Makefile.am @@ -5,10 +5,12 @@ bin_PROGRAMS = hidd hidd_SOURCES = main.c hidd.h sdp.c -hidd_LDADD = @BLUEZ_LIBS@ +hidd_LDADD = @BLUEZ_LIBS@ $(top_builddir)/common/libtextfile.a AM_CFLAGS = @BLUEZ_CFLAGS@ +INCLUDES = -I$(top_srcdir)/common + man_MANS = hidd.1 EXTRA_DIST = $(man_MANS) diff --git a/hidd/hidd.h b/hidd/hidd.h index cd0c102c..ab8a94ec 100644 --- a/hidd/hidd.h +++ b/hidd/hidd.h @@ -29,4 +29,5 @@ #define L2CAP_PSM_HIDP_CTRL 0x11 #define L2CAP_PSM_HIDP_INTR 0x13 -int get_hid_device_info(bdaddr_t *src, bdaddr_t *dst, struct hidp_connadd_req *req); +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); diff --git a/hidd/main.c b/hidd/main.c index 84d94b78..25567c9e 100644 --- a/hidd/main.c +++ b/hidd/main.c @@ -258,8 +258,12 @@ static int create_device(int ctl, int csk, int isk, uint8_t subclass, int nosdp, req.flags = 0; req.idle_to = timeout * 60; + err = get_stored_device_info(&src, &dst, &req); + if (!err) + goto create; + if (!nosdp) { - err = get_hid_device_info(&src, &dst, &req); + err = get_sdp_device_info(&src, &dst, &req); if (err < 0) goto error; } else { @@ -280,6 +284,7 @@ static int create_device(int ctl, int csk, int isk, uint8_t subclass, int nosdp, req.subclass = 0xc0; } +create: if (subclass != 0x00) req.subclass = subclass; @@ -399,8 +404,17 @@ 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) { + struct hidp_connadd_req req; int csk, isk, err; + memset(&req, 0, sizeof(req)); + + if (get_sdp_device_info(src, dst, &req) < 0) { + perror("Can't get device information"); + close(ctl); + exit(1); + } + csk = l2cap_connect(src, dst, L2CAP_PSM_HIDP_CTRL); if (csk < 0) { perror("Can't create HID control channel"); diff --git a/hidd/sdp.c b/hidd/sdp.c index 24ed4b53..c202c763 100644 --- a/hidd/sdp.c +++ b/hidd/sdp.c @@ -32,6 +32,12 @@ #include #include +#include +#include +#include +#include +#include +#include #include #include @@ -39,6 +45,7 @@ #include #include +#include "textfile.h" #include "hidd.h" static void epox_endian_quirk(unsigned char *data, int size) @@ -66,7 +73,96 @@ static void epox_endian_quirk(unsigned char *data, int size) } } -int get_hid_device_info(bdaddr_t *src, bdaddr_t *dst, struct hidp_connadd_req *req) +static int store_device_info(const bdaddr_t *src, const bdaddr_t *dst, struct hidp_connadd_req *req) +{ + char filename[PATH_MAX + 1], addr[18], *str, *desc; + int i, fd, size; + + ba2str(src, addr); + snprintf(filename, PATH_MAX, "%s/%s/hidd", STORAGEDIR, addr); + + size = 15 + 3 + 3 + 5 + (req->rd_size * 2) + 1 + 9 + strlen(req->name) + 2; + str = malloc(size); + if (!str) + return -ENOMEM; + + desc = malloc((req->rd_size * 2) + 1); + if (!desc) { + free(str); + return -ENOMEM; + } + + memset(desc, 0, (req->rd_size * 2) + 1); + for (i = 0; i < req->rd_size; i++) + sprintf(desc + (i * 2), "%2.2X", req->rd_data[i]); + + snprintf(str, size - 1, "%04X:%04X:%04X %02X %02X %04X %s %08X %s", + req->vendor, req->product, req->version, + req->subclass, req->country, req->parser, desc, + req->flags, req->name); + + fd = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (fd < 0) + return -errno; + + close(fd); + + ba2str(dst, addr); + return textfile_put(filename, addr, str); +} + +int get_stored_device_info(const bdaddr_t *src, const bdaddr_t *dst, struct hidp_connadd_req *req) +{ + char filename[PATH_MAX + 1], addr[18], tmp[3], *str, *desc; + unsigned int vendor, product, version, subclass, country, parser, pos; + int i; + + desc = malloc(4096); + if (!desc) + return -ENOMEM; + + memset(desc, 0, 4096); + + ba2str(src, addr); + snprintf(filename, PATH_MAX, "%s/%s/hidd", STORAGEDIR, addr); + + ba2str(dst, addr); + str = textfile_get(filename, addr); + if (!str) { + free(desc); + return -EIO; + } + + sscanf(str, "%04X:%04X:%04X %02X %02X %04X %4095s %08X %n", + &vendor, &product, &version, &subclass, &country, + &parser, desc, &req->flags, &pos); + + free(str); + + req->vendor = vendor; + req->product = product; + req->version = version; + req->subclass = subclass; + req->country = country; + req->parser = parser; + + snprintf(req->name, 128, str + pos); + + req->rd_size = strlen(desc) / 2; + req->rd_data = malloc(req->rd_size); + if (!req->rd_data) + return -ENOMEM; + + memset(tmp, 0, sizeof(tmp)); + for (i = 0; i < req->rd_size; i++) { + memcpy(tmp, desc + (i * 2), 2); + req->rd_data[i] = (uint8_t) strtol(tmp, NULL, 16); + } + + return 0; +} + +int get_sdp_device_info(const bdaddr_t *src, const bdaddr_t *dst, struct hidp_connadd_req *req) { uint32_t range = 0x0000ffff; sdp_session_t *s; @@ -163,5 +259,7 @@ int get_hid_device_info(bdaddr_t *src, bdaddr_t *dst, struct hidp_connadd_req *r sdp_record_free(rec); + store_device_info(src, dst, req); + return 0; } -- cgit