Skip to content

Commit bf99a5f

Browse files
DrZlo13CalcProgrammer1
authored andcommitted
New device: Obinslab Anne Pro 2
* Renamed "Obins Lab" to "Obinslab" as that is the name that I saw used most frequently in store listings. Commit amended for code style and to update the name by Adam Honse <[email protected]>
1 parent 0755959 commit bf99a5f

File tree

7 files changed

+467
-0
lines changed

7 files changed

+467
-0
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*-----------------------------------------*\
2+
| AnnePro2Controller.cpp |
3+
| |
4+
| Driver for Obins Lab AnnePro2 keyboard |
5+
| |
6+
| Sergey Gavrilov (DrZlo13) 06/06/2021 |
7+
\*-----------------------------------------*/
8+
9+
#include "AnnePro2Controller.h"
10+
11+
using namespace std::chrono_literals;
12+
13+
AnnePro2Controller::AnnePro2Controller(hid_device* dev_handle, const char* path)
14+
{
15+
dev = dev_handle;
16+
location = path;
17+
}
18+
19+
AnnePro2Controller::~AnnePro2Controller()
20+
{
21+
hid_close(dev);
22+
}
23+
24+
std::string AnnePro2Controller::GetDeviceLocation()
25+
{
26+
return("HID: " + location);
27+
}
28+
29+
std::string AnnePro2Controller::GetSerialString()
30+
{
31+
wchar_t serial_string[128];
32+
int ret = hid_get_serial_number_string(dev, serial_string, 128);
33+
34+
if(ret != 0)
35+
{
36+
return("");
37+
}
38+
39+
std::wstring return_wstring = serial_string;
40+
std::string return_string(return_wstring.begin(), return_wstring.end());
41+
42+
return(return_string);
43+
}
44+
45+
void AnnePro2Controller::SendDirect(unsigned char frame_count, unsigned char * frame_data)
46+
{
47+
/*-------------------------------------------------------------*\
48+
| Reverse engineered by https://github.com/manualmanul/Annemone |
49+
\*-------------------------------------------------------------*/
50+
51+
const unsigned char hid_cmd_service_data_length = 4;
52+
const unsigned char hid_cmd_service_data[hid_cmd_service_data_length] = {0, 123, 16, 65};
53+
54+
const unsigned char hid_cmd_static_message_length = 3;
55+
const unsigned char hid_cmd_static_message[hid_cmd_static_message_length] = {0, 0, 125};
56+
57+
const unsigned char hid_cmd_command_info_length = 3;
58+
const unsigned char hid_cmd_command_info[hid_cmd_command_info_length] = {32, 3, 255};
59+
60+
const unsigned char real_command_info_length = hid_cmd_command_info_length + 1;
61+
const unsigned char max_hid_length = 64;
62+
63+
const unsigned char max_command_length = max_hid_length - hid_cmd_service_data_length - 2 - hid_cmd_static_message_length;
64+
const unsigned char max_message_length = max_command_length - real_command_info_length;
65+
const unsigned char messages_to_send_amount = frame_count / max_message_length + 1;
66+
const unsigned char val_1 = frame_count % max_message_length;
67+
const unsigned char val_2 = (0 == val_1) ? max_message_length : val_1;
68+
69+
unsigned char hid_command[max_hid_length];
70+
71+
unsigned char led_data = 0;
72+
73+
for(unsigned char p = 0; p < messages_to_send_amount; p++)
74+
{
75+
const unsigned char e = (messages_to_send_amount << 4) + p;
76+
const unsigned char a = ((messages_to_send_amount - 1) == p) ? val_2 + real_command_info_length : max_message_length + real_command_info_length;
77+
78+
/*---------------------------------------------------------*\
79+
| Service data |
80+
\*---------------------------------------------------------*/
81+
hid_command[0] = hid_cmd_service_data[0];
82+
hid_command[1] = hid_cmd_service_data[1];
83+
hid_command[2] = hid_cmd_service_data[2];
84+
hid_command[3] = hid_cmd_service_data[3];
85+
86+
hid_command[4] = e;
87+
hid_command[5] = a;
88+
89+
/*---------------------------------------------------------*\
90+
| Static message |
91+
\*---------------------------------------------------------*/
92+
hid_command[6] = hid_cmd_static_message[0];
93+
hid_command[7] = hid_cmd_static_message[1];
94+
hid_command[8] = hid_cmd_static_message[2];
95+
96+
/*---------------------------------------------------------*\
97+
| Command info |
98+
\*---------------------------------------------------------*/
99+
hid_command[9] = hid_cmd_command_info[0];
100+
hid_command[10] = hid_cmd_command_info[1];
101+
hid_command[11] = hid_cmd_command_info[2];
102+
103+
hid_command[12] = 2;
104+
105+
/*---------------------------------------------------------*\
106+
| LED data |
107+
\*---------------------------------------------------------*/
108+
for(uint8_t i = 0; i < max_message_length; i++)
109+
{
110+
hid_command[13 + i] = frame_data[led_data];
111+
led_data++;
112+
}
113+
114+
hid_write(dev, hid_command, max_hid_length);
115+
116+
/*---------------------------------------------------------*\
117+
| Needed due to Anne Pro 2 ignoring commands when they're |
118+
| sent faster than 50ms apart from each other. |
119+
\*---------------------------------------------------------*/
120+
std::this_thread::sleep_for(50ms);
121+
}
122+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*-----------------------------------------*\
2+
| AnnePro2Controller.h |
3+
| |
4+
| Driver for Obins Lab AnnePro2 keyboard |
5+
| |
6+
| Sergey Gavrilov (DrZlo13) 06/06/2021 |
7+
\*-----------------------------------------*/
8+
9+
#pragma once
10+
#include "RGBController.h"
11+
12+
#include <string>
13+
#include <vector>
14+
#include <hidapi/hidapi.h>
15+
16+
#pragma once
17+
18+
class AnnePro2Controller
19+
{
20+
public:
21+
AnnePro2Controller(hid_device* dev_handle, const char* path);
22+
~AnnePro2Controller();
23+
24+
std::string GetDeviceLocation();
25+
std::string GetSerialString();
26+
27+
void SendDirect
28+
(
29+
unsigned char frame_count,
30+
unsigned char * frame_data
31+
);
32+
33+
private:
34+
hid_device* dev;
35+
std::string location;
36+
};
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include "Detector.h"
2+
#include "AnnePro2Controller.h"
3+
#include "RGBController.h"
4+
#include "RGBController_AnnePro2.h"
5+
#include <hidapi/hidapi.h>
6+
7+
#define ANNE_PRO_2_VID 0x04D9
8+
#define ANNE_PRO_2_PID_1 0x8008
9+
#define ANNE_PRO_2_PID_2 0x8009
10+
#define ANNE_PRO_2_PID_3 0xA292
11+
#define ANNE_PRO_2_PID_4 0xA293
12+
13+
/******************************************************************************************\
14+
* *
15+
* DetectAnnePro2Controllers *
16+
* *
17+
* Tests the USB address to see if an Obins Lab AnnePro2 keyboard exists there. *
18+
* *
19+
\******************************************************************************************/
20+
21+
void DetectAnnePro2Controllers(hid_device_info* info, const std::string&)
22+
{
23+
hid_device* dev = hid_open_path(info->path);
24+
if( dev )
25+
{
26+
AnnePro2Controller* controller = new AnnePro2Controller(dev, info->path);
27+
RGBController_AnnePro2* rgb_controller = new RGBController_AnnePro2(controller);
28+
// Constructor sets the name
29+
ResourceManager::get()->RegisterRGBController(rgb_controller);
30+
}
31+
}
32+
33+
REGISTER_HID_DETECTOR_I("Anne Pro 2", DetectAnnePro2Controllers, ANNE_PRO_2_VID, ANNE_PRO_2_PID_1, 1);
34+
REGISTER_HID_DETECTOR_I("Anne Pro 2", DetectAnnePro2Controllers, ANNE_PRO_2_VID, ANNE_PRO_2_PID_2, 1);
35+
REGISTER_HID_DETECTOR_I("Anne Pro 2", DetectAnnePro2Controllers, ANNE_PRO_2_VID, ANNE_PRO_2_PID_3, 1);
36+
REGISTER_HID_DETECTOR_I("Anne Pro 2", DetectAnnePro2Controllers, ANNE_PRO_2_VID, ANNE_PRO_2_PID_4, 1);

0 commit comments

Comments
 (0)