@@ -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 */
8191enum 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
511685static bool valid_time_string (const char * time_string )
512686{
0 commit comments