drivers/iio/humidity/dht11.c

Source file repositories/reference/linux-study-clean/drivers/iio/humidity/dht11.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/humidity/dht11.c
Extension
.c
Size
9100 bytes
Lines
341
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 dht11 {
	struct device			*dev;

	struct gpio_desc		*gpiod;
	int				irq;

	struct completion		completion;
	/* The iio sysfs interface doesn't prevent concurrent reads: */
	struct mutex			lock;

	s64				timestamp;
	int				temperature;
	int				humidity;

	/* num_edges: -1 means "no transmission in progress" */
	int				num_edges;
	struct {s64 ts; int value; }	edges[DHT11_EDGES_PER_READ];
};

#ifdef CONFIG_DYNAMIC_DEBUG
/*
 * dht11_edges_print: show the data as actually received by the
 *                    driver.
 */
static void dht11_edges_print(struct dht11 *dht11)
{
	int i;

	dev_dbg(dht11->dev, "%d edges detected:\n", dht11->num_edges);
	for (i = 1; i < dht11->num_edges; ++i) {
		dev_dbg(dht11->dev, "%d: %lld ns %s\n", i,
			dht11->edges[i].ts - dht11->edges[i - 1].ts,
			str_high_low(dht11->edges[i - 1].value));
	}
}
#endif /* CONFIG_DYNAMIC_DEBUG */

static unsigned char dht11_decode_byte(char *bits)
{
	unsigned char ret = 0;
	int i;

	for (i = 0; i < 8; ++i) {
		ret <<= 1;
		if (bits[i])
			++ret;
	}

	return ret;
}

static int dht11_decode(struct dht11 *dht11, int offset)
{
	int i, t;
	char bits[DHT11_BITS_PER_READ];
	unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum;

	for (i = 0; i < DHT11_BITS_PER_READ; ++i) {
		t = dht11->edges[offset + 2 * i + 2].ts -
			dht11->edges[offset + 2 * i + 1].ts;
		if (!dht11->edges[offset + 2 * i + 1].value) {
			dev_dbg(dht11->dev,
				"lost synchronisation at edge %d\n",
				offset + 2 * i + 1);
			return -EIO;
		}
		bits[i] = t > DHT11_THRESHOLD;
	}

	hum_int = dht11_decode_byte(bits);
	hum_dec = dht11_decode_byte(&bits[8]);
	temp_int = dht11_decode_byte(&bits[16]);
	temp_dec = dht11_decode_byte(&bits[24]);
	checksum = dht11_decode_byte(&bits[32]);

	if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum) {
		dev_dbg(dht11->dev, "invalid checksum\n");
		return -EIO;
	}

	dht11->timestamp = ktime_get_boottime_ns();
	if (hum_int < 4) {  /* DHT22: 100000 = (3*256+232)*100 */
		dht11->temperature = (((temp_int & 0x7f) << 8) + temp_dec) *
					((temp_int & 0x80) ? -100 : 100);
		dht11->humidity = ((hum_int << 8) + hum_dec) * 100;
	} else if (temp_dec == 0 && hum_dec == 0) {  /* DHT11 */
		dht11->temperature = temp_int * 1000;
		dht11->humidity = hum_int * 1000;
	} else {
		dev_err(dht11->dev,

Annotation

Implementation Notes