drivers/misc/lis3lv02d/lis3lv02d.c

Source file repositories/reference/linux-study-clean/drivers/misc/lis3lv02d/lis3lv02d.c

File Facts

System
Linux kernel
Corpus path
drivers/misc/lis3lv02d/lis3lv02d.c
Extension
.c
Size
33956 bytes
Lines
1260
Domain
Driver Families
Bucket
drivers/misc
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations lis3lv02d_misc_fops = {
	.owner   = THIS_MODULE,
	.read    = lis3lv02d_misc_read,
	.open    = lis3lv02d_misc_open,
	.release = lis3lv02d_misc_release,
	.poll    = lis3lv02d_misc_poll,
	.fasync  = lis3lv02d_misc_fasync,
};

int lis3lv02d_joystick_enable(struct lis3lv02d *lis3)
{
	struct input_dev *input_dev;
	int err;
	int max_val, fuzz, flat;
	int btns[] = {BTN_X, BTN_Y, BTN_Z};

	if (lis3->idev)
		return -EINVAL;

	input_dev = input_allocate_device();
	if (!input_dev)
		return -ENOMEM;

	input_dev->name       = "ST LIS3LV02DL Accelerometer";
	input_dev->phys       = DRIVER_NAME "/input0";
	input_dev->id.bustype = BUS_HOST;
	input_dev->id.vendor  = 0;
	input_dev->dev.parent = &lis3->fdev->dev;

	input_dev->open = lis3lv02d_joystick_open;
	input_dev->close = lis3lv02d_joystick_close;

	max_val = (lis3->mdps_max_val * lis3->scale) / LIS3_ACCURACY;
	if (lis3->whoami == WAI_12B) {
		fuzz = LIS3_DEFAULT_FUZZ_12B;
		flat = LIS3_DEFAULT_FLAT_12B;
	} else {
		fuzz = LIS3_DEFAULT_FUZZ_8B;
		flat = LIS3_DEFAULT_FLAT_8B;
	}
	fuzz = (fuzz * lis3->scale) / LIS3_ACCURACY;
	flat = (flat * lis3->scale) / LIS3_ACCURACY;

	input_set_abs_params(input_dev, ABS_X, -max_val, max_val, fuzz, flat);
	input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat);
	input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat);

	input_set_drvdata(input_dev, lis3);
	lis3->idev = input_dev;

	err = input_setup_polling(input_dev, lis3lv02d_joystick_poll);
	if (err)
		goto err_free_input;

	input_set_poll_interval(input_dev, MDPS_POLL_INTERVAL);
	input_set_min_poll_interval(input_dev, MDPS_POLL_MIN);
	input_set_max_poll_interval(input_dev, MDPS_POLL_MAX);

	lis3->mapped_btns[0] = lis3lv02d_get_axis(abs(lis3->ac.x), btns);
	lis3->mapped_btns[1] = lis3lv02d_get_axis(abs(lis3->ac.y), btns);
	lis3->mapped_btns[2] = lis3lv02d_get_axis(abs(lis3->ac.z), btns);

	err = input_register_device(lis3->idev);
	if (err)
		goto err_free_input;

	return 0;

err_free_input:
	input_free_device(input_dev);
	lis3->idev = NULL;
	return err;

}
EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable);

void lis3lv02d_joystick_disable(struct lis3lv02d *lis3)
{
	if (lis3->irq)
		free_irq(lis3->irq, lis3);
	if (lis3->pdata && lis3->pdata->irq2)
		free_irq(lis3->pdata->irq2, lis3);

	if (!lis3->idev)
		return;

	if (lis3->irq)
		misc_deregister(&lis3->miscdev);
	input_unregister_device(lis3->idev);
	lis3->idev = NULL;

Annotation

Implementation Notes