drivers/iio/proximity/mb1232.c

Source file repositories/reference/linux-study-clean/drivers/iio/proximity/mb1232.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/proximity/mb1232.c
Extension
.c
Size
6443 bytes
Lines
271
Domain
Driver Families
Bucket
drivers/iio
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 mb1232_data {
	struct i2c_client	*client;

	struct mutex		lock;

	/*
	 * optionally a gpio can be used to announce when ranging has
	 * finished
	 * since we are just using the falling trigger of it we request
	 * only the interrupt for announcing when data is ready to be read
	 */
	struct completion	ranging;
	int			irqnr;
};

static irqreturn_t mb1232_handle_irq(int irq, void *dev_id)
{
	struct iio_dev *indio_dev = dev_id;
	struct mb1232_data *data = iio_priv(indio_dev);

	complete(&data->ranging);

	return IRQ_HANDLED;
}

static s16 mb1232_read_distance(struct mb1232_data *data)
{
	struct i2c_client *client = data->client;
	int ret;
	s16 distance;
	__be16 buf;

	mutex_lock(&data->lock);

	reinit_completion(&data->ranging);

	ret = i2c_smbus_write_byte(client, MB1232_RANGE_COMMAND);
	if (ret < 0) {
		dev_err(&client->dev, "write command - err: %d\n", ret);
		goto error_unlock;
	}

	if (data->irqnr > 0) {
		/* it cannot take more than 100 ms */
		ret = wait_for_completion_killable_timeout(&data->ranging,
									HZ/10);
		if (ret < 0)
			goto error_unlock;
		else if (ret == 0) {
			ret = -ETIMEDOUT;
			goto error_unlock;
		}
	} else {
		/* use simple sleep if announce irq is not connected */
		msleep(15);
	}

	ret = i2c_master_recv(client, (char *)&buf, sizeof(buf));
	if (ret < 0) {
		dev_err(&client->dev, "i2c_master_recv: ret=%d\n", ret);
		goto error_unlock;
	}

	distance = __be16_to_cpu(buf);
	/* check for not returning misleading error codes */
	if (distance < 0) {
		dev_err(&client->dev, "distance=%d\n", distance);
		ret = -EINVAL;
		goto error_unlock;
	}

	mutex_unlock(&data->lock);

	return distance;

error_unlock:
	mutex_unlock(&data->lock);

	return ret;
}

static irqreturn_t mb1232_trigger_handler(int irq, void *p)
{
	struct iio_poll_func *pf = p;
	struct iio_dev *indio_dev = pf->indio_dev;
	struct mb1232_data *data = iio_priv(indio_dev);
	struct {
		s16 distance;
		aligned_s64 ts;
	} scan = { };

Annotation

Implementation Notes