Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp937632pxf; Wed, 7 Apr 2021 15:32:54 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwPqG9WV/vPN81grxUlHINMysIU7Jm8bVcTnzDj6DeYGTHiGexft+KFhUu3yuB/FEFwicCs X-Received: by 2002:a17:906:1115:: with SMTP id h21mr6747379eja.352.1617834774623; Wed, 07 Apr 2021 15:32:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1617834774; cv=none; d=google.com; s=arc-20160816; b=Pxpj7zcpARkKS/TDcR148sh67WePU4fxLh3GiuGfJnW80Lcmh8HTiMEKo4tSwhs3vZ fig7y8/5MjPENyR8PK2GBfTHCzGH2CxY9KTLsXJ6UYPDjt3N9/gY0v3A2hEK2Q98zI67 xRgZm6z0yVONC7Z3WJcnRcU/dFbidhNsUY1/AVSyxLsV1dNU/rCyaHXR545LZBhwLIZo ysST5I3sIauOZxW4t9DlI7mb8dr3kuDOU/oIyLYCLNBoX1nugnjSfW81coULZs2ENQfs tPr06omaRbgWRDX5NluBpF03O144ET7wrgr1CZ3f5mCADXoAAsp3Va0n0ScxW5oPZnze V/Vw== 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=q8b+vp+Kos0XCcWOwLv4FkdpawEhpj36zdSruePcwx0=; b=fl69Vbigaokny9PiB8mb3nuEsyQMC0aBYHR90bPanu6pxJINW8wFDMf06D9HdKtxo8 loZwu+1W+OtYVvHCby2/nDiqymTcNxUUkNaQ2brsSqrxMkzQVnBsjIzYtKE1GLDwLiin 2s5QogaVrQ2hcjuZNIfuNFMRMdlXg/q33dUCjx4r9omXXRDmzC/5tS2HcIYBHaoDyAtA pwzMAVSY3ZN0RfsjgaOom/ob3tRJenhTo7rg9M3459hg9J+hWpk/KrLutB82LuFdApTS rS1M54rBMNaz8h5838TquEeksQL3fGE0ucjbvEYQAlDrOU7ELfw2QFvPjodaPOz3jAxR AJgg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=IY4r7OiO; 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 lt25si4432164ejb.646.2021.04.07.15.31.23; Wed, 07 Apr 2021 15:32:54 -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=IY4r7OiO; 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 S243977AbhDGHRZ (ORCPT + 99 others); Wed, 7 Apr 2021 03:17:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37098 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239419AbhDGHRY (ORCPT ); Wed, 7 Apr 2021 03:17:24 -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 27838C06174A for ; Wed, 7 Apr 2021 00:17:15 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id k15so16604617ybh.6 for ; Wed, 07 Apr 2021 00:17:15 -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=q8b+vp+Kos0XCcWOwLv4FkdpawEhpj36zdSruePcwx0=; b=IY4r7OiO09fjKOCPRoml8PY4t4WdK/4qABZFQ7oJKNPeLJZJ011ckzvq3FjItACY7P DlmHeF90rwBTCHtf+YMZDZqCiMzfiOy/egQLQFoew1d8e4xoH0eQCqFO2z2wRoIgf5qD g8S38uWfQJpZ7tAlls/NpWCrg3qAFCCXVAvx2Uj5snAgJL2XlJYYdvgrDIKCgYFzVHQA 0QD0Oh37UyQSEclLYuX6/gCvQHbzLyAtB9z38XMTNjtki/CWo1pRrD5JqhDlUYNYJ1k7 p2qncTSnU/u6XpGM4HBvAO7AqrQx+kpnvYXxMFFVrhgpYmZ/5T6YZvg88OprlHwLRX/M 5ngg== 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=q8b+vp+Kos0XCcWOwLv4FkdpawEhpj36zdSruePcwx0=; b=D3tGzktbbx6ohpo7PRDvptT9/V/sMt9E963Jd+ipTRKLObE6G3NfXOLvYmIffYPHTQ 4aQWcLpT8s2bJo9PZra024ie9usmGNQ4HVcVRtLgoxEOI5Rp0HKx1qR6x/qM98pyBc5L //a3SB4ANAVm/SwAkVuGWiMJ+XPNYy9ndknYfM8Sd2WXplPvnQ9nyEFgYo3oo4VQ5GGv +0pOWJGFn3i/04xzpT1mQfdSLd+/DgESBgPHVc0AjgGHxuSoDNrIJAonpTFFvACFSxOG 39mIiL5o/kdnGRrQqmTDr0kbs6EZu3sVhhiqrinCxiJcIbbwFIfg0NGhxaGVYIIRH1JI bk0A== X-Gm-Message-State: AOAM5304RgzjAXjA7BoJokXhegamg4L/+55Qta62yjAY4W4ytofQgJGD LJ2E6tNJ6UDUMtvFeFvUoEuHrfi5L0hIlNEzoz2Idj3XISyaJ5q1VH7YZA41lcPeJ/1Irw6DrlY NT+21fMraY0FQ6iPtaSAM+NXs9Mek+lAUDB2Uk4l+Ddq68QqT3l8TZXyS7PDIebKoSfROxZxP9z AC X-Received: from apusaka-p920.tpe.corp.google.com ([2401:fa00:1:b:7515:f813:8ede:d08c]) (user=apusaka job=sendgmr) by 2002:a25:d914:: with SMTP id q20mr2562987ybg.397.1617779834352; Wed, 07 Apr 2021 00:17:14 -0700 (PDT) Date: Wed, 7 Apr 2021 15:17:08 +0800 Message-Id: <20210407151649.Bluez.1.I4ff127dde9bc6adb2a07507af2bf2cc6b6bcf0f2@changeid> Mime-Version: 1.0 X-Mailer: git-send-email 2.31.0.208.g409f899ff0-goog Subject: [Bluez PATCH] 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 --- attrib/att.h | 1 + profiles/input/hog-lib.c | 105 ++++++++++++++++++++++++++++----------- src/attrib-server.c | 1 + 3 files changed, 79 insertions(+), 28 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..2b81ee5b28 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, @@ -339,10 +390,7 @@ static void report_ccc_written_cb(guint8 status, const guint8 *pdu, if (report->notifyid) 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"); } @@ -1714,10 +1762,7 @@ bool bt_hog_attach(struct bt_hog *hog, void *gatt) if (r->notifyid) 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