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; }
/* * 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; }