drivers/input/keyboard/lm8333.c

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

File Facts

System
Linux kernel
Corpus path
drivers/input/keyboard/lm8333.c
Extension
.c
Size
4911 bytes
Lines
214
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 lm8333 {
	struct i2c_client *client;
	struct input_dev *input;
	unsigned short keycodes[LM8333_NUM_ROWS << LM8333_ROW_SHIFT];
};

/* The accessors try twice because the first access may be needed for wakeup */
#define LM8333_READ_RETRIES 2

int lm8333_read8(struct lm8333 *lm8333, u8 cmd)
{
	int retries = 0, ret;

	do {
		ret = i2c_smbus_read_byte_data(lm8333->client, cmd);
	} while (ret < 0 && retries++ < LM8333_READ_RETRIES);

	return ret;
}

int lm8333_write8(struct lm8333 *lm8333, u8 cmd, u8 val)
{
	int retries = 0, ret;

	do {
		ret = i2c_smbus_write_byte_data(lm8333->client, cmd, val);
	} while (ret < 0 && retries++ < LM8333_READ_RETRIES);

	return ret;
}

int lm8333_read_block(struct lm8333 *lm8333, u8 cmd, u8 len, u8 *buf)
{
	int retries = 0, ret;

	do {
		ret = i2c_smbus_read_i2c_block_data(lm8333->client,
						    cmd, len, buf);
	} while (ret < 0 && retries++ < LM8333_READ_RETRIES);

	return ret;
}

static void lm8333_key_handler(struct lm8333 *lm8333)
{
	struct input_dev *input = lm8333->input;
	u8 keys[LM8333_FIFO_TRANSFER_SIZE];
	u8 code, pressed;
	int i, ret;

	ret = lm8333_read_block(lm8333, LM8333_FIFO_READ,
				LM8333_FIFO_TRANSFER_SIZE, keys);
	if (ret != LM8333_FIFO_TRANSFER_SIZE) {
		dev_err(&lm8333->client->dev,
			"Error %d while reading FIFO\n", ret);
		return;
	}

	for (i = 0; i < LM8333_FIFO_TRANSFER_SIZE && keys[i]; i++) {
		pressed = keys[i] & 0x80;
		code = keys[i] & 0x7f;

		input_event(input, EV_MSC, MSC_SCAN, code);
		input_report_key(input, lm8333->keycodes[code], pressed);
	}

	input_sync(input);
}

static irqreturn_t lm8333_irq_thread(int irq, void *data)
{
	struct lm8333 *lm8333 = data;
	u8 status = lm8333_read8(lm8333, LM8333_READ_INT);

	if (!status)
		return IRQ_NONE;

	if (status & LM8333_ERROR_IRQ) {
		u8 err = lm8333_read8(lm8333, LM8333_READ_ERROR);

		if (err & (LM8333_ERROR_KEYOVR | LM8333_ERROR_FIFOOVR)) {
			u8 dummy[LM8333_FIFO_TRANSFER_SIZE];

			lm8333_read_block(lm8333, LM8333_FIFO_READ,
					LM8333_FIFO_TRANSFER_SIZE, dummy);
		}
		dev_err(&lm8333->client->dev, "Got error %02x\n", err);
	}

	if (status & LM8333_KEYPAD_IRQ)

Annotation

Implementation Notes