📄 tspi.c
字号:
(LINECALLSTATE_IDLE |
LINECALLSTATE_OFFERING |
LINECALLSTATE_ACCEPTED |
LINECALLSTATE_CONNECTED |
LINECALLSTATE_DISCONNECTED |
LINECALLSTATE_UNKNOWN) :
(LINECALLSTATE_IDLE |
LINECALLSTATE_DIALTONE |
LINECALLSTATE_DIALING |
LINECALLSTATE_PROCEEDING |
LINECALLSTATE_CONNECTED |
LINECALLSTATE_DISCONNECTED |
LINECALLSTATE_UNKNOWN);
lpCallInfo->dwOrigin = pLineDev->dwCallFlags & CALL_INBOUND ?
LINECALLORIGIN_INBOUND : LINECALLORIGIN_OUTBOUND;
lpCallInfo->dwReason = pLineDev->dwCallFlags & CALL_INBOUND ?
LINECALLREASON_UNAVAIL : LINECALLREASON_DIRECT;
lpCallInfo->dwCallerIDFlags = LINECALLPARTYID_UNAVAIL;
lpCallInfo->dwCalledIDFlags = LINECALLPARTYID_UNAVAIL;
lpCallInfo->dwConnectedIDFlags = LINECALLPARTYID_UNAVAIL;
lpCallInfo->dwRedirectionIDFlags = LINECALLPARTYID_UNAVAIL;
lpCallInfo->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
lpCallInfo->dwAddressType = LINEADDRESSTYPE_PHONENUMBER;
exitPoint:
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:-TSPI_lineGetCallInfo %x\n"), rc));
return rc;
} // TSPI_lineGetCallInfo
LONG
TSPIAPI
TSPI_lineGetCallStatus(
HDRVCALL hdCall,
LPLINECALLSTATUS lpCallStatus
)
{
PTLINEDEV pLineDev;
LONG rc;
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:+TSPI_lineGetCallStatus\n")));
InitVarData((LPVOID)lpCallStatus, sizeof(LINECALLSTATUS));
if ((pLineDev = GetLineDevfromHandle ((DWORD)hdCall)) == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("UNIMODEM:TSPI_lineGetCallStatus Invalid hdCall\n")));
rc = LINEERR_INVALCALLHANDLE;
goto exitPoint;
}
rc = 0;
//
// Current call information
//
lpCallStatus->dwCallState = pLineDev->dwCallState;
lpCallStatus->dwCallStateMode = pLineDev->dwCallStateMode;
// if we are in takeover mode, disallow all dwCallFeatures
if (!pLineDev->fTakeoverMode) {
switch(lpCallStatus->dwCallState) {
case LINECALLSTATE_OFFERING:
lpCallStatus->dwCallFeatures = LINECALLFEATURE_ACCEPT |
LINECALLFEATURE_SETCALLPARAMS |
LINECALLFEATURE_DROP;
// We can only answer if a possible media mode is DATAMODEM.
if (pLineDev->dwCurMediaModes & LINEMEDIAMODE_DATAMODEM) {
lpCallStatus->dwCallFeatures |= LINECALLFEATURE_ANSWER;
}
break;
case LINECALLSTATE_DIALTONE:
lpCallStatus->dwCallFeatures = LINECALLFEATURE_DROP;
break;
case LINECALLSTATE_DIALING:
lpCallStatus->dwCallFeatures = LINECALLFEATURE_DROP;
if (DEVST_PORTCONNECTWAITFORLINEDIAL == pLineDev->DevState) {
lpCallStatus->dwCallFeatures |= LINECALLFEATURE_DIAL;
}
break;
case LINECALLSTATE_ACCEPTED:
lpCallStatus->dwCallFeatures = LINECALLFEATURE_SETCALLPARAMS|LINECALLFEATURE_DROP;
// We can only answer if a possible media mode is DATAMODEM.
if (pLineDev->dwCurMediaModes & LINEMEDIAMODE_DATAMODEM) {
lpCallStatus->dwCallFeatures |= LINECALLFEATURE_ANSWER;
}
break;
case LINECALLSTATE_CONNECTED:
lpCallStatus->dwCallFeatures = LINECALLFEATURE_SETCALLPARAMS |
LINECALLFEATURE_DROP;
break;
case LINECALLSTATE_UNKNOWN:
case LINECALLSTATE_PROCEEDING:
case LINECALLSTATE_DISCONNECTED:
lpCallStatus->dwCallFeatures = LINECALLFEATURE_DROP;
break;
case LINECALLSTATE_IDLE:
default:
lpCallStatus->dwCallFeatures = 0;
break;
}
}
exitPoint:
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:-TSPI_lineGetCallStatus %x\n"), rc));
return rc;
} // TSPI_lineGetCallStatus
static const WCHAR szProviderName[] = TEXT("UNIMODEM");
//
// Determine Telephony capabilites for the specified device.
//
// NOTES:
// WinCE UNIMODEM uses a DWORD of DevSpecific information (denoted by
// LINEDEVCAPS.dwDevSpecificSize and LINEDEVCAPS.dwDevSpecificOffset).
// The format of of these 4 bytes is that the first WORD is a device type
// and the second WORD is an "active" indicator (0 for PC card modems that
// have been removed).
//
// The provider name is stored in the ProviderInfo section (denoted by
// LINEDEVCAPS.dwProviderInfoSize and LINEDEVCAPS.dwProviderInfoOffset).
//
LONG TSPIAPI
TSPI_lineGetDevCaps(
DWORD dwDeviceID,
DWORD dwTSPIVersion,
DWORD dwExtVersion,
LPLINEDEVCAPS lpLineDevCaps
)
{
PTLINEDEV pLineDev;
int cbLineNameLen = 0;
int cbProviderNameLen = 0;
int cbDevClassLen = 0;
int cbAvailMem = 0;
DWORD dwRet = SUCCESS;
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:+TSPI_lineGetDevCaps\n")));
InitVarData((LPVOID)lpLineDevCaps, sizeof(LINEDEVCAPS));
// We need to fill in a device caps struct specific to
// the device.
if ((pLineDev = GetLineDevfromID ((DWORD)dwDeviceID)) == NULL)
return LINEERR_NODEVICE;
// Check to see how much memory we'll need.
cbLineNameLen = (wcslen(pLineDev->szFriendlyName) + 1) * sizeof(WCHAR);
cbProviderNameLen = (wcslen(szProviderName) + 1) * sizeof(WCHAR);
cbDevClassLen = sizeof(g_szzClassList);
cbAvailMem = (int) (lpLineDevCaps->dwTotalSize - lpLineDevCaps->dwUsedSize);
// Enter the size we ideally need.
lpLineDevCaps->dwNeededSize = lpLineDevCaps->dwUsedSize +
cbLineNameLen + // room for linename
cbProviderNameLen + // room for provider name
cbDevClassLen + // room for device class list
(2*sizeof(WORD)); // and room for DevSpecific info
if (cbAvailMem >= sizeof(DWORD) )
{
*(LPWORD)((LPSTR)lpLineDevCaps + lpLineDevCaps->dwUsedSize) = pLineDev->wDeviceType;
*((LPWORD)((LPSTR)lpLineDevCaps + lpLineDevCaps->dwUsedSize) + 1) = pLineDev->wDeviceAvail;
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:TSPI_lineGetDevCaps Storing Device Type x%X, available x%X\n"),
pLineDev->wDeviceType,
pLineDev->wDeviceAvail));
lpLineDevCaps->dwDevSpecificSize = sizeof( DWORD );
lpLineDevCaps->dwDevSpecificOffset = lpLineDevCaps->dwUsedSize;
lpLineDevCaps->dwUsedSize += lpLineDevCaps->dwDevSpecificSize;
cbAvailMem -= lpLineDevCaps->dwDevSpecificSize;
}
else
{
lpLineDevCaps->dwDevSpecificSize = 0;
lpLineDevCaps->dwDevSpecificOffset = 0;
lpLineDevCaps->dwNeededSize += sizeof(WORD);
}
// If the provider info fits, then also append the line name
if (cbAvailMem >= cbLineNameLen)
{
wcscpy((LPWSTR)((LPSTR)lpLineDevCaps + lpLineDevCaps->dwUsedSize),
pLineDev->szFriendlyName);
lpLineDevCaps->dwLineNameSize = cbLineNameLen;
lpLineDevCaps->dwLineNameOffset = lpLineDevCaps->dwUsedSize;
lpLineDevCaps->dwUsedSize += cbLineNameLen;
cbAvailMem -= cbLineNameLen;
}
else
{
lpLineDevCaps->dwLineNameSize = 0;
lpLineDevCaps->dwLineNameOffset = 0;
}
if (cbAvailMem >= cbProviderNameLen)
{
wcscpy((LPWSTR)((LPSTR)lpLineDevCaps + lpLineDevCaps->dwUsedSize), szProviderName);
lpLineDevCaps->dwProviderInfoSize = cbProviderNameLen;
lpLineDevCaps->dwProviderInfoOffset = lpLineDevCaps->dwUsedSize;
lpLineDevCaps->dwUsedSize += cbProviderNameLen;
cbAvailMem -= cbProviderNameLen;
}
else
{
lpLineDevCaps->dwProviderInfoSize = 0;
lpLineDevCaps->dwProviderInfoOffset = 0;
}
// TODO - We don't have permanent ID's yet.
lpLineDevCaps->dwPermanentLineID = 0;
lpLineDevCaps->dwStringFormat = STRINGFORMAT_UNICODE;
lpLineDevCaps->dwAddressModes = LINEADDRESSMODE_ADDRESSID;
lpLineDevCaps->dwNumAddresses = 1;
// Bearer mode & information
lpLineDevCaps->dwMaxRate = pLineDev->dwMaxDCERate;
lpLineDevCaps->dwBearerModes = pLineDev->dwBearerModes;
// Media mode
lpLineDevCaps->dwMediaModes = pLineDev->dwMediaModes;
// We can simulate wait-for-bong if the modem isn't capable of
// supporting it.
lpLineDevCaps->dwDevCapFlags = pLineDev->dwDevCapFlags |
LINEDEVCAPFLAGS_DIALBILLING |
LINEDEVCAPFLAGS_CLOSEDROP;
lpLineDevCaps->dwRingModes = 1;
lpLineDevCaps->dwMaxNumActiveCalls = 1;
// Line device state to be notified
lpLineDevCaps->dwLineStates = LINEDEVSTATE_CONNECTED |
LINEDEVSTATE_DISCONNECTED |
LINEDEVSTATE_OPEN |
LINEDEVSTATE_CLOSE |
LINEDEVSTATE_INSERVICE |
LINEDEVSTATE_OUTOFSERVICE |
LINEDEVSTATE_REMOVED |
LINEDEVSTATE_RINGING |
LINEDEVSTATE_REINIT;
lpLineDevCaps->dwLineFeatures = LINEFEATURE_MAKECALL;
//
// Don't go beyond older version app's buffer
//
if (lpLineDevCaps->dwTotalSize >= sizeof(LINEDEVCAPS)) {
lpLineDevCaps->dwSettableDevStatus = 0;
// Copy device classes if it fits
if (cbAvailMem >= cbDevClassLen) {
memcpy((LPBYTE)lpLineDevCaps + lpLineDevCaps->dwUsedSize, g_szzClassList, cbDevClassLen);
lpLineDevCaps->dwDeviceClassesSize = cbDevClassLen;
lpLineDevCaps->dwDeviceClassesOffset= lpLineDevCaps->dwUsedSize;
lpLineDevCaps->dwUsedSize += cbDevClassLen;
cbAvailMem -= cbDevClassLen;
} else {
lpLineDevCaps->dwDeviceClassesSize = 0;
lpLineDevCaps->dwDeviceClassesOffset = 0;
}
lpLineDevCaps->dwAddressTypes = LINEADDRESSTYPE_PHONENUMBER;
lpLineDevCaps->dwAvailableTracking = 0;
}
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:-TSPI_lineGetDevCaps x%X\n"), dwRet));
return dwRet;
}
//
// WINCE NOTE:
// TSPI_lineGetDevConfig returns the default device configuration for the specified device.
// This is done so applications can avoid storing the devcfg when the user wants the default
// settings. If the settings are different than the default, then the application needs to store
// them and set them via lineSetDevConfig whether lineGetDevConfig returns defaults or not.
//
LONG TSPIAPI
TSPI_lineGetDevConfig(
DWORD dwDeviceID,
LPVARSTRING lpDeviceConfig,
LPCWSTR lpszDeviceClass
)
{
PTLINEDEV pLineDev;
DWORD dwRet = SUCCESS;
BYTE cbSize;
PDEVMINICFG pDevMiniCfg;
DEBUGMSG(ZONE_FUNC, (TEXT("UNIMODEM:+TSPI_lineGetDevConfig\n")));
// Validate the requested device class
//
if (lpszDeviceClass != NULL)
{
if (!ValidateDevCfgClass(lpszDeviceClass))
return LINEERR_INVALDEVICECLASS;
}
// Validate the buffer
//
if (lpDeviceConfig == NULL)
return LINEERR_INVALPOINTER;
if (lpDeviceConfig->dwTotalSize < sizeof(VARSTRING))
return LINEERR_STRUCTURETOOSMALL;
// Validate the device ID
//
if ((pLineDev = GetLineDevfromID (dwDeviceID)) == NULL)
return LINEERR_NODEVICE;
// Validate the buffer size
//
cbSize = sizeof(DEVMINICFG);
lpDeviceConfig->dwUsedSize = sizeof(VARSTRING);
lpDeviceConfig->dwNeededSize = sizeof(VARSTRING) + cbSize;
if (lpDeviceConfig->dwTotalSize >= lpDeviceConfig->dwNeededSize)
{
pDevMiniCfg = (PDEVMINICFG)(((LPBYTE)lpDeviceConfig) + sizeof(VARSTRING));
// If someone does a SetDevCfg for some provider who needs a post-dial-terminal
// and they then want to create a new connection via GetDevCfg/CfgDialogEdit,
// they will end up with the default connection lookin like the original.
// To work around this, I will always return the default config here. If the app
// needs to remember a specific config for later edit, they must store it themselves.
// LAM
getDefaultDevConfig( pLineDev, pDevMiniCfg );
lpDeviceConfig->dwStringFormat = STRINGFORMAT_BINARY;
lpDeviceConfig->dwStringSize = cbSize;
lpDeviceConfig->dwStringOffset = sizeof(VARSTRING);
lpDeviceConfig->dwUsedSize += cbSize;
DEBUGMSG(ZONE_FUNC|ZONE_CALLS,
(TEXT("UNIMODEM:TSPI_lineGetDevConfig (DevID %d): dwModemOptions x%X, fwOptions x%X, dwCallSetupFail x%X\n"),
dwDeviceID, pDevMiniCfg->dwModemOptions, pDevMiniCfg->fwOptions, pDevMiniCfg->dwCallSetupFailTimer));
}
else
{
// Not enough room
DEBUGMSG(ZONE_FUNC,
(TEXT("UNIMODEM:TSPI_lineGetDevConfig needed %d bytes, had %d\n"),
lpDeviceConfig->dwNeededSize, lpDeviceConfig->dwTotalSize));
};
DEBUGMSG(ZONE_FUNC,
(TEXT("UNIMODEM:-TSPI_lineGetDevConfig x%X (Used %d, Need %d)\n"),
dwRet, lpDeviceConfig->dwUsedSize, lpDeviceConfig->dwNeededSize));
return dwRet;
}
typedef HICON (WINAPI * PFN_LOADICON)(HINSTANCE, LPCWSTR);
LONG
TSPIAPI
TSPI_lineGetIcon(
DWORD dwDeviceID,
LPCWSTR lpszDeviceClass,
LPHICON lphIcon
)
{
LONG rc;
PFN_LOADICON pfnLoadIcon;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -