Contribute
Register

Lenovo V330 - 15ikb

Status
Not open for further replies.
@RehabMan

Im doing the keyboard map right now but im facing a weird problem with F10 (Projector) key, it is generating me two codes:
Code:
kernel: (VoodooPS2Keyboard) ApplePS2Keyboard: sending key e05b=3a up
kernel: (VoodooPS2Keyboard) ApplePS2Keyboard: sending key e05b=3a down
kernel: (VoodooPS2Keyboard) ApplePS2Keyboard: sending key 19=23 down
kernel: (VoodooPS2Keyboard) ApplePS2Keyboard: sending key 19=23 up
How do i fix this problem, I wanted to map it to video/mirror toggle function on macOS.

It is a macro key (e05b is the Windows key, 19 is P... Windows+P)... you can use Macro Inversion to turn it into a single key again.
Look at the u430 repo.

Same goes for F9 (Lock) "On windows 10 it used to lock laptop to login in screen"
Code:
kernel: (VoodooPS2Keyboard) ApplePS2Keyboard: sending key e05b=3a up
kernel: (VoodooPS2Keyboard) ApplePS2Keyboard: sending key e05b=3a down
kernel: (VoodooPS2Keyboard) ApplePS2Keyboard: sending key 26=25 down
kernel: (VoodooPS2Keyboard) ApplePS2Keyboard: sending key 26=25 up
So as you can see, it does send the "e05b=3a" first for both of the mentioned keys then just the second scan code is different.
Any idea on these situations ?

Same here, but a macro for Windows+L.
 
It is a macro key (e05b is the Windows key, 19 is P... Windows+P)... you can use Macro Inversion to turn it into a single key again.
Look at the u430 repo.



Same here, but a macro for Windows+L.
Can you please extract the data a bit for me so i can understand better where the replacements should take place:
From your Y50 repo
Code:
"Macro Inversion", Package()
{
Package(){},
//F3
Buffer() { 0xff, 0xff, 0x02, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5b, 0x01, 0x19 }, //e06a
Buffer() { 0xff, 0xff, 0x02, 0xea, 0x00, 0x00, 0x00, 0x00, 0x01, 0x99, 0x02, 0xdb }, //e0ea
//F9
Buffer() { 0xff, 0xff, 0x02, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5b, 0x01, 0x17 }, //e06b
Buffer() { 0xff, 0xff, 0x02, 0xeb, 0x00, 0x00, 0x00, 0x00, 0x01, 0x97, 0x02, 0xdb }, //e0eb
//F10
Buffer() { 0xff, 0xff, 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5b, 0x01, 0x21 }, //e06c
Buffer() { 0xff, 0xff, 0x02, 0xec, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa1, 0x02, 0xdb }, //e0ec
//F11
Buffer() { 0xff, 0xff, 0x02, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38, 0x01, 0x1d, 0x01, 0x0f }, //e06d
Buffer() { 0xff, 0xff, 0x02, 0xed, 0x00, 0x00, 0x00, 0x00, 0x01, 0xb8, 0x01, 0x9d, 0x01, 0x8f }, //e0ed
},
or for U430 since it has a FN + XX key combo which might better explanation so I can replace Windows + L & Windows + P:
Code:
"Macro Inversion", Package()
{
Package(){},
// Fn+F4
Buffer() { 0xff, 0xff, 0x02, 0x64, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38, 0x01, 0x3e },
Buffer() { 0xff, 0xff, 0x02, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x01, 0xbe, 0x01, 0xb8 },
// F5 (without Fn)
Buffer() { 0xff, 0xff, 0x02, 0x65, 0x01, 0x00, 0x00, 0x00, 0x01, 0x3f },
Buffer() { 0xff, 0xff, 0x02, 0xe5, 0x01, 0x00, 0x00, 0x00, 0x01, 0xbf },
// Fn+Ctrl+F6
Buffer() { 0xff, 0xff, 0x02, 0x27, 0x00, 0x03, 0xff, 0xff, 0x02, 0x66 },
Buffer() { 0xff, 0xff, 0x02, 0xa7, 0x00, 0x03, 0xff, 0xff, 0x02, 0xe6 },
// Ctrl+F6
Buffer() { 0xff, 0xff, 0x02, 0x27, 0x00, 0x03, 0xff, 0xff, 0x02, 0x40 },
Buffer() { 0xff, 0xff, 0x02, 0xa7, 0x00, 0x03, 0xff, 0xff, 0x02, 0xc0 },
// Fn+F8
Buffer() { 0xff, 0xff, 0x02, 0x68, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1d, 0x01, 0x38, 0x01, 0x0f },
Buffer() { 0xff, 0xff, 0x02, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x01, 0xb8, 0x02, 0x9d },
// Fn+F10
Buffer() { 0xff, 0xff, 0x02, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5b, 0x01, 0x19 },
Buffer() { 0xff, 0xff, 0x02, 0xea, 0x00, 0x00, 0x00, 0x00, 0x01, 0x99, 0x02, 0xdb },
},
 
Can you please extract the data a bit for me so i can understand better where the replacements should take place:
From your Y50 repo
Code:
"Macro Inversion", Package()
{
Package(){},
//F3
Buffer() { 0xff, 0xff, 0x02, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5b, 0x01, 0x19 }, //e06a
Buffer() { 0xff, 0xff, 0x02, 0xea, 0x00, 0x00, 0x00, 0x00, 0x01, 0x99, 0x02, 0xdb }, //e0ea
//F9
Buffer() { 0xff, 0xff, 0x02, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5b, 0x01, 0x17 }, //e06b
Buffer() { 0xff, 0xff, 0x02, 0xeb, 0x00, 0x00, 0x00, 0x00, 0x01, 0x97, 0x02, 0xdb }, //e0eb
//F10
Buffer() { 0xff, 0xff, 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5b, 0x01, 0x21 }, //e06c
Buffer() { 0xff, 0xff, 0x02, 0xec, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa1, 0x02, 0xdb }, //e0ec
//F11
Buffer() { 0xff, 0xff, 0x02, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38, 0x01, 0x1d, 0x01, 0x0f }, //e06d
Buffer() { 0xff, 0xff, 0x02, 0xed, 0x00, 0x00, 0x00, 0x00, 0x01, 0xb8, 0x01, 0x9d, 0x01, 0x8f }, //e0ed
},
or for U430 since it has a FN + XX key combo which might better explanation so I can replace Windows + L & Windows + P:
Code:
"Macro Inversion", Package()
{
Package(){},
// Fn+F4
Buffer() { 0xff, 0xff, 0x02, 0x64, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38, 0x01, 0x3e },
Buffer() { 0xff, 0xff, 0x02, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x01, 0xbe, 0x01, 0xb8 },
// F5 (without Fn)
Buffer() { 0xff, 0xff, 0x02, 0x65, 0x01, 0x00, 0x00, 0x00, 0x01, 0x3f },
Buffer() { 0xff, 0xff, 0x02, 0xe5, 0x01, 0x00, 0x00, 0x00, 0x01, 0xbf },
// Fn+Ctrl+F6
Buffer() { 0xff, 0xff, 0x02, 0x27, 0x00, 0x03, 0xff, 0xff, 0x02, 0x66 },
Buffer() { 0xff, 0xff, 0x02, 0xa7, 0x00, 0x03, 0xff, 0xff, 0x02, 0xe6 },
// Ctrl+F6
Buffer() { 0xff, 0xff, 0x02, 0x27, 0x00, 0x03, 0xff, 0xff, 0x02, 0x40 },
Buffer() { 0xff, 0xff, 0x02, 0xa7, 0x00, 0x03, 0xff, 0xff, 0x02, 0xc0 },
// Fn+F8
Buffer() { 0xff, 0xff, 0x02, 0x68, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1d, 0x01, 0x38, 0x01, 0x0f },
Buffer() { 0xff, 0xff, 0x02, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x8f, 0x01, 0xb8, 0x02, 0x9d },
// Fn+F10
Buffer() { 0xff, 0xff, 0x02, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5b, 0x01, 0x19 },
Buffer() { 0xff, 0xff, 0x02, 0xea, 0x00, 0x00, 0x00, 0x00, 0x01, 0x99, 0x02, 0xdb },
},

The data for the projector key (Fn+F10 on my u430) is this:
Code:
                    // Fn+F10
                    Buffer() { 0xff, 0xff, 0x02, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5b, 0x01, 0x19 },
                    Buffer() { 0xff, 0xff, 0x02, 0xea, 0x00, 0x00, 0x00, 0x00, 0x01, 0x99, 0x02, 0xdb },

First line deals with make codes (keys going down).
The 0x02 0x5b corresponds to the ps2 e05b, and the 0x01, 0x19 corresponds to the ps2 19.
The code it generates is e06a (corresponds to 0x02 0x6a).
Once you generate a unique ps2 code for the macro keys coming in, then you can assign to an ADB with the ADB map. You will see that also if you look at the "Custom ADB Map" for the u430.

