int EvCompGetMemberName(EvGroupID_t groupID, EvGroupID_t memberID, int error, char * memberName) { EvGroupInfo_t *EGroup; EvPendRem_t *Pend; unsigned long Flags; read_lock_irqsave(&EvGroupLock, Flags); if ((EGroup = EvGetGroupBase(groupID)) == NULL) { read_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_EXIST; } write_lock(&EGroup->EgiLock); read_unlock(&EvGroupLock); /* Pend the pending control struct for this ID. */ if ((Pend = EvFindPendEntry(EGroup, EV_REM_GET_MEMBER_NAME, memberID, 0, 0, 0, 0, NULL)) == NULL) { write_unlock_irqrestore(&EGroup->EgiLock, Flags); return -EV_ERROR_NO_REQUESTOR; } /* Fill in the return values. */ Pend->PrRetInfo.EpInfo[0] = error; Pend->PrRetInfo.EpData = memberName; /* Wake up the requester. */ wake_up_interruptible(&Pend->PrWaitQ); write_unlock_irqrestore(&EGroup->EgiLock, Flags); return EV_NOERR; }
int EvSetClassAccessCode(EvGroupID_t groupID, EvClassID_t classID, EvAccess_t oldCode, EvAccess_t newCode) { EvGroupInfo_t *EGroup; EvClassInfo_t *HashBase; EvClassInfo_t *ClassBase; EvDestBase_t *EventBase; unsigned long Flags; read_lock_irqsave(&EvGroupLock, Flags); if ((EGroup = EvGetGroupBase(groupID)) == NULL) { read_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_EXIST; } HashBase = EvGetHashBase(EGroup, classID); spin_lock(&HashBase->EciLock); read_unlock(&EvGroupLock); if ((EventBase = EvFindEventBase(classID,HashBase,&ClassBase))==NULL) { spin_unlock_irqrestore(&HashBase->EciLock, Flags); return -EV_ERROR_CLASS_EXISTS; } if (EvCheckAccessCode(ClassBase->EciAccessCode, oldCode)) { spin_unlock_irqrestore(&HashBase->EciLock, Flags); return -EV_ERROR_CLASS_ACCESS; } ClassBase->EciAccessCode = newCode; spin_unlock_irqrestore(&HashBase->EciLock, Flags); return EV_NOERR; }
/* * Connection daemon has recieved a message from the event master * that a new class is available for this member. This function * registers that new class. */ int EvRemoteRegisterEventClass(EvGroupID_t groupID, char *className, EvAccess_t groupAccessCode, EvAccess_t classAccessCode, int error, EvClassID_t classID) { EvGroupInfo_t *EGroup; EvPendRem_t *Pend; EvClassInfo_t *HashBase; unsigned long Flags; int RetVal; read_lock_irqsave(&EvGroupLock, Flags); if ((EGroup = EvGetGroupBase(groupID)) == NULL) { read_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_EXIST; } write_lock(&EGroup->EgiLock); read_unlock(&EvGroupLock); /* Pend the pending control struct for this ID. * * If Pend is NULL then this is the master reporting a new event * class. */ if ((Pend = EvFindPendEntry(EGroup, EV_REM_REGISTER_EVENT_CLASS, groupAccessCode, classAccessCode, 0, 0, strlen(className)+1, className)) != NULL) { /* Fill in the return values. */ Pend->PrRetInfo.EpInfo[0] = error; Pend->PrRetInfo.EpInfo[1] = classID; /* Wake up the requester. */ wake_up_interruptible(&Pend->PrWaitQ); write_unlock_irqrestore(&EGroup->EgiLock, Flags); return EV_NOERR; } /* Register a new event class on a group member for the master. */ HashBase = EvGetHashBase(EGroup, classID); while (HashBase->EciNext != NULL) { HashBase = HashBase->EciNext; } RetVal=EvFillInHashInfo(HashBase, classAccessCode, className, &classID); write_unlock_irqrestore(&EGroup->EgiLock, Flags); return RetVal; }
int EvGetMemberName(EvGroupID_t groupID, EvGroupID_t memberID, char *memberName) { EvGroupInfo_t *EGroup; EvMemberList_t *Member; unsigned long Flags; write_lock_irqsave(&EvGroupLock, Flags); if ((EGroup = EvGetGroupBase(groupID)) == NULL) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_EXIST; } write_lock(&EGroup->EgiLock); write_unlock(&EvGroupLock); /* If this is a member and not a master group controler. */ if (EGroup->EgiType == EG_MEMBER) { /* If the member is this group member then localize. */ if (EGroup->EgiMemberID == memberID) { strncpy(memberName, EGroup->EgiMemberName, 16); write_unlock_irqrestore(&EGroup->EgiLock, Flags); return EV_NOERR; } return EvSendGetMemberName(EGroup, memberID, memberName, Flags); } if (EGroup->EgiMemberID == memberID) { strncpy(memberName, EGroup->EgiMemberName, 16); write_unlock_irqrestore(&EGroup->EgiLock, Flags); return EV_NOERR; } Member = EGroup->EgiMembers; while (Member) { if (Member->EslID == memberID) { strncpy(memberName, Member->EslName, 16); write_unlock_irqrestore(&EGroup->EgiLock, Flags); return EV_NOERR; } Member = Member->EslNext; } write_unlock_irqrestore(&EGroup->EgiLock, Flags); return -EV_ERROR_MEMBER_EXIST; }
int EvSubscribeGroupEvents(EvUserID_t userID, EvGroupID_t groupID, EvAccess_t accessCode, int (*kernelCB)(EvUserID_t, int, EvGroupID_t, EvGroupID_t, EvClassID_t, EvEventID_t, int, int, int, int, int, void *)) { EvKernelInfo_t *EventUser; EvGroupInfo_t *EGroup; unsigned long Flags; read_lock_irqsave(&EvUsersLock, Flags); if ((EventUser = EvCheckUser(userID)) == NULL) { read_unlock_irqrestore(&EvUsersLock, Flags); return -EV_ERROR_USER_EXISTS; } write_lock(&EvGroupLock); read_unlock(&EvUsersLock); if ((EGroup = EvGetGroupBase(groupID)) == NULL) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_EXIST; } /* Check the access code for the group. */ if (EvCheckAccessCode(EGroup->EgiAccessCode, accessCode)) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_ACCESS; } /* Check that there are no current control processes. */ if (EGroup->EgiGroupDest.EdID != 0) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_BUSY; } EGroup->EgiGroupDest.EdPri = 0; /* Not used. */ EGroup->EgiGroupDest.EdID = userID; EGroup->EgiGroupDest.EdUinfo = NULL; EGroup->EgiGroupDest.EdCB = kernelCB; EGroup->EgiGroupDest.EdKinfo = EventUser; EGroup->EgiUseCount++; write_unlock_irqrestore(&EvGroupLock, Flags); return EV_NOERR; }
/* * This function returns the name of the event group identified by the ID * field. */ int EvGetGroupName(EvGroupID_t groupID, char *name) { EvGroupInfo_t *EGroup; unsigned long Flags; write_lock_irqsave(&EvGroupLock, Flags); if ((EGroup = EvGetGroupBase(groupID)) == NULL) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_EXIST; } strncpy(name, EGroup->EgiName, 16); write_unlock_irqrestore(&EvGroupLock, Flags); return EV_NOERR; }
int EvRemoteUnRegisterEventClass(EvGroupID_t groupID, EvClassID_t classID, EvAccess_t accessCode, int error) { EvGroupInfo_t *EGroup; EvPendRem_t *Pend; unsigned long Flags; int RetVal; read_lock_irqsave(&EvGroupLock, Flags); if ((EGroup = EvGetGroupBase(groupID)) == NULL) { read_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_EXIST; } write_lock(&EGroup->EgiLock); read_unlock(&EvGroupLock); /* Pend the pending control struct for this ID. * * If Pend is NULL then this is the master reporting a new event * class. */ if ((Pend = EvFindPendEntry(EGroup, EV_REM_UNREGISTER_EVENT_CLASS, accessCode, classID, 0, 0, 0, NULL)) != NULL) { /* Fill in the return values. */ Pend->PrRetInfo.EpInfo[0] = error; /* Wake up the requester. */ wake_up_interruptible(&Pend->PrWaitQ); write_unlock_irqrestore(&EGroup->EgiLock, Flags); return EV_NOERR; } RetVal = EvInternalUnRegisterEventClass(EGroup, classID, accessCode); write_unlock_irqrestore(&EGroup->EgiLock, Flags); return RetVal; }
int EvSetGroupAccessCode(EvGroupID_t groupID, EvAccess_t oldCode, EvAccess_t newCode) { EvGroupInfo_t *EGroup; unsigned long Flags; read_lock_irqsave(&EvGroupLock, Flags); if ((EGroup = EvGetGroupBase(groupID)) == NULL) { read_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_EXIST; } if (EvCheckAccessCode(EGroup->EgiAccessCode, oldCode)) { read_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_ACCESS; } EGroup->EgiAccessCode = newCode; write_unlock_irqrestore(&EvGroupLock, Flags); return EV_NOERR; }
int EvUnSubscribeGroupEvents(EvUserID_t userID, EvGroupID_t groupID) { EvKernelInfo_t *EventUser; EvGroupInfo_t *EGroup; unsigned long Flags; read_lock_irqsave(&EvUsersLock, Flags); if ((EventUser = EvCheckUser(userID)) == NULL) { read_unlock_irqrestore(&EvUsersLock, Flags); return -EV_ERROR_USER_EXISTS; } write_lock(&EvGroupLock); read_unlock(&EvUsersLock); if ((EGroup = EvGetGroupBase(groupID)) == NULL) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_EXIST; } /* Check that there are no current control processes. */ if (EGroup->EgiGroupDest.EdID != userID) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_ACCESS; } EGroup->EgiGroupDest.EdID = 0; EGroup->EgiGroupDest.EdUinfo = NULL; EGroup->EgiGroupDest.EdCB = NULL; EGroup->EgiGroupDest.EdKinfo = NULL; EGroup->EgiUseCount--; write_unlock_irqrestore(&EvGroupLock, Flags); return EV_NOERR; }
/* * EvUnSubscribeEvent() removes the user id from the list of subscribers * waiting for the particular event to occur. * * If the user ID does not indicate a currently registered user then * -ENOENT is returned. If the event group is not a currently registered * group then -EEXIST is returned. If the class in not found in the this * of currently know classes then -EINVAL is returned. If the user is * not currently subscribed to recieve the event then -EBUSY is returned. * * Otherwise the subscription is removed and a zero is returned to * indicate susccess. */ int EvUnSubscribeEvent(EvUserID_t userID, EvGroupID_t groupID, EvClassID_t classID, EvEventID_t eventID) { EvDest_t *EventDestP = NULL; EvDest_t *FreeDest = NULL; EvDestBase_t *EventBase; EvDestBase_t *LastEventBase = NULL; EvKernelInfo_t *EventUser; EvGroupInfo_t *EGroup; EvClassInfo_t *HashBase; EvClassInfo_t *ClassBase; unsigned long Flags; /* Check the user id. */ read_lock_irqsave(&EvUsersLock, Flags); if ((EventUser = EvCheckUser(userID)) == NULL) { read_unlock_irqrestore(&EvUsersLock, Flags); return -EV_ERROR_USER_EXISTS; } read_lock(&EvGroupLock); read_unlock(&EvUsersLock); /* Get the base event group information. */ if ((EGroup = EvGetGroupBase(groupID)) == NULL) { read_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_EXIST; } HashBase = EvGetHashBase(EGroup, classID); /* Find the top level entry for this class of events. */ if ((EventBase = EvFindEventBase(classID,HashBase,&ClassBase)) == NULL){ read_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_CLASS_EXISTS; } spin_lock(&ClassBase->EciLock); read_unlock(&EvGroupLock); /* search until the event is found in this catagory or until the * last blank element on the list if found. */ while (EventBase->EdbNext != NULL) { if (EventBase->EdbEvent == eventID) { EventDestP = &EventBase->EdbDestQ; break; } LastEventBase = EventBase; EventBase = EventBase->EdbNext; } /* If event type not found then the user process was obviously not * registered for this event. */ if (EventDestP == NULL) { spin_unlock_irqrestore(&ClassBase->EciLock, Flags); return -EV_ERROR_CLASS_NO_SUB; } if (EventDestP->EdID == userID) { if (EventDestP->EdNext == NULL) { /* This is the only element on the list so it * will be removed below. */ goto EvUnRegFreeBase; } EventDestP->EdUinfo = EventDestP->EdNext->EdUinfo; EventDestP->EdCB = EventDestP->EdNext->EdCB; EventDestP->EdID = EventDestP->EdNext->EdID; EventDestP->EdKinfo = EventDestP->EdNext->EdKinfo; FreeDest = EventDestP->EdNext; EventDestP->EdNext = EventDestP->EdNext->EdNext; goto EvUnRegFreeBase; } /* Allways search one ahead to help with single link list removal. */ while (EventDestP->EdNext->EdNext != NULL) { if (EventDestP->EdNext->EdID == userID) { FreeDest = EventDestP->EdNext; EventDestP->EdNext = EventDestP->EdNext->EdNext; goto EvUnRegFreeBase; } EventDestP = EventDestP->EdNext; } /* Entry not found in list. */ spin_unlock_irqrestore(&ClassBase->EciLock, Flags); return -EV_ERROR_CLASS_NO_SUB; EvUnRegFreeBase: EventBase->EdbUseCount--; if (EventBase->EdbUseCount == 0) { /* Nobody is registered to receive this event. */ if (LastEventBase == NULL) { /* Free the top element */ EventBase->EdbEvent = EventBase->EdbNext->EdbEvent; EventBase->EdbUseCount = EventBase->EdbNext->EdbUseCount; EventBase->EdbDestQ = EventBase->EdbNext->EdbDestQ; LastEventBase = EventBase->EdbNext; EventBase->EdbNext = LastEventBase->EdbNext; kfree(LastEventBase); } else { LastEventBase->EdbNext = EventBase->EdbNext; kfree(EventBase); } } ClassBase->EciUseCount--; kfree(FreeDest); spin_unlock_irqrestore(&ClassBase->EciLock, Flags); return EV_NOERR; }
/* * EvSubscribeEvent() subscribes a kernel component to recieve * an event. If the event call back function kernelCB is specified * events will be delivered by calling this function. Otherwise * events will be placed on an internal event queue and the queue must * be polled using the EvGetEvent function. * * This function subscribes to an event localy. It does not attempt to * inform a remote master that a subscriber has been attached. This * should be added in a later version of the function. */ int EvSubscribeEvent(EvUserID_t userID, EvPri_t pri, EvGroupID_t groupID, EvClassID_t classID, EvEventID_t eventID, EvAccess_t accessCode, int (*kernelCB)(EvUserID_t, EvPri_t, EvGroupID_t, EvGroupID_t, EvClassID_t, EvEventID_t, int, int, int, int, int, void *)) { EvDest_t *EventDestP = NULL; EvDest_t *TmpDestP = NULL; EvDest_t *LastEventDestP = NULL; EvDestBase_t *EventBase; EvKernelInfo_t *EventUser; EvGroupInfo_t *EGroup; EvClassInfo_t *HashBase; EvClassInfo_t *ClassBase; unsigned long Flags; /* Check the user ID for validity. */ read_lock_irqsave(&EvUsersLock, Flags); if ((EventUser = EvCheckUser(userID)) == NULL) { read_unlock_irqrestore(&EvUsersLock, Flags); return -EV_ERROR_USER_EXISTS; } /* Assume the Event user returned status will no change during * the life of this request. */ read_lock(&EvGroupLock); read_unlock(&EvUsersLock); /* Get the event group pointer. */ if ((EGroup = EvGetGroupBase(groupID)) == NULL) { read_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_EXIST; } HashBase = EvGetHashBase(EGroup, classID); /* Find the top level entry for this class of events. */ if ((EventBase = EvFindEventBase(classID,HashBase,&ClassBase)) == NULL){ read_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_CLASS_EXISTS; } spin_lock(&ClassBase->EciLock); read_unlock(&EvGroupLock); /* Check permissions. */ if (EvCheckAccessCode(ClassBase->EciAccessCode, accessCode)) { spin_unlock_irqrestore(&ClassBase->EciLock, Flags); return -EV_ERROR_CLASS_ACCESS; } /* search until the event is found in this catagory or until the * last blank element on the list if found. */ while (EventBase->EdbNext != NULL) { if (EventBase->EdbEvent == eventID) { EventDestP = &EventBase->EdbDestQ; break; } EventBase = EventBase->EdbNext; } /* If no destination pointer has been identified for a chain * search then this event type has not yet been registered by anybody * so fill in the last empty list element and create a new empty one * to inidcate end of list. */ if (EventDestP == NULL) { EventBase->EdbEvent = eventID; EventBase->EdbUseCount = 0; /* Create the next empty element to indicate end of list. */ if ((EventBase->EdbNext = kmalloc(sizeof(EvDestBase_t), GFP_ATOMIC)) == NULL) { spin_unlock_irqrestore(&ClassBase->EciLock, Flags); return -EV_ERROR_MEM_ALLOC; } EventBase->EdbNext->EdbNext = NULL; EventDestP = &EventBase->EdbDestQ; EventDestP->EdNext = kmalloc(sizeof(EvDest_t), GFP_ATOMIC); EventDestP->EdNext->EdNext = NULL; goto EvFillInKernelRequestPacket; } /* Now search to see if this file descriptor already has registered * for this event type. */ while (EventDestP->EdNext != NULL) { if (EventDestP->EdID == userID) { spin_unlock_irqrestore(&ClassBase->EciLock, Flags); return -EV_ERROR_CLASS_BUSY; } LastEventDestP = EventDestP; EventDestP = EventDestP->EdNext; } /* Now record the destination and create a new empty element to * indicate end of list. */ /* Most registrations go at the end of the list. */ if ((LastEventDestP != NULL) && (LastEventDestP->EdPri >= pri)) { if ((EventDestP->EdNext = kmalloc(sizeof(EvDest_t), GFP_ATOMIC)) == NULL) { spin_unlock_irqrestore(&ClassBase->EciLock, Flags); return -EV_ERROR_MEM_ALLOC; } EventDestP->EdNext->EdNext = NULL; goto EvFillInKernelRequestPacket; } EventDestP = &EventBase->EdbDestQ; /* Check the priority against the top element */ if (EventDestP->EdPri >= pri) { /* Priority of event places it somewhere in the middle */ while (EventDestP->EdNext->EdPri >= pri) { EventDestP = EventDestP->EdNext; } } if ((TmpDestP = kmalloc(sizeof(EvDest_t), GFP_ATOMIC)) == NULL) { spin_unlock_irqrestore(&ClassBase->EciLock, Flags); return -EV_ERROR_MEM_ALLOC; } TmpDestP->EdPri = EventDestP->EdPri; TmpDestP->EdUinfo = EventDestP->EdUinfo; TmpDestP->EdCB = EventDestP->EdCB; TmpDestP->EdID = EventDestP->EdID; TmpDestP->EdKinfo = EventDestP->EdKinfo; TmpDestP->EdNext = EventDestP->EdNext; EventDestP->EdNext = TmpDestP; EvFillInKernelRequestPacket: EventBase->EdbUseCount++; EventDestP->EdPri = pri; EventDestP->EdUinfo = NULL; EventDestP->EdID = userID; EventDestP->EdCB = kernelCB; EventDestP->EdKinfo = EventUser; ClassBase->EciUseCount++; spin_unlock_irqrestore(&ClassBase->EciLock, Flags); return EV_NOERR; }
int EvRemoteSendEvent(EvUserID_t senderID, EvGroupID_t memberID, EvPri_t pri, EvGroupID_t groupID, EvClassID_t classID, EvEventID_t eventID, EvAccess_t accessCode, int info0, int info1, int info2, int info3, int dataLen, void *data) { EvGroupInfo_t *EGroup; EvDestBase_t *EventBase; EvClassInfo_t *HashBase; EvClassInfo_t *ClassBase; unsigned long Flags; int RetVal; read_lock_irqsave(&EvGroupLock, Flags); if ((EGroup = EvGetGroupBase(groupID)) == NULL) { read_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_EXIST; } /* If this a remote gen to the master then echo it back to * all members. */ if (EGroup->EgiType == EG_MASTER) { if (EGroup->EgiGroupDest.EdID != 0) { RetVal = EvGroupSendEvent(senderID, pri, EGroup->EgiID, EGroup->EgiMemberID, accessCode, classID, eventID, info0, info1, info2, info3, &EGroup->EgiGroupDest, dataLen, data); if (RetVal) { read_unlock_irqrestore(&EvGroupLock, Flags); return RetVal; } } } /* If the memberID issuing the event is the same as the member * id of this system then we have been echoed back an event * we sent tot he master. Ignore it. */ if ((EGroup->EgiType == EG_MEMBER) && (EGroup->EgiMemberID == memberID)) { read_unlock_irqrestore(&EvGroupLock, Flags); return EV_NOERR; } HashBase = EvGetHashBase(EGroup, classID); if ((EventBase = EvFindEventBase(classID, HashBase, &ClassBase))==NULL) { read_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_CLASS_EXISTS; } spin_lock(&ClassBase->EciLock); read_unlock(&EvGroupLock); RetVal = _EvSendEvent(EventBase, senderID, pri, groupID, memberID, classID, eventID, info0, info1, info2, info3, dataLen, data); spin_unlock_irqrestore(&ClassBase->EciLock, Flags); return RetVal; }