Skip to content

Commit 6e86094

Browse files
committed
driver: modem: gsm_ppp: Add Quectel GNSS commands
1 parent 114574a commit 6e86094

File tree

3 files changed

+322
-0
lines changed

3 files changed

+322
-0
lines changed

drivers/modem/Kconfig.gsm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ config MODEM_GSM_QUECTEL
3535

3636
endchoice
3737

38+
config MODEM_GSM_QUECTEL_GNSS
39+
bool "Enables GNSS functions for Quectel modems"
40+
depends on MODEM_GSM_QUECTEL
41+
default n
42+
help
43+
Enables GPS functions for Quectel modems that support GNSS.
3844

3945
config MODEM_GSM_RX_STACK_SIZE
4046
int "Size of the stack allocated for receiving data from modem"

drivers/modem/gsm_ppp.c

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,16 @@ static const char TIME_STRING_FORMAT[] = "\"yy/MM/dd,hh:mm:ss?zz\"";
7777
#define SIZE_OF_NUL 1
7878
#endif
7979

80+
#if CONFIG_MODEM_GSM_QUECTEL_GNSS
81+
static const char quectel_nmea_str[5][16] = {
82+
"gpsnmeatype\0",
83+
"glonassnmeatype\0",
84+
"galileonmeatype\0",
85+
"beidounmeatype\0",
86+
"gsvextnmeatype\0",
87+
};
88+
#endif
89+
8090
/* Modem network registration state */
8191
enum network_state {
8292
GSM_NOT_REGISTERED = 0,
@@ -507,6 +517,170 @@ static const struct setup_cmd setup_cmds[] = {
507517
SETUP_CMD_NOHANDLE("AT+CGDCONT=1,\"IP\",\"" CONFIG_MODEM_GSM_APN "\""),
508518
};
509519

520+
#ifdef CONFIG_MODEM_GSM_QUECTEL_GNSS
521+
int quectel_gnss_cfg_outport(const struct device *dev, char* outport)
522+
{
523+
int ret;
524+
char buf[sizeof("AT+QGPSCFG=\"outport\",\"#########\"")] = {0};
525+
struct gsm_modem *gsm = dev->data;
526+
527+
snprintk(buf, sizeof(buf), "AT+QGPSCFG=\"outport\",\"%s\"", outport);
528+
529+
ret = modem_cmd_send(&gsm->context.iface, &gsm->context.cmd_handler,
530+
NULL, 0U, buf, &gsm->sem_response,
531+
GSM_CMD_AT_TIMEOUT);
532+
if (ret < 0) {
533+
LOG_ERR("%s ret:%d", log_strdup(buf), ret);
534+
errno = -ret;
535+
return -1;
536+
}
537+
538+
LOG_INF("Configured GNSS outport to %s", outport);
539+
540+
return ret;
541+
}
542+
543+
int quectel_gnss_cfg_nmea(const struct device *dev, quectel_nmea_types_t gnss,
544+
quectel_nmea_type_t cfg)
545+
{
546+
int ret;
547+
uint8_t val;
548+
char buf[sizeof("AT+QGPSCFG=\"glonassnmeatype\",##")] = {0};
549+
struct gsm_modem *gsm = dev->data;
550+
551+
switch(gnss)
552+
{
553+
case QUECTEL_NMEA_GPS:
554+
val = (cfg.gps.vtg << 4 | cfg.gps.gsa << 3 |
555+
cfg.gps.gsv << 2 | cfg.gps.rmc << 1 |
556+
cfg.gps.gga);
557+
558+
LOG_INF("Configuring GPS NMEA: %X", val);
559+
560+
break;
561+
case QUECTEL_NMEA_GLONASS:
562+
val = (cfg.glonass.gns << 2 | cfg.glonass.gsa << 1 |
563+
cfg.glonass.gsv);
564+
565+
LOG_INF("Configuring GLONASS NMEA: %X", val);
566+
567+
break;
568+
case QUECTEL_NMEA_GALILEO:
569+
val = (cfg.galileo.gsv);
570+
571+
LOG_INF("Configuring GALILEO NMEA: %X", val);
572+
573+
break;
574+
case QUECTEL_NMEA_BEIDOU:
575+
val = (cfg.beidou.gsv << 1 | cfg.beidou.gsa);
576+
577+
LOG_INF("Configuring BEIDOU NMEA: %X", val);
578+
579+
break;
580+
case QUECTEL_NMEA_GSVEXT:
581+
val = cfg.gsvext.enable;
582+
583+
LOG_INF("Configuring GSVEXT NMEA: %X", val);
584+
585+
break;
586+
default:
587+
LOG_ERR("Invalid quectel_nmea_types_t");
588+
errno = -EINVAL;
589+
return -1;
590+
}
591+
592+
snprintk(buf, sizeof(buf), "AT+QGPSCFG=\"%s\",%u",
593+
quectel_nmea_str[gnss], val);
594+
595+
ret = modem_cmd_send(&gsm->context.iface, &gsm->context.cmd_handler,
596+
NULL, 0U, buf, &gsm->sem_response,
597+
GSM_CMD_AT_TIMEOUT);
598+
if (ret < 0) {
599+
LOG_ERR("%s ret:%d", log_strdup(buf), ret);
600+
errno = -ret;
601+
return -1;
602+
}
603+
604+
return ret;
605+
}
606+
607+
int quectel_gnss_cfg_gnss(const struct device *dev, quectel_gnss_conf_t cfg)
608+
{
609+
int ret;
610+
char buf[sizeof("AT+QGPSCFG=\"gnssconfig\",#")] = {0};
611+
struct gsm_modem *gsm = dev->data;
612+
613+
snprintk(buf, sizeof(buf), "AT+QGPSCFG=\"gnssconfig\",%u", cfg);
614+
615+
ret = modem_cmd_send(&gsm->context.iface, &gsm->context.cmd_handler,
616+
NULL, 0U, buf, &gsm->sem_response,
617+
GSM_CMD_AT_TIMEOUT);
618+
if (ret < 0) {
619+
LOG_ERR("%s ret:%d", log_strdup(buf), ret);
620+
errno = -ret;
621+
return -1;
622+
}
623+
624+
LOG_INF("Configured GNSS config: %d", (int)cfg);
625+
626+
return ret;
627+
}
628+
629+
int quectel_gnss_enable(const struct device *dev, uint8_t fixmaxtime,
630+
uint16_t fixmaxdist, uint16_t fixcount,
631+
uint16_t fixrate)
632+
{
633+
int ret;
634+
char buf[sizeof("AT+QGPS=1,###,####,####,#####")] = {0};
635+
struct gsm_modem *gsm = dev->data;
636+
637+
if ((fixmaxtime == 0) ||
638+
(fixmaxtime == 0) || (fixmaxtime > 1000) ||
639+
(fixcount > 1000) ||
640+
(fixrate == 0))
641+
{
642+
errno = -EINVAL;
643+
return -1;
644+
}
645+
646+
snprintk(buf, sizeof(buf), "AT+QGPS=1,%u,%u,%u,%u", fixmaxtime,
647+
fixmaxdist,
648+
fixcount,
649+
fixrate);
650+
651+
ret = modem_cmd_send(&gsm->context.iface, &gsm->context.cmd_handler,
652+
NULL, 0U, buf, &gsm->sem_response,
653+
GSM_CMD_AT_TIMEOUT);
654+
if (ret < 0) {
655+
LOG_ERR("%s ret:%d", log_strdup(buf), ret);
656+
errno = -ret;
657+
return -1;
658+
}
659+
660+
LOG_INF("Enabled Quectel GNSS");
661+
662+
return ret;
663+
}
664+
665+
int quectel_gnss_disable(const struct device *dev)
666+
{
667+
int ret;
668+
struct gsm_modem *gsm = dev->data;
669+
ret = modem_cmd_send(&gsm->context.iface, &gsm->context.cmd_handler,
670+
NULL, 0U, "AT+QGPSEND", &gsm->sem_response,
671+
GSM_CMD_AT_TIMEOUT);
672+
if (ret < 0) {
673+
LOG_ERR("AT+QGPSEND ret:%d", ret);
674+
errno = -ret;
675+
return -1;
676+
}
677+
678+
LOG_INF("Disabled Quectel GNSS");
679+
680+
return ret;
681+
}
682+
#endif /* #if CONFIG_MODEM_QUECTEL_GNSS */
683+
510684
#ifdef CONFIG_NEWLIB_LIBC
511685
static bool valid_time_string(const char *time_string)
512686
{

include/drivers/gsm_ppp.h

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,86 @@
1414

1515
#define GSM_MODEM_DEVICE_NAME "modem_gsm"
1616

17+
#ifdef CONFIG_MODEM_GSM_QUECTEL_GNSS
18+
typedef enum quectel_gnss_modes
19+
{
20+
QUECTEL_GNSS_STANDALONE = 0,
21+
QUECTEL_GNSS_MS_BASED,
22+
QUECTEL_GNSS_MS_ASSISTED,
23+
QUECTEL_GNSS_SPEED_OPTIMAL,
24+
QUECTEL_GNSS_MODE_MAX,
25+
} quectel_gnss_modes_t;
26+
27+
typedef enum quectel_nmea_types
28+
{
29+
QUECTEL_NMEA_GPS = 0,
30+
QUECTEL_NMEA_GLONASS,
31+
QUECTEL_NMEA_GALILEO,
32+
QUECTEL_NMEA_BEIDOU,
33+
QUECTEL_NMEA_GSVEXT,
34+
} quectel_nmea_types_t;
35+
36+
typedef enum quectel_gnss_conf
37+
{
38+
/* GLONASS off/BeiDou off/Galileo off */
39+
GN_OFF_BD_OFF_GL_OFF = 0,
40+
/* GLONASS on/BeiDou on/Galileo on */
41+
GN_ON_BD_ON_GL_ON,
42+
/* GLONASS on/BeiDou on/Galileo off */
43+
GN_ON_BD_ON_GL_OFF,
44+
/* GLONASS on/BeiDou off/Galileo on */
45+
GN_ON_BD_OFF_GL_ON,
46+
/* GLONASS on/BeiDou off/Galileo off */
47+
GN_ON_BD_OFF_GL_OFF,
48+
/* GLONASS off/BeiDou on/Galileo on */
49+
GN_OFF_BD_ON_GL_ON,
50+
/* GLONASS off/BeiDou off/Galileo on */
51+
GN_OFF_BD_OFF_GL_ON,
52+
} quectel_gnss_conf_t;
53+
54+
typedef union quectel_nmea_type
55+
{
56+
struct quectel_nmea_type_gps
57+
{
58+
bool gga;
59+
bool rmc;
60+
bool gsv;
61+
bool gsa;
62+
bool vtg;
63+
} gps;
64+
65+
struct quectel_nmea_type_glonass
66+
{
67+
bool gsv;
68+
bool gsa;
69+
bool gns;
70+
} glonass;
71+
72+
struct quectel_nmea_type_galileo
73+
{
74+
bool gsv;
75+
} galileo;
76+
77+
struct quectel_nmea_type_beidou
78+
{
79+
bool gsa;
80+
bool gsv;
81+
} beidou;
82+
83+
struct quectel_nmea_type_gsvext
84+
{
85+
bool enable;
86+
} gsvext;
87+
} quectel_nmea_type_t;
88+
89+
/* GNSS output disabled */
90+
#define QUECTEL_GNSS_OP_NONE "none"
91+
/* GNSS output to USB port */
92+
#define QUECTEL_GNSS_OP_USB "usbnmea"
93+
/* GNSS output to UART debug port */
94+
#define QUECTEL_GNSS_OP_UART "uartdebug"
95+
#endif
96+
1797
/** @cond INTERNAL_HIDDEN */
1898
struct device;
1999
void gsm_ppp_start(const struct device *dev);
@@ -33,6 +113,68 @@ int32_t gsm_ppp_get_local_time(const struct device *dev,
33113
struct tm *tm,
34114
int32_t *offset);
35115
#endif
116+
117+
#ifdef CONFIG_MODEM_GSM_QUECTEL_GNSS
118+
/**
119+
* @brief Configure the outport of the GNSS
120+
*
121+
* @param[in] dev Pointer to the gsm_ppp device structure
122+
* @param[in] outport Outport of the NMEA sentences, can be either
123+
* QUECTEL_GNSS_OP_NONE, QUECTEL_GNSS_OP_USB or QUECTEL_GNSS_OP_UART.
124+
* @retval 0 on success, negative on failure.
125+
*/
126+
int quectel_gnss_cfg_outport(const struct device *dev, char* outport);
127+
128+
/**
129+
* @brief Selectively configures the NMEA sentences
130+
*
131+
* @param[in] dev Pointer to the gsm_ppp device structure
132+
* @param[in] gnss Type of the GNSS to configure, see quectel_nmea_types_t.
133+
* @param[in] cfg The configuration itself, see quectel_nmea_type_t.
134+
* @retval 0 on success, negative on failure.
135+
*/
136+
int quectel_gnss_cfg_nmea(const struct device *dev,
137+
quectel_nmea_types_t gnss,
138+
quectel_nmea_type_t cfg);
139+
140+
/**
141+
* @brief Configures supported GNSS constellation
142+
*
143+
* @param[in] dev Pointer to the gsm_ppp device structure
144+
* @param[in] cfg The configuration of the constellation, see
145+
* quectel_gnss_conf_t.
146+
* @retval 0 on success, negative on failure.
147+
*/
148+
int quectel_gnss_cfg_gnss(const struct device *dev,
149+
quectel_gnss_conf_t cfg);
150+
151+
/**
152+
* @brief Enables the GNSS, for more info please read the Quectel GNSS manual.
153+
*
154+
* @param[in] dev Pointer to the gsm_ppp device structure
155+
* @param[in] fixmaxtime Maximum positioning time in second. [1 - 255 : 30]
156+
* @param[in] fixmaxdist Accuracy threshold of positioning in meter.
157+
* [1 - 1000 : 50]
158+
* @param[in] fixcount Number of attempts for positioning. 0 for continuous,
159+
* maximum 1000. [0 - 1000 : 0]
160+
* @param[in] fixrate Interval time between positioning in second.
161+
* [1 - 65535 : 1]
162+
*
163+
* @retval 0 on success, negative on failure.
164+
*/
165+
int quectel_gnss_enable(const struct device *dev, uint8_t fixmaxtime,
166+
uint16_t fixmaxdist, uint16_t fixcount,
167+
uint16_t fixrate);
168+
169+
/**
170+
* @brief Disables the GNSS.
171+
*
172+
* @param[in] dev Pointer to the gsm_ppp device structure
173+
*
174+
* @retval 0 on success, negative on failure.
175+
*/
176+
int quectel_gnss_disable(const struct device *dev);
177+
#endif
36178
/** @endcond */
37179

38180
#endif /* GSM_PPP_H_ */

0 commit comments

Comments
 (0)