diff --git a/drivers/modem/Kconfig.hl7800 b/drivers/modem/Kconfig.hl7800 index 0c5d16f99ad..1623793b2e8 100644 --- a/drivers/modem/Kconfig.hl7800 +++ b/drivers/modem/Kconfig.hl7800 @@ -269,9 +269,27 @@ config MODEM_HL7800_GET_IP_ADDR_INFO_ATTEMPTS int "Number of attempts to get IP address info during init" default 4 -config MODEM_HL7800_DELAY_START +choice + prompt "Modem Boot Type" + default MODEM_HL7800_BOOT_NORMAL + +config MODEM_HL7800_BOOT_NORMAL + bool "No Delay" + +config MODEM_HL7800_BOOT_DELAY bool "Delay secondary initialization of driver and network attach" help - When true the application must call mdm_hl7800_reset. + When true the application must call mdm_hl7800_reset. + This mode delays the validity of modem info. + +config MODEM_HL7800_BOOT_IN_AIRPLANE_MODE + bool "Enter airplane mode during init" + help + mdm_hl7800_set_functionality must be used by app to exit + airplane mode. + If bands are reconfigured, then this setting is overridden + because modem is rebooted into full functionality mode. + +endchoice endif # MODEM_HL7800 diff --git a/drivers/modem/hl7800.c b/drivers/modem/hl7800.c index eb668379bca..25b989d132b 100644 --- a/drivers/modem/hl7800.c +++ b/drivers/modem/hl7800.c @@ -516,6 +516,7 @@ struct hl7800_iface_ctx { int device_services_ind; bool new_rat_cmd_support; uint8_t operator_index; + enum mdm_hl7800_functionality functionality; /* modem state */ bool allow_sleep; @@ -1075,6 +1076,41 @@ int32_t mdm_hl7800_get_operator_index(void) } } +int32_t mdm_hl7800_get_functionality(void) +{ + int ret; + + hl7800_lock(); + wakeup_hl7800(); + ictx.last_socket_id = 0; + ret = send_at_cmd(NULL, "AT+CFUN?", MDM_CMD_SEND_TIMEOUT, 0, false); + allow_sleep(true); + hl7800_unlock(); + + if (ret < 0) { + return ret; + } else { + return ictx.functionality; + } +} + +int32_t mdm_hl7800_set_functionality(enum mdm_hl7800_functionality mode) +{ + int ret; + char buf[sizeof("AT+CFUN=0,0")] = { 0 }; + + hl7800_lock(); + wakeup_hl7800(); + snprintk(buf, sizeof(buf), "AT+CFUN=%u,0", mode); + ictx.last_socket_id = 0; + ret = send_at_cmd(NULL, buf, MDM_CMD_SEND_TIMEOUT, + MDM_DEFAULT_AT_CMD_RETRIES, false); + allow_sleep(true); + hl7800_unlock(); + + return ret; +} + void mdm_hl7800_generate_status_events(void) { hl7800_lock(); @@ -2480,6 +2516,32 @@ done: return true; } +static bool on_cmd_modem_functionality(struct net_buf **buf, uint16_t len) +{ + struct net_buf *frag = NULL; + size_t out_len; + char rsp[MDM_HL7800_MODEM_FUNCTIONALITY_SIZE]; + + wait_for_modem_data_and_newline(buf, net_buf_frags_len(*buf), + MDM_HL7800_MODEM_FUNCTIONALITY_SIZE); + + len = net_buf_findcrlf(*buf, &frag); + frag = NULL; + if (!frag) { + LOG_ERR("Unable to find end of response"); + goto done; + } + + out_len = net_buf_linearize(rsp, MDM_HL7800_MODEM_FUNCTIONALITY_STRLEN, + *buf, 0, len); + rsp[out_len] = 0; + ictx.functionality = strtol(rsp, NULL, 10); + + LOG_INF("Modem Functionality: %u", ictx.functionality); +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) @@ -3446,6 +3508,7 @@ static void hl7800_rx(void) CMD_HANDLER("AT+CEREG?", network_report_query), CMD_HANDLER("+KCARRIERCFG: ", operator_index_query), CMD_HANDLER("AT+CIMI", atcmdinfo_imsi), + CMD_HANDLER("+CFUN: ", modem_functionality), #ifdef CONFIG_NEWLIB_LIBC CMD_HANDLER("+CCLK: ", rtc_query), #endif @@ -3839,12 +3902,6 @@ static int modem_boot_handler(char *reason) __ASSERT(!ictx.mdm_echo_is_on, "Echo should be off"); - /* The Laird bootloader puts the modem into airplane mode ("AT+CFUN=4,0"). - * The radio is enabled here because airplane mode - * survives reset and power removal. - */ - SEND_AT_CMD_EXPECT_OK("AT+CFUN=1,0"); - return 0; error: @@ -3993,6 +4050,13 @@ reboot: } #endif + /* If this isn't defined, then keep the current state. + * If the bands are being reconfigured, this is overridden. + */ +#ifdef CONFIG_MODEM_HL7800_BOOT_IN_AIRPLANE_MODE + SEND_AT_CMD_EXPECT_OK("AT+CFUN=4,0"); +#endif + SEND_AT_CMD_EXPECT_OK("AT+KBNDCFG?"); /* Configure LTE bands */ @@ -4191,7 +4255,7 @@ reboot: /* trigger APN update event */ event_handler(HL7800_EVENT_APN_UPDATE, &ictx.mdm_apn); -#ifdef CONFIG_MODEM_HL7800_DELAY_START +#ifdef CONFIG_MODEM_HL7800_BOOT_DELAY if (!ictx.initialized) { if (ictx.iface != NULL) { hl7800_build_mac(&ictx); @@ -5073,7 +5137,7 @@ static int hl7800_init(const struct device *dev) RX_THREAD_PRIORITY, 0, K_NO_WAIT), "hl7800 rx"); -#ifdef CONFIG_MODEM_HL7800_DELAY_START +#ifdef CONFIG_MODEM_HL7800_BOOT_DELAY modem_reset(); #else ret = modem_reset_and_configure(); @@ -5090,7 +5154,7 @@ static void offload_iface_init(struct net_if *iface) iface->if_dev->offload = &offload_funcs; ctx->iface = iface; - if (!IS_ENABLED(CONFIG_MODEM_HL7800_DELAY_START)) { + if (!IS_ENABLED(CONFIG_MODEM_HL7800_BOOT_DELAY)) { hl7800_build_mac(&ictx); net_if_set_link_addr(iface, ictx.mac_addr, sizeof(ictx.mac_addr), NET_LINK_ETHERNET); diff --git a/include/drivers/modem/hl7800.h b/include/drivers/modem/hl7800.h index ed3e84e9a68..c652c28d40c 100644 --- a/include/drivers/modem/hl7800.h +++ b/include/drivers/modem/hl7800.h @@ -64,6 +64,10 @@ struct mdm_hl7800_apn { #define MDM_HL7800_IMSI_MAX_STR_SIZE 16 #define MDM_HL7800_IMSI_MAX_STRLEN (MDM_HL7800_IMSI_MAX_STR_SIZE - 1) +#define MDM_HL7800_MODEM_FUNCTIONALITY_SIZE 2 +#define MDM_HL7800_MODEM_FUNCTIONALITY_STRLEN \ + (MDM_HL7800_MODEM_FUNCTIONALITY_SIZE - 1) + enum mdm_hl7800_radio_mode { MDM_RAT_CAT_M1 = 0, MDM_RAT_CAT_NB1 }; enum mdm_hl7800_event { @@ -122,6 +126,12 @@ enum mdm_hl7800_fota_state { HL7800_FOTA_COMPLETE, }; +enum mdm_hl7800_functionality { + HL7800_FUNCTIONALITY_MINIMUM = 0, + HL7800_FUNCTIONALITY_FULL = 1, + HL7800_FUNCTIONALITY_AIRPLANE = 4 +}; + /* The modem reports state values as an enumeration and a string */ struct mdm_hl7800_compound_event { uint8_t code; @@ -283,6 +293,25 @@ int32_t mdm_hl7800_update_fw(char *file_path); */ int32_t mdm_hl7800_get_operator_index(void); +/** + * @brief Get modem functionality + * + * @return int32_t negative errno on failure, else mdm_hl7800_functionality + */ +int32_t mdm_hl7800_get_functionality(void); + +/** + * @brief Set airplane, normal, or reduced functionality mode. + * Airplane mode persists when reset. + * + * @note Boot functionality is also controlled by Kconfig + * MODEM_HL7800_BOOT_IN_AIRPLANE_MODE. + * + * @param mode + * @return int32_t negative errno, 0 on success + */ +int32_t mdm_hl7800_set_functionality(enum mdm_hl7800_functionality mode); + #ifdef __cplusplus } #endif