mirror of https://gerrit.osmocom.org/libosmocore
112 lines
3.4 KiB
C
112 lines
3.4 KiB
C
/*! \file sercomm.h
|
|
* Osmocom Sercomm HDLC (de)multiplex.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <osmocom/core/msgb.h>
|
|
|
|
/*! \defgroup sercomm Seriall Communications (HDLC)
|
|
* @{
|
|
* \file sercomm.h */
|
|
|
|
/*! A low sercomm_dlci means high priority. A high DLCI means low priority */
|
|
enum sercomm_dlci {
|
|
SC_DLCI_HIGHEST = 0,
|
|
SC_DLCI_DEBUG = 4,
|
|
SC_DLCI_L1A_L23 = 5,
|
|
SC_DLCI_LOADER = 9,
|
|
SC_DLCI_CONSOLE = 10,
|
|
SC_DLCI_ECHO = 128,
|
|
_SC_DLCI_MAX
|
|
};
|
|
|
|
struct osmo_sercomm_inst;
|
|
/*! call-back function for per-DLC receive handler
|
|
* \param[in] sercomm instance on which msg was received
|
|
* \param[in] dlci DLC Identifier of received msg
|
|
* \param[in] msg received message that needs to be processed */
|
|
typedef void (*dlci_cb_t)(struct osmo_sercomm_inst *sercomm, uint8_t dlci, struct msgb *msg);
|
|
|
|
/*! one instance of a sercomm multiplex/demultiplex */
|
|
struct osmo_sercomm_inst {
|
|
/*! Has this instance been initialized? */
|
|
int initialized;
|
|
/*! UART Identifier */
|
|
int uart_id;
|
|
|
|
/*! transmit side */
|
|
struct {
|
|
/*! per-DLC queue of pending transmit msgbs */
|
|
struct llist_head dlci_queues[_SC_DLCI_MAX];
|
|
/*! msgb currently being transmitted */
|
|
struct msgb *msg;
|
|
/*! transmit state */
|
|
int state;
|
|
/*! next to-be-transmitted char in msg */
|
|
uint8_t *next_char;
|
|
} tx;
|
|
|
|
/*! receive side */
|
|
struct {
|
|
/*! per-DLC handler call-back functions */
|
|
dlci_cb_t dlci_handler[_SC_DLCI_MAX];
|
|
/*! msgb allocation size for rx msgs */
|
|
unsigned int msg_size;
|
|
/*! currently received msgb */
|
|
struct msgb *msg;
|
|
/*! receive state */
|
|
int state;
|
|
/*! DLCI of currently received msgb */
|
|
uint8_t dlci;
|
|
/*! CTRL of currently received msgb */
|
|
uint8_t ctrl;
|
|
} rx;
|
|
};
|
|
|
|
|
|
void osmo_sercomm_init(struct osmo_sercomm_inst *sercomm);
|
|
int osmo_sercomm_initialized(struct osmo_sercomm_inst *sercomm);
|
|
|
|
/* User Interface: Tx */
|
|
void osmo_sercomm_sendmsg(struct osmo_sercomm_inst *sercomm, uint8_t dlci, struct msgb *msg);
|
|
unsigned int osmo_sercomm_tx_queue_depth(struct osmo_sercomm_inst *sercomm, uint8_t dlci);
|
|
|
|
/* User Interface: Rx */
|
|
int osmo_sercomm_register_rx_cb(struct osmo_sercomm_inst *sercomm, uint8_t dlci, dlci_cb_t cb);
|
|
|
|
int osmo_sercomm_change_speed(struct osmo_sercomm_inst *sercomm, uint32_t bdrt);
|
|
|
|
/* Driver Interface */
|
|
|
|
int osmo_sercomm_drv_pull(struct osmo_sercomm_inst *sercomm, uint8_t *ch);
|
|
int osmo_sercomm_drv_rx_char(struct osmo_sercomm_inst *sercomm, uint8_t ch);
|
|
|
|
extern void sercomm_drv_lock(unsigned long *flags);
|
|
extern void sercomm_drv_unlock(unsigned long *flags);
|
|
|
|
/*! low-level driver routine to request start of transmission
|
|
* The Sercomm code calls this function to inform the low-level driver
|
|
* that some data is pending for transmission, and the low-level driver
|
|
* should (if not active already) start enabling tx_empty interrupts
|
|
* and pull drivers out of sercomm using osmo_sercomm_drv_pull() until
|
|
* the latter returns 0.
|
|
* \param[in] sercomm Osmocom sercomm instance for which to change
|
|
*/
|
|
extern void sercomm_drv_start_tx(struct osmo_sercomm_inst *sercomm);
|
|
|
|
/*! low-level driver routine to execute baud-rate change
|
|
* \param[in] sercomm Osmocom sercomm instance for which to change
|
|
* \param[in] bdrt New Baud-Rate (integer)
|
|
* \returns 0 on success; negative in case of error
|
|
*/
|
|
extern int sercomm_drv_baudrate_chg(struct osmo_sercomm_inst *sercomm, uint32_t bdrt);
|
|
|
|
/*! Sercomm msgb allocator function */
|
|
static inline struct msgb *osmo_sercomm_alloc_msgb(unsigned int len)
|
|
{
|
|
return msgb_alloc_headroom(len+4, 4, "sercomm_tx");
|
|
}
|
|
|
|
/*! @} */
|