|
| 1 | +/*---------------------------------------------------------*\ |
| 2 | +| Mountain60KeyboardController.cpp | |
| 3 | +| | |
| 4 | +| Driver for Mountain keyboard | |
| 5 | +| | |
| 6 | +| O'D.Sæzl Jan 2025 | |
| 7 | +| | |
| 8 | +| This file is part of the OpenRGB project | |
| 9 | +| SPDX-License-Identifier: GPL-2.0-only | |
| 10 | +\*---------------------------------------------------------*/ |
| 11 | + |
| 12 | +#include <chrono> |
| 13 | +#include <cstring> |
| 14 | +#include <thread> |
| 15 | +#include "Mountain60KeyboardController.h" |
| 16 | +#include "StringUtils.h" |
| 17 | + |
| 18 | +using namespace std::chrono_literals; |
| 19 | + |
| 20 | +Mountain60KeyboardController::Mountain60KeyboardController(hid_device* dev_handle, const char* path) |
| 21 | +{ |
| 22 | + dev = dev_handle; |
| 23 | + location = path; |
| 24 | +} |
| 25 | + |
| 26 | +Mountain60KeyboardController::~Mountain60KeyboardController() |
| 27 | +{ |
| 28 | + hid_close(dev); |
| 29 | +} |
| 30 | + |
| 31 | +std::string Mountain60KeyboardController::GetDeviceLocation() |
| 32 | +{ |
| 33 | + return("HID: " + location); |
| 34 | +} |
| 35 | + |
| 36 | +const char* Mountain60KeyboardController::GetPath() |
| 37 | +{ |
| 38 | + return location.c_str(); |
| 39 | +} |
| 40 | + |
| 41 | +std::string Mountain60KeyboardController::GetSerialString() |
| 42 | +{ |
| 43 | + wchar_t serial_string[128]; |
| 44 | + int ret = hid_get_serial_number_string(dev, serial_string, 128); |
| 45 | + |
| 46 | + if(ret != 0) |
| 47 | + { |
| 48 | + return(""); |
| 49 | + } |
| 50 | + |
| 51 | + return(StringUtils::wstring_to_string(serial_string)); |
| 52 | +} |
| 53 | + |
| 54 | +void Mountain60KeyboardController::SetDevice(hid_device* new_device) |
| 55 | +{ |
| 56 | + hid_close(dev); |
| 57 | + dev = new_device; |
| 58 | +} |
| 59 | + |
| 60 | +void Mountain60KeyboardController::UpdateData() |
| 61 | +{ |
| 62 | + unsigned char usb_buf[MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE]; |
| 63 | + unsigned char read[MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE]; |
| 64 | + memset(usb_buf, 0x00, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 65 | + |
| 66 | + usb_buf[0x01] = MOUNTAIN60_KEYBOARD_CHECK_NUMPAD; |
| 67 | + usb_buf[0x02] = 0x46; //constant data |
| 68 | + usb_buf[0x03] = 0x23; //constant data |
| 69 | + usb_buf[0x04] = 0xEA; //constant data |
| 70 | + |
| 71 | + hid_send_feature_report(dev, usb_buf, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 72 | + memset(read, 0x00, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 73 | + hid_get_feature_report(dev, read, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 74 | +} |
| 75 | + |
| 76 | +void Mountain60KeyboardController::SendModeDetails(const mode* current_mode) |
| 77 | +{ |
| 78 | + unsigned char usb_buf[MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE]; |
| 79 | + unsigned char color_mode [] = {MOUNTAIN60_KEYBOARD_COLOR_MODE_SINGLE,MOUNTAIN60_KEYBOARD_COLOR_MODE_DUAL}; |
| 80 | + memset(usb_buf, 0x00, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 81 | + |
| 82 | + usb_buf[0x01] = MOUNTAIN60_KEYBOARD_SEND_CMD; |
| 83 | + usb_buf[0x02] = 0x46; //constant data |
| 84 | + usb_buf[0x03] = 0x23; //constant data |
| 85 | + usb_buf[0x04] = 0xEA; //constant data |
| 86 | + |
| 87 | + usb_buf[0x05] = current_mode->value; |
| 88 | + usb_buf[0x07] = current_mode->value == MOUNTAIN60_KEYBOARD_MODE_STATIC ? 0x32 : current_mode->speed * 25; |
| 89 | + usb_buf[0x08] = current_mode->brightness * 25; |
| 90 | + usb_buf[0x09] = current_mode->color_mode == MODE_COLORS_RANDOM ? MOUNTAIN60_KEYBOARD_COLOR_MODE_RAINBOW : color_mode[current_mode->colors.size() - 1]; |
| 91 | + usb_buf[0x0A] = ConvertDirection(current_mode->direction,current_mode->value == MOUNTAIN60_KEYBOARD_MODE_TORNADO); |
| 92 | + |
| 93 | + for (int idx = 0; idx < current_mode->colors.size(); ++idx) |
| 94 | + { |
| 95 | + unsigned int offset = 12 + (idx * 3); |
| 96 | + usb_buf[offset] = RGBGetRValue(current_mode->colors[idx]); |
| 97 | + usb_buf[offset+1] = RGBGetGValue(current_mode->colors[idx]); |
| 98 | + usb_buf[offset+2] = RGBGetBValue(current_mode->colors[idx]); |
| 99 | + } |
| 100 | + |
| 101 | + hid_send_feature_report(dev, usb_buf, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 102 | + std::this_thread::sleep_for(10ms); |
| 103 | + SaveData(current_mode->value); |
| 104 | +} |
| 105 | + |
| 106 | +void Mountain60KeyboardController::SelectMode(unsigned char mode_idx) |
| 107 | +{ |
| 108 | + unsigned char usb_buf[MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE]; |
| 109 | + unsigned char read[MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE]; |
| 110 | + memset(usb_buf, 0x00, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 111 | + |
| 112 | + usb_buf[0x01] = MOUNTAIN60_KEYBOARD_SELECT_MODE_CMD; |
| 113 | + usb_buf[0x02] = 0x46; //constant data |
| 114 | + usb_buf[0x03] = 0x23; //constant data |
| 115 | + usb_buf[0x04] = 0xEA; //constant data |
| 116 | + usb_buf[0x05] = 0x01; //constant data |
| 117 | + |
| 118 | + usb_buf[0x09] = mode_idx; |
| 119 | + |
| 120 | + hid_send_feature_report(dev, usb_buf, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 121 | + memset(read, 0x00, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 122 | + hid_get_feature_report(dev, read, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 123 | +} |
| 124 | + |
| 125 | +void Mountain60KeyboardController::SaveData(unsigned char mode_idx) |
| 126 | +{ |
| 127 | + unsigned char usb_buf[MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE]; |
| 128 | + unsigned char read[MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE]; |
| 129 | + memset(usb_buf, 0x00, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 130 | + |
| 131 | + usb_buf[0x01] = MOUNTAIN60_KEYBOARD_SAVE_CMD; |
| 132 | + usb_buf[0x02] = 0x46; //constant data |
| 133 | + usb_buf[0x03] = 0x23; //constant data |
| 134 | + usb_buf[0x04] = 0xEA; //constant data |
| 135 | + |
| 136 | + usb_buf[0x05] = mode_idx; |
| 137 | + |
| 138 | + hid_send_feature_report(dev, usb_buf, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 139 | + memset(read, 0x00, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 140 | + hid_get_feature_report(dev, read, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 141 | +} |
| 142 | + |
| 143 | +void Mountain60KeyboardController::SendDirectStartPacketCmd(unsigned int brightness) |
| 144 | +{ |
| 145 | + unsigned char usb_buf[MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE]; |
| 146 | + unsigned char read[MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE]; |
| 147 | + memset(usb_buf, 0x00, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 148 | + |
| 149 | + usb_buf[0x01] = MOUNTAIN60_KEYBOARD_START_DIRECT_CMD; |
| 150 | + usb_buf[0x02] = 0x46; //constant data |
| 151 | + usb_buf[0x03] = 0x23; //constant data |
| 152 | + usb_buf[0x04] = 0xEA; //constant data |
| 153 | + usb_buf[0x06] = 0xC0; //constant data |
| 154 | + |
| 155 | + usb_buf[0x05] = brightness * 25; |
| 156 | + |
| 157 | + hid_send_feature_report(dev, usb_buf, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 158 | + memset(read, 0x00, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 159 | + hid_get_feature_report(dev, read, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 160 | +} |
| 161 | + |
| 162 | +void Mountain60KeyboardController::SendDirectPacketCmd(unsigned char stream_control, unsigned char *data, unsigned int data_size) |
| 163 | +{ |
| 164 | + unsigned char usb_buf[MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE]; |
| 165 | + memset(usb_buf, 0x00, MOUNTAIN60_KEYBOARD_USB_BUFFER_HEADER_SIZE); |
| 166 | + |
| 167 | + usb_buf[0x01] = MOUNTAIN60_KEYBOARD_MAP_DIRECT_CMD; |
| 168 | + usb_buf[0x02] = 0x46; //constant data |
| 169 | + usb_buf[0x03] = 0x23; //constant data |
| 170 | + usb_buf[0x04] = 0xEA; //constant data |
| 171 | + |
| 172 | + usb_buf[0x05] = stream_control; |
| 173 | + |
| 174 | + if(data_size <= MOUNTAIN60_KEYBOARD_USB_MAX_DIRECT_PAYLOAD_SIZE) |
| 175 | + { |
| 176 | + unsigned char read[MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE]; |
| 177 | + memcpy(&usb_buf[MOUNTAIN60_KEYBOARD_USB_BUFFER_HEADER_SIZE],data,data_size); |
| 178 | + |
| 179 | + if(data_size < MOUNTAIN60_KEYBOARD_USB_MAX_DIRECT_PAYLOAD_SIZE) |
| 180 | + { |
| 181 | + memset(&usb_buf[MOUNTAIN60_KEYBOARD_USB_BUFFER_HEADER_SIZE + data_size],0xFF,MOUNTAIN60_KEYBOARD_USB_MAX_DIRECT_PAYLOAD_SIZE-data_size); |
| 182 | + } |
| 183 | + |
| 184 | + hid_send_feature_report(dev, usb_buf, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 185 | + memset(read, 0x00, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 186 | + hid_get_feature_report(dev, read, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 187 | + } |
| 188 | +} |
| 189 | + |
| 190 | +void Mountain60KeyboardController::SendDirectPacketFinishCmd() |
| 191 | +{ |
| 192 | + unsigned char usb_buf[MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE]; |
| 193 | + unsigned char read[MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE]; |
| 194 | + memset(usb_buf, 0x00, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 195 | + |
| 196 | + usb_buf[0x01] = MOUNTAIN60_KEYBOARD_END_DIRECT_CMD; |
| 197 | + usb_buf[0x02] = 0x46; //constant data |
| 198 | + usb_buf[0x03] = 0x23; //constant data |
| 199 | + usb_buf[0x04] = 0xEA; //constant data |
| 200 | + |
| 201 | + hid_send_feature_report(dev, usb_buf, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 202 | + memset(read, 0x00, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 203 | + hid_get_feature_report(dev, read, MOUNTAIN60_KEYBOARD_USB_BUFFER_SIZE); |
| 204 | +} |
| 205 | + |
| 206 | +void Mountain60KeyboardController::SendDirect(unsigned int brightness, unsigned char* color_data, unsigned int data_size) |
| 207 | +{ |
| 208 | + static unsigned char prv_buffer[MOUNTAIN60_KEYBOARD_TRANSFER_BUFFER_SIZE] = {0xFF}; |
| 209 | + unsigned char *data_ptr = color_data; |
| 210 | + unsigned char *prv_data_ptr = prv_buffer; |
| 211 | + unsigned int data_len = data_size; |
| 212 | + unsigned char stream_control_flag = 0x0E; |
| 213 | + |
| 214 | + SendDirectStartPacketCmd(brightness); |
| 215 | + |
| 216 | + while(data_len>0) |
| 217 | + { |
| 218 | + if(data_len >= MOUNTAIN60_KEYBOARD_USB_MAX_DIRECT_PAYLOAD_SIZE) |
| 219 | + { |
| 220 | + Mountain60KeyboardController::SendDirectPacketCmd(stream_control_flag,data_ptr,MOUNTAIN60_KEYBOARD_USB_MAX_DIRECT_PAYLOAD_SIZE); |
| 221 | + memcpy(prv_data_ptr,data_ptr,MOUNTAIN60_KEYBOARD_USB_MAX_DIRECT_PAYLOAD_SIZE); |
| 222 | + |
| 223 | + data_ptr += MOUNTAIN60_KEYBOARD_USB_MAX_DIRECT_PAYLOAD_SIZE; |
| 224 | + prv_data_ptr += MOUNTAIN60_KEYBOARD_USB_MAX_DIRECT_PAYLOAD_SIZE; |
| 225 | + data_len -= MOUNTAIN60_KEYBOARD_USB_MAX_DIRECT_PAYLOAD_SIZE; |
| 226 | + } |
| 227 | + else |
| 228 | + { |
| 229 | + stream_control_flag = 0x0A; |
| 230 | + Mountain60KeyboardController::SendDirectPacketCmd(stream_control_flag,data_ptr,data_len); |
| 231 | + memcpy(prv_data_ptr,data_ptr,data_len); |
| 232 | + data_len = 0; |
| 233 | + } |
| 234 | + } |
| 235 | + |
| 236 | + SendDirectPacketFinishCmd(); |
| 237 | +} |
| 238 | + |
| 239 | +unsigned char Mountain60KeyboardController::ConvertDirection(unsigned int direction, bool rotation) |
| 240 | +{ |
| 241 | + unsigned char ret; |
| 242 | + switch(direction) |
| 243 | + { |
| 244 | + case MODE_DIRECTION_LEFT: |
| 245 | + { |
| 246 | + ret = rotation?MOUNTAIN60_KEYBOARD_DIRECTION_ANTICLK:MOUNTAIN60_KEYBOARD_DIRECTION_LEFT; |
| 247 | + } |
| 248 | + break; |
| 249 | + |
| 250 | + case MODE_DIRECTION_RIGHT: |
| 251 | + { |
| 252 | + ret = rotation?MOUNTAIN60_KEYBOARD_DIRECTION_CLK:MOUNTAIN60_KEYBOARD_DIRECTION_RIGHT; |
| 253 | + } |
| 254 | + break; |
| 255 | + |
| 256 | + case MODE_DIRECTION_UP: |
| 257 | + { |
| 258 | + ret = MOUNTAIN60_KEYBOARD_DIRECTION_UP; |
| 259 | + } |
| 260 | + break; |
| 261 | + |
| 262 | + case MODE_DIRECTION_DOWN: |
| 263 | + { |
| 264 | + ret = MOUNTAIN60_KEYBOARD_DIRECTION_DOWN; |
| 265 | + } |
| 266 | + break; |
| 267 | + |
| 268 | + default: |
| 269 | + { |
| 270 | + ret = MOUNTAIN60_KEYBOARD_DIRECTION_LEFT; |
| 271 | + } |
| 272 | + break; |
| 273 | + } |
| 274 | + return ret; |
| 275 | +} |
0 commit comments