Development environment: Electron 30.2.0 Run-time configuration: macOS 14.5 (23F79) DESCRIPTION OF PROBLEM I have one keyboard which will wake up the Mac OS from sleep when sending command to it at the time system starting to sleep. But this keyboard will not have such problem on Window OS, I don't know why sending command to that keyboard will wake up the Mac OS system from sleep. Does anyone know from a hardware or software point of view, what kind of usb keyboard operation will cause the macos system to wake up? Or can someone give us guidance, how to debug and solve the usb keyboard caused by the wake up system problem on Mac OS system? STEPS TO REPRODUCE Sending command to that keyboard when the system start to sleep
Usb keyboard will wake up system when sending command to it at the time system starting to sleep
Does anyone know from a hardware or software point of view, what kind of usb keyboard operation will cause the macos system to wake up?
Starting up with a few questions:
-
What do you mean by "wake up" kernel's concept of "sleep" is very different than user spaces, so there's a big difference between "the screen woke up again" and "the USB bus powered up again".
-
What API(s) are you actually communicating through? One of the user space user clients (which one?) or are the commands coming from a a DEXT or IOKit driver?
-
Are there any other components involved here, particularly 3rd party drivers?
Or can someone give us guidance, how to debug and solve the usb keyboard caused by the wake up system problem on Mac OS system?
Conceptually, you can broadly think of sleep/wake as being managed at three different levels:
-
User space apps can directly defer/prevent sleep, either directly using APIs like the ones in QA1340 or indirectly because an API the called did the same sort of thing. One thing to note here is that this is the very "earliest" part of the sleep process and that different parts of the system sleep at very different times. For example, the screen will often be turned off WELL before the kernel has put most of the system to sleep. If you've ever noticed that the system seems to wake up very quickly IMMEDIATELY after it "goes to sleep", that's what's actually going on. The screen was turned off but the much of the system was still running "normally".
-
The kernel is what actually implements the mechanics of the sleep process, with individual drivers (KEXTs and DEXTs) having a great deal of control over the entire sleep process.
-
Each bus has it's own definition of what "sleep" actually means, including how devices can prevent sleep, trigger wakes, etc.
Further complicating all of this, all of these layers are also interacting with each other. So, for example, sleep can stop because:
-
A user space app "directly" prevent sleep.
-
A user space client sent a command to the kernel and a driver decided it needed to defer sleep (or trigger a wake) in order to correctly process the command.
-
The command was sent all the way to the accessory and the accessory itself changed the buses state.
SO, the first step here is to basically "figure out what happened", but the details of that greatly depend on where your code fits into the system. If you're working in a DEXT/KEXT, you can often determine what happened by looking closely at the relevant sleep callback. For user space clients, the console log is generally the best resource. The real key there is to make sure you're code is logging to the console log, relate your apps logging to the wake you're seeing ("what do you log/do just before the wake begins/ends"), and then look for those logs messages inside the broader system log. The system does a pretty good job of logging sleep activity, so you can then just "look" for whatever happened between your log messages.
Some quick recommendations on the console log:
a) Take a look at "Your Friend the System Log", both as background context and to make sure you're really taking advantage of what it can do for you.
b) The hardest thing about console log analysis is that the log volume is ENORMOUS, so anything you can do to reduce log activity is enormously helpful. For a hardware issue like this, that (ideally) means using a dedicated test machine that you've specifically configured to make this kind of testing easier. That includes things like:
-
Don't install anything except was required to reproduce the problem.
-
Avoid as much machine configuration as possible, particularly things like logging into iCloud which implicitly create more "activity".
-
Turn of everything you don't need. Turn off bluetooth, disable all network interfaces, don't attach any external devices, etc.
Setting up a machine like this can be time consuming but if you're doing a lot of this kind of testing/analysis it can easily save more time than it costs.
c) Test slowly and carefully. Note the time you start/stop each test and pause for a minute or so between tests. When you're done testing, wait a few minutes before triggering the sysdiagnose. Testing to fast can make it very hard to separate each test run and, in the worst case, is the difference between a useful log and a worthless one.
d) Collect a sysdiagnose (or just the log data) instead of trying to work out of the "live" log. Two major reasons for this:
-
If you work out of the live log, at some point you will accidentally start the stream or quit the app at the EXACT moment you'd just started to get your head around what was going on.
-
Keeping the log archives around means that you can go back to older logs to look for something you just noticed/understood from looking at a different log.
The live log can be handy for "quick" things, but use a log archive when you're actually trying to understand how the system works.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware