1 /* 2 * HID Sensors Driver 3 * Copyright (c) 2017, Intel Corporation. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms and conditions of the GNU General Public License, 7 * version 2, as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 * You should have received a copy of the GNU General Public License along with 15 * this program. 16 */ 17 #include <linux/device.h> 18 #include <linux/hid-sensor-hub.h> 19 #include <linux/iio/buffer.h> 20 #include <linux/iio/iio.h> 21 #include <linux/iio/triggered_buffer.h> 22 #include <linux/iio/trigger_consumer.h> 23 #include <linux/module.h> 24 #include <linux/platform_device.h> 25 26 #include "../common/hid-sensors/hid-sensor-trigger.h" 27 28 struct temperature_state { 29 struct hid_sensor_common common_attributes; 30 struct hid_sensor_hub_attribute_info temperature_attr; 31 s32 temperature_data; 32 int scale_pre_decml; 33 int scale_post_decml; 34 int scale_precision; 35 int value_offset; 36 }; 37 38 /* Channel definitions */ 39 static const struct iio_chan_spec temperature_channels[] = { 40 { 41 .type = IIO_TEMP, 42 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 43 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | 44 BIT(IIO_CHAN_INFO_SCALE) | 45 BIT(IIO_CHAN_INFO_SAMP_FREQ) | 46 BIT(IIO_CHAN_INFO_HYSTERESIS), 47 }, 48 IIO_CHAN_SOFT_TIMESTAMP(3), 49 }; 50 51 /* Adjust channel real bits based on report descriptor */ 52 static void temperature_adjust_channel_bit_mask(struct iio_chan_spec *channels, 53 int channel, int size) 54 { 55 channels[channel].scan_type.sign = 's'; 56 /* Real storage bits will change based on the report desc. */ 57 channels[channel].scan_type.realbits = size * 8; 58 /* Maximum size of a sample to capture is s32 */ 59 channels[channel].scan_type.storagebits = sizeof(s32) * 8; 60 } 61 62 static int temperature_read_raw(struct iio_dev *indio_dev, 63 struct iio_chan_spec const *chan, 64 int *val, int *val2, long mask) 65 { 66 struct temperature_state *temp_st = iio_priv(indio_dev); 67 68 switch (mask) { 69 case IIO_CHAN_INFO_RAW: 70 if (chan->type != IIO_TEMP) 71 return -EINVAL; 72 hid_sensor_power_state( 73 &temp_st->common_attributes, true); 74 *val = sensor_hub_input_attr_get_raw_value( 75 temp_st->common_attributes.hsdev, 76 HID_USAGE_SENSOR_TEMPERATURE, 77 HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE, 78 temp_st->temperature_attr.report_id, 79 SENSOR_HUB_SYNC); 80 hid_sensor_power_state( 81 &temp_st->common_attributes, 82 false); 83 84 return IIO_VAL_INT; 85 86 case IIO_CHAN_INFO_SCALE: 87 *val = temp_st->scale_pre_decml; 88 *val2 = temp_st->scale_post_decml; 89 return temp_st->scale_precision; 90 91 case IIO_CHAN_INFO_OFFSET: 92 *val = temp_st->value_offset; 93 return IIO_VAL_INT; 94 95 case IIO_CHAN_INFO_SAMP_FREQ: 96 return hid_sensor_read_samp_freq_value( 97 &temp_st->common_attributes, val, val2); 98 99 case IIO_CHAN_INFO_HYSTERESIS: 100 return hid_sensor_read_raw_hyst_value( 101 &temp_st->common_attributes, val, val2); 102 default: 103 return -EINVAL; 104 } 105 } 106 107 static int temperature_write_raw(struct iio_dev *indio_dev, 108 struct iio_chan_spec const *chan, 109 int val, int val2, long mask) 110 { 111 struct temperature_state *temp_st = iio_priv(indio_dev); 112 113 switch (mask) { 114 case IIO_CHAN_INFO_SAMP_FREQ: 115 return hid_sensor_write_samp_freq_value( 116 &temp_st->common_attributes, val, val2); 117 case IIO_CHAN_INFO_HYSTERESIS: 118 return hid_sensor_write_raw_hyst_value( 119 &temp_st->common_attributes, val, val2); 120 default: 121 return -EINVAL; 122 } 123 } 124 125 static const struct iio_info temperature_info = { 126 .read_raw = &temperature_read_raw, 127 .write_raw = &temperature_write_raw, 128 }; 129 130 /* Callback handler to send event after all samples are received and captured */ 131 static int temperature_proc_event(struct hid_sensor_hub_device *hsdev, 132 unsigned int usage_id, void *pdev) 133 { 134 struct iio_dev *indio_dev = platform_get_drvdata(pdev); 135 struct temperature_state *temp_st = iio_priv(indio_dev); 136 137 if (atomic_read(&temp_st->common_attributes.data_ready)) 138 iio_push_to_buffers_with_timestamp(indio_dev, 139 &temp_st->temperature_data, 140 iio_get_time_ns(indio_dev)); 141 142 return 0; 143 } 144 145 /* Capture samples in local storage */ 146 static int temperature_capture_sample(struct hid_sensor_hub_device *hsdev, 147 unsigned int usage_id, size_t raw_len, 148 char *raw_data, void *pdev) 149 { 150 struct iio_dev *indio_dev = platform_get_drvdata(pdev); 151 struct temperature_state *temp_st = iio_priv(indio_dev); 152 153 switch (usage_id) { 154 case HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE: 155 temp_st->temperature_data = *(s32 *)raw_data; 156 return 0; 157 default: 158 return -EINVAL; 159 } 160 } 161 162 /* Parse report which is specific to an usage id*/ 163 static int temperature_parse_report(struct platform_device *pdev, 164 struct hid_sensor_hub_device *hsdev, 165 struct iio_chan_spec *channels, 166 unsigned int usage_id, 167 struct temperature_state *st) 168 { 169 int ret; 170 171 ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT, 172 usage_id, 173 HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE, 174 &st->temperature_attr); 175 if (ret < 0) 176 return ret; 177 178 temperature_adjust_channel_bit_mask(channels, 0, 179 st->temperature_attr.size); 180 181 st->scale_precision = hid_sensor_format_scale( 182 HID_USAGE_SENSOR_TEMPERATURE, 183 &st->temperature_attr, 184 &st->scale_pre_decml, &st->scale_post_decml); 185 186 /* Set Sensitivity field ids, when there is no individual modifier */ 187 if (st->common_attributes.sensitivity.index < 0) 188 sensor_hub_input_get_attribute_info(hsdev, 189 HID_FEATURE_REPORT, usage_id, 190 HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS | 191 HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE, 192 &st->common_attributes.sensitivity); 193 194 return ret; 195 } 196 197 static struct hid_sensor_hub_callbacks temperature_callbacks = { 198 .send_event = &temperature_proc_event, 199 .capture_sample = &temperature_capture_sample, 200 }; 201 202 /* Function to initialize the processing for usage id */ 203 static int hid_temperature_probe(struct platform_device *pdev) 204 { 205 static const char *name = "temperature"; 206 struct iio_dev *indio_dev; 207 struct temperature_state *temp_st; 208 struct iio_chan_spec *temp_chans; 209 struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev); 210 int ret; 211 212 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*temp_st)); 213 if (!indio_dev) 214 return -ENOMEM; 215 216 temp_st = iio_priv(indio_dev); 217 temp_st->common_attributes.hsdev = hsdev; 218 temp_st->common_attributes.pdev = pdev; 219 220 ret = hid_sensor_parse_common_attributes(hsdev, 221 HID_USAGE_SENSOR_TEMPERATURE, 222 &temp_st->common_attributes); 223 if (ret) 224 return ret; 225 226 temp_chans = devm_kmemdup(&indio_dev->dev, temperature_channels, 227 sizeof(temperature_channels), GFP_KERNEL); 228 if (!temp_chans) 229 return -ENOMEM; 230 231 ret = temperature_parse_report(pdev, hsdev, temp_chans, 232 HID_USAGE_SENSOR_TEMPERATURE, temp_st); 233 if (ret) 234 return ret; 235 236 indio_dev->channels = temp_chans; 237 indio_dev->num_channels = ARRAY_SIZE(temperature_channels); 238 indio_dev->dev.parent = &pdev->dev; 239 indio_dev->info = &temperature_info; 240 indio_dev->name = name; 241 indio_dev->modes = INDIO_DIRECT_MODE; 242 243 ret = devm_iio_triggered_buffer_setup(&pdev->dev, indio_dev, 244 &iio_pollfunc_store_time, NULL, NULL); 245 if (ret) 246 return ret; 247 248 atomic_set(&temp_st->common_attributes.data_ready, 0); 249 ret = hid_sensor_setup_trigger(indio_dev, name, 250 &temp_st->common_attributes); 251 if (ret) 252 return ret; 253 254 platform_set_drvdata(pdev, indio_dev); 255 256 temperature_callbacks.pdev = pdev; 257 ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE, 258 &temperature_callbacks); 259 if (ret) 260 goto error_remove_trigger; 261 262 ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev); 263 if (ret) 264 goto error_remove_callback; 265 266 return ret; 267 268 error_remove_callback: 269 sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE); 270 error_remove_trigger: 271 hid_sensor_remove_trigger(&temp_st->common_attributes); 272 return ret; 273 } 274 275 /* Function to deinitialize the processing for usage id */ 276 static int hid_temperature_remove(struct platform_device *pdev) 277 { 278 struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev); 279 struct iio_dev *indio_dev = platform_get_drvdata(pdev); 280 struct temperature_state *temp_st = iio_priv(indio_dev); 281 282 sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE); 283 hid_sensor_remove_trigger(&temp_st->common_attributes); 284 285 return 0; 286 } 287 288 static const struct platform_device_id hid_temperature_ids[] = { 289 { 290 /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ 291 .name = "HID-SENSOR-200033", 292 }, 293 { /* sentinel */ } 294 }; 295 MODULE_DEVICE_TABLE(platform, hid_temperature_ids); 296 297 static struct platform_driver hid_temperature_platform_driver = { 298 .id_table = hid_temperature_ids, 299 .driver = { 300 .name = "temperature-sensor", 301 .pm = &hid_sensor_pm_ops, 302 }, 303 .probe = hid_temperature_probe, 304 .remove = hid_temperature_remove, 305 }; 306 module_platform_driver(hid_temperature_platform_driver); 307 308 MODULE_DESCRIPTION("HID Environmental temperature sensor"); 309 MODULE_AUTHOR("Song Hongyan <hongyan.song@intel.com>"); 310 MODULE_LICENSE("GPL v2"); 311