[no subject]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> +
> +       data_size = HX9023S_3BYTES;
> +
> +       /* ch0~ch3 */
> +       p = rx_buf;
> +       size = (HX9023S_CH_NUM - 1) * data_size;
> +       ret = regmap_bulk_read(data->regmap, HX9023S_RAW_BL_CH0_0, p, size);
> +       if (ret)
> +               return ret;
> +
> +       /* ch4 */
> +       p = rx_buf + size;
> +       size = data_size;
> +       ret = regmap_bulk_read(data->regmap, HX9023S_RAW_BL_CH4_0, p, size);
> +       if (ret)
> +               return ret;
> +
> +       for (i = 0; i < HX9023S_CH_NUM; i++) {

[1]
Maybe use some per-device (example: indio_dev->num_channels) here
(instead of HX9023S_CH_NUM)?
If adding support for a part with fewer channels, this would crash.
This comment is for all places where for (i = 0; i < HX9023S_CH_NUM;
i++)  is used

> +               value = get_unaligned_le16(&rx_buf[i * data_size + 1]);
> +               value = sign_extend32(value, 15);
> +               data->ch_data[i].raw = 0;
> +               data->ch_data[i].bl = 0;
> +               if (data->ch_data[i].sel_raw == true)
> +                       data->ch_data[i].raw = value;
> +               if (data->ch_data[i].sel_bl == true)
> +                       data->ch_data[i].bl = value;
> +       }
> +
> +       /* ch0~ch3 */
> +       p = rx_buf;
> +       size = (HX9023S_CH_NUM - 1) * data_size;
> +       ret = regmap_bulk_read(data->regmap, HX9023S_LP_DIFF_CH0_0, p, size);
> +       if (ret)
> +               return ret;
> +
> +       /* ch4 */
> +       p = rx_buf + size;
> +       size = data_size;
> +       ret = regmap_bulk_read(data->regmap, HX9023S_LP_DIFF_CH4_0, p, size);
> +       if (ret)
> +               return ret;
> +
> +       for (i = 0; i < HX9023S_CH_NUM; i++) {

See comment [1]

> +               value = get_unaligned_le16(&rx_buf[i * data_size + 1]);
> +               value = sign_extend32(value, 15);
> +               data->ch_data[i].lp = 0;
> +               data->ch_data[i].diff = 0;
> +               if (data->ch_data[i].sel_lp == true)
> +                       data->ch_data[i].lp = value;
> +               if (data->ch_data[i].sel_diff == true)
> +                       data->ch_data[i].diff = value;
> +       }
> +
> +       for (i = 0; i < HX9023S_CH_NUM; i++) {

See comment [1]

> +               if (data->ch_data[i].sel_lp == true && data->ch_data[i].sel_bl == true)
> +                       data->ch_data[i].diff = data->ch_data[i].lp - data->ch_data[i].bl;
> +       }
> +
> +       /* offset DAC */
> +       offset_data_size = HX9023S_2BYTES;
> +       p = rx_buf;
> +       size = HX9023S_CH_NUM * offset_data_size;
> +       ret = regmap_bulk_read(data->regmap, HX9023S_OFFSET_DAC0_7_0, p, size);
> +       if (ret)
> +               return ret;
> +
> +       for (i = 0; i < HX9023S_CH_NUM; i++) {

See comment [1]

> +               value = get_unaligned_le16(&rx_buf[i * offset_data_size]);
> +               value = FIELD_GET(GENMASK(11, 0), value);
> +               data->ch_data[i].dac = value;
> +       }
> +
> +       ret = hx9023s_data_lock(data, false);
> +       if (ret)
> +               return ret;
> +
> +       return 0;
> +}
> +
> +static int hx9023s_ch_en(struct hx9023s_data *data, u8 ch_id, bool en)
> +{
> +       int ret;
> +       unsigned int buf;
> +
> +       ret = regmap_read(data->regmap, HX9023S_CH_NUM_CFG, &buf);
> +       if (ret)
> +               return ret;
> +
> +       data->ch_en_stat = buf;
> +       if (en && data->ch_en_stat == 0)
> +               data->prox_state_reg = 0;
> +
> +       data->ch_data[ch_id].enable = en;
> +       __assign_bit(ch_id, &data->ch_en_stat, en);
> +
> +       return regmap_write(data->regmap, HX9023S_CH_NUM_CFG, data->ch_en_stat);
> +}
> +
> +static int hx9023s_property_get(struct hx9023s_data *data)
> +{
> +       struct fwnode_handle *child;
> +       struct device *dev = regmap_get_device(data->regmap);
> +       int ret;
> +       u32 i, reg, temp, array[2];
> +
> +       data->chan_in_use = 0;
> +       for (i = 0; i < HX9023S_CH_NUM; i++) {

See comment [1]

> +               data->ch_data[i].channel_positive = HX9023S_NOT_CONNECTED;
> +               data->ch_data[i].channel_negative = HX9023S_NOT_CONNECTED;
> +       }
> +
> +       device_for_each_child_node(dev, child) {
> +               ret = fwnode_property_read_u32(child, "reg", &reg);

Maybe add a protection for when reg >= num_channels (HX9023S_CH_NUM)?

> +               if (ret) {
> +                       fwnode_handle_put(child);
> +                       return dev_err_probe(dev, ret, "Failed to read reg\n");
> +               }
> +               __set_bit(reg, &data->chan_in_use);
> +
> +               if (fwnode_property_read_u32(child, "input-channel", &temp) == 0) {
> +                       data->ch_data[reg].channel_positive = temp;
> +                       data->ch_data[reg].channel_negative = HX9023S_NOT_CONNECTED;
> +               } else if (fwnode_property_read_u32_array(child, "diff-channels",
> +                                                       array, sizeof(array)) == 0) {
> +                       data->ch_data[reg].channel_positive = array[0];
> +                       data->ch_data[reg].channel_negative = array[1];
> +               } else {
> +                       fwnode_handle_put(child);
> +                       return dev_err_probe(dev, ret,
> +                               "Failed to read channel input for channel %d\n", reg);
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +static int hx9023s_update_chan_en(struct hx9023s_data *data,
> +                               unsigned long chan_read,
> +                               unsigned long chan_event)
> +{
> +       unsigned int i;
> +       unsigned long channels = chan_read | chan_event;
> +
> +       if ((data->chan_read | data->chan_event) != channels) {
> +               for_each_set_bit(i, &channels, HX9023S_CH_NUM)
> +                       hx9023s_ch_en(data, i, test_bit(i, &data->chan_in_use));
> +               for_each_clear_bit(i, &channels, HX9023S_CH_NUM)
> +                       hx9023s_ch_en(data, i, false);
> +       }
> +
> +       data->chan_read = chan_read;
> +       data->chan_event = chan_event;
> +
> +       return 0;
> +}
> +
> +static int hx9023s_get_proximity(struct hx9023s_data *data,
> +                               const struct iio_chan_spec *chan,
> +                               int *val)
> +{
> +       int ret;
> +
> +       ret = hx9023s_sample(data);
> +       if (ret)
> +               return ret;
> +
> +       ret = hx9023s_get_prox_state(data);
> +       if (ret)
> +               return ret;
> +
> +       *val = data->ch_data[chan->channel].diff;
> +       return IIO_VAL_INT;
> +}
> +
> +static int hx9023s_get_samp_freq(struct hx9023s_data *data, int *val, int *val2)
> +{
> +       int ret;
> +       unsigned int odr, index;
> +
> +       ret = regmap_read(data->regmap, HX9023S_PRF_CFG, &index);
> +       if (ret)
> +               return ret;
> +
> +       odr = hx9023s_samp_freq_table[index];
> +       *val = KILO / odr;
> +       *val2 = div_u64((KILO % odr) * MICRO, odr);
> +
> +       return IIO_VAL_INT_PLUS_MICRO;
> +}
> +
> +static int hx9023s_read_raw(struct iio_dev *indio_dev, const struct iio_chan_spec *chan,
> +                               int *val, int *val2, long mask)
> +{
> +       struct hx9023s_data *data = iio_priv(indio_dev);
> +       int ret;
> +
> +       if (chan->type != IIO_PROXIMITY)
> +               return -EINVAL;
> +
> +       switch (mask) {
> +       case IIO_CHAN_INFO_RAW:
> +               ret = iio_device_claim_direct_mode(indio_dev);
> +               if (ret)
> +                       return ret;
> +
> +               ret = hx9023s_get_proximity(data, chan, val);
> +               iio_device_release_direct_mode(indio_dev);
> +               return ret;
> +       case IIO_CHAN_INFO_SAMP_FREQ:
> +               return hx9023s_get_samp_freq(data, val, val2);
> +       default:
> +               return -EINVAL;
> +       }
> +}
> +
> +static int hx9023s_set_samp_freq(struct hx9023s_data *data, int val, int val2)
> +{
> +       struct device *dev = regmap_get_device(data->regmap);
> +       unsigned int i, period_ms;
> +
> +       period_ms = div_u64(NANO, (val * MEGA + val2));
> +
> +       for (i = 0; i < ARRAY_SIZE(hx9023s_samp_freq_table); i++) {
> +               if (period_ms == hx9023s_samp_freq_table[i])
> +                       break;
> +       }
> +       if (i == ARRAY_SIZE(hx9023s_samp_freq_table)) {
> +               dev_err(dev, "Period:%dms NOT found!\n", period_ms);
> +               return -EINVAL;
> +       }
> +
> +       return regmap_write(data->regmap, HX9023S_PRF_CFG, i);
> +}
> +
> +static int hx9023s_write_raw(struct iio_dev *indio_dev, const struct iio_chan_spec *chan,
> +                               int val, int val2, long mask)
> +{
> +       struct hx9023s_data *data = iio_priv(indio_dev);
> +
> +       if (chan->type != IIO_PROXIMITY)
> +               return -EINVAL;
> +
> +       if (mask != IIO_CHAN_INFO_SAMP_FREQ)
> +               return -EINVAL;
> +
> +       return hx9023s_set_samp_freq(data, val, val2);
> +}
> +
> +static irqreturn_t hx9023s_irq_handler(int irq, void *private)
> +{
> +       struct iio_dev *indio_dev = private;
> +       struct hx9023s_data *data = iio_priv(indio_dev);
> +
> +       if (data->trigger_enabled)
> +               iio_trigger_poll(data->trig);
> +
> +       return IRQ_WAKE_THREAD;
> +}
> +
> +static void hx9023s_push_events(struct iio_dev *indio_dev)
> +{
> +       struct hx9023s_data *data = iio_priv(indio_dev);
> +       s64 timestamp = iio_get_time_ns(indio_dev);
> +       unsigned long prox_changed;
> +       unsigned int chan;
> +
> +       hx9023s_sample(data);
> +       hx9023s_get_prox_state(data);
> +
> +       prox_changed = (data->chan_prox_stat ^ data->prox_state_reg) & data->chan_event;
> +       for_each_set_bit(chan, &prox_changed, HX9023S_CH_NUM) {
> +               unsigned int dir;
> +
> +               dir = (data->prox_state_reg & BIT(chan)) ? IIO_EV_DIR_FALLING : IIO_EV_DIR_RISING;
> +
> +               iio_push_event(indio_dev,
> +                       IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, chan, IIO_EV_TYPE_THRESH, dir),
> +                       timestamp);
> +       }
> +       data->chan_prox_stat = data->prox_state_reg;
> +}
> +
> +static irqreturn_t hx9023s_irq_thread_handler(int irq, void *private)
> +{
> +       struct iio_dev *indio_dev = private;
> +       struct hx9023s_data *data = iio_priv(indio_dev);
> +
> +       guard(mutex)(&data->mutex);
> +       hx9023s_push_events(indio_dev);
> +
> +       return IRQ_HANDLED;
> +}
> +
> +static int hx9023s_read_event_val(struct iio_dev *indio_dev,
> +                                const struct iio_chan_spec *chan,
> +                                enum iio_event_type type,
> +                                enum iio_event_direction dir,
> +                                enum iio_event_info info, int *val, int *val2)
> +{
> +       struct hx9023s_data *data = iio_priv(indio_dev);
> +
> +       if (chan->type != IIO_PROXIMITY)
> +               return -EINVAL;
> +
> +       switch (info) {
> +       case IIO_EV_INFO_VALUE:
> +               switch (dir) {
> +               case IIO_EV_DIR_RISING:
> +                       return hx9023s_get_thres_far(data, chan->channel, val);
> +               case IIO_EV_DIR_FALLING:
> +                       return hx9023s_get_thres_near(data, chan->channel, val);
> +               default:
> +                       return -EINVAL;
> +               }
> +       case IIO_EV_INFO_PERIOD:
> +               switch (dir) {
> +               case IIO_EV_DIR_RISING:
> +                       return hx9023s_read_far_debounce(data, val);
> +               case IIO_EV_DIR_FALLING:
> +                       return hx9023s_read_near_debounce(data, val);
> +               default:
> +                       return -EINVAL;
> +               }
> +       default:
> +               return -EINVAL;
> +       }
> +}
> +
> +static int hx9023s_write_event_val(struct iio_dev *indio_dev,
> +                                 const struct iio_chan_spec *chan,
> +                                 enum iio_event_type type,
> +                                 enum iio_event_direction dir,
> +                                 enum iio_event_info info, int val, int val2)
> +{
> +       struct hx9023s_data *data = iio_priv(indio_dev);
> +
> +       if (chan->type != IIO_PROXIMITY)
> +               return -EINVAL;
> +
> +       switch (info) {
> +       case IIO_EV_INFO_VALUE:
> +               switch (dir) {
> +               case IIO_EV_DIR_RISING:
> +                       return hx9023s_set_thres_far(data, chan->channel, val);
> +               case IIO_EV_DIR_FALLING:
> +                       return hx9023s_set_thres_near(data, chan->channel, val);
> +               default:
> +                       return -EINVAL;
> +               }
> +       case IIO_EV_INFO_PERIOD:
> +               switch (dir) {
> +               case IIO_EV_DIR_RISING:
> +                       return hx9023s_write_far_debounce(data, val);
> +               case IIO_EV_DIR_FALLING:
> +                       return hx9023s_write_near_debounce(data, val);
> +               default:
> +                       return -EINVAL;
> +               }
> +       default:
> +               return -EINVAL;
> +       }
> +}
> +
> +static int hx9023s_read_event_config(struct iio_dev *indio_dev,
> +                               const struct iio_chan_spec *chan,
> +                               enum iio_event_type type,
> +                               enum iio_event_direction dir)
> +{
> +       struct hx9023s_data *data = iio_priv(indio_dev);
> +
> +       return test_bit(chan->channel, &data->chan_event);
> +}
> +
> +static int hx9023s_write_event_config(struct iio_dev *indio_dev,
> +                               const struct iio_chan_spec *chan,
> +                               enum iio_event_type type,
> +                               enum iio_event_direction dir,
> +                               int state)
> +{
> +       struct hx9023s_data *data = iio_priv(indio_dev);
> +
> +       if (test_bit(chan->channel, &data->chan_in_use)) {
> +               hx9023s_ch_en(data, chan->channel, !!state);
> +               __assign_bit(chan->channel, &data->chan_event, data->ch_data[chan->channel].enable);
> +       }
> +
> +       return 0;
> +}
> +
> +static const struct iio_info hx9023s_info = {
> +       .read_raw = hx9023s_read_raw,
> +       .write_raw = hx9023s_write_raw,
> +       .read_event_value = hx9023s_read_event_val,
> +       .write_event_value = hx9023s_write_event_val,
> +       .read_event_config = hx9023s_read_event_config,
> +       .write_event_config = hx9023s_write_event_config,
> +};
> +
> +static int hx9023s_set_trigger_state(struct iio_trigger *trig, bool state)
> +{
> +       struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
> +       struct hx9023s_data *data = iio_priv(indio_dev);
> +
> +       guard(mutex)(&data->mutex);
> +       if (state)
> +               hx9023s_interrupt_enable(data);
> +       else if (!data->chan_read)
> +               hx9023s_interrupt_disable(data);
> +       data->trigger_enabled = state;
> +
> +       return 0;
> +}
> +
> +static const struct iio_trigger_ops hx9023s_trigger_ops = {
> +       .set_trigger_state = hx9023s_set_trigger_state,
> +};
> +
> +static irqreturn_t hx9023s_trigger_handler(int irq, void *private)
> +{
> +       struct iio_poll_func *pf = private;
> +       struct iio_dev *indio_dev = pf->indio_dev;
> +       struct hx9023s_data *data = iio_priv(indio_dev);
> +       struct device *dev = regmap_get_device(data->regmap);
> +       int ret;
> +       unsigned int bit, index, i = 0;
> +
> +       guard(mutex)(&data->mutex);
> +       ret = hx9023s_sample(data);
> +       if (ret) {
> +               dev_warn(dev, "sampling failed\n");
> +               goto out;
> +       }
> +
> +       ret = hx9023s_get_prox_state(data);
> +       if (ret) {
> +               dev_warn(dev, "get prox failed\n");
> +               goto out;
> +       }
> +
> +       for_each_set_bit(bit, indio_dev->active_scan_mask, indio_dev->masklength) {
> +               index = indio_dev->channels[bit].channel;
> +               data->buffer.channels[i++] = cpu_to_le16(data->ch_data[index].diff);
> +       }
> +
> +       iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer, pf->timestamp);
> +
> +out:
> +       iio_trigger_notify_done(indio_dev->trig);
> +
> +       return IRQ_HANDLED;
> +}
> +
> +static int hx9023s_buffer_preenable(struct iio_dev *indio_dev)
> +{
> +       struct hx9023s_data *data = iio_priv(indio_dev);
> +       unsigned long channels = 0;
> +       unsigned int bit;
> +
> +       guard(mutex)(&data->mutex);
> +       for_each_set_bit(bit, indio_dev->active_scan_mask, indio_dev->masklength)
> +               __set_bit(indio_dev->channels[bit].channel, &channels);
> +
> +       hx9023s_update_chan_en(data, channels, data->chan_event);
> +
> +       return 0;
> +}
> +
> +static int hx9023s_buffer_postdisable(struct iio_dev *indio_dev)
> +{
> +       struct hx9023s_data *data = iio_priv(indio_dev);
> +
> +       guard(mutex)(&data->mutex);
> +       hx9023s_update_chan_en(data, 0, data->chan_event);
> +
> +       return 0;
> +}
> +
> +static const struct iio_buffer_setup_ops hx9023s_buffer_setup_ops = {
> +       .preenable = hx9023s_buffer_preenable,
> +       .postdisable = hx9023s_buffer_postdisable,
> +};
> +
> +static int hx9023s_id_check(struct iio_dev *indio_dev)
> +{
> +       struct hx9023s_data *data = iio_priv(indio_dev);
> +       int ret;
> +       unsigned int id;
> +
> +       ret = regmap_read(data->regmap, HX9023S_DEVICE_ID, &id);
> +       if (ret)
> +               return ret;
> +
> +       if (id == HX9023S_CHIP_ID) {
> +               indio_dev->name = "hx9023s";

This assignment is quirky here.
Maybe move this into the probe function?
The rest of the function looks fine.

> +               return 0;
> +       }
> +
> +       return -ENODEV;
> +}
> +
> +static int hx9023s_probe(struct i2c_client *client)
> +{
> +       struct device *dev = &client->dev;
> +       struct iio_dev *indio_dev;
> +       struct hx9023s_data *data;
> +       int ret;
> +
> +       indio_dev = devm_iio_device_alloc(dev, sizeof(struct hx9023s_data));
> +       if (!indio_dev)
> +               return -ENOMEM;
> +
> +       data = iio_priv(indio_dev);
> +       mutex_init(&data->mutex);
> +
> +       data->regmap = devm_regmap_init_i2c(client, &hx9023s_regmap_config);
> +       if (IS_ERR(data->regmap))
> +               return dev_err_probe(dev, PTR_ERR(data->regmap), "regmap init failed\n");
> +
> +       ret = hx9023s_property_get(data);
> +       if (ret)
> +               return dev_err_probe(dev, ret, "dts phase failed\n");
> +
> +       ret = devm_regulator_get_enable(dev, "vdd");
> +       if (ret)
> +               return dev_err_probe(dev, ret, "regulator get failed\n");
> +
> +       ret = hx9023s_id_check(indio_dev);
> +       if (ret)
> +               return dev_err_probe(dev, ret, "id check failed\n");
> +
> +       indio_dev->channels = hx9023s_channels;
> +       indio_dev->num_channels = ARRAY_SIZE(hx9023s_channels);
> +       indio_dev->info = &hx9023s_info;
> +       indio_dev->modes = INDIO_DIRECT_MODE;
> +       i2c_set_clientdata(client, indio_dev);
> +
> +       ret = hx9023s_reg_init(data);
> +       if (ret)
> +               return dev_err_probe(dev, ret, "device init failed\n");
> +
> +       ret = hx9023s_ch_cfg(data);
> +       if (ret)
> +               return dev_err_probe(dev, ret, "channel config failed\n");
> +
> +       ret = regcache_sync(data->regmap);
> +       if (ret)
> +               return dev_err_probe(dev, ret, "regcache sync failed\n");
> +
> +       if (client->irq) {
> +               ret = devm_request_threaded_irq(dev, client->irq, hx9023s_irq_handler,
> +                                               hx9023s_irq_thread_handler, IRQF_ONESHOT,
> +                                               "hx9023s_event", indio_dev);
> +               if (ret)
> +                       return dev_err_probe(dev, ret, "irq request failed\n");
> +
> +               data->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name,
> +                                               iio_device_id(indio_dev));
> +               if (!data->trig)
> +                       return dev_err_probe(dev, -ENOMEM,
> +                                       "iio trigger alloc failed\n");
> +
> +               data->trig->ops = &hx9023s_trigger_ops;
> +               iio_trigger_set_drvdata(data->trig, indio_dev);
> +
> +               ret = devm_iio_trigger_register(dev, data->trig);
> +               if (ret)
> +                       return dev_err_probe(dev, ret,
> +                                       "iio trigger register failed\n");
> +       }
> +
> +       ret = devm_iio_triggered_buffer_setup(dev, indio_dev, iio_pollfunc_store_time,
> +                                       hx9023s_trigger_handler, &hx9023s_buffer_setup_ops);
> +       if (ret)
> +               return dev_err_probe(dev, ret,
> +                               "iio triggered buffer setup failed\n");
> +
> +       ret = devm_iio_device_register(dev, indio_dev);

A direct return would also work:
return devm_iio_device_register(dev, indio_dev);

And it would get logged if it happens.

> +       if (ret)
> +               return dev_err_probe(dev, ret, "iio device register failed\n");
> +
> +       return 0;
> +}
> +
> +static int hx9023s_suspend(struct device *dev)
> +{
> +       struct hx9023s_data *data = iio_priv(dev_get_drvdata(dev));
> +
> +       hx9023s_interrupt_disable(data);
> +
> +       return 0;
> +}
> +
> +static int hx9023s_resume(struct device *dev)
> +{
> +       struct hx9023s_data *data = iio_priv(dev_get_drvdata(dev));
> +
> +       if (data->trigger_enabled)
> +               hx9023s_interrupt_enable(data);
> +
> +       return 0;
> +}
> +
> +static DEFINE_SIMPLE_DEV_PM_OPS(hx9023s_pm_ops, hx9023s_suspend, hx9023s_resume);
> +
> +static const struct of_device_id hx9023s_of_match[] = {
> +       { .compatible = "tyhx,hx9023s" },
> +       {}
> +};
> +MODULE_DEVICE_TABLE(of, hx9023s_of_match);
> +
> +static const struct i2c_device_id hx9023s_id[] = {
> +       { "hx9023s" },
> +       {}
> +};
> +MODULE_DEVICE_TABLE(i2c, hx9023s_id);
> +
> +static struct i2c_driver hx9023s_driver = {
> +       .driver = {
> +               .name = "hx9023s",
> +               .of_match_table = hx9023s_of_match,
> +               .pm = &hx9023s_pm_ops,
> +
> +               /*
> +                * The I2C operations in hx9023s_reg_init() and hx9023s_ch_cfg()
> +                * are time-consuming. Prefer async so we don't delay boot
> +                * if we're builtin to the kernel.
> +                */
> +               .probe_type = PROBE_PREFER_ASYNCHRONOUS,
> +       },
> +       .probe = hx9023s_probe,
> +       .id_table = hx9023s_id,
> +};
> +module_i2c_driver(hx9023s_driver);
> +
> +MODULE_AUTHOR("Yasin Lee <yasin.lee.x@xxxxxxxxx>");
> +MODULE_DESCRIPTION("Driver for TYHX HX9023S SAR sensor");
> +MODULE_LICENSE("GPL");
>
> --
> 2.25.1
>
>





[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux