├── BleAbsMouse.cpp ├── BleAbsMouse.h ├── BleConnectionStatus.cpp ├── BleConnectionStatus.h ├── README.md ├── examples ├── Click │ └── Click.ino └── PressAndRelease │ └── PressAndRelease.ino ├── keywords.txt └── library.properties /BleAbsMouse.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "BLE2902.h" 5 | #include "BLEHIDDevice.h" 6 | #include "HIDTypes.h" 7 | #include "HIDKeyboardTypes.h" 8 | #include 9 | #include "sdkconfig.h" 10 | 11 | #include "BleConnectionStatus.h" 12 | #include "BleAbsMouse.h" 13 | 14 | #if defined(CONFIG_ARDUHAL_ESP_LOG) 15 | #include "esp32-hal-log.h" 16 | #define LOG_TAG "" 17 | #else 18 | #include "esp_log.h" 19 | static const char* LOG_TAG = "BLEDevice"; 20 | #endif 21 | 22 | #define REPORTID_TOUCH 0x01 23 | 24 | #define LSB(v) ((v >> 8) & 0xff) 25 | #define MSB(v) (v & 0xff) 26 | 27 | static const uint8_t _hidReportDescriptor[] = { 28 | 0x05, 0x0d, /* USAGE_PAGE (Digitizer) */ 29 | 0x09, 0x04, /* USAGE (Touch Screen) */ 30 | 0xa1, 0x01, /* COLLECTION (Application) */ 31 | 0x85, REPORTID_TOUCH, /* REPORT_ID */ 32 | 33 | /* declare a finger collection */ 34 | 0x09, 0x20, /* Usage (Stylus) */ 35 | 0xA1, 0x00, /* Collection (Physical) */ 36 | 37 | /* Declare a finger touch (finger up/down) */ 38 | 0x09, 0x42, /* Usage (Tip Switch) */ 39 | 0x09, 0x32, /* USAGE (In Range) */ 40 | 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 41 | 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ 42 | 0x75, 0x01, /* REPORT_SIZE (1) */ 43 | 0x95, 0x02, /* REPORT_COUNT (2) */ 44 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ 45 | 46 | /* Declare the remaining 6 bits of the first data byte as constant -> the driver will ignore them */ 47 | 0x75, 0x01, /* REPORT_SIZE (1) */ 48 | 0x95, 0x06, /* REPORT_COUNT (6) */ 49 | 0x81, 0x01, /* INPUT (Cnst,Ary,Abs) */ 50 | 51 | /* Define absolute X and Y coordinates of 16 bit each (percent values multiplied with 100) */ 52 | /* http://www.usb.org/developers/hidpage/Hut1_12v2.pdf */ 53 | /* Chapter 16.2 says: "In the Stylus collection a Pointer physical collection will contain the axes reported by the stylus." */ 54 | 0x05, 0x01, /* Usage Page (Generic Desktop) */ 55 | 0x09, 0x01, /* Usage (Pointer) */ 56 | 0xA1, 0x00, /* Collection (Physical) */ 57 | 0x09, 0x30, /* Usage (X) */ 58 | 0x09, 0x31, /* Usage (Y) */ 59 | 0x16, 0x00, 0x00, /* Logical Minimum (0) */ 60 | 0x26, 0x10, 0x27, /* Logical Maximum (10000) */ 61 | 0x36, 0x00, 0x00, /* Physical Minimum (0) */ 62 | 0x46, 0x10, 0x27, /* Physical Maximum (10000) */ 63 | 0x66, 0x00, 0x00, /* UNIT (None) */ 64 | 0x75, 0x10, /* Report Size (16), */ 65 | 0x95, 0x02, /* Report Count (2), */ 66 | 0x81, 0x02, /* Input (Data,Var,Abs) */ 67 | 0xc0, /* END_COLLECTION */ 68 | 0xc0, /* END_COLLECTION */ 69 | 0xc0 /* END_COLLECTION */ 70 | 71 | // With this declaration a data packet must be sent as: 72 | // byte 1 -> "touch" state (bit 0 = pen up/down, bit 1 = In Range) 73 | // byte 2,3 -> absolute X coordinate (0...10000) 74 | // byte 4,5 -> absolute Y coordinate (0...10000) 75 | }; 76 | 77 | BleAbsMouse::BleAbsMouse(std::string deviceName, std::string deviceManufacturer, uint8_t batteryLevel) : 78 | hid(0) 79 | { 80 | this->deviceName = deviceName; 81 | this->deviceManufacturer = deviceManufacturer; 82 | this->batteryLevel = batteryLevel; 83 | this->connectionStatus = new BleConnectionStatus(); 84 | this->isPressed = false; 85 | } 86 | 87 | void BleAbsMouse::begin(void) 88 | { 89 | xTaskCreate(this->taskServer, "server", 20000, (void *)this, 5, NULL); 90 | } 91 | 92 | void BleAbsMouse::end(void) 93 | { 94 | } 95 | 96 | void BleAbsMouse::click(int16_t x, int16_t y) 97 | { 98 | this->move(x, y); 99 | this->release(); 100 | } 101 | 102 | void BleAbsMouse::move(int16_t x, int16_t y) 103 | { 104 | this->send(3, x, y); 105 | this->isPressed = true; 106 | } 107 | 108 | void BleAbsMouse::release() 109 | { 110 | this->send(0, 0, 0); 111 | this->isPressed = false; 112 | } 113 | 114 | void BleAbsMouse::send(int state, int16_t x, int16_t y) 115 | { 116 | if (this->isConnected()) 117 | { 118 | uint8_t m[5]; 119 | m[0] = state; 120 | m[1] = MSB(x); 121 | m[2] = LSB(x); 122 | m[3] = MSB(y); 123 | m[4] = LSB(y); 124 | this->inputAbsMouse->setValue(m, 5); 125 | this->inputAbsMouse->notify(); 126 | } 127 | } 128 | 129 | bool BleAbsMouse::isConnected(void) { 130 | return this->connectionStatus->connected; 131 | } 132 | 133 | void BleAbsMouse::setBatteryLevel(uint8_t level) { 134 | this->batteryLevel = level; 135 | if (hid != 0) 136 | this->hid->setBatteryLevel(this->batteryLevel); 137 | } 138 | 139 | void BleAbsMouse::taskServer(void* pvParameter) { 140 | BleAbsMouse* bleMouseInstance = (BleAbsMouse *) pvParameter; //static_cast(pvParameter); 141 | BLEDevice::init(bleMouseInstance->deviceName); 142 | BLEServer *pServer = BLEDevice::createServer(); 143 | pServer->setCallbacks(bleMouseInstance->connectionStatus); 144 | 145 | bleMouseInstance->hid = new BLEHIDDevice(pServer); 146 | bleMouseInstance->inputAbsMouse = bleMouseInstance->hid->inputReport(REPORTID_TOUCH); // <-- input REPORTID from report map 147 | bleMouseInstance->connectionStatus->inputAbsMouse = bleMouseInstance->inputAbsMouse; 148 | 149 | bleMouseInstance->hid->manufacturer()->setValue(bleMouseInstance->deviceManufacturer); 150 | 151 | bleMouseInstance->hid->pnp(0x02, 0xe502, 0xa111, 0x0210); 152 | bleMouseInstance->hid->hidInfo(0x00,0x02); 153 | 154 | BLESecurity *pSecurity = new BLESecurity(); 155 | 156 | pSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND); 157 | 158 | bleMouseInstance->hid->reportMap((uint8_t*)_hidReportDescriptor, sizeof(_hidReportDescriptor)); 159 | bleMouseInstance->hid->startServices(); 160 | 161 | bleMouseInstance->onStarted(pServer); 162 | 163 | BLEAdvertising *pAdvertising = pServer->getAdvertising(); 164 | pAdvertising->setAppearance(HID_MOUSE); 165 | pAdvertising->addServiceUUID(bleMouseInstance->hid->hidService()->getUUID()); 166 | pAdvertising->start(); 167 | bleMouseInstance->hid->setBatteryLevel(bleMouseInstance->batteryLevel); 168 | 169 | ESP_LOGD(LOG_TAG, "Advertising started!"); 170 | vTaskDelay(portMAX_DELAY); //delay(portMAX_DELAY); 171 | } 172 | -------------------------------------------------------------------------------- /BleAbsMouse.h: -------------------------------------------------------------------------------- 1 | #ifndef ESP32_BLE_ABS_MOUSE_H 2 | #define ESP32_BLE_ABS_MOUSE_H 3 | #include "sdkconfig.h" 4 | #if defined(CONFIG_BT_ENABLED) 5 | 6 | #include "BleConnectionStatus.h" 7 | #include "BLEHIDDevice.h" 8 | #include "BLECharacteristic.h" 9 | 10 | class BleAbsMouse { 11 | private: 12 | BleConnectionStatus* connectionStatus; 13 | BLEHIDDevice* hid; 14 | BLECharacteristic* inputAbsMouse; 15 | void rawAction(uint8_t msg[], char msgSize); 16 | static void taskServer(void* pvParameter); 17 | public: 18 | BleAbsMouse(std::string deviceName = "ESP32 Bluetooth Abs Mouse", std::string deviceManufacturer = "Espressif", uint8_t batteryLevel = 100); 19 | void begin(void); 20 | void end(void); 21 | void click(int16_t x, int16_t y); 22 | void move(int16_t x, int16_t y); 23 | void release(void); 24 | void send(int state, int16_t x, int16_t y); 25 | bool isConnected(void); 26 | void setBatteryLevel(uint8_t level); 27 | uint8_t batteryLevel; 28 | std::string deviceManufacturer; 29 | std::string deviceName; 30 | bool isPressed; 31 | protected: 32 | virtual void onStarted(BLEServer *pServer) { }; 33 | }; 34 | 35 | #endif // CONFIG_BT_ENABLED 36 | #endif // ESP32_BLE_ABS_MOUSE_H 37 | -------------------------------------------------------------------------------- /BleConnectionStatus.cpp: -------------------------------------------------------------------------------- 1 | #include "BleConnectionStatus.h" 2 | 3 | BleConnectionStatus::BleConnectionStatus(void) { 4 | } 5 | 6 | void BleConnectionStatus::onConnect(BLEServer* pServer) 7 | { 8 | this->connected = true; 9 | BLE2902* desc = (BLE2902*)this->inputAbsMouse->getDescriptorByUUID(BLEUUID((uint16_t)0x2902)); 10 | desc->setNotifications(true); 11 | } 12 | 13 | void BleConnectionStatus::onDisconnect(BLEServer* pServer) 14 | { 15 | this->connected = false; 16 | BLE2902* desc = (BLE2902*)this->inputAbsMouse->getDescriptorByUUID(BLEUUID((uint16_t)0x2902)); 17 | desc->setNotifications(false); 18 | } 19 | -------------------------------------------------------------------------------- /BleConnectionStatus.h: -------------------------------------------------------------------------------- 1 | #ifndef ESP32_BLE_CONNECTION_STATUS_H 2 | #define ESP32_BLE_CONNECTION_STATUS_H 3 | #include "sdkconfig.h" 4 | #if defined(CONFIG_BT_ENABLED) 5 | 6 | #include 7 | #include "BLE2902.h" 8 | #include "BLECharacteristic.h" 9 | 10 | class BleConnectionStatus : public BLEServerCallbacks 11 | { 12 | public: 13 | BleConnectionStatus(void); 14 | bool connected = false; 15 | void onConnect(BLEServer* pServer); 16 | void onDisconnect(BLEServer* pServer); 17 | BLECharacteristic* inputAbsMouse; 18 | }; 19 | 20 | #endif // CONFIG_BT_ENABLED 21 | #endif // ESP32_BLE_CONNECTION_STATUS_H 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP32 BLE Abs Mouse library 2 | 3 | This library allows you to make the ESP32 act as a Bluetooth Absolute Mouse and control what it does. E.g. click, move, release and etc. 4 | 5 | You might also be interested in: 6 | - [ESP32-BLE-Mouse](https://github.com/T-vK/ESP32-BLE-Mouse) 7 | - [ESP32-BLE-Keyboard](https://github.com/T-vK/ESP32-BLE-Keyboard) 8 | - [ESP32-BLE-Gamepad](https://github.com/lemmingDev/ESP32-BLE-Gamepad) 9 | 10 | ## Features 11 | 12 | - [x] Click 13 | - [x] Move 14 | - [x] Release 15 | - [x] Report optional battery level to host (basically works, but it doesn't show up in Android's status bar) 16 | - [x] Customize Bluetooth device name/manufacturer 17 | - [x] Compatible with Android 18 | - [ ] Compatible with Windows 19 | - [ ] Compatible with Linux 20 | - [ ] Compatible with MacOS X 21 | - [ ] Compatible with iOS 22 | 23 | ## Installation 24 | - (Make sure you can use the ESP32 with the Arduino IDE. [Instructions can be found here.](https://github.com/espressif/arduino-esp32#installation-instructions)) 25 | - [Download the latest release of this library from the release page.](https://github.com/sobrinho/ESP32-BLE-Abs-Mouse/releases) 26 | - In the Arduino IDE go to "Sketch" -> "Include Library" -> "Add .ZIP Library..." and select the file you just downloaded. 27 | - You can now go to "File" -> "Examples" -> "ESP32 BLE Abs Mouse" and select any of the examples to get started. 28 | 29 | ## Examples 30 | 31 | ``` 32 | #include 33 | 34 | BleAbsMouse bleAbsMouse; 35 | 36 | void setup() { 37 | bleAbsMouse.begin(); 38 | } 39 | 40 | void loop() { 41 | if(bleAbsMouse.isConnected()) { 42 | bleAbsMouse.click(5000, 5000); 43 | } 44 | delay(2000); 45 | } 46 | ``` 47 | 48 | Check [examples](examples) for concrete examples. 49 | 50 | ## API docs 51 | 52 | ``` 53 | // Use 0 up to 10000 to represent: 54 | // x: from left to right 55 | // y: from top to bottom 56 | bleAbsMouse.click(x,y); 57 | 58 | // If you want to click and stay clicked, use move instead: 59 | bleAbsMouse.move(x,y); 60 | 61 | // Since move keeps the finger as pressed, you need to release it when convenient 62 | bleAbsMouse.release(); 63 | ``` 64 | 65 | There is also Bluetooth specific information that you can use (optional): 66 | 67 | Instead of `BleAbsMouse bleAbsMouse;` you can do `BleAbsMouse bleAbsMouse("Bluetooth Device Name", "Bluetooth Device Manufacturer", 100);`. 68 | 69 | The third parameter is the initial battery level of your device. To adjust the battery level later on you can simply call e.g. `bleAbsMouse.setBatteryLevel(50)` (set battery level to 50%). 70 | By default the battery level will be set to 100%, the device name will be `ESP32 Bluetooth Abs Mouse` and the manufacturer will be `Espressif`. 71 | 72 | ## Credits 73 | 74 | Credits to [T-vK](https://github.com/T-vK) as this library is based on [ESP32-Ble-Mouse](https://github.com/T-vK/ESP32-BLE-Mouse) that he created. 75 | -------------------------------------------------------------------------------- /examples/Click/Click.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * This example turns the ESP32 into a Bluetooth LE Absolute Mouse that clicks 3 | * the center of the screen every 2 seconds. 4 | */ 5 | #include 6 | 7 | BleAbsMouse bleAbsMouse; 8 | 9 | void setup() { 10 | Serial.begin(115200); 11 | Serial.println("Starting BLE work!"); 12 | bleAbsMouse.begin(); 13 | } 14 | 15 | void loop() { 16 | if(bleAbsMouse.isConnected()) { 17 | Serial.println("Click"); 18 | bleAbsMouse.click(5000, 5000); 19 | } 20 | delay(2000); 21 | } 22 | -------------------------------------------------------------------------------- /examples/PressAndRelease/PressAndRelease.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * This example turns the ESP32 into a Bluetooth LE Absolute Mouse that presses, 3 | * moves and releases (drags n' drops) something from the left to the right of 4 | * the screen every 2 seconds. 5 | */ 6 | #include 7 | 8 | BleAbsMouse bleAbsMouse; 9 | 10 | void setup() { 11 | Serial.begin(115200); 12 | Serial.println("Starting BLE work!"); 13 | bleAbsMouse.begin(); 14 | } 15 | 16 | void loop() { 17 | if(bleAbsMouse.isConnected()) { 18 | Serial.println("Press"); 19 | bleAbsMouse.move(2500, 2500); 20 | delay(1000); 21 | 22 | Serial.println("Move"); 23 | bleAbsMouse.move(5000, 5000); 24 | delay(1000); 25 | 26 | Serial.println("Move"); 27 | bleAbsMouse.move(7500, 7500); 28 | delay(1000); 29 | 30 | Serial.println("Release"); 31 | bleAbsMouse.release(); 32 | } 33 | 34 | delay(2000); 35 | } 36 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For ESP32 BLE Abs Mouse 3 | ####################################### 4 | # Class 5 | ####################################### 6 | 7 | BleAbsMouse KEYWORD1 8 | 9 | ####################################### 10 | # Methods and Functions 11 | ####################################### 12 | 13 | begin KEYWORD2 14 | end KEYWORD2 15 | click KEYWORD2 16 | move KEYWORD2 17 | release KEYWORD2 18 | send KEYWORD2 19 | isConnected KEYWORD2 20 | setBatteryLevel KEYWORD2 21 | 22 | ####################################### 23 | # Constants 24 | ####################################### 25 | 26 | REPORTID_TOUCH LITERAL1 27 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=ESP32 BLE Abs Mouse 2 | version=0.1.0 3 | author=Gabriel Sobrinho 4 | maintainer=Gabriel Sobrinho 5 | sentence=Bluetooth LE Abs Mouse library for the ESP32. 6 | paragraph=Bluetooth LE Abs Mouse library for the ESP32. 7 | category=Communication 8 | url=https://github.com/sobrinho/ESP32-BLE-Abs-Mouse 9 | architectures=esp32 10 | --------------------------------------------------------------------------------