📄 mh_handset.c
字号:
LEDOFF(LED_ID_RING); }}/************************************************************************** * HandsetVMWI * Turn on/off the VMWI on a given handset * oLineNumber - line on which to set the VMWI * bOn - 1=ON, 0=OFF **************************************************************************/void HandsetVMWI(OCTET oLineNumber, BOOL bOn){ HANDSET *pHandset = &pxHandset[oLineNumber-1]; if (!g_bHandsetStarted) return; if ((!pHandset->bOffHook) && (pHandset->oPhoneState == HSTATE_ONHOOK_IDLE)) { /* Start VMWI OSI state, pull line power low */ _HandsetStartStateSequence(oLineNumber, pSEQ_VMWI); } pHandset->oVMWIStatus = bOn?VMWI_TURN_ON:VMWI_TURN_OFF;}/************************************************************************** * HandsetGenerateTone * Turn a given tone on or off. If bOn = ON, the currently active tone * is switched off and the new tone dwTone is played locally. If bOn = OFF * the tone dwTone is removed from the tone queue. If dwTone is currently * playing, it will be switched off. It dwTone has been queued to play at * a later stage, it will be removed from the tone queue. * oLineNumber - Line on which to activate tone * dwTone - tone to switch on/off. * bOn - 0=OFF, 1=ON **************************************************************************/void HandsetGenerateTone(OCTET oLineNumber, DWORD dwTone, BOOL bOn){ HANDSET *pHandset = &pxHandset[oLineNumber-1]; if (!g_bHandsetStarted) return;#ifdef HOOKER HandsetHookerSendToneEvent(oLineNumber, dwTone, bOn);#endif /* Handle special tones (e.g. ring tone, CWT, VMWI etc...) */ switch (dwTone) { /* Ring tones - handled differently */ case HANDSET_RING0: case HANDSET_RING1: case HANDSET_RING2: case HANDSET_RING3: case HANDSET_RING4: case HANDSET_RING5: case HANDSET_RING6: case HANDSET_RING7: case HANDSET_RING8: case HANDSET_RING9: if (!pHandset->bOffHook) { if (bOn) { /* Load the appropriate ring cadence pattern */ LoadRingCadencePattern(&(pHandset->xRingCadencePattern),dwTone); pHandset->bFirstRing = TRUE; pHandset->oRingPatternCount = 0; pHandset->dwRingTimer = pHandset->xRingCadencePattern.wPatternDurations[0]; /* Make sure there is power on the line */ _HandsetLineVoltagePolarity(oLineNumber,1); HandsetLinePower(oLineNumber,1); /* Do we have CID info to display?*/ if (pHandset->pCID != NULL) { _HandsetStartStateSequence(oLineNumber,pSEQ_RING_WITH_CID); } else { /* Before ring sequence starts, wait a short while (100ms) for CID info * to arrive from the application */ _HandsetStartStateSequence(oLineNumber,pSEQ_RING_WITH_WAIT_FOR_CID); } } else { HandsetRinger(oLineNumber,OFF); pHandset->bRinging = FALSE; pHandset->bFirstRing = FALSE; _HandsetSetState(oLineNumber,HSTATE_ONHOOK_IDLE,INDEFINITE); } } break; /* All tones, includes ring tone */ case AUDIO_TONE_ALL: if (!bOn) { if (pHandset->bRinging) { _HandsetSetState(oLineNumber,HSTATE_ONHOOK_IDLE,INDEFINITE); pHandset->bRinging = FALSE; pHandset->bFirstRing = FALSE; } if (pHandset->bOffHook) _HandsetSetState(oLineNumber,HSTATE_OFFHOOK_IDLE,INDEFINITE); } _HandsetPlayTone(oLineNumber,dwTone,bOn); break; /* Call waiting tone - need to start timer for subsequent CID info */ case AUDIO_CALLWAITING: case AUDIO_CALLWAITING2: case AUDIO_CALLWAITING3: case AUDIO_CALLWAITING4: if (bOn && pHandset->oPhoneState != HSTATE_OFFHOOK_CWT_ON) { _HandsetSetState(oLineNumber,HSTATE_OFFHOOK_CWT_ON,500); _HandsetPlayTone(oLineNumber,dwTone,bOn); } break; default: _HandsetPlayTone(oLineNumber,dwTone,bOn); break; }}#ifndef HANDSET_NO_CALLER_ID/************************************************************************** * HandsetDisplayCallerID * Saves and prepares CID data for sending to handset * oLineNumber - line number to send CID data to * pxCID - CALLER_ID_INFO structure containing caller ID data * * NOTE: This *SHOULD* be called before HandsetGenerateTone(HANDSET_RING) * if caller ID is to be accompanied with ringing **************************************************************************/void HandsetDisplayCallerID(OCTET oLineNumber, CALLER_ID_INFO *pxCID){ HANDSET *pHandset = &pxHandset[oLineNumber-1]; if (!g_bHandsetStarted) return; if (pHandset->pCID != NULL) { free(pHandset->pCID); } /* Copy and store CID info */ pHandset->pCID = (CALLER_ID_INFO *)calloc(1,sizeof(CALLER_ID_INFO)); pHandset->pCID->tmCallTime = pxCID->tmCallTime; if (strlen(pxCID->pcCallerName)) strncpy(pHandset->pCID->pcCallerName,pxCID->pcCallerName,CALLERNAME_MAX_LENGTH); if (strlen(pxCID->pcCallerNumber)) strncpy(pHandset->pCID->pcCallerNumber,pxCID->pcCallerNumber,CALLERNUMBER_MAX_LENGTH); /* Is the handset off-hook and no call waiting tone is busy playing? If so, * send CID data in off-hook transmission mode */ if (pHandset->oPhoneState == HSTATE_OFFHOOK_IDLE) { _SendCallerIDData(oLineNumber,FALSE); _HandsetSetState(oLineNumber,HSTATE_OFFHOOK_CWT_ON,500); } /* Check to see if ringing state sequence has started. This might happen * if the ring signal arrives from the top application before the caller ID * data is sent. Some ring sequences start with a 100ms general delay to * wait for any caller ID info to arrive from the application, as they * need to do special things to send CID before ringing starts. */ else if (!pHandset->bOffHook && pHandset->oPhoneState == HSTATE_WAITING_FOR_CID) { /* CID arrived, start ring sequence with CID */ _HandsetStartStateSequence(oLineNumber,pSEQ_RING_WITH_CID); }}/************************************************************************** * HandsetDisplayCallerIDWithCWT * Saves and prepares CID data for sending to handset * Also plays CWT before sending CID data * oLineNumber - line number to send CID data to * pxCID - CALLER_ID_INFO structure containing caller ID data **************************************************************************/void HandsetDisplayCallerIDWithCWT(OCTET oLineNumber, CALLER_ID_INFO *pxCID){ if (!g_bHandsetStarted) return; HandsetGenerateTone(oLineNumber,AUDIO_CALLWAITING,1); HandsetDisplayCallerID(oLineNumber,pxCID);}/************************************************************************** * HandsetStoreCallerID * Append a caller ID info to the calls history list * oLineNumber - line number to send CID data to * pxCallerInfo - pointer to the incoming CALLER_ID_INFO **************************************************************************/void HandsetStoreCallerID(OCTET oLineNumber, CALLER_ID_INFO *pxCallerInfo){}#endif // HANDSET_NO_CALLER_ID/************************************************************************** * HandsetProcess * Queries a handset for any events (hook events, DTMF events) * * NOTE: This function should be called from within the main application * loop (i.e. it should be called every 10ms). All timers in the * handset state machine are thus assumed to clock every 10ms. * * The following are returned to the calling application under the various * scenarios: * * HANDSET_HOOK_DOWN_EVENT: [Returned by MediaHub and IPPhone] * Hookswitch has been pressed, may be start of "hit", "flash" or "true" * onhook event * * HANDSET_ON_HOOK_EVENT: [Returned by MediaHub and IPPhone] * "True" long term on-hook event (i.e. not hook "hit" or "flash") * * HANDSET_HIT_HOOK_EVENT: [Returned by MediaHub and IPPhone] * Hookswitch has been lifted, but it's hook "hit" event * (on hook for < 200ms) * * HANDSET_FLASH_HOOK_EVENT: [Returned by MediaHub and IPPhone] * Hookswitch has been lifted, but it's hook "flash" event * (on hook for > 200ms and < 1100ms) * * HANDSET_OFF_HOOK_EVENT: [Returned by MediaHub and IPPhone] * Hookswitch has been lifted. It's a "True" long term off-hook event * (i.e. not part of hook "hit" or "flash") * * HANDSET_DIAL_EVENT: [Returned by IPPhone only] * A number is to be dialled. This would be returned if the handset is * off hook and/or speakerphone mode is on. The number to redial is * returned in chKeyPressed. * * HANDSET_OFF_HOOK_WITH_DIAL_EVENT: [Returned by IPPhone only] * Same as HANDSET_OFF_HOOK_EVENT, but there is also a number to be * dialled at the same time. This would occur if REDIAL key pressed * while handset is on hook and speakerphone mode is off. The number * to dial is returned in chKeyPressed * * HANDSET_KEY_DOWN_EVENT: [Returned by MediaHub and IPPhone] * Returned at start of a key press event. The key character is returned * in chKeyPressed. * * HANDSET_KEY_UP_EVENT: [Returned by MediaHub and IPPhone] * Returned at end of a key press event. The key character is returned * in chKeyPressed. * * HANDSET_MODEM_TONE_EVENT: [Returned by MediaHub only] * Returned when a modem tone (V.21) is detected. * * HANDSET_FAX_TONE_EVENT: [Returned by MediaHub only] * Returned when a fax tone (CNG) is detected. * * HANDSET_ANSWER_TONE_EVENT: [Returned by MediaHub only] * Returned when a modem answer tone is detected. * * HANDSET_LONG_DURATION_DTMF_EVENT: [Returned by MediaHub and IPPhone] * Returned when a DTMF key is held down (or detected) for more than 2s. * * HANDSET_NO_EVENT: [Returned by MediaHub and IPPhone] * No handset activity * * oLineNumber - Line number of query * chKeyPressed - the key that was pressed, or the number that was * (re)dialled (returned) * * This function also handles special key functions such as: * Volume control buttons * Speakerphone button * Mute button * Call review buttons (left/right) * Call delete button * Dial button * Redial button * DTMF buttons (store in redial string, play local DTMF tone) * Mode button **************************************************************************/E_HANDSET_RETURN_VALUES HandsetProcess(OCTET oLineNumber, unsigned char *chKeyPressed){ HANDSET *pHandset = &pxHandset[oLineNumber-1]; E_HANDSET_RETURN_VALUES eReturn = 0; OCTET oHookState; if (!g_bHandsetStarted || oLineNumber > g_oNumHandsetLines) { return HANDSET_NO_EVENT; } /* Get hook state */ ioctl(g_iSlicFd, SLIC_IOCTL_GETHOOKSTATE, (OCTET)oLineNumber, (BOOL*)&oHookState); if (g_bPulseDial && pHandset->oPhoneState == HSTATE_OFFHOOK_IDLE) { pHandset->oSamplingCount++; pHandset->oCurrentPulseSample = oHookState; } #ifdef HOOKER eReturn = HandsetHookerProcess(oLineNumber, chKeyPressed); if (eReturn != HANDSET_NO_EVENT) { return eReturn; }#endif /* Update the handset state */ if ((eReturn=_HandsetUpdateState(oLineNumber)) > 0) { return eReturn; } #ifdef HANDSET_USEDISPLAY /* Process menu & LCD */ if (--g_dwDisplayCounter == 0) { _HandsetUpdateLCD(); }#endif // HANDSET_USEDISPLAY /* First, process the hook state */ if (!pHandset->bOffHook && oHookState == 0) { LONG lReturn = HANDSET_OFF_HOOK_EVENT; /* Default unless hit or flash */ /* Check if flash hit */ if (pHandset->oPhoneState == HSTATE_ONHOOK_WAITING_FOR_FLASH) { if((pHandset->dwStateTimer < FLASH_HOOK_TIMER) && (pHandset->dwStateTimer > (FLASH_HOOK_TIMER - 20))) { /* 200ms not up yet. this is a hook hit - ignore */ lReturn = HANDSET_HIT_HOOK_EVENT; } else if (pHandset->dwStateTimer <= (FLASH_HOOK_TIMER - 20)) { /* Phone picked up during flash-timer countdown, therefore flash hook has occurred */ lReturn = HANDSET_FLASH_HOOK_EVENT; } } #ifndef HANDSET_NO_CALLER_ID /* process Japanese caller ID */ if (pHandset->oPhoneState == HSTATE_ONHOOK_WAIT_FOR_CONNECT) { _HandsetNextState(oLineNumber); return 0; } else if (pHandset->oPhoneState == HSTATE_DELAY) { pHandset->bRinging = FALSE; pHandset->bFirstRing = FALSE; return 0; } else if (pHandset->oPhoneState == HSTATE_ONHOOK_WAIT_FOR_DISCONNECT) { memcpy(&(pHandset->xRingCadencePattern), &g_xJPRingCadences[1], sizeof(HANDSET_RING_CADENCE)); pHandset->bFirstRing = FALSE; pHandset->oRingPatternCount = 0; pHandset->xRingCadencePattern.wPatternDurations[0]/=10; pHandset->xRingCadencePattern.wPatternDurations[1]/=10; pHandset->dwRingTimer = pHandset->xRingCadencePattern.wPatternDurations[0]; return 0; } else if(pHandset->oPhoneState == HSTATE_DELAYINDEF){ _HandsetNextState(oLineNumber); }#endif _ProcessOffHookEvent(oLineNumber); if (g_bPulseDial) { pHandset->oLastPulseSample = oHookState; pHandset->oPulseCount = 0; } return lReturn; }#ifndef HANDSET_NO_CALLER_ID else if (pHandset->oPhoneState==HSTATE_ONHOOK_WAIT_FOR_DISCONNECT && oHookState==1) { _HandsetNextState(oLineNumber); return 0; }#endif else if (!g_bPulseDial && pHandset->bOffHook && oHookState == 1) { /* Hookswitch has been pressed */ _ProcessOnHookEvent(oLineNumber); return HANDSET_HOOK_DOWN_EVENT; } if (g_bPulseDial && pHandset->oPhoneState == HSTATE_OFFHOOK_IDLE) { if (pHandset->oLastPulseSample == 0 && pHandset->oCurrentPulseSample == 1) { pHandset->oSamplingCount = 1; } else if (pHandset->oLastPulseSample == 1 && pHandset->oCurrentPulseSample == 0) { if (pHandset->oSamplingCount >= 4 && pHandset->oSamplingCount <= 8) { pHandset->oPulseCount++; } pHandset->oSamplingCount = 1; } else if (pHandset->oLastPulseSample == 1 && pHandset->oCurrentPulseSample == 1 && pHandset->oSamplingCount > 10) { /* Assume back on hook */ _ProcessOnHookEvent(oLineNumber); return HANDSET_HOOK_DOWN_EVENT; } else if (pHandset->oLastPulseSample == 0 && pHandset->oCurrentPulseSample == 0 && pHandset->oSamplingCount > 7 && pHandset->oPulseCount > 0) { /* Assume number has been completed */ if (pHandset->oPulseCount > 9) pHandset->oPulseCount = 0; pHandset->oDtmfPressed = '0' + pHandset->oPulseCount; pHandset->oDtmfStatus = 255; pHandset->oPulseCount = 0; } pHandset->oLastPulseSample = pHandset->oCurrentPulseSample; } /* Check if any DTMFs have been detected */ if (pHandset->oDtmfPressed != 0xff) { OCTET chKey = pHandset->oDtmfPressed; *chKeyPressed = chKey; pHandset->oDtmfPressed = 0xff; switch(chKey) { /* DTMF digit */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '*': case '#': case 'A': case 'B': case 'C': case 'D': if (g_bPulseDial && pHandset->oDtmfStatus == 255) { SYSLOG(LOG_DEBUG,"PULSE DIAL %c digit detected on line %d\n",chKey,oLineNumber); return HANDSET_PULSE_DIAL_EVENT; } else if (pHandset->oDtmfStatus == 0) { /* The DTMF event has just been detected */ SYSLOG(LOG_DEBUG,"DTMF %d tone start detected on line %d\n",chKey,oLineNumber); return HANDSET_KEY_DOWN_EVENT; } else { /* The DTMF event has stopped */ SYSLOG(LOG_DEBUG,"DTMF %d tone stop detected on line %d\n",chKey,oLineNumber); return HANDSET_KEY_UP_EVENT; } /* Fax tone detected */ case 'F': *chKeyPressed = 'X'; /* use 'X' to avoid conflict with flash hook 'F' */ SYSLOG(LOG_DEBUG,"Fax tone detected on line %d\n",oLineNumber); return HANDSET_FAX_TONE_EVENT; /* Modem tone detected */ case 'M': SYSLOG(LOG_DEBUG,"Modem tone detected on line %d\n",oLineNumber); return HANDSET_MODEM_TONE_EVENT; /* Answer tone detected */ case 'R': SYSLOG(LOG_DEBUG,"Answer tone detected on line %d\n",oLineNumber); return HANDSET_ANSWER_TONE_EVENT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -