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.cpp144
1 files changed, 109 insertions, 35 deletions
diff --git a/cores/arduino/HID.cpp b/cores/arduino/HID.cpp
index 8ed1566..ac63608 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)
{
@@ -202,7 +201,15 @@ bool WEAK HID_Setup(Setup& setup)
//================================================================================
// Mouse
-Mouse_::Mouse_() : _buttons(0)
+Mouse_::Mouse_(void) : _buttons(0)
+{
+}
+
+void Mouse_::begin(void)
+{
+}
+
+void Mouse_::end(void)
{
}
@@ -245,7 +252,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,18 +261,21 @@ bool Mouse_::isPressed(uint8_t b)
//================================================================================
// Keyboard
-Keyboard_::Keyboard_() : _keyMap(0)
+Keyboard_::Keyboard_(void)
{
}
-void Keyboard_::sendReport(KeyReport* keys)
+void Keyboard_::begin(void)
+{
+}
+
+void Keyboard_::end(void)
{
- HID_SendReport(2,keys,sizeof(KeyReport));
}
-void Keyboard_::setKeyMap(KeyMap* keyMap)
+void Keyboard_::sendReport(KeyReport* keys)
{
- _keyMap = keyMap;
+ HID_SendReport(2,keys,sizeof(KeyReport));
}
extern
@@ -406,41 +416,105 @@ 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) { // it's a capital letter or other character reached with shift
+ _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;
+ 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) { // it's a capital letter or other character reached with shift
+ _keyReport.modifiers &= ~(0x02); // the left shift modifier
+ k &= 0x7F;
+ }
}
+
+ // Test the key report to see if k is present. Clear it if it exists.
+ // Check all positions in case the key is present more than once (which it shouldn't be)
+ for (i=0; i<6; i++) {
+ if (0 != k && _keyReport.keys[i] == k) {
+ _keyReport.keys[i] = 0x00;
+ }
+ }
+
+ 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);
+}
+
+size_t Keyboard_::write(uint8_t c)
+{
+ uint8_t p = press(c); // Keydown
+ uint8_t r = release(c); // Keyup
+ return (p); // just return the result of press() since release() almost always returns 1
+}
+
#endif
#endif /* if defined(USBCON) */ \ No newline at end of file