diff options
-rw-r--r-- | input/device.c | 37 | ||||
-rw-r--r-- | src/device.c | 18 | ||||
-rw-r--r-- | src/device.h | 2 | ||||
-rw-r--r-- | src/storage.c | 54 | ||||
-rw-r--r-- | src/storage.h | 5 |
5 files changed, 98 insertions, 18 deletions
diff --git a/input/device.c b/input/device.c index d2ca1fdf..8391326e 100644 --- a/input/device.c +++ b/input/device.c @@ -598,8 +598,9 @@ cleanup: g_free(req); } -static int hidp_add_connection(const bdaddr_t *src, const bdaddr_t *dst, int ctrl_sk, - int intr_sk, int timeout, const char *name, const uint32_t handle) +static int hidp_add_connection(const struct input_device *idev, + const struct input_conn *iconn) + { struct hidp_connadd_req *req; struct fake_hid *fake_hid; @@ -609,15 +610,15 @@ static int hidp_add_connection(const bdaddr_t *src, const bdaddr_t *dst, int ctr int err; req = g_new0(struct hidp_connadd_req, 1); - req->ctrl_sock = ctrl_sk; - req->intr_sock = intr_sk; + req->ctrl_sock = iconn->ctrl_sk; + req->intr_sock = iconn->intr_sk; req->flags = 0; - req->idle_to = timeout; + req->idle_to = iconn->timeout; - ba2str(src, src_addr); - ba2str(dst, dst_addr); + ba2str(&idev->src, src_addr); + ba2str(&idev->dst, dst_addr); - rec = fetch_record(src_addr, dst_addr, handle); + rec = fetch_record(src_addr, dst_addr, idev->handle); if (!rec) { error("Rejected connection from unknown device %s", dst_addr); err = -EPERM; @@ -627,22 +628,25 @@ static int hidp_add_connection(const bdaddr_t *src, const bdaddr_t *dst, int ctr extract_hid_record(rec, req); sdp_record_free(rec); + read_pnp(src_addr, dst_addr, &req->vendor, &req->product, + &req->version); + fake_hid = get_fake_hid(req->vendor, req->product); if (fake_hid) { fake = g_new0(struct fake_input, 1); fake->connect = fake_hid_connect; fake->disconnect = fake_hid_disconnect; fake->priv = fake_hid; - err = fake_hid_connadd(fake, intr_sk, fake_hid); + err = fake_hid_connadd(fake, iconn->intr_sk, fake_hid); goto cleanup; } - if (name) - strncpy(req->name, name, 128); + if (idev->name) + strncpy(req->name, idev->name, 128); /* Encryption is mandatory for keyboards */ if (req->subclass & 0x40) { - err = bt_acl_encrypt(src, dst, encrypt_completed, req); + err = bt_acl_encrypt(&idev->src, &idev->dst, encrypt_completed, req); if (err == 0) { /* Waiting async encryption */ return 0; @@ -657,7 +661,7 @@ static int hidp_add_connection(const bdaddr_t *src, const bdaddr_t *dst, int ctr if (req->vendor == 0x054c && req->product == 0x0268) { unsigned char buf[] = { 0x53, 0xf4, 0x42, 0x03, 0x00, 0x00 }; - err = write(ctrl_sk, buf, sizeof(buf)); + err = write(iconn->ctrl_sk, buf, sizeof(buf)); } err = ioctl_connadd(req); @@ -683,9 +687,7 @@ static void interrupt_connect_cb(GIOChannel *chan, int err, const bdaddr_t *src, } iconn->intr_sk = g_io_channel_unix_get_fd(chan); - err = hidp_add_connection(&idev->src, &idev->dst, - iconn->ctrl_sk, iconn->intr_sk, - iconn->timeout, idev->name, idev->handle); + err = hidp_add_connection(idev, iconn); if (err < 0) goto failed; @@ -1202,8 +1204,7 @@ int input_device_connadd(const bdaddr_t *src, const bdaddr_t *dst) if (!iconn) return -ENOENT; - err = hidp_add_connection(src, dst, iconn->ctrl_sk, iconn->intr_sk, - iconn->timeout, idev->name, idev->handle); + err = hidp_add_connection(idev, iconn); if (err < 0) goto error; diff --git a/src/device.c b/src/device.c index a1d1575e..eadc9d51 100644 --- a/src/device.c +++ b/src/device.c @@ -830,6 +830,24 @@ static void update_services(struct browse_req *req, sdp_list_t *recs) if (!uuid_str) continue; + if (!strcasecmp(uuid_str, PNP_UUID)) { + uint16_t vendor, product, version; + sdp_data_t *pdlist; + + pdlist = sdp_data_get(rec, SDP_ATTR_VENDOR_ID); + vendor = pdlist ? pdlist->val.uint16 : 0x0000; + + pdlist = sdp_data_get(rec, SDP_ATTR_PRODUCT_ID); + product = pdlist ? pdlist->val.uint16 : 0x0000; + + pdlist = sdp_data_get(rec, SDP_ATTR_VERSION); + version = pdlist ? pdlist->val.uint16 : 0x0000; + + if (vendor || product || version) + store_pnp(srcaddr, dstaddr, vendor, product, + version); + } + /* Driver uuid found */ l = g_slist_find_custom(req->uuids, uuid_str, (GCompareFunc) strcasecmp); diff --git a/src/device.h b/src/device.h index d2331173..21f7ffaa 100644 --- a/src/device.h +++ b/src/device.h @@ -45,6 +45,8 @@ uint8_t device_get_auth(struct btd_device *device); #define BTD_UUIDS(args...) ((const char *[]) { args, NULL } ) +#define PNP_UUID "00001200-0000-1000-8000-00805f9b34fb" + struct btd_device_driver { const char *name; const char **uuids; diff --git a/src/storage.c b/src/storage.c index 0690fc1a..559c3b12 100644 --- a/src/storage.c +++ b/src/storage.c @@ -810,3 +810,57 @@ int delete_record(const gchar *src, const gchar *dst, const uint32_t handle) return textfile_del(filename, key); } + +int store_pnp(const gchar *src, const gchar *dst, const uint16_t vendor, + const uint16_t product, const uint16_t version) +{ + char filename[PATH_MAX + 1], str[15]; + + create_name(filename, PATH_MAX, STORAGEDIR, src, "pnp"); + + create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + + snprintf(str, sizeof(str), "%04X %04X %04X", vendor, product, version); + + return textfile_put(filename, dst, str); +} + +int read_pnp(const gchar *src, const gchar *dst, uint32_t *vendor, + uint16_t *product, uint16_t *version) +{ + char filename[PATH_MAX + 1]; + char *str, *product_str, *version_str; + + create_name(filename, PATH_MAX, STORAGEDIR, src, "pnp"); + + str = textfile_get(filename, dst); + + if (!str) + return -ENOENT; + + product_str = strchr(str, ' '); + if (!product_str) { + free(str); + return -ENOENT; + } + *(product_str++) = 0; + + version_str = strchr(product_str, ' '); + if (!version_str) { + free(str); + return -ENOENT; + } + *(version_str++) = 0; + + if (vendor) + *vendor = (uint16_t) strtol(str, NULL, 16); + + if (product) + *product = (uint16_t) strtol(product_str, NULL, 16); + + if (version) + *version = (uint16_t) strtol(version_str, NULL, 16); + + free(str); + return 0; +} diff --git a/src/storage.h b/src/storage.h index 7f89ef19..a4eb82da 100644 --- a/src/storage.h +++ b/src/storage.h @@ -59,3 +59,8 @@ int delete_entry(bdaddr_t *src, const char *storage, const char *key); int store_record(const gchar *src, const gchar *dst, sdp_record_t *rec); sdp_record_t *fetch_record(const gchar *src, const gchar *dst, const uint32_t handle); int delete_record(const gchar *src, const gchar *dst, const uint32_t handle); + +int store_pnp(const gchar *src, const gchar *dst, const uint16_t vendor, + const uint16_t product, const uint16_t version); +int read_pnp(const gchar *src, const gchar *dst, uint32_t *vendor, + uint16_t *product, uint16_t *version); |