Contribute
Register

Battery Manager with Fix for Boot without Batteries

Status
Not open for further replies.
I don't see an issue there. What, exactly, isn't working?
Sorry, I wasted your's time. I have some confused about DesignCapacity: mWh and mAh.
 
hey rehab,

first off i'd like to thank you for all the work you've put into this. as a side note, your kext is the only one enabling me to boot with the battery plugged in and not KP'ing...
however, and even considering it is not essential, even though the kext works it does not have full functionality (does not show percentages, etc).
i was wondering if it could be a DSDT problem (mine was extracted, cleaned and compiled by myself: currently only shows one warning). if you have the time could you have a look?

thanks in advance
 

Attachments

  • screenshot_battery.jpg
    screenshot_battery.jpg
    234 KB · Views: 228
  • DSDT_asusn76vz.7z
    27.7 KB · Views: 96
hey rehab,

first off i'd like to thank you for all the work you've put into this. as a side note, your kext is the only one enabling me to boot with the battery plugged in and not KP'ing...
however, and even considering it is not essential, even though the kext works it does not have full functionality (does not show percentages, etc).
i was wondering if it could be a DSDT problem (mine was extracted, cleaned and compiled by myself: currently only shows one warning). if you have the time could you have a look?

thanks in advance

Certainly it is a DSDT issue. The biggest task to make the battery methods work is they have to access the EC with 8-bit access only. It is a limitation of 64-bit AppleACPIPlatform. I don't have a program to read *.7z and don't really want to install one, so if you want me to look at it, upload as a plain old ZIP.
 
Certainly it is a DSDT issue. The biggest task to make the battery methods work is they have to access the EC with 8-bit access only. It is a limitation of 64-bit AppleACPIPlatform. I don't have a program to read *.7z and don't really want to install one, so if you want me to look at it, upload as a plain old ZIP.

there you go. thanks as my DSDT knowledge is quite restricted
 

Attachments

  • DSDT_asusn76vz.zip
    32.3 KB · Views: 90
there you go. thanks as my DSDT knowledge is quite restricted

First thing to check would be to run the debug version of my AppleSmartBatteryManager.kext. Look for 'Battery' in Console.app, so you can see the debug output. Then you can see which methods are failing, and thus which ones need changes.

Then look at the methods (_STA, _BST, _BIF), probably in that order in the Device (BAT0) in your DSDT, especially if they are failing. For example, if you look at method _STA:
Code:
            Method (_STA, 0, NotSerialized)  // _STA: Status
            {
                If (^^LPCB.EC0.BATP (Zero))
                {
                    Return (0x1F)
                }
                Else
                {
                    Return (0x0F)
                }
            }

You can see there are two return paths. One returns 0x1F (battery present) and one returns 0x0F (battery not present). So you want to be sure the "battery present path" is the one being followed. If you look in the file for the BATP method, search for 'Method (BATP', you can see that it is returning DCPF (because we know it is being called with Zero):

Code:
        Method (BATP, 1, Serialized)
        {
            If (Arg0)
            {
                Return (DCP2)
            }
            Else
            {
                Return (DCPF)
            }
        }

And then search for DCPF and we can see it is an 8-bit field in SystemMemory RAMW. So it is probably ok, and will probably work.

A bit more complex will be the _BST method which returns information on the current charge/discharge state of the battery (page 504 ACPI 5.0 spec):

Code:
            Method (_BST, 0, NotSerialized)  // _BST: Battery Status
            {
                Store (Zero, Index (PBST, Zero))
                Store (Ones, Index (PBST, One))
                Store (Ones, Index (PBST, 0x02))
                Store (Ones, Index (PBST, 0x03))
                If (LNot (^^LPCB.EC0.BATP (Zero)))
                {
                    Return (PBST)
                }

                If (LEqual (^^LPCB.EC0.GBTT (Zero), 0xFF))
                {
                    Return (PBST)
                }

                If (MES4)
                {
                    Decrement (MES4)
                    Return (PBST)
                }

                BATO ()
                BATS (Zero)
                Store (^^LPCB.EC0.BSTS (), Local0)
                Store (^^LPCB.EC0.BCRT (), Local1)
                Store (^^LPCB.EC0.BRCP (), Local2)
                Store (^^LPCB.EC0.BVOT (), Local3)
                If (LNotEqual (Local0, Ones))
                {
                    If (LNotEqual (Local1, Ones))
                    {
                        If (LNotEqual (Local2, Ones))
                        {
                            If (LNotEqual (Local3, Ones))
                            {
                                FBST (Local0, Local1, Local2, Local3)
                                CBST ()
                            }
                        }
                    }
                }

                BATR ()
                Return (PBST)
            }

