diff options
author | Peter Wu <peter@lekensteyn.nl> | 2014-12-13 00:02:12 +0100 |
---|---|---|
committer | Peter Wu <peter@lekensteyn.nl> | 2014-12-13 00:02:12 +0100 |
commit | 692e5d592a7c88765b9cbb29612729d2987cfcba (patch) | |
tree | 33ee569d9bdfce654d7c453062dca7f46d6dac0e | |
parent | 9e13e4aac322bf23a9fa1eaf7d7a8d5e605233cb (diff) | |
download | ltunify-692e5d592a7c88765b9cbb29612729d2987cfcba.tar.gz |
lib/hidpp20: support feature retrieval
-rw-r--r-- | lib/hidpp20.c | 121 | ||||
-rw-r--r-- | lib/hidpp20.h | 29 |
2 files changed, 144 insertions, 6 deletions
diff --git a/lib/hidpp20.c b/lib/hidpp20.c index 25e7a43..f8a2374 100644 --- a/lib/hidpp20.c +++ b/lib/hidpp20.c @@ -20,11 +20,128 @@ #include <assert.h> #include <stddef.h> #include <stdint.h> +#include <stdlib.h> #include "debug.h" #include "hidpp.h" #include "hidpp10.h" #include "hidpp20.h" +int hidpp20_get_features_count(int fd, uint8_t device_index, + const FeatureInfo *ifeatureset, + uint8_t *count) +{ + int r; + HidppMessage req = { + .report_id = HIDPP_SHORT, + .device_index = device_index, + .feature_index = ifeatureset->feature_index, + .func = HIDPP20_FUNC(0), + }; + r = hidpp10_request(fd, &req, NULL, NULL); + if (r == 0) { + *count = req.params[0]; + } else { + trace_log("[ix=%02x] IFeatureSet.GetCount failed with %#x\n", + device_index, r); + } + return r; +} + +int hidpp20_get_feature(int fd, uint8_t device_index, + const FeatureInfo *ifeatureset, + uint8_t feature_index, FeatureInfo *fi) +{ + int r; + HidppMessage req = { + .report_id = HIDPP_SHORT, + .device_index = device_index, + .feature_index = ifeatureset->feature_index, + .func = HIDPP20_FUNC(1), /* GetFeatureId */ + .params = { feature_index } + }; + assert(device_index >= 1 && device_index <= MAX_DEVICES); + + r = hidpp10_request(fd, &req, NULL, NULL); + if (r == 0) { + fi->feature_index = feature_index; + fi->feature_id = (req.params[0] << 8) | req.params[1]; + fi->feature_type = req.params[2]; + } else { + trace_log("[ix=%02x] failed to get feature %i, error=%i\n", + device_index, feature_index, r); + } + return r; +} + +int hidpp20_get_feature_by_id(int fd, uint8_t device_index, uint16_t feature_id, + FeatureInfo *fi) +{ + int r; + HidppMessage req = { + .report_id = HIDPP_SHORT, + .device_index = device_index, + .feature_index = 0x00, /* IRoot */ + .func = HIDPP20_FUNC(0), /* GetFeature */ + .params = { feature_id >> 8, (uint8_t) feature_id } + }; + assert(device_index >= 1 && device_index <= MAX_DEVICES); + + r = hidpp10_request(fd, &req, NULL, NULL); + if (r == 0) { + fi->feature_index = req.params[0]; + fi->feature_id = feature_id; + fi->feature_type = req.params[1]; + } else { + trace_log("[ix=%02x] failed to get feature id %#06x, error=%i\n", + device_index, feature_id, r); + } + return r; +} + +FeatureInfo *hidpp20_get_features(int fd, uint8_t device_index, unsigned *count) +{ + int r, i; + FeatureInfo fi; + FeatureInfo *infos; + uint8_t count_nonroot; /* features count not including root feature */ + + assert(device_index >= 1 && device_index <= MAX_DEVICES); + + *count = 0; + r = hidpp20_get_version(fd, device_index); + if (r < 0x0200) { + trace_log("[ix=%02x] HID++ 2.0 required for features, got %#4x\n", + device_index, r); + return NULL; + } + + r = hidpp20_get_feature_by_id(fd, device_index, 0x0001, &fi); + if (r) { + trace_log("[ix=%02x] FeatureSet not found, error=%#x\n", + device_index, r); + return NULL; + } + r = hidpp20_get_features_count(fd, device_index, &fi, &count_nonroot); + if (r) + return NULL; + infos = calloc(*count, sizeof(FeatureInfo)); + + /* infos[0] is the Root feature which has index=0, id=0, type=0 */ + + for (i = 1; i <= count_nonroot; i++) { + r = hidpp20_get_feature(fd, device_index, &fi, i, &infos[i]); + if (r) { + trace_log("[ix=%02x] feature %i not found, error=%#x\n", + device_index, i, r); + free(infos); + return NULL; + } + } + /* maybe qsort(infos); here? */ + *count = count_nonroot + 1; + return infos; +} + uint16_t hidpp20_get_version(int fd, uint8_t device_index) { int r; @@ -33,8 +150,8 @@ uint16_t hidpp20_get_version(int fd, uint8_t device_index) HidppMessage req = { .report_id = HIDPP_SHORT, .device_index = device_index, - .feature_id = 0x00, - .func = 0x14, + .feature_index = 0x00, /* IRoot */ + .func = HIDPP20_FUNC(1), .params = { 0, 0, pingData } }; diff --git a/lib/hidpp20.h b/lib/hidpp20.h index 49181e1..696d729 100644 --- a/lib/hidpp20.h +++ b/lib/hidpp20.h @@ -39,35 +39,56 @@ typedef struct { uint16_t feature_id; uint8_t feature_type; } FeatureInfo; - +/* TODO: HID++ 1.0 vs 2.0 errors? */ /** * Retrieves the number of HID++ 2.0 features. * * @param fd File descriptor of the hidraw device. + * @param device_index Device index (between 1 and 6). + * @param ifeatureset[in] The IFeatureSet feature to call this method on. * @param count[out] The number of HID++ 2.0 features. * @return Zero on success, a HID++ error code otherwise. */ -int hidpp20_get_features_count(int fd, uint8_t *count); +int hidpp20_get_features_count(int fd, uint8_t device_index, + const FeatureInfo *ifeatureset, + uint8_t *count); /** * Retrieves feature information from a feature index. * * @param fd File descriptor of the hidraw device. + * @param device_index Device index (between 1 and 6). + * @param ifeatureset[in] The IFeatureSet feature to call this method on. * @param feature_index A feature index to find information for. * @param fi[out] Feature information on success. * @return Zero on success, a HID++ error code otherwise. */ -int hidpp20_get_feature(int fd, uint8_t feature_index, FeatureInfo *fi); +int hidpp20_get_feature(int fd, uint8_t device_index, + const FeatureInfo *ifeatureset, + uint8_t feature_index, FeatureInfo *fi); /** * Retrieves the feature index for a given feature ID. * * @param fd File descriptor of the hidraw device. + * @param device_index Device index (between 1 and 6). * @param feature_id A 16-bit feature identifier. * @param fi[out] Feature information on success. * @return Zero on success, a HID++ error code otherwise. */ -int hidpp20_get_feature_by_id(int fd, uint16_t feature_id, FeatureInfo *fi); +int hidpp20_get_feature_by_id(int fd, uint8_t device_index, uint16_t feature_id, + FeatureInfo *fi); + +/** + * Retrieves all features of a connected device. + * + * @param fd File descriptor of the hidraw device. + * @param device_index Device index (between 1 and 6). + * @param count[out] The number of discovered features or 0 if an error occured + * (in that case, NULL is returned too). + * @return NULL on error or an array of features supported by the device. + */ +FeatureInfo *hidpp20_get_features(int fd, uint8_t device_index, unsigned *count); /** * Retrieves the HID++ version for the device. |