Hey @MCU, MPU & Firmware @Helper Guys, i have a slight logic problem,
So i built a BLE HID device using zephyr which tags input from a console and send BLE HID packets to the connected device
All well and good…for now
The problem arises here, where the HID report is based of the relative position of the cursor, but my client requires a way to give it through Absolute position of a device(Main eg: phone)
Could anyone help how we can give absolute movement from relative movement(Even external(PC based) code implementation is Okay)
My HID report is
0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */
0x09, 0x02, /* Usage (Mouse) */
0xA1, 0x01, /* Collection (Application) */
0x85, 0x01, /* Report Id (1) */
0x09, 0x01, /* Usage (Pointer) */
0xA1, 0x00, /* Collection (Physical) */
0x05, 0x09, /* Usage Page (Button) */
0x19, 0x01, /* Usage Minimum (0x01) */
0x29, 0x03, /* Usage Maximum (0x03) */
0x15, 0x00, /* Logical Minimum (0) */
0x25, 0x01, /* Logical Maximum (1) */
0x95, 0x03, /* Report Count (3) */
0x75, 0x01, /* Report Size (1) */
0x81, 0x02, /* Input (Data,Var,Abs,No Wrap,Linear,…) */
0x95, 0x01, /* Report Count (1) */
0x75, 0x05, /* Report Size (5) */
0x81, 0x03, /* Input (Const,Var,Abs,No Wrap,Linear,…) */
0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */
0x09, 0x30, /* Usage (X) */
0x09, 0x31, /* Usage (Y) */
0x15, 0x81, /* Logical Minimum (129) */
0x25, 0x7F, /* Logical Maximum (127) */
0x75, 0x08, /* Report Size (8) */
0x95, 0x02, /* Report Count (2) */
0x81, 0x06, /* Input (Data,Var,Rel,No Wrap,Linear,…) */ {I have tried 0x81, 0x02 for Abs but it didnt register in my phone as a HID device for some reason}
0xC0, /* End Collection */
0xC0, /* End Collection */
which software are you using
The RTOS i am using is Zephyr
Any help and clarifications needed are welcome!
To convert relative movement to absolute positioning for your BLE HID device, you’ll need to make a few changes to both your HID report descriptor and your firmware implementation. Here’s how you can approach this:
Modify the HID report descriptor:
Change the X and Y input fields to absolute positioning by modifying these lines:
This changes the X and Y fields to 16-bit absolute values with a range of 0-32767.
Update your firmware implementation:
You’ll need to maintain the current cursor position in your device’s memory. When you receive input from the console, instead of sending relative movement, you’ll send the new absolute position.
Here’s a basic example of how you might implement this in your firmware:
“`
#include
#include
#include
#include
#include
#include
#include
#define SCREEN_WIDTH 32768
#define SCREEN_HEIGHT 32768
struct hid_report {
uint8_t buttons;
uint16_t x;
uint16_t y;
} __packed;
static struct hid_report report = {0};
void update_cursor_position(int16_t dx, int16_t dy) {
// Update absolute position based on relative movement
report.x = MIN(MAX(report.x + dx, 0), SCREEN_WIDTH – 1);
report.y = MIN(MAX(report.y + dy, 0), SCREEN_HEIGHT – 1);
// Send the updated report
bt_gatt_notify(NULL, &hid_svc.attrs[2], &report, sizeof(report));
}
void set_cursor_position(uint16_t x, uint16_t y) {
report.x = MIN(x, SCREEN_WIDTH – 1);
report.y = MIN(y, SCREEN_HEIGHT – 1);
// Send the updated report
bt_gatt_notify(NULL, &hid_svc.attrs[2], &report, sizeof(report));
}
“`
In this example, update_cursor_position takes relative movement as input and updates the absolute position, while set_cursor_position allows you to set the absolute position directly.
Handling phone compatibility:
If your phone isn’t recognizing the device with absolute positioning, you might need to add a physical (x, y) min/max to your descriptor:
“`
0x35, 0x00, // Physical Minimum (0)
0x46, 0xFF, 0x7F, // Physical Maximum (32767)
“`
Add these lines just before the Logical Minimum and Maximum in your descriptor.
Calibration:
You’ll need to implement a calibration process to map the phone’s screen dimensions to your 0-32767 range. This could involve having the user touch specific points on the screen and adjusting your coordinates accordingly.
I’m really not an expert but it should help
Interesting!
Lemme implement this n let yk furthur
Thanks for your time mate!
I have a few doubts
if we are setting this HID report to abs, why should we implement the below functions, as they seems to be converting relative to abs
BTW,
I have tried HID format change
but after getting connected, it doesnt seem to move the cursor
Absolute vs. Relative Positioning:
If you’ve set up your HID report for absolute positioning, you’re correct that you shouldn’t need to convert from relative to absolute movements. The functions I provided earlier were indeed more suited for a hybrid approach, which isn’t necessary if you’re fully committed to absolute positioning.
for the cursor : you have to ensure your HID report is being sent correctly with the new format.
and then Verify that the absolute values you’re sending are within the range you specified in the descriptor (0 to 32767 in the example).
note that Some devices might expect different ranges or additional information in the HID report for absolute positioning.
“`struct hid_report {
uint8_t buttons;
uint16_t x;
uint16_t y;
} __packed;
static struct hid_report report = {0};
void set_cursor_position(uint16_t x, uint16_t y) {
report.x = x;
report.y = y;
// Send the updated report
bt_gatt_notify(NULL, &hid_svc.attrs[2], &report, sizeof(report));
}“`
Hmm,
Still the same
Connects but doesnt send the mouse commands
Hmmm… weird
CONTRIBUTE TO THIS THREAD