libcm is a C development framework with an emphasis on audio signal processing applications.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cmKeyboard.c 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. //| Copyright: (C) 2009-2020 Kevin Larke <contact AT larke DOT org>
  2. //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
  3. #include "cmPrefix.h"
  4. #include "cmGlobal.h"
  5. #include "cmKeyboard.h"
  6. #include <termios.h>
  7. //#include <stropts.h>
  8. #include <sys/ioctl.h>
  9. //#include <linux/kd.h>
  10. //#include <linux/keyboard.h>
  11. #include <unistd.h>
  12. struct termios new_settings;
  13. struct termios stored_settings;
  14. void set_keypress(void)
  15. {
  16. struct termios new_settings;
  17. tcgetattr(0,&stored_settings);
  18. new_settings = stored_settings;
  19. new_settings.c_lflag &= (~ICANON);
  20. new_settings.c_lflag &= (~ECHO);
  21. new_settings.c_cc[VTIME] = 0;
  22. //int i;
  23. //for(i=0; i<NCCS; ++i)
  24. // printf("%i ",new_settings.c_cc[i]);
  25. //printf("\n");
  26. tcgetattr(0,&stored_settings);
  27. new_settings.c_cc[VMIN] = 1;
  28. tcsetattr(0,TCSANOW,&new_settings);
  29. }
  30. void reset_keypress(void)
  31. {
  32. tcsetattr(0,TCSANOW,&stored_settings);
  33. }
  34. #define CM_KB_TBL_CNT (10)
  35. unsigned _cmKbTbl[][CM_KB_TBL_CNT] =
  36. {
  37. // alt ctl code
  38. { 3, 27, 91, 68, 0, 0, 0, 0, 0, kLeftArrowKId },
  39. { 3, 27, 91, 67, 0, 0, 0, 0, 0, kRightArrowKId },
  40. { 3, 27, 91, 65, 0, 0, 0, 0, 0, kUpArrowKId },
  41. { 3, 27, 91, 66, 0, 0, 0, 0, 0, kDownArrowKId },
  42. { 3, 27, 79, 72, 0, 0, 0, 0, 0, kHomeKId },
  43. { 3, 27, 79, 70, 0, 0, 0, 0, 0, kEndKId },
  44. { 4, 27, 91, 53, 126, 0, 0, 0, 0, kPgUpKId },
  45. { 4, 27, 91, 54, 126, 0, 0, 0, 0, kPgDownKId },
  46. { 4, 27, 91, 50, 126, 0, 0, 0, 0, kInsertKId },
  47. { 4, 27, 91, 51, 126, 0, 0, 0, 0, kDeleteKId },
  48. { 6, 27, 91, 49, 59, 53, 68, 0, 1, kLeftArrowKId },
  49. { 6, 27, 91, 49, 59, 53, 67, 0, 1, kRightArrowKId },
  50. { 6, 27, 91, 49, 59, 53, 65, 0, 1, kUpArrowKId },
  51. { 6, 27, 91, 49, 59, 53, 66, 0, 1, kDownArrowKId },
  52. { 6, 27, 91, 53, 59, 53, 126, 0, 1, kPgUpKId },
  53. { 6, 27, 91, 54, 59, 53, 126, 0, 1, kPgDownKId },
  54. { 4, 27, 91, 51, 59, 53, 126, 0, 1, kDeleteKId },
  55. { 0, 0, 0, 0, 0, 0, 0, 0, 0, kInvalidKId }
  56. };
  57. void cmKeyPress( cmKbRecd* p )
  58. {
  59. const int bufN = 16;
  60. char buf[bufN];
  61. int n,j, k;
  62. int rc;
  63. char c;
  64. if( p != NULL )
  65. {
  66. p->code = kInvalidKId;
  67. p->ch = 0;
  68. p->ctlFl = false;
  69. p->altFl = false;
  70. }
  71. set_keypress();
  72. // block for the first character
  73. if((rc = read(0, &c, 1 )) == 1)
  74. buf[0]=c;
  75. // loop in non-blocking for successive characters
  76. new_settings.c_cc[VMIN] = 0;
  77. tcsetattr(0,TCSANOW,&new_settings);
  78. for(n=1; n<bufN; ++n)
  79. if(read(0,&c,1) == 1 )
  80. buf[n] = c;
  81. else
  82. break;
  83. new_settings.c_cc[VMIN] = 1;
  84. tcsetattr(0,TCSANOW,&new_settings);
  85. /*
  86. for(j=0; j<n; ++j)
  87. printf("{%c (%i)} ",buf[j],buf[j]);
  88. printf(" :%i\f\n",n);
  89. fflush(stdout);
  90. */
  91. if( p != NULL )
  92. {
  93. // translate the keypress
  94. if( n == 1)
  95. {
  96. p->code = kAsciiKId;
  97. p->ch = buf[0];
  98. p->ctlFl = buf[0] <= 31;
  99. }
  100. else
  101. {
  102. for(j=0; _cmKbTbl[j][0] != 0; ++j)
  103. if( _cmKbTbl[j][0] == n )
  104. {
  105. for(k=1; k<=n; ++k)
  106. if( _cmKbTbl[j][k] != buf[k-1] )
  107. break;
  108. // if the key was found
  109. if( k==n+1 )
  110. {
  111. p->code = _cmKbTbl[j][ CM_KB_TBL_CNT - 1 ];
  112. p->ctlFl = _cmKbTbl[j][ CM_KB_TBL_CNT - 2 ];
  113. break;
  114. }
  115. }
  116. }
  117. }
  118. reset_keypress();
  119. }
  120. void cmKbTest()
  121. {
  122. set_keypress();
  123. int c = 0;
  124. int r;
  125. while( c != 'q' )
  126. {
  127. printf("0>"); fflush(stdout);
  128. r = read(0, &c, 1 );
  129. printf("0: %c (%i)\r\n",(char)c,c);
  130. new_settings.c_cc[VMIN] = 0;
  131. tcsetattr(0,TCSANOW,&new_settings);
  132. if( r == 1 && c == 27 )
  133. {
  134. r = read(0, &c, 1 );
  135. printf("1: %c (%i)\n",(char)c,c);
  136. if( r == 1 && c == '[' )
  137. {
  138. r = read(0, &c, 1 );
  139. printf("2: %c (%i)\n",(char)c,c);
  140. }
  141. }
  142. new_settings.c_cc[VMIN] = 1;
  143. tcsetattr(0,TCSANOW,&new_settings);
  144. }
  145. reset_keypress();
  146. }
  147. // Note: this technique does not work because the
  148. void testKb2()
  149. {
  150. set_keypress();
  151. fd_set rfds;
  152. struct timeval tv;
  153. int retval;
  154. int c=0;
  155. while( c != 'q' )
  156. {
  157. int i = 0;
  158. printf(">");
  159. do
  160. {
  161. /* Watch stdin (fd 0) to see when it has input. */
  162. FD_ZERO(&rfds);
  163. FD_SET(0, &rfds);
  164. // don't wait
  165. tv.tv_sec = 0;
  166. tv.tv_usec = 0;
  167. retval = select(1, &rfds, NULL, NULL, i==0 ? NULL : &tv);
  168. // Don't rely on the value of tv now - it may have been overwritten by select
  169. // if an error occurred
  170. if (retval == -1)
  171. perror("select()");
  172. else
  173. {
  174. // if data is waiting
  175. if (retval)
  176. {
  177. c = getchar();
  178. printf("%i %c (%i) ",i,(char)c,c);
  179. ++i;
  180. }
  181. else
  182. {
  183. printf("\n");
  184. break; // no data available
  185. }
  186. }
  187. } while( 1 );
  188. }
  189. reset_keypress();
  190. }
  191. // Based on: // From: http://www.flipcode.com/archives/_kbhit_for_Linux.shtml
  192. int cmIsKeyWaiting()
  193. {
  194. static const int STDIN = 0;
  195. static bool initialized = false;
  196. struct timeval timeout;
  197. fd_set rdset;
  198. if (! initialized)
  199. {
  200. // Use termios to turn off line buffering
  201. struct termios term;
  202. tcgetattr(STDIN, &term);
  203. term.c_lflag &= ~ICANON;
  204. tcsetattr(STDIN, TCSANOW, &term);
  205. setbuf(stdin, NULL);
  206. initialized = true;
  207. }
  208. FD_ZERO(&rdset);
  209. FD_SET(STDIN, &rdset);
  210. timeout.tv_sec = 0;
  211. timeout.tv_usec = 0;
  212. // time out immediately if STDIN is not ready.
  213. return select(STDIN + 1, &rdset, NULL, NULL, &timeout);
  214. }