/* * ipc_event.c * * Copyright 2001-2009 Texas Instruments, Inc. - http://www.ti.com/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /**************************************************************************** * * MODULE: IPC_Event.c * * PURPOSE: * * DESCRIPTION: * ============ * * ****************************************************************************/ /* includes */ /************/ #include <sys/types.h> #include <sys/socket.h> #include <net/if.h> #include <linux/rtnetlink.h> #include <signal.h> #include <sys/mman.h> #include <unistd.h> #include <linux/wireless.h> #include "cu_osapi.h" #include "oserr.h" #include "TWDriver.h" #include "STADExternalIf.h" #include "ParsEvent.h" #include "ipc_event.h" /* defines */ /***********/ #define PIPE_READ 0 #define PIPE_WRITE 1 #define IPC_EVENT_KEY ((key_t)123456789) /* IPC evemt messages to child */ #define IPC_EVENT_MSG_KILL "IPC_EVENT_MSG_KILL" #define IPC_EVENT_MSG_UPDATE_DEBUG_LEVEL "IPC_EVENT_MSG_UPDATE_DEBUG_LEVEL" #define IPC_EVENT_MSG_MAX_LEN 50 /* local types */ /***************/ typedef struct IpcEvent_Shared_Memory_t { int pipe_fields[2]; u64 event_mask; union { S32 debug_level; } content; } IpcEvent_Shared_Memory_t; /* Module control block */ typedef struct IpcEvent_t { IpcEvent_Shared_Memory_t* p_shared_memory; S32 child_process_id; S32 pipe_to_child; } IpcEvent_t; typedef struct IpcEvent_Child_t { S32 STA_socket; IpcEvent_Shared_Memory_t* p_shared_memory; S32 pipe_from_parent; } IpcEvent_Child_t; /* local variables */ /*******************/ VOID g_tester_send_event(U8 event_index); /* local fucntions */ /*******************/ static VOID IpcEvent_SendMessageToChild(IpcEvent_t* pIpcEvent, PS8 msg) { write(pIpcEvent->pipe_to_child, msg, os_strlen(msg)); } static S32 IpcEvent_Sockets_Open(VOID) { S32 skfd; struct sockaddr_nl local; skfd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (skfd < 0) { return -1; } os_memset(&local, 0, sizeof(local)); local.nl_family = AF_NETLINK; local.nl_groups = RTMGRP_LINK; if (bind(skfd, (struct sockaddr *) &local, sizeof(local)) < 0) { close(skfd); return -2; } return skfd; } static inline VOID IpcEvent_Sockets_Close(S32 skfd) { close(skfd); } void ProcessLoggerMessage(PU8 data, U16 len); static VOID IpcEvent_PrintEvent(IpcEvent_Child_t* pIpcEventChild, U32 EventId, TI_UINT8* pData, S32 DataLen) { if(pIpcEventChild->p_shared_memory->event_mask & ((u64)1<<EventId)) { switch(EventId) { case IPC_EVENT_DISASSOCIATED: { OS_802_11_DISASSOCIATE_REASON_T *pDisAssoc; if (NULL == pData) { return; } else { pDisAssoc = (OS_802_11_DISASSOCIATE_REASON_T*)pData; } switch(pDisAssoc->eDisAssocType) { case OS_DISASSOC_STATUS_UNSPECIFIED: os_error_printf(CU_MSG_ERROR, "CLI Event - Disassociated with unspecified reason (User/SG/Recovery)\n"); break; case OS_DISASSOC_STATUS_AUTH_REJECT: if (pDisAssoc->uStatusCode == STATUS_PACKET_REJ_TIMEOUT) { os_error_printf(CU_MSG_ERROR, "CLI Event - Disassociated due to no Auth response \n"); } else { os_error_printf(CU_MSG_ERROR, "CLI Event - Disassociated due to Auth response packet with reason = %d\n", pDisAssoc->uStatusCode); } break; case OS_DISASSOC_STATUS_ASSOC_REJECT: if (pDisAssoc->uStatusCode == STATUS_PACKET_REJ_TIMEOUT) { os_error_printf(CU_MSG_ERROR, "CLI Event - Disassociated due to no Assoc response \n"); } else { os_error_printf(CU_MSG_ERROR, "CLI Event - Disassociated due to Assoc response packet with reason = %d\n", pDisAssoc->uStatusCode); } break; case OS_DISASSOC_STATUS_SECURITY_FAILURE: os_error_printf(CU_MSG_ERROR, "CLI Event - Disassociated due to RSN failure\n"); break; case OS_DISASSOC_STATUS_AP_DEAUTHENTICATE: os_error_printf(CU_MSG_ERROR, "CLI Event - Disassociated due to AP deAuthenticate packet with reason = %d\n", pDisAssoc->uStatusCode); break; case OS_DISASSOC_STATUS_AP_DISASSOCIATE: os_error_printf(CU_MSG_ERROR, "CLI Event - Disassociated due to AP disAssoc packet with reason = %d\n", pDisAssoc->uStatusCode); break; case OS_DISASSOC_STATUS_ROAMING_TRIGGER: os_error_printf(CU_MSG_ERROR, "CLI Event - Disassociated due to roaming trigger = %d\n", pDisAssoc->uStatusCode); break; default: os_error_printf(CU_MSG_ERROR, "CLI Event - Disassociated with unknown reason = %d\n", pDisAssoc->eDisAssocType); break; } break; /* the end of the IPC_EVENT_DISASSOCIATED case */ } case IPC_EVENT_ASSOCIATED: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_ASSOCIATED\n"); break; case IPC_EVENT_MEDIA_SPECIFIC: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_MEDIA_SPECIFIC\n"); break; case IPC_EVENT_SCAN_COMPLETE: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_SCAN_COMPLETE\n"); break; /* custom events */ case IPC_EVENT_SCAN_STOPPED: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_SCAN_STOPPED\n"); break; case IPC_EVENT_LINK_SPEED: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_LINK_SPEED\n"); break; case IPC_EVENT_AUTH_SUCC: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_AUTH_SUCC\n"); break; case IPC_EVENT_CCKM_START: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_CCKM_START\n"); break; case IPC_EVENT_EAPOL: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_EAPOL\n"); break; case IPC_EVENT_RE_AUTH_STARTED: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_RE_AUTH_STARTED\n"); break; case IPC_EVENT_RE_AUTH_COMPLETED: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_RE_AUTH_COMPLETED\n"); break; case IPC_EVENT_RE_AUTH_TERMINATED: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_RE_AUTH_TERMINATED\n"); break; case IPC_EVENT_BOUND: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_BOUND\n"); break; case IPC_EVENT_UNBOUND: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_UNBOUND\n"); break; case IPC_EVENT_PREAUTH_EAPOL: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_PREAUTH_EAPOL\n"); break; case IPC_EVENT_LOW_RSSI: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_LOW_RSSI\n"); break; case IPC_EVENT_TSPEC_STATUS: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_TSPEC_STATUS\n"); OS_802_11_QOS_TSPEC_PARAMS* tspec = (OS_802_11_QOS_TSPEC_PARAMS*)pData; os_error_printf(CU_MSG_ERROR, "CLI Event - IPC_EVENT_TSPEC_STATUS -- (ReasonCode = %d) \n",tspec->uReasonCode); os_error_printf(CU_MSG_ERROR, "Tspec Parameters (as received through event handler):\n"); os_error_printf(CU_MSG_ERROR, "-----------------------------------------------------\n"); os_error_printf(CU_MSG_ERROR, "userPriority = %d\n",tspec->uUserPriority); os_error_printf(CU_MSG_ERROR, "uNominalMSDUsize = %d\n",tspec->uNominalMSDUsize); os_error_printf(CU_MSG_ERROR, "uMeanDataRate = %d\n",tspec->uMeanDataRate); os_error_printf(CU_MSG_ERROR, "uMinimumPHYRate = %d\n",tspec->uMinimumPHYRate); os_error_printf(CU_MSG_ERROR, "uSurplusBandwidthAllowance = %d\n",tspec->uSurplusBandwidthAllowance); os_error_printf(CU_MSG_ERROR, "uAPSDFlag = %d\n",tspec->uAPSDFlag); os_error_printf(CU_MSG_ERROR, "MinimumServiceInterval = %d\n",tspec->uMinimumServiceInterval); os_error_printf(CU_MSG_ERROR, "MaximumServiceInterval = %d\n",tspec->uMaximumServiceInterval); os_error_printf(CU_MSG_ERROR, "uMediumTime = %d\n\n",tspec->uMediumTime); break; case IPC_EVENT_TSPEC_RATE_STATUS: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_TSPEC_RATE_STATUS\n"); break; case IPC_EVENT_MEDIUM_TIME_CROSS: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_MEDIUM_TIME_CROSS\n"); break; case IPC_EVENT_ROAMING_COMPLETE: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_ROAMING_COMPLETE\n"); break; case IPC_EVENT_EAP_AUTH_FAILURE: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_EAP_AUTH_FAILURE\n"); break; case IPC_EVENT_WPA2_PREAUTHENTICATION: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_WPA2_PREAUTHENTICATION\n"); break; case IPC_EVENT_TRAFFIC_INTENSITY_THRESHOLD_CROSSED: { U32 *crossInfo = (U32 *)pData; os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_TRAFFIC_INTENSITY_THRESHOLD_CROSSED\n"); os_error_printf(CU_MSG_ERROR, (PS8)"Threshold(High=0, Low=1) crossed= %d\n", crossInfo[0]); os_error_printf(CU_MSG_ERROR, (PS8)"Direction(Above=0, Below=1) crossed= %d\n", crossInfo[1]); break; } case IPC_EVENT_SCAN_FAILED: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_SCAN_FAILED\n"); break; case IPC_EVENT_WPS_SESSION_OVERLAP: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_WPS_SESSION_OVERLAP\n"); break; case IPC_EVENT_RSSI_SNR_TRIGGER: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_RSSI_SNR_TRIGGER (index = %d), Data = %d\n", (S8)(*(pData + 2) - 1),(S8)(*pData)); break; case IPC_EVENT_TIMEOUT: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_TIMEOUT\n"); break; case IPC_EVENT_GWSI: os_error_printf(CU_MSG_ERROR, (PS8)"IpcEvent_PrintEvent - received IPC_EVENT_GWSI\n"); break; case IPC_EVENT_LOGGER: #ifdef ETH_SUPPORT ProcessLoggerMessage(pData, (U16)DataLen); #endif break; default : os_error_printf(CU_MSG_ERROR, (PS8)"**** Unknow EventId %d ****\n", EventId); } } } static VOID IpcEvent_wext_event_wireless(IpcEvent_Child_t* pIpcEventChild, PS8 data, S32 len) { struct iw_event iwe; struct stream_descr stream; S32 ret; IPC_EV_DATA* pEvent; U32 EventId = 0; /* init the event stream */ os_memset((char *)&stream, '\0', sizeof(struct stream_descr)); stream.current = (char *)data; stream.end = (char *)(data + len); do { /* Extract an event and print it */ ret = ParsEvent_GetEvent(&stream, &iwe); if(ret <= 0) break; switch (iwe.cmd) { case SIOCGIWAP: if((iwe.u.ap_addr.sa_data[0] == 0) && (iwe.u.ap_addr.sa_data[1] == 0) && (iwe.u.ap_addr.sa_data[2] == 0) && (iwe.u.ap_addr.sa_data[3] == 0) && (iwe.u.ap_addr.sa_data[4] == 0) && (iwe.u.ap_addr.sa_data[5] == 0)) { EventId=IPC_EVENT_DISASSOCIATED; IpcEvent_PrintEvent(pIpcEventChild, EventId, NULL,0); } else { #ifdef XCC_MODULE_INCLUDED /* Send a signal to the udhcpc application to trigger the renew request */ system("killall -SIGUSR1 udhcpc"); #endif EventId=IPC_EVENT_ASSOCIATED; IpcEvent_PrintEvent(pIpcEventChild, EventId, NULL,0); } break; case IWEVMICHAELMICFAILURE: EventId=IPC_EVENT_MEDIA_SPECIFIC; IpcEvent_PrintEvent(pIpcEventChild, EventId, NULL,0); break; case IWEVCUSTOM: pEvent = (IPC_EV_DATA*)iwe.u.data.pointer; if (pEvent) { EventId = (U32)pEvent->EvParams.uEventType; IpcEvent_PrintEvent (pIpcEventChild, EventId, pEvent->uBuffer, pEvent->uBufferSize); } break; case SIOCGIWSCAN: EventId=IPC_EVENT_SCAN_COMPLETE; IpcEvent_PrintEvent(pIpcEventChild, EventId, NULL,0); break; case IWEVASSOCREQIE: /* NOP */ break; case IWEVASSOCRESPIE: /* NOP */ break; case IWEVPMKIDCAND: EventId=IPC_EVENT_MEDIA_SPECIFIC; IpcEvent_PrintEvent(pIpcEventChild, EventId, NULL,0); break; } g_tester_send_event((U8) EventId); } while(1); } static VOID IpcEvent_wext_event_rtm_newlink(IpcEvent_Child_t* pIpcEventChild, struct nlmsghdr *h, S32 len) { struct ifinfomsg *ifi; S32 attrlen, nlmsg_len, rta_len; struct rtattr * attr; if (len < sizeof(*ifi)) return; ifi = NLMSG_DATA(h); /* if ((if_nametoindex("wlan") != ifi->ifi_index) && (if_nametoindex("wifi") != ifi->ifi_index)) { os_error_printf(CU_MSG_ERROR, "ERROR - IpcEvent_wext_event_rtm_newlink - Ignore event for foreign ifindex %d", ifi->ifi_index); return; } */ nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); attrlen = h->nlmsg_len - nlmsg_len; if (attrlen < 0) return; attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); rta_len = RTA_ALIGN(sizeof(struct rtattr)); while (RTA_OK(attr, attrlen)) { if (attr->rta_type == IFLA_WIRELESS) { IpcEvent_wext_event_wireless(pIpcEventChild, ((PS8) attr) + rta_len, attr->rta_len - rta_len); } else if (attr->rta_type == IFLA_IFNAME) { os_error_printf(CU_MSG_WARNING, (PS8)"WARNING - IpcEvent_wext_event_rtm_newlink - unsupported rta_type = IFLA_IFNAME\n"); } attr = RTA_NEXT(attr, attrlen); } } static VOID IpcEvent_Handle_STA_Event(IpcEvent_Child_t* pIpcEventChild) { S8 buf[512]; S32 left; struct sockaddr_nl from; socklen_t fromlen; struct nlmsghdr *h; fromlen = sizeof(from); left = recvfrom(pIpcEventChild->STA_socket, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr *) &from, &fromlen); if (left < 0) { os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - IpcEvent_Handle_STA_Event - cant recv from socket %X .\n", pIpcEventChild->STA_socket); return; } h = (struct nlmsghdr *) buf; while (left >= sizeof(*h)) { S32 len, plen; len = h->nlmsg_len; plen = len - sizeof(*h); if (len > left || plen < 0) { os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - IpcEvent_Handle_STA_Event - Malformed netlink message: len=%d left=%d plen=%d", len, left, plen); break; } switch (h->nlmsg_type) { case RTM_NEWLINK: IpcEvent_wext_event_rtm_newlink(pIpcEventChild, h, plen); break; } len = NLMSG_ALIGN(len); left -= len; h = (struct nlmsghdr *) ((char *) h + len); } if (left > 0) { os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - IpcEvent_Handle_STA_Event - %d extra bytes in the end of netlink ", left); IpcEvent_Handle_STA_Event(pIpcEventChild); } } static S32 IpcEvent_Handle_Parent_Event(IpcEvent_Child_t* pIpcEventChild) { S8 msg[IPC_EVENT_MSG_MAX_LEN]; S32 msgLen = read(pIpcEventChild->pipe_from_parent,msg, IPC_EVENT_MSG_MAX_LEN); msg[msgLen] = 0; if(!os_strcmp(msg, (PS8)IPC_EVENT_MSG_KILL)) { return TRUE; } if(!os_strcmp(msg, (PS8)IPC_EVENT_MSG_UPDATE_DEBUG_LEVEL)) { /* g_debug_level= pIpcEventChild->p_shared_memory->content.debug_level;*/ return FALSE; }else os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - IpcEvent_Handle_Parent_Event - unknown msgLen=%d msg=|%s| \n",msgLen,msg); return FALSE; } static VOID IpcEvent_Child_Destroy(IpcEvent_Child_t* pIpcEventChild) { if(pIpcEventChild->STA_socket) { IpcEvent_Sockets_Close(pIpcEventChild->STA_socket); } } static VOID IpcEvent_Child(IpcEvent_Child_t* pIpcEventChild) { /* open the socket from the driver */ pIpcEventChild->STA_socket = IpcEvent_Sockets_Open(); if(pIpcEventChild->STA_socket < 0) { os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - IpcEvent_Create - cant open socket for communication with the driver (%d)\n",pIpcEventChild->STA_socket); return; } while(1) { fd_set read_set; /* File descriptors for select */ S32 ret; FD_ZERO(&read_set); FD_SET(pIpcEventChild->STA_socket, &read_set); FD_SET(pIpcEventChild->pipe_from_parent, &read_set); #ifndef ANDROID ret = select(max(pIpcEventChild->pipe_from_parent,pIpcEventChild->STA_socket) + 1, &read_set, NULL, NULL, NULL); #else ret = select(pIpcEventChild->STA_socket + 1, &read_set, NULL, NULL, NULL); #endif if(ret < 0) { os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - IpcEvent_Child - Unhandled signal - exiting...\n"); break; } if(ret == 0) { continue; } /* Check for interface discovery events. */ if(FD_ISSET(pIpcEventChild->STA_socket, &read_set)) IpcEvent_Handle_STA_Event(pIpcEventChild); #ifndef ANDROID if(FD_ISSET(pIpcEventChild->pipe_from_parent, &read_set)) { S32 exit = IpcEvent_Handle_Parent_Event(pIpcEventChild); if(exit) break; } #endif } IpcEvent_Child_Destroy(pIpcEventChild); } /* functions */ /*************/ THandle IpcEvent_Create(VOID) { IpcEvent_t* pIpcEvent = (IpcEvent_t*)os_MemoryCAlloc(sizeof(IpcEvent_t), sizeof(U8)); if(pIpcEvent == NULL) { os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - IpcEvent_Create - cant allocate control block\n"); return NULL; } /* create a shared memory space */ pIpcEvent->p_shared_memory = mmap(0, sizeof(IpcEvent_Shared_Memory_t), PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0); if ( pIpcEvent->p_shared_memory == ((PVOID)-1)) { os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - IpcEvent_Create - cant allocate shared memory\n"); IpcEvent_Destroy(pIpcEvent); return NULL; } /* create a pipe */ pipe(pIpcEvent->p_shared_memory->pipe_fields); /* set the event mask to all disabled */ pIpcEvent->p_shared_memory->event_mask = 0; /* Create a child process */ pIpcEvent->child_process_id = fork(); if (0 == pIpcEvent->child_process_id) { /******************/ /* Child process */ /****************/ IpcEvent_Child_t* pIpcEventChild = (IpcEvent_Child_t*)os_MemoryCAlloc(sizeof(IpcEvent_Child_t), sizeof(U8)); if(pIpcEventChild == NULL) { os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - IpcEvent_Create - cant allocate child control block\n"); _exit(1); } pIpcEventChild->p_shared_memory = pIpcEvent->p_shared_memory; pIpcEventChild->pipe_from_parent = pIpcEventChild->p_shared_memory->pipe_fields[PIPE_READ]; close(pIpcEventChild->p_shared_memory->pipe_fields[PIPE_WRITE]); IpcEvent_Child(pIpcEventChild); os_MemoryFree(pIpcEventChild); _exit(0); } pIpcEvent->pipe_to_child = pIpcEvent->p_shared_memory->pipe_fields[PIPE_WRITE]; close(pIpcEvent->p_shared_memory->pipe_fields[PIPE_READ]); return pIpcEvent; } VOID IpcEvent_Destroy(THandle hIpcEvent) { IpcEvent_t* pIpcEvent = (IpcEvent_t*)hIpcEvent; if((pIpcEvent->p_shared_memory != ((PVOID)-1)) && (pIpcEvent->p_shared_memory)) { munmap(pIpcEvent->p_shared_memory, sizeof(IpcEvent_Shared_Memory_t)); } /* kill child process */ kill(pIpcEvent->child_process_id, SIGKILL); os_MemoryFree(pIpcEvent); } S32 IpcEvent_EnableEvent(THandle hIpcEvent, U32 event) { IpcEvent_t* pIpcEvent = (IpcEvent_t*)hIpcEvent; if(pIpcEvent->p_shared_memory->event_mask & ((u64)1 << event)) { return EOALERR_IPC_EVENT_ERROR_EVENT_ALREADY_ENABLED; } else { pIpcEvent->p_shared_memory->event_mask |= ((u64)1 << event); } return OK; } S32 IpcEvent_DisableEvent(THandle hIpcEvent, U32 event) { IpcEvent_t* pIpcEvent = (IpcEvent_t*)hIpcEvent; if(!(pIpcEvent->p_shared_memory->event_mask & (1 << event))) { return EOALERR_IPC_EVENT_ERROR_EVENT_ALREADY_DISABLED; } else { pIpcEvent->p_shared_memory->event_mask &= ~(1 << event); } return OK; } S32 IpcEvent_UpdateDebugLevel(THandle hIpcEvent, S32 debug_level) { IpcEvent_t* pIpcEvent = (IpcEvent_t*)hIpcEvent; pIpcEvent->p_shared_memory->content.debug_level = debug_level; IpcEvent_SendMessageToChild(pIpcEvent, (PS8)IPC_EVENT_MSG_UPDATE_DEBUG_LEVEL); return OK; }