Here you can see this method makes several other method calls... BATP (already looked at above), GBTT, BATO, BATS, FBST, CBST, BATR. Each of these methods should be inspected to see what they access and if they are 8-bit access.

GBTT: You can see it accesses EB0T, EB1T, both 8-bit.
FBST: You can see it calls out to ACAP, which accesses ACPF, which is 8-bit. It also calls into CHGS, which would have to be examined (and anything it calls [BCHG and anything it calls/accesses... ECAV... EB1S which is 8-bit... which all seem fine)). In addition you can see access to EB0S, which is 8-bit. A little further down, you see:
Code:
                If (LEqual (PUNT, Zero))
                {
                    Multiply (Local1, ^^LPCB.EC0.B0DV, Local1)
                    Multiply (Local2, 0x0A, Local2)
                }

PUNT is just a Name, so it is fine. But B0DV, you can see is 16-bit, in a group of fields that appear to be 16-bit battery related:
Code:
...
                B0VL,   16, 
                B0RC,   16, 
                B0FC,   16, 
                B0MD,   16, 
                B0ST,   16, 
                B0CC,   16, 
                B0DC,   16, 
                B0DV,   16, 
                B1VL,   16, 
                B1RC,   16, 
                B1FC,   16, 
                B1MD,   16, 
                B1ST,   16, 
                B1CC,   16, 
                B1DC,   16, 
                B1DV,   16

It is likely all of those need to be changed to 8-bit, especially those that start with B0 (likely first battery). You could do the ones associated with the second battery, B1, but you probably don't as the second battery code, Device (BAT1), won't be getting used.

So next, you convert all the 16-bit fields to 8-bit pairs:
Code:
                //B0VL,   16, 
B0V0, 8, B0V1, 8,
                //B0RC,   16, 
B0R0, 8, B0R1, 8,
                //B0FC,   16, 
BOF0, 8, B0F1, 8,
                //B0MD,   16, 
B0M0, 8, B0M1, 8,
                //B0ST,   16, 
B0S0, 8, B0S1, 8,
                //B0CC,   16, 
B0C0, 8, B0C1, 8,
                //B0DC,   16, 
B0D0, 8, B0D1, 8,
                //B0DV,   16, 
B0E0, 8, B0E0, 8,  // using 'E' because we already used 'D' above...

All of these field names have to be 4-characters or less, so you need to come up with a naming method for each part. I think it is pretty obvious what I did there...

Next, you have to fix the code that accesses these fields. For example:
Code:
        Method (BVOT, 0, NotSerialized)
        {
            If (BSLF)
            {
                Store (B1VL, Local0)
            }
            Else
            {
                Store (B0VL, Local0)
            }

            Return (Local0)
        }

To:
Code:
        Method (BVOT, 0, NotSerialized)
        {
            If (BSLF)
            {
                Store (B1VL, Local0)
            }
            Else
            {
                //Store (B0VL, Local0)
                Store (B1B2(B0V0, B0V1), Local0)
            }

            Return (Local0)
        }

You will need to add the helper method B1B2 to assist:
Code:
    Method (B1B2, 2, NotSerialized)
    {
        ShiftLeft (Arg1, 0x08, Local0)
        Or (Arg0, Local0, Local0)
        Return (Local0)
    }

