From nobody Tue Jun 30 02:40:27 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BFA8CC433EF for ; Thu, 27 Jan 2022 08:36:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237829AbiA0Ig2 (ORCPT ); Thu, 27 Jan 2022 03:36:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50402 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237826AbiA0Ig0 (ORCPT ); Thu, 27 Jan 2022 03:36:26 -0500 Received: from mail-pf1-x432.google.com (mail-pf1-x432.google.com [IPv6:2607:f8b0:4864:20::432]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B1CDDC061747 for ; Thu, 27 Jan 2022 00:36:26 -0800 (PST) Received: by mail-pf1-x432.google.com with SMTP id y27so2050844pfa.0 for ; Thu, 27 Jan 2022 00:36:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=hOnwD3XCBEoi7EneALZ2BHLkba3O2+aqmrT8y3nvWFQ=; b=d2lE1NH16Rc6+e11u77wATb37z8W5WlkCUvTH/RnKm7YwDYJnl7Cajzxs8W1EuWoAF TEOaQ5yCX1l8i+Wp0nd+6EfegfQVYcuEa5pGHv6dCm3A23shxn/KFakjpqGkr9xo+7mU 7D1Y3l/LjODJBIAHPfj/875lWkj8Aozz7e+Cg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=hOnwD3XCBEoi7EneALZ2BHLkba3O2+aqmrT8y3nvWFQ=; b=aEjieRpYXdu2mQnEbikwIHiMlHeHinJ5Ui9aDZ/lg2z+bWUf7ScWYTxT7VpUZxjwX4 NXc15S7AP4F+HH0MgnsMzsjR3zsfASXMQ55tGLa3n3bbFEklpiFgeyHorSM0xHPrNXzD x8R0TWt4ZeLNuirWdxtbmC56mu6B0eJudO/8t/1t8/ljA7/xU1p7lSvkjETNmuI+3byd 9qIwYRdZG31BbdVUpdC5QkCtpM0a6JyVJXbFbjyG8GU8q/sPjY3cfz5ASuRkel+oBqPN Vop6mNGNl8FoKALLCN1kmmgkCFVralwJ4/2Nkkj+hw9gvUsq+jHLTWLsNmCavb2B1gXI f2yg== X-Gm-Message-State: AOAM5304Tj4tDdRaghXUhCSejZlfhwL3oBB8VZ5oco4gYoyXmY1DX2XA r3gttgWcuUWa7eiA5bEM7wQrVPKX4prutQ== X-Google-Smtp-Source: ABdhPJzZVUv2RArMoBn4C067RzCz45V7UTw30ToXK3eajNyX45E+Vcc239HtueOA3cPLvJuTT1bXkg== X-Received: by 2002:a63:215a:: with SMTP id s26mr2018176pgm.141.1643272586012; Thu, 27 Jan 2022 00:36:26 -0800 (PST) Received: from localhost ([2401:fa00:9:14:f81:dff7:4d7c:382]) by smtp.gmail.com with UTF8SMTPSA id z13sm1476023pfh.45.2022.01.27.00.36.23 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 27 Jan 2022 00:36:25 -0800 (PST) From: =?UTF-8?q?Sami=20Ky=C3=B6stil=C3=A4?= To: LKML Cc: dtor@chromium.org, evanbenn@chromium.org, arnd@arndb.de, gregkh@linuxfoundation.org, =?UTF-8?q?Sami=20Ky=C3=B6stil=C3=A4?= Subject: [PATCH 1/2] drivers/misc: add a driver for HPS Date: Thu, 27 Jan 2022 19:35:44 +1100 Message-Id: <20220127083545.1020423-2-skyostil@chromium.org> X-Mailer: git-send-email 2.35.0.rc0.227.g00780c9af4-goog In-Reply-To: <20220127083545.1020423-1-skyostil@chromium.org> References: <20220127083545.1020423-1-skyostil@chromium.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch introduces a driver for the ChromeOS snooping protection sensor (aka. HPS). The driver supports a sensor connected to the I2C bus and identified as "GOOG0020" in the ACPI tables. When loaded, the driver exports the sensor to userspace through a character device. This initial version of the device only supports power management, i.e., communicating with the sensor must be done through I2C from userspace. Power management is implemented by enabling the respective power GPIO while at least one userspace process holds an open fd on the character device. By default, the device is powered down if there are no active clients. Note that the driver makes no effort to preserve the state of the sensor between power down and power up events. Userspace is responsible for reinitializing any needed state once power has been restored. The device firmware, I2C protocol and other documentation is available at https://chromium.googlesource.com/chromiumos/platform/hps-firmware. Signed-off-by: Sami Ky=C3=B6stil=C3=A4 --- MAINTAINERS | 6 ++ drivers/misc/Kconfig | 10 ++ drivers/misc/Makefile | 1 + drivers/misc/hps-i2c.c | 223 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 240 insertions(+) create mode 100644 drivers/misc/hps-i2c.c diff --git a/MAINTAINERS b/MAINTAINERS index ea3e6c914384..9dea4b8c2ab5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8798,6 +8798,12 @@ S: Maintained W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi F: fs/hpfs/ =20 +HPS (ChromeOS snooping protection sensor) DRIVER +M: Sami Ky=C3=B6stil=C3=A4 +R: Evan Benn +S: Maintained +F: drivers/misc/hps-i2c.c + HSI SUBSYSTEM M: Sebastian Reichel S: Maintained diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 0f5a49fc7c9e..b48b7803f537 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -244,6 +244,16 @@ config HP_ILO To compile this driver as a module, choose M here: the module will be called hpilo. =20 +config HPS_I2C + tristate "ChromeOS HPS device support" + depends on HID && I2C && PM + help + Say Y here if you want to enable support for the ChromeOS + anti-snooping sensor (HPS), attached via I2C. The driver supports a + sensor connected to the I2C bus and exposes it as a character device. + To save power, the sensor is automatically powered down when no + clients are accessing it. + config QCOM_COINCELL tristate "Qualcomm coincell charger support" depends on MFD_SPMI_PMIC || COMPILE_TEST diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index a086197af544..162a7d530dab 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_SGI_GRU) +=3D sgi-gru/ obj-$(CONFIG_CS5535_MFGPT) +=3D cs5535-mfgpt.o obj-$(CONFIG_GEHC_ACHC) +=3D gehc-achc.o obj-$(CONFIG_HP_ILO) +=3D hpilo.o +obj-$(CONFIG_HPS_I2C) +=3D hps-i2c.o obj-$(CONFIG_APDS9802ALS) +=3D apds9802als.o obj-$(CONFIG_ISL29003) +=3D isl29003.o obj-$(CONFIG_ISL29020) +=3D isl29020.o diff --git a/drivers/misc/hps-i2c.c b/drivers/misc/hps-i2c.c new file mode 100644 index 000000000000..fe9f073b0352 --- /dev/null +++ b/drivers/misc/hps-i2c.c @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for the ChromeOS anti-snooping sensor (HPS), attached via I2C. + * + * The driver exposes HPS as a character device, although currently no rea= d or + * write operations are supported. Instead, the driver only controls the p= ower + * state of the sensor, keeping it on only while userspace holds an open f= ile + * descriptor to the HPS device. + * + * Copyright 2022 Google LLC. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define HPS_ACPI_ID "GOOG0020" +#define HPS_MAX_DEVICES 1 + +struct hps_drvdata { + struct i2c_client *client; + + struct cdev cdev; + struct class *cdev_class; + + struct gpio_desc *enable_gpio; +}; + +static int hps_dev_major; + +static void hps_power_on(struct hps_drvdata *hps) +{ + if (!IS_ERR_OR_NULL(hps->enable_gpio)) + gpiod_set_value_cansleep(hps->enable_gpio, 1); +} + +static void hps_power_off(struct hps_drvdata *hps) +{ + if (!IS_ERR_OR_NULL(hps->enable_gpio)) + gpiod_set_value_cansleep(hps->enable_gpio, 0); +} + +static void hps_unload(void *drv_data) +{ + struct hps_drvdata *hps =3D drv_data; + + hps_power_on(hps); +} + +static int hps_open(struct inode *inode, struct file *file) +{ + struct hps_drvdata *hps =3D container_of(inode->i_cdev, struct hps_drvdat= a, cdev); + struct device *dev =3D &hps->client->dev; + int ret; + + ret =3D pm_runtime_get_sync(dev); + if (ret < 0) + goto pm_get_fail; + return 0; + +pm_get_fail: + pm_runtime_put(dev); + pm_runtime_disable(dev); + return ret; +} + +static int hps_release(struct inode *inode, struct file *file) +{ + struct hps_drvdata *hps =3D container_of(inode->i_cdev, struct hps_drvdat= a, cdev); + struct device *dev =3D &hps->client->dev; + int ret; + + ret =3D pm_runtime_put(dev); + if (ret < 0) + goto pm_put_fail; + return 0; + +pm_put_fail: + pm_runtime_disable(dev); + return ret; +} + +const struct file_operations hps_fops =3D { + .owner =3D THIS_MODULE, + .open =3D hps_open, + .release =3D hps_release, +}; + +static int hps_i2c_probe(struct i2c_client *client) +{ + struct hps_drvdata *hps; + int ret =3D 0; + dev_t hps_dev; + + hps =3D devm_kzalloc(&client->dev, sizeof(*hps), GFP_KERNEL); + if (!hps) + return -ENOMEM; + + i2c_set_clientdata(client, hps); + hps->client =3D client; + hps->enable_gpio =3D devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_HIG= H); + if (IS_ERR(hps->enable_gpio)) { + ret =3D PTR_ERR(hps->enable_gpio); + dev_err(&client->dev, "failed to get enable gpio: %d\n", ret); + return ret; + } + + ret =3D devm_add_action(&client->dev, &hps_unload, hps); + if (ret) { + dev_err(&client->dev, + "failed to install unload action: %d\n", ret); + return ret; + } + + ret =3D alloc_chrdev_region(&hps_dev, 0, HPS_MAX_DEVICES, "hps"); + if (ret) { + dev_err(&client->dev, + "failed to register char dev: %d\n", ret); + return ret; + } + hps_dev_major =3D MAJOR(hps_dev); + cdev_init(&hps->cdev, &hps_fops); + ret =3D cdev_add(&hps->cdev, hps_dev, 1); + if (ret) { + dev_err(&client->dev, "cdev_add() failed: %d\n", ret); + goto cdev_add_failed; + } + + hps->cdev_class =3D class_create(THIS_MODULE, "hps"); + if (IS_ERR(hps->cdev_class)) { + dev_err(&client->dev, "class_create() failed: %d\n", ret); + goto class_create_failed; + } + device_create(hps->cdev_class, NULL, hps_dev, NULL, "hps"); + + hps_power_off(hps); + pm_runtime_enable(&client->dev); + return ret; + +class_create_failed: + ret =3D PTR_ERR(hps->cdev_class); + hps->cdev_class =3D NULL; + +cdev_add_failed: + unregister_chrdev_region(MKDEV(hps_dev_major, 0), HPS_MAX_DEVICES); + hps_dev_major =3D 0; + return ret; +} + +static int hps_i2c_remove(struct i2c_client *client) +{ + struct hps_drvdata *hps =3D i2c_get_clientdata(client); + + pm_runtime_disable(&client->dev); + if (hps_dev_major) { + dev_t hps_dev =3D MKDEV(hps_dev_major, 0); + + device_destroy(hps->cdev_class, hps_dev); + class_destroy(hps->cdev_class); + hps->cdev_class =3D NULL; + + cdev_del(&hps->cdev); + unregister_chrdev_region(hps_dev, HPS_MAX_DEVICES); + hps_dev_major =3D 0; + } + return 0; +} + +static int hps_suspend(struct device *dev) +{ + struct i2c_client *client =3D to_i2c_client(dev); + struct hps_drvdata *hps =3D i2c_get_clientdata(client); + + hps_power_off(hps); + return 0; +} + +static int hps_resume(struct device *dev) +{ + struct i2c_client *client =3D to_i2c_client(dev); + struct hps_drvdata *hps =3D i2c_get_clientdata(client); + + hps_power_on(hps); + return 0; +} +static UNIVERSAL_DEV_PM_OPS(hps_pm_ops, hps_suspend, hps_resume, NULL); + +static const struct i2c_device_id hps_i2c_id[] =3D { + { "hps", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, hps_i2c_id); + +#ifdef CONFIG_ACPI +static const struct acpi_device_id hps_acpi_id[] =3D { + { HPS_ACPI_ID, 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, hps_acpi_id); +#endif /* CONFIG_ACPI */ + +static struct i2c_driver hps_i2c_driver =3D { + .probe_new =3D hps_i2c_probe, + .remove =3D hps_i2c_remove, + .id_table =3D hps_i2c_id, + .driver =3D { + .name =3D "hps", + .pm =3D &hps_pm_ops, +#ifdef CONFIG_ACPI + .acpi_match_table =3D ACPI_PTR(hps_acpi_id), +#endif + }, +}; +module_i2c_driver(hps_i2c_driver); + +MODULE_ALIAS("acpi:" HPS_ACPI_ID); +MODULE_AUTHOR("Sami Ky=C3=B6stil=C3=A4 "); +MODULE_DESCRIPTION("Driver for ChromeOS HPS"); +MODULE_LICENSE("GPL"); --=20 2.35.0.rc0.227.g00780c9af4-goog From nobody Tue Jun 30 02:40:27 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1FBB1C433F5 for ; Thu, 27 Jan 2022 08:36:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237837AbiA0Igi (ORCPT ); Thu, 27 Jan 2022 03:36:38 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50432 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237850AbiA0Igd (ORCPT ); Thu, 27 Jan 2022 03:36:33 -0500 Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0CD75C06173B for ; Thu, 27 Jan 2022 00:36:33 -0800 (PST) Received: by mail-pj1-x102c.google.com with SMTP id r59so2219445pjg.4 for ; Thu, 27 Jan 2022 00:36:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=/cB6BQlkH3tVpBvxYH7RGzF//Mdgv4SIiThB1PpNT8c=; b=hWpvbgR85SykG0uPKlggJxreC7FZWygPtTwswJ0WGv89ZwzqKkEcQF08a0WAnJ4HuO 6LUrPJw3x7lb2ZYUbNS+pdWaOT96fk7j6hlnz8Q+HzzpEVJiusMNHoLtpB4BoZDpNBMY qA9G83KpyFFP8MVYrxuDqTtQZnEVEyDrh0Fq0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=/cB6BQlkH3tVpBvxYH7RGzF//Mdgv4SIiThB1PpNT8c=; b=k+aY6hY1K3/Ag42qqCnlnVvwrDopZZFPXARRKCycpIWVW25TCmjX1ZeWbPgy/OmhWU AE3oFU+7sHoaydHIngPsIxF1EngsNnQhNYrrETrNShVcu661u+btjYD8A/ueRqF/0nvu 7GWLcLqvGJR44KLvOq+6O1+xELJYAfWydTA6Kr7rdjLSS9VNdMatW2X/aZzf7X3c+akO usMqY6YdrrT0Q5h1O9/G4zHtmn0AXHgo6hWVzdeW4idgBNC1Wd8zROBi5I5/ECgA1o4z j37SRaDJ5tF9Qdy0rPCphWiEiwNWL3N7d/vOyY04+Z9/p8A9FLK7IuPB/vlYGoiOiPAl gUsA== X-Gm-Message-State: AOAM532plfuOXfl+ob8N3r9mzmYEhgYml3L3SwuWDmVz8TXpa/Yqg31e XcdKer2BXVaD0O9Zl6N2eNioFvLn3E9X2A== X-Google-Smtp-Source: ABdhPJwdt0MnHkgPn5sEM05523pP62A+RnVLw4nwtBmbPb6w+6/eL+m4tVJMPBe1VPuuEvt2zGN8KQ== X-Received: by 2002:a17:90b:1a85:: with SMTP id ng5mr13089576pjb.53.1643272592406; Thu, 27 Jan 2022 00:36:32 -0800 (PST) Received: from localhost ([2401:fa00:9:14:f81:dff7:4d7c:382]) by smtp.gmail.com with UTF8SMTPSA id l17sm4666614pfu.61.2022.01.27.00.36.30 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 27 Jan 2022 00:36:32 -0800 (PST) From: =?UTF-8?q?Sami=20Ky=C3=B6stil=C3=A4?= To: LKML Cc: dtor@chromium.org, evanbenn@chromium.org, arnd@arndb.de, gregkh@linuxfoundation.org, =?UTF-8?q?Sami=20Ky=C3=B6stil=C3=A4?= Subject: [PATCH 2/2] drivers/misc: add transfer ioctl for HPS Date: Thu, 27 Jan 2022 19:35:45 +1100 Message-Id: <20220127083545.1020423-3-skyostil@chromium.org> X-Mailer: git-send-email 2.35.0.rc0.227.g00780c9af4-goog In-Reply-To: <20220127083545.1020423-1-skyostil@chromium.org> References: <20220127083545.1020423-1-skyostil@chromium.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch adds an ioctl operation for sending and receiving data from the ChromeOS snooping protection sensor (a.k.a., HPS). This allows userspace programs to perform a combined read/write I2C transaction through a single syscall. The I2C wire protocol for the device is documented at: https://chromium.googlesource.com/chromiumos/platform/hps-firmware/+/ refs/heads/main/docs/host_device_i2c_protocol.md Signed-off-by: Sami Ky=C3=B6stil=C3=A4 --- MAINTAINERS | 1 + drivers/misc/hps-i2c.c | 81 ++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/hps.h | 20 ++++++++++ 3 files changed, 102 insertions(+) create mode 100644 include/uapi/linux/hps.h diff --git a/MAINTAINERS b/MAINTAINERS index 9dea4b8c2ab5..d5fc066fdbc2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8803,6 +8803,7 @@ M: Sami Ky=C3=B6stil=C3=A4 R: Evan Benn S: Maintained F: drivers/misc/hps-i2c.c +F: include/uapi/linux/hps.h =20 HSI SUBSYSTEM M: Sebastian Reichel diff --git a/drivers/misc/hps-i2c.c b/drivers/misc/hps-i2c.c index fe9f073b0352..748ead49d678 100644 --- a/drivers/misc/hps-i2c.c +++ b/drivers/misc/hps-i2c.c @@ -17,9 +17,11 @@ #include #include #include +#include =20 #define HPS_ACPI_ID "GOOG0020" #define HPS_MAX_DEVICES 1 +#define HPS_MAX_MSG_SIZE 8192 =20 struct hps_drvdata { struct i2c_client *client; @@ -60,6 +62,8 @@ static int hps_open(struct inode *inode, struct file *fil= e) ret =3D pm_runtime_get_sync(dev); if (ret < 0) goto pm_get_fail; + + file->private_data =3D hps->client; return 0; =20 pm_get_fail: @@ -84,10 +88,87 @@ static int hps_release(struct inode *inode, struct file= *file) return ret; } =20 +static int hps_do_ioctl_transfer(struct i2c_client *client, + struct hps_transfer_ioctl_data *args) +{ + int ret; + int nmsg =3D 0; + struct i2c_msg msgs[2] =3D { + { + .addr =3D client->addr, + .flags =3D client->flags, + }, + { + .addr =3D client->addr, + .flags =3D client->flags, + }, + }; + + if (args->isize) { + msgs[nmsg].len =3D args->isize; + msgs[nmsg].buf =3D memdup_user(args->ibuf, args->isize); + if (IS_ERR(msgs[nmsg].buf)) { + ret =3D PTR_ERR(msgs[nmsg].buf); + goto memdup_fail; + } + nmsg++; + } + + if (args->osize) { + msgs[nmsg].len =3D args->osize; + msgs[nmsg].buf =3D memdup_user(args->obuf, args->osize); + msgs[nmsg].flags |=3D I2C_M_RD; + if (IS_ERR(msgs[nmsg].buf)) { + ret =3D PTR_ERR(msgs[nmsg].buf); + goto memdup_fail; + } + nmsg++; + } + + ret =3D i2c_transfer(client->adapter, &msgs[0], nmsg); + if (ret > 0 && args->osize) { + if (copy_to_user(args->obuf, msgs[nmsg - 1].buf, ret)) + ret =3D -EFAULT; + } + +memdup_fail: + while (nmsg > 0) + kfree(msgs[--nmsg].buf); + return ret; +} + +static long hps_ioctl(struct file *file, unsigned int cmd, unsigned long a= rg) +{ + struct i2c_client *client =3D file->private_data; + + switch (cmd) { + case HPS_IOC_TRANSFER: { + struct hps_transfer_ioctl_data args; + + if (copy_from_user(&args, + (struct hps_transfer_ioctl_data __user *)arg, + sizeof(args))) { + return -EFAULT; + } + + if (!args.isize && !args.osize) + return -EINVAL; + if (args.isize > HPS_MAX_MSG_SIZE || args.osize > HPS_MAX_MSG_SIZE) + return -EINVAL; + + return hps_do_ioctl_transfer(client, &args); + } + default: + return -EFAULT; + } +} + + const struct file_operations hps_fops =3D { .owner =3D THIS_MODULE, .open =3D hps_open, .release =3D hps_release, + .unlocked_ioctl =3D hps_ioctl, }; =20 static int hps_i2c_probe(struct i2c_client *client) diff --git a/include/uapi/linux/hps.h b/include/uapi/linux/hps.h new file mode 100644 index 000000000000..2c1bd174cd02 --- /dev/null +++ b/include/uapi/linux/hps.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * Copyright 2022 Google LLC. + */ + +#ifndef _UAPI_HPS_H +#define _UAPI_HPS_H + +#include + +#define HPS_IOC_TRANSFER _IOWR('h', 0x01, struct hps_transfer_ioctl_data) + +struct hps_transfer_ioctl_data { + __u32 isize; /* Number of bytes to send */ + unsigned char __user *ibuf; /* Input buffer */ + __u32 osize; /* Number of bytes to receive */ + unsigned char __user *obuf; /* Output buffer */ +}; + +#endif /* _UAPI_HPS_H */ --=20 2.35.0.rc0.227.g00780c9af4-goog