From ef322d9e16a3af68666a81a70934f9a5774be88c Mon Sep 17 00:00:00 2001 From: Ryan Erickson Date: Wed, 1 Sep 2021 08:24:31 -0500 Subject: [PATCH] drivers: modem: hl7800 Add Site Survey Add API to determine nearby cell towers and their signal strength. Signed-off-by: Ryan Erickson --- drivers/modem/hl7800.c | 85 ++++++++++++++++++++++++++++++++++ include/drivers/modem/hl7800.h | 21 ++++++++- 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/drivers/modem/hl7800.c b/drivers/modem/hl7800.c index 9f8d2704008..30122c6c9af 100644 --- a/drivers/modem/hl7800.c +++ b/drivers/modem/hl7800.c @@ -1220,6 +1220,22 @@ error: #endif /* CONFIG_MODEM_HL7800_POLTE */ +/** + * @brief Perform a site survey. + * + */ +int32_t mdm_hl7800_perform_site_survey(void) +{ + int ret; + + hl7800_lock(); + wakeup_hl7800(); + ret = send_at_cmd(NULL, "at%meas=\"97\"", MDM_CMD_SEND_TIMEOUT, 0, false); + allow_sleep(true); + hl7800_unlock(); + return ret; +} + void mdm_hl7800_generate_status_events(void) { hl7800_lock(); @@ -3045,6 +3061,74 @@ done: return true; } +/* There can be multiple responses from a single command. + * %MEAS: EARFCN=5826, CellID=420, RSRP=-99, RSRQ=-15 + * %MEAS: EARFCN=6400, CellID=201, RSRP=-93, RSRQ=-21 + */ +static bool on_cmd_survey_status(struct net_buf **buf, uint16_t len) +{ + struct net_buf *frag = NULL; + char response[sizeof("EARFCN=XXXXXXXXXXX, CellID=XXXXXXXXXXX, RSRP=-XXX, RSRQ=-XXX")]; + char *key; + size_t out_len; + char *value; + struct mdm_hl7800_site_survey site_survey; + + wait_for_modem_data_and_newline(buf, net_buf_frags_len(*buf), + sizeof(response)); + + frag = NULL; + len = net_buf_findcrlf(*buf, &frag); + if (!frag) { + LOG_ERR("Unable to find end"); + goto done; + } + + out_len = net_buf_linearize(response, sizeof(response), *buf, 0, len); + LOG_HEXDUMP_DBG(response, out_len, "Site Survey"); + + key = "EARFCN="; + value = strstr(response, key); + if (value == NULL) { + goto done; + } else { + value += strlen(key); + site_survey.earfcn = strtoul(value, NULL, 10); + } + + key = "CellID="; + value = strstr(response, key); + if (value == NULL) { + goto done; + } else { + value += strlen(key); + site_survey.cell_id = strtoul(value, NULL, 10); + } + + key = "RSRP="; + value = strstr(response, key); + if (value == NULL) { + goto done; + } else { + value += strlen(key); + site_survey.rsrp = strtol(value, NULL, 10); + } + + key = "RSRQ="; + value = strstr(response, key); + if (value == NULL) { + goto done; + } else { + value += strlen(key); + site_survey.rsrq = strtol(value, NULL, 10); + } + + event_handler(HL7800_EVENT_SITE_SURVEY, &site_survey); + +done: + return true; +} + #ifdef CONFIG_NEWLIB_LIBC /* Handler: +CCLK: "yy/MM/dd,hh:mm:ss±zz" */ static bool on_cmd_rtc_query(struct net_buf **buf, uint16_t len) @@ -4012,6 +4096,7 @@ static void hl7800_rx(void) CMD_HANDLER("+KCARRIERCFG: ", operator_index_query), CMD_HANDLER("AT+CIMI", atcmdinfo_imsi), CMD_HANDLER("+CFUN: ", modem_functionality), + CMD_HANDLER("%MEAS: ", survey_status), #ifdef CONFIG_NEWLIB_LIBC CMD_HANDLER("+CCLK: ", rtc_query), #endif diff --git a/include/drivers/modem/hl7800.h b/include/drivers/modem/hl7800.h index 0b42d898b99..759b21a2958 100644 --- a/include/drivers/modem/hl7800.h +++ b/include/drivers/modem/hl7800.h @@ -84,6 +84,13 @@ struct mdm_hl7800_apn { #define MDM_HL7800_SET_POLTE_USER_AND_PASSWORD_FMT_STR "AT%%POLTECMD=\"SERVERAUTH\",\"%s\",\"%s\"" +struct mdm_hl7800_site_survey { + uint32_t earfcn; /* EUTRA Absolute Radio Frequency Channel Number */ + uint32_t cell_id; + int rsrp; + int rsrq; +}; + enum mdm_hl7800_radio_mode { MDM_RAT_CAT_M1 = 0, MDM_RAT_CAT_NB1 }; enum mdm_hl7800_event { @@ -104,7 +111,8 @@ enum mdm_hl7800_event { HL7800_EVENT_GPS_POSITION_STATUS, HL7800_EVENT_POLTE_REGISTRATION, HL7800_EVENT_POLTE_LOCATE_STATUS, - HL7800_EVENT_POLTE + HL7800_EVENT_POLTE, + HL7800_EVENT_SITE_SURVEY, }; enum mdm_hl7800_startup_state { @@ -237,6 +245,7 @@ struct mdm_hl7800_polte_location_data { * HL7800_EVENT_POLTE_REGISTRATION mdm_hl7800_polte_registration_event_data * HL7800_EVENT_POLTE mdm_hl7800_polte_location_data * HL7800_EVENT_POLTE_LOCATE_STATUS int + * HL7800_EVENT_SITE_SURVEY mdm_hl7800_site_survey */ typedef void (*mdm_hl7800_event_callback_t)(enum mdm_hl7800_event event, void *event_data); @@ -441,6 +450,16 @@ int32_t mdm_hl7800_polte_enable(char *user, char *password); */ int32_t mdm_hl7800_polte_locate(void); +/** + * @brief Perform a site survey. This command may return different values + * each time it is run (depending on what is in range). + * + * HL7800_EVENT_SITE_SURVEY is generated for each response received from modem. + * + * @retval negative error code, 0 on success + */ +int32_t mdm_hl7800_perform_site_survey(void); + #ifdef __cplusplus } #endif