assistant_daemon 0.1.0

Daemon program for providing many features.
//
//  main.cpp
//  test
//
//  Created by Shihao Xia on 7/20/23.
//

#include <iostream>
#include <IOKit/IOKitLib.h>
#include <IOKit/pwr_mgt/IOPM.h>
#include <mach/mach.h>

#include "lib.h"

__attribute__((constructor))
void init(){
}


static void onPMrootDomainChange(void *refcon, io_service_t service, uint32_t messageType, void *messageArgument) {
    if (messageType == kIOPMMessageClamshellStateChange) {
        const int isClamshellClosed = (reinterpret_cast<uint64_t>(messageArgument)  & kClamshellStateBit);

        CallbackFunc cb = reinterpret_cast<CallbackFunc>(refcon);
        cb(isClamshellClosed == 0);
    }

}

dispatch_queue_t serialQueue = nullptr;
IONotificationPortRef notifyPort = nullptr;
io_object_t notification = 0;

void register_callback_for_clamshell_change(CallbackFunc callback) {
    if(notification){
        // this function only allow call once if no unregister_callback_for_clamshell_change is called
        return;
    }
    io_connect_t connection = IO_OBJECT_NULL;
    io_service_t pmRootDomain = IOServiceGetMatchingService(kIOMainPortDefault,
                                           IOServiceMatching("IOPMrootDomain"));
    
    
  
    if(pmRootDomain)
    {
        
        serialQueue = dispatch_queue_create("com.dustinrue.ControlPlane.LaptopLidEvidenceSource", DISPATCH_QUEUE_SERIAL);
           if (!serialQueue) {
               return;
           }
           dispatch_set_target_queue(serialQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));

           notifyPort = IONotificationPortCreate(kIOMainPortDefault);
           if (!notifyPort) {
               return;
           }
           IONotificationPortSetDispatchQueue(notifyPort, serialQueue);
        
        kern_return_t kr = IOServiceAddInterestNotification(
            notifyPort,
            pmRootDomain,
            kIOGeneralInterest,
           onPMrootDomainChange, 
           reinterpret_cast<void *>(callback), 
           &notification);
    IOObjectRelease(pmRootDomain);

           
    }
    
}

void unregister_callback_for_clamshell_change() {
    if (notification) {
        IOObjectRelease(notification);
        notification = 0;
    }
    
    if (notifyPort) {
        IONotificationPortSetDispatchQueue(notifyPort, nullptr);
        IONotificationPortDestroy(notifyPort);
        notifyPort = nullptr;
    }
    
    if (serialQueue) {
        dispatch_release(serialQueue);
        serialQueue = nullptr;
    }
}