Nayel
Nayel
DIIDevHeads IoT Integration Server
Created by melta101 on 7/31/2024 in #middleware-and-os
How to convert relative cursor movement to absolute position for BLE HID using Zephyr?
#include <zephyr/types.h>
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/gatt.h>

#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));
}
#include <zephyr/types.h>
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/gatt.h>

#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)
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.
15 replies