2017-04-30 19:21:52 +00:00
|
|
|
#ifndef _SERCOMM_H
|
|
|
|
#define _SERCOMM_H
|
|
|
|
|
|
|
|
#include <osmocom/core/msgb.h>
|
|
|
|
|
|
|
|
#define HDLC_FLAG 0x7E
|
|
|
|
#define HDLC_ESCAPE 0x7D
|
|
|
|
|
|
|
|
#define HDLC_C_UI 0x03
|
|
|
|
#define HDLC_C_P_BIT (1 << 4)
|
|
|
|
#define HDLC_C_F_BIT (1 << 4)
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
};
|
|
|
|
|
2017-04-30 21:57:55 +00:00
|
|
|
struct osmo_sercomm_inst;
|
|
|
|
typedef void (*dlci_cb_t)(struct osmo_sercomm_inst *sercomm, uint8_t dlci, struct msgb *msg);
|
2017-04-30 19:39:33 +00:00
|
|
|
|
2017-04-30 21:57:55 +00:00
|
|
|
struct osmo_sercomm_inst {
|
2017-04-30 19:39:33 +00:00
|
|
|
int initialized;
|
|
|
|
int uart_id;
|
|
|
|
|
|
|
|
/* transmit side */
|
|
|
|
struct {
|
|
|
|
struct llist_head dlci_queues[_SC_DLCI_MAX];
|
|
|
|
struct msgb *msg;
|
|
|
|
int state;
|
|
|
|
uint8_t *next_char;
|
|
|
|
} tx;
|
|
|
|
|
|
|
|
/* receive side */
|
|
|
|
struct {
|
|
|
|
dlci_cb_t dlci_handler[_SC_DLCI_MAX];
|
2017-04-30 22:19:13 +00:00
|
|
|
unsigned int msg_size;
|
2017-04-30 19:39:33 +00:00
|
|
|
struct msgb *msg;
|
|
|
|
int state;
|
|
|
|
uint8_t dlci;
|
|
|
|
uint8_t ctrl;
|
|
|
|
} rx;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-04-30 19:21:52 +00:00
|
|
|
#ifndef HOST_BUILD
|
|
|
|
#include <uart.h>
|
|
|
|
/* helper functions for target */
|
2017-04-30 21:57:55 +00:00
|
|
|
void osmo_sercomm_bind_uart(struct osmo_sercomm_inst *sercomm, int uart);
|
|
|
|
int osmo_sercomm_get_uart(struct osmo_sercomm_inst *sercomm);
|
|
|
|
void osmo_sercomm_change_speed(struct osmo_sercomm_inst *sercomm, enum uart_baudrate bdrt);
|
2017-04-30 19:21:52 +00:00
|
|
|
#endif
|
|
|
|
|
2017-04-30 21:57:55 +00:00
|
|
|
void osmo_sercomm_init(struct osmo_sercomm_inst *sercomm);
|
|
|
|
int osmo_sercomm_initialized(struct osmo_sercomm_inst *sercomm);
|
2017-04-30 19:21:52 +00:00
|
|
|
|
|
|
|
/* User Interface: Tx */
|
|
|
|
|
|
|
|
/* user interface for transmitting messages for a given DLCI */
|
2017-04-30 21:57:55 +00:00
|
|
|
void osmo_sercomm_sendmsg(struct osmo_sercomm_inst *sercomm, uint8_t dlci, struct msgb *msg);
|
2017-04-30 19:21:52 +00:00
|
|
|
/* how deep is the Tx queue for a given DLCI */
|
2017-04-30 21:57:55 +00:00
|
|
|
unsigned int osmo_sercomm_tx_queue_depth(struct osmo_sercomm_inst *sercomm, uint8_t dlci);
|
2017-04-30 19:21:52 +00:00
|
|
|
|
|
|
|
/* User Interface: Rx */
|
|
|
|
|
|
|
|
/* receiving messages for a given DLCI */
|
2017-04-30 21:57:55 +00:00
|
|
|
int osmo_sercomm_register_rx_cb(struct osmo_sercomm_inst *sercomm, uint8_t dlci, dlci_cb_t cb);
|
2017-04-30 19:21:52 +00:00
|
|
|
|
|
|
|
/* Driver Interface */
|
|
|
|
|
|
|
|
/* fetch one octet of to-be-transmitted serial data. returns 0 if no more data */
|
2017-04-30 21:57:55 +00:00
|
|
|
int osmo_sercomm_drv_pull(struct osmo_sercomm_inst *sercomm, uint8_t *ch);
|
2017-04-30 19:21:52 +00:00
|
|
|
/* the driver has received one byte, pass it into sercomm layer.
|
|
|
|
returns 1 in case of success, 0 in case of unrecognized char */
|
2017-04-30 21:57:55 +00:00
|
|
|
int osmo_sercomm_drv_rx_char(struct osmo_sercomm_inst *sercomm, uint8_t ch);
|
2017-04-30 19:21:52 +00:00
|
|
|
|
2017-04-30 21:57:55 +00:00
|
|
|
static inline struct msgb *osmo_sercomm_alloc_msgb(unsigned int len)
|
2017-04-30 19:21:52 +00:00
|
|
|
{
|
|
|
|
return msgb_alloc_headroom(len+4, 4, "sercomm_tx");
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* _SERCOMM_H */
|