Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

iio: hid-sensor-prox: Add support for more channels

Egis620 supports 3 channels: presense, proximity and attention.

Modify the driver so it can read those channels as well.

Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
Link: https://patch.msgid.link/20241101-hpd-v3-5-e9c80b7c7164@chromium.org
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Ricardo Ribalda and committed by
Jonathan Cameron
596ef5cf f7a1fc1a

+103 -75
+103 -75
drivers/iio/light/hid-sensor-prox.c
··· 13 13 #include <linux/iio/buffer.h> 14 14 #include "../common/hid-sensors/hid-sensor-trigger.h" 15 15 16 - #define CHANNEL_SCAN_INDEX_PRESENCE 0 16 + static const u32 prox_usage_ids[] = { 17 + HID_USAGE_SENSOR_HUMAN_PRESENCE, 18 + HID_USAGE_SENSOR_HUMAN_PROXIMITY, 19 + HID_USAGE_SENSOR_HUMAN_ATTENTION, 20 + }; 21 + 22 + #define MAX_CHANNELS ARRAY_SIZE(prox_usage_ids) 23 + 24 + enum { 25 + HID_HUMAN_PRESENCE, 26 + HID_HUMAN_PROXIMITY, 27 + HID_HUMAN_ATTENTION, 28 + }; 17 29 18 30 struct prox_state { 19 31 struct hid_sensor_hub_callbacks callbacks; 20 32 struct hid_sensor_common common_attributes; 21 - struct hid_sensor_hub_attribute_info prox_attr; 22 - u32 human_presence; 33 + struct hid_sensor_hub_attribute_info prox_attr[MAX_CHANNELS]; 34 + struct iio_chan_spec channels[MAX_CHANNELS]; 35 + u32 channel2usage[MAX_CHANNELS]; 36 + u32 human_presence[MAX_CHANNELS]; 23 37 int scale_pre_decml; 24 38 int scale_post_decml; 25 39 int scale_precision; 40 + unsigned long scan_mask[2]; /* One entry plus one terminator. */ 41 + int num_channels; 26 42 }; 27 43 28 44 static const u32 prox_sensitivity_addresses[] = { ··· 46 30 HID_USAGE_SENSOR_DATA_PRESENCE, 47 31 }; 48 32 49 - /* Channel definitions */ 50 - static const struct iio_chan_spec prox_channels[] = { 51 - { 52 - .type = IIO_PROXIMITY, 53 - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 54 - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | 55 - BIT(IIO_CHAN_INFO_SCALE) | 56 - BIT(IIO_CHAN_INFO_SAMP_FREQ) | 57 - BIT(IIO_CHAN_INFO_HYSTERESIS), 58 - .scan_index = CHANNEL_SCAN_INDEX_PRESENCE, 59 - .indexed = true, 33 + #define PROX_CHANNEL(_is_proximity, _channel) \ 34 + {\ 35 + .type = _is_proximity ? IIO_PROXIMITY : IIO_ATTENTION,\ 36 + .info_mask_separate = _is_proximity ? BIT(IIO_CHAN_INFO_RAW) :\ 37 + BIT(IIO_CHAN_INFO_PROCESSED),\ 38 + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |\ 39 + BIT(IIO_CHAN_INFO_SCALE) |\ 40 + BIT(IIO_CHAN_INFO_SAMP_FREQ) |\ 41 + BIT(IIO_CHAN_INFO_HYSTERESIS),\ 42 + .indexed = _is_proximity,\ 43 + .channel = _channel,\ 60 44 } 45 + 46 + /* Channel definitions (same order as prox_usage_ids) */ 47 + static const struct iio_chan_spec prox_channels[] = { 48 + PROX_CHANNEL(true, HID_HUMAN_PRESENCE), 49 + PROX_CHANNEL(true, HID_HUMAN_PROXIMITY), 50 + PROX_CHANNEL(false, 0), 61 51 }; 62 52 63 53 /* Adjust channel real bits based on report descriptor */ ··· 85 63 { 86 64 struct prox_state *prox_state = iio_priv(indio_dev); 87 65 struct hid_sensor_hub_device *hsdev; 88 - int report_id = -1; 66 + int report_id; 89 67 u32 address; 90 68 int ret_type; 91 69 s32 min; ··· 94 72 *val2 = 0; 95 73 switch (mask) { 96 74 case IIO_CHAN_INFO_RAW: 97 - switch (chan->scan_index) { 98 - case CHANNEL_SCAN_INDEX_PRESENCE: 99 - report_id = prox_state->prox_attr.report_id; 100 - min = prox_state->prox_attr.logical_minimum; 101 - address = HID_USAGE_SENSOR_HUMAN_PRESENCE; 102 - hsdev = prox_state->common_attributes.hsdev; 103 - break; 104 - default: 105 - report_id = -1; 106 - break; 107 - } 108 - if (report_id >= 0) { 109 - hid_sensor_power_state(&prox_state->common_attributes, 110 - true); 111 - *val = sensor_hub_input_attr_get_raw_value( 112 - hsdev, hsdev->usage, address, report_id, 113 - SENSOR_HUB_SYNC, min < 0); 114 - hid_sensor_power_state(&prox_state->common_attributes, 115 - false); 116 - } else { 117 - *val = 0; 75 + if (chan->scan_index >= prox_state->num_channels) 118 76 return -EINVAL; 119 - } 77 + address = prox_state->channel2usage[chan->scan_index]; 78 + report_id = prox_state->prox_attr[chan->scan_index].report_id; 79 + hsdev = prox_state->common_attributes.hsdev; 80 + min = prox_state->prox_attr[chan->scan_index].logical_minimum; 81 + hid_sensor_power_state(&prox_state->common_attributes, true); 82 + *val = sensor_hub_input_attr_get_raw_value(hsdev, 83 + hsdev->usage, 84 + address, 85 + report_id, 86 + SENSOR_HUB_SYNC, 87 + min < 0); 88 + if (prox_state->channel2usage[chan->scan_index] == 89 + HID_USAGE_SENSOR_HUMAN_ATTENTION) 90 + *val *= 100; 91 + hid_sensor_power_state(&prox_state->common_attributes, false); 120 92 ret_type = IIO_VAL_INT; 121 93 break; 122 94 case IIO_CHAN_INFO_SCALE: ··· 120 104 break; 121 105 case IIO_CHAN_INFO_OFFSET: 122 106 *val = hid_sensor_convert_exponent( 123 - prox_state->prox_attr.unit_expo); 107 + prox_state->prox_attr[chan->scan_index].unit_expo); 124 108 ret_type = IIO_VAL_INT; 125 109 break; 126 110 case IIO_CHAN_INFO_SAMP_FREQ: ··· 195 179 { 196 180 struct iio_dev *indio_dev = platform_get_drvdata(priv); 197 181 struct prox_state *prox_state = iio_priv(indio_dev); 198 - int ret = -EINVAL; 182 + int multiplier = 1; 183 + int chan; 199 184 200 - switch (usage_id) { 201 - case HID_USAGE_SENSOR_HUMAN_PRESENCE: 202 - switch (raw_len) { 203 - case 1: 204 - prox_state->human_presence = *(u8 *)raw_data; 205 - return 0; 206 - case 4: 207 - prox_state->human_presence = *(u32 *)raw_data; 208 - return 0; 209 - default: 185 + for (chan = 0; chan < prox_state->num_channels; chan++) 186 + if (prox_state->channel2usage[chan] == usage_id) 210 187 break; 211 - } 212 - break; 188 + if (chan == prox_state->num_channels) 189 + return -EINVAL; 190 + 191 + if (usage_id == HID_USAGE_SENSOR_HUMAN_ATTENTION) 192 + multiplier = 100; 193 + 194 + switch (raw_len) { 195 + case 1: 196 + prox_state->human_presence[chan] = *(u8 *)raw_data * multiplier; 197 + return 0; 198 + case 4: 199 + prox_state->human_presence[chan] = *(u32 *)raw_data * multiplier; 200 + return 0; 213 201 } 214 202 215 - return ret; 203 + return -EINVAL; 216 204 } 217 205 218 206 /* Parse report which is specific to an usage id*/ 219 207 static int prox_parse_report(struct platform_device *pdev, 220 208 struct hid_sensor_hub_device *hsdev, 221 - struct iio_chan_spec *channels, 222 - unsigned usage_id, 223 209 struct prox_state *st) 224 210 { 211 + struct iio_chan_spec *channels = st->channels; 212 + int index = 0; 225 213 int ret; 214 + int i; 226 215 227 - ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT, 228 - usage_id, 229 - HID_USAGE_SENSOR_HUMAN_PRESENCE, 230 - &st->prox_attr); 231 - if (ret < 0) 216 + for (i = 0; i < MAX_CHANNELS; i++) { 217 + u32 usage_id = prox_usage_ids[i]; 218 + 219 + ret = sensor_hub_input_get_attribute_info(hsdev, 220 + HID_INPUT_REPORT, 221 + hsdev->usage, 222 + usage_id, 223 + &st->prox_attr[index]); 224 + if (ret < 0) 225 + continue; 226 + st->channel2usage[index] = usage_id; 227 + st->scan_mask[0] |= BIT(index); 228 + channels[index] = prox_channels[i]; 229 + channels[index].scan_index = index; 230 + prox_adjust_channel_bit_mask(channels, index, 231 + st->prox_attr[index].size); 232 + dev_dbg(&pdev->dev, "prox %x:%x\n", st->prox_attr[index].index, 233 + st->prox_attr[index].report_id); 234 + index++; 235 + } 236 + 237 + if (!index) 232 238 return ret; 233 - prox_adjust_channel_bit_mask(channels, CHANNEL_SCAN_INDEX_PRESENCE, 234 - st->prox_attr.size); 235 239 236 - dev_dbg(&pdev->dev, "prox %x:%x\n", st->prox_attr.index, 237 - st->prox_attr.report_id); 240 + st->num_channels = index; 238 241 239 - return ret; 242 + return 0; 240 243 } 241 244 242 245 /* Function to initialize the processing for usage id */ ··· 286 251 return ret; 287 252 } 288 253 289 - indio_dev->channels = devm_kmemdup(&pdev->dev, prox_channels, 290 - sizeof(prox_channels), GFP_KERNEL); 291 - if (!indio_dev->channels) { 292 - dev_err(&pdev->dev, "failed to duplicate channels\n"); 293 - return -ENOMEM; 294 - } 295 - 296 - ret = prox_parse_report(pdev, hsdev, 297 - (struct iio_chan_spec *)indio_dev->channels, 298 - hsdev->usage, prox_state); 254 + ret = prox_parse_report(pdev, hsdev, prox_state); 299 255 if (ret) { 300 256 dev_err(&pdev->dev, "failed to setup attributes\n"); 301 257 return ret; 302 258 } 303 259 304 - indio_dev->num_channels = ARRAY_SIZE(prox_channels); 260 + indio_dev->num_channels = prox_state->num_channels; 261 + indio_dev->channels = prox_state->channels; 262 + indio_dev->available_scan_masks = prox_state->scan_mask; 305 263 indio_dev->info = &prox_info; 306 264 indio_dev->name = name; 307 265 indio_dev->modes = INDIO_DIRECT_MODE;