| #include <stdio.h> |
| #include "sdk_qs_utils.h" |
| /* |
| * These files are required by all applications. "vp_api.h" includes all of the |
| * API libraries required by the application. "ZLR965324H_SM2_FULL_ASR.h" includes the |
| * profiles used by the application. At a minimum, there must be a Device |
| * Profile for the device to initialize. |
| */ |
| #include "vp_api.h" |
| #include "ZLR965324H_SM2_FULL_ASR.h" |
| #include "user_intf.h" |
| #include "vp886_registers.h" |
| |
| extern VpLineCtxType lineCtx[]; |
| extern int MISLIC_APITest_HandleEvents(void); |
| |
| bool quit_loop = false; |
| static pthread_t APITest_MainLoopTask; |
| int user_selection = 15; |
| /* |
| * CID Message of DTMF mode, ASCII encoding |
| * - The start code for calling number shall be either DTMF "A" or "D". |
| * - The start code for redirecting number shall be DTMF "D". |
| * - The start code for information values shall be DTMF "B". |
| * - The information may be sent in any order and shall always end with DTMF "C". |
| */ |
| char cidMessageDTMF[] = "A9876543210C"; |
| |
| /* |
| * CID Message of FSK mode, ASCII encoding |
| */ |
| #if 1 |
| char cidMessageFSK[] = |
| "\x80" /* MDMF Type */ |
| "\x17" /* Message Length */ |
| "\x01" /* Date/Time Param *//*-----message body begin-----*/ |
| "\x08" /* 8-byte Date/Time */ |
| "07040815" /* July 4th 08:15 am */ |
| "\x02" /* Calling Number Param */ |
| "\x0B" /* 11-byte Calling Number */ |
| "13914750000" /* Phone Number *//*-----message body end-----*/ |
| "\x00" /* Placeholder for Checksum */ |
| "\x00" /* Markout */ |
| ; |
| |
| #else |
| char cidMessageFSK[] = |
| "\x04" /* SDMF Type */ |
| "\x12" /* Message Length */ |
| "05251856" /* May 25th 18:56 pm */ |
| "9876543210" /* Phone Number */ |
| "\x00" /* Placeholder for Checksum */ |
| "\x00" /* Markout */ |
| ; |
| #endif |
| |
| /** |
| * PrintEvent(VpEventType *pEvent) |
| * |
| * Description: This function prints all the events |
| * for debugging purpose. |
| */ |
| |
| void |
| UtilPrintEvent( |
| VpEventType *pEvent) |
| { |
| VpEventCategoryType eventCategory = pEvent->eventCategory; |
| uint16 eventId = pEvent->eventId; |
| |
| char *eventCategorySt[] = { |
| "VP_EVCAT_FAULT", |
| "VP_EVCAT_SIGNALING", |
| "VP_EVCAT_RESPONSE", |
| "VP_EVCAT_TEST", |
| "VP_EVCAT_PROCESS", |
| "VP_EVCAT_FXO", |
| "VP_EVCAT_PACKET", |
| }; |
| |
| if (eventCategory < VP_NUM_EVCATS) { |
| QS_DEBUG("\t\teventCategory = %s\n", eventCategorySt[eventCategory]); |
| } else { |
| QS_DEBUG("\t\teventCategory = INVALID (0x%x)\n", eventCategory); |
| } |
| |
| QS_DEBUG("\t\teventId = "); |
| if (eventCategory == VP_EVCAT_FAULT) { |
| switch (eventId) { |
| case VP_DEV_EVID_BAT_FLT: |
| QS_DEBUG("VP_DEV_EVID_BAT_FLT\n"); break; |
| case VP_DEV_EVID_CLK_FLT: |
| QS_DEBUG("VP_DEV_EVID_CLK_FLT\n"); break; |
| case VP_LINE_EVID_THERM_FLT: |
| QS_DEBUG("VP_LINE_EVID_THERM_FLT\n"); break; |
| case VP_LINE_EVID_DC_FLT: |
| QS_DEBUG("VP_LINE_EVID_DC_FLT\n"); break; |
| case VP_LINE_EVID_AC_FLT: |
| QS_DEBUG("VP_LINE_EVID_AC_FLT\n"); break; |
| case VP_DEV_EVID_EVQ_OFL_FLT: |
| QS_DEBUG("VP_DEV_EVID_EVQ_OFL_FLT\n"); break; |
| case VP_DEV_EVID_WDT_FLT: |
| QS_DEBUG("VP_DEV_EVID_WDT_FLT\n"); break; |
| default: |
| QS_DEBUG("INVALID (0x%x)\n", eventId); break; |
| } |
| } else if (eventCategory == VP_EVCAT_SIGNALING) { |
| switch (eventId) { |
| case VP_LINE_EVID_HOOK_OFF: |
| QS_DEBUG("VP_LINE_EVID_HOOK_OFF\n"); break; |
| case VP_LINE_EVID_HOOK_ON: |
| QS_DEBUG("VP_LINE_EVID_HOOK_ON\n"); break; |
| case VP_LINE_EVID_GKEY_DET: |
| QS_DEBUG("VP_LINE_EVID_GKEY_DET\n"); break; |
| case VP_LINE_EVID_GKEY_REL: |
| QS_DEBUG("VP_LINE_EVID_GKEY_REL\n"); break; |
| case VP_LINE_EVID_FLASH: |
| QS_DEBUG("VP_LINE_EVID_FLASH\n"); break; |
| case VP_LINE_EVID_STARTPULSE: |
| QS_DEBUG("VP_LINE_EVID_STARTPULSE\n"); break; |
| case VP_LINE_EVID_DTMF_DIG: |
| QS_DEBUG("VP_LINE_EVID_DTMF_DIG\n"); break; |
| case VP_LINE_EVID_PULSE_DIG: |
| QS_DEBUG("VP_LINE_EVID_PULSE_DIG\n"); break; |
| case VP_LINE_EVID_MTONE: |
| QS_DEBUG("VP_LINE_EVID_MTONE\n"); break; |
| case VP_DEV_EVID_TS_ROLLOVER: |
| QS_DEBUG("VP_DEV_EVID_TS_ROLLOVER\n"); break; |
| default: |
| QS_DEBUG("INVALID (0x%x)\n", eventId); break; |
| } |
| } else if (eventCategory == VP_EVCAT_RESPONSE) { |
| switch (eventId) { |
| case VP_DEV_EVID_BOOT_CMP: |
| QS_DEBUG("VP_DEV_EVID_BOOT_CMP\n"); break; |
| case VP_LINE_EVID_LLCMD_TX_CMP: |
| QS_DEBUG("VP_LINE_EVID_LLCMD_TX_CMP\n"); break; |
| case VP_LINE_EVID_LLCMD_RX_CMP: |
| QS_DEBUG("VP_LINE_EVID_LLCMD_RX_CMP\n"); break; |
| case VP_DEV_EVID_DNSTR_MBOX: |
| QS_DEBUG("VP_DEV_EVID_DNSTR_MBOX\n"); break; |
| case VP_LINE_EVID_RD_OPTION: |
| QS_DEBUG("VP_LINE_EVID_RD_OPTION\n"); break; |
| case VP_LINE_EVID_RD_LOOP: |
| QS_DEBUG("VP_LINE_EVID_RD_LOOP\n"); break; |
| case VP_EVID_CAL_CMP: |
| QS_DEBUG("VP_EVID_CAL_CMP\n"); break; |
| case VP_EVID_CAL_BUSY: |
| QS_DEBUG("VP_EVID_CAL_BUSY\n"); break; |
| case VP_LINE_EVID_GAIN_CMP: |
| QS_DEBUG("VP_LINE_EVID_GAIN_CMP\n"); break; |
| case VP_DEV_EVID_DEV_INIT_CMP: |
| QS_DEBUG("VP_DEV_EVID_DEV_INIT_CMP\n"); break; |
| case VP_LINE_EVID_LINE_INIT_CMP: |
| QS_DEBUG("VP_LINE_EVID_LINE_INIT_CMP\n"); break; |
| case VP_DEV_EVID_IO_ACCESS_CMP: |
| QS_DEBUG("VP_DEV_EVID_IO_ACCESS_CMP\n"); break; |
| default: |
| QS_DEBUG("INVALID (0x%x)\n", eventId); break; |
| } |
| } else if (eventCategory == VP_EVCAT_TEST) { |
| switch (eventId) { |
| case VP_LINE_EVID_TEST_CMP: |
| QS_DEBUG("VP_LINE_EVID_TEST_CMP\n"); break; |
| case VP_LINE_EVID_DTONE_DET: |
| QS_DEBUG("VP_LINE_EVID_DTONE_DET\n"); break; |
| case VP_LINE_EVID_DTONE_LOSS: |
| QS_DEBUG("VP_LINE_EVID_DTONE_LOSS\n"); break; |
| case VP_DEV_EVID_STEST_CMP: |
| QS_DEBUG("VP_DEV_EVID_STEST_CMP\n"); break; |
| case VP_DEV_EVID_CHKSUM: |
| QS_DEBUG("VP_DEV_EVID_CHKSUM\n"); break; |
| default: |
| QS_DEBUG("INVALID (0x%x)\n", eventId); break; |
| } |
| } else if(eventCategory == VP_EVCAT_PROCESS) { |
| switch (eventId) { |
| case VP_LINE_EVID_MTR_CMP: |
| QS_DEBUG("VP_LINE_EVID_MTR_CMP\n"); break; |
| case VP_LINE_EVID_MTR_ABORT: |
| QS_DEBUG("VP_LINE_EVID_MTR_ABORT\n"); break; |
| case VP_LINE_EVID_CID_DATA: |
| QS_DEBUG("VP_LINE_EVID_CID_DATA\n"); break; |
| case VP_LINE_EVID_RING_CAD: |
| QS_DEBUG("VP_LINE_EVID_RING_CAD\n"); break; |
| case VP_LINE_EVID_GEN_TIMER: |
| QS_DEBUG("VP_LINE_EVID_GEN_TIMER\n"); break; |
| default: |
| QS_DEBUG("INVALID (0x%x)\n", eventId); break; |
| } |
| } else if(eventCategory == VP_EVCAT_FXO) { |
| switch (eventId) { |
| case VP_LINE_EVID_RING_ON: |
| QS_DEBUG("VP_LINE_EVID_RING_ON\n"); break; |
| case VP_LINE_EVID_RING_OFF: |
| QS_DEBUG("VP_LINE_EVID_RING_OFF\n"); break; |
| case VP_LINE_EVID_LIU: |
| QS_DEBUG("VP_LINE_EVID_LIU\n"); break; |
| case VP_LINE_EVID_LNIU: |
| QS_DEBUG("VP_LINE_EVID_LNIU\n"); break; |
| case VP_LINE_EVID_FEED_DIS: |
| QS_DEBUG("VP_LINE_EVID_FEED_DIS\n"); break; |
| case VP_LINE_EVID_FEED_EN: |
| QS_DEBUG("VP_LINE_EVID_FEED_EN\n"); break; |
| case VP_LINE_EVID_DISCONNECT: |
| QS_DEBUG("VP_LINE_EVID_DISCONNECT\n"); break; |
| case VP_LINE_EVID_RECONNECT: |
| QS_DEBUG("VP_LINE_EVID_RECONNECT\n"); break; |
| case VP_LINE_EVID_POLREV: |
| QS_DEBUG("VP_LINE_EVID_POLREV\n"); break; |
| case VP_LINE_EVID_POH: |
| QS_DEBUG("VP_LINE_EVID_POH\n"); break; |
| case VP_LINE_EVID_PNOH: |
| QS_DEBUG("VP_LINE_EVID_PNOH\n"); break; |
| default: |
| QS_DEBUG("INVALID (0x%x)\n", eventId); break; |
| } |
| } else { |
| QS_DEBUG("0x%x\n", eventId); |
| } |
| } |
| |
| |
| char * |
| MapStatus( |
| VpStatusType status) |
| { |
| int idx = 0; |
| |
| static char buff[50]; |
| |
| static const char *strTable[VP_STATUS_NUM_TYPES] = { |
| "VP_STATUS_SUCCESS", |
| "VP_STATUS_FAILURE", |
| "VP_STATUS_FUNC_NOT_SUPPORTED", |
| "VP_STATUS_INVALID_ARG", |
| "VP_STATUS_MAILBOX_BUSY", |
| "VP_STATUS_ERR_VTD_CODE", |
| "VP_STATUS_OPTION_NOT_SUPPORTED", |
| "VP_STATUS_ERR_VERIFY", |
| "VP_STATUS_DEVICE_BUSY", |
| "VP_STATUS_MAILBOX_EMPTY", |
| "VP_STATUS_ERR_MAILBOX_DATA", |
| "VP_STATUS_ERR_HBI", |
| "VP_STATUS_ERR_IMAGE", |
| "VP_STATUS_IN_CRTCL_SECTN", |
| "VP_STATUS_DEV_NOT_INITIALIZED", |
| "VP_STATUS_ERR_PROFILE", |
| "VP_STATUS_INVALID_VOICE_STREAM", |
| "VP_STATUS_CUSTOM_TERM_NOT_CFG", |
| "VP_STATUS_DEDICATED_PINS", |
| "VP_STATUS_INVALID_LINE", |
| "VP_STATUS_LINE_NOT_CONFIG", |
| "VP_STATUS_ERR_SPI" |
| }; |
| |
| if (status < VP_STATUS_NUM_TYPES) { |
| idx = sprintf(&buff[idx], "(%s)", (char *)strTable[status]); |
| } |
| idx = sprintf(&buff[idx], " = %d", (uint16)status); |
| |
| return buff; |
| } |
| |
| /*******************************************************************************\ |
| * Function: sig_handler |
| * handle the signal of "CTRL+C" and "kill -15" to end the RingingwithCID |
| \*******************************************************************************/ |
| static void APITest_sig_handler(int sig) |
| { |
| quit_loop = true; |
| printf("%s: signal number: %d.\n", __FUNCTION__, sig); |
| |
| return; |
| } |
| |
| void DTMF_RingingwithCID(void) |
| { |
| uint8 channelId = 0; |
| VpLineCtxType *pLineCtx = &lineCtx[channelId]; |
| uint8 cidLen; |
| uint8 initCidLen; |
| VpStatusType status; |
| |
| cidLen = strlen(cidMessageDTMF); |
| |
| /* We can initialize a maximum of 32 bytes */ |
| if (cidLen >= 32) { |
| initCidLen = 32; |
| } else { |
| initCidLen = cidLen; |
| } |
| |
| status = VpInitRing(pLineCtx, CR_CN, CID_DTMF); |
| if (status != VP_STATUS_SUCCESS) { |
| LOG_OUT_E("Error running VpInitRing on channel %d: %s\n", channelId, MapStatus(status)); |
| return; |
| } |
| |
| /* Initialize up to 32 bytes of the CID data */ |
| status = VpInitCid(pLineCtx, initCidLen, cidMessageDTMF); |
| if (status != VP_STATUS_SUCCESS) { |
| LOG_OUT_E("Error running VpInitCid on channel %d: %s\n", channelId, MapStatus(status)); |
| return; |
| } |
| |
| /* Begin the ringing + CID cadence */ |
| status = VpSetLineState(pLineCtx, VP_LINE_RINGING); |
| if (status != VP_STATUS_SUCCESS) { |
| LOG_OUT_E("Error running VpSetLineState on channel %d: %s\n", channelId, MapStatus(status)); |
| return; |
| } |
| } |
| |
| void FSK_RingingwithCID(void) |
| { |
| uint8 channelId = 0; |
| VpLineCtxType *pLineCtx = &lineCtx[channelId]; |
| uint8 cidLen; |
| uint8 initCidLen; |
| VpStatusType status; |
| |
| cidLen = strlen(cidMessageFSK); |
| |
| /* We can initialize a maximum of 32 bytes */ |
| if (cidLen >= 32) { |
| initCidLen = 32; |
| } else { |
| initCidLen = cidLen; |
| } |
| |
| /* Provide the ringing cadence and CID profiles */ |
| status = VpInitRing(pLineCtx, CR_CN, CID_TYPE1_CN); |
| if (status != VP_STATUS_SUCCESS) { |
| LOG_OUT_E("Error running VpInitRing on channel %d: %s\n", channelId, MapStatus(status)); |
| return; |
| } |
| |
| /* Initialize up to 32 bytes of the CID data */ |
| status = VpInitCid(pLineCtx, initCidLen, cidMessageFSK); |
| if (status != VP_STATUS_SUCCESS) { |
| LOG_OUT_E("Error running VpInitCid on channel %d: %s\n", channelId, MapStatus(status)); |
| return; |
| } |
| |
| /* Begin the ringing + CID cadence */ |
| status = VpSetLineState(pLineCtx, VP_LINE_RINGING); |
| if (status != VP_STATUS_SUCCESS) { |
| LOG_OUT_E("Error running VpSetLineState on channel %d: %s\n", channelId, MapStatus(status)); |
| return; |
| } |
| |
| } |
| |
| void RingingwithCID(uint8 mode) |
| { |
| uint8 channelId = 0; |
| VpLineCtxType *pLineCtx = &lineCtx[channelId]; |
| uint8 cidLen; |
| uint8 initCidLen; |
| VpStatusType status; |
| |
| if(mode == 0) { |
| cidLen = strlen(cidMessageFSK); |
| LOG_OUT_D("%s:FSK CID.\n", __FUNCTION__); |
| } |
| else { |
| cidLen = strlen(cidMessageDTMF); |
| LOG_OUT_D("%s:DTMF CID.\n", __FUNCTION__); |
| } |
| |
| /* We can initialize a maximum of 32 bytes */ |
| if (cidLen >= 32) { |
| initCidLen = 32; |
| } else { |
| initCidLen = cidLen; |
| } |
| |
| /* Provide the ringing cadence and CID profiles */ |
| if(mode == 0) |
| status = VpInitRing(pLineCtx, CR_CN, CID_TYPE1_CN); |
| else |
| status = VpInitRing(pLineCtx, CR_CN, CID_DTMF); |
| if (status != VP_STATUS_SUCCESS) { |
| LOG_OUT_E("Error running VpInitRing on channel %d: %s\n", channelId, MapStatus(status)); |
| return; |
| } |
| |
| /* Initialize up to 32 bytes of the CID data */ |
| if(mode == 0) |
| status = VpInitCid(pLineCtx, initCidLen, cidMessageFSK); |
| else |
| status = VpInitCid(pLineCtx, initCidLen, cidMessageDTMF); |
| if (status != VP_STATUS_SUCCESS) { |
| LOG_OUT_E("Error running VpInitCid on channel %d: %s\n", channelId, MapStatus(status)); |
| return; |
| } |
| |
| /* Begin the ringing + CID cadence */ |
| status = VpSetLineState(pLineCtx, VP_LINE_RINGING); |
| if (status != VP_STATUS_SUCCESS) { |
| LOG_OUT_E("Error running VpSetLineState on channel %d: %s\n", channelId, MapStatus(status)); |
| return; |
| } |
| } |
| |
| pthread_t thread_stress_test_spi; |
| int on_stress_testing = TRUE; |
| |
| extern VpDeviceIdType deviceId; |
| |
| /* Read the revision and product code */ |
| void MISLIC_read_RCNPCN(void) |
| { |
| uint8 readBuffer[16] = {0}; |
| |
| /* Read the revision and product code */ |
| VpMpiCmd(deviceId, VP886_EC_GLOBAL, VP886_R_RCNPCN_RD, VP886_R_RCNPCN_LEN, &readBuffer[0]); |
| |
| //if ((0x08 != readBuffer[0]) || (0x49 != readBuffer[1])) |
| { |
| printf("Revision code 0x%02X, product code 0x%02X\n", readBuffer[0], readBuffer[1]); |
| } |
| |
| return; |
| } |
| |
| static void MISLIC_test_lib_spi(void *arg) |
| { |
| while (on_stress_testing) |
| { |
| MISLIC_read_RCNPCN(); |
| } |
| |
| return; |
| } |
| |
| void MISLIC_start_SPI_stress_test(void) |
| { |
| int rc = 0; |
| |
| rc = pthread_create(&thread_stress_test_spi, NULL, (void *)&MISLIC_test_lib_spi, NULL); |
| if (rc < 0) { |
| fprintf(stderr,"%s: error creating thread_start!\n", __FUNCTION__); |
| } |
| return; |
| } |
| |
| void MISLIC_stop_SPI_stress_test(void) |
| { |
| on_stress_testing = FALSE; |
| pthread_detach(thread_stress_test_spi); |
| return; |
| } |
| /*****************************************************************************************************/ |
| static void APITest_MainLoop(void) |
| { |
| while (1) |
| { |
| usleep(5000); |
| |
| MISLIC_APITest_HandleEvents(); |
| |
| switch(user_selection) |
| { |
| case 0: |
| VpSetLineState(&lineCtx[0], VP_LINE_ACTIVE); |
| printf("Stop Ringing.\n"); |
| break; |
| |
| case 1: |
| VpSetLineState(&lineCtx[0], VP_LINE_RINGING); |
| printf("Start Ringing.\n"); |
| break; |
| |
| case 2: |
| RingingwithCID(0); |
| printf("Ring with CID in FSK.\n"); |
| break; |
| |
| case 3: |
| RingingwithCID(1); |
| printf("Ring with CID in DTMF.\n"); |
| break; |
| |
| case 4: |
| MISLIC_stop_SPI_stress_test(); |
| printf("Stop SPI stress test.\n"); |
| break; |
| |
| case 5: |
| MISLIC_start_SPI_stress_test(); |
| printf("Start SPI stress test.\n"); |
| break; |
| |
| default: |
| break; |
| |
| } |
| |
| user_selection = 15; |
| |
| if (quit_loop) { |
| printf("normal quit the APITest_MainLoop.\n"); |
| return; |
| } |
| } |
| } |
| |
| void MISLIC_APITest_Menu() |
| { |
| pthread_attr_t tattr; |
| const char *menu_items[] = |
| { |
| "Stop Ringing", |
| "Start Ringing", |
| "Ring with CID in FSK", |
| "Ring with CID in DTMF", |
| "Stop SPI stress test", |
| "Start SPI stress test", |
| NULL |
| }; |
| |
| /* install signal handler and begin to capture signal for close */ |
| signal(SIGINT, APITest_sig_handler); |
| signal(SIGTERM, APITest_sig_handler); |
| |
| /*Create thread to poll interrupts*/ |
| pthread_attr_init(&tattr); |
| pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); |
| pthread_create(&APITest_MainLoopTask, &tattr, (void *)APITest_MainLoop, NULL); |
| |
| do |
| { |
| user_selection = get_menu_selection( display_menu("MISLIC API Test Menu", menu_items), 0); |
| printf("\n\n"); |
| |
| if (quit_loop) { |
| printf("normal quit the select loop.\n"); |
| goto EXIT_APITEST; |
| } |
| } |
| while(user_selection != QUIT_MENU); |
| |
| EXIT_APITEST: |
| //Cancel pooling thread |
| pthread_cancel(APITest_MainLoopTask); |
| } |