Re: [PATCH v7 1/2] hwmon: (asus_wmi_ec_sensors) Support B550 Asus WMI.
From: <hidden>
Date: 2021-10-15 16:39:04
Also in:
linux-hwmon, lkml, platform-driver-x86
On 2021-10-15T08:58+0300, Denis Pauk wrote:
+/*
+ * The next four functions converts to/from BRxx string argument format
+ * The format of the string is as follows:
+ * The string consists of two-byte UTF-16 characters
+ * The value of the very first byte int the string is equal to the total length
+ * of the next string in bytes, thus excluding the first two-byte character
+ * The rest of the string encodes pairs of (bank, index) pairs, where both
+ * values are byte-long (0x00 to 0xFF)
+ * Numbers are encoded as UTF-16 hex values
+ */
+static void asus_wmi_ec_decode_reply_buffer(const u8 *inp, u8 *out, u32 length)
+{
+ char buffer[ASUSWMI_MAX_BUF_LEN * 2];
+ const char *pos = buffer;
+ const u8 *data = inp + 2;
+ unsigned int i;
+ u32 len;
+
+ len = min3((u32)ASUSWMI_MAX_BUF_LEN, (length - 2) / 4, (u32)inp[0] / 4);This will still access out of bounds memory when length == 0.
+ + utf16s_to_utf8s((wchar_t *)data, len * 2, UTF16_LITTLE_ENDIAN, buffer, len * 2); + + for (i = 0; i < len; i++, pos += 2) + out[i] = (hex_to_bin(pos[0]) << 4) + hex_to_bin(pos[1]); +}
+static int asus_wmi_ec_find_sensor_index(const struct asus_wmi_ec_info *ec,
+ enum hwmon_sensor_types type, int channel)
+{
+ int i;
+
+ for (i = 0; i < ec->nr_sensors; i++) {
+ if (known_ec_sensors[ec->sensors[i].info_index].type == type) {
+ if (channel == 0)
+ return i;
+
+ channel--;
+ }
+ }
+ return -EINVAL;
+}
+
+static int asus_wmi_ec_get_cached_value_or_update(int sensor_index,
+ struct asus_wmi_sensors *state,
+ u32 *value)In both drivers there is function like this where the caller is responsible for halding the mutex. Maybe the mutex could be handled by the function directly.
+{
+ int ret;
+
+ if (time_after(jiffies, state->ec.last_updated + HZ)) {
+ ret = asus_wmi_ec_block_read(ASUSWMI_METHODID_BREC,
+ state->ec.read_arg,
+ state->ec.read_buffer);
+ if (ret)
+ return ret;
+
+ asus_wmi_ec_update_ec_sensors(&state->ec);
+ state->ec.last_updated = jiffies;
+ }
+
+ *value = state->ec.sensors[sensor_index].cached_value;
+ return 0;
+}+static umode_t asus_wmi_ec_hwmon_is_visible(const void *drvdata,
+ enum hwmon_sensor_types type, u32 attr,
+ int channel)
+{
+ int index;
+ const struct asus_wmi_sensors *sensor_data = drvdata;
+
+ index = asus_wmi_ec_find_sensor_index(&sensor_data->ec, type, channel);
+
+ return index == 0xff ? 0 : 0444;Should this not check for index < 0?
+}
+static int asus_wmi_probe(struct wmi_device *wdev, const void *context)
+{
+ struct asus_wmi_sensors *sensor_data;
+ struct asus_wmi_data *board_sensors;
+ const enum known_ec_sensor *bsi;
+ const struct dmi_system_id *dmi_id;
+ struct device *dev = &wdev->dev;
+
+ dmi_id = dmi_first_match(asus_wmi_ec_dmi_table);
+ if (!dmi_id)
+ return -ENODEV;
+
+ board_sensors = dmi_id->driver_data;
+ if (!board_sensors)
+ return -ENODEV;
+
+ bsi = board_sensors->known_board_sensors;
+
+ sensor_data = devm_kzalloc(dev, sizeof(struct asus_wmi_sensors),
+ GFP_KERNEL);sizeof(*sensor_data);
+ if (!sensor_data) + return -ENOMEM; + + mutex_init(&sensor_data->lock); + + dev_set_drvdata(dev, sensor_data); + + /* ec init */ + return asus_wmi_ec_configure_sensor_setup(dev, + sensor_data, bsi); +}