Skip to content

Instantly share code, notes, and snippets.

@argonism
Created December 6, 2019 09:48
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/b345f14cbdb0b21fc0aecb4d79a87323 to your computer and use it in GitHub Desktop.
Save argonism/b345f14cbdb0b21fc0aecb4d79a87323 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 to_down(uint8_t* data, uint8_t* diff, hid_device* dev, int globalCount)
{
data[0] -= *diff;
printf("down\n");
printf("diff: %x\n", *diff);
printf("data: %x\n", data[0]);
SendSubcommand(dev, 0x30, data, 1, &globalCount);
}
void to_up(uint8_t* data, uint8_t* diff, hid_device* dev, int globalCount)
{
data[0] += *diff;
printf("up\n");
printf("diff: %x\n", *diff);
printf("data: %x\n", data[0]);
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];
// hid_set_nonblocking(dev, 1);
data[0] = 0x00;
// 0x03番のサブコマンドに、0x01を送信します。
// ランプはビットフラグで、4桁。ランプの一番上から10進数で 1, 2, 4, 8 と対応しています。
// double time;
// data[0] = 0x10;
bool down = false;
bool secound = false;
// uint8_t i = 0x00;
// ボタンの入力を受け付けるぞ!
uint8_t diff = 0x01;
SendSubcommand(handler[0], 0x30, data, 1, &globalCount);
SendSubcommand(handler[1], 0x30, data, 1, &globalCount);
while (true)
{
if (std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() <= 100)
{
end = std::chrono::system_clock::now();
continue;
}
if (data[0] == 0x08 && down == false) {
down = true;
diff = 0x00;
data[0] = 0x08;
// SendSubcommand(handler[0], 0x30, data, 1, &globalCount);
// SendSubcommand(handler[1], 0x30, data, 1, &globalCount);
if (secound) {
secound = false;
uint8_t temp[0x01];
temp[0] = 0x00;
// SendSubcommand(handler[0], 0x30, data, 1, &globalCount);
SendSubcommand(handler[1], 0x30, temp, 1, &globalCount);
// to_down(data, &diff, handler[0], globalCount);
} else {
secound = true;
uint8_t temp[0x01];
temp[0] = 0x00;
// SendSubcommand(handler[1], 0x30, data, 1, &globalCount);
SendSubcommand(handler[0], 0x30, temp, 1, &globalCount);
// to_down(data, &diff, handler[1], globalCount);
}
continue;
}
else if (data[0] == 0x01 && down) {
down = false;
data[0] = 0x01;
diff = 0x01;
}
hid_device* dev = (secound) ? handler[1] : handler[0];
if (down) {
to_down(data, &diff, dev, globalCount);
if (diff != 1)
diff = data[0] / 2;
} else {
to_up(data, &diff, dev, globalCount);
diff = data[0];
}
// printf("awawa!: %x\n", diff);
start = std::chrono::system_clock::now();
}
}
#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;
};
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];
// hid_set_nonblocking(dev, 1);
data[0] = 0x00;
// 0x03番のサブコマンドに、0x01を送信します。
// ランプはビットフラグで、4桁。ランプの一番上から10進数で 1, 2, 4, 8 と対応しています。
// double time;
// data[0] = 0x10;
bool down = false;
// uint8_t i = 0x00;
// ボタンの入力を受け付けるぞ!
uint8_t diff = 0x01;
SendSubcommand(handler[0], 0x30, data, 1, &globalCount);
SendSubcommand(handler[1], 0x30, data, 1, &globalCount);
while (true)
{
if (std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() <= 100)
{
end = std::chrono::system_clock::now();
continue;
}
if (data[0] == 0x0F)
{
down = true;
}
else if (data[0] == 0x00)
{
down = false;
}
if (down)
{
data[0] = (data[0] - diff);
if (data[0] != 0x00)
diff = diff / 2;
}
else
{
data[0] += diff;
if (data[0] != 0x0F)
diff = diff * 2;
}
printf(" %s \n", (down ? "true" : "false"));
printf("diff: %x\n", diff);
printf("data: %x\n", data[0]);
SendSubcommand(handler[0], 0x30, data, 1, &globalCount);
SendSubcommand(handler[1], 0x30, data, 1, &globalCount);
start = std::chrono::system_clock::now();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment