Dell Precision M4800 VoodooPS2Controller 键盘/触控驱动修复过程

前言

对于Dell Precision M4800来说,触控板是ALPS,如果直接使用2017年2月发布的 DrHurt 版本的VoodooPS2Controller有以下bug:

  1. 数字锁定键Num Lock和LED指示灯,及功能切换不工作
  2. 亮度调节键被映射到Fn+F3Fn+Insert,Dell原生亮度键调节键Fn+Fn+不工作。
  3. 触控板开关键Fn+F5不工作
  4. SysRq/PrntScrn 不工作
  5. Pause(Fn+Insert)不工作
  6. 计算器键Calc不工作
  7. Ctrl+Alt+Delete不工作

 
因此,为了完美使用Big Sur,必须对其进行修复。

 

步骤一 准备工作

工欲善其事,必先利其器。为了修复工作,我们先做准备。

  1. 抓取DrHurt的远程仓库VoodooPS2Controller

    git clone git@github.com:DrHurt/OS-X-ALPS-DRIVER.git
    cd OS-X-ALPS-DRIVER
    
  2. Xcode打开项目VoodooPS2Controller.xcodeproj,并根据你的MacOS版本配置好环境,确保XcodeProduct/Build测试编译成功

  3. 下载ioio调试工具, 解压后将ioio二进制文件复制到目录/usr/local/bin/

    wget https://bitbucket.org/RehabMan/os-x-ioio/downloads/RehabMan-ioio-2014-0122.zip
    
  4. 为了动态抓取键位的PS code/ADB code映射我们先写个简单的脚本vim ioio_debug.sh, 复制以下几行代码然后在vim:wq保存退出

    #!/bin/sh
    ioio -s ApplePS2Keyboard LogScanCodes 1
    watch "sudo dmesg | grep ApplePS2Keyboard | tail -20"
    

    并赋予可执行权限 chmod 755 ./ioio_debug.sh。 (注:如没有watch命令需要安装 brew install watch)

  5. 终端下运行./ioio_debug.sh测试键位调试是否成功,成功后终端会有以下输出

    argv[0] = { ioio }
    argv[1] = { -s }
    argv[2] = { ApplePS2Keyboard }
    argv[3] = { LogScanCodes }
    argv[4] = { 1 }
    ioio: setting property 'ApplePS2Keyboard:LogScanCodes' as number to 1 (0x1)
    Password:
    

    键入本机管理员密码后, 然后按任意键屏幕上会按照你的键位返回对应的PS CodeADB Code,就会显示如下终端输出信息.

    [ 2585.028727]: ApplePS2Keyboard: sending key 31=2d down
    [ 2585.102607]: ApplePS2Keyboard: sending key 1f=1 down
    [ 2585.683917]: ApplePS2Keyboard: sending key 7=16 down
    [ 2585.846499]: ApplePS2Keyboard: sending key 5=15 down
    [ 2586.028108]: ApplePS2Keyboard: sending key 3=13 down
    

至此,准备工作完成,现在我们可以愉快的进行修复工作了。

 

步骤二 修复数字锁定键和小键盘映射

首先分析源码,得到键盘驱动源码主文件为VoodooPS2Keyboard.cpp

先在终端下运行./ioio_debug.sh,点按小键盘上的每一个按键,先得到数字锁定键的PS2键位码为 [0x45], 然后再得到数字小键盘区域每个按键得到数字小键盘PS2 Code映射表,并结合ApplePS2ToADBMap.h整理出一份Apple的ADB Code映射关系如下:

PS2 CodeADB Code(数字键)ADB Code(功能键)描述(数字键/功能键)
[0x48]0x5b0x7e8 up arrow
[0x50]0x540x7d2 down arrow
[0x4B]0x560x7b4 left arrow
[0x4D]0x580x7c6 right arrow
[0x52]0x520x920 insert / CDROM inject
[0x53]0x410x75. delete
[0x49]0x5c0x749 page up
[0x51]0x550x793 page down
[0x47]0x590x737 home
[0x4F]0x530x771 end

 

然后在 bool ApplePS2Keyboard::init(OSDictionary * dict) 函数加一行 “_numKeypadLocked = true;” 初始化_numKeypadLocked变量.

下一步再在 dispatchKeyboardEventWithPacket函数的switch (keyCode)方法中加入数字锁定键 [0x45] 的执行逻辑如下:

