USB HID for Power Devices

Post here first, or if you can't find a relevant section!
Post Reply
swanepoeljan
Posts: 1
Joined: Fri Feb 28, 2020 6:29 pm

USB HID for Power Devices

Post by swanepoeljan »

Recently I discovered the USB Composite library and have a project in mind where I want to use it. I am powering a single board computer from a battery. What I would like to do is use the USB HID for Power Devices to provide the state of the battery (which is sampled by a BluePill) to Windows. If it's then possible to have Windows display the battery state in the taskbar like for a laptop that would be great. If not then I would attempt to write some small program in C# to do this. But first I need to get the connection going. I worked through the examples (for keyboard and mouse) provided and also tried to make sense of the documents provided at USB.org.

My progress so far is slow and I was wondering if anybody has done something similar and has some examples to share?

What I have managed so far is to have Windows detect my BluePill as a "HID UPS Battery" by using the USBHID class and creating a simple ReportDescriptor:

Code: Select all

#define HID_POWER_DEVICE_REPORT_DESCRIPTOR \
    0x05, 0x84,                    /* USAGE_PAGE (Power Device)*/ \
    0x09, 0x04,                    /* USAGE (UPS)*/ \
    0xa1, 0x01,                    /* COLLECTION (Application)*/ \
    0x09, 0x1e,                    /*   USAGE (Flow)*/ \
    0xa1, 0x02,                    /*   COLLECTION (Logical)*/ \
    0x85, 0x01,                    /*     REPORT_ID (1)*/ \
    0x09, 0x1f,                    /*     USAGE (FlowID)*/ \
    0x75, 0x04,                    /*     REPORT_SIZE (4)*/ \
    0x95, 0x01,                    /*     REPORT_COUNT (1)*/ \
    0x15, 0x00,                    /*     LOGICAL_MINIMUM (0)*/ \
    0x25, 0x0f,                    /*     LOGICAL_MAXIMUM (15)*/ \
    0xb1, 0x03,                    /*     FEATURE (Cnst,Var,Abs)*/ \
    0x75, 0x04,                    /*     REPORT_SIZE (4)*/ \
    0x95, 0x01,                    /*     REPORT_COUNT (1)*/ \
    0xb1, 0x03,                    /*     FEATURE (Cnst,Var,Abs)*/ \
    0x09, 0x01,                    /*     USAGE (iName)*/ \
    0x75, 0x08,                    /*     REPORT_SIZE (8)*/ \
    0x95, 0x01,                    /*     REPORT_COUNT (1)*/ \
    0x15, 0x00,                    /*     LOGICAL_MINIMUM (0)*/ \
    0x26, 0xff, 0x00,              /*     LOGICAL_MAXIMUM (255)*/ \
    0xb1, 0x03,                    /*     FEATURE (Cnst,Var,Abs)*/ \
    0x09, 0x40,                    /*     USAGE (ConfigVoltage)*/ \
    0x75, 0x08,                    /*     REPORT_SIZE (8)*/ \
    0x95, 0x01,                    /*     REPORT_COUNT (1)*/ \
    0x67, 0x21, 0xd1, 0xf0, 0x00,  /*     UNIT (SI Lin:Volts)*/ \
    0x55, 0x07,                    /*     UNIT_EXPONENT (7)*/ \
    0x15, 0x00,                    /*     LOGICAL_MINIMUM (0)*/ \
    0x26, 0xfa, 0x00,              /*     LOGICAL_MAXIMUM (250)*/ \
    0xb1, 0x03,                    /*     FEATURE (Cnst,Var,Abs)*/ \
    0x09, 0x42,                    /*     USAGE (ConfigFrequency)*/ \
    0x75, 0x08,                    /*     REPORT_SIZE (8)*/ \
    0x95, 0x01,                    /*     REPORT_COUNT (1)*/ \
    0x66, 0x01, 0xf0,              /*     UNIT (SI Lin:Hertz)*/ \
    0x55, 0x00,                    /*     UNIT_EXPONENT (0)*/ \
    0x15, 0x00,                    /*     LOGICAL_MINIMUM (0)*/ \
    0x25, 0x3c,                    /*     LOGICAL_MAXIMUM (60)*/ \
    0xb1, 0x03,                    /*     FEATURE (Cnst,Var,Abs)*/ \
    0x65, 0x00,                    /*     UNIT (None)*/ \
    0xc0,                          /*   END_COLLECTION*/ \
    0xc0                           /* END_COLLECTION*/  
Then I created a report structure and a HIDPower class that derives from HIDReporter (similar to the implementation of the HIDMouse). Next I tried to send a report the same way that the mouse examples send reports, by filling the report and using

Code: Select all

sendReport();
I have a small application which can monitor batteries connected to my computer which kind of shows that there is now an extra battery but all the fields seems to be undefined. So my concern is that I can't really use sendReport() when sending Feature items, could this be? Is there maybe a different mechanism to send feature item data?

Not sure if it's relevant but in the HID v1.11 documentation they also mention "Only Input reports are sent via the Interrupt In pipe. Feature and Output reports must be initiated by the host via the Control pipe or an optional Interrupt Out pipe."

If anybody has some ideas or suggestions that would be great?
User avatar
fpiSTM
Posts: 1745
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: USB HID for Power Devices

Post by fpiSTM »

I think @arpruss is the one who could answer on this as he maintains the USBComposite library, if I'm not wrong.
arpruss
Posts: 83
Joined: Sat Dec 21, 2019 10:06 pm

Re: USB HID for Power Devices

Post by arpruss »

What you want to do is call setFeature(). Then the host will hopefully request the feature data when needed. See my many function GameCube controller USB adapter:
https://github.com/arpruss/gamecube-usb ... roller.ino
zolotoi_s88
Posts: 1
Joined: Tue Feb 16, 2021 6:15 am

Re: USB HID for Power Devices

Post by zolotoi_s88 »

Hello
I solve a similar problem. I still can't decide. Could you share your best practices on this issue, or in any way help me in solving this issue. now my computer is giving a driver error or an invalid device descriptor message.
Post Reply

Return to “General discussion”