And that is just a little bit... Obviously you can see why we develop these as patches that are automated instead of editing by hand (see https://github.com/RehabMan/HP-ProBook-4x30s-DSDT-Patch, in particular 06_Battery.txt).

You can see it is a very time consuming process, and requires some "programming skills." It will probably take at least a couple of days to get it right. Hope this gives you enough clues to proceed on your own.
 
And that is just a little bit... Obviously you can see why we develop these as patches that are automated instead of editing by hand (see https://github.com/RehabMan/HP-ProBook-4x30s-DSDT-Patch, in particular 06_Battery.txt).

You can see it is a very time consuming process, and requires some "programming skills." It will probably take at least a couple of days to get it right. Hope this gives you enough clues to proceed on your own.

thanks for the detailed information. i'll be sure to study it extensively and i'll let you know of any progress.
 
thanks for the detailed information. i'll be sure to study it extensively and i'll let you know of any progress.

hello man, my laptop is Dell Latitude E6410
I try to install ACPIPlatomBattery and SmartBattery from you, but don't work and i try using VoodooBattery, it's also not work.

Must I patch DSDT for Battery to work? But i don't knows somethings about DSDT.

Can you help me patch DSDT for Battery?

Here my DSDT:
 

Attachments

  • DSDT.rar
    15.8 KB · Views: 91
hello man, my laptop is Dell Latitude E6410
I try to install ACPIPlatomBattery and SmartBattery from you, but don't work and i try using VoodooBattery, it's also not work.

Must I patch DSDT for Battery to work? But i don't knows somethings about DSDT.

Can you help me patch DSDT for Battery?

Here my DSDT:

You most likely need DSDT patches... almost everyone does for any ACPI battery manager.
You might search (here or google) for patches for your laptop or a similar Dell.

If you post as ZIP, I may take a quick look at it. But, sometimes it is a complex process involving trial & error with the actual machine.
 
Hey, perhaps you could add approximation for charge cycles for those of us who don't have extra or extended _BIF info to monitor the actual count?
I've originally stumbled upon this approach in zprood's code for AppleACPIBatteryManager, I see that you have included his approach for getting the extra info from _BIF 13, but approximation wasn't added. Here's my research:

My battery has an onboard controller of sorts, there's no EC or SMB register in which the actual count is stored, but Dell's BIOS Diagnostics utility called ePSA has access to the battery controller and is able to read the actual data from SMI. The diagnostics utility reports the following:
Design Capacity: 4400 mWh
Last Full Charge: 4078 mWh (this is your last charge Max capacity used in kexts)
Cycles as per ePSA: 55
Cycles as per approximation: 46 calculated from (designed-max)/7

So as you can see, a more precise result to a real value would be divided by 6, which is 54 (round from 53.(6)).

Code:
  /* If the cycle count can not be obtained through extra _BIF entry, it will be estimated according to the design capacity and maximum capacity, otherwise will be set based on the acquired cycle count from _BIF*/
    if (-1 == cycleCnt) {
        if (fDesignCapacity > fMaxCapacity) {
            setCycleCount((fDesignCapacity - fMaxCapacity) / 6);
        } else {
            setCycleCount((fMaxCapacity - fDesignCapacity) / 6);
        }
    } else {
        setCycleCount(cycleCnt);
    }
Just set the initial value for cycleCnt to be equal to -1 instead of current 0, because having 0 cycles is technically possible if battery is still brand new, whereas -1 cycles would be suspicious :D Remove the setCycleCount(cycleCnt); after it and add the piece of code above, this should do the trick for people who's DSDT doesn't allow for cycle monitoring through means of using extra _BIF entry (monitoring some register value) or extended _BIF.
 
Hey, perhaps you could add approximation for charge cycles for those of us who don't have extra or extended _BIF info to monitor the actual count?
I've originally stumbled upon this approach in zprood's code for AppleACPIBatteryManager, I see that you have included his approach for getting the extra info from _BIF 13, but approximation wasn't added. Here's my research:

My battery has an onboard controller of sorts, there's no EC or SMB register in which the actual count is stored, but Dell's BIOS Diagnostics utility called ePSA has access to the battery controller and is able to read the actual data from SMI. The diagnostics utility reports the following:
Design Capacity: 4400 mWh
Last Full Charge: 4078 mWh (this is your last charge Max capacity used in kexts)
Cycles as per ePSA: 55
Cycles as per approximation: 46 calculated from (designed-max)/7

So as you can see, a more precise result to a real value would be divided by 6, which is 54 (round from 53.(6)).

Code:
  /* If the cycle count can not be obtained through extra _BIF entry, it will be estimated according to the design capacity and maximum capacity, otherwise will be set based on the acquired cycle count from _BIF*/
    if (-1 == cycleCnt) {
        if (fDesignCapacity > fMaxCapacity) {
            setCycleCount((fDesignCapacity - fMaxCapacity) / 6);
        } else {
            setCycleCount((fMaxCapacity - fDesignCapacity) / 6);
        }
    } else {
        setCycleCount(cycleCnt);
    }
Just set the initial value for cycleCnt to be equal to -1 instead of current 0, because having 0 cycles is technically possible if battery is still brand new, whereas -1 cycles would be suspicious :D Remove the setCycleCount(cycleCnt); after it and add the piece of code above, this should do the trick for people who's DSDT doesn't allow for cycle monitoring through means of using extra _BIF entry (monitoring some register value) or extended _BIF.

I remember seeing that code when I started work on my version. I think I ended up removing it because it didn't make sense. I guess I understand a little more of what the intention was, but the whole thing still seems pointless. Make up a value to represent cycle count just so a number that is non-zero is displayed in system info, even though the value has little or nothing to do with the actual cycle count the battery may have experienced??!!

Also the else case seems strange. In what case would maxcap be greater than designcap? Wouldn't that be a sign of a battery in better condition than it was designed for, so shouldn't cycle count just be set to zero in that case?

And probably the magic number 6 (I've seen 7 used elsewhere) should be configurable in the Info.plist instead of being hard coded.
 
Status
Not open for further replies.
Back
Top