FreeBSD/sys/dev/usb/usb_process.c
/*------------------------------------------------------------------------*
 *	usb_proc_msignal
 *
 * This function will queue one of the passed USB process messages on
 * the USB process queue. The first message that is not already queued
 * will get queued. If both messages are already queued the one queued
 * last will be removed from the queue and queued in the end. The USB
 * process mutex must be locked when calling this function. This
 * function exploits the fact that a process can only do one callback
 * at a time. The message that was queued is returned.
 *------------------------------------------------------------------------*/
usb_proc_msignal
This function will queue one of the passed USB process messages on
the USB process queue. The first message that is not already queued
will get queued. If both messages are already queued the one queued
last will be removed from the queue and queued in the end. The USB
process mutex must be locked when calling this function. This
function exploits the fact that a process can only do one callback
at a time. The message that was queued is returned.
usb_proc_msignal This function will queue one of the passed USB process messages on the USB process queue . The first message that is not already queued will get queued . If both messages are already queued the one queued last will be removed from the queue and queued in the end . The USB process mutex must be locked when calling this function . This function exploits the fact that a process can only do one callback at a time . The message that was queued is returned .
void   *
usb_proc_msignal(struct usb_process *up, void *_pm0, void *_pm1)
{
	struct usb_proc_msg *pm0 = _pm0;
	struct usb_proc_msg *pm1 = _pm1;
	struct usb_proc_msg *pm2;
	usb_size_t d;
	uint8_t t;
	if (up->up_gone)
		return (_pm0);
	mtx_assert(up->up_mtx, MA_OWNED);
	t = 0;
	if (pm0->pm_qentry.tqe_prev) {
		t |= 1;
	}
	if (pm1->pm_qentry.tqe_prev) {
		t |= 2;
	}
	if (t == 0) {
		pm2 = pm0;
	} else if (t == 1) {
		if (pm0->pm_num == up->up_msg_num) {
			up->up_msg_num++;
		}
		pm2 = pm1;
	} else if (t == 2) {
		if (pm1->pm_num == up->up_msg_num) {
			up->up_msg_num++;
		}
		pm2 = pm0;
	} else if (t == 3) {
		d = (pm1->pm_num - pm0->pm_num);
		if (d & 0x80000000) {
			pm2 = pm0;
		} else {
			pm2 = pm1;
		}
		TAILQ_REMOVE(&up->up_qhead, pm2, pm_qentry);
	} else {
		pm2 = NULL;		
	}
	DPRINTF(" t=%u, num=%u\n", t, up->up_msg_num);
	pm2->pm_num = up->up_msg_num;
	TAILQ_INSERT_TAIL(&up->up_qhead, pm2, pm_qentry);
	if (up->up_msleep) {
		up->up_msleep = 0;	
		cv_signal(&up->up_cv);
	}
	return (pm2);
}
void * usb_proc_msignal ( struct usb_process * up , void * _pm0 , void * _pm1 ) { struct usb_proc_msg * pm0 = _pm0 ; struct usb_proc_msg * pm1 = _pm1 ; struct usb_proc_msg * pm2 ; usb_size_t d ; uint8_t t ; if ( up -> up_gone ) return ( _pm0 ) ; mtx_assert ( up -> up_mtx , MA_OWNED ) ; t = 0 ; if ( pm0 -> pm_qentry . tqe_prev ) { t |= 1 ; } if ( pm1 -> pm_qentry . tqe_prev ) { t |= 2 ; } if ( t == 0 ) { pm2 = pm0 ; } else if ( t == 1 ) { if ( pm0 -> pm_num == up -> up_msg_num ) { up -> up_msg_num ++ ; } pm2 = pm1 ; } else if ( t == 2 ) { if ( pm1 -> pm_num == up -> up_msg_num ) { up -> up_msg_num ++ ; } pm2 = pm0 ; } else if ( t == 3 ) { d = ( pm1 -> pm_num - pm0 -> pm_num ) ; if ( d & 0x80000000 ) { pm2 = pm0 ; } else { pm2 = pm1 ; } TAILQ_REMOVE ( & up -> up_qhead , pm2 , pm_qentry ) ; } else { pm2 = NULL ; } DPRINTF ( " \n " , t , up -> up_msg_num ) ; pm2 -> pm_num = up -> up_msg_num ; TAILQ_INSERT_TAIL ( & up -> up_qhead , pm2 , pm_qentry ) ; if ( up -> up_msleep ) { up -> up_msleep = 0 ; cv_signal ( & up -> up_cv ) ; } return ( pm2 ) ; }
usb_proc_msignal
 This function will queue one of the passed USB process messages on
 the USB process queue.
usb_proc_msignal This function will queue one of the passed USB process messages on the USB process queue .
/* check if gone, return dummy value */ /*
		 * No entries are queued. Queue "pm0" and use the existing
		 * message number.
		 */ /* Check if we need to increment the message number. */ /* Check if we need to increment the message number. */ /*
		 * Both entries are queued. Re-queue the entry closest to
		 * the end.
		 */ /* Check sign after subtraction */ /* panic - should not happen */ /* Put message last on queue */ /* Check if we need to wakeup the USB process. */ /* save "cv_signal()" calls */