Line data Source code
1 : /*
2 : This program is free software: you can redistribute it and/or modify
3 : it under the terms of the GNU General Public License as published by
4 : the Free Software Foundation, either version 3 of the License, or
5 : (at your option) any later version.
6 :
7 : This program is distributed in the hope that it will be useful,
8 : but WITHOUT ANY WARRANTY; without even the implied warranty of
9 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 : GNU General Public License for more details.
11 :
12 : You should have received a copy of the GNU General Public License
13 : along with this program. If not, see <http://www.gnu.org/licenses/>.
14 : */
15 : /*
16 : handle device operations over MAVLink
17 : */
18 :
19 : #include "GCS_config.h"
20 :
21 : #if AP_MAVLINK_MSG_DEVICE_OP_ENABLED
22 :
23 : #include <AP_HAL/AP_HAL.h>
24 : #include <AP_HAL/Device.h>
25 : #include <AP_HAL/I2CDevice.h>
26 : #include "GCS.h"
27 : #include <stdio.h>
28 :
29 : extern const AP_HAL::HAL& hal;
30 :
31 : /*
32 : handle DEVICE_OP_READ message
33 : */
34 0 : void GCS_MAVLINK::handle_device_op_read(const mavlink_message_t &msg)
35 : {
36 : mavlink_device_op_read_t packet;
37 0 : mavlink_msg_device_op_read_decode(&msg, &packet);
38 0 : AP_HAL::Device *dev = nullptr;
39 0 : uint8_t retcode = 0;
40 0 : uint8_t data[sizeof(mavlink_device_op_read_reply_t::data)] {};
41 0 : bool ret = false;
42 0 : uint8_t regstart = packet.regstart;
43 :
44 0 : if (packet.bustype == DEVICE_OP_BUSTYPE_I2C) {
45 0 : dev = hal.i2c_mgr->get_device_ptr(packet.bus, packet.address);
46 0 : } else if (packet.bustype == DEVICE_OP_BUSTYPE_SPI) {
47 0 : dev = hal.spi->get_device_ptr(packet.busname);
48 : } else {
49 0 : retcode = 1;
50 0 : goto fail;
51 : }
52 0 : if (!dev) {
53 0 : retcode = 2;
54 0 : goto fail;
55 : }
56 0 : if (packet.count > sizeof(data)) {
57 0 : retcode = 5;
58 0 : goto fail;
59 : }
60 0 : if (!dev->get_semaphore()->take(10)) {
61 0 : retcode = 3;
62 0 : goto fail;
63 : }
64 0 : if (regstart == 0xff) {
65 : // assume raw transfer, non-register interface
66 0 : ret = dev->transfer_bank(packet.bank, nullptr, 0, data, packet.count);
67 : // reply using register start 0 for display purposes
68 0 : regstart = 0;
69 : } else {
70 0 : ret = dev->read_bank_registers(packet.bank, packet.regstart, data, packet.count);
71 : }
72 0 : dev->get_semaphore()->give();
73 0 : if (!ret) {
74 0 : retcode = 4;
75 0 : goto fail;
76 : }
77 0 : mavlink_msg_device_op_read_reply_send(
78 : chan,
79 : packet.request_id,
80 : retcode,
81 : regstart,
82 0 : packet.count,
83 : data,
84 0 : packet.bank);
85 0 : delete dev;
86 0 : return;
87 :
88 0 : fail:
89 0 : mavlink_msg_device_op_read_reply_send(
90 : chan,
91 : packet.request_id,
92 : retcode,
93 0 : packet.regstart,
94 : 0,
95 : nullptr,
96 0 : packet.bank);
97 0 : delete dev;
98 : }
99 :
100 : /*
101 : handle DEVICE_OP_WRITE message
102 : */
103 0 : void GCS_MAVLINK::handle_device_op_write(const mavlink_message_t &msg)
104 : {
105 : mavlink_device_op_write_t packet;
106 0 : mavlink_msg_device_op_write_decode(&msg, &packet);
107 0 : AP_HAL::Device *dev = nullptr;
108 0 : uint8_t retcode = 0;
109 :
110 0 : if (packet.bustype == DEVICE_OP_BUSTYPE_I2C) {
111 0 : dev = hal.i2c_mgr->get_device_ptr(packet.bus, packet.address);
112 0 : } else if (packet.bustype == DEVICE_OP_BUSTYPE_SPI) {
113 0 : dev = hal.spi->get_device_ptr(packet.busname);
114 : } else {
115 0 : retcode = 1;
116 0 : goto fail;
117 : }
118 0 : if (!dev) {
119 0 : retcode = 2;
120 0 : goto fail;
121 : }
122 0 : if (packet.count > sizeof(packet.data)) {
123 : // bound count against the payload buffer to prevent OOB read
124 : // from packet.data[i] in the register write loop and OOB read
125 : // in the raw transfer_bank() path below.
126 0 : retcode = 5;
127 0 : goto fail;
128 : }
129 0 : if (!dev->get_semaphore()->take(10)) {
130 0 : retcode = 3;
131 0 : goto fail;
132 : }
133 0 : if (packet.regstart == 0xff) {
134 : // assume raw transfer, non-register interface
135 0 : if (!dev->transfer_bank(packet.bank, packet.data, packet.count, nullptr, 0)) {
136 0 : retcode = 4;
137 : }
138 : } else {
139 0 : for (uint8_t i=0; i<packet.count; i++) {
140 0 : if (!dev->write_bank_register(packet.bank, packet.regstart+i, packet.data[i])) {
141 0 : retcode = 4;
142 0 : break;
143 : }
144 : }
145 : }
146 0 : dev->get_semaphore()->give();
147 :
148 0 : fail:
149 0 : mavlink_msg_device_op_write_reply_send(
150 : chan,
151 : packet.request_id,
152 : retcode);
153 :
154 0 : delete dev;
155 0 : }
156 :
157 : #endif // AP_MAVLINK_MSG_DEVICE_OP_ENABLED
|