drivers/input/keyboard/cypress-sf.c

Source file repositories/reference/linux-study-clean/drivers/input/keyboard/cypress-sf.c

File Facts

System
Linux kernel
Corpus path
drivers/input/keyboard/cypress-sf.c
Extension
.c
Size
5902 bytes
Lines
239
Domain
Driver Families
Bucket
drivers/input
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct cypress_sf_data {
	struct i2c_client *client;
	struct input_dev *input_dev;
	struct regulator_bulk_data regulators[2];
	u32 *keycodes;
	unsigned long keystates;
	int num_keys;
};

static irqreturn_t cypress_sf_irq_handler(int irq, void *devid)
{
	struct cypress_sf_data *touchkey = devid;
	unsigned long keystates, changed;
	bool new_state;
	int val, key;

	val = i2c_smbus_read_byte_data(touchkey->client,
				       CYPRESS_SF_REG_BUTTON_STATUS);
	if (val < 0) {
		dev_err(&touchkey->client->dev,
			"Failed to read button status: %d", val);
		return IRQ_NONE;
	}
	keystates = val;

	bitmap_xor(&changed, &keystates, &touchkey->keystates,
		   touchkey->num_keys);

	for_each_set_bit(key, &changed, touchkey->num_keys) {
		new_state = keystates & BIT(key);
		dev_dbg(&touchkey->client->dev,
			"Key %d changed to %d", key, new_state);
		input_report_key(touchkey->input_dev,
				 touchkey->keycodes[key], new_state);
	}

	input_sync(touchkey->input_dev);
	touchkey->keystates = keystates;

	return IRQ_HANDLED;
}

static void cypress_sf_disable_regulators(void *arg)
{
	struct cypress_sf_data *touchkey = arg;

	regulator_bulk_disable(ARRAY_SIZE(touchkey->regulators),
			       touchkey->regulators);
}

static int cypress_sf_probe(struct i2c_client *client)
{
	struct cypress_sf_data *touchkey;
	int key, error;

	touchkey = devm_kzalloc(&client->dev, sizeof(*touchkey), GFP_KERNEL);
	if (!touchkey)
		return -ENOMEM;

	touchkey->client = client;
	i2c_set_clientdata(client, touchkey);

	touchkey->regulators[0].supply = "vdd";
	touchkey->regulators[1].supply = "avdd";

	error = devm_regulator_bulk_get(&client->dev,
					ARRAY_SIZE(touchkey->regulators),
					touchkey->regulators);
	if (error) {
		dev_err(&client->dev, "Failed to get regulators: %d\n", error);
		return error;
	}

	touchkey->num_keys = device_property_read_u32_array(&client->dev,
							    "linux,keycodes",
							    NULL, 0);
	if (touchkey->num_keys < 0) {
		/* Default key count */
		touchkey->num_keys = 2;
	}

	touchkey->keycodes = devm_kcalloc(&client->dev,
					  touchkey->num_keys,
					  sizeof(*touchkey->keycodes),
					  GFP_KERNEL);
	if (!touchkey->keycodes)
		return -ENOMEM;

	error = device_property_read_u32_array(&client->dev, "linux,keycodes",
					       touchkey->keycodes,

Annotation

Implementation Notes