drivers/hwmon/sht4x.c

Source file repositories/reference/linux-study-clean/drivers/hwmon/sht4x.c

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/sht4x.c
Extension
.c
Size
11124 bytes
Lines
452
Domain
Driver Families
Bucket
drivers/hwmon
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 sht4x_data {
	struct i2c_client	*client;
	unsigned long		heating_complete;	/* in jiffies */
	bool			data_pending;
	u32			heater_power;	/* in milli-watts */
	u32			heater_time;	/* in milli-seconds */
	bool			valid;	/* validity of fields below */
	long			update_interval;	/* in milli-seconds */
	long			last_updated;	/* in jiffies */
	s32			temperature;
	s32			humidity;
};

/**
 * sht4x_read_values() - read and parse the raw data from the SHT4X
 * @data: the struct sht4x_data to use for the lock
 * Return: 0 if successful, -ERRNO if not
 */
static int sht4x_read_values(struct sht4x_data *data)
{
	int ret;
	u16 t_ticks, rh_ticks;
	unsigned long next_update;
	struct i2c_client *client = data->client;
	u8 crc;
	u8 cmd[SHT4X_CMD_LEN] = {SHT4X_CMD_MEASURE_HPM};
	u8 raw_data[SHT4X_RESPONSE_LENGTH];
	unsigned long curr_jiffies;

	curr_jiffies = jiffies;
	if (time_before(curr_jiffies, data->heating_complete))
		msleep(jiffies_to_msecs(data->heating_complete - curr_jiffies));

	if (data->data_pending &&
	    time_before(jiffies, data->heating_complete + data->update_interval)) {
		data->data_pending = false;
	} else {
		next_update = data->last_updated +
			msecs_to_jiffies(data->update_interval);

		if (data->valid && time_before_eq(jiffies, next_update))
			return 0;

		ret = i2c_master_send(client, cmd, SHT4X_CMD_LEN);
		if (ret < 0)
			return ret;

		usleep_range(SHT4X_MEAS_DELAY_HPM, SHT4X_MEAS_DELAY_HPM + SHT4X_DELAY_EXTRA);
	}

	ret = i2c_master_recv(client, raw_data, SHT4X_RESPONSE_LENGTH);
	if (ret != SHT4X_RESPONSE_LENGTH) {
		if (ret >= 0)
			ret = -ENODATA;
		return ret;
	}

	t_ticks = raw_data[0] << 8 | raw_data[1];
	rh_ticks = raw_data[3] << 8 | raw_data[4];

	crc = crc8(sht4x_crc8_table, &raw_data[0], SHT4X_WORD_LEN, CRC8_INIT_VALUE);
	if (crc != raw_data[2]) {
		dev_err(&client->dev, "data integrity check failed\n");
		return -EIO;
	}

	crc = crc8(sht4x_crc8_table, &raw_data[3], SHT4X_WORD_LEN, CRC8_INIT_VALUE);
	if (crc != raw_data[5]) {
		dev_err(&client->dev, "data integrity check failed\n");
		return -EIO;
	}

	data->temperature = ((21875 * (int32_t)t_ticks) >> 13) - 45000;
	data->humidity = ((15625 * (int32_t)rh_ticks) >> 13) - 6000;
	data->last_updated = jiffies;
	data->valid = true;
	return 0;
}

static ssize_t sht4x_interval_write(struct sht4x_data *data, long val)
{
	data->update_interval = clamp_val(val, SHT4X_MIN_POLL_INTERVAL, INT_MAX);

	return 0;
}

/* sht4x_interval_read() - read the minimum poll interval in milliseconds */
static size_t sht4x_interval_read(struct sht4x_data *data, long *val)
{
	*val = data->update_interval;

Annotation

Implementation Notes