Skip to content

Instantly share code, notes, and snippets.

@argonism
Created December 6, 2019 11:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save argonism/baf72f44d2bd4459957486511d391ce4 to your computer and use it in GitHub Desktop.
Save argonism/baf72f44d2bd4459957486511d391ce4 to your computer and use it in GitHub Desktop.
#define JOYCON_L_PRODUCT_ID 8198
#define JOYCON_R_PRODUCT_ID 8199
#define MAX_JOYSTICKS_NUM 16
#include <hidapi.h>
#include <stdint.h>
#include <string.h>
#include <iostream>
#include <chrono>
#include <array>
void SendSubcommand(hid_device *dev, uint8_t command, uint8_t data[], int len, int* globalCount) {
uint8_t buf[0x40]; memset(buf, 0x0, size_t(0x40));
buf[0] = 1; // 0x10 for rumble only
buf[1] = *globalCount; // Increment by 1 for each packet sent. It loops in 0x0 - 0xF range.
if (*globalCount == 0xf0) {
*globalCount = 0x00;
} else {
*globalCount++;
}
buf[10] = command;
memcpy(buf + 11, data, len);
hid_write(dev, buf, 0x40);
}
std::array<hid_device*, MAX_JOYSTICKS_NUM> RefreshConnectedState()
{
hid_init();
std::array<hid_device*, MAX_JOYSTICKS_NUM> handler;
// hidハンドラーの取得
hid_device_info *device = hid_enumerate(0, 0);
const char *path;
int i = 0;
while (device)
{
path = device->path;
if ( device->product_id == JOYCON_L_PRODUCT_ID || device->product_id == JOYCON_R_PRODUCT_ID)
{
printf("\nproduct_id: %ls\n", device->product_string);
printf("\npath: %s\n", device->path);
printf("%hu, %hu, %ls\n", device->vendor_id, device->product_id, device->serial_number);
// hid_device *dev = hid_open_ref(device->dev_ref);
hid_device *dev = hid_open_path(device->path);
if (dev)
{
hid_set_nonblocking(dev, 1);
printf("open devise: %ls\n", device->product_string);
hid_set_nonblocking(dev, 1);
handler[i] = dev;
printf("set hid_device: %ls\n", device->product_string);
}
else
{
printf("fail to hid open\n");
}
i++;
}
device = device->next;
}
hid_free_enumeration(device);
return handler;
};
void light_up(hid_device* dev, uint8_t* data, int globalCount, bool increase) {
if (increase) {
if (data[0] == 0x08) {
data[0] = 0x01;
} else {
data[0] *= 2;
}
} else {
if (data[0] == 0x01) {
data[0] = 0x08;
} else {
data[0] /= 2;
}
}
SendSubcommand(dev, 0x30, data, 1, &globalCount);
}
int main()
{
int globalCount = 0;
std::array<hid_device*, MAX_JOYSTICKS_NUM> handler = RefreshConnectedState();
std::chrono::system_clock::time_point start, end;
start = std::chrono::system_clock::now();
end = std::chrono::system_clock::now();
uint8_t data[0x01];
uint8_t rep_id[0x01];
data[0] = 0x01;
printf("aaa");
// 0x03番のサブコマンドに、0x01を送信します。
// ランプはビットフラグで、4桁。ランプの一番上から10進数で 1, 2, 4, 8 と対応しています。
rep_id[0] = 0x3F;
for (int i=0; i <= 1; i++) {
hid_set_nonblocking(handler[i], 0);
SendSubcommand(handler[i], 0x30, data, 1, &globalCount);
SendSubcommand(handler[i], 0x03, rep_id, 1, &globalCount);
}
// read input report
uint8_t buff[0x40]; memset(buff, 0x40, size_t(0x40));
// 読み込むサイズを指定。
size_t size = 49;
while (true)
{
// if (std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() <= 100)
// {
// end = std::chrono::system_clock::now();
// continue;
// }
// input report を受けとる。
// for (int i=0; i <= 2; i++) {
// }
int ret = hid_read(handler[0], buff, size);
// input report の id が 0x3F のものに絞る。
if (*buff != 0x3F)
{
continue;
}
// input report の id を表示。
printf("\ninput report id: %d\n", *buff);
// ボタンのビットビットフィールドを表示。
printf("button byte 1: %d\n", buff[1]);
printf("button byte 2: %d\n", buff[1]);
if (buff[3] == 0x02)
{
printf("in a buff[1");
light_up(handler[1], data, globalCount, true);
}
else if (buff[3] == 0x06)
{
light_up(handler[1], data, globalCount, false);
}
// start = std::chrono::system_clock::now();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment