Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp938288pxf; Wed, 7 Apr 2021 15:33:59 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzC2iGZAaJ7Cb0cA5pb7WZhTpOKGZyYN4jacjy0Zre9cQzPHdwWIQCRKtb9HXYpZhabP6kP X-Received: by 2002:a17:906:c08f:: with SMTP id f15mr6519133ejz.318.1617834839698; Wed, 07 Apr 2021 15:33:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1617834839; cv=none; d=google.com; s=arc-20160816; b=NXF31zwE2rJy4Zj3YzxASS5IpqF0P7/j18yV3PEtdsKieq1Ln/I6qStGHMF5jJMkr2 tQxe9zAozWuiND/ymzvRZypThpD1N3odfKigJAbCdR96RovmwMLwXbN8i+3NKpx7md8u d3HGbU2SN7bo+ppkU2EvtRKrYOcV3+nCYrNNfjYwIeGqUzzzU+K2NxCiCgEuDI9CZnga fnwE7mX3KsRQonJrZm6XnC/mpe04ZjtHUYYilpGzr7z2z5lXkdjk6FmxFKvHpXiAlqyj 5UyaPHzbF2aW6zSP+3enNmJqnmpSnEtKQXdKfJKO7gn7CFzjZ9DWvNyiv1BPpea+8e7K bAUQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:mime-version:message-id:date :dkim-signature; bh=z5xITeATKBgmYLo/GqpbsuwzH79+EZP5gqcHP+s9QWw=; b=KbvLdL+FrgITGO2kZPkWn8HkvXXrADKrYQY6npm5Ba9TNG0DUTRVlvdupfSWJRcSzk q/wr2LT54pA9V+FmrVlbV3AApgA292FMgyD1K5kpdDC8cEUUDtRD3PfEJY4x2OkIzUd8 wHHE7mfhQFi/A64CzIZle9niWOoiBTVPweytnovSZuTa1jcZzj+27KXhMPQzJ/WwmaLO gcTwyJQNiDYDV/Z/9hs+ggQX7rMW4B7RzKV6ivgBsoZoSVfhBthbQgH39B2GVj1793RW nrldrXX6IjloopAu2Nqm9c1TBSft3mjd7WFztVHF0R4Lm4ZNBqtZjcPknJ7qVB6/gVmM kFbA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=km+NboSP; spf=pass (google.com: domain of linux-bluetooth-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-bluetooth-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id m26si21522279edv.514.2021.04.07.15.33.23; Wed, 07 Apr 2021 15:33:59 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-bluetooth-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=km+NboSP; spf=pass (google.com: domain of linux-bluetooth-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-bluetooth-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347127AbhDGIiP (ORCPT + 99 others); Wed, 7 Apr 2021 04:38:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54872 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S245372AbhDGIiP (ORCPT ); Wed, 7 Apr 2021 04:38:15 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6013DC06174A for ; Wed, 7 Apr 2021 01:38:05 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id i6so23228508ybk.2 for ; Wed, 07 Apr 2021 01:38:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:message-id:mime-version:subject:from:to:cc; bh=z5xITeATKBgmYLo/GqpbsuwzH79+EZP5gqcHP+s9QWw=; b=km+NboSPEyhVeEb458vBzHP7v70lRWfO1iaSRKBhotrmy34BT/uqkimR+9Z17WW6YX gLkP1LPn55mzIN0kVMfnjEBivYY1Zv7FemIW+ZAS4JU0Gx7ks9ttgJnrPpMAV/KYgpOT PJ2pF7WJg+RNQ8oiqVlnDDfc9wm5UihB+r3SdpvEAKKG913AsWrxIWMlDjdOd9A/roD0 bN8i4tkMdS+1d03be7uTlyrX3HNvrUXI/rYzXRGoplQXkXJ+wjHdkbpArPlkMIlmP7A9 szmXU9MwP0z1AKl9q5auRXcMbn4ObHo9bKzAF5LOZCEuOVXtV36U6H9e/XVGC54UBDaU Rupg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=z5xITeATKBgmYLo/GqpbsuwzH79+EZP5gqcHP+s9QWw=; b=rMkLa3ha5DwE2GIHPG55KDkbSQO/tx2ehmSX0SILkbS3KFNzl9NSPMjcqPzMdZxXnY iot/FxBPBnD1SWPxbPZQXajcTQrk4mo0ZD+5hlB8uxbF1AGeTw75d0+TJMN5xfdYERdx MtllgswiDPWN8UBr3BKjX30gIqK5PaOMymfU+Hi+yXs4rQaAfwWuXIuuqjmEeuSRz/OJ DjAxDNLKC1lc0mBcpTtHWJzQKYT4sdPfirYTRR6ToYw/lsxfrh2tEzjIOIxL3Q5QMh1k fm4X9vnKZbLPd7Z7PkXpiwGlCIgq8ET1B8ywVpv88R2e7tH4RgwO4Y6mBpPMAEEHQS39 MwHg== X-Gm-Message-State: AOAM532yeYG+G8UKP4RHl27OBRaQ+zAREPoPSuV5HoIGdkr0ZZdCkVxg UiKtfBGapQ6vyYCc3N9l933MqNF5NIWDfY+LCGUaoNjjdXZpGZzPSFaCgNm8qKAlMR0yMvAINpL uDBFkcwm73+U9PItt8Z3wk85K5l9u1MdMoIOiHYfXFBjtLR+7QD+Rq+fyu1jaWTYDY243cBnyx1 ID X-Received: from apusaka-p920.tpe.corp.google.com ([2401:fa00:1:b:7515:f813:8ede:d08c]) (user=apusaka job=sendgmr) by 2002:a25:df81:: with SMTP id w123mr2954751ybg.436.1617784684582; Wed, 07 Apr 2021 01:38:04 -0700 (PDT) Date: Wed, 7 Apr 2021 16:37:45 +0800 Message-Id: <20210407163723.Bluez.v2.1.I4ff127dde9bc6adb2a07507af2bf2cc6b6bcf0f2@changeid> Mime-Version: 1.0 X-Mailer: git-send-email 2.31.0.208.g409f899ff0-goog Subject: [Bluez PATCH v2] input/hog: support multiple variable length notification From: Archie Pusaka To: linux-bluetooth , Luiz Augusto von Dentz Cc: CrosBT Upstreaming , Archie Pusaka , Sonny Sasaka Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Archie Pusaka Processing Multiple Variable Length Notification is mandatory if EATT is enabled (Core Spec Vol 3 Part G Sec 4.2). Reviewed-by: Sonny Sasaka --- Changes in v2: * fix compilation error attrib/att.h | 1 + profiles/input/hog-lib.c | 109 ++++++++++++++++++++++++++++----------- src/attrib-server.c | 1 + 3 files changed, 81 insertions(+), 30 deletions(-) diff --git a/attrib/att.h b/attrib/att.h index 13a0c3a31f..0dbfb14b83 100644 --- a/attrib/att.h +++ b/attrib/att.h @@ -42,6 +42,7 @@ #define ATT_OP_HANDLE_NOTIFY 0x1B #define ATT_OP_HANDLE_IND 0x1D #define ATT_OP_HANDLE_CNF 0x1E +#define ATT_OP_HANDLE_NOTIFY_MULTI 0x23 #define ATT_OP_SIGNED_WRITE_CMD 0xD2 /* Error codes for Error response PDU */ diff --git a/profiles/input/hog-lib.c b/profiles/input/hog-lib.c index e5e3d3e7f5..aa6c64a3f2 100644 --- a/profiles/input/hog-lib.c +++ b/profiles/input/hog-lib.c @@ -65,7 +65,6 @@ #define HOG_REPORT_MAP_MAX_SIZE 512 #define HID_INFO_SIZE 4 -#define ATT_NOTIFICATION_HEADER_SIZE 3 struct bt_hog { int ref_count; @@ -112,7 +111,8 @@ struct report { uint16_t value_handle; uint8_t properties; uint16_t ccc_handle; - guint notifyid; + guint notify_id; + guint notify_multi_id; uint16_t len; uint8_t *value; }; @@ -283,22 +283,14 @@ static void find_included(struct bt_hog *hog, GAttrib *attrib, free(req); } -static void report_value_cb(const guint8 *pdu, guint16 len, gpointer user_data) +static void process_notification(struct report *report, guint16 len, + const uint8_t *data) { - struct report *report = user_data; struct bt_hog *hog = report->hog; struct uhid_event ev; uint8_t *buf; int err; - if (len < ATT_NOTIFICATION_HEADER_SIZE) { - error("Malformed ATT notification"); - return; - } - - pdu += ATT_NOTIFICATION_HEADER_SIZE; - len -= ATT_NOTIFICATION_HEADER_SIZE; - memset(&ev, 0, sizeof(ev)); ev.type = UHID_INPUT; buf = ev.u.input.data; @@ -306,19 +298,78 @@ static void report_value_cb(const guint8 *pdu, guint16 len, gpointer user_data) if (hog->has_report_id) { buf[0] = report->id; len = MIN(len, sizeof(ev.u.input.data) - 1); - memcpy(buf + 1, pdu, len); - ev.u.input.size = ++len; + memcpy(buf + 1, data, len); + ev.u.input.size = len + 1; } else { len = MIN(len, sizeof(ev.u.input.data)); - memcpy(buf, pdu, len); + memcpy(buf, data, len); ev.u.input.size = len; } err = bt_uhid_send(hog->uhid, &ev); - if (err < 0) { + if (err < 0) error("bt_uhid_send: %s (%d)", strerror(-err), -err); - return; +} + +static void report_value_cb(const guint8 *pdu, guint16 len, gpointer user_data) +{ + struct report *report = user_data; + uint8_t opcode = pdu[0]; + guint16 report_len; + guint16 header_len; + + /* Skip opcode field */ + pdu += 1; + len -= 1; + + if (opcode == ATT_OP_HANDLE_NOTIFY_MULTI) + header_len = 4; + else + header_len = 2; + + if (len < header_len) + goto fail; + + while (len >= header_len) { + /* Skip first 2 bytes (handle) */ + pdu += 2; + len -= 2; + + if (opcode == ATT_OP_HANDLE_NOTIFY_MULTI) { + report_len = get_le16(pdu); + pdu += 2; + len -= 2; + + if (report_len > len) + goto fail; + } else { + report_len = len; + } + + process_notification(report, report_len, pdu); + + pdu += report_len; + len -= report_len; } + + if (len == 0) + return; + +fail: + error("Malformed ATT notification"); +} + +static void register_notify_handler(struct bt_hog *hog, struct report *report) +{ + report->notify_id = g_attrib_register(hog->attrib, + ATT_OP_HANDLE_NOTIFY, + report->value_handle, + report_value_cb, report, NULL); + + report->notify_multi_id = g_attrib_register(hog->attrib, + ATT_OP_HANDLE_NOTIFY_MULTI, + report->value_handle, + report_value_cb, report, NULL); } static void report_ccc_written_cb(guint8 status, const guint8 *pdu, @@ -336,13 +387,10 @@ static void report_ccc_written_cb(guint8 status, const guint8 *pdu, return; } - if (report->notifyid) + if (report->notify_id) return; - report->notifyid = g_attrib_register(hog->attrib, - ATT_OP_HANDLE_NOTIFY, - report->value_handle, - report_value_cb, report, NULL); + register_notify_handler(hog, report); DBG("Report characteristic descriptor written: notifications enabled"); } @@ -1711,13 +1759,10 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt) for (l = hog->reports; l; l = l->next) { struct report *r = l->data; - if (r->notifyid) + if (r->notify_id) continue; - r->notifyid = g_attrib_register(hog->attrib, - ATT_OP_HANDLE_NOTIFY, - r->value_handle, - report_value_cb, r, NULL); + register_notify_handler(hog, r); } return true; @@ -1764,9 +1809,13 @@ void bt_hog_detach(struct bt_hog *hog) for (l = hog->reports; l; l = l->next) { struct report *r = l->data; - if (r->notifyid > 0) { - g_attrib_unregister(hog->attrib, r->notifyid); - r->notifyid = 0; + if (r->notify_id > 0) { + g_attrib_unregister(hog->attrib, r->notify_id); + r->notify_id = 0; + } + if (r->notify_multi_id > 0) { + g_attrib_unregister(hog->attrib, r->notify_multi_id); + r->notify_multi_id = 0; } } diff --git a/src/attrib-server.c b/src/attrib-server.c index 5a178f95ea..fb11d3db2d 100644 --- a/src/attrib-server.c +++ b/src/attrib-server.c @@ -1085,6 +1085,7 @@ static void channel_handler(const uint8_t *ipdu, uint16_t len, return; case ATT_OP_HANDLE_IND: case ATT_OP_HANDLE_NOTIFY: + case ATT_OP_HANDLE_NOTIFY_MULTI: /* The attribute client is already handling these */ return; case ATT_OP_READ_MULTI_REQ: -- 2.31.0.208.g409f899ff0-goog