Advertisement
Xfos

DigiKeyboard_h

Apr 7th, 2017
416
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.17 KB | None | 0 0
  1. /*
  2. * Based on Obdev's AVRUSB code and under the same license.
  3. *
  4. * TODO: Make a proper file header. :-)
  5. * Modified for Digispark by Digistump
  6. */
  7. #ifndef __DigiKeyboard_h__
  8. #define __DigiKeyboard_h__
  9.  
  10. #include <Arduino.h>
  11. #include <avr/pgmspace.h>
  12. #include <avr/interrupt.h>
  13. #include <avr/delay.h>
  14. #include <string.h>
  15.  
  16. #include "usbdrv.h"
  17. #include "scancode-ascii-table.h"
  18.  
  19. // TODO: Work around Arduino 12 issues better.
  20. //#include <WConstants.h>
  21. //#undef int()
  22.  
  23. typedef uint8_t byte;
  24.  
  25.  
  26. #define BUFFER_SIZE 2 // Minimum of 2: 1 for modifiers + 1 for keystroke
  27.  
  28.  
  29. static uchar idleRate; // in 4 ms units
  30.  
  31.  
  32. /* We use a simplifed keyboard report descriptor which does not support the
  33. * boot protocol. We don't allow setting status LEDs and but we do allow
  34. * simultaneous key presses.
  35. * The report descriptor has been created with usb.org's "HID Descriptor Tool"
  36. * which can be downloaded from http://www.usb.org/developers/hidpage/.
  37. * Redundant entries (such as LOGICAL_MINIMUM and USAGE_PAGE) have been omitted
  38. * for the second INPUT item.
  39. */
  40. const PROGMEM char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { /* USB report descriptor */
  41. 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  42. 0x09, 0x06, // USAGE (Keyboard)
  43. 0xa1, 0x01, // COLLECTION (Application)
  44. 0x05, 0x07, // USAGE_PAGE (Keyboard)
  45. 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
  46. 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
  47. 0x15, 0x00, // LOGICAL_MINIMUM (0)
  48. 0x25, 0x01, // LOGICAL_MAXIMUM (1)
  49. 0x75, 0x01, // REPORT_SIZE (1)
  50. 0x95, 0x08, // REPORT_COUNT (8)
  51. 0x81, 0x02, // INPUT (Data,Var,Abs)
  52. 0x95, 0x01, // REPORT_COUNT (simultaneous keystrokes)
  53. 0x75, 0x08, // REPORT_SIZE (8)
  54. 0x25, 0x65, // LOGICAL_MAXIMUM (101)
  55. 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
  56. 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
  57. 0x81, 0x00, // INPUT (Data,Ary,Abs)
  58. 0xc0 // END_COLLECTION
  59. };
  60.  
  61.  
  62.  
  63. /* Keyboard usage values, see usb.org's HID-usage-tables document, chapter
  64. * 10 Keyboard/Keypad Page for more codes.
  65. */
  66. #define MOD_CONTROL_LEFT (1<<0)
  67. #define MOD_SHIFT_LEFT (1<<1)
  68. #define MOD_ALT_LEFT (1<<2)
  69. #define MOD_GUI_LEFT (1<<3)
  70. #define MOD_CONTROL_RIGHT (1<<4)
  71. #define MOD_SHIFT_RIGHT (1<<5)
  72. #define MOD_ALT_RIGHT (1<<6)
  73. #define MOD_GUI_RIGHT (1<<7)
  74.  
  75. #define KEY_A 4
  76. #define KEY_B 5
  77. #define KEY_C 6
  78. #define KEY_D 7
  79. #define KEY_E 8
  80. #define KEY_F 9
  81. #define KEY_G 10
  82. #define KEY_H 11
  83. #define KEY_I 12
  84. #define KEY_J 13
  85. #define KEY_K 14
  86. #define KEY_L 15
  87. #define KEY_M 16
  88. #define KEY_N 17
  89. #define KEY_O 18
  90. #define KEY_P 19
  91. #define KEY_Q 20
  92. #define KEY_R 21
  93. #define KEY_S 22
  94. #define KEY_T 23
  95. #define KEY_U 24
  96. #define KEY_V 25
  97. #define KEY_W 26
  98. #define KEY_X 27
  99. #define KEY_Y 28
  100. #define KEY_Z 29
  101. #define KEY_1 30
  102. #define KEY_2 31
  103. #define KEY_3 32
  104. #define KEY_4 33
  105. #define KEY_5 34
  106. #define KEY_6 35
  107. #define KEY_7 36
  108. #define KEY_8 37
  109. #define KEY_9 38
  110. #define KEY_0 39
  111.  
  112. #define KEY_ENTER 40
  113.  
  114. #define KEY_SPACE 44
  115.  
  116. #define KEY_F1 58
  117. #define KEY_F2 59
  118. #define KEY_F3 60
  119. #define KEY_F4 61
  120. #define KEY_F5 62
  121. #define KEY_F6 63
  122. #define KEY_F7 64
  123. #define KEY_F8 65
  124. #define KEY_F9 66
  125. #define KEY_F10 67
  126. #define KEY_F11 68
  127. #define KEY_F12 69
  128.  
  129. #define KEY_ARROW_LEFT 0x50
  130.  
  131.  
  132. class DigiKeyboardDevice : public Print {
  133. public:
  134. DigiKeyboardDevice () {
  135. cli();
  136. usbDeviceDisconnect();
  137. _delay_ms(250);
  138. usbDeviceConnect();
  139.  
  140.  
  141. usbInit();
  142.  
  143. sei();
  144.  
  145. // TODO: Remove the next two lines once we fix
  146. // missing first keystroke bug properly.
  147. memset(reportBuffer, 0, sizeof(reportBuffer));
  148. usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
  149. }
  150.  
  151. void update() {
  152. usbPoll();
  153. }
  154.  
  155. // delay while updating until we are finished delaying
  156. void delay(long milli) {
  157. unsigned long last = millis();
  158. while (milli > 0) {
  159. unsigned long now = millis();
  160. milli -= now - last;
  161. last = now;
  162. update();
  163. }
  164. }
  165.  
  166. //sendKeyStroke: sends a key press AND release
  167. void sendKeyStroke(byte keyStroke) {
  168. sendKeyStroke(keyStroke, 0);
  169. }
  170.  
  171. //sendKeyStroke: sends a key press AND release with modifiers
  172. void sendKeyStroke(byte keyStroke, byte modifiers) {
  173. sendKeyPress(keyStroke, modifiers);
  174. // This stops endlessly repeating keystrokes:
  175. sendKeyPress(0,0);
  176. }
  177.  
  178. //sendKeyPress: sends a key press only - no release
  179. //to release the key, send again with keyPress=0
  180. void sendKeyPress(byte keyPress) {
  181. sendKeyPress(keyPress, 0);
  182. }
  183.  
  184. //sendKeyPress: sends a key press only, with modifiers - no release
  185. //to release the key, send again with keyPress=0
  186. void sendKeyPress(byte keyPress, byte modifiers) {
  187. while (!usbInterruptIsReady()) {
  188. // Note: We wait until we can send keyPress
  189. // so we know the previous keyPress was
  190. // sent.
  191. usbPoll();
  192. _delay_ms(5);
  193. }
  194.  
  195. memset(reportBuffer, 0, sizeof(reportBuffer));
  196.  
  197. reportBuffer[0] = modifiers;
  198. reportBuffer[1] = keyPress;
  199.  
  200. usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
  201. }
  202.  
  203. size_t write(uint8_t chr) {
  204. uint8_t data = pgm_read_byte_near(ascii_to_scan_code_table + (chr - 8));
  205. sendKeyStroke(data & 0b01111111, data >> 7 ? MOD_SHIFT_RIGHT : 0);
  206. return 1;
  207. }
  208.  
  209. //private: TODO: Make friend?
  210. uchar reportBuffer[2]; // buffer for HID reports [ 1 modifier byte + (len-1) key strokes]
  211. using Print::write;
  212. };
  213.  
  214. DigiKeyboardDevice DigiKeyboard = DigiKeyboardDevice();
  215.  
  216. #ifdef __cplusplus
  217. extern "C"{
  218. #endif
  219. // USB_PUBLIC uchar usbFunctionSetup
  220. uchar usbFunctionSetup(uchar data[8]) {
  221. usbRequest_t *rq = (usbRequest_t *)((void *)data);
  222.  
  223. usbMsgPtr = DigiKeyboard.reportBuffer; //
  224. if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) {
  225. /* class request type */
  226.  
  227. if (rq->bRequest == USBRQ_HID_GET_REPORT) {
  228. /* wValue: ReportType (highbyte), ReportID (lowbyte) */
  229.  
  230. /* we only have one report type, so don't look at wValue */
  231. // TODO: Ensure it's okay not to return anything here?
  232. return 0;
  233.  
  234. } else if (rq->bRequest == USBRQ_HID_GET_IDLE) {
  235. //usbMsgPtr = &idleRate;
  236. //return 1;
  237. return 0;
  238.  
  239. } else if (rq->bRequest == USBRQ_HID_SET_IDLE) {
  240. idleRate = rq->wValue.bytes[1];
  241.  
  242. }
  243. } else {
  244. /* no vendor specific requests implemented */
  245. }
  246.  
  247. return 0;
  248. }
  249. #ifdef __cplusplus
  250. } // extern "C"
  251. #endif
  252.  
  253.  
  254. #endif // __DigiKeyboard_h__
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement