@@ -229,6 +229,140 @@ class GamepadInputReport : public hid::report::base<hid::report::type::INPUT, RE
229229 }
230230};
231231
232+ // / HID Xbox Battery Input Report
233+ // / This class implements a copy of the Xbox Battery input report. It is a
234+ // / single byte input which contains information about the type of the battery,
235+ // / its battery level, as well as a few other things.
236+ // /
237+ // / \section hid_rp_ex1 HID-RP Example
238+ // / \snippet hid_rp_example.cpp hid rp example
239+ template <uint8_t REPORT_ID = 4 >
240+ class XboxBatteryInputReport : public hid ::report::base<hid::report::type::INPUT, REPORT_ID> {
241+ public:
242+ protected:
243+ static constexpr uint8_t battery_min{0 };
244+ static constexpr uint8_t battery_max{255 };
245+ static constexpr uint8_t num_data_bytes{1 };
246+
247+ uint8_t battery_status{0 }; // /< The battery status byte
248+
249+ public:
250+ // / The possible errors for the battery
251+ enum class Error {
252+ NONE, // /< No error
253+ BATTERY_LOW, // /< The battery is low
254+ BATTERY_CRITICAL, // /< The battery is critically low
255+ };
256+
257+ // / Reset the battery status
258+ constexpr void reset () { battery_status = 0 ; }
259+
260+ // / Set whether the battery is rechargeable
261+ // / \param rechargeable True if the battery is rechargeable, false otherwise.
262+ constexpr void set_rechargeable (bool rechargeable) {
263+ if (rechargeable) {
264+ battery_status |= 0x04 ;
265+ } else {
266+ battery_status &= ~0x04 ;
267+ }
268+ }
269+
270+ // / Set the battery level
271+ // / \param level The battery level as a percentage, from 0 to 100.
272+ constexpr void set_battery_level (int level) {
273+ if (level > 70 ) {
274+ battery_status |= 0x03 ;
275+ } else if (level > 40 ) {
276+ battery_status |= 0x02 ;
277+ } else if (level > 5 ) {
278+ battery_status |= 0x01 ;
279+ }
280+ }
281+
282+ // / Set whether the battery is connected to a cable
283+ // / \param connected True if the battery is connected to a cable, false otherwise.
284+ constexpr void set_cable_connected (bool connected) {
285+ if (connected) {
286+ battery_status |= 0x10 ;
287+ } else {
288+ battery_status &= ~0x10 ;
289+ }
290+ }
291+
292+ // / Set whether the battery is charging
293+ // / \param charging True if the battery is charging, false otherwise.
294+ constexpr void set_charging (bool charging) {
295+ if (charging) {
296+ battery_status |= 0x20 ;
297+ } else {
298+ battery_status &= ~0x20 ;
299+ }
300+ }
301+
302+ // / Set the error state of the battery
303+ // / \param error The error state of the battery.
304+ constexpr void set_error (Error error) {
305+ switch (error) {
306+ case Error::BATTERY_LOW:
307+ battery_status |= 0x80 ;
308+ break ;
309+ case Error::BATTERY_CRITICAL:
310+ battery_status |= 0xC0 ;
311+ break ;
312+ default :
313+ break ;
314+ }
315+ }
316+
317+ // / Get the input report as a vector of bytes
318+ // / \return The input report as a vector of bytes.
319+ // / \note The report id is not included in the returned vector.
320+ constexpr auto get_report () {
321+ // the first byte is the id, which we don't want...
322+ size_t offset = 1 ;
323+ auto report_data = this ->data () + offset;
324+ auto report_size = num_data_bytes;
325+ return std::vector<uint8_t >(report_data, report_data + report_size);
326+ }
327+
328+ // / Get the report descriptor as a hid::rdf::descriptor
329+ // / \return The report descriptor as a hid::rdf::descriptor.
330+ // / \note This is an incomplete descriptor, you will need to add it to a
331+ // / collection::application descriptor to create a complete report descriptor.
332+ // / \code{.cpp}
333+ // / using namespace hid::page;
334+ // / using namespace hid::rdf;
335+ // / auto gamepad_descriptor = gamepad_input_report.get_descriptor();
336+ // / auto rdf_descriptor = descriptor(
337+ // / usage_page<generic_desktop>(),
338+ // / usage(generic_desktop::GAMEPAD),
339+ // / collection::application(
340+ // / gamepad_descriptor
341+ // / )
342+ // / );
343+ // / auto descriptor = std::vector<uint8_t>(rdf_descriptor.begin(), rdf_descriptor.end());
344+ // / \endcode
345+ static constexpr auto get_descriptor () {
346+ using namespace hid ::page;
347+ using namespace hid ::rdf;
348+
349+ // clang-format off
350+ return descriptor (
351+ conditional_report_id<REPORT_ID>(),
352+
353+ // Battery status
354+ usage (generic_device::BATTERY_STRENGTH),
355+ conditional_report_id<4 >(),
356+ logical_limits<1 ,2 >(battery_min, battery_max),
357+ report_size (8 ),
358+ report_count (1 ),
359+ usage (generic_device::BATTERY_STRENGTH),
360+ input::absolute_variable ()
361+ );
362+ // clang-format on
363+ }
364+ };
365+
232366// / HID Gamepad LED Output Report
233367// / This class implements a HID Gamepad with a configurable number of LEDs.
234368// / It supports setting the LEDs, as well as serializing the output report and
0 commit comments