nekr0z / matebook-applet

System tray applet/control app for Huawei Matebook
GNU General Public License v3.0
142 stars 9 forks source link

Support MacOS #26

Open nekr0z opened 3 years ago

nekr0z commented 3 years ago

People are running MacOS on Matebooks, and it looks like matebook-applet would be welcome there.

It should be relatively easy to add MacOS-specific endpoints and have them probed when running the applet on MacOS. All our dependencies support MacOS, so there shouldn't be a problem.

Two things prevent me from implementing this straight away:

  1. Their current way of doing things doesn't allow to set arbitrary thresholds. Setting arbitrary thresholds is more versatile and is our preferred way of interacting with endpoints. It can be worked around, but I'd prefer not to if there's a way.
  2. It's unclear how to get the currently set values on MacOS.
nekr0z commented 3 years ago

Not really at compilation time, but I can access environment variables (including PATH) from within Go code, and set them, too. The problem is I need to figure a way to debug this. I could try to trace it, but I don't know how to access the output when running from the bundle, and the output when running standalone is useless because the issue isn't there. :-\

ldan93 commented 3 years ago

I'm a bit clueless about this one...

nekr0z commented 3 years ago

Okay, I love this project, I'm learning something new every day. Yay! ;-)

I redirected the logging facilities to the syslog, made the applet trace all the environment variables at startup, and compared the logs, running standalone and bundled versions. Those are different environments, I'm telling ya! When running from bundle, there are only half as much environment variables, and PATH is shorter.

On the particular machine with OS X 10.8, when run from terminal:

PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/go/bin

on the same machine, running from bundle:

PATH=/usr/bin:/bin:/usr/sbin:/sbin

Go fugure! Looks like MacOS has two versions of PATH, one for the terminal sessions, and a different one for the app bundles. Don't ask me why, or how, or what for.

I'm guessing that symlinking ioio and log (though log is likely already there somewhere) to /usr/bin should result in a working bundled applet. But I'm not sure in anything anymore, it's MacOS, there be dragons. :-D

ldan93 commented 3 years ago

Ok, so if I'm not mistaken, here's the catch :/usr/bin, /bin, /usr/sbin and /sbin aren't writeable in modern macOS versions, even with root privileges due to System Integrity Protection. Log, as a default system binary is already in /usr/bin, but not ioio. The right approach to add a binary to PATH, is to put it / symlink it in /usr/local/bin. That's what I did with ioio, and that's why it works on my system running from Terminal. https://stackoverflow.com/a/36734569 I can try to disable SIP temporarily to add a symlink to ioio in /usr/bin in order to verify your theory, but this is by no means a viable solution... Could you add /usr/local/bin to PATH within Go code ?

Edit : I've tried, just for the sake of it, to disable SIP, re-mount /usr/bin as writeable, and symlink ioio. It's really complicated / dangerous / unorthodox... But YES, then, the .app bundle works. So this is definitely a PATH problem.

nekr0z commented 3 years ago

Could you add /usr/local/bin to PATH within Go code ?

I believe I could, but I'd rather not. While it's a viable solution, anything hardcoded inside is by definition non-flexible. I would like a user to be able to change these things without needing a functioning Go installation, if you know what I mean. So I'm researching the alternatives before going to that last resort.

I've actually been able to achieve the required PATH via Info.plist. You said earlier you had no luck with that, but let's give it a try once again.

From what I understood, the first time you run an app bundle, it gets registered by the system somehow, so when you do changes to Info.plist, they don't kick in immediately; maybe that's why it didn't work out for you earlier.

Anyway, the newly pushed code has the following changes:

  1. It gives a trace of the current PATH it has on the startup.
  2. It has tracing enabled (i.e. -vv) by default, and all the output is redirected to the system log (this is temporary, for us to have an understanding of what's going on in the bundle; I will revert this before merging to master).
  3. It has PATH set to /usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin in the generated Info.plist.

I suggest you delete the .app you have (so it gets de-registered by the system), build a new one (go run build.go -m) and give it a test. ;-)

