function KeyboardMouse(options) {
  function clearKeymap() {
    for (var i = 0; i < me.kmap.length; i++) me.kmap[i] = !1;
  }
  var me = this, canvas = options.canvas, worker = options.worker;
  this.version = options.ilo_version || 5, this.kbdLayoutId = "en", this.mousex = 0,
  this.mousey = 0, this.mouse_ax = 0, this.mouse_ay = 0, this.mouse_btn = 0, this.kmap = Array(256);
  var en_kbd_map = [ 0, 0, 0, 72, 0, 0, 0, 0, 42, 43, 0, 0, 216, 40, 0, 0, 0, 0, 0, 72, 57, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 44, 75, 78, 77, 74, 80, 82, 79, 81, 0, 0, 0, 70, 73, 76, 0, 39, 30, 31, 32, 33, 34, 35, 36, 37, 38, 37, 51, 0, 0, 0, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 227, 231, 101, 0, 0, 98, 89, 90, 91, 92, 93, 94, 95, 96, 97, 85, 87, 0, 86, 99, 84, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 229, 224, 228, 226, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 46, 54, 45, 55, 56, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 49, 48, 52, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255 ], ja_kbd_map = [ 0, 0, 0, 72, 0, 0, 0, 0, 42, 43, 0, 0, 216, 40, 0, 0, 0, 0, 0, 72, 57, 0, 0, 0, 0, 53, 0, 41, 138, 139, 0, 0, 44, 75, 78, 77, 74, 80, 82, 79, 81, 0, 0, 0, 70, 73, 76, 0, 39, 30, 31, 32, 33, 34, 35, 36, 37, 38, 37, 51, 0, 0, 0, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 227, 231, 101, 0, 0, 98, 89, 90, 91, 92, 93, 94, 95, 96, 97, 85, 87, 0, 86, 99, 84, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 229, 224, 228, 226, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 51, 54, 45, 55, 56, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 137, 50, 46, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 136, 53, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255 ], locations = {
    0: "",
    1: "Left",
    2: "Right",
    3: "Numpad"
  }, keyboardCodes = {
    KeyA: 4,
    KeyB: 5,
    KeyC: 6,
    KeyD: 7,
    KeyE: 8,
    KeyF: 9,
    KeyG: 10,
    KeyH: 11,
    KeyI: 12,
    KeyJ: 13,
    KeyK: 14,
    KeyL: 15,
    KeyM: 16,
    KeyN: 17,
    KeyO: 18,
    KeyP: 19,
    KeyQ: 20,
    KeyR: 21,
    KeyS: 22,
    KeyT: 23,
    KeyU: 24,
    KeyV: 25,
    KeyW: 26,
    KeyX: 27,
    KeyY: 28,
    KeyZ: 29,
    Digit1: 30,
    Digit2: 31,
    Digit3: 32,
    Digit4: 33,
    Digit5: 34,
    Digit6: 35,
    Digit7: 36,
    Digit8: 37,
    Digit9: 38,
    Digit0: 39,
    Enter: 40,
    Escape: 41,
    Backspace: 42,
    Tab: 43,
    Space: 44,
    Minus: 45,
    Equal: 46,
    BracketLeft: 47,
    BracketRight: 48,
    Backslash: 49,
    IntlHash: 50,
    Semicolon: 51,
    Quote: 52,
    Backquote: 53,
    Comma: 54,
    Period: 55,
    Slash: 56,
    CapsLock: 57,
    F1: 58,
    F2: 59,
    F3: 60,
    F4: 61,
    F5: 62,
    F6: 63,
    F7: 64,
    F8: 65,
    F9: 66,
    F10: 67,
    F11: 68,
    F12: 69,
    PrintScreen: 70,
    ScrollLock: 71,
    Pause: 72,
    Insert: 73,
    Home: 74,
    PageUp: 75,
    Delete: 76,
    End: 77,
    PageDown: 78,
    ArrowRight: 79,
    ArrowLeft: 80,
    ArrowDown: 81,
    ArrowUp: 82,
    NumLock: 83,
    NumpadDivide: 84,
    NumpadMultiply: 85,
    NumpadSubtract: 86,
    NumpadAdd: 87,
    NumpadEnter: 88,
    Numpad1: 89,
    Numpad2: 90,
    Numpad3: 91,
    Numpad4: 92,
    Numpad5: 93,
    Numpad6: 94,
    Numpad7: 95,
    Numpad8: 96,
    Numpad9: 97,
    Numpad0: 98,
    NumpadDecimal: 99,
    IntlBackslash: 100,
    ContextMenu: 101,
    Power: 102,
    NumpadEqual: 103,
    F13: 104,
    F14: 105,
    F15: 106,
    F16: 107,
    F17: 108,
    F18: 109,
    F19: 110,
    F20: 111,
    F21: 112,
    F22: 113,
    F23: 114,
    F24: 115,
    Open: 116,
    Help: 117,
    Props: 118,
    Select: 119,
    Stop: 120,
    Again: 121,
    Undo: 122,
    Cut: 123,
    Copy: 124,
    Paste: 125,
    Find: 126,
    AudioVolumeMute: 127,
    AudioVolumeUp: 128,
    AudioVolumeDown: 129,
    NumpadComma: 133,
    IntlRo: 135,
    KanaMode: 136,
    IntlYen: 137,
    Convert: 138,
    NonConvert: 139,
    Lang1: 144,
    Lang2: 145,
    Lang3: 146,
    Lang4: 147,
    Lang5: 148,
    Lang6: 149,
    Lang7: 150,
    Lang8: 151,
    Lang9: 152,
    NumpadParenLeft: 182,
    NumpadParenRight: 183,
    NumpadBackspace: 187,
    NumpadMemoryStore: 208,
    NumpadMemoryRecall: 209,
    NumpadMemoryClear: 210,
    NumpadMemoryAdd: 211,
    NumpadMemorySubtract: 212,
    NumpadClear: 216,
    NumpadClearEntry: 217,
    ControlLeft: 224,
    ShiftLeft: 225,
    AltLeft: 226,
    OSLeft: 227,
    MetaLeft: 227,
    ControlRight: 228,
    ShiftRight: 229,
    AltRight: 230,
    OSRight: 231,
    MetaRight: 231
  };
  this.setKbdLayoutId = function(id) {
    switch (id) {
     case "ja":
      me.kbdLayoutId = "ja", me.jskey_to_hid = ja_kbd_map;
      break;

     case "zh":
     case "fr":
      $.log("'" + id + "' is not a supported keyboard type.");

     case "en":
     default:
      me.kbdLayoutId = "en", me.jskey_to_hid = en_kbd_map;
    }
    return iLO.setCookie("UserPref", [ "kbd_type", me.kbdLayoutId ]), clearKeymap(),
    me.kbdLayoutId;
  }, this.setKbdLayoutId(iLO.getCookie("UserPref", "kbd_type")), this.send_vkey = function(code, down) {
    var old, i, hid = keyboardCodes[code], j = 0, kcmd = [ 0, 0, 0, 0, 0, 0, 0, 0 ];
    if (hid && (old = me.kmap[hid], me.kmap[hid] = down, old !== down)) {
      for (i = 0; 256 > i; i++) me.kmap[i] && (224 === (224 & i) ? kcmd[0] |= 1 << i - 224 : (kcmd[2 + j] = i,
      6 === ++j && (j = 5)));
      worker.kbd_send(kcmd);
    }
  }, this.on_key = function(evt) {
    var old, i, down = "keydown" === evt.type ? !0 : !1, code = evt.code || evt.originalEvent.code, key = evt.key || evt.originalEvent.key, loc = evt.location || evt.originalEvent.location, hid = code && keyboardCodes[code] ? keyboardCodes[code] : me.jskey_to_hid[evt.keyCode], j = 0, kcmd = [ 0, 0, 0, 0, 0, 0, 0, 0 ];
    if (!code) switch (key) {
     case "Control":
     case "Shift":
     case "Alt":
      loc > 0 && 3 > loc && (hid = keyboardCodes[key + locations[loc]]);
      break;

     case "Win":
     case "Meta":
      loc > 0 && 3 > loc && (hid = keyboardCodes["OS" + locations[loc]]);
    }
    if (old = me.kmap[hid], me.kmap[hid] = down, old !== down) {
      for (i = 0; 256 > i; i++) me.kmap[i] && (224 === (224 & i) ? kcmd[0] |= 1 << i - 224 : (kcmd[2 + j] = i,
      6 === ++j && (j = 5)));
      worker.kbd_send(kcmd);
    }
    return evt.cancelable = !0, evt.stopPropagation(), evt.preventDefault(), evt.returnValue = !1,
    !1;
  }, this.on_mouse_button = function(evt) {
    var mcmd = [ 255, 0, 0 ], b = 0;
    if (2 === me.version) switch (evt.button) {
     case 0:
      b = 4;
      break;

     case 1:
      b = 2;
      break;

     case 2:
      b = 1;
    } else switch (evt.button) {
     case 0:
      b = 1;
      break;

     case 1:
      b = 4;
      break;

     case 2:
      b = 2;
    }
    return "mousedown" === evt.type ? (mcmd[1] = 209, mcmd[2] = b, me.mouse_btn |= b) : "mouseup" === evt.type ? (mcmd[1] = 210,
    mcmd[2] = b, me.mouse_btn &= ~b) : $.log("Unknown mouse event: " + evt), me.mouse_send(0, 0, me.mouse_ax, me.mouse_ay, me.mouse_btn, 0) ? !1 : (worker.mouse_send(mcmd),
    !1);
  }, this.mouse_send = function(rx, ry, ax, ay, button, wheel) {
    if (2 === this.version) return !1;
    var buf = [ 2, 0, 255 & ax, ax >> 8, 255 & ay, ay >> 8, 255 & rx, 255 & ry, button, wheel ];
    return worker.mouse_send(buf), !0;
  }, this.on_mouse_move = function(evt) {
    var ax, ay, dx, dy, mcmd = [ 255, 208, 0, 0, 0, 0, 0, 0 ], $canvas = $(canvas), offset = $canvas.offset(), width = $canvas.width(), height = $canvas.height(), x = evt.pageX - offset.left, y = evt.pageY - offset.top;
    return ax = ~~(3e3 * x / width), ay = ~~(3e3 * y / height), 0 > ax && (ax = 0),
    0 > ay && (ay = 0), dx = x - me.mousex, me.mousex = x, dy = -(y - me.mousey), me.mousey = y,
    me.mouse_ax = ax, me.mouse_ay = ay, -127 > dx && (dx = -127), dx > 127 && (dx = 127),
    -127 > dy && (dy = -127), dy > 127 && (dy = 127), me.mouse_send(dx, dy, ax, ay, me.mouse_btn, 0) ? void 0 : (mcmd[2] = 255 & dx,
    mcmd[3] = 255 & dy, mcmd[4] = ax >> 8, mcmd[5] = 255 & ax, mcmd[6] = ay >> 8, mcmd[7] = 255 & ay,
    worker.mouse_send(mcmd), !1);
  }, this.on_mouse_wheel = function(evt) {
    return me.mouse_send(0, 0, me.mouse_ax, me.mouse_ay, me.mouse_btn, 255 & evt.deltaY),
    !1;
  }, this.mouseenter = function(evt) {
    var $canvas = $(canvas);
    $canvas.attr("contentEditable", "true").trigger("focus"), $canvas.attr("contentEditable", "false"),
    $(document).on("keydown", me.on_key), $(document).on("keyup", me.on_key);
  }, this.mouseleave = function(evt) {
    $(document).off("keydown", me.on_key), $(document).off("keyup", me.on_key);
  }, this.no_op = function() {
    return !1;
  }, this.bind_all = function() {
    $(document).ready(function() {
      me.unbind_all();
      var $canvas = $(canvas);
      $canvas.on("mouseover", me.mouseenter), $canvas.on("mouseout", me.mouseleave), $canvas.on("mousemove", me.on_mouse_move),
      $canvas.on("mousedown", me.on_mouse_button), $canvas.on("mouseup", me.on_mouse_button),
      $canvas.on("mousewheel", me.on_mouse_wheel), $canvas.on("keydown", me.on_key), $canvas.on("keyup", me.on_key),
      $canvas.on("contextmenu", me.no_op), $(document, ".hrc-dialog-window").on("blur focusout", me.all_keys_up),
      $(document, ".hrc-dialog-window").on("help", me.no_op);
    });
  }, this.unbind_all = function() {
    var $canvas = $(canvas);
    $canvas.off("mouseover", me.mouseenter), $canvas.off("mouseout", me.mouseleave),
    $canvas.off("mousemove", me.on_mouse_move), $canvas.off("mousedown", me.on_mouse_button),
    $canvas.off("mouseup", me.on_mouse_button), $canvas.off("mousewheel", me.on_mouse_wheel),
    $canvas.off("keydown", me.on_key), $canvas.off("keyup", me.on_key), $(document, ".hrc-dialog-window").off("blur focusout", me.all_keys_up),
    $(document, ".hrc-dialog-window").off("help", me.no_op);
  };
}