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; }
/* * EvDeleteGroup() removes and event group from the system. This function * is not allowed to succed if there are event subscribers waiting on this * event group. First the local structures for the event group are removed. * Once this is done if this is an events. * * Looks like this still needs some work. */ int EvDeleteGroup(EvGroupID_t groupID, EvAccess_t accessCode) { EvGroupInfo_t *TmpGroup; EvGroupInfo_t *FreeGroup; unsigned long Flags; write_lock_irqsave(&EvGroupLock, Flags); if (EvGroupHead == NULL) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_EXIST; } /* Check to see if this is at the head. If so this is the local * group and in not deletable. */ if (EvGroupHead->EgiID == groupID) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_BUSY; } TmpGroup = EvGroupHead; while(TmpGroup->EgiNext) { if (TmpGroup->EgiNext->EgiID == groupID) { FreeGroup = TmpGroup->EgiNext; if (FreeGroup->EgiUseCount > 1) { /* For now just do not allow unregisteration. */ write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_BUSY; } if (EvCheckAccessCode(FreeGroup->EgiAccessCode, accessCode)) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_ACCESS; } EvInternalUnRegisterEventClass(FreeGroup, 0, EvGetClassAccess(FreeGroup, 0)); TmpGroup->EgiNext = FreeGroup->EgiNext; write_unlock_irqrestore(&EvGroupLock, Flags); kfree(FreeGroup->EgiClassHash); kfree(FreeGroup); return EV_NOERR; } TmpGroup = TmpGroup->EgiNext; } write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_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 is as yet incomplete and is here for a particular use. More * to follow. DO NOT USE. */ int EvTakeOverMaster(EvGroupID_t groupID, EvGroupID_t memberID, EvAccess_t accessCode) { EvGroupInfo_t *EGroup = EvGroupHead; unsigned long Flags; write_lock_irqsave(&EvGroupLock, Flags); /* Has the event group already been created or not? */ while (EGroup && (EGroup->EgiID != groupID)) { EGroup = EGroup->EgiNext; } if (EGroup == NULL) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_EXIST; } /* If this is not a master group control the error */ if (EGroup->EgiType != EG_MEMBER) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_TYPE; } /* Permissions? */ if (EvCheckAccessCode(EGroup->EgiAccessCode, accessCode)) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_ACCESS; } if (memberID == EGroup->EgiMemberID) { /* This instance is taking over as master. */ EGroup->EgiType = EG_MASTER; EGroup->EgiMasterID = EGroup->EgiMemberID; EGroup->EgiNextMemberID = memberID + 1; } else { /* Set the new master instance. */ } write_unlock_irqrestore(&EvGroupLock, Flags); return EV_NOERR; }
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; }
/* * 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 EvInternalUnRegisterEventClass(EvGroupInfo_t *eGroup, EvClassID_t classID, EvAccess_t accessCode) { EvClassInfo_t *HashBase; EvClassInfo_t* HashDel; HashBase = EvGetHashBase(eGroup, classID); /* Does this hash have any classes assigned? */ if (HashBase->EciNext == NULL) { return -EV_ERROR_CLASS_EXISTS; } /* Is the top element his class? */ if (HashBase->EciClass == classID) { /* If subscribers use count is not zero then return error. */ if (HashBase->EciUseCount != 0) { return -EV_ERROR_CLASS_BUSY; } if (EvCheckAccessCode(HashBase->EciAccessCode, accessCode)) { return -EV_ERROR_CLASS_ACCESS; } HashDel = HashBase->EciNext; HashBase->EciClass = HashDel->EciClass; strncpy(HashBase->EciName, HashDel->EciName, 16); HashBase->EciEventQ = HashDel->EciEventQ; HashBase->EciNext = HashDel->EciNext; goto EvDelHashInfo; } HashDel = HashBase->EciNext; while(HashDel->EciNext != NULL) { if (HashDel->EciClass == classID) { break; } HashBase = HashDel; HashDel = HashDel->EciNext; } if (HashDel->EciNext == NULL) { return -EV_ERROR_CLASS_EXISTS; } if (HashDel->EciUseCount != 0) { return -EV_ERROR_CLASS_BUSY; } if (EvCheckAccessCode(HashDel->EciAccessCode, accessCode)) { return -EV_ERROR_CLASS_ACCESS; } HashBase->EciNext = HashDel->EciNext; EvDelHashInfo: /* Now reaquire the Group lock decrement the use count and send * remote packets. */ eGroup->EgiUseCount--; /* If this is a master send remove packets to all members. */ if (eGroup->EgiType == EG_MASTER) { EvSendUnRegClassToMembers(eGroup, classID, accessCode); } if (HashDel->EciEventQ) { kfree(HashDel->EciEventQ); } kfree(HashDel); return EV_NOERR; }
int EvDetachGroup(EvGroupID_t groupID, EvGroupID_t memberID, EvAccess_t accessCode) { EvGroupInfo_t *EGroup = EvGroupHead; unsigned long Flags; EvMemberList_t *Member; EvMemberList_t *FreeMember; write_lock_irqsave(&EvGroupLock, Flags); /* Has the event group already been created or not? */ while (EGroup && (EGroup->EgiID != groupID)) { EGroup = EGroup->EgiNext; } if (EGroup == NULL) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_EXIST; } /* If this is not a master group control the error */ if (EGroup->EgiType != EG_MASTER) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_TYPE; } /* Are there any members registered? */ if (EGroup->EgiMembers == NULL) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_MEMBER_EXIST; } /* Permissions? */ if (EvCheckAccessCode(EGroup->EgiAccessCode, accessCode)) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_ACCESS; } /* Find the member pointer */ if (EGroup->EgiMembers->EslID == memberID) { FreeMember = EGroup->EgiMembers; EGroup->EgiMembers = EGroup->EgiMembers->EslNext; /* Do not forget to indicate the member is gone. */ EGroup->EgiUseCount--; write_unlock_irqrestore(&EvGroupLock, Flags); kfree(FreeMember); return EV_NOERR; } Member = EGroup->EgiMembers; while (Member->EslNext) { if (Member->EslNext->EslID == memberID) { FreeMember = Member->EslNext; Member->EslNext = FreeMember->EslNext; /* Do not forget to indicate the member is gone. */ EGroup->EgiUseCount--; write_unlock_irqrestore(&EvGroupLock, Flags); kfree(FreeMember); return EV_NOERR; } Member = Member->EslNext; } write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_MEMBER_EXIST; }
int EvAttachGroup(EvGroupID_t groupID, char *memberName, EvAccess_t accessCode, EvGroupID_t *memberID) { EvGroupInfo_t *EGroup = EvGroupHead; unsigned long Flags; EvMemberList_t *Member; write_lock_irqsave(&EvGroupLock, Flags); /* Has the event group already been created or not? */ while (EGroup && (EGroup->EgiID != groupID)) { EGroup = EGroup->EgiNext; } if (EGroup == NULL) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_EXIST; } /* If this is not a master group control the error */ if (EGroup->EgiType != EG_MASTER) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_TYPE; } /* Permissions? */ if (EvCheckAccessCode(EGroup->EgiAccessCode, accessCode)) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_GROUP_ACCESS; } /* Has this member already been registered? */ Member = EGroup->EgiMembers; while (Member) { if (!strncmp(Member->EslName, memberName, 16)) { return -EV_ERROR_MEMBER_EXIST; } Member = Member->EslNext; } /* Now allocate an element to store the member info into. */ if (EGroup->EgiMembers == NULL) { if ((EGroup->EgiMembers = kmalloc(sizeof(EvMemberList_t), GFP_ATOMIC)) == NULL) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_MEM_ALLOC; } Member = EGroup->EgiMembers; } else { Member = EGroup->EgiMembers; while (Member->EslNext != NULL) { Member = Member->EslNext; } if ((Member->EslNext = kmalloc(sizeof(EvMemberList_t), GFP_ATOMIC)) == NULL) { write_unlock_irqrestore(&EvGroupLock, Flags); return -EV_ERROR_MEM_ALLOC; } Member = Member->EslNext; } /* Fill in the member information. */ strncpy(Member->EslName, memberName, 16); Member->EslID = EGroup->EgiNextMemberID++; Member->EslNext = NULL; /* Incrementing use count prevents the master from deleting * the event group control structures while remotes are trying * to use it; */ EGroup->EgiUseCount++; /* Fill in returned member ID value */ *memberID = Member->EslID; write_unlock_irqrestore(&EvGroupLock, Flags); return EV_NOERR;; }