ldan93 commented 3 years ago

I can report that the .app generated with your new code works as expected ! 😁

nekr0z commented 3 years ago

Are we awesome or what? ;-)

Need to carefully document all the quirks now, set up Travis to properly build and upload MacOS binaries, and the job's done.

Would you mind sharing the final DSDT/SSDT you ended up with, so that it can be used as a part of the documentation?

ldan93 commented 3 years ago

Yes of course ! Here's my final SSDT file : SSDT-RMDT.aml.zip Here's the list of what is required for the app to work :

Both SSDT-RMDT.aml and ACPI_Debug.kext should be loaded with OpenCore (it's a very common hackintosh trick).

@profzei Maybe you could include these two files as part a future release ?

profzei commented 3 years ago

@ldan93

Maybe you could include these two files as part a future release ?

Yeah! Of course! Amazing job!

@nekr0z Looking forward to trying the final macOS binary!

nekr0z commented 3 years ago

@profzei The final one is still some time away, but code-wise it will not differ much from this one: matebook-applet.app.zip

In the meantime, the more eyes/testing, the better. ;-)

profzei commented 3 years ago

@nekr0z @ldan93 Maybe there is something I missed to configure properly but datebook-applet is not working for me...

These are my steps:

I cannot see the various thresholds and nothing happens when I click on "Battery protection is OFF"

I need to say that instead "Battery Protection is (effectively) ON" because it was set as ON in Windows and charging battery is limited to 70% even on macOS

Screenshot 2021-01-27 at 11 17 35
ldan93 commented 3 years ago

What happens if you try to launch the binary inside the .app ? ( right-click on the .app, "Show content", and then launch Contents/MacOS/matebook-applet )

Also, can you launch ioio from the Terminal ? (just type-in the command)

nekr0z commented 3 years ago

@profzei

What happens if you try to launch the binary inside the .app ? ( right-click on the .app, "Show content", and then launch Contents/MacOS/matebook-applet )

That. Also, from terminal, what do which ioio and which log commands say?

@ldan93 could you please test that build on your machine, too? I built it on my ancient MacBook, and you've been building on your modern system all this time, maybe there's some discrepancy.

ldan93 commented 3 years ago

Your build works on my machine... Maybe there's an extra-step I did to make matebook-applet work during the debugging process or when I wrote the first script, and that I forgot to document. Let's see @profzei 's feedback...

profzei commented 3 years ago

@nekr0z @ldan93

What happens if you try to launch the binary inside the .app ? ( right-click on the .app, "Show content", and then launch Contents/MacOS/matebook-applet )

This is the associated Terminal.app output:

Last login: Wed Jan 27 11:16:52 on ttys001
/Applications/matebook-applet.app/Contents/MacOS/matebook-applet ; exit;
riccardo@Lich-MBXP ~ % /Applications/matebook-applet.app/Contents/MacOS/matebook-applet ; exit;
could not detect locale

Also, can you launch ioio from the Terminal ? (just type-in the command)

This is the associated Terminal.app output (which means I can launch ioio command from Terminal):

riccardo@Lich-MBXP ~ % ioio
Usage: ioio [options] <name> <value>
Options:
  -s <service> (default service is ApplePS2SynapticsTouchPad)
  -h prints this messsage

<name> is name of property to set (use quotes if it has spaces)
<value> is value to set
  use true, false, yes, or no for boolean properties
  use non-digits for strings
  for string starting with a digit prefix string with :
  use digits for decimal number

Also, from terminal, what do which ioio and which log commands say?

riccardo@Lich-MBXP ~ % which ioio
/usr/local/bin/ioio

and

riccardo@Lich-MBXP ~ % which log
/usr/bin/log
nekr0z commented 3 years ago

@profzei Looks like whatever locale your system is reporting, the applet fails to detect. Out of curiosity: what's that locale you have? (Terminal echo $LANG.)

I have added a fallback to English, hopefully this works: matebook-applet.app.zip

profzei commented 3 years ago

