/* * Copyright (c) 2012 * Lars-Dominik Braun * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #include #include #include #include #include "reprogrammable.h" #include "usb.h" #include "device.h" typedef enum { HIDPP_TASK_VOLUP = 1, HIDPP_TASK_VOLDOWN = 2, HIDPP_TASK_MUTE = 3, HIDPP_TASK_PLAYPAUSE = 4, HIDPP_TASK_NEXTFF = 5, HIDPP_TASK_PREVRW = 6, HIDPP_TASK_STOP = 7, HIDPP_TASK_APPSWITCH = 8, } hidppReprogrammableKeyTask_t; typedef enum { /* reprogrammmable */ HIDPP_RK_REPGROGRAMMABLE = (1 << 4), /* affected by fn key */ HIDPP_RK_FNTOGGLE = (1 << 3), /* hotkey */ HIDPP_RK_HOTKEY = (1 << 2), /* fn key */ HIDPP_RK_FN = (1 << 1), /* mouse button */ HIDPP_RK_MOUSE = (1 << 0), } hidppReprogrammableKeyFlags_t; typedef struct { uint16_t id; hidppReprogrammableKeyTask_t task; hidppReprogrammableKeyFlags_t flags; } hidppReprogrammableKey_t; typedef struct { hidppReprogrammableKey_t *key; size_t count; } hidppReprogrammableData_t; const char *hidppReprogrammableTaskToStr (const hidppReprogrammableKeyTask_t t) { switch (t) { case HIDPP_TASK_VOLUP: return "volume up"; break; case HIDPP_TASK_VOLDOWN: return "volume down"; break; case HIDPP_TASK_MUTE: return "mute"; break; case HIDPP_TASK_PLAYPAUSE: return "play/pause"; break; case HIDPP_TASK_NEXTFF: return "next/fast forward"; break; case HIDPP_TASK_PREVRW: return "previous/rewind"; break; case HIDPP_TASK_STOP: return "stop"; break; case HIDPP_TASK_APPSWITCH: return "application switcher"; break; default: return "unknown"; break; } } void hidppReprogrammablePrint (const void * const data) { const hidppReprogrammableData_t * const d = data; assert (d != NULL); for (size_t i = 0; i < d->count; i++) { const hidppReprogrammableKey_t * const k = &d->key[i]; printf (" Key: (0x%x)\n" " Task: %s (%u)\n" " Flags:%s%s%s%s%s (0x%x)\n", k->id, hidppReprogrammableTaskToStr (k->task), k->task, (k->flags & HIDPP_RK_REPGROGRAMMABLE) ? " reprogrammable" : "", (k->flags & HIDPP_RK_FNTOGGLE) ? " fntoggle" : "", (k->flags & HIDPP_RK_HOTKEY) ? " hotkey" : "", (k->flags & HIDPP_RK_FN) ? " fn" : "", (k->flags & HIDPP_RK_MOUSE) ? " mouse" : "", k->flags); } } void hidppReprogrammableGet (hidppDevice_t *d, void ** const retData) { hidppReprogrammableData_t *data; hidppPacket_t rp; assert (d != NULL); assert (retData != NULL); data = calloc (1, sizeof (*data)); hidppUsbRequest (d, HIDPP_FEATURE_PROGRAMMABLE_KEYS, 0x0, NULL, 0, &rp); data->count = rp.args[0]; data->key = calloc (data->count, sizeof (*data->key)); for (uint8_t i = 0; i < data->count; i++) { hidppReprogrammableKey_t * const k = &data->key[i]; hidppUsbRequest (d, HIDPP_FEATURE_PROGRAMMABLE_KEYS, 0x1, &i, 1, &rp); k->id = (rp.args[0] << 8) | rp.args[1]; k->task = (rp.args[2] << 8) | rp.args[3]; k->flags = rp.args[4]; } *retData = data; } bool hidppReprogrammableAvailable (const hidppDevice_t * const d) { uint8_t ret; return hidppFeatureIdToIdx (d, HIDPP_FEATURE_PROGRAMMABLE_KEYS, &ret); } hidppModule_t moduleReprogrammable = {hidppReprogrammableAvailable, hidppReprogrammableGet, hidppReprogrammablePrint};