/* * 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 "battery.h" #include "usb.h" #include "device.h" typedef enum { HIDPP_BATTERY_STATUS_DISCHARGING = 0, HIDPP_BATTERY_STATUS_RECHARGING = 1, HIDPP_BATTERY_STATUS_CHARGE_FINAL = 2, HIDPP_BATTERY_STATUS_CHARGE_COMPLETE = 3, HIDPP_BATTERY_STATUS_RECHARGING_SLOW = 4, HIDPP_BATTERY_STATUS_INVALID_BATTERY = 5, HIDPP_BATTERY_STATUS_THERMAL_ERROR = 6, HIDPP_BATTERY_STATUS_CHARGE_ERROR = 7, } hidppBatteryStatus_t; typedef enum { HIDPP_BATTERY_FLAGS_DISABLED = (1 << 0), HIDPP_BATTERY_FLAGS_MILEAGE = (1 << 1), HIDPP_BATTERY_FLAGS_RECHARGEABLE = (1 << 2), } hidppBatteryFlags_t; typedef struct { uint8_t level, nextLevel, criticalLevel; /* in percent */ hidppBatteryStatus_t status; uint8_t levelsCount; hidppBatteryFlags_t flags; uint16_t life; } hidppBattery_t; const char *hidppBatteryStatusToStr (const hidppBatteryStatus_t s) { switch (s) { case HIDPP_BATTERY_STATUS_DISCHARGING: return "discharging"; break; case HIDPP_BATTERY_STATUS_RECHARGING: return "recharging"; break; case HIDPP_BATTERY_STATUS_CHARGE_FINAL: return "charge in final state"; break; case HIDPP_BATTERY_STATUS_CHARGE_COMPLETE: return "charge complete"; break; case HIDPP_BATTERY_STATUS_RECHARGING_SLOW: return "recharging below optimal speed"; break; case HIDPP_BATTERY_STATUS_INVALID_BATTERY: return "invalid battery"; break; case HIDPP_BATTERY_STATUS_THERMAL_ERROR: return "thermal error"; break; case HIDPP_BATTERY_STATUS_CHARGE_ERROR: return "charge error"; break; default: return "unkown"; break; } } void hidppBatteryPrint (const void * const data) { const hidppBattery_t * const b = data; assert (b != NULL); printf (" Battery:\n" " Status: %s (%u)\n" " Level: %u%%\n" " Next level: %u%%\n" " Critical level: %u%%\n" " Number of levels: %u\n" " Flags:%s%s%s (0x%x)\n" " Life: %u\n", hidppBatteryStatusToStr (b->status), b->status, b->level, b->nextLevel, b->criticalLevel, b->levelsCount, (b->flags & HIDPP_BATTERY_FLAGS_DISABLED) ? " disabled" : "", (b->flags & HIDPP_BATTERY_FLAGS_MILEAGE) ? " mileage" : "", (b->flags & HIDPP_BATTERY_FLAGS_RECHARGEABLE) ? " rechargeable" : "", b->flags, b->life); } void hidppBatteryGet (hidppDevice_t * const d, void ** const data) { hidppBattery_t *b; hidppPacket_t rp; assert (d != NULL); b = calloc (1, sizeof (*b)); hidppUsbRequest (d, HIDPP_FEATURE_BATTERY_STATUS, 0x0, NULL, 0, &rp); b->level = rp.args[0]; b->nextLevel = rp.args[1]; hidppUsbRequest (d, HIDPP_FEATURE_BATTERY_STATUS, 0x1, NULL, 0, &rp); b->levelsCount = rp.args[0]; b->flags = rp.args[1]; b->life = (rp.args[2] << 8) | rp.args[3]; b->criticalLevel = rp.args[4]; *data = b; } bool hidppBatteryAvailable (const hidppDevice_t * const d) { uint8_t ret; return hidppFeatureIdToIdx (d, HIDPP_FEATURE_BATTERY_STATUS, &ret); } hidppModule_t moduleBattery = {hidppBatteryAvailable, hidppBatteryGet, hidppBatteryPrint};