예제 #1
0
/* get next frame from the tx queue. because the ms has multiple datalinks,
 * each datalink's queue is read round-robin.
 */
static int l2_ph_data_conf(struct msgb *msg, struct lapdm_entity *le)
{
	struct osmo_phsap_prim pp;

	/* we may send again */
	le->tx_pending = 0;

	/* free confirm message */
	if (msg)
		msgb_free(msg);

	if (lapdm_phsap_dequeue_prim(le, &pp) < 0) {
		/* no message in all queues */

		/* If user didn't request PH-EMPTY_FRAME.req, abort */
		if (!(le->flags & LAPDM_ENT_F_EMPTY_FRAME))
			return 0;

		/* otherwise, send PH-EMPTY_FRAME.req */
		osmo_prim_init(&pp.oph, SAP_GSM_PH,
				PRIM_PH_EMPTY_FRAME,
				PRIM_OP_REQUEST, NULL);
	} else {
		le->tx_pending = 1;
	}

	return le->l1_prim_cb(&pp.oph, le->l1_ctx);
}
예제 #2
0
/*! \brief dequeue a msg that's pending transmission via L1 and wrap it into
 * a osmo_phsap_prim */
int lapdm_phsap_dequeue_prim(struct lapdm_entity *le, struct osmo_phsap_prim *pp)
{
	struct msgb *msg;
	uint8_t pad;

	msg = tx_dequeue_msgb(le);
	if (!msg)
		return -ENODEV;

	/* if we have a message, send PH-DATA.req */
	osmo_prim_init(&pp->oph, SAP_GSM_PH, PRIM_PH_DATA,
			PRIM_OP_REQUEST, msg);

	/* Pull chan_nr and link_id */
	pp->u.data.chan_nr = *msg->data;
	msgb_pull(msg, 1);
	pp->u.data.link_id = *msg->data;
	msgb_pull(msg, 1);
	pad = *msg->data;
	msgb_pull(msg, 1);

	/* Pad the frame, we can transmit now */
	lapdm_pad_msgb(msg, pad);

	return 0;
}
예제 #3
0
/* write a frame into the tx queue */
static int tx_ph_data_enqueue(struct lapdm_datalink *dl, struct msgb *msg,
				uint8_t chan_nr, uint8_t link_id, uint8_t pad)
{
	struct lapdm_entity *le = dl->entity;
	struct osmo_phsap_prim pp;

	/* if there is a pending message, queue it */
	if (le->tx_pending || le->flags & LAPDM_ENT_F_POLLING_ONLY) {
		*msgb_push(msg, 1) = pad;
		*msgb_push(msg, 1) = link_id;
		*msgb_push(msg, 1) = chan_nr;
		msgb_enqueue(&dl->dl.tx_queue, msg);
		return -EBUSY;
	}

	osmo_prim_init(&pp.oph, SAP_GSM_PH, PRIM_PH_DATA,
			PRIM_OP_REQUEST, msg);
	pp.u.data.chan_nr = chan_nr;
	pp.u.data.link_id = link_id;

	/* send the frame now */
	le->tx_pending = 0; /* disabled flow control */
	lapdm_pad_msgb(msg, pad);

	return le->l1_prim_cb(&pp.oph, le->l1_ctx);
}
예제 #4
0
/* forward a RUA message to the SCCP User API to SCCP/SUA */
static int rua_to_scu(struct hnb_context *hnb, struct hnbgw_cnlink *cn,
		      enum osmo_scu_prim_type type,
		      uint32_t context_id, uint32_t cause,
		      const uint8_t *data, unsigned int len)
{
	struct msgb *msg = msgb_alloc(1500, "rua_to_sua");
	struct osmo_scu_prim *prim;
	struct hnbgw_context_map *map;
	int rc;

	if (!cn) {
		DEBUGP(DRUA, "CN=NULL, discarding message\n");
		return 0;
	}

	prim = (struct osmo_scu_prim *) msgb_put(msg, sizeof(*prim));
	osmo_prim_init(&prim->oph, SCCP_SAP_USER, type, PRIM_OP_REQUEST, msg);

	map = context_map_alloc_by_hnb(hnb, context_id, cn);

	/* add primitive header */
	switch (type) {
	case OSMO_SCU_PRIM_N_CONNECT:
		prim->u.connect.called_addr;
		prim->u.connect.calling_addr;
		prim->u.connect.sccp_class = 2;
		prim->u.connect.conn_id = map->scu_conn_id;
		break;
	case OSMO_SCU_PRIM_N_DATA:
		prim->u.data.conn_id = map->scu_conn_id;
		break;
	case OSMO_SCU_PRIM_N_DISCONNECT:
		prim->u.disconnect.conn_id = map->scu_conn_id;
		prim->u.disconnect.cause = cause;
		break;
	case OSMO_SCU_PRIM_N_UNITDATA:
		prim->u.unitdata.called_addr;
		prim->u.unitdata.calling_addr;
		break;
	default:
		return -EINVAL;
	}

	/* add optional data section, if needed */
	if (data && len) {
		msg->l2h = msgb_put(msg, len);
		memcpy(msg->l2h, data, len);
	}

	rc = osmo_sua_user_link_down(cn->sua_link, &prim->oph);

	return rc;
}
예제 #5
0
파일: oml.c 프로젝트: jemmy655/osmo
static int mph_info_chan_confirm(struct gsm_lchan *lchan,
			enum osmo_mph_info_type type, uint8_t cause)
{
	struct osmo_phsap_prim l1sap;

	memset(&l1sap, 0, sizeof(l1sap));
	osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, PRIM_OP_CONFIRM,
		NULL);
	l1sap.u.info.type = type;
	l1sap.u.info.u.act_cnf.chan_nr = gsm_lchan2chan_nr(lchan);
	l1sap.u.info.u.act_cnf.cause = cause;

	return l1sap_up(lchan->ts->trx, &l1sap);
}
예제 #6
0
static int send(struct msgb *in_msg, struct lapdm_channel *chan)
{
	struct osmo_phsap_prim pp;
	struct msgb *msg;
	int rc;

	msg = msgb_alloc_headroom(128, 64, "PH-DATA.ind");
	osmo_prim_init(&pp.oph, SAP_GSM_PH, PRIM_PH_DATA,
			PRIM_OP_INDICATION, msg);
	/* copy over actual MAC block */
	msg->l2h = msgb_put(msg, msgb_l2len(in_msg));
	memcpy(msg->l2h, in_msg->l2h, msgb_l2len(in_msg));

	/* LAPDm requires those... */
	pp.u.data.chan_nr = 0;
	pp.u.data.link_id = 0;
        /* feed into the LAPDm code of libosmogsm */
        rc = lapdm_phsap_up(&pp.oph, &chan->lapdm_dcch);
	ASSERT(rc == 0 || rc == -EBUSY);
	return 0;
}