aboutsummaryrefslogtreecommitdiff
path: root/cores/arduino/HID.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cores/arduino/HID.cpp')
-rw-r--r--cores/arduino/HID.cpp145
1 files changed, 110 insertions, 35 deletions
diff --git a/cores/arduino/HID.cpp b/cores/arduino/HID.cpp
index 8ed1566..378a157 100644
--- a/cores/arduino/HID.cpp
+++ b/cores/arduino/HID.cpp
@@ -144,7 +144,6 @@ u8 _hid_protocol = 1;
u8 _hid_idle = 1;
#define WEAK __attribute__ ((weak))
-#define WEAK
int WEAK HID_GetInterface(u8* interfaceNum)
{
@@ -245,7 +244,7 @@ void Mouse_::release(uint8_t b)
bool Mouse_::isPressed(uint8_t b)
{
- if (b & _buttons > 0)
+ if ((b & _buttons) > 0)
return true;
return false;
}
@@ -254,7 +253,7 @@ bool Mouse_::isPressed(uint8_t b)
//================================================================================
// Keyboard
-Keyboard_::Keyboard_() : _keyMap(0)
+Keyboard_::Keyboard_()
{
}
@@ -263,11 +262,6 @@ void Keyboard_::sendReport(KeyReport* keys)
HID_SendReport(2,keys,sizeof(KeyReport));
}
-void Keyboard_::setKeyMap(KeyMap* keyMap)
-{
- _keyMap = keyMap;
-}
-
extern
const uint8_t _asciimap[128] PROGMEM;
@@ -406,38 +400,119 @@ const uint8_t _asciimap[128] =
};
uint8_t USBPutChar(uint8_t c);
-size_t Keyboard_::write(uint8_t c)
+
+// press() adds the specified key (printing, non-printing, or modifier)
+// to the persistent key report and sends the report. Because of the way
+// USB HID works, the host acts like the key remains pressed until we
+// call release(), releaseAll(), or otherwise clear the report and resend.
+size_t Keyboard_::press(uint8_t k)
{
- // Keydown
- {
- KeyReport keys = {0};
- if (_keyMap)
- _keyMap->charToKey(c,&keys);
- else
- {
- if (c >= 128) {
- setWriteError();
- return 0;
- }
- c = pgm_read_byte(_asciimap + c);
- if (!c) {
- setWriteError();
- return 0;
- }
- if (c & 0x80)
- {
- keys.modifiers |= KEY_MODIFIER_LEFT_SHIFT;
- c &= 0x7F;
+ uint8_t i;
+ if (k >= 136) { // it's a non-printing key (not a modifier)
+ k = k - 136;
+ } else if (k >= 128) { // it's a modifier key
+ _keyReport.modifiers |= (1<<(k-128));
+ k = 0;
+ } else { // it's a printing key
+ k = pgm_read_byte(_asciimap + k);
+ if (!k) {
+ setWriteError();
+ return 0;
+ }
+ if (k & 0x80) {
+ _keyReport.modifiers |= 0x02; // the left shift modifier
+ k &= 0x7F;
+ }
+ }
+
+ // Add k to the key report only if it's not already present
+ // and if there is an empty slot.
+ if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
+ _keyReport.keys[2] != k && _keyReport.keys[3] != k &&
+ _keyReport.keys[4] != k && _keyReport.keys[5] != k) {
+
+ for (i=0; i<6; i++) {
+ if (_keyReport.keys[i] == 0x00) {
+ _keyReport.keys[i] = k;
+ break;
}
- keys.keys[0] = c;
}
- sendReport(&keys);
+ if (i == 6) {
+ setWriteError();
+ return 0;
+ }
}
- // Keyup
- {
- KeyReport keys = {0};
- sendReport(&keys);
+ sendReport(&_keyReport);
+ return 1;
+}
+
+// release() takes the specified key out of the persistent key report and
+// sends the report. This tells the OS the key is no longer pressed and that
+// it shouldn't be repeated any more.
+size_t Keyboard_::release(uint8_t k)
+{
+ /*
+ uint8_t i;
+ k = pgm_read_byte(_asciimap + k);
+ if (!k) {
+ return 0;
+ }
+ if (k & 0x80) {
+ _keyReport.modifiers |= 0x02; // the left shift modifier
+ k &= 0x7F;
+ }
+ */
+ uint8_t i;
+ if (k >= 136) { // it's a non-printing key (not a modifier)
+ k = k - 136;
+ } else if (k >= 128) { // it's a modifier key
+ _keyReport.modifiers &= ~(1<<(k-128));
+ k = 0;
+ } else { // it's a printing key
+ k = pgm_read_byte(_asciimap + k);
+ if (!k) {
+ return 0;
+ }
+ if (k & 0x80) {
+ _keyReport.modifiers &= ~(0x02); // the left shift modifier
+ k &= 0x7F;
+ }
+ }
+
+ // Test the key report to see if k is present. Clear it if it exists.
+ for (i=0; i<6; i++) {
+ if (_keyReport.keys[i] == k) {
+ _keyReport.keys[i] = 0x00;
+ break;
+ }
+ }
+ if (i == 6) {
+ return 0;
}
+ sendReport(&_keyReport);
+ return 1;
+}
+
+void Keyboard_::releaseAll(void)
+{
+ _keyReport.keys[0] = 0;
+ _keyReport.keys[1] = 0;
+ _keyReport.keys[2] = 0;
+ _keyReport.keys[3] = 0;
+ _keyReport.keys[4] = 0;
+ _keyReport.keys[5] = 0;
+ _keyReport.modifiers = 0;
+ sendReport(&_keyReport);
+}
+
+// type() does a press and release of the specified key.
+size_t Keyboard_::type(uint8_t c)
+{
+ releaseAll();
+ // Keydown
+ press(c);
+ // Keyup
+ releaseAll();
return 1;
}