lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20251028-funky-rose-rook-3ccab5@kuoka>
Date: Tue, 28 Oct 2025 08:44:29 +0100
From: Krzysztof Kozlowski <krzk@...nel.org>
To: Hendrik Noack <hendrik-noack@....de>
Cc: Dmitry Torokhov <dmitry.torokhov@...il.com>, 
	Rob Herring <robh@...nel.org>, Krzysztof Kozlowski <krzk+dt@...nel.org>, 
	Conor Dooley <conor+dt@...nel.org>, linux-input@...r.kernel.org, devicetree@...r.kernel.org, 
	linux-kernel@...r.kernel.org
Subject: Re: [PATCH 2/2] Input: Add support for Wacom W9000-series penabled
 touchscreens

On Mon, Oct 27, 2025 at 10:25:35PM +0100, Hendrik Noack wrote:
> +
> +static const struct of_device_id wacom_w9000_of_match[] = {
> +	{ .compatible = "wacom,w9007a_lt03", .data = &wacom_w9007a_lt03, },
> +	{ .compatible = "wacom,w9007a_v1", .data = &wacom_w9007a_v1, },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, wacom_w9000_of_match);

This goes next to other ID table, around the probe.

> +
> +static int wacom_w9000_read(struct i2c_client *client, u8 command, int len, char *data)
> +{
> +	struct i2c_msg xfer[2];
> +	bool retried = false;
> +	int ret;
> +

...

> +
> +static int wacom_w9000_probe(struct i2c_client *client)
> +{
> +	struct device *dev = &client->dev;
> +	struct wacom_w9000_data *wacom_data;
> +	struct input_dev *input_dev;
> +	int ret;
> +	u32 val;
> +
> +	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
> +		dev_err(dev, "i2c_check_functionality error\n");
> +		return -EIO;
> +	}
> +
> +	wacom_data = devm_kzalloc(dev, sizeof(struct wacom_w9000_data), GFP_KERNEL);

sizeof(*)

Please use existing kernel coding style, not some downstream version.

> +	if (!wacom_data)
> +		return -ENOMEM;
> +
> +	wacom_data->variant = i2c_get_match_data(client);
> +
> +	wacom_data->client = client;
> +
> +	input_dev = devm_input_allocate_device(dev);
> +	if (!input_dev)
> +		return -ENOMEM;
> +	wacom_data->input_dev = input_dev;
> +
> +	wacom_data->irq = client->irq;
> +	i2c_set_clientdata(client, wacom_data);
> +
> +	wacom_data->regulator = devm_regulator_get(dev, "vdd");
> +	if (IS_ERR(wacom_data->regulator)) {
> +		ret = PTR_ERR(wacom_data->regulator);
> +		dev_err(dev, "Failed to get regulators %d\n", ret);
> +		return ret;

Nope. Look at all other drivers. Syntax is since some years return
dev_err_probe.

> +	}
> +
> +	/* Request flash-mode line and don't go into flash mode */
> +	wacom_data->flash_mode_gpio = devm_gpiod_get_optional(dev, "flash-mode", GPIOD_OUT_LOW);
> +	if (IS_ERR(wacom_data->flash_mode_gpio)) {
> +		ret = PTR_ERR(wacom_data->flash_mode_gpio);
> +		dev_err(dev, "Failed to get flash-mode gpio: %d\n", ret);
> +		return ret;

You must handle deferred probe. Please look at all other drivers how
they do it.

> +	}
> +
> +	/* Request pdct line  */
> +	wacom_data->pen_detect_gpio = devm_gpiod_get_optional(dev, "pdct", GPIOD_IN);
> +	if (IS_ERR(wacom_data->pen_detect_gpio)) {
> +		ret = PTR_ERR(wacom_data->pen_detect_gpio);
> +		dev_err(dev, "Failed to get pdct gpio: %d\n", ret);
> +		return ret;
> +	}
> +
> +	/* Request pen-insert line  */
> +	wacom_data->pen_inserted_gpio = devm_gpiod_get_optional(dev, "pen-inserted", GPIOD_IN);
> +	if (IS_ERR(wacom_data->pen_inserted_gpio)) {
> +		ret = PTR_ERR(wacom_data->pen_inserted_gpio);
> +		dev_err(dev, "Failed to get pen-insert gpio: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = regulator_enable(wacom_data->regulator);
> +	if (ret) {
> +		dev_err(dev, "Failed to enable regulators: %d\n", ret);
> +		return ret;
> +	}
> +
> +	msleep(200);
> +
> +	ret = wacom_w9000_query(wacom_data);
> +	if (ret)
> +		goto err_disable_regulators;
> +
> +	input_dev->name = wacom_data->variant->name;
> +	input_dev->id.bustype = BUS_I2C;
> +	input_dev->dev.parent = dev;
> +	input_dev->id.vendor = 0x56a;
> +	input_dev->id.version = wacom_data->fw_version;
> +	input_dev->open = wacom_w9000_open;
> +	input_dev->close = wacom_w9000_close;
> +
> +	__set_bit(EV_KEY, input_dev->evbit);
> +	__set_bit(EV_ABS, input_dev->evbit);
> +	__set_bit(BTN_TOUCH, input_dev->keybit);
> +	__set_bit(BTN_TOOL_PEN, input_dev->keybit);
> +	__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
> +	__set_bit(BTN_STYLUS, input_dev->keybit);
> +
> +	// Calculate x and y resolution from size in devicetree
> +	ret = device_property_read_u32(dev, "touchscreen-x-mm", &val);
> +	if (ret)
> +		input_abs_set_res(input_dev, ABS_X, 100);
> +	else
> +		input_abs_set_res(input_dev, ABS_X, wacom_data->prop.max_x / val);
> +	ret = device_property_read_u32(dev, "touchscreen-y-mm", &val);
> +	if (ret)
> +		input_abs_set_res(input_dev, ABS_Y, 100);
> +	else
> +		input_abs_set_res(input_dev, ABS_Y, wacom_data->prop.max_y / val);
> +
> +	input_set_abs_params(input_dev, ABS_X, 0, wacom_data->prop.max_x, 4, 0);
> +	input_set_abs_params(input_dev, ABS_Y, 0, wacom_data->prop.max_y, 4, 0);
> +	input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_data->max_pressure, 0, 0);
> +	input_set_abs_params(input_dev, ABS_DISTANCE, 0, 255, 0, 0);
> +
> +	touchscreen_parse_properties(input_dev, false, &wacom_data->prop);
> +
> +	ret = devm_request_threaded_irq(dev, wacom_data->irq, NULL, wacom_w9000_interrupt,
> +					IRQF_ONESHOT | IRQF_NO_AUTOEN, client->name, wacom_data);
> +	if (ret) {
> +		dev_err(dev, "Failed to register interrupt\n");
> +		goto err_disable_regulators;
> +	}
> +
> +	if (wacom_data->pen_detect_gpio) {
> +		wacom_data->pen_detect_irq = gpiod_to_irq(wacom_data->pen_detect_gpio);

Why is this a GPIO? Your binding said this is GPIO, your code says this
is an interrupt.

> +		ret = devm_request_threaded_irq(dev, wacom_data->pen_detect_irq, NULL,
> +						wacom_w9000_interrupt_pen_detect, IRQF_ONESHOT |
> +						IRQF_NO_AUTOEN | IRQF_TRIGGER_RISING |
> +						IRQF_TRIGGER_FALLING, "wacom_pdct", wacom_data);
> +		if (ret) {
> +			dev_err(dev, "Failed to register pdct interrupt\n");
> +			goto err_disable_regulators;
> +		}
> +	}
> +
> +	if (wacom_data->pen_inserted_gpio) {
> +		input_dev->evbit[0] |= BIT_MASK(EV_SW);
> +		input_set_capability(input_dev, EV_SW, SW_PEN_INSERTED);
> +		wacom_data->pen_insert_irq = gpiod_to_irq(wacom_data->pen_inserted_gpio);

Same question here.

> +		ret = devm_request_threaded_irq(dev, wacom_data->pen_insert_irq, NULL,
> +						wacom_w9000_interrupt_pen_insert, IRQF_ONESHOT |
> +						IRQF_NO_AUTOEN | IRQF_TRIGGER_RISING |
> +						IRQF_TRIGGER_FALLING, "wacom_pen_insert",
> +						wacom_data);
> +		if (ret) {
> +			dev_err(dev, "Failed to register pen-insert interrupt\n");
> +			goto err_disable_regulators;
> +		}
> +	}
> +
> +	input_set_drvdata(input_dev, wacom_data);
> +
> +	wacom_data->pen_inserted = gpiod_get_value(wacom_data->pen_inserted_gpio);
> +	if (wacom_data->pen_inserted)
> +		regulator_disable(wacom_data->regulator);
> +	else
> +		enable_irq(wacom_data->irq);
> +
> +	input_report_switch(wacom_data->input_dev, SW_PEN_INSERTED, wacom_data->pen_inserted);
> +	input_sync(wacom_data->input_dev);
> +
> +	if (wacom_data->pen_inserted_gpio)
> +		enable_irq(wacom_data->pen_insert_irq);
> +
> +	if (wacom_data->pen_detect_gpio)
> +		enable_irq(wacom_data->pen_detect_irq);
> +
> +	ret = input_register_device(wacom_data->input_dev);
> +	if (ret) {
> +		dev_err(dev, "Failed to register input device: %d\n", ret);
> +		goto err_disable_regulators;
> +	}
> +
> +	return 0;
> +
> +err_disable_regulators:
> +	regulator_disable(wacom_data->regulator);
> +	return ret;
> +}
> +
> +static void wacom_w9000_remove(struct i2c_client *client)
> +{
> +	struct wacom_w9000_data *wacom_data = i2c_get_clientdata(client);
> +
> +	if (regulator_is_enabled(wacom_data->regulator))
> +		regulator_disable(wacom_data->regulator);
> +}
> +
> +static int wacom_w9000_suspend(struct device *dev)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	struct wacom_w9000_data *wacom_data = i2c_get_clientdata(client);
> +	struct input_dev *input_dev = wacom_data->input_dev;
> +
> +	mutex_lock(&input_dev->mutex);
> +
> +	if (regulator_is_enabled(wacom_data->regulator)) {
> +		disable_irq(wacom_data->irq);
> +		regulator_disable(wacom_data->regulator);
> +	}
> +
> +	mutex_unlock(&input_dev->mutex);
> +
> +	return 0;
> +}
> +
> +static int wacom_w9000_resume(struct device *dev)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	struct wacom_w9000_data *wacom_data = i2c_get_clientdata(client);
> +	struct input_dev *input_dev = wacom_data->input_dev;
> +	int ret = 0;
> +
> +	mutex_lock(&input_dev->mutex);
> +
> +	if (!wacom_data->pen_inserted && !regulator_is_enabled(wacom_data->regulator)) {
> +		ret = regulator_enable(wacom_data->regulator);
> +		if (ret) {
> +			dev_err(&wacom_data->client->dev, "Failed to enable regulators: %d\n",
> +				ret);
> +		} else {
> +			msleep(200);
> +			enable_irq(wacom_data->irq);
> +		}
> +	}
> +
> +	mutex_unlock(&input_dev->mutex);
> +
> +	return ret;
> +}
> +
> +static DEFINE_SIMPLE_DEV_PM_OPS(wacom_w9000_pm, wacom_w9000_suspend, wacom_w9000_resume);
> +
> +static const struct i2c_device_id wacom_w9000_id[] = {
> +	{ "w9007a_lt03" },
> +	{ "w9007a_v1" },

This does not match your OF table.

> +	{ }
> +};
> +MODULE_DEVICE_TABLE(i2c, wacom_w9000_id);
> +
> +static struct i2c_driver wacom_w9000_driver = {
> +	.driver = {
> +		.name	= "wacom_w9000",
> +		.of_match_table = wacom_w9000_of_match,
> +		.pm	= pm_sleep_ptr(&wacom_w9000_pm),
> +	},
> +	.probe		= wacom_w9000_probe,
> +	.remove		= wacom_w9000_remove,
> +	.id_table	= wacom_w9000_id,
> +};
> +module_i2c_driver(wacom_w9000_driver);
> +
> +/* Module information */
> +MODULE_AUTHOR("Hendrik Noack <hendrik-noack@....de>");
> +MODULE_DESCRIPTION("Wacom W9000-series penabled touchscreen driver");
> +MODULE_LICENSE("GPL");
> -- 
> 2.43.0
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