drivers/rtc/rtc-hid-sensor-time.c

Source file repositories/reference/linux-study-clean/drivers/rtc/rtc-hid-sensor-time.c

File Facts

System
Linux kernel
Corpus path
drivers/rtc/rtc-hid-sensor-time.c
Extension
.c
Size
9210 bytes
Lines
330
Domain
Driver Families
Bucket
drivers/rtc
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 hid_time_state {
	struct hid_sensor_hub_callbacks callbacks;
	struct hid_sensor_common common_attributes;
	struct hid_sensor_hub_attribute_info info[TIME_RTC_CHANNEL_MAX];
	struct rtc_time last_time;
	spinlock_t lock_last_time;
	struct completion comp_last_time;
	struct rtc_time time_buf;
	struct rtc_device *rtc;
};

static const u32 hid_time_addresses[TIME_RTC_CHANNEL_MAX] = {
	HID_USAGE_SENSOR_TIME_YEAR,
	HID_USAGE_SENSOR_TIME_MONTH,
	HID_USAGE_SENSOR_TIME_DAY,
	HID_USAGE_SENSOR_TIME_HOUR,
	HID_USAGE_SENSOR_TIME_MINUTE,
	HID_USAGE_SENSOR_TIME_SECOND,
};

/* Channel names for verbose error messages */
static const char * const hid_time_channel_names[TIME_RTC_CHANNEL_MAX] = {
	"year", "month", "day", "hour", "minute", "second",
};

/* Callback handler to send event after all samples are received and captured */
static int hid_time_proc_event(struct hid_sensor_hub_device *hsdev,
				unsigned usage_id, void *priv)
{
	unsigned long flags;
	struct hid_time_state *time_state = platform_get_drvdata(priv);

	spin_lock_irqsave(&time_state->lock_last_time, flags);
	time_state->last_time = time_state->time_buf;
	spin_unlock_irqrestore(&time_state->lock_last_time, flags);
	complete(&time_state->comp_last_time);
	return 0;
}

static u32 hid_time_value(size_t raw_len, char *raw_data)
{
	switch (raw_len) {
	case 1:
		return *(u8 *)raw_data;
	case 2:
		return *(u16 *)raw_data;
	case 4:
		return *(u32 *)raw_data;
	default:
		return (u32)(~0U); /* 0xff... or -1 to denote an error */
	}
}

static int hid_time_capture_sample(struct hid_sensor_hub_device *hsdev,
				unsigned usage_id, size_t raw_len,
				char *raw_data, void *priv)
{
	struct hid_time_state *time_state = platform_get_drvdata(priv);
	struct rtc_time *time_buf = &time_state->time_buf;

	switch (usage_id) {
	case HID_USAGE_SENSOR_TIME_YEAR:
		/*
		 * The draft for HID-sensors (HUTRR39) currently doesn't define
		 * the range for the year attribute. Therefor we support
		 * 8 bit (0-99) and 16 or 32 bits (full) as size for the year.
		 */
		if (raw_len == 1) {
			time_buf->tm_year = *(u8 *)raw_data;
			if (time_buf->tm_year < 70)
				/* assume we are in 1970...2069 */
				time_buf->tm_year += 100;
		} else
			time_buf->tm_year =
				(int)hid_time_value(raw_len, raw_data)-1900;
		break;
	case HID_USAGE_SENSOR_TIME_MONTH:
		/* sensors are sending the month as 1-12, we need 0-11 */
		time_buf->tm_mon = (int)hid_time_value(raw_len, raw_data)-1;
		break;
	case HID_USAGE_SENSOR_TIME_DAY:
		time_buf->tm_mday = (int)hid_time_value(raw_len, raw_data);
		break;
	case HID_USAGE_SENSOR_TIME_HOUR:
		time_buf->tm_hour = (int)hid_time_value(raw_len, raw_data);
		break;
	case HID_USAGE_SENSOR_TIME_MINUTE:
		time_buf->tm_min = (int)hid_time_value(raw_len, raw_data);
		break;
	case HID_USAGE_SENSOR_TIME_SECOND:

Annotation

Implementation Notes