Lely core libraries  2.2.5
sdo_error.cpp
Go to the documentation of this file.
1 
24 #include "coapp.hpp"
25 #include <lely/co/sdo.h>
26 #include <lely/coapp/sdo_error.hpp>
27 #include <lely/util/error.hpp>
28 
29 #include <iomanip>
30 #include <sstream>
31 #include <string>
32 
33 namespace lely {
34 
35 namespace canopen {
36 
37 namespace {
38 
39 class SdoErrcCategory : public ::std::error_category {
40  public:
41  const char*
42  name() const noexcept override {
43  return "SDO";
44  }
45 
46  ::std::error_condition default_error_condition(int ev) const
47  noexcept override;
48 
49  ::std::string
50  message(int ev) const override {
51  return co_sdo_ac2str(ev);
52  }
53 };
54 
55 ::std::error_condition
56 SdoErrcCategory::default_error_condition(int ev) const noexcept {
57  switch (static_cast<SdoErrc>(ev)) {
58  case SdoErrc::TOGGLE:
59  return ::std::errc::protocol_error;
60  case SdoErrc::TIMEOUT:
61  return ::std::errc::timed_out;
62  case SdoErrc::NO_CS:
63  case SdoErrc::BLK_SIZE:
64  case SdoErrc::BLK_SEQ:
65  return ::std::errc::protocol_error;
66  case SdoErrc::BLK_CRC:
67  return ::std::errc::illegal_byte_sequence;
68  case SdoErrc::NO_MEM:
69  return ::std::errc::not_enough_memory;
70  case SdoErrc::NO_ACCESS:
71  case SdoErrc::NO_READ:
72  case SdoErrc::NO_WRITE:
73  return ::std::errc::permission_denied;
74  case SdoErrc::NO_OBJ:
75  return ::std::errc::no_such_file_or_directory;
76  // case SdoErrc::NO_PDO:
77  // case SdoErrc::PDO_LEN:
78  case SdoErrc::PARAM:
79  return ::std::errc::invalid_argument;
80  case SdoErrc::COMPAT:
81  return ::std::errc::no_such_device_or_address;
82  case SdoErrc::HARDWARE:
83  return ::std::errc::io_error;
84  case SdoErrc::TYPE_LEN:
87  return ::std::errc::invalid_argument;
88  case SdoErrc::NO_SUB:
89  return ::std::errc::no_such_file_or_directory;
90  case SdoErrc::PARAM_VAL:
91  return ::std::errc::invalid_argument;
92  case SdoErrc::PARAM_HI:
93  case SdoErrc::PARAM_LO:
95  return ::std::errc::result_out_of_range;
96  case SdoErrc::NO_SDO:
97  return ::std::errc::protocol_not_supported;
98  // case SdoErrc::ERROR:
99  case SdoErrc::DATA:
100  return ::std::errc::io_error;
101  case SdoErrc::DATA_CTL:
102  case SdoErrc::DATA_DEV:
103  return ::std::errc::device_or_resource_busy;
104  // case SdoErrc::NO_OD:
105 #if !defined(__MINGW32__) || defined(ENODATA)
106  case SdoErrc::NO_VAL:
107  return ::std::errc::no_message_available;
108 #endif
109  default:
110  return ::std::error_condition(ev, *this);
111  }
112 }
113 
114 ::std::string
115 SdoWhat(uint8_t id, uint16_t idx, uint8_t subidx, ::std::error_code ec,
116  const ::std::string& what_arg = "") {
117  ::std::stringstream ss;
118  ss << ::std::uppercase << ::std::setfill('0') << ::std::hex;
119  if (!what_arg.empty()) ss << what_arg << ':';
120  ss << ::std::setw(2) << int(id) << ':';
121  ss << ::std::setw(4) << idx << ':' << ::std::setw(2) << int(subidx) << ": ";
122  ss << ec.message();
123  ss << " (" << ::std::setw(8) << uint32_t(ec.value()) << ')';
124  return ss.str();
125 }
126 
127 } // namespace
128 
129 SdoError::SdoError(uint8_t id, uint16_t idx, uint8_t subidx,
130  ::std::error_code ec)
131  : ::std::system_error(ec, SdoWhat(id, idx, subidx, ec)),
132  id_(id),
133  idx_(idx),
134  subidx_(subidx) {}
135 
136 SdoError::SdoError(uint8_t id, uint16_t idx, uint8_t subidx,
137  ::std::error_code ec, const ::std::string& what_arg)
138  : ::std::system_error(ec, SdoWhat(id, idx, subidx, ec, what_arg)),
139  id_(id),
140  idx_(idx),
141  subidx_(subidx) {}
142 
143 SdoError::SdoError(uint8_t id, uint16_t idx, uint8_t subidx,
144  ::std::error_code ec, const char* what_arg)
145  : ::std::system_error(ec, SdoWhat(id, idx, subidx, ec, what_arg)),
146  id_(id),
147  idx_(idx),
148  subidx_(subidx) {}
149 
150 SdoError::SdoError(uint8_t id, uint16_t idx, uint8_t subidx, int ev)
151  : SdoError(id, idx, subidx, ::std::error_code(ev, SdoCategory())) {}
152 
153 SdoError::SdoError(uint8_t id, uint16_t idx, uint8_t subidx, int ev,
154  const ::std::string& what_arg)
155  : SdoError(id, idx, subidx, ::std::error_code(ev, SdoCategory()),
156  what_arg) {}
157 
158 SdoError::SdoError(uint8_t id, uint16_t idx, uint8_t subidx, int ev,
159  const char* what_arg)
160  : SdoError(id, idx, subidx, ::std::error_code(ev, SdoCategory()),
161  what_arg) {}
162 
163 const ::std::error_category&
164 SdoCategory() noexcept {
165  static const SdoErrcCategory category;
166  return category;
167 }
168 
169 ::std::error_code
171  return {static_cast<int>(e), SdoCategory()};
172 }
173 
174 ::std::error_condition
176  return {static_cast<int>(e), SdoCategory()};
177 }
178 
179 SdoErrc
180 sdo_errc(::std::error_code ec) {
181  if (ec) {
182  if (ec.category() == SdoCategory()) {
183  return static_cast<SdoErrc>(ec.value());
184  } else if (ec.category() == ::std::generic_category()) {
185  switch (static_cast<::std::errc>(ec.value())) {
186  case ::std::errc::timed_out:
187  return SdoErrc::TIMEOUT;
188  case ::std::errc::not_enough_memory:
189  return SdoErrc::NO_MEM;
190  default:
191  return SdoErrc::ERROR;
192  }
193  } else if (ec.category() == ::std::system_category()) {
194  switch (errc2num(ec.value())) {
195  case ERRNUM_TIMEDOUT:
196  return SdoErrc::TIMEOUT;
197  case ERRNUM_NOMEM:
198  return SdoErrc::NO_MEM;
199  default:
200  return SdoErrc::ERROR;
201  }
202  }
203  return SdoErrc::ERROR;
204  }
205  return static_cast<SdoErrc>(0);
206 }
207 
208 ::std::exception_ptr
209 make_sdo_exception_ptr(uint8_t id, uint16_t idx, uint8_t subidx,
210  ::std::error_code ec) noexcept {
211  try {
212  if (ec.category() == SdoCategory())
213  return ::std::make_exception_ptr(SdoError(id, idx, subidx, ec));
214  else
215  return ::std::make_exception_ptr(::std::system_error(ec));
216  } catch (...) {
217  return ::std::current_exception();
218  }
219 }
220 
221 ::std::exception_ptr
222 make_sdo_exception_ptr(uint8_t id, uint16_t idx, uint8_t subidx,
223  ::std::error_code ec,
224  const ::std::string& what_arg) noexcept {
225  try {
226  if (ec.category() == SdoCategory())
227  return ::std::make_exception_ptr(SdoError(id, idx, subidx, ec, what_arg));
228  else
229  return ::std::make_exception_ptr(::std::system_error(ec, what_arg));
230  } catch (...) {
231  return ::std::current_exception();
232  }
233 }
234 
235 ::std::exception_ptr
236 make_sdo_exception_ptr(uint8_t id, uint16_t idx, uint8_t subidx,
237  ::std::error_code ec, const char* what_arg) noexcept {
238  try {
239  if (ec.category() == SdoCategory())
240  return ::std::make_exception_ptr(SdoError(id, idx, subidx, ec, what_arg));
241  else
242  return ::std::make_exception_ptr(::std::system_error(ec, what_arg));
243  } catch (...) {
244  return ::std::current_exception();
245  }
246 }
247 
248 } // namespace canopen
249 
250 } // namespace lely
lely::canopen::SdoErrc::TYPE_LEN_HI
@ TYPE_LEN_HI
Data type does not match, length of service parameter too high.
lely::canopen::SdoErrc::BLK_CRC
@ BLK_CRC
CRC error (block mode only).
lely::canopen::SdoErrc::TOGGLE
@ TOGGLE
Toggle bit not altered.
lely::canopen::SdoErrc::TYPE_LEN
@ TYPE_LEN
Data type does not match, length of service parameter does not match.
lely::canopen::SdoErrc::BLK_SEQ
@ BLK_SEQ
Invalid sequence number (block mode only).
lely::canopen::SdoErrc::TIMEOUT
@ TIMEOUT
SDO protocol timed out.
sdo_error.hpp
lely::canopen::SdoCategory
const ::std::error_category & SdoCategory() noexcept
Returns a reference to the error category object for SDO abort codes.
Definition: sdo_error.cpp:164
lely::canopen::make_error_condition
::std::error_condition make_error_condition(SdoErrc e) noexcept
Creates an error condition corresponding to an SDO abort code.
Definition: sdo_error.cpp:175
co_sdo_ac2str
const char * co_sdo_ac2str(co_unsigned32_t ac)
Returns a string describing an SDO abort code.
Definition: sdo.c:57
ERRNUM_NOMEM
@ ERRNUM_NOMEM
Not enough space.
Definition: errnum.h:169
lely::canopen::SdoErrc::NO_CS
@ NO_CS
Client/server command specifier not valid or unknown.
lely::canopen::SdoErrc::NO_OBJ
@ NO_OBJ
Object does not exist in the object dictionary.
lely::canopen::SdoErrc::COMPAT
@ COMPAT
General internal incompatibility in the device.
sdo.h
lely::canopen::SdoErrc::TYPE_LEN_LO
@ TYPE_LEN_LO
Data type does not match, length of service parameter too low.
lely::canopen::SdoErrc::PARAM_LO
@ PARAM_LO
Value of parameter written too low (download only).
lely::canopen::SdoErrc::NO_READ
@ NO_READ
Attempt to read a write only object.
lely::canopen::SdoErrc::PARAM
@ PARAM
General parameter incompatibility reason.
lely::canopen::SdoErrc::DATA_DEV
@ DATA_DEV
Data cannot be transferred or stored to the application because of the present device state.
lely::canopen::SdoErrc::PARAM_RANGE
@ PARAM_RANGE
Maximum value is less than minimum value (download only).
lely::canopen::SdoErrc::PARAM_HI
@ PARAM_HI
Value of parameter written too high (download only).
lely::canopen::SdoErrc
SdoErrc
The SDO abort codes.
Definition: sdo_error.hpp:42
coapp.hpp
lely::canopen::SdoErrc::BLK_SIZE
@ BLK_SIZE
Invalid block size (block mode only).
lely::canopen::SdoErrc::PARAM_VAL
@ PARAM_VAL
Invalid value for parameter (download only).
lely::canopen::SdoErrc::NO_WRITE
@ NO_WRITE
Attempt to write a read only object.
lely::canopen::SdoError
The type of exception thrown when an SDO abort code is received.
Definition: sdo_error.hpp:121
errc2num
errnum_t errc2num(int errc)
Transforms a native error code to a platform-independent error number.
Definition: errnum.c:310
lely::canopen::SdoErrc::HARDWARE
@ HARDWARE
Access failed due to a hardware error.
lely::canopen::SdoErrc::NO_MEM
@ NO_MEM
Out of memory.
lely::canopen::SdoErrc::NO_ACCESS
@ NO_ACCESS
Unsupported access to an object.
lely::canopen::make_sdo_exception_ptr
::std::exception_ptr make_sdo_exception_ptr(uint8_t id, uint16_t idx, uint8_t subidx, ::std::error_code ec) noexcept
Creates an std::exception_ptr that holds a reference to a lely::canopen::SdoError with the specified ...
Definition: sdo_error.cpp:209
lely::canopen::SdoErrc::NO_SDO
@ NO_SDO
Resource not available: SDO connection.
ERRNUM_TIMEDOUT
@ ERRNUM_TIMEDOUT
Connection timed out.
Definition: errnum.h:226
lely::canopen::sdo_errc
SdoErrc sdo_errc(::std::error_code ec)
Returns the SDO abort code corresponding to an error code.
Definition: sdo_error.cpp:180
lely::canopen::SdoErrc::DATA_CTL
@ DATA_CTL
Data cannot be transferred or stored to the application because of local control.
lely::canopen::make_error_code
::std::error_code make_error_code(SdoErrc e) noexcept
Creates an error code corresponding to an SDO abort code.
Definition: sdo_error.cpp:170
lely::canopen::SdoErrc::NO_VAL
@ NO_VAL
No data available. (NO_DATA is a macro defined in <netdb.h>)
lely::canopen::SdoErrc::ERROR
@ ERROR
General error.
lely::canopen::SdoErrc::DATA
@ DATA
Data cannot be transferred or stored to the application.
lely::canopen::SdoErrc::NO_SUB
@ NO_SUB
Sub-index does not exist.
error.hpp