PX4 Firmware
PX4 Autopilot Software http://px4.io
mavlink_shell.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2016 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file mavlink_shell.cpp
36  * A shell to be used via MAVLink
37  *
38  * @author Beat Küng <beat-kueng@gmx.net>
39  */
40 
41 #include "mavlink_shell.h"
42 #include <px4_platform_common/defines.h>
43 
44 #include <unistd.h>
45 #include <errno.h>
46 #include <sys/ioctl.h>
47 
48 
49 #ifdef __PX4_NUTTX
50 #include <nshlib/nshlib.h>
51 #endif /* __PX4_NUTTX */
52 
53 #ifdef __PX4_CYGWIN
54 #include <asm/socket.h>
55 #endif
56 
58 {
59  //closing the pipes will stop the thread as well
60  if (_to_shell_fd >= 0) {
61  PX4_INFO("Stopping mavlink shell");
62  close(_to_shell_fd);
63  }
64 
65  if (_from_shell_fd >= 0) {
66  close(_from_shell_fd);
67  }
68 }
69 
71 {
72  //this currently only works for NuttX
73 #ifndef __PX4_NUTTX
74  return -1;
75 #endif /* __PX4_NUTTX */
76 
77 
78  PX4_INFO("Starting mavlink shell");
79 
80  int p1[2], p2[2];
81 
82  /* Create the shell task and redirect its stdin & stdout. If we used pthread, we would redirect
83  * stdin/out of the calling process as well, so we need px4_task_spawn_cmd. However NuttX only
84  * keeps (duplicates) the first 3 fd's when creating a new task, all others are not inherited.
85  * This means we need to temporarily change the first 3 fd's of the current task (or at least
86  * the first 2 if stdout=stderr).
87  * And we hope :-) that during the temporary phase, no other thread from the same task writes to
88  * stdout (as it would end up in the pipe).
89  */
90 
91  if (pipe(p1) != 0) {
92  return -errno;
93  }
94 
95  if (pipe(p2) != 0) {
96  close(p1[0]);
97  close(p1[1]);
98  return -errno;
99  }
100 
101  int ret = 0;
102 
103  _from_shell_fd = p1[0];
104  _to_shell_fd = p2[1];
105  _shell_fds[0] = p2[0];
106  _shell_fds[1] = p1[1];
107 
108  int fd_backups[2]; //we don't touch stderr, we will redirect it to stdout in the startup of the shell task
109 
110  for (int i = 0; i < 2; ++i) {
111  fd_backups[i] = dup(i);
112 
113  if (fd_backups[i] == -1) {
114  ret = -errno;
115  }
116  }
117 
118  dup2(_shell_fds[0], 0);
119  dup2(_shell_fds[1], 1);
120 
121  if (ret == 0) {
122  _task = px4_task_spawn_cmd("mavlink_shell",
123  SCHED_DEFAULT,
124  SCHED_PRIORITY_DEFAULT,
125  2048,
127  nullptr);
128 
129  if (_task < 0) {
130  ret = -1;
131  }
132  }
133 
134  //restore fd's
135  for (int i = 0; i < 2; ++i) {
136  if (dup2(fd_backups[i], i) == -1) {
137  ret = -errno;
138  }
139 
140  close(fd_backups[i]);
141  }
142 
143  //close unused pipe fd's
144  close(_shell_fds[0]);
145  close(_shell_fds[1]);
146 
147  return ret;
148 }
149 
150 int MavlinkShell::shell_start_thread(int argc, char *argv[])
151 {
152  dup2(1, 2); //redirect stderror to stdout
153 
154 #ifdef __PX4_NUTTX
155  nsh_consolemain(0, NULL);
156 #endif /* __PX4_NUTTX */
157 
158  return 0;
159 }
160 
161 size_t MavlinkShell::write(uint8_t *buffer, size_t len)
162 {
163  return ::write(_to_shell_fd, buffer, len);
164 }
165 
166 size_t MavlinkShell::read(uint8_t *buffer, size_t len)
167 {
168  return ::read(_from_shell_fd, buffer, len);
169 }
170 
172 {
173  int ret = 0;
174 
175  if (ioctl(_from_shell_fd, FIONREAD, (unsigned long)&ret) == OK) {
176  return ret;
177  }
178 
179  return 0;
180 }
static void read(bootloader_app_shared_t *pshared)
static void write(bootloader_app_shared_t *pshared)
#define OK
Definition: uavcan_main.cpp:71