sercomm: Better integration of driver interface

We cannot assume a certain UART API like uart_baudrate() which only
exists in OsmocomBB.  Rather, use generic function prototypes
(sercomm_drv_*) which are to be provided by the application /
environment to the sercomm core.

Change-Id: I01ea3067baf1791000c1a7d537ccce496a1ab1ee
This commit is contained in:
Harald Welte 2017-05-15 17:16:48 +02:00
parent a362ee90b4
commit 799bef5cf6
2 changed files with 24 additions and 34 deletions

View File

@ -58,12 +58,6 @@ struct osmo_sercomm_inst {
};
#ifdef EMBEDDED
#include <uart.h>
/* helper functions for target */
void osmo_sercomm_change_speed(struct osmo_sercomm_inst *sercomm, enum uart_baudrate bdrt);
#endif
void osmo_sercomm_init(struct osmo_sercomm_inst *sercomm);
int osmo_sercomm_initialized(struct osmo_sercomm_inst *sercomm);
@ -74,11 +68,18 @@ unsigned int osmo_sercomm_tx_queue_depth(struct osmo_sercomm_inst *sercomm, uint
/* 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);
extern void sercomm_drv_start_tx(struct osmo_sercomm_inst *sercomm);
extern int sercomm_drv_baudrate_chg(struct osmo_sercomm_inst *sercomm, uint32_t bdrt);
static inline struct msgb *osmo_sercomm_alloc_msgb(unsigned int len)
{
return msgb_alloc_headroom(len+4, 4, "sercomm_tx");

View File

@ -20,6 +20,8 @@
*
*/
#include "config.h"
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
@ -30,31 +32,20 @@
#include <osmocom/core/linuxlist.h>
#ifndef EMBEDDED
# define DEFAULT_RX_MSG_SIZE 2048
static inline void sercomm_drv_lock(unsigned long __attribute__((unused)) *flags) {}
static inline void sercomm_drv_unlock(unsigned long __attribute__((unused)) *flags) {}
void sercomm_drv_lock(unsigned long __attribute__((unused)) *flags) {}
void sercomm_drv_unlock(unsigned long __attribute__((unused)) *flags) {}
#else
# define DEFAULT_RX_MSG_SIZE 256
# include <debug.h>
# include <asm/system.h>
#endif /* EMBEDDED */
static inline void sercomm_drv_lock(unsigned long *flags)
/* weak symbols to be overridden by application */
__attribute__((weak)) void sercomm_drv_start_tx(struct osmo_sercomm_inst *sercomm) {};
__attribute__((weak)) int sercomm_drv_baudrate_chg(struct osmo_sercomm_inst *sercomm, uint32_t bdrt)
{
local_firq_save(*flags);
return -1;
}
static inline void sercomm_drv_unlock(unsigned long *flags)
{
local_irq_restore(*flags);
}
# include <uart.h>
#endif
#define HDLC_FLAG 0x7E
#define HDLC_ESCAPE 0x7D
@ -107,10 +98,8 @@ void osmo_sercomm_sendmsg(struct osmo_sercomm_inst *sercomm, uint8_t dlci, struc
msgb_enqueue(&sercomm->tx.dlci_queues[dlci], msg);
sercomm_drv_unlock(&flags);
#ifdef EMBEDDED
/* tell UART that we have something to send */
uart_irq_enable(sercomm->uart_id, UART_IRQ_TX_EMPTY, 1);
#endif
sercomm_drv_start_tx(sercomm);
}
/* how deep is the Tx queue for a given DLCI */
@ -126,10 +115,9 @@ unsigned int osmo_sercomm_tx_queue_depth(struct osmo_sercomm_inst *sercomm, uint
return num;
}
#ifdef EMBEDDED
/* wait until everything has been transmitted, then grab the lock and
* change the baud rate as requested */
void osmo_sercomm_change_speed(struct osmo_sercomm_inst *sercomm, enum uart_baudrate bdrt)
int osmo_sercomm_change_speed(struct osmo_sercomm_inst *sercomm, uint32_t bdrt)
{
unsigned int i, count;
unsigned long flags;
@ -138,7 +126,7 @@ void osmo_sercomm_change_speed(struct osmo_sercomm_inst *sercomm, enum uart_baud
/* count the number of pending messages */
count = 0;
for (i = 0; i < ARRAY_SIZE(sercomm->tx.dlci_queues); i++)
count += sercomm_tx_queue_depth(i);
count += osmo_sercomm_tx_queue_depth(sercomm, i);
/* if we still have any in the queue, restart */
if (count == 0)
break;
@ -149,15 +137,16 @@ void osmo_sercomm_change_speed(struct osmo_sercomm_inst *sercomm, enum uart_baud
* stays that way */
sercomm_drv_lock(&flags);
if (!sercomm->tx.msg && !sercomm->tx.next_char) {
int rc;
/* change speed */
uart_baudrate(sercomm->uart_id, bdrt);
rc = sercomm_drv_baudrate_chg(sercomm, bdrt);
sercomm_drv_unlock(&flags);
break;
}
return rc;
} else
sercomm_drv_unlock(&flags);
}
return -1;
}
#endif
/*! \brief fetch one octet of to-be-transmitted serial data
* \param[in] sercomm Sercomm Instance from which to fetch pending data