/* Cubesat Space Protocol - A small network-layer protocol designed for Cubesats Copyright (C) 2012 Gomspace ApS (http://www.gomspace.com) Copyright (C) 2012 AAUSAT3 Project (http://aausat3.space.aau.dk) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _CSP_H_ #define _CSP_H_ #ifdef __cplusplus extern "C" { #endif /* Includes */ #include #include /* CSP includes */ #include "csp_types.h" #include "csp_platform.h" #include "csp_error.h" #include "csp_debug.h" #include "csp_buffer.h" #include "csp_rtable.h" #include "csp_iflist.h" /** csp_init * Start up the can-space protocol * @param my_node_address The CSP node address */ int csp_init(uint8_t my_node_address); /** csp_set_address * Set the systems own address * @param addr The new address of the system */ void csp_set_address(uint8_t addr); /** csp_get_address * Get the systems own address * @return The current address of the system */ uint8_t csp_get_address(void); /** csp_set_hostname * Set subsystem hostname. * This function takes a pointer to a string, which should remain static * @param hostname Hostname to set */ void csp_set_hostname(const char *hostname); /** csp_get_hostname * Get current subsystem hostname. * @return Pointer to char array with current hostname. */ const char *csp_get_hostname(void); /** csp_set_model * Set subsystem model name. * This function takes a pointer to a string, which should remain static * @param model Model name to set */ void csp_set_model(const char *model); /** csp_get_model * Get current model name. * @return Pointer to char array with current model name. */ const char *csp_get_model(void); /** csp_set_revision * Set subsystem revision. This can be used to override the CMP revision field. * This function takes a pointer to a string, which should remain static * @param revision Revision name to set */ void csp_set_revision(const char *revision); /** csp_get_revision * Get subsystem revision. * @return Pointer to char array with software revision. */ const char *csp_get_revision(void); /** csp_socket * Create CSP socket endpoint * @param opts Socket options * @return Pointer to socket on success, NULL on failure */ csp_socket_t *csp_socket(uint32_t opts); /** * Wait for a new connection on a socket created by csp_socket * @param socket Socket to accept connections on * @param timeout use CSP_MAX_DELAY for infinite timeout * @return Return pointer to csp_conn_t or NULL if timeout was reached */ csp_conn_t *csp_accept(csp_socket_t *socket, uint32_t timeout); /** * Read data from a connection * This fuction uses the RX queue of a connection to receive a packet * If no packet is available and a timeout has been specified * The call will block. * Do NOT call this from ISR * @param conn pointer to connection * @param timeout timeout in ms, use CSP_MAX_DELAY for infinite blocking time * @return Returns pointer to csp_packet_t, which you MUST free yourself, either by calling csp_buffer_free() or reusing the buffer for a new csp_send. */ csp_packet_t *csp_read(csp_conn_t *conn, uint32_t timeout); /** * Send a packet on an already established connection * @param conn pointer to connection * @param packet pointer to packet, * @param timeout a timeout to wait for TX to complete. NOTE: not all underlying drivers supports flow-control. * @return returns 1 if successful and 0 otherwise. you MUST free the frame yourself if the transmission was not successful. */ int csp_send(csp_conn_t *conn, csp_packet_t *packet, uint32_t timeout); /** * Send a packet on an already established connection, and change the default priority of the connection * * @note When using this function, the priority of the connection will change. If you need to change it back * use another call to csp_send_prio, or ensure that all packets sent on a given connection is using send_prio call. * * @param prio csp priority * @param conn pointer to connection * @param packet pointer to packet, * @param timeout a timeout to wait for TX to complete. NOTE: not all underlying drivers supports flow-control. * @return returns 1 if successful and 0 otherwise. you MUST free the frame yourself if the transmission was not successful. */ int csp_send_prio(uint8_t prio, csp_conn_t *conn, csp_packet_t *packet, uint32_t timeout); /** * Perform an entire request/reply transaction * Copies both input buffer and reply to output buffeer. * Also makes the connection and closes it again * @param prio CSP Prio * @param dest CSP Dest * @param port CSP Port * @param timeout timeout in ms * @param outbuf pointer to outgoing data buffer * @param outlen length of request to send * @param inbuf pointer to incoming data buffer * @param inlen length of expected reply, -1 for unknown size (note inbuf MUST be large enough) * @return Return 1 or reply size if successful, 0 if error or incoming length does not match or -1 if timeout was reached */ int csp_transaction(uint8_t prio, uint8_t dest, uint8_t port, uint32_t timeout, void *outbuf, int outlen, void *inbuf, int inlen); /** * Perform an entire request/reply transaction * Copies both input buffer and reply to output buffeer. * Also makes the connection and closes it again * @param prio CSP Prio * @param dest CSP Dest * @param port CSP Port * @param timeout timeout in ms * @param outbuf pointer to outgoing data buffer * @param outlen length of request to send * @param inbuf pointer to incoming data buffer * @param inlen length of expected reply, -1 for unknown size (note inbuf MUST be large enough) * @param opts Connection options. * @return Return 1 or reply size if successful, 0 if error or incoming length does not match or -1 if timeout was reached */ int csp_transaction2(uint8_t prio, uint8_t dest, uint8_t port, uint32_t timeout, void *outbuf, int outlen, void *inbuf, int inlen, uint32_t opts); /** * Use an existing connection to perform a transaction, * This is only possible if the next packet is on the same port and destination! * @param conn pointer to connection structure * @param timeout timeout in ms * @param outbuf pointer to outgoing data buffer * @param outlen length of request to send * @param inbuf pointer to incoming data buffer * @param inlen length of expected reply, -1 for unknown size (note inbuf MUST be large enough) * @return */ int csp_transaction_persistent(csp_conn_t *conn, uint32_t timeout, void *outbuf, int outlen, void *inbuf, int inlen); /** * Read data from a connection-less server socket * This fuction uses the socket directly to receive a frame * If no packet is available and a timeout has been specified the call will block. * Do NOT call this from ISR * @return Returns pointer to csp_packet_t, which you MUST free yourself, either by calling csp_buffer_free() or reusing the buffer for a new csp_send. */ csp_packet_t *csp_recvfrom(csp_socket_t *socket, uint32_t timeout); /** * Send a packet without previously opening a connection * @param prio CSP_PRIO_x * @param dest destination node * @param dport destination port * @param src_port source port * @param opts CSP_O_x * @param packet pointer to packet * @param timeout timeout used by interfaces with blocking send * @return -1 if error (you must free packet), 0 if OK (you must discard pointer) */ int csp_sendto(uint8_t prio, uint8_t dest, uint8_t dport, uint8_t src_port, uint32_t opts, csp_packet_t *packet, uint32_t timeout); /** * Send a packet as a direct reply to the source of an incoming packet, * but still without holding an entire connection * @param request_packet pointer to packet to reply to * @param reply_packet actual reply data * @param opts CSP_O_x * @param timeout timeout used by interfaces with blocking send * @return -1 if error (you must free packet), 0 if OK (you must discard pointer) */ int csp_sendto_reply(csp_packet_t * request_packet, csp_packet_t * reply_packet, uint32_t opts, uint32_t timeout); /** csp_connect * Used to establish outgoing connections * This function searches the port table for free slots and finds an unused * connection from the connection pool * There is no handshake in the CSP protocol * @param prio Connection priority. * @param dest Destination address. * @param dport Destination port. * @param timeout Timeout in ms. * @param opts Connection options. * @return a pointer to a new connection or NULL */ csp_conn_t *csp_connect(uint8_t prio, uint8_t dest, uint8_t dport, uint32_t timeout, uint32_t opts); /** csp_close * Closes a given connection and frees buffers used. * @param conn pointer to connection structure * @return CSP_ERR_NONE if connection was closed. Otherwise, an err code is returned. */ int csp_close(csp_conn_t *conn); /** * @param conn pointer to connection structure * @return destination port of an incoming connection */ int csp_conn_dport(csp_conn_t *conn); /** * @param conn pointer to connection structure * @return source port of an incoming connection */ int csp_conn_sport(csp_conn_t *conn); /** * @param conn pointer to connection structure * @return destination address of an incoming connection */ int csp_conn_dst(csp_conn_t *conn); /** * @param conn pointer to connection structure * @return source address of an incoming connection */ int csp_conn_src(csp_conn_t *conn); /** * @param conn pointer to connection structure * @return flags field of an incoming connection */ int csp_conn_flags(csp_conn_t *conn); /** * Set socket to listen for incoming connections * @param socket Socket to enable listening on * @param conn_queue_length Lenght of backlog connection queue * @return 0 on success, -1 on error. */ int csp_listen(csp_socket_t *socket, size_t conn_queue_length); /** * Bind port to socket * @param socket Socket to bind port to * @param port Port number to bind * @return 0 on success, -1 on error. */ int csp_bind(csp_socket_t *socket, uint8_t port); /** * Start the router task. * @param task_stack_size The number of portStackType to allocate. This only affects FreeRTOS systems. * @param priority The OS task priority of the router */ int csp_route_start_task(unsigned int task_stack_size, unsigned int priority); /** * Call the router worker function manually (without the router task) * This must be run inside a loop or called periodically for the csp router to work. * Use this function instead of calling and starting the router task. * @param timeout max blocking time * @return -1 if no packet was processed, 0 otherwise */ int csp_route_work(uint32_t timeout); /** * Start the bridge task. * @param task_stack_size The number of portStackType to allocate. This only affects FreeRTOS systems. * @param priority The OS task priority of the router * @param _if_a pointer to first side * @param _if_b pointer to second side * @return CSP_ERR type */ int csp_bridge_start(unsigned int task_stack_size, unsigned int task_priority, csp_iface_t * _if_a, csp_iface_t * _if_b); /** * Enable promiscuous mode packet queue * This function is used to enable promiscuous mode for the router. * If enabled, a copy of all incoming packets are placed in a queue * that can be read with csp_promisc_get(). Not all interface drivers * support promiscuous mode. * * @param buf_size Size of buffer for incoming packets */ int csp_promisc_enable(unsigned int buf_size); /** * Disable promiscuous mode. * If the queue was initialised prior to this, it can be re-enabled * by calling promisc_enable(0) */ void csp_promisc_disable(void); /** * Get packet from promiscuous mode packet queue * Returns the first packet from the promiscuous mode packet queue. * The queue is FIFO, so the returned packet is the oldest one * in the queue. * * @param timeout Timeout in ms to wait for a new packet */ csp_packet_t *csp_promisc_read(uint32_t timeout); /** * Send multiple packets using the simple fragmentation protocol * CSP will add total size and offset to all packets * This can be read by the client using the csp_sfp_recv, if the CSP_FFRAG flag is set * @param conn pointer to connection * @param data pointer to data to send * @param totalsize size of data to send * @param mtu maximum transfer unit * @param timeout timeout in ms to wait for csp_send() * @return 0 if OK, -1 if ERR */ int csp_sfp_send(csp_conn_t * conn, const void * data, int totalsize, int mtu, uint32_t timeout); /** * Same as csp_sfp_send but with option to supply your own memcpy function. * This is usefull if you wish to send data stored in flash memory or another location * @param conn pointer to connection * @param data pointer to data to send * @param totalsize size of data to send * @param mtu maximum transfer unit * @param timeout timeout in ms to wait for csp_send() * @param memcpyfcn, pointer to memcpy function * @return 0 if OK, -1 if ERR */ int csp_sfp_send_own_memcpy(csp_conn_t * conn, const void * data, int totalsize, int mtu, uint32_t timeout, void * (*memcpyfcn)(void *, const void *, size_t)); /** * This is the counterpart to the csp_sfp_send function * @param conn pointer to active conn, on which you expect to receive sfp packed data * @param dataout pointer to NULL pointer, whill be overwritten with malloc pointer * @param datasize actual size of received data * @param timeout timeout in ms to wait for csp_recv() * @return 0 if OK, -1 if ERR */ int csp_sfp_recv(csp_conn_t * conn, void ** dataout, int * datasize, uint32_t timeout); /** * This is the counterpart to the csp_sfp_send function * @param conn pointer to active conn, on which you expect to receive sfp packed data * @param dataout pointer to NULL pointer, whill be overwritten with malloc pointer * @param datasize actual size of received data * @param timeout timeout in ms to wait for csp_recv() * @param first_packet This is a pointer to the first SFP packet (previously received with csp_read) * @return 0 if OK, -1 if ERR */ int csp_sfp_recv_fp(csp_conn_t * conn, void ** dataout, int * datasize, uint32_t timeout, csp_packet_t * first_packet); /** * If the given packet is a service-request (that is uses one of the csp service ports) * it will be handled according to the CSP service handler. * This function will either use the packet buffer or delete it, * so this function is typically called in the last "default" clause of * a switch/case statement in a csp_listener task. * In order to listen to csp service ports, bind your listener to the CSP_ANY port. * This function may only be called from task context. * @param conn Pointer to the new connection * @param packet Pointer to the first packet, obtained by using csp_read() */ void csp_service_handler(csp_conn_t *conn, csp_packet_t *packet); /** * Send a single ping/echo packet * @param node node id * @param timeout timeout in ms * @param size size of packet to transmit * @param conn_options csp connection options * @return >0 = Echo time in ms, -1 = ERR */ int csp_ping(uint8_t node, uint32_t timeout, unsigned int size, uint8_t conn_options); /** * Send a single ping/echo packet without waiting for reply * @param node node id */ void csp_ping_noreply(uint8_t node); /** * Request process list. * @note This is only available for FreeRTOS systems * @param node node id * @param timeout timeout in ms */ void csp_ps(uint8_t node, uint32_t timeout); /** * Request amount of free memory * @param node node id * @param timeout timeout in ms */ void csp_memfree(uint8_t node, uint32_t timeout); /** * Request number of free buffer elements * @param node node id * @param timeout timeout in ms */ void csp_buf_free(uint8_t node, uint32_t timeout); /** * Reboot subsystem * @param node node id */ void csp_reboot(uint8_t node); /** * Shutdown subsystem * @param node node id */ void csp_shutdown(uint8_t node); /** * Request subsystem uptime * @param node node id * @param timeout timeout in ms */ void csp_uptime(uint8_t node, uint32_t timeout); /** * Set RDP options * @param window_size Window size * @param conn_timeout_ms Connection timeout in ms * @param packet_timeout_ms Packet timeout in ms * @param delayed_acks Enable/disable delayed acknowledgements * @param ack_timeout Acknowledgement timeout when delayed ACKs is enabled * @param ack_delay_count Send acknowledgement for every ack_delay_count packets */ void csp_rdp_set_opt(unsigned int window_size, unsigned int conn_timeout_ms, unsigned int packet_timeout_ms, unsigned int delayed_acks, unsigned int ack_timeout, unsigned int ack_delay_count); /** * Get RDP options * @param window_size Window size * @param conn_timeout_ms Connection timeout in ms * @param packet_timeout_ms Packet timeout in ms * @param delayed_acks Enable/disable delayed acknowledgements * @param ack_timeout Acknowledgement timeout when delayed ACKs is enabled * @param ack_delay_count Send acknowledgement for every ack_delay_count packets */ void csp_rdp_get_opt(unsigned int *window_size, unsigned int *conn_timeout_ms, unsigned int *packet_timeout_ms, unsigned int *delayed_acks, unsigned int *ack_timeout, unsigned int *ack_delay_count); /** * Set XTEA key * @param key Pointer to key array * @param keylen Length of key * @return 0 if key was successfully set, -1 otherwise */ int csp_xtea_set_key(char *key, uint32_t keylen); /** * Set HMAC key * @param key Pointer to key array * @param keylen Length of key * @return 0 if key was successfully set, -1 otherwise */ int csp_hmac_set_key(char *key, uint32_t keylen); /** * Print connection table */ void csp_conn_print_table(void); int csp_conn_print_table_str(char * str_buf, int str_size); /** * Print buffer usage table */ void csp_buffer_print_table(void); /** * Hex dump to stdout */ void csp_hex_dump(const char *desc, void *addr, int len); #ifdef __AVR__ typedef uint32_t csp_memptr_t; #else typedef void * csp_memptr_t; #endif typedef csp_memptr_t (*csp_memcpy_fnc_t)(csp_memptr_t, const csp_memptr_t, size_t); void csp_cmp_set_memcpy(csp_memcpy_fnc_t fnc); /** * Set csp_debug hook function * @param f Hook function */ #include typedef void (*csp_debug_hook_func_t)(csp_debug_level_t level, const char *format, va_list args); void csp_debug_hook_set(csp_debug_hook_func_t f); #ifdef __cplusplus } /* extern "C" */ #endif #endif // _CSP_H_