On Sun, 2019-10-06 at 01:04 +0000, Mazin Rezk wrote: > This patch adds support for the 0x0001 (FeatureSet) feature. This feature > is used to look up the feature ID of a feature index on a device and list > the total count of features on the device. > > I also added the hidpp20_get_features function which iterates through all > feature indexes on the device and stores a map of them in features an > hidpp_device struct. This function runs when an HID++ 2.0 device is probed. > > Signed-off-by: Mazin Rezk <[email protected]> > --- > drivers/hid/hid-logitech-hidpp.c | 92 ++++++++++++++++++++++++++++++++ > 1 file changed, 92 insertions(+) > > diff --git a/drivers/hid/hid-logitech-hidpp.c > b/drivers/hid/hid-logitech-hidpp.c > index a0efa8a43213..64ac94c581aa 100644 > --- a/drivers/hid/hid-logitech-hidpp.c > +++ b/drivers/hid/hid-logitech-hidpp.c > @@ -190,6 +190,9 @@ struct hidpp_device { > > struct hidpp_battery battery; > struct hidpp_scroll_counter vertical_wheel_counter; > + > + u16 *features; > + u8 feature_count; > }; > > /* HID++ 1.0 error codes */ > @@ -911,6 +914,84 @@ static int hidpp_root_get_protocol_version(struct > hidpp_device *hidpp) > return 0; > } > > +/* > -------------------------------------------------------------------------- */ > +/* 0x0001: FeatureSet > */ > +/* > -------------------------------------------------------------------------- */ > + > +#define HIDPP_PAGE_FEATURESET 0x0001 > + > +#define CMD_FEATURESET_GET_COUNT 0x00 > +#define CMD_FEATURESET_GET_FEATURE 0x11 > + > +static int hidpp20_featureset_get_feature(struct hidpp_device *hidpp,
Can you change this to `hidpp20_featureset_get_feature_id` please? So
that we keep in sync with the documentation, and to avoid minor
confusion as IRoot has a `get_feature` function.
> + u8 featureset_index, u8 feature_index, u16 *feature_id)
> +{
> + struct hidpp_report response;
> + int ret;
> +
> + ret = hidpp_send_fap_command_sync(hidpp, featureset_index,
> + CMD_FEATURESET_GET_FEATURE, &feature_index, 1, &response);
> +
> + if (ret)
> + return ret;
> +
> + *feature_id = (response.fap.params[0] << 8) | response.fap.params[1];
> +
> + return ret;
> +}
> +
> +static int hidpp20_featureset_get_count(struct hidpp_device *hidpp,
> + u8 feature_index, u8 *count)
> +{
> + struct hidpp_report response;
> + int ret;
> +
> + ret = hidpp_send_fap_command_sync(hidpp, feature_index,
> + CMD_FEATURESET_GET_COUNT, NULL, 0, &response);
> +
> + if (ret)
> + return ret;
> +
> + *count = response.fap.params[0];
> +
> + return ret;
> +}
Just a nitpick but can we put this before
`hidpp20_featureset_get_feature`? This way we keep the ID order.
> +
> +static int hidpp20_get_features(struct hidpp_device *hidpp)
> +{
> + int ret;
> + u8 featureset_index, featureset_type;
> + u8 i;
> +
> + hidpp->feature_count = 0;
> +
> + ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_FEATURESET,
> + &featureset_index, &featureset_type);
> +
> + if (ret == -ENOENT) {
> + hid_warn(hidpp->hid_dev, "Unable to retrieve feature set.");
> + return 0;
> + }
> +
> + if (ret)
> + return ret;
> +
> + ret = hidpp20_featureset_get_count(hidpp, featureset_index,
> + &hidpp->feature_count);
> +
> + if (ret)
> + return ret;
> +
> + hidpp->features = devm_kzalloc(&hidpp->hid_dev->dev,
> + hidpp->feature_count * sizeof(u16), GFP_KERNEL);
> +
> + for (i = 0; i < hidpp->feature_count && !ret; i++)
> + ret = hidpp20_featureset_get_feature(hidpp, featureset_index,
> + i, &(hidpp->features[i]));
> +
> + return ret;
> +}
> +
> /*
> -------------------------------------------------------------------------- */
> /* 0x0005: GetDeviceNameType
> */
> /*
> -------------------------------------------------------------------------- */
Please use `DeviceNameType` here to keep in sync with the
documentation.
> @@ -3625,6 +3706,17 @@ static int hidpp_probe(struct hid_device *hdev, const
> struct hid_device_id *id)
> hidpp_overwrite_name(hdev);
> }
>
> + /* Cache feature indexes and IDs to check reports faster */
> + if (hidpp->protocol_major >= 2) {
> + if (hidpp20_get_features(hidpp)) {
> + hid_err(hdev, "%s:hidpp20_get_features returned
> error\n",
> + __func__);
> + goto hid_hw_init_fail;
> + }
> + } else {
> + hidpp->feature_count = 0;
> + }
I have not looked at the whole code that much but is the else really
needed here?
> +
> if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)) {
> ret = wtp_get_config(hidpp);
> if (ret)
> --
> 2.23.0
>
--
Filipe Laíns
3DCE 51D6 0930 EBA4 7858 BA41 46F6 33CB B0EB 4BF2
signature.asc
Description: This is a digitally signed message part

