app_utils.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. /*********************************************************************
  2. * _ _ _
  3. * _ __ | |_ _ | | __ _ | |__ ___
  4. * | '__|| __|(_)| | / _` || '_ \ / __|
  5. * | | | |_ _ | || (_| || |_) |\__ \
  6. * |_| \__|(_)|_| \__,_||_.__/ |___/
  7. *
  8. * www.rt-labs.com
  9. * Copyright 2018 rt-labs AB, Sweden.
  10. *
  11. * This software is dual-licensed under GPLv3 and a commercial
  12. * license. See the file LICENSE.md distributed with this software for
  13. * full license information.
  14. ********************************************************************/
  15. #ifndef APP_UTILS_H
  16. #define APP_UTILS_H
  17. /**
  18. * @file
  19. * @brief Application utilities and helper functions
  20. *
  21. * Functions for getting string representation of
  22. * P-Net events, error codes and more.
  23. *
  24. * API, slot and subslot administration.
  25. *
  26. * Initialization of P-Net configuration from app_gsdml.h.
  27. */
  28. #ifdef __cplusplus
  29. extern "C" {
  30. #endif
  31. #include "osal.h"
  32. #include "pnal.h"
  33. #include <pnet_api.h>
  34. typedef struct app_utils_netif_name
  35. {
  36. char name[PNET_INTERFACE_NAME_MAX_SIZE];
  37. } app_utils_netif_name_t;
  38. typedef struct app_utils_netif_namelist
  39. {
  40. app_utils_netif_name_t netif[PNET_MAX_PHYSICAL_PORTS + 1];
  41. } app_utils_netif_namelist_t;
  42. /* Forward declaration */
  43. typedef struct app_subslot app_subslot_t;
  44. /**
  45. * Callback for updated cyclic data
  46. *
  47. * @param subslot InOut: Subslot structure
  48. * @param tag InOut: Typically a handle to a submodule
  49. */
  50. typedef void (*app_utils_cyclic_callback) (app_subslot_t * subslot, void * tag);
  51. /**
  52. * Information of submodule plugged into a subslot.
  53. *
  54. * Note that submodule data is not stored here but must
  55. * be handled by the submodule implementation.
  56. *
  57. * All parameters are initialized by the app_utils_plug_submodule()
  58. * function.
  59. *
  60. * The cyclic_callback is used when app_utils_cyclic_data_poll()
  61. * is called. Typically on the tick event in the main task.
  62. * The \a tag parameter is passed with the cyclic_callback and
  63. * is typically a handle to a submodule on application.
  64. */
  65. typedef struct app_subslot
  66. {
  67. /** True when the position in the subslot array is occupied */
  68. bool used;
  69. /** True when the subslot is plugged */
  70. bool plugged;
  71. uint16_t slot_nbr;
  72. uint16_t subslot_nbr;
  73. uint32_t submodule_id;
  74. const char * submodule_name;
  75. pnet_data_cfg_t data_cfg;
  76. /** Status indicator from PLC */
  77. uint8_t indata_iocs;
  78. /** Status indicator from PLC */
  79. uint8_t outdata_iops;
  80. /** Callback for cyclic input- or output data, or NULL if not implemented */
  81. app_utils_cyclic_callback cyclic_callback;
  82. void * tag;
  83. } app_subslot_t;
  84. /**
  85. * Information of module plugged into a slot,
  86. * and array of subslots for admin of submodules.
  87. */
  88. typedef struct app_slot
  89. {
  90. bool plugged;
  91. uint32_t module_id;
  92. const char * name; /** Module name */
  93. /** Subslots. Use a separate index, as the subslot number might be large.
  94. * For example the subslot for DAP port 1 has number 0x8001 */
  95. app_subslot_t subslots[PNET_MAX_SUBSLOTS];
  96. } app_slot_t;
  97. /**
  98. * Information relating to an application relation.
  99. */
  100. typedef struct app_ar
  101. {
  102. uint32_t arep;
  103. uint32_t events;
  104. } app_ar_t;
  105. /**
  106. * AR list iterator state.
  107. */
  108. typedef struct app_ar_iterator
  109. {
  110. app_ar_t *ar;
  111. int16_t index;
  112. bool modified;
  113. } app_ar_iterator_t;
  114. /**
  115. * Profinet API state for application
  116. *
  117. * Used to manage plugged modules into slots (and submodules into subslots).
  118. */
  119. typedef struct app_api_t
  120. {
  121. uint32_t api_id;
  122. /**
  123. * Active AR:s.
  124. * A list which is terminated by an entry with arep == UINT32_MAX.
  125. */
  126. app_ar_t ar[PNET_MAX_AR];
  127. /** Slots. Use slot number as index */
  128. app_slot_t slots[PNET_MAX_SLOTS];
  129. } app_api_t;
  130. /**
  131. * Add an arep to the AR list of an API.
  132. * @param api InOut: The \a app_api_t instance.
  133. * @param arep In: The arep to add.
  134. * @param ar Out: The AR entry, if successful.
  135. *
  136. * @return 0 if the arep could not be added.
  137. * 1 if the arep was added.
  138. */
  139. int app_ar_add_arep (app_api_t * api, uint32_t arep, app_ar_t ** ar);
  140. /**
  141. * Get the arep of an AR.
  142. * @param ar In: The AR.
  143. * @return the arep of the AR.
  144. */
  145. uint32_t app_ar_arep (app_ar_t * ar);
  146. /**
  147. * Clear an event from the events value of the AR.
  148. * @param ar InOut: The AR to modify.
  149. * @param event In: The event(s) (bitmask) that should be cleared.
  150. * @return 0 if none of the set bits in \a event were set for the AR.
  151. * 1 if at least one of the set bits in \a event were set for the AR.
  152. */
  153. int app_ar_event_clr (app_ar_t * ar, uint32_t event);
  154. /**
  155. * Set an event from the events value of the AR.
  156. * @param ar InOut: The AR to modify.
  157. * @param event In: The event(s) (bitmask) that should be set.
  158. */
  159. void app_ar_event_set (app_ar_t * ar, uint32_t event);
  160. /**
  161. * Initialize a list iterator for the AR list of an API.
  162. * @param iterator InOut: The iterator to be initialized.
  163. * @param api In: The \a app_api_t instance.
  164. */
  165. void app_ar_iterator_init (
  166. app_ar_iterator_t * iterator,
  167. app_api_t * api);
  168. /**
  169. * Get the next AR from a list iterator.
  170. * @param iterator InOut: The iterator to use.
  171. * @param ar Out: If the return value is 1, the next AR from
  172. * the list.
  173. * @return 0 if there were no more items in the list.
  174. * 1 if there was another item in the list.
  175. */
  176. int app_ar_iterator_next (app_ar_iterator_t * iterator, app_ar_t ** ar);
  177. /**
  178. * Check whether the iterator has run to the end of entries.
  179. * @param iterator InOut: The iterator.
  180. * @return 0 if the iterator is finished.
  181. * 1 if the iterator is finished.
  182. */
  183. int app_ar_iterator_done (app_ar_iterator_t * iterator);
  184. /**
  185. * Delete the current AR entry of the list iterator.
  186. * @param ar InOut: The AR.
  187. */
  188. void app_ar_iterator_delete_current (app_ar_iterator_t * iterator);
  189. /**
  190. * Convert IP address to string
  191. * @param ip In: IP address
  192. * @param outputstring Out: Resulting string buffer. Should have size
  193. * PNAL_INET_ADDRSTR_SIZE.
  194. */
  195. void app_utils_ip_to_string (pnal_ipaddr_t ip, char * outputstring);
  196. /**
  197. * Get string description of data direction
  198. * @param direction In: Submodule data direction
  199. * @return String representation of data direction
  200. */
  201. const char * app_utils_submod_dir_to_string (pnet_submodule_dir_t direction);
  202. /**
  203. * Get string description of PNIO producer or consumer status
  204. * @param ioxs In: Producer or consumer status (IOPS/IOCS)
  205. * @return String representation of ioxs (IOPS/IOCS)
  206. */
  207. const char * app_utils_ioxs_to_string (pnet_ioxs_values_t ioxs);
  208. /**
  209. * Convert MAC address to string
  210. * @param mac In: MAC address
  211. * @param outputstring Out: Resulting string buffer. Should have size
  212. * PNAL_ETH_ADDRSTR_SIZE.
  213. */
  214. void app_utils_mac_to_string (pnet_ethaddr_t mac, char * outputstring);
  215. /**
  216. * Convert error code to string format
  217. * Only common error codes supported.
  218. * Todo: Add rest of error codes.
  219. *
  220. * @param err_cls In: The error class. See PNET_ERROR_CODE_1_*
  221. * @param err_code In: The error code. See PNET_ERROR_CODE_2_*
  222. * @param err_cls_str Out: The error class string
  223. * @param err_code_str Out: The error code string
  224. */
  225. void app_utils_get_error_code_strings (
  226. uint16_t err_cls,
  227. uint16_t err_code,
  228. const char ** err_cls_str,
  229. const char ** err_code_str);
  230. /**
  231. * Copy an IP address (as an integer) to a struct
  232. * @param destination_struct Out: Destination
  233. * @param ip In: IP address
  234. */
  235. void app_utils_copy_ip_to_struct (
  236. pnet_cfg_ip_addr_t * destination_struct,
  237. pnal_ipaddr_t ip);
  238. /**
  239. * Return a string representation of
  240. * the given dcontrol command.
  241. * @param event In: control_command
  242. * @return A string representing the command
  243. */
  244. const char * app_utils_dcontrol_cmd_to_string (
  245. pnet_control_command_t control_command);
  246. /**
  247. * Return a string representation of the given event.
  248. * @param event In: event
  249. * @return A string representing the event
  250. */
  251. const char * app_utils_event_to_string (pnet_event_values_t event);
  252. /**
  253. * Update network configuration from a string
  254. * defining a list of network interfaces examples:
  255. * "eth0" or "br0,eth0,eth1"
  256. *
  257. * Read IP, netmask etc from operating system.
  258. *
  259. * @param netif_list_str In: Comma separated string of network ifs
  260. * @param if_list Out: Array of network ifs
  261. * @param number_of_ports Out: Number of ports
  262. * @param if_cfg Out: P-Net network configuration to be updated
  263. * @return 0 on success, -1 on error
  264. */
  265. int app_utils_pnet_cfg_init_netifs (
  266. const char * netif_list_str,
  267. app_utils_netif_namelist_t * if_list,
  268. uint16_t * number_of_ports,
  269. pnet_if_cfg_t * if_cfg);
  270. /**
  271. * Parse a comma separated list of network interfaces and check
  272. * that the number of interfaces match the PNET_MAX_PHYSICAL_PORTS
  273. * configuration.
  274. *
  275. * For a single Ethernet interface, the \a arg_str should consist of
  276. * one name. For two Ethernet interfaces, the \a arg_str should consist of
  277. * three names, as we also need a bridge interface.
  278. *
  279. * Does only consider the number of comma separated names. No check of the
  280. * names themselves are done.
  281. *
  282. * Examples:
  283. * arg_str num_ports
  284. * "eth0" 1
  285. * "eth0,eth1" error (We need a bridge as well)
  286. * "br0,eth0,eth1" 2
  287. *
  288. * @param arg_str In: Network interface list as comma separated,
  289. * terminated string. For example "eth0" or
  290. * "br0,eth0,eth1".
  291. * @param max_port In: PNET_MAX_PHYSICAL_PORTS, passed as argument to
  292. * allow test.
  293. * @param p_if_list Out: List of network interfaces
  294. * @param p_num_ports Out: Resulting number of physical ports
  295. * @return 0 on success
  296. * -1 on error
  297. */
  298. int app_utils_get_netif_namelist (
  299. const char * arg_str,
  300. uint16_t max_port,
  301. app_utils_netif_namelist_t * p_if_list,
  302. uint16_t * p_num_ports);
  303. /**
  304. * Print network configuration using APP_LOG_INFO().
  305. *
  306. * @param if_cfg In: Network configuration
  307. * @param number_of_ports In: Number of used ports
  308. */
  309. void app_utils_print_network_config (
  310. pnet_if_cfg_t * if_cfg,
  311. uint16_t number_of_ports);
  312. /**
  313. * Print message if IOXS has changed.
  314. *
  315. * Uses APP_LOG_INFO()
  316. *
  317. * @param subslot In: Subslot
  318. * @param ioxs_str In: String description Producer or Consumer
  319. * @param ioxs_current In: Current status
  320. * @param ioxs_new In: New status
  321. */
  322. void app_utils_print_ioxs_change (
  323. const app_subslot_t * subslot,
  324. const char * ioxs_str,
  325. uint8_t ioxs_current,
  326. uint8_t ioxs_new);
  327. /**
  328. * Init the p-net configuration to default values.
  329. *
  330. * Most values are picked from app_gsdml.h
  331. *
  332. * Network configuration not initialized.
  333. * This means that \a '.if_cfg' must be set by application.
  334. *
  335. * Use this function to init P-Net configuration before
  336. * before passing config to app_init().
  337. *
  338. * @param pnet_cfg Out: Configuration for use by p-net
  339. * @return 0 if the operation succeeded.
  340. * -1 if an error occurred.
  341. */
  342. int app_utils_pnet_cfg_init_default (pnet_cfg_t * pnet_cfg);
  343. /**
  344. * Plug application module
  345. *
  346. * This is for the application to remember which slots are
  347. * populated in the p-net stack.
  348. *
  349. * @param p_api InOut: API
  350. * @param slot_nbr In: Slot number
  351. * @param id In: Module identity
  352. * @param name In: Module name
  353. * @return 0 on success, -1 on error
  354. */
  355. int app_utils_plug_module (
  356. app_api_t * p_api,
  357. uint16_t slot_nbr,
  358. uint32_t id,
  359. const char * name);
  360. /**
  361. * Pull any application module in given slot.
  362. *
  363. * This is for the application to remember which slots are
  364. * populated in the p-net stack.
  365. *
  366. * @param p_api InOut: API
  367. * @param slot_nbr In: Slot number
  368. * @return 0 on success, -1 on error
  369. */
  370. int app_utils_pull_module (app_api_t * p_api, uint16_t slot_nbr);
  371. /**
  372. * Plug application submodule.
  373. *
  374. * This is for the application to remember which subslots are
  375. * populated in the p-net stack.
  376. *
  377. * @param p_api InOut: API
  378. * @param slot_nbr In: Slot number
  379. * @param subslot_nbr In: Subslot number
  380. * @param submodule_id In: Submodule identity
  381. * @param p_data_cfg In: Data configuration,
  382. * direction, in and out sizes
  383. * @param submodule_name In: Submodule name
  384. * @param cyclic_callback In: Submodule data callback
  385. * @param tag In: Tag passed in cyclic callback
  386. * Typically application or
  387. * submodule handle
  388. * @return Reference to allocated subslot,
  389. * NULL if no free subslot is available. This should
  390. * never happen if application is aligned with p-net state.
  391. */
  392. app_subslot_t * app_utils_plug_submodule (
  393. app_api_t * p_api,
  394. uint16_t slot_nbr,
  395. uint16_t subslot_nbr,
  396. uint32_t submodule_id,
  397. const pnet_data_cfg_t * p_data_cfg,
  398. const char * submodule_name,
  399. app_utils_cyclic_callback cyclic_callback,
  400. void * tag);
  401. /**
  402. * Unplug any application submodule from given subslot.
  403. *
  404. * This is for the application to remember which subslots are
  405. * populated in the p-net stack.
  406. *
  407. * @param p_api InOut: API
  408. * @param slot_nbr In: Slot number
  409. * @param subslot_nbr In: Subslot number
  410. * @return 0 on success, -1 on error.
  411. */
  412. int app_utils_pull_submodule (
  413. app_api_t * p_api,
  414. uint16_t slot_nbr,
  415. uint16_t subslot_nbr);
  416. /**
  417. * Trigger data callback for all plugged submodules in all slots.
  418. *
  419. * The callbacks given in \a app_utils_plug_submodule() are used.
  420. *
  421. * @param p_api In: API
  422. */
  423. void app_utils_cyclic_data_poll (app_api_t * p_api);
  424. /**
  425. * Get subslot application information.
  426. *
  427. * @param p_appdata InOut: Application state.
  428. * @param slot_nbr In: Slot number.
  429. * @param subslot_nbr In: Subslot number. Range 0 - 0x9FFF.
  430. * @return Reference to application subslot,
  431. * NULL if subslot is not found/plugged.
  432. */
  433. app_subslot_t * app_utils_subslot_get (
  434. app_api_t * p_api,
  435. uint16_t slot_nbr,
  436. uint16_t subslot_nbr);
  437. /**
  438. * Return true if subslot is input.
  439. *
  440. * @param p_subslot In: Reference to subslot.
  441. * @return true if subslot is input or input/output.
  442. * false if not.
  443. */
  444. bool app_utils_subslot_is_input (const app_subslot_t * p_subslot);
  445. /**
  446. * Return true if subslot is neither input or output.
  447. *
  448. * This is applies for DAP submodules/slots
  449. *
  450. * @param p_subslot In: Reference to subslot.
  451. * @return true if subslot is input or input/output.
  452. * false if not.
  453. */
  454. bool app_utils_subslot_is_no_io (const app_subslot_t * p_subslot);
  455. /**
  456. * Return true if subslot is output.
  457. *
  458. * @param p_subslot In: Reference to subslot.
  459. * @return true if subslot is output or input/output,
  460. * false if not.
  461. */
  462. bool app_utils_subslot_is_output (const app_subslot_t * p_subslot);
  463. #ifdef __cplusplus
  464. }
  465. #endif
  466. #endif /* APP_UTILS_H */