The second line is similar but deals with translating the break codes (keys going up).

It gets pretty geeky and documenting it gave me a headache (so I didn't), but full details can extracted by reading the source code.
 
The data for the projector key (Fn+F10 on my u430) is this:
Code:
                    // Fn+F10
                    Buffer() { 0xff, 0xff, 0x02, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5b, 0x01, 0x19 },
                    Buffer() { 0xff, 0xff, 0x02, 0xea, 0x00, 0x00, 0x00, 0x00, 0x01, 0x99, 0x02, 0xdb },

First line deals with make codes (keys going down).
The 0x02 0x5b corresponds to the ps2 e05b, and the 0x01, 0x19 corresponds to the ps2 19.
The code it generates is e06a (corresponds to 0x02 0x6a).
Once you generate a unique ps2 code for the macro keys coming in, then you can assign to an ADB with the ADB map. You will see that also if you look at the "Custom ADB Map" for the u430.

The second line is similar but deals with translating the break codes (keys going up).

It gets pretty geeky and documenting it gave me a headache (so I didn't), but full details can extracted by reading the source code.
Thank you Rehabman,

Keyboard is fully mapped now & all keys working as desired & meant to:
Code:
// Lenovo V330-15IKB Keyboard Map

DefinitionBlock ("", "SSDT", 2, "V330", "_KBD", 0)
{
    External (_SB.PCI0.LPCB.EC0, DeviceObj)
    External (_SB.PCI0.LPCB.KBD0, DeviceObj)

    Scope (_SB.PCI0.LPCB.EC0)
    {
        Method (_Q1C, 0, NotSerialized) // Brightness Up
        {
            Notify (KBD0, 0x0406)
        }
        Method (_Q1D, 0, NotSerialized) // Brightness Down
        {
            Notify (KBD0, 0x0405)
        }
        Method (_Q3D, 0, NotSerialized) // Mic Mute (F16) - Siri
        {
            Notify (KBD0, 0x0367)
        }
        Method (_Q28, 0, NotSerialized) // Airplane Mode (F17) "Notification Center"
        {
            Notify (KBD0, 0x0368)
        }
    }

    Scope (_SB.PCI0.LPCB.KBD0)
    {
        Name (RMCF, Package ()
        {
            "Keyboard", 
            Package ()
            {
                "Breakless PS2", Package()
                {
                    Package(){}, //indicating array
                    "e06a", // Fn+F9
                    "e06b", // Fn+F10

                },
                "MaximumMacroTime", 25000000,
                "Macro Inversion", Package()
                {
                    Package(){},
                    // Fn+F9
                    Buffer() { 0xff, 0xff, 0x02, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5b, 0x01, 0x26 },
                    Buffer() { 0xff, 0xff, 0x02, 0xea, 0x00, 0x00, 0x00, 0x00, 0x01, 0x99, 0x02, 0xdb },
                    // Fn+F10
                    Buffer() { 0xff, 0xff, 0x02, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5b, 0x01, 0x19 },
                    Buffer() { 0xff, 0xff, 0x02, 0xeb, 0x00, 0x00, 0x00, 0x00, 0x01, 0x99, 0x02, 0xdb },
                },
                "Custom ADB Map", Package()
                {
                    Package(){},
                    "e06a=4f", // F18 (Lock) - System Preferences
                    "e06b=70", // video mirror
                },
                "Custom PS2 Map", 
                Package ()
                {
                    Package (){}, 
                    "e037=64" // PrtSC (F13) - Save selected area as screenshot
                }
            }
        })
    }
}
//EOF

Remaining to do list:

- Test HDMI Audio
- Test InjectEDID=true & add the custom EDID via config.plist instead of Display Override.
- Test USB-C Ports
- Correct Framebuffer Ports by order @0 for Internal Display, @1 HDMI, @2 VGA
- Find fan RPM "reading" code to have correct fan RPM show up on HWMonitor.app & other similar apps.
- Get a better hotpatch idea/proposal for Touchpad/VoodooI2C device.
- Have a final in general check by Rehabman to verify if everything is correct
- Merge all SSDTs via #include hotpatch method into a single SSDT-V330.aml

Done !
 
@RehabMan I can confirm that for me even InjectEDID=True & CustomEDID injected via config.plist does solve the laggy graphics & black screen after HDMI unplug.
So for me no need to Build a Display Override, removed it, working without it.
Checked the Overrides folder if system did create it by itself, folder not there, IOREG shows the correct injected edid by clover.
Success!.

Hopefully tomorrow I can complete the rest and starting using it normally.
 
@RehabMan I can confirm that for me even InjectEDID=True & CustomEDID injected via config.plist does solve the laggy graphics & black screen after HDMI unplug.
So for me no need to Build a Display Override, removed it, working without it.

Thanks for testing/confirming that fact.
And CustomEDID is much easier to use than a display override.
Probably those that claim CustomEDID doesn't work, weren't doing it correctly.
 
Thanks for testing/confirming that fact.
And CustomEDID is much easier to use than a display override.
Probably those that claim CustomEDID doesn't work, weren't doing it correctly.
I was curious to test that as well, because it always used to work, I was just saying "probably" broken if it would've been a clover bug so maybe thats why they were claiming,but no, it does work correctly, just changing the 20 byte in my case "95" to "A5" of MacBook Pro solved the problem for both methods.
 
@RehabMan
I think im very close into completing this laptop.
What i need from you now is to have more detailed look into PR files and see if you can find something wrong or that needs to be fixed or not necessary that needs to be removed.

Remaining Issues:
1.You were right about TPD0 device which is my Touchpad, I did hotpatch it, it works but now both TPDX (renamed as i wanted to disable it) and the TPD0 (the patched version for VoodooI2C) is showing up on IOreg.
What would be a better way to hotpatch it ?

2. I noticed that the volume Down/Volume Up buttons sometimes are acting weird.
I press once to increase the volume and the volume keeps going up on its own, I have to press one more time as it keeps going up, or same scenario with volume down, is this another known issue that needs to be patched (keyboard wise) ?.

3.USB-C Ports status for now is unknown as I don't have a USB-C device, I will take a look for it tomorrow, test the Google Pixel 2 of a friend to connect it and see if it connects to a XHC Port..
 

Attachments

  • debug_15485.zip
    1.7 MB · Views: 151
Remaining Issues:
1.You were right about TPD0 device which is my Touchpad, I did hotpatch it, it works but now both TPDX (renamed as i wanted to disable it) and the TPD0 (the patched version for VoodooI2C) is showing up on IOreg.
What would be a better way to hotpatch it ?

One method:
You could probably hotpatch just TPD0._STA to disable native TPD0...
So... rename _STA in TPD0 with an ACPI/DSDT/Patches entry:
Comment: Rename TPD0._STA to XSTA
TgtBridge: <5450 4430>
Find: <5f53 5441>
Replace: <5853 5441>
Then in your SSDT, provide an implementation of TPD0._STA that is zero.
Name(_SB.PCI0.I2C0.TPD0._STA, 0)

Then easy to provide the replacement TPD0 as TPDX (no need to rename TPD0 in DSDT to TPDX, as the name of the new object is not likely significant).

Second method:
You're really only changing two methods _DSM and _CRS... So you could rename both of those and replace them.
Two patches:
Comment: Rename TPD0._CRS to XCRS
TgtBridge: <5450 4430>
Find: <5f43 5253>
Replace: <5843 5253>

Comment: Rename TPD0._DSM to XDSM
TgtBridge: <5450 4430>
Find: <5f44 534d>
Replace: <5844 534d>

Then you can provide only the replacements in the SSDT-I2C. You will need to provide the appropriate External declarations to access all the identifiers used by the replacement _DSM and replacement _CRS, and also the modified SBFG, but using a different name.

Code:
    External(_SB.PCI0.I2C0, DeviceObj)
    External(_SB.PCI0.I2C0.TPD0, DeviceObj)
//etc
    Scope(_SB.PCI0.I2C0)
    {
         Scope(TPD0)
         {
            // SBFX is modified SBFG
            Name (SBFX, ResourceTemplate ()
            {
                GpioInt(Level, ActiveLow, ExclusiveAndWake, PullDefault, 0x0000,
                    "\\_SB.PCI0.GPI0", 0x00, ResourceConsumer, ,
                   )
                   {   // Pin list
                       0x001B
                   }
            })
            Method (_DSM, 4, Serialized)  // _DSM: Device-Specific Method
            {
                If (LEqual (Arg0, HIDG)) // HIDG and others will need External
                {
                    Return (HIDD (Arg0, Arg1, Arg2, Arg3, HID2)) // HIDD/HID2 too
                }

                If (LEqual (Arg0, TP7G)) // TP7G as well/etc
                {
                    Return (TP7D (Arg0, Arg1, Arg2, Arg3, SBFB, SBFX)) // External for SBFB/TP7G, but using modified SBFX 
                }

                Return (Buffer (One)
                {
                     0x00                                          
                })
            }
            Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
            {
                Return (ConcatenateResTemplate (SBFB, SBFX))
            }
        }
    }

2. I noticed that the volume Down/Volume Up buttons sometimes are acting weird.
I press once to increase the volume and the volume keeps going up on its own, I have to press one more time as it keeps going up, or same scenario with volume down, is this another known issue that needs to be patched (keyboard wise) ?.

If they are breakless (eg. not sending break codes... sounds like it), add to "Breakless PS2".
 
Last edited:
One method:
You could probably hotpatch just TPD0._STA to disable native TPD0...
So... rename _STA in TPD0 with an ACPI/DSDT/Patches entry:
Comment: Rename TPD0._STA to XSTA
TgtBridge: <5450 4430>
Find: <5f53 5441>
Replace: <5853 5441>
Then in your SSDT, provide an implementation of TPD0._STA that is zero.
Name(_SB.PCI0.I2C0.TPD0._STA, 0)

Then easy to provide the replacement TPD0 as TPDX (no need to rename TPD0 in DSDT to TPDX, as the name of the new object is not likely significant).

Second method:
You're really only changing two methods _DSM and _CR... So you could rename both of those and replace them.
Two patches:
Comment: Rename TPD0._CRS to XCRS
TgtBridge: <5450 4430>
Find: <5f43 5253>
Replace: <5843 5253>

Comment: Rename TPD0._DSM to XDSM
Comment: Rename TPD0._CRS to XCRS
TgtBridge: <5450 4430>
Find: <5f44 534d>
Replace: <5844 534d>

Then you can provide only the replacements in the SSDT-I2C. You will need to provide the appropriate External declarations to access all the identifiers used by the replacement _DSM and replacement _CRS, and also the modified SBFG, but using a different name.

Code:
    External(_SB.PCI0.I2C0, DeviceObj)
    External(_SB.PCI0.I2C0.TPD0, DeviceObj)
//etc
    Scope(_SB.PCI0.I2C0)
    {
         Scope(TPD0)
         {
            // SBFX is modified SBFG
            Name (SBFX, ResourceTemplate ()
            {
                GpioInt(Level, ActiveLow, ExclusiveAndWake, PullDefault, 0x0000,
                    "\\_SB.PCI0.GPI0", 0x00, ResourceConsumer, ,
                   )
                   {   // Pin list
                       0x001B
                   }
            })
            Method (_DSM, 4, Serialized)  // _DSM: Device-Specific Method
            {
                If (LEqual (Arg0, HIDG)) // HIDG and others will need External
                {
                    Return (HIDD (Arg0, Arg1, Arg2, Arg3, HID2)) // HIDD/HID2 too
                }

                If (LEqual (Arg0, TP7G)) // TP7G as well/etc
                {
                    Return (TP7D (Arg0, Arg1, Arg2, Arg3, SBFB, SBFX)) // External for SBFB/TP7G, but using modified SBFX 
                }

                Return (Buffer (One)
                {
                     0x00                                          
                })
            }
            Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
            {
                Return (ConcatenateResTemplate (SBFB, SBFX))
            }
        }
    }



If they are breakless (eg. not sending break codes... sounds like it), add to "Breakless PS2".
Used second method: by just renaming _DSM & _CRS and providing the SSDT-I2C you added with the added externals.
Its working ok now. now only a single TPD0 appears on ioreg.

Also fixed the Volume Buttons by adding them on SSDT-KBD as Breakless.

All the necessary fixes are done on this laptop, except of untested USB-C ports which i will do tomorrow if i found someone with such device or Smartphone with USB-C port/charging cable

There some cosmetical things that i want to know if they can be done:

1. Card Reader into (About this Mac > System Information > Card Reader) says "this computer doesn't contain any Apple Internal Memory Card Readers, while it is natively supported, is it possible to add the informations there, not a must have thing but just for aesthetics.

2. FanRPM to show on HWMonitor.app & other similar apps.
So far I checked DSDT and couldn't find any related Offset , there is FANS, 8, but same scenario on my previous laptops, it's only a 8-bit offset, it's not large enough to contain the code for that.
The laptop does have a PTID device but not skilled enough to find out if its implemented or not.
If you can check this, the PR files are on Post #68, if you need newer ones, let me know.
 
Status
Not open for further replies.
Back
Top