@nekr0z This is an issue:

riccardo@Lich-MBXP ~ % echo $LANG

riccardo@Lich-MBXP ~ %

@ldan93 How it is possible not getting an output? Any hint to fix this?

Nothing changed using your latest version...

nekr0z commented 3 years ago

@profzei Looks like there are more issues. Could you by any chance try to execute the binary from the Terminal with the key for verbose output? I.e.

/wherever/you/have/matebook-applet.app/Contents/MacOS/matebook-applet -vv
profzei commented 3 years ago

@nekr0z @ldan93 This is the output for locale command (on a fresh macOS 11.0.1 updated to 11.1)

riccardo@Lich-MBXP ~ % locale
LANG=""
LC_COLLATE="C"
LC_CTYPE="UTF-8"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=
profzei commented 3 years ago

Looks like there are more issues. Could you by any chance try to execute the binary from the Terminal with the key for verbose output?

Here is the output:

riccardo@Lich-MBXP ~ % cd /Applications/matebook-applet.app/Contents/MacOS 
riccardo@Lich-MBXP MacOS % ./matebook-applet -vv
could not detect locale
en
TRACE: 2021/01/27 16:11:53 driver-darwin.go:35: PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/share/dotnet:~/.dotnet/tools:/Library/Apple/usr/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands
INFO: 2021/01/27 16:11:53 main.go:75: matebook-applet version 2.5.0.darwin-dbg.65+g429a93f
TRACE: 2021/01/27 16:11:54 driver-darwin.go:218: Read from the log: Filtering the log data using "senderImagePath CONTAINS "ACPIDebug""
TRACE: 2021/01/27 16:11:54 driver-darwin.go:219: Killing the log output process...
TRACE: 2021/01/27 16:11:54 driver-darwin.go:218: Read from the log: Filtering the log data using "senderImagePath CONTAINS "ACPIDebug""
TRACE: 2021/01/27 16:11:54 driver-darwin.go:219: Killing the log output process...
TRACE: 2021/01/27 16:11:54 driver.go:141: Checking if the threshold endpoint is writable...
TRACE: 2021/01/27 16:11:54 main.go:85: looking for endpoint to save thresholds to...
TRACE: 2021/01/27 16:11:54 driver.go:178: Couldn't access "/etc/default/huawei-wmi/charge_control_thresholds".
TRACE: 2021/01/27 16:11:54 driver.go:178: Couldn't access "/etc/default/huawei-wmi/charge_thresholds".
TRACE: 2021/01/27 16:11:54 applet.go:33: Setting up menu...
INFO: 2021/01/27 16:11:54 applet.go:110: Couldn't get custom icon, falling back to default
TRACE: 2021/01/27 16:11:54 driver.go:141: Checking if the threshold endpoint is writable...
TRACE: 2021/01/27 16:11:54 applet.go:58: no way to change BP settings, not showing the corresponding GUI
TRACE: 2021/01/27 16:11:54 applet.go:62: no access to Fn-Lock setting, not showing its GUI
TRACE: 2021/01/27 16:11:54 applet.go:67: Menu is now ready
TRACE: 2021/01/27 16:11:54 applet-darwin.go:26: GUI thread not implemented
nekr0z commented 3 years ago

