@@ -229,6 +229,140 @@ class GamepadInputReport : public hid::report::base<hid::report::type::INPUT, RE
229
229
}
230
230
};
231
231
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
+
232
366
// / HID Gamepad LED Output Report
233
367
// / This class implements a HID Gamepad with a configurable number of LEDs.
234
368
// / It supports setting the LEDs, as well as serializing the output report and
0 commit comments