LCOV - code coverage report
Current view: top level - GCS_MAVLink - GCS_serial_control.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 95 0.0 %
Date: 2026-09-09 11:02:08 Functions: 0 1 0.0 %

          Line data    Source code
       1             : /*
       2             :   MAVLink SERIAL_CONTROL handling
       3             :  */
       4             : 
       5             : /*
       6             :    This program is free software: you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation, either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include "GCS_config.h"
      21             : 
      22             : #if AP_MAVLINK_MSG_SERIAL_CONTROL_ENABLED
      23             : 
      24             : #include <AP_HAL/AP_HAL.h>
      25             : #include "GCS.h"
      26             : #include <AP_GPS/AP_GPS.h>
      27             : 
      28             : extern const AP_HAL::HAL& hal;
      29             : 
      30             : /**
      31             :    handle a SERIAL_CONTROL message
      32             :  */
      33           0 : void GCS_MAVLINK::handle_serial_control(const mavlink_message_t &msg)
      34             : {
      35             :     mavlink_serial_control_t packet;
      36           0 :     mavlink_msg_serial_control_decode(&msg, &packet);
      37             : 
      38           0 :     AP_HAL::UARTDriver *port = nullptr;
      39           0 :     AP_HAL::BetterStream *stream = nullptr;
      40             : 
      41           0 :     if (packet.flags & SERIAL_CONTROL_FLAG_REPLY) {
      42             :         // how did this packet get to us?
      43           0 :         return;
      44             :     }
      45             : 
      46           0 :     bool exclusive = (packet.flags & SERIAL_CONTROL_FLAG_EXCLUSIVE) != 0;
      47             : 
      48           0 :     switch (packet.device) {
      49           0 :     case SERIAL_CONTROL_DEV_TELEM1: {
      50           0 :         GCS_MAVLINK *link = gcs().chan(1);
      51           0 :         if (link == nullptr) {
      52           0 :             break;
      53             :         }
      54           0 :         stream = port = link->get_uart();
      55           0 :         link->lock(exclusive);
      56           0 :         break;
      57             :     }
      58           0 :     case SERIAL_CONTROL_DEV_TELEM2: {
      59           0 :         GCS_MAVLINK *link = gcs().chan(2);
      60           0 :         if (link == nullptr) {
      61           0 :             break;
      62             :         }
      63           0 :         stream = port = link->get_uart();
      64           0 :         link->lock(exclusive);
      65           0 :         break;
      66             :     }
      67             : #if AP_GPS_ENABLED
      68           0 :     case SERIAL_CONTROL_DEV_GPS1:
      69           0 :         stream = port = hal.serial(3);
      70           0 :         AP::gps().lock_port(0, exclusive);
      71           0 :         break;
      72           0 :     case SERIAL_CONTROL_DEV_GPS2:
      73           0 :         stream = port = hal.serial(4);
      74           0 :         AP::gps().lock_port(1, exclusive);
      75           0 :         break;
      76             : #endif  // AP_GPS_ENABLED
      77           0 :     case SERIAL_CONTROL_SERIAL0 ... SERIAL_CONTROL_SERIAL9: {
      78             :         // direct access to a SERIALn port
      79           0 :         stream = port = AP::serialmanager().get_serial_by_id(packet.device - SERIAL_CONTROL_SERIAL0);
      80             : 
      81             :         // see if we need to lock mavlink
      82           0 :         for (uint8_t i=0; i<gcs().num_gcs(); i++) {
      83           0 :             GCS_MAVLINK *link = gcs().chan(i);
      84           0 :             if (link == nullptr || link->get_uart() != port) {
      85           0 :                 continue;
      86             :             }
      87           0 :             link->lock(exclusive);
      88           0 :             break;
      89             :         }
      90           0 :         break;
      91             :     }
      92             : 
      93           0 :     default:
      94             :         // not supported yet
      95           0 :         return;
      96             :     }
      97           0 :     if (stream == nullptr) {
      98             :         // this is probably very bad
      99             : #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
     100           0 :         AP_HAL::panic("stream is nullptr");
     101             : #endif
     102           0 :         return;
     103             :     }
     104             : 
     105           0 :     if (exclusive && port != nullptr) {
     106             :         // force flow control off for exclusive access. This protocol
     107             :         // is used to talk to bootloaders which may not have flow
     108             :         // control support
     109           0 :         port->set_flow_control(AP_HAL::UARTDriver::FLOW_CONTROL_DISABLE);
     110             :     }
     111             : 
     112             :     // optionally change the baudrate
     113           0 :     if (packet.baudrate != 0 && port != nullptr) {
     114           0 :         port->begin(packet.baudrate);
     115             :     }
     116             : 
     117             :     // write the data
     118           0 :     if (packet.count != 0) {
     119           0 :         if (packet.count > sizeof(packet.data)) {
     120           0 :             packet.count = sizeof(packet.data);
     121             :         }
     122             : 
     123           0 :         if ((packet.flags & SERIAL_CONTROL_FLAG_BLOCKING) == 0) {
     124           0 :             stream->write(packet.data, packet.count);
     125             :         } else {
     126           0 :             const uint8_t *data = &packet.data[0];
     127           0 :             uint8_t count = packet.count;
     128           0 :             while (count > 0) {
     129           0 :                 while (stream->txspace() <= 0) {
     130           0 :                     hal.scheduler->delay(5);
     131             :                 }
     132           0 :                 uint16_t n = stream->txspace();
     133           0 :                 if (n > count) {
     134           0 :                     n = count;
     135             :                 }
     136           0 :                 stream->write(data, n);
     137           0 :                 data += n;
     138           0 :                 count -= n;
     139             :             }
     140             :         }
     141             :     }
     142             : 
     143           0 :     if ((packet.flags & SERIAL_CONTROL_FLAG_RESPOND) == 0) {
     144             :         // no response expected
     145           0 :         return;
     146             :     }
     147             : 
     148           0 :     uint8_t flags = packet.flags;
     149             : 
     150           0 : more_data:
     151             :     // sleep for the timeout
     152           0 :     while (packet.timeout != 0 && 
     153           0 :            stream->available() < (int16_t)sizeof(packet.data)) {
     154           0 :         hal.scheduler->delay(1);
     155           0 :         packet.timeout--;
     156             :     }
     157             : 
     158           0 :     packet.flags = SERIAL_CONTROL_FLAG_REPLY;
     159             : 
     160             :     // work out how many bytes are available
     161           0 :     int16_t available = stream->available();
     162           0 :     if (available < 0) {
     163           0 :         available = 0;
     164             :     }
     165           0 :     if (available > (int16_t)sizeof(packet.data)) {
     166           0 :         available = sizeof(packet.data);
     167             :     }
     168           0 :     if (available == 0 && (flags & SERIAL_CONTROL_FLAG_BLOCKING) == 0) {
     169           0 :         return;
     170             :     }
     171             : 
     172           0 :     if (packet.flags & SERIAL_CONTROL_FLAG_BLOCKING) {
     173           0 :         while (!HAVE_PAYLOAD_SPACE(chan, SERIAL_CONTROL)) {
     174           0 :             hal.scheduler->delay(1);
     175             :         }
     176             :     } else {
     177           0 :         if (!HAVE_PAYLOAD_SPACE(chan, SERIAL_CONTROL)) {
     178             :             // no space for reply
     179           0 :             return;
     180             :         }
     181             :     }
     182             : 
     183             :     // read any reply data
     184           0 :     packet.count = 0;
     185           0 :     memset(packet.data, 0, sizeof(packet.data));
     186           0 :     while (available > 0) {
     187           0 :         packet.data[packet.count++] = (uint8_t)stream->read();
     188           0 :         available--;
     189             :     }
     190             : 
     191             :     // and send the reply
     192           0 :     _mav_finalize_message_chan_send(chan, 
     193             :                                     MAVLINK_MSG_ID_SERIAL_CONTROL,
     194             :                                     (const char *)&packet,
     195             :                                     MAVLINK_MSG_ID_SERIAL_CONTROL_MIN_LEN,
     196             :                                     MAVLINK_MSG_ID_SERIAL_CONTROL_LEN,
     197             :                                     MAVLINK_MSG_ID_SERIAL_CONTROL_CRC);
     198           0 :     if ((flags & SERIAL_CONTROL_FLAG_MULTI) && packet.count != 0) {
     199           0 :         if (flags & SERIAL_CONTROL_FLAG_BLOCKING) {
     200           0 :             hal.scheduler->delay(1);
     201             :         }
     202           0 :         goto more_data;
     203             :     }
     204             : }
     205             : 
     206             : #endif  // AP_MAVLINK_MSG_SERIAL_CONTROL_ENABLED

Generated by: LCOV version 1.14