bool ApplePS2Keyboard::dispatchKeyboardEventWithPacket(const UInt8* packet)
{

    // handle special cases
    switch (keyCode)
    {

        // ......    

        case 0x45:  //num lock remapping
            keyCode = 0;

            //NUM LOCK fix For DELL Precision M4800
            if(goingDown)
            {
                setNumLockFeedback(_numKeypadLocked);
                _numKeypadLocked = !_numKeypadLocked;
            }

            // remap NUM PAD by NUMLOCK LED status
            if(!_numKeypadLocked)
            {
                _PS2ToADBMap[0x48] = 0x5b;     // 8 up arrow
                _PS2ToADBMap[0x50] = 0x54;     // 2 down arrow
                _PS2ToADBMap[0x4B] = 0x56;     // 4 left arrow
                _PS2ToADBMap[0x4D] = 0x58;     // 6 right arrow
                _PS2ToADBMap[0x52] = 0x52;     // 0 insert / CDROM inject
                _PS2ToADBMap[0x53] = 0x41;     // . delete
                _PS2ToADBMap[0x49] = 0x5c;     // 9 page up
                _PS2ToADBMap[0x51] = 0x55;     // 3 page down
                _PS2ToADBMap[0x47] = 0x59;     // 7 home
                _PS2ToADBMap[0x4F] = 0x53;     // 1 end
                
            }
            else
            {
                _PS2ToADBMap[0x48] = 0x7e;      // 8 up arrow
                _PS2ToADBMap[0x50] = 0x7d;      // 2 down arrow
                _PS2ToADBMap[0x4B] = 0x7b;      // 4 left arrow
                _PS2ToADBMap[0x4D] = 0x7c;      // 6 right arrow
                _PS2ToADBMap[0x52] = 0x92;      // 0 insert / CDROM inject
                _PS2ToADBMap[0x53] = 0x75;      // . delete
                _PS2ToADBMap[0x49] = 0x74;      // 9 page up
                _PS2ToADBMap[0x51] = 0x79;      // 3 page down
                _PS2ToADBMap[0x47] = 0x73;      // 7 home
                _PS2ToADBMap[0x4F] = 0x77;      // 1 end

            }
            break;

        // .......    
    }
}

最后在键盘初始化函数initkeyboard里加入一行代码 “setNumLockFeedback(_numKeypadLocked);” 启用开机小键盘数字键锁定Num Lock。

void ApplePS2Keyboard::initKeyboard()
{
    //......


    setNumLockFeedback(_numKeypadLocked);       //开机启用小键盘数字键锁定Num Lock,点亮LED指示灯


    //......
}

至此,数字小键盘按键修复完成。编译打包,将生成的ApplePS2Controller.kext复制到/EFI/OC/Kexts/替换掉原来的文件,重启测试成功。

 

步骤三 修复Dell原生亮度调节键Fn+/

第一步: 修改SSDT,启用 e005e006 Dell原生PS2键位码(此处为不再详述,可参详SSDT源码)。

第二步: 在VoodooPS2Keyboard-Info.plist的Custom ADB Map中加入以下映射将亮度调节键映射到F14F15

e005=6b;FN+down arrow to brightness down
e006=71;FN+up arrow to brightness up

原生亮度调节键修复完成。

 

步骤四 修复Dell原生触控板开关键Fn+F5

先在终端下运行./ioio_debug.sh,点按Fn+F5得到PS2键位码为 [e01e]
dispatchKeyboardEventWithPacket函数的switch (keyCode)方法中加入 [0x011e] (注:e0为扩展码标志,程序执行为0x01)的执行逻辑如下:

bool ApplePS2Keyboard::dispatchKeyboardEventWithPacket(const UInt8* packet)
{
    // handle special cases
    switch (keyCode)
    {

        case 0x011e:    // fn+f5 (Dell precision M4800)
        {
            unsigned origKeyCode = keyCode;
            keyCode = 0;
            if (!goingDown)
                break;
            if (!checkModifierState(kMaskLeftControl))
            {
                // get current enabled status, and toggle it
                bool enabled;
                _device->dispatchMouseMessage(kPS2M_getDisableTouchpad, &enabled);
                enabled = !enabled;
                _device->dispatchMouseMessage(kPS2M_setDisableTouchpad, &enabled);
                break;
            }
            if (origKeyCode != 0x011e)
                break; // do not fall through for 0x0128
            // fall through
        }

        // .......    
    }
}

编译打包,原生触控键修复完成。

 

步骤五 修复截屏键SysRq/PrntScrn

第一步: 先在终端下运行./ioio_debug.sh,点按Fn+End/Home得到PS2键位码为 [e037]

