#include #include #include #include #include #include #include #include "eos.h" #include "net.h" #include "at_cmd.h" #include "cell.h" static const char *TAG = "EOS CELL VOICE"; extern char *at_cmd_buf; void eos_cell_voice_handler(unsigned char _mtype, EOSMessage *msg, uint16_t len) { unsigned char mtype; unsigned char *buffer = msg->buffer; int rv; if (len < 1) return; mtype = buffer[0] & ~EOS_CELL_MTYPE_MASK; buffer++; len--; switch (mtype) { case EOS_CELL_MTYPE_VOICE_DIAL: { if (len > EOS_CELL_SIZE_PHNUM) break; rv = snprintf(at_cmd_buf, AT_SIZE_CMD_BUF, "ATD%.*s;\r", len, buffer); if ((rv < 0) || (rv >= AT_SIZE_CMD_BUF)) break; rv = eos_modem_take(1000); if (rv) break; at_cmd(at_cmd_buf); rv = at_expect("^OK", "^(ERROR|\\+CME ERROR: [0-9]+)", 1000); eos_modem_give(); eos_cell_pcm_start(); break; } case EOS_CELL_MTYPE_VOICE_ANSWER: { rv = eos_modem_take(1000); if (rv) break; at_cmd("ATA\r"); // Response will be picked up by urc handler eos_modem_give(); eos_cell_pcm_start(); break; } case EOS_CELL_MTYPE_VOICE_HANGUP: { eos_cell_pcm_stop(); rv = eos_modem_take(1000); if (rv) break; at_cmd("AT+CHUP\r"); // Response will be picked up by urc handler eos_modem_give(); break; } case EOS_CELL_MTYPE_VOICE_PCM: { eos_cell_pcm_push(buffer, len); break; } } } static void ring_handler(char *urc, regmatch_t m[]) { EOSMessage msg; uint16_t len; char *buffer; regmatch_t match[2]; int rv = EOS_OK; eos_net_alloc(&msg); if (msg.size < EOS_CELL_SIZE_PHNUM + 1) { eos_net_free(&msg); return; } msg.buffer[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_RING; len = 1; rv = at_expect_match("^\\+CLIP: \"(\\+?[0-9]+)\"", NULL, &buffer, match, 2, REG_EXTENDED, 1000); if (!rv) { regoff_t num_len; num_len = match[1].rm_eo - match[1].rm_so; if (num_len > EOS_CELL_SIZE_PHNUM) { eos_net_free(&msg); return; } memcpy(msg.buffer + 1, buffer + match[1].rm_so, num_len); len += num_len; } rv = eos_net_send(EOS_NET_MTYPE_CELL, &msg, len); if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } static void busy_handler(char *urc, regmatch_t m[]) { EOSMessage msg; int rv; eos_cell_pcm_stop(); eos_net_alloc(&msg); if (msg.size < 1) { eos_net_free(&msg); return; } msg.buffer[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_BUSY; rv = eos_net_send(EOS_NET_MTYPE_CELL, &msg, 1); if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } static void miss_handler(char *urc, regmatch_t m[]) { EOSMessage msg; int rv; eos_cell_pcm_stop(); eos_net_alloc(&msg); if (msg.size < 1) { eos_net_free(&msg); return; } msg.buffer[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_MISS; rv = eos_net_send(EOS_NET_MTYPE_CELL, &msg, 1); if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } static void call_begin_handler(char *urc, regmatch_t m[]) { EOSMessage msg; int rv; eos_net_alloc(&msg); if (msg.size < 1) { eos_net_free(&msg); return; } vTaskDelay(100 / portTICK_PERIOD_MS); at_cmd("AT+CECH=0x0000\r"); at_expect("^OK", "^ERROR", 1000); at_cmd("AT+CECDT=0x0000\r"); at_expect("^OK", "^ERROR", 1000); at_cmd("AT+CECWB=0x0000\r"); at_expect("^OK", "^ERROR", 1000); at_cmd("AT+CNSLIM=0x0000\r"); at_expect("^OK", "^ERROR", 1000); /* at_cmd("AT+CECRX=0\r"); at_expect("^OK", "^ERROR", 1000); */ msg.buffer[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_BEGIN; rv = eos_net_send(EOS_NET_MTYPE_CELL, &msg, 1); if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } static void call_end_handler(char *urc, regmatch_t m[]) { EOSMessage msg; int duration = 0; int rv; eos_cell_pcm_stop(); eos_net_alloc(&msg); if (msg.size < 5) { eos_net_free(&msg); return; } sscanf(urc + m[1].rm_so, "%6d", &duration); msg.buffer[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_END; msg.buffer[1] = duration >> 24; msg.buffer[2] = duration >> 16; msg.buffer[3] = duration >> 8; msg.buffer[4] = duration; rv = eos_net_send(EOS_NET_MTYPE_CELL, &msg, 5); if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } void eos_cell_voice_init(void) { int rv; rv = at_urc_insert("^RING", ring_handler, REG_EXTENDED); assert(rv == EOS_OK); rv = at_urc_insert("^BUSY", busy_handler, REG_EXTENDED); assert(rv == EOS_OK); rv = at_urc_insert("^NO CARRIER", miss_handler, REG_EXTENDED); assert(rv == EOS_OK); rv = at_urc_insert("^MISSED.CALL: [^ ]+ (\\+?[0-9]+)$", miss_handler, REG_EXTENDED); assert(rv == EOS_OK); rv = at_urc_insert("^VOICE CALL: BEGIN", call_begin_handler, REG_EXTENDED); assert(rv == EOS_OK); rv = at_urc_insert("^VOICE CALL: END: ([0-9]{6}$)$", call_end_handler, REG_EXTENDED); assert(rv == EOS_OK); }