Closed rahmanshaber closed 3 years ago
Thanks for reporting, i will test it, because from code level it seems to be ok.
What OS are you using, what keyboard layout?
Windows. i will use the device in the linux,
Ok, for modifiers you are not using values: https://github.com/hathach/tinyusb/blob/master/src/class/hid/hid.h#L410-L417 instead you have to use: https://github.com/hathach/tinyusb/blob/master/src/class/hid/hid.h#L282-L289
So the commented processkey code will work fine, it's not an issue in the function? i mean this one
//static uint8_t modifierKey = 0x00;
//
//static void processKeys(void)
//{
// if (!Dummy.getKeys())
// return;
//
// int i;
//
// for (i = 0; i < LIST_MAX; i++) {
// if (!Dummy.key[i].stateChanged)
// continue;
//
// uint8_t key = mapKey(Dummy.key[i].kchar);
//
// if (key == KMAP_SWITCH || key == KBATTERY_SWITCH || key == NOTIFICATION_BUZZER || key == KMOUSE_LEFT || key == KMOUSE_RIGHT || key == EXPANSION_SWITCH || key == NOTIFICATION_LED || key == LCD_SWITCH || key == POWEROFF)
// continue;
//
// switch (Dummy.key[i].kstate) {
// case PRESSED: {
// if (key & HID_KEY_SHIFT_LEFT) {
// modifierKey = key;
// } else if (key & HID_KEY_CONTROL_LEFT) {
// modifierKey = key;
// } else if (key & HID_KEY_ALT_LEFT) {
// modifierKey = key;
// } else if (key & HID_KEY_GUI_LEFT) {
// modifierKey = key;
// } else {
// if (modifierKey & 0x00) { // if empty modifier
// device.sendKey(key);
// modifierKey = 0x00;
// } else {
// device.sendKey(key, modifierKey);
// modifierKey = 0x00;
// }
// }
// }
// break;
// case RELEASED: {
// device.sendRelease();
// modifierKey = 0x00;
// }
// break;
// }
// }
//}
Probably yes, i didnt check your code.
The point is that modifier is a 8 bit value, where each bit is a special key. The HID_KEY_ALT_LEFT
are used to build hid report descriptor, and you could eventually use it as key, not modifier, value, but most likely descriptor is not prepared to use it this way.
okay, i tested with KEYBOARD_MODIFIER_LEFTCTRL and sendKey function it does not work. can you give me an example code to test the modifier keys. like hold ctrl then v to past.
This is code i tested with, on linux, with keyboard layout test app:
/**
* Simple HID keyboard
* author: chegewara
*/
#include "Arduino.h"
#include "hidkeyboard.h"
HIDkeyboard dev;
class MyHIDCallbacks: public HIDCallbacks{
void onData(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
Serial.printf("ID: %d, type: %d, size: %d\n", report_id, (int)report_type, bufsize);
for (size_t i = 0; i < bufsize; i++)
{
Serial.printf("%d\n", buffer[i]);
}
}
};
void dataCB(uint8_t report_id, uint8_t report_type, uint8_t const* buffer, uint16_t bufsize)
{
for (size_t i = 0; i < bufsize; i++)
{
Serial.printf("%d\n", buffer[i]);
Serial.printf("%c\n", buffer[i]);
}
}
void setup()
{
Serial.begin(115200);
dev.begin();
dev.setCallbacks(new MyHIDCallbacks());
}
void loop()
{
delay(1000);
// dev.sendKey(0, KEYBOARD_MODIFIER_LEFTCTRL); // press and release CTRL
dev.sendPress(0, KEYBOARD_MODIFIER_LEFTCTRL); // hold CTRL
}
I can see the Control L
is being pressed hold (you cant see it on this screenshot, because any action with mouse or keyboard change its state in that app, but i can confirm CTRL is held with mouse wheel changing font size in apps):
okay, i had some issues in the code and i fixed some of it, and now ctrl and windows key works. but still can't get the combination working, i think library has something to do with it. can you add 2 button, use 1 for ctrl and other for v, see if combination is working, i mean the past. Also when i press E i get the gui key, means the start menu shows up. my if function can't filter the difference as the gui modifier uses 8. MODIFIER_GUI_LEFT == HID_KEY_E == 0x08 is there a way to know that a modifier key is pressed?
static void processKeys(void)
{
if (!Dummy.getKeys())
return;
int i;
for (i = 0; i < LIST_MAX; i++) {
if (!Dummy.key[i].stateChanged)
continue;
uint8_t key = mapKey(Dummy.key[i].kchar);
if (key == KMAP_SWITCH || key == KBATTERY_SWITCH || key == NOTIFICATION_BUZZER || key == KMOUSE_LEFT || key == KMOUSE_RIGHT || key == EXPANSION_SWITCH || key == NOTIFICATION_LED || key == LCD_SWITCH || key == POWEROFF)
continue;
switch (Dummy.key[i].kstate) {
case PRESSED: {
if (key == KEYBOARD_MODIFIER_LEFTCTRL) {
Serial.print("LEFT MODIFIER PRESSED");
device.sendPress(0, KEYBOARD_MODIFIER_LEFTCTRL);
} else if (key == KEYBOARD_MODIFIER_LEFTGUI) {
Serial.print("LEFT GUI PRESSED");
device.sendPress(0, KEYBOARD_MODIFIER_LEFTGUI);
} else {
Serial.print("SOME KEY PRESSED");
device.sendPress(key);
}
}
break;
case RELEASED: {
device.sendRelease();
}
break;
}
}
}
The library works fine. You have to send key at the same time with modifier:
device.sendPress(key, KEYBOARD_MODIFIER_LEFTGUI);
When you send device.sendRelease();
all keys are released, also modifier keys.
the combination works, but can't figure out how to solve that GUI_key issue. Pressing e press windows key. how to recognize modifier key
i used those modifier keys and working great. but issue is my if function can't differenceit between this keys, as they have assigned same values. MODIFIER_GUI_LEFT == HID_KEY_E == 0x08 what can i do to solve this issue. everytime i press E key i get the Gui_key
static void processKeys(void)
{
if (!Dummy.getKeys())
return;
int i;
for (i = 0; i < LIST_MAX; i++) {
if (!Dummy.key[i].stateChanged)
continue;
uint8_t key = mapKey(Dummy.key[i].kchar);
if (key == KMAP_SWITCH || key == KBATTERY_SWITCH || key == NOTIFICATION_BUZZER || key == KMOUSE_LEFT || key == KMOUSE_RIGHT || key == EXPANSION_SWITCH || key == NOTIFICATION_LED || key == LCD_SWITCH || key == POWEROFF)
continue;
switch (Dummy.key[i].kstate) {
case PRESSED: {
if (key == KEYBOARD_MODIFIER_LEFTCTRL) {
Serial.print("LEFT MODIFIER PRESSED");
device.sendPress(0, KEYBOARD_MODIFIER_LEFTCTRL);
} else if (key == KEYBOARD_MODIFIER_LEFTGUI) {
Serial.print("LEFT GUI PRESSED");
device.sendPress(0, KEYBOARD_MODIFIER_LEFTGUI);
} else {
Serial.print("SOME KEY PRESSED");
device.sendPress(key);
}
}
break;
case RELEASED: {
device.sendRelease();
}
break;
}
}
}
You are mixing 2 things. HID_KEY_E
is a key value, MODIFIER_GUI_LEFT
is a modifier value.
If you have problem in code then you have problem with design.
You could use HID_KEY_CONTROL_LEFT
in your code to detect key, but to send as modifier you have to use KEYBOARD_MODIFIER_LEFTCTRL
.
Thanks a lot, i got my code working. Thanks a lot for this nice ardinuo library.
I will share my working code if in case someone needs it. Here is my project https://mutantc.gitlab.io/index.html
// firmware V4.1
// mutantC v4
#include "Arduino.h"
#include "hidcomposite.h"
#include <Keypad.h>
HIDcomposite device;
const int LED_1 = 17;
const int LED_2 = 5;
const int POWER_MAIN =37;
const int POWER_OFF =26;
const int POWER_EX =39;
const int POWER_LCD =38;
const int BUZZER =40;
const int PI_STATE =42;
const int BATTERY_MESUREMENT =18;
// Thumbstick, set pin numbers for the five buttons:
const int rightButton = 9;
const int upButton= 8;
const int leftButton = 4;
const int downButton= 10;
const int mouseButton = 3;
// For Thumbstick
int range = 10; // output range of X or Y movement; affects movement speed
int responseDelay = 10; // response delay of the mouse, in ms
// Switch Stats
static bool keymapState = 0;
static bool expansionState = 0;
static bool lcdState = 0;
bool powerstate = 0;
// For Keypad
const byte ROWS = 5;
const byte COLS = 11;
// For Battery Voltage
int value = 0;
float voltage;
#define POWEROFF 0x91
#define KMAP_SWITCH 0x92
#define EXPANSION_SWITCH 0x93
#define LCD_SWITCH 0x94
#define NOTIFICATION_LED 0x95
#define KMOUSE_LEFT 0x96
#define KMOUSE_RIGHT 0x97
#define KBATTERY_SWITCH 0x98
#define NOTIFICATION_BUZZER 0x99
static uint8_t keymapAlpha [] = {
KMOUSE_RIGHT, LCD_SWITCH, EXPANSION_SWITCH, KBATTERY_SWITCH, NOTIFICATION_BUZZER, POWEROFF, NOTIFICATION_LED, 'E', 'E', KMAP_SWITCH, KMOUSE_LEFT,
HID_KEY_1, HID_KEY_2, HID_KEY_3, HID_KEY_4, HID_KEY_5, HID_KEY_6, HID_KEY_7, HID_KEY_8, HID_KEY_9, HID_KEY_0, HID_KEY_ARROW_LEFT ,
HID_KEY_Q, HID_KEY_W, HID_KEY_E, HID_KEY_R, HID_KEY_T, HID_KEY_Y, HID_KEY_U, HID_KEY_I, HID_KEY_O, HID_KEY_P, HID_KEY_ARROW_RIGHT ,
HID_KEY_CAPS_LOCK , HID_KEY_A, HID_KEY_S, HID_KEY_D, HID_KEY_F, HID_KEY_G, HID_KEY_H, HID_KEY_J, HID_KEY_K, HID_KEY_L, HID_KEY_BACKSPACE,
HID_KEY_CONTROL_LEFT, HID_KEY_GUI_LEFT, HID_KEY_Z, HID_KEY_X, HID_KEY_C, HID_KEY_V, HID_KEY_B, HID_KEY_N, HID_KEY_M, HID_KEY_SPACE, HID_KEY_RETURN
};
static uint8_t keymapSymbols[] = {
KMOUSE_RIGHT, LCD_SWITCH, EXPANSION_SWITCH, KBATTERY_SWITCH, NOTIFICATION_BUZZER, POWEROFF, NOTIFICATION_LED, 'E', 'E', KMAP_SWITCH, KMOUSE_LEFT,
HID_KEY_ESCAPE, HID_KEY_APOSTROPHE, HID_KEY_BACKSLASH, HID_KEY_SLASH, HID_KEY_SLASH, HID_KEY_SLASH, HID_KEY_SLASH, HID_KEY_SEMICOLON, HID_KEY_APOSTROPHE, HID_KEY_BRACKET_RIGHT, HID_KEY_ARROW_LEFT,
HID_KEY_TAB, HID_KEY_BRACKET_RIGHT, HID_KEY_ARROW_UP, HID_KEY_BRACKET_RIGHT, HID_KEY_BRACKET_RIGHT, HID_KEY_BRACKET_RIGHT, HID_KEY_BRACKET_RIGHT, HID_KEY_BRACKET_RIGHT, HID_KEY_BRACKET_RIGHT, HID_KEY_BRACKET_RIGHT, HID_KEY_ARROW_RIGHT,
HID_KEY_CAPS_LOCK, 'E', HID_KEY_ARROW_DOWN, 'E', HID_KEY_BRACKET_RIGHT, HID_KEY_BRACKET_RIGHT , HID_KEY_BRACKET_LEFT , HID_KEY_BRACKET_RIGHT, HID_KEY_BRACKET_RIGHT, HID_KEY_BRACKET_RIGHT, HID_KEY_BACKSPACE,
HID_KEY_CONTROL_LEFT , HID_KEY_GUI_LEFT, HID_KEY_EQUAL, HID_KEY_MINUS, HID_KEY_SLASH, HID_KEY_BRACKET_RIGHT, HID_KEY_KEYPAD_EQUAL, HID_KEY_COMMA, HID_KEY_PERIOD, HID_KEY_BRACKET_RIGHT, HID_KEY_RETURN
};
static char dummyKeypad[ROWS][COLS] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
{11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21},
{22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32},
{33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43},
{44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54}
};
byte rowPins[ROWS] = {2, 41, 11, 12, 13}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {6, 21, 33, 36, 34, 35, 16, 1, 14, 15, 7}; //connect to the column pinouts of the
//initialize an instance of class NewKeypad
Keypad Dummy = Keypad(makeKeymap(dummyKeypad), rowPins, colPins, ROWS, COLS);
void setup(void){
// Set PIN Stater
pinMode(LED_1, OUTPUT);
pinMode(LED_2, OUTPUT);
pinMode(POWER_MAIN, OUTPUT);
pinMode(POWER_OFF, INPUT_PULLUP);
pinMode(POWER_EX, OUTPUT);
pinMode(POWER_LCD, OUTPUT);
pinMode(BUZZER, OUTPUT);
pinMode(BATTERY_MESUREMENT, INPUT_PULLUP);
pinMode(PI_STATE, INPUT_PULLUP);
// Set thumbstick PIN Stater
pinMode(upButton, INPUT_PULLUP);
pinMode(downButton, INPUT_PULLUP);
pinMode(leftButton, INPUT_PULLUP);
pinMode(rightButton, INPUT_PULLUP);
pinMode(mouseButton, INPUT_PULLUP);
// Set Switch State
digitalWrite(POWER_MAIN, HIGH);
// digitalWrite(POWER_EX, LOW);
digitalWrite(POWER_LCD, LOW);
digitalWrite(BUZZER, LOW);
powerstate = digitalRead(POWER_OFF);
// Serial setup
Serial.begin(115200);
// Set up Keyboard and Mouse HID
device.begin();
// Set up keypad matrix
Dummy.setHoldTime(1);
Dummy.setDebounceTime(0);
Dummy.addEventListener(keypadEvent);
delay(1000);
}
void loop(void){
// digitalWrite(LED_1, HIGH);
// digitalWrite(LED_2, HIGH);
// delay(1000);
// digitalWrite(LED_1, LOW);
// digitalWrite(LED_2, LOW);
// Serial.println(powerstate);
// Serial.println(digitalRead(POWER_OFF));
// Check Mouse state
thumbstick ();
// Check Keyboard state
processKeys();
}
static void selectAlphabet(void)
{
digitalWrite(LED_1, LOW);
keymapState = 0;
}
static void selectSymbols(void)
{
digitalWrite(LED_1, HIGH);
keymapState = 1;
}
static void switchKeymap(void)
{
if (keymapState)
selectAlphabet();
else
selectSymbols();
}
static uint8_t mapKey(char key)
{
if (keymapState)
return keymapSymbols[key];
return keymapAlpha[key];
}
static void keypadEvent(KeypadEvent key)
{
if (Dummy.getState() != PRESSED)
return;
uint8_t kcode = mapKey(key);
switch (kcode) {
case KMAP_SWITCH:
switchKeymap();
break;
case KBATTERY_SWITCH:
battery_state();
break;
case KMOUSE_LEFT:
mouse_left();
break;
case KMOUSE_RIGHT:
mouse_rgiht();
break;
case NOTIFICATION_BUZZER:
notificationBuzzer();
break;
case EXPANSION_SWITCH:
power_expansion();
break;
case NOTIFICATION_LED:
notificationLED();
break;
case LCD_SWITCH:
power_lcd();
break;
case POWEROFF:
poweroff();
break;
}
}
static uint8_t modifierKey = 0;
static void processKeys(void)
{
if (!Dummy.getKeys())
return;
int i;
for (i = 0; i < LIST_MAX; i++) {
if (!Dummy.key[i].stateChanged)
continue;
uint8_t key = mapKey(Dummy.key[i].kchar);
if (key == KMAP_SWITCH || key == KBATTERY_SWITCH || key == NOTIFICATION_BUZZER || key == KMOUSE_LEFT || key == KMOUSE_RIGHT || key == EXPANSION_SWITCH || key == NOTIFICATION_LED || key == LCD_SWITCH || key == POWEROFF)
continue;
switch (Dummy.key[i].kstate) {
case PRESSED: {
if (key == HID_KEY_CONTROL_LEFT) {
device.sendPress(0, KEYBOARD_MODIFIER_LEFTCTRL);
modifierKey = KEYBOARD_MODIFIER_LEFTCTRL;
} else if (key == HID_KEY_GUI_LEFT) {
device.sendPress(0, KEYBOARD_MODIFIER_LEFTGUI);
modifierKey = KEYBOARD_MODIFIER_LEFTCTRL;
} else {
device.sendPress(key, modifierKey);
modifierKey = 0;
}
}
break;
case RELEASED: {
device.sendRelease();
modifierKey = 0;
}
break;
}
}
}
void thumbstick (void){
// read the thumbstick buttons:
int upState = digitalRead(upButton);
int downState = digitalRead(downButton);
int rightState = digitalRead(rightButton);
int leftState = digitalRead(leftButton);
// calculate the movement distance based on the button states:
int xDistance = (leftState - rightState) * range;
int yDistance = (upState - downState) * range;
// if X or Y is non-zero, move:
if ((xDistance != 0) || (yDistance != 0)) {
device.move(xDistance, yDistance);
}
// a delay so the mouse doesn't move too fast:
delay(responseDelay);
}
void mouse_left (void){
device.pressLeft();
delay(responseDelay);
}
void mouse_rgiht (void){
device.pressRight();
delay(responseDelay);
}
static void power_lcd(void)
{
if(lcdState){
digitalWrite(POWER_LCD, LOW);
Serial.println("POWER_LCD=LOW");
lcdState = 0;
} else {
digitalWrite(POWER_LCD, HIGH);
Serial.println("POWER_LCD=HIGH");
lcdState = 1;
}
}
static void power_expansion(void)
{
if(expansionState){
digitalWrite(POWER_EX, LOW);
Serial.println("POWER_EX=LOW");
expansionState = 0;
} else {
digitalWrite(POWER_EX, HIGH);
Serial.println("POWER_EX=HIGH");
expansionState = 1;
}
}
static void notificationLED(void)
{
Serial.println("notificationLED");
digitalWrite(LED_2, HIGH);
delay(25);
digitalWrite(LED_2, LOW);
delay(25);
digitalWrite(LED_2, HIGH);
delay(25);
digitalWrite(LED_2, LOW);
delay(25);
digitalWrite(LED_1, HIGH);
delay(25);
digitalWrite(LED_1, LOW);
delay(25);
digitalWrite(LED_1, HIGH);
delay(25);
digitalWrite(LED_1, LOW);
delay(25);
}
static void notificationBuzzer(void)
{
Serial.println("notificationBuzzer");
digitalWrite(BUZZER, HIGH);
delay(50);
digitalWrite(BUZZER, LOW);
delay(50);
digitalWrite(BUZZER, HIGH);
delay(50);
digitalWrite(BUZZER, LOW);
}
static void poweroff(void)
{
// uint8_t i;
/* Ask RPi to powerdown */
// Keyboard.write(CONSUMER_POWER);
// /* Wait for about 16 seconds */
// for (i = 0; i < 20; i++) {
// notification();
// }
// delay(16000);
/* And finally turn off the power */
Serial.println("poweroffOFF");
digitalWrite(POWER_MAIN, LOW);
}
static void battery_state(void)
{
Serial.println("battery_state");
Serial.println(read_voltage());
}
static float read_voltage(void)
{
// Get Battery voltage
value = analogRead(BATTERY_MESUREMENT);
voltage = value * 5.0/1023;
// Serial.print("Voltage= ");
// Serial.println(voltage);
delay(200);
return voltage;
}
// written by
// Cyril Hrubis @metan-ucw
// Abrar @s96Abrar
// rahmanshaber @rahmanshaber
I am trying to use the MODIFIER keys from this list, but it does not work. I get no output. see the processKeys function, i tried both commented and un-commented one. Commented one also does not work also it only gives output from some keys fromthe array. but un-commented one, every key works except the HID_KEY_CONTROL_LEFT. https://github.com/hathach/tinyusb/blob/master/src/class/hid/hid.h#L282