第二步: 分析源码,我们可以看到源码中有case 0x0137:的执行逻辑是将 [e037] 映射到了触控板控制开关。所以,我们将原这段代码删除或者注释掉。

//        case 0x0128:    // alternate that cannot fnkeys toggle (discrete trackpad toggle)
//        case 0x0137:    // prt sc/sys rq
//        {
//            unsigned origKeyCode = keyCode;
//            keyCode = 0;
//            if (!goingDown)
//                break;
//            if (!checkModifierState(kMaskLeftControl))
//            {
//                // get current enabled status, and toggle it
//                bool enabled;
//                _device->dispatchMouseMessage(kPS2M_getDisableTouchpad, &enabled);
//                enabled = !enabled;
//                _device->dispatchMouseMessage(kPS2M_setDisableTouchpad, &enabled);
//                break;
//            }
//            if (origKeyCode != 0x0137)
//                break; // do not fall through for 0x0128
//            // fall through
//        }

第三步: 在VoodooPS2Keyboard-Info.plist的Custom ADB Map中加入以下映射将SysRqPrntScrn映射到F13

e037=69;fn+Home/End to F13

第四步: 编译打包,将生成的ApplePS2Controller.kext复制到/EFI/OC/Kexts/替换掉原来的文件,重启。打开系统偏好设置>键盘>快捷键, 将截屏映射到SysRq/PrntScrnF13)。

 

步骤六 修复Pause(Fn+Insert)

第一步: 先在终端下运行./ioio_debug.sh,点按Fn+Insert得到PS2键位码为 [e045]

第二步: 在VoodooPS2Keyboard-Info.plist的Custom ADB Map中加入以下映射将Pause(Fn+Insert)映射到F18

第三步: 重复 步骤五 >第四步 将Pause(Fn+Insert)映射到你需要的功能键。

 

步骤七 修复 计算器键Calc

第一步: 先在终端下运行./ioio_debug.sh,点按Fn+Insert得到PS2键位码为 [e021]

第二步: 在VoodooPS2Keyboard-Info.plist的Custom ADB Map中加入以下映射将Calc映射到F19

第三步: 编译打包,将生成的ApplePS2Controller.kext复制到/EFI/OC/Kexts/替换掉原来的文件,重启

第四步:用MacOS字带的工具自动操作Calc(F19)映射到计算器app。

 

步骤八 修复Ctrl+Alt+Delete

第一步: 先在终端下运行./ioio_debug.sh,点按Delete得到PS2键位码为 [e053]

第二步: 分析源码VoodooPS2Keyboard.cpp, 得到case 0x0153 的运作逻辑是屏蔽了Ctrl+Alt+Delete以避免触发电源开关造成异常关机.
为了实现与Windows一样的锁屏效果,修改case 0x0153源码如下将Ctrl+Alt+Delete映射到Ctrl+Command+Q

bool ApplePS2Keyboard::dispatchKeyboardEventWithPacket(const UInt8* packet)
{
    // handle special cases
    switch (keyCode)
    {
        // .......   
        case 0x0153:    // delete
            
            // check for Ctrl+Alt+Delete? (three finger salute)
            if (checkModifierState(kMaskLeftControl|kMaskLeftAlt))
            {
                keyCode = 0;
                if (goingDown)
                {
                    // Note: If OS X thinks the Command and Control keys are down at the time of
                    //  receiving an ADB 0x7f (power button), it will unconditionaly and unsafely
                    //  reboot the computer, much like the old PC/AT Ctrl+Alt+Delete!
                    // That's why we make sure Control (0x3b) and Alt (0x37) are up!!
                    // then map to Ctrl + Command + Q (screen lock)
                    dispatchKeyboardEventX(0x37, true, now_abs);
                    dispatchKeyboardEventX(0x3b, true, now_abs);
                    dispatchKeyboardEventX(0xc, true, now_abs);
                    dispatchKeyboardEventX(0x7f, false, now_abs);
                }
                
                dispatchKeyboardEventX(0x37, false, now_abs);
                dispatchKeyboardEventX(0x3b, false, now_abs);
                dispatchKeyboardEventX(0xc, false, now_abs);
                dispatchKeyboardEventX(0x7f, false, now_abs);
            }

            break;
        // .......    
    }
}

第三步: 编译打包,将生成的ApplePS2Controller.kext复制到/EFI/OC/Kexts/替换掉原来的文件,重启

 
 
 

自此,历经步骤一步骤八,我们所有按键均修复完成,可以愉快地玩耍了。。。。。。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值