Example #1
0
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;
}
Example #2
0
/*
 * 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;
}
Example #3
0
/*
 * 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;
}
Example #4
0
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;
}