diff options
Diffstat (limited to 'drivers/rtc/rtc-hid-sensor-time.c')
-rw-r--r-- | drivers/rtc/rtc-hid-sensor-time.c | 48 |
1 files changed, 36 insertions, 12 deletions
diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c index 63024505dddc..7273b0139e5c 100644 --- a/drivers/rtc/rtc-hid-sensor-time.c +++ b/drivers/rtc/rtc-hid-sensor-time.c | |||
@@ -76,6 +76,20 @@ static int hid_time_proc_event(struct hid_sensor_hub_device *hsdev, | |||
76 | return 0; | 76 | return 0; |
77 | } | 77 | } |
78 | 78 | ||
79 | static u32 hid_time_value(size_t raw_len, char *raw_data) | ||
80 | { | ||
81 | switch (raw_len) { | ||
82 | case 1: | ||
83 | return *(u8 *)raw_data; | ||
84 | case 2: | ||
85 | return *(u16 *)raw_data; | ||
86 | case 4: | ||
87 | return *(u32 *)raw_data; | ||
88 | default: | ||
89 | return (u32)(~0U); /* 0xff... or -1 to denote an error */ | ||
90 | } | ||
91 | } | ||
92 | |||
79 | static int hid_time_capture_sample(struct hid_sensor_hub_device *hsdev, | 93 | static int hid_time_capture_sample(struct hid_sensor_hub_device *hsdev, |
80 | unsigned usage_id, size_t raw_len, | 94 | unsigned usage_id, size_t raw_len, |
81 | char *raw_data, void *priv) | 95 | char *raw_data, void *priv) |
@@ -85,26 +99,35 @@ static int hid_time_capture_sample(struct hid_sensor_hub_device *hsdev, | |||
85 | 99 | ||
86 | switch (usage_id) { | 100 | switch (usage_id) { |
87 | case HID_USAGE_SENSOR_TIME_YEAR: | 101 | case HID_USAGE_SENSOR_TIME_YEAR: |
88 | time_buf->tm_year = *(u8 *)raw_data; | 102 | /* |
89 | if (time_buf->tm_year < 70) | 103 | * The draft for HID-sensors (HUTRR39) currently doesn't define |
90 | /* assume we are in 1970...2069 */ | 104 | * the range for the year attribute. Therefor we support |
91 | time_buf->tm_year += 100; | 105 | * 8 bit (0-99) and 16 or 32 bits (full) as size for the year. |
106 | */ | ||
107 | if (raw_len == 1) { | ||
108 | time_buf->tm_year = *(u8 *)raw_data; | ||
109 | if (time_buf->tm_year < 70) | ||
110 | /* assume we are in 1970...2069 */ | ||
111 | time_buf->tm_year += 100; | ||
112 | } else | ||
113 | time_buf->tm_year = | ||
114 | (int)hid_time_value(raw_len, raw_data)-1900; | ||
92 | break; | 115 | break; |
93 | case HID_USAGE_SENSOR_TIME_MONTH: | 116 | case HID_USAGE_SENSOR_TIME_MONTH: |
94 | /* sensor sending the month as 1-12, we need 0-11 */ | 117 | /* sensors are sending the month as 1-12, we need 0-11 */ |
95 | time_buf->tm_mon = *(u8 *)raw_data-1; | 118 | time_buf->tm_mon = (int)hid_time_value(raw_len, raw_data)-1; |
96 | break; | 119 | break; |
97 | case HID_USAGE_SENSOR_TIME_DAY: | 120 | case HID_USAGE_SENSOR_TIME_DAY: |
98 | time_buf->tm_mday = *(u8 *)raw_data; | 121 | time_buf->tm_mday = (int)hid_time_value(raw_len, raw_data); |
99 | break; | 122 | break; |
100 | case HID_USAGE_SENSOR_TIME_HOUR: | 123 | case HID_USAGE_SENSOR_TIME_HOUR: |
101 | time_buf->tm_hour = *(u8 *)raw_data; | 124 | time_buf->tm_hour = (int)hid_time_value(raw_len, raw_data); |
102 | break; | 125 | break; |
103 | case HID_USAGE_SENSOR_TIME_MINUTE: | 126 | case HID_USAGE_SENSOR_TIME_MINUTE: |
104 | time_buf->tm_min = *(u8 *)raw_data; | 127 | time_buf->tm_min = (int)hid_time_value(raw_len, raw_data); |
105 | break; | 128 | break; |
106 | case HID_USAGE_SENSOR_TIME_SECOND: | 129 | case HID_USAGE_SENSOR_TIME_SECOND: |
107 | time_buf->tm_sec = *(u8 *)raw_data; | 130 | time_buf->tm_sec = (int)hid_time_value(raw_len, raw_data); |
108 | break; | 131 | break; |
109 | default: | 132 | default: |
110 | return -EINVAL; | 133 | return -EINVAL; |
@@ -150,9 +173,10 @@ static int hid_time_parse_report(struct platform_device *pdev, | |||
150 | "not all needed attributes inside the same report!\n"); | 173 | "not all needed attributes inside the same report!\n"); |
151 | return -EINVAL; | 174 | return -EINVAL; |
152 | } | 175 | } |
153 | if (time_state->info[i].size != 1) { | 176 | if (time_state->info[i].size == 3 || |
177 | time_state->info[i].size > 4) { | ||
154 | dev_err(&pdev->dev, | 178 | dev_err(&pdev->dev, |
155 | "attribute '%s' not 8 bits wide!\n", | 179 | "attribute '%s' not 8, 16 or 32 bits wide!\n", |
156 | hid_time_attrib_name( | 180 | hid_time_attrib_name( |
157 | time_state->info[i].attrib_id)); | 181 | time_state->info[i].attrib_id)); |
158 | return -EINVAL; | 182 | return -EINVAL; |