@profzei ioio gets called and gives no error (or we'd see complaints), but the log readings are empty, neither DBG4 nor DBG6 produce valid log output (or any ACPIDebug-marked log output, for that matter). @ldan93 any ideas on further investigation strategy?

ldan93 commented 3 years ago

@profzei

Could you please open a Terminal and type-in the following command : log stream --predicate 'senderImagePath contains "ACPIDebug"' > log.txt

Then, while keeping this process running, open another terminal instance (new window or tab), and type in one by one the following commands :

ioio -s org_rehabman_ACPIDebug dbg4 0
ioio -s org_rehabman_ACPIDebug dbg7 0
ioio -s org_rehabman_ACPIDebug dbg5 1677721600
ioio -s org_rehabman_ACPIDebug dbg4 0
ioio -s org_rehabman_ACPIDebug dbg1 0

After that, go back to the first terminal (with the log stream process). Kill the process with CTRL+C.

You should have a log.txt file in you home directory (or wherever you were when you launched the log stream command). Please, upload this log.

profzei commented 3 years ago

@ldan93 Here is the requested log file log.txt

Edit: it's almost empty...

nekr0z commented 3 years ago

@profzei the applet relies on the information in the log to read the battery values and the Fn-Lock state. Since you have everything properly loaded (or so I understood from the previous messages), my first (and only, actually) logical guess is something is switched off in the logging system itself, so that the messages ACPIDebug sends to the logging system don't end up in the log. @ldan93 may have more ideas, but I know too little about MacOS to be of any help in solving this particular mistery.

profzei commented 3 years ago

@nekr0z Yes I agree with you: it's completely clear.

But, as I said, my install should be standard so this "issue" could be relevant also for many other users interested in this applet...

nekr0z commented 3 years ago

@profzei Absolutely!

nekr0z commented 3 years ago

Sorry, misclicked.

profzei commented 3 years ago

@ldan93 Just to be sure... what are your settings in config.plist for Misc -> Debug variables? ...in particular for Target key? Mine are those you could find in my releases which are based on non-debug OpenCore release! Did you changed something for ACPIDebug.kext in your config.plist?

ldan93 commented 3 years ago

To check if it's just a problem of log tracing, can you tell us whether ioio -s org_rehabman_ACPIDebug dbg5 1677721600 does disable battery protection ?

Can you also try to :

I don't remember changing something in config.plist other than adding ACPIDebug.kext in kext section and SSDT-RMDT.aml in the ACPI/Add section... Please find my : config.plist.zip (I've only removed my serial number data)

I must say that, from what I remember, I just followed Rehabman's readme

EDIT : I don't know what is you current kext loading order, but if that's not already the case, can you try to load ACPIDebug as the very last kext ?

ldan93 commented 3 years ago

OK, so I've done some research. I think there's a problem with macOS Big Sur and ACPI_Debug.kext log feature. Here is what I've tried :

@profzei Can you perform the same DBG9 test on your real Big Sur environment please ? Here the new SSDT with DBG9 method : SSDT-RMDT.aml.zip

There is at least another GitHub issue where someone wasn't able to get logs from ACPI Debug with Big Sur.

The kext hasn't been updated since 2015, but it worked with all macOS versions since then, we are very unlucky... But its developer is still very active in the hackintosh community, so we can get in touch with him to report the issue. Well, actually not, he kind of retired from the hackintosh community. So we have to figure this out on our own, or find another way of reporting values without the log trick in macOS Big Sur...

profzei commented 3 years ago

@ldan93 If I run command ioio -s org_rehabman_ACPIDebug dbg5 1677721600 then nothing changed in the matebook-applet but battery stops to charging as if you had set the current battery value as the charge limit.

I followed your steps for Console, but nothing is traced in Console.app with ACPIDebug as filter...

profzei commented 3 years ago

@ldan93 I'll do it probably this night...

Do you think DebugEnhancer or YogaSMC are viable solutions?

profzei commented 3 years ago

I don't remember changing something in config.plist other than adding ACPIDebug.kext in kext section and SSDT-RMDT.aml in the ACPI/Add section... Please find my : config.plist.zip (I've only removed my serial number data)

There is one difference: you are loading YogaSMC.kext, me not. I tried loading it but nothing changed... (as expected)

I just followed Rehabman's readme

Me too...

I don't know what is you current kext loading order, but if that's not already the case, can you try to load ACPIDebug as the very last kext ?

Done: nothing changed...

Good news about DBG9

nekr0z commented 3 years ago

I already asked, but looks like it got lost:

Would you mind patching your ioreg output to a text file (i.e. ioreg > ioreg.txt) and letting me have a look? It will only give one of the planes by default, but the ACPI devices are likely to be shown...

Maybe there is a less hacky way to read the values than messing up with the logs after all. Long shot, I know...

ldan93 commented 3 years ago

@profzei Thanks for your debugging. It looks like ACPI calls made by ioio are still effective but the log feature is broken in Big Sur. So we have to find another way... About YogaSMC : yeah I tried to use this kext because it implements EC field reading, but couldn't get it to the work so far. It's designed for Lenovo laptops in the first place. @nekr0z Please find the output of ioreg : ioreg.txt.zip

nekr0z commented 3 years ago

@ldan93 the objects named EC0, EC, and AppleACPIEC look the most promising. Could you please take look inside them, i.e. ioreg -n EC0 -r, and also for the other two?

profzei commented 3 years ago

@nekr0z @ldan93 I don't know if this could be useful, but I made some tests...

With sudo dmesg command we are accessing the kernel-log. This is a so called ringbuffer of (by default) 4kb size (which can be patched to a larger size by DebugEnhancer.kext [I don't know how...] or via msgbuf-bootarg) and will only show, by default, the last 4kb of the kernel-log. If you get many log-entries, its perfectly possible you are missing many entries. The actual size of msgbuf is checked with sysctl -a kern.msgbuf.

Therefore I put in my config.plist in boot-args the parameter msgbuf=1048576.

I opened a Terminal and typed-in one by one the following commands checking every time what I got with sudo dmesg:

ioio -s org_rehabman_ACPIDebug dbg4 0
ioio -s org_rehabman_ACPIDebug dbg7 0
ioio -s org_rehabman_ACPIDebug dbg5 1677721600
ioio -s org_rehabman_ACPIDebug dbg4 0
ioio -s org_rehabman_ACPIDebug dbg1 0

This is what I got respectively: ioio -s org_rehabman_ACPIDebug dbg4 0

[ 2011.770322]: ACPIDebug: "View Thresholds"
[ 2011.783462]: ACPIDebug: { "Reading (hexadecimal values):", 0x0, 0x0, }

ioio -s org_rehabman_ACPIDebug dbg7 0

[ 2153.481542]: ACPIDebug: { "Value : ", 0x0, }
[ 2153.481824]: ACPIDebug: "Fn-Lock state set"

ioio -s org_rehabman_ACPIDebug dbg5 1677721600

[ 2193.872452]: ACPIDebug: { "Value : ", 0x64000000, }
[ 2193.872606]: ACPIDebug: "Manually setting thresholds to 0-100"
[ 2193.875455]: ACPIDebug: "Set"

ioio -s org_rehabman_ACPIDebug dbg4 0

[ 2243.377869]: ACPIDebug: "View Thresholds"
[ 2243.383784]: ACPIDebug: { "Reading (hexadecimal values):", 0x0, 0x64, }

ioio -s org_rehabman_ACPIDebug dbg1 0

[ 2286.778231]: ACPIDebug evaluateObject("DBG1") failed (e00002bc)

@ldan93 With the last command battery stopped charging... is it normal? What command I need to type now to unset this limit?

ldan93 commented 3 years ago

@nekr0z Please find the requested ioreg results : ioreg_logs.zip

@profzei Oh, great findings ! Does this bootarg enable you to get these log messages in Console.app (with ACPIDebug search filter) or with the log stream command in another terminal ?

The logs you get with dmesg are totally expected. But the last command is supposed to do nothing : as the error message indicates, DGB1 method does not even exist, I just wanted to check if calling an undefined method printed something on Big Sur... The command ioio -s org_rehabman_ACPIDebug dbg5 1677721600 is supposed to disable battery protection, it should already be charging... You can also try ioio -s org_rehabman_ACPIDebug dbg5 6553600

Tell me if you battery is now charging with these commands...

profzei commented 3 years ago

@ldan93

Does this bootarg enable you to get these log messages in Console.app (with ACPIDebug search filter) or with the log stream command in another terminal ?

...Nope! I cannot see any ACPIDebug related content nor in Console.app nor with the log stream command in another terminal...

The command ioio -s org_rehabman_ACPIDebug dbg5 1677721600 is supposed to disable battery protection, it should already be charging... You can also try ioio -s org_rehabman_ACPIDebug dbg5 6553600

Yes! Battery is charging fine...

@ldan93 It seems like ACPIDebug.kext cannot write on log stream on Big Sur... ACPIDebug.kext is an old/unmaintained kext and maybe it needs some changes to work with Big Sur: same situation happened, for example some months ago, to VoltageShift.kext which required upgrade for functioning with Big Sur by implementing what developer called DriverKit layer... Do you think we could ask some hint to @zhen-zen? He's the YogaSMC's developer so maybe he already faced such difficulties... If you agree with this, could you try to open a request of help in its YogaSMC repo? (as you see my English skills are very poor in explaining all our situation)

profzei commented 3 years ago

@ldan93 @nekr0z I found a way for writing on Big Sur system log: I can see messages both on Console.app and using on Terminal the command log stream ...but it needs more tweaking: I'm not able (from the programming point of view) to get one string output with Debug command if more than one argument is passed to a function (I don't know how to concatenate output...)

@ldan93 Reference is https://pikeralpha.wordpress.com/2013/12/23/enabling-acpi-debugging/ Instructions:

Now outputs from commands ioio -s org_rehabman_ACPIDebug dbg* seem to be working... Matebook-applet is not working yet since output strings need to be properly formatted...

ldan93 commented 3 years ago

Thank you very much for these new elements. So, we know there is still a way ! It involves some heavy tweaking though...

Let's see if we get some feedback from @zhen-zen about other options. Maybe there is a more straightforward / cleaner way to do this. But at least we now have a backup plan.

profzei commented 3 years ago

@ldan93 Sure!😊👍🏻

ldan93 commented 3 years ago

Hi, Sorry for coming back so late, I had to wait before upgrading my system to Big Sur and investigate the issue further.

Here are some news :

@profzei : do you know what are the differences between loading a kext at boot stage with OpenCore and manually loading the kext ? Could the kext be loaded the same way with OpenCore ? Maybe this is a matter of timing, I don't know...

profzei commented 3 years ago

do you know what are the differences between loading a kext at boot stage with OpenCore and manually loading the kext ? Could the kext be loaded the same way with OpenCore ? Maybe this is a matter of timing, I don't know...

@ldan93 Honestly I don't know... but I guess the issue could be due not to a matter of timing (i.e. if a kext is loaded... it is loaded and that's all...) but maybe which path (i.e. local path or EFI path... since I guess that when you load manually ACPIDebug.kext then ACPIDebug.kext is not placed in EFI folder) kext is loaded from

nekr0z commented 3 years ago

@ldan93 @profzei gentlemen, what you are talking about is waaay beyond my OS X expertise.

Considering the current state of code (and documentation) in the darwin branch, is it a good idea to give it a little brush-up and finally release, or are we still in the woods?

ldan93 commented 3 years ago

Well, I think we have to make a decision about the way forward. Here are the possibilities that I see :

  1. Implementing a clean way of reading EC values (with YogaSMC) : definitely the ideal way, but I don't feel up to the task. If you feel up to it, you can reach zhen-zhen on the GitHub issue that I mentioned
  2. Manually loading the kext after boot in Big Sur : doesn't seem reasonable (the kext is unsigned so it would require disabling MacOS securities)
  3. Investigate profzei's lead : promising but requires some more work. And I don't know if it's OK to constantly run the OS with debug boot parameters (security, performances, ...)
  4. Since we can still invoke ACPI commands but can't get logs : let matebook applet run in a "write only" mode in Big Sur = we can set battery thresholds but we won't have any feedback / reading of current values. Easiest path in my opinion, but it would be quite a loss of functionality...

@profzei and @nekr0z : what do you think ?

nekr0z commented 3 years ago

I skimmed through your discussion with zhen-zhen, and as much as I'd love to take option 1, debugging it (with zhen-zhen's help) requires running OS X on the hardware, and I don't have a spare Matebook to do that. :(