summaryrefslogtreecommitdiff
path: root/hw/usb/hid-logitech-hidpp20.c
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2014-03-24 00:00:05 +0100
committerPeter Wu <peter@lekensteyn.nl>2014-03-24 00:00:05 +0100
commita4a17543cee0f422b6348020d170d887f05e97fc (patch)
treeb5058493aa0a8352a2b7a8175a9bfd1ba1eadbb5 /hw/usb/hid-logitech-hidpp20.c
parent5ae3eabba2c39b02775be614447dd8baf6ae2d5d (diff)
downloadqemu-a4a17543cee0f422b6348020d170d887f05e97fc.tar.gz
unifying: implement IRoot completely
Do not treat IRoot special in hidpp_process_device_hidpp20, but implement it as a generic feature using hidpp20_feature_call. This makes it easier to re-use the error reporting stuff. Signed-off-by: Peter Wu <peter@lekensteyn.nl>
Diffstat (limited to 'hw/usb/hid-logitech-hidpp20.c')
-rw-r--r--hw/usb/hid-logitech-hidpp20.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/hw/usb/hid-logitech-hidpp20.c b/hw/usb/hid-logitech-hidpp20.c
index be1e02df53..95393050a5 100644
--- a/hw/usb/hid-logitech-hidpp20.c
+++ b/hw/usb/hid-logitech-hidpp20.c
@@ -48,6 +48,34 @@ struct HidppFeature {
#define HIDPP20_FEATURE(name) \
int name(LHidDevice *hd, Hidpp20Msg *msg, uint8_t fn, uint8_t *params)
+static HIDPP20_FEATURE(feat_iroot)
+{
+ uint16_t feature_id;
+ unsigned i;
+ const HidppFeature *feat;
+
+ switch (fn) {
+ case 0: /* featureIndex, featureType = GetFeature(featureID) */
+ feature_id = (params[0] << 8) | params[1];
+ params[0] = params[1] = 0;
+ for (i = 0; i < hd->info.features_count; i++) {
+ feat = &hd->info.features[i];
+ if (feat->id == feature_id) {
+ params[0] = i + 1;
+ params[1] = feat->type;
+ }
+ }
+ return 2;
+ case 1: /* ping = GetFeature(pingData) or version = GetProtocolVersion() */
+ params[0] = hd->info.protocol_version >> 8;
+ params[1] = (uint8_t) hd->info.protocol_version;
+ // params[2] is not changed, that's the pingData
+ return 3;
+ default:
+ return -HIDPP20_ERR_CODE_INVALID_FUNCTION_ID;
+ }
+}
+
static HIDPP20_FEATURE(feat_featureset)
{
const HidppFeature *feat;
@@ -96,8 +124,12 @@ int hidpp20_feature_call(LHidDevice *hd, Hidpp20Msg *func)
assert(hd->info.features != NULL);
- feat = &hd->info.features[func->feat_index - 1];
- r = feat->callback(hd, func, fn, func->params);
+ if (func->feat_index == 0) { /* IRoot (dual HID++ 1.0 and HID++ 2.0) */
+ r = feat_iroot(hd, func, fn, func->params);
+ } else { /* other features */
+ feat = &hd->info.features[func->feat_index - 1];
+ r = feat->callback(hd, func, fn, func->params);
+ }
if (r > 0) {
// r are the parameters that must be kept, the others are cleared.
assert(r <= sizeof(func->params));