Subversion Repositories HelenOS

Rev

Rev 2409 | Rev 2479 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2007 Michal Kebrt
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup kbdarm32gxemul GXemul
  30.  * @brief   HelenOS arm32 GXEmul uspace keyboard handler.
  31.  * @ingroup  kbdarm32
  32.  * @{
  33.  */
  34. /** @file
  35.  *  @brief GXemul uspace keyboard handler.
  36.  */
  37.  
  38. #include <ipc/ipc.h>
  39. #include <sysinfo.h>
  40. #include <kbd.h>
  41. #include <keys.h>
  42. #include <bool.h>
  43.  
  44.  
  45. /* GXemul key codes in no-framebuffer mode. */
  46. #define GXEMUL_KEY_F1  0x504f1bL
  47. #define GXEMUL_KEY_F2  0x514f1bL
  48. #define GXEMUL_KEY_F3  0x524f1bL
  49. #define GXEMUL_KEY_F4  0x534f1bL
  50. #define GXEMUL_KEY_F5  0x35315b1bL
  51. #define GXEMUL_KEY_F6  0x37315b1bL
  52. #define GXEMUL_KEY_F7  0x38315b1bL
  53. #define GXEMUL_KEY_F8  0x39315b1bL
  54. #define GXEMUL_KEY_F9  0x30325b1bL
  55. #define GXEMUL_KEY_F10 0x31325b1bL
  56. #define GXEMUL_KEY_F11 0x33325d1bL
  57. #define GXEMUL_KEY_F12 0x34325b1bL
  58.  
  59. /** Start code of F5-F12 keys. */
  60. #define GXEMUL_KEY_F5_F12_START_CODE 0x7e
  61.  
  62. /* GXemul key codes in framebuffer mode. */
  63. #define GXEMUL_FB_KEY_F1 0x504f5b1bL
  64. #define GXEMUL_FB_KEY_F2 0x514f5b1bL
  65. #define GXEMUL_FB_KEY_F3 0x524f5b1bL
  66. #define GXEMUL_FB_KEY_F4 0x534f5b1bL
  67. #define GXEMUL_FB_KEY_F5 0x35315b1bL
  68. #define GXEMUL_FB_KEY_F6 0x37315b1bL
  69. #define GXEMUL_FB_KEY_F7 0x38315b1bL
  70. #define GXEMUL_FB_KEY_F8 0x39315b1bL
  71. #define GXEMUL_FB_KEY_F9 0x38325b1bL
  72. #define GXEMUL_FB_KEY_F10 0x39325b1bL
  73. #define GXEMUL_FB_KEY_F11 0x33325b1bL
  74. #define GXEMUL_FB_KEY_F12 0x34325b1bL
  75.  
  76.  
  77. /** Function keys start code (F1=0x101) */
  78. #define FUNCTION_KEYS 0x100
  79.  
  80. static irq_cmd_t gxemul_cmds[] = {
  81.     {
  82.         CMD_MEM_READ_1,
  83.         (void *) 0,
  84.         0,
  85.         2
  86.     }
  87. };
  88.  
  89. static irq_code_t gxemul_kbd = {
  90.     1,
  91.     gxemul_cmds
  92. };
  93.  
  94.  
  95. /** Framebuffer switched on. */
  96. static bool fb;
  97.  
  98.  
  99. /*
  100. // Please preserve this code (it can be used to determine scancodes)
  101. int to_hex(int v)
  102. {
  103.         return "0123456789ABCDEF"[v];
  104. }
  105. */
  106.  
  107.  
  108. /** Process data sent when a key is pressed (in no-framebuffer mode).
  109.  *  
  110.  *  @param keybuffer Buffer of pressed key.
  111.  *  @param scan_code Scan code.
  112.  *
  113.  *  @return Always 1.
  114.  */
  115. static int gxemul_kbd_process_no_fb(keybuffer_t *keybuffer, int scan_code)
  116. {
  117.     // holds at most 4 latest scan codes
  118.     static unsigned long buf = 0;
  119.  
  120.     // number of scan codes in #buf
  121.     static int count = 0;  
  122.  
  123.     /*
  124.     // Preserve for detecting scan codes.
  125.     keybuffer_push(keybuffer, to_hex((scan_code>>4)&0xf));
  126.     keybuffer_push(keybuffer, to_hex(scan_code&0xf));
  127.     keybuffer_push(keybuffer, 'X');
  128.     keybuffer_push(keybuffer, 'Y');
  129.     return 1;
  130.     */
  131.  
  132.     if (scan_code == '\r') {
  133.         scan_code = '\n';
  134.     }
  135.    
  136.     if (scan_code == GXEMUL_KEY_F5_F12_START_CODE) {
  137.         switch (buf) {
  138.         case GXEMUL_KEY_F5:
  139.             keybuffer_push(keybuffer,FUNCTION_KEYS | 5);
  140.             buf = count = 0;
  141.             return 1;
  142.         case GXEMUL_KEY_F6:
  143.             keybuffer_push(keybuffer,FUNCTION_KEYS | 6);
  144.             buf = count = 0;
  145.             return 1;
  146.         case GXEMUL_KEY_F7:
  147.             keybuffer_push(keybuffer,FUNCTION_KEYS | 7);
  148.             buf = count = 0;
  149.             return 1;
  150.         case GXEMUL_KEY_F8:
  151.             keybuffer_push(keybuffer,FUNCTION_KEYS | 8);
  152.             buf = count = 0;
  153.             return 1;
  154.         case GXEMUL_KEY_F9:
  155.             keybuffer_push(keybuffer,FUNCTION_KEYS | 9);
  156.             buf = count = 0;
  157.             return 1;
  158.         case GXEMUL_KEY_F10:
  159.             keybuffer_push(keybuffer,FUNCTION_KEYS | 10);
  160.             buf = count = 0;
  161.             return 1;
  162.         case GXEMUL_KEY_F11:
  163.             keybuffer_push(keybuffer,FUNCTION_KEYS | 11);
  164.             buf = count = 0;
  165.             return 1;
  166.         case GXEMUL_KEY_F12:
  167.             keybuffer_push(keybuffer,FUNCTION_KEYS | 12);
  168.             buf = count = 0;
  169.             return 1;
  170.         default:
  171.             keybuffer_push(keybuffer, buf & 0xff);
  172.             keybuffer_push(keybuffer, (buf >> 8)  & 0xff);
  173.             keybuffer_push(keybuffer, (buf >> 16) & 0xff);
  174.             keybuffer_push(keybuffer, (buf >> 24) & 0xff);
  175.             keybuffer_push(keybuffer, scan_code);
  176.             buf = count = 0;
  177.             return 1;
  178.         }
  179.     }
  180.  
  181.     // add to buffer
  182.     buf |= ((unsigned long) scan_code) << (8 * (count++));
  183.    
  184.     if ((buf & 0xff) != (GXEMUL_KEY_F1 & 0xff)) {
  185.         keybuffer_push(keybuffer, buf);
  186.         buf = count = 0;
  187.         return 1;
  188.     }
  189.  
  190.     if (count <= 1) {
  191.         return 1;
  192.     }
  193.  
  194.     if ((buf & 0xffff) != (GXEMUL_KEY_F1 & 0xffff)
  195.         && (buf & 0xffff) != (GXEMUL_KEY_F5 & 0xffff) ) {
  196.  
  197.         keybuffer_push(keybuffer, buf & 0xff);
  198.         keybuffer_push(keybuffer, (buf >> 8) &0xff);
  199.         buf = count = 0;
  200.         return 1;
  201.     }
  202.  
  203.     if (count <= 2) {
  204.         return 1;
  205.     }
  206.  
  207.     switch (buf) {
  208.     case GXEMUL_KEY_F1:
  209.         keybuffer_push(keybuffer,FUNCTION_KEYS | 1);
  210.         buf = count = 0;
  211.         return 1;
  212.     case GXEMUL_KEY_F2:
  213.         keybuffer_push(keybuffer,FUNCTION_KEYS | 2);
  214.         buf = count = 0;
  215.         return 1;
  216.     case GXEMUL_KEY_F3:
  217.         keybuffer_push(keybuffer,FUNCTION_KEYS | 3);
  218.         buf = count = 0;
  219.         return 1;
  220.     case GXEMUL_KEY_F4:
  221.         keybuffer_push(keybuffer,FUNCTION_KEYS | 4);
  222.         buf = count = 0;
  223.         return 1;
  224.     }
  225.  
  226.  
  227.     if ((buf & 0xffffff) != (GXEMUL_KEY_F5 & 0xffffff)
  228.         && (buf & 0xffffff) != (GXEMUL_KEY_F9 & 0xffffff)) {
  229.  
  230.         keybuffer_push(keybuffer, buf & 0xff);
  231.         keybuffer_push(keybuffer, (buf >> 8) & 0xff);
  232.         keybuffer_push(keybuffer, (buf >> 16) & 0xff);
  233.         buf = count = 0;
  234.         return 1;
  235.     }
  236.  
  237.     if (count <= 3) {
  238.         return 1;
  239.     }
  240.    
  241.     switch (buf) {
  242.     case GXEMUL_KEY_F5:
  243.     case GXEMUL_KEY_F6:
  244.     case GXEMUL_KEY_F7:
  245.     case GXEMUL_KEY_F8:
  246.     case GXEMUL_KEY_F9:
  247.     case GXEMUL_KEY_F10:
  248.     case GXEMUL_KEY_F11:
  249.     case GXEMUL_KEY_F12:
  250.         return 1;
  251.     default:
  252.         keybuffer_push(keybuffer, buf & 0xff);
  253.         keybuffer_push(keybuffer, (buf >> 8)  & 0xff);
  254.         keybuffer_push(keybuffer, (buf >> 16) & 0xff);
  255.         keybuffer_push(keybuffer, (buf >> 24) & 0xff);
  256.         buf = count = 0;
  257.         return 1;
  258.     }
  259.  
  260.     return 1;
  261. }
  262.  
  263.  
  264. /** Process data sent when a key is pressed (in framebuffer mode).
  265.  *  
  266.  *  @param keybuffer Buffer of pressed keys.
  267.  *  @param scan_code Scan code.
  268.  *
  269.  *  @return Always 1.
  270.  */
  271. static int gxemul_kbd_process_fb(keybuffer_t *keybuffer, int scan_code)
  272. {
  273.     // holds at most 4 latest scan codes
  274.     static unsigned long buf = 0;
  275.  
  276.     // number of scan codes in #buf
  277.     static int count = 0;  
  278.  
  279.     /*
  280.     // Please preserve this code (it can be used to determine scancodes)
  281.     keybuffer_push(keybuffer, to_hex((scan_code>>4)&0xf));
  282.     keybuffer_push(keybuffer, to_hex(scan_code&0xf));
  283.     keybuffer_push(keybuffer, ' ');
  284.     keybuffer_push(keybuffer, ' ');
  285.     return 1;
  286.     */
  287.    
  288.     if (scan_code == '\r') {
  289.         scan_code = '\n';
  290.     }
  291.    
  292.     // add to buffer
  293.     buf |= ((unsigned long) scan_code) << (8*(count++));
  294.    
  295.    
  296.     if ((buf & 0xff) != (GXEMUL_FB_KEY_F1 & 0xff)) {
  297.         keybuffer_push(keybuffer, buf);
  298.         buf = count = 0;
  299.         return 1;
  300.     }
  301.  
  302.     if (count <= 1) {
  303.         return 1;
  304.     }
  305.  
  306.     if ((buf & 0xffff) != (GXEMUL_FB_KEY_F1 & 0xffff)) {
  307.         keybuffer_push(keybuffer, buf & 0xff);
  308.         keybuffer_push(keybuffer, (buf >> 8) &0xff);
  309.         buf = count = 0;
  310.         return 1;
  311.     }
  312.  
  313.     if (count <= 2) {
  314.         return 1;
  315.     }
  316.  
  317.     if ((buf & 0xffffff) != (GXEMUL_FB_KEY_F1 & 0xffffff)
  318.         && (buf & 0xffffff) != (GXEMUL_FB_KEY_F5 & 0xffffff)
  319.         && (buf & 0xffffff) != (GXEMUL_FB_KEY_F9 & 0xffffff)) {
  320.  
  321.         keybuffer_push(keybuffer, buf & 0xff);
  322.         keybuffer_push(keybuffer, (buf >> 8) & 0xff);
  323.         keybuffer_push(keybuffer, (buf >> 16) & 0xff);
  324.         buf = count = 0;
  325.         return 1;
  326.     }
  327.  
  328.     if (count <= 3) {
  329.         return 1;
  330.     }
  331.  
  332.     switch (buf) {
  333.     case GXEMUL_FB_KEY_F1:
  334.         keybuffer_push(keybuffer,FUNCTION_KEYS | 1 );
  335.         buf = count = 0;
  336.         return 1;
  337.     case GXEMUL_FB_KEY_F2:
  338.         keybuffer_push(keybuffer,FUNCTION_KEYS | 2 );
  339.         buf = count = 0;
  340.         return 1;
  341.     case GXEMUL_FB_KEY_F3:
  342.         keybuffer_push(keybuffer,FUNCTION_KEYS | 3 );
  343.         buf = count = 0;
  344.         return 1;
  345.     case GXEMUL_FB_KEY_F4:
  346.         keybuffer_push(keybuffer,FUNCTION_KEYS | 4 );
  347.         buf = count = 0;
  348.         return 1;
  349.     case GXEMUL_FB_KEY_F5:
  350.         keybuffer_push(keybuffer,FUNCTION_KEYS | 5 );
  351.         buf = count = 0;
  352.         return 1;
  353.     case GXEMUL_FB_KEY_F6:
  354.         keybuffer_push(keybuffer,FUNCTION_KEYS | 6 );
  355.         buf = count = 0;
  356.         return 1;
  357.     case GXEMUL_FB_KEY_F7:
  358.         keybuffer_push(keybuffer,FUNCTION_KEYS | 7 );
  359.         buf = count = 0;
  360.         return 1;
  361.     case GXEMUL_FB_KEY_F8:
  362.         keybuffer_push(keybuffer,FUNCTION_KEYS | 8 );
  363.         buf = count = 0;
  364.         return 1;
  365.     case GXEMUL_FB_KEY_F9:
  366.         keybuffer_push(keybuffer,FUNCTION_KEYS | 9 );
  367.         buf = count = 0;
  368.         return 1;
  369.     case GXEMUL_FB_KEY_F10:
  370.         keybuffer_push(keybuffer,FUNCTION_KEYS | 10 );
  371.         buf = count = 0;
  372.         return 1;
  373.     case GXEMUL_FB_KEY_F11:
  374.         keybuffer_push(keybuffer,FUNCTION_KEYS | 11 );
  375.         buf = count = 0;
  376.         return 1;
  377.     case GXEMUL_FB_KEY_F12:
  378.         keybuffer_push(keybuffer,FUNCTION_KEYS | 12 );
  379.         buf = count = 0;
  380.         return 1;
  381.     default:
  382.         keybuffer_push(keybuffer, buf & 0xff );
  383.         keybuffer_push(keybuffer, (buf >> 8)  & 0xff);
  384.         keybuffer_push(keybuffer, (buf >> 16) & 0xff);
  385.         keybuffer_push(keybuffer, (buf >> 24) & 0xff);
  386.         buf = count = 0;
  387.         return 1;
  388.     }
  389.  
  390.     return 1;
  391. }
  392.  
  393.  
  394. /** Initializes keyboard handler. */
  395. int kbd_arch_init(void)
  396. {
  397.     fb = (sysinfo_value("fb.kind") == 1);
  398.     gxemul_cmds[0].addr = (void *) sysinfo_value("kbd.address.virtual");
  399.     ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), 0, &gxemul_kbd);
  400.     return 0;
  401. }
  402.  
  403.  
  404. /** Process data sent when a key is pressed.
  405.  *  
  406.  *  @param keybuffer Buffer of pressed keys.
  407.  *  @param call      IPC call.
  408.  *
  409.  *  @return Always 1.
  410.  */
  411. int kbd_arch_process(keybuffer_t *keybuffer, ipc_call_t *call)
  412. {
  413.     int scan_code = IPC_GET_ARG2(*call);
  414.  
  415.     if (fb) {
  416.         return gxemul_kbd_process_fb(keybuffer, scan_code);
  417.     } else {
  418.         return gxemul_kbd_process_no_fb(keybuffer, scan_code);
  419.     }
  420.  
  421. }
  422.  
  423. /** @}
  424.  */
  425.