Ejemplo n.º 1
0
static bool
wpa_recv(hndrte_dev_t *dev, void *ctx, struct lbuf *lb, uint16 ethtype)
{
	uint8 *pkt = lb->data;
	int len = lb->len;
	nas_wksp_t *nwksp = (nas_wksp_t *)ctx;
	nas_wpa_cb_t *nwcb;
	bcm_event_t *pvt_data = (bcm_event_t *)pkt;

	/* recv wpa message from relay */
	/* validate the recv packet */
	if (nas_validate_wlpvt_message(len, pkt) != 0) {
		goto error0;
	}
	pvt_data  = (bcm_event_t *)pkt;

	nwcb = nas_wksp_find_nwcb_by_mac(nwksp, pvt_data->eth.ether_dhost,
	                                 pvt_data->event.ifname);

	if (nwcb && !(nwcb->flags & NAS_WPA_CB_FLAG_ERROR))
		nas_handle_wlpvt_messages(nwcb, (void *)pvt_data, len, 1);

	lb_free(lb);
	return TRUE;

error0:
	/* way to say not our message */
	NASDBG("Not a WPA NAS packet, returning pkt to relay 0x%p\n", lb);
	return FALSE;
}
Ejemplo n.º 2
0
/*  sb_resize:
 *  change the maximum number of lines in the screen buffer to <size>
 *  discard lines at the top if necessary
 */
void 
sb_resize(LPSB sb, uint size)
{
    LPLB lb;
    uint sidx, idx, count;
    uint len;

    /* allocate new buffer */
    lb = calloc(size + 1, sizeof(LB));

    len = sb_internal_length(sb);
    sidx = (size > len) ? 0 : (len - size);
    count = (size > len) ? len : size;

    /* free elements if necessary */
    for(idx = 0; idx < sidx; idx++)
	lb_free(sb_internal_get(sb, idx));

    /* copy elements to new buffer */
    for(idx = 0; idx < count; idx++, sidx++)
	lb_copy(&(lb[idx]), sb_internal_get(sb, sidx));

    /* replace old buffer by new one */
    free(sb->lb);
    sb->lb = lb;
    sb->size = size + 1;
    sb->head = 0;
    sb->tail = count;
}
Ejemplo n.º 3
0
/*  sb_free:
 *  free all line buffers of a screen buffer
 */
void 
sb_free(LPSB sb)
{
    uint idx, len;

    assert(sb != NULL);
    assert(sb->lb != NULL);

    /* free all line buffers */
    len = sb_internal_length(sb);
    for(idx = 0; idx < len; idx++)
	lb_free(&(sb->lb[idx]));

    free(sb->lb);
    sb->lb = NULL;
    sb->head = sb->tail = 0;
    sb->size = 0;
}
Ejemplo n.º 4
0
static int
bcm_rpc_tp_buf_send_internal(rpc_tp_info_t * rpcb, rpc_buf_t *b, uint32 tx_ep_index)
{
	int err;
	struct lbuf *lb = (struct lbuf *)b;
	hndrte_dev_t *chained = rpcb->ctx->chained;
	uint pktlen;

	ASSERT(chained);

		ASSERT(b != NULL);
		pktlen = bcm_rpc_buf_totlen_get(rpcb, b);

		if (pktlen == BCM_RPC_TP_DNGL_TOTLEN_BAD) {
			RPC_TP_AGG(("%s, pkt is %d bytes, padding %d bytes\n", __FUNCTION__,
				BCM_RPC_TP_DNGL_TOTLEN_BAD, BCM_RPC_TP_DNGL_TOTLEN_BAD_PAD));

			bcm_rpc_tp_buf_pad(rpcb, b, BCM_RPC_TP_DNGL_TOTLEN_BAD_PAD);

		} else if (pktlen % BCM_RPC_TP_DNGL_BULKEP_MPS == 0) {
			RPC_TP_AGG(("%s, tp pkt is multiple of %d bytes, padding %d bytes\n",
				__FUNCTION__,
				BCM_RPC_TP_DNGL_BULKEP_MPS, BCM_RPC_TP_DNGL_ZLP_PAD));

			bcm_rpc_tp_buf_pad(rpcb, b, BCM_RPC_TP_DNGL_ZLP_PAD);
		}


	lb = PKTTONATIVE(rpcb->osh, b);
	/* send through data endpoint */
	if ((err = chained->funcs->xmit(rpcb->ctx, chained, lb)) != 0) {
		RPC_TP_ERR(("%s: xmit failed; free pkt %p\n", __FUNCTION__, lb));
		rpcb->txerr_cnt++;
		lb_free(lb);
	} else {
		rpcb->tx_cnt++;

		/* give pkt ownership to usb driver, decrement the counter */
		rpcb->buf_cnt_inuse -= pktsegcnt(rpcb->osh, b);
	}

	return err;
}
Ejemplo n.º 5
0
int
bcm_rpc_tp_send_callreturn(rpc_tp_info_t * rpc_th, rpc_buf_t *b)
{
	int err, pktlen;
	struct lbuf *lb;
	hndrte_dev_t *chained = rpc_th->ctx->chained;

	ASSERT(chained);

	/* Add the TP encapsulation */
	bcm_rpc_tp_tx_encap(rpc_th, b);

	/* Pad if pkt size is a multiple of MPS */
	pktlen = bcm_rpc_buf_totlen_get(rpc_th, b);
		if (pktlen % BCM_RPC_TP_DNGL_CTRLEP_MPS == 0) {
			RPC_TP_AGG(("%s, tp pkt is multiple of %d bytes, padding %d bytes\n",
			__FUNCTION__, BCM_RPC_TP_DNGL_CTRLEP_MPS, BCM_RPC_TP_DNGL_ZLP_PAD));

		bcm_rpc_tp_buf_pad(rpc_th, b, BCM_RPC_TP_DNGL_ZLP_PAD);
	}

	lb = PKTTONATIVE(rpc_th->osh, b);

	if (rpc_th->has_2nd_bulk_in_ep) {
		err = chained->funcs->xmit2(rpc_th->ctx, chained, lb, USBDEV_BULK_IN_EP2);
	} else {
		err = chained->funcs->xmit_ctl(rpc_th->ctx, chained, lb);
	}
	/* send through control endpoint */
	if (err != 0) {
		RPC_TP_ERR(("%s: xmit failed; free pkt %p\n", __FUNCTION__, lb));
		rpc_th->txerr_cnt++;
		lb_free(lb);
	} else {
		rpc_th->tx_cnt++;

		/* give pkt ownership to usb driver, decrement the counter */
		rpc_th->buf_cnt_inuse -= pktsegcnt(rpc_th->osh, b);
	}

	return err;

}
Ejemplo n.º 6
0
/*  sb_append:
 *  append a line buffer at the end of the screen buffer,
 *  if the screen buffer is full discard the first line;
 *  the line is _copied_ to the screen buffer
 */
int 
sb_append(LPSB sb, LPLB lb)
{
    uint idx;
    int y_correction = 0;

    assert(sb != NULL);
    assert(lb != NULL);

    idx = sb->tail;
    sb->tail = (sb->tail + 1) % sb->size;
    if (sb->tail == sb->head) {
	y_correction = sb_lines(sb, &(sb->lb[sb->head]));
	lb_free(&(sb->lb[sb->head]));
	sb->head = (sb->head + 1) % sb->size;
    }
    lb_copy(&(sb->lb[idx]), lb);

    sb->length += sb_lines(sb, lb) - y_correction;
    return y_correction;
}
Ejemplo n.º 7
0
void
bcm_rpc_tp_rx_from_dnglbus(rpc_tp_info_t *rpc_th, struct lbuf *lb)
{
	void *orig_p, *p;
	void *rpc_p, *rpc_prev;
	uint pktlen, tp_len, iter = 0;
	osl_t *osh;
	bool dbg_agg;
	uint dbg_data[16], i;	/* must fit host agg limit BCM_RPC_TP_HOST_AGG_MAX_SFRAME+1 */

	dbg_agg = FALSE;

	rpc_th->rx_cnt++;

	if (rpc_th->rx_pkt == NULL) {
		RPC_TP_ERR(("%s: no rpc rx fn, dropping\n", __FUNCTION__));
		rpc_th->rxdrop_cnt++;
		lb_free(lb);
		return;
	}
	orig_p = PKTFRMNATIVE(rpc_th->osh, lb);


	osh = rpc_th->osh;

	/* take ownership of the dnglbus packet chain
	 * since it will be freed by bcm_rpc_tp_buf_free()
	 */
	rpc_th->buf_cnt_inuse += pktsegcnt(rpc_th->osh, orig_p);

	dbg_data[0] = pktsegcnt(rpc_th->osh, orig_p);

	pktlen = PKTLEN(osh, orig_p);

	p = orig_p;

	/* while we have more data in the TP frame's packet chain,
	 *   create a packet chain(could be cloned) for the next RPC frame
	 *   then give it away to high layer for process(buffer not freed)
	 */
	while (p != NULL) {
		iter++;

		/* read TP_HDR(len of rpc frame) and pull the data pointer past the length word */
		if (pktlen >= BCM_RPC_TP_ENCAP_LEN) {
			ASSERT(((uint)PKTDATA(osh, p) & 0x3) == 0); /* ensure aligned word read */
			tp_len = ltoh32(*(uint32*)PKTDATA(osh, p));
			PKTPULL(osh, p, BCM_RPC_TP_ENCAP_LEN);
			pktlen -= BCM_RPC_TP_ENCAP_LEN;
		} else {
			/* error case: less data than the encapsulation size
			 * treat as an empty tp buffer, at end of current buffer
			 */
			tp_len = 0;
			pktlen = 0;

			rpc_th->tp_dngl_deagg_cnt_badsflen++;	/* bad sf len */
		}

		/* if TP header finished a buffer(rpc header in next chained buffer), open next */
		if (pktlen == 0) {
			void *next_p = PKTNEXT(osh, p);
			PKTSETNEXT(osh, p, NULL);
			rpc_th->buf_cnt_inuse--;
			PKTFREE(osh, p, FALSE);
			p = next_p;
			if (p)
				pktlen = PKTLEN(osh, p);
		}

		dbg_data[iter] = tp_len;

		if (tp_len < pktlen || dbg_agg) {
			dbg_agg = TRUE;
			RPC_TP_DEAGG(("DEAGG: [%d] p %p data %p pktlen %d tp_len %d\n",
				iter, p, PKTDATA(osh, p), pktlen, tp_len));
			rpc_th->tp_dngl_deagg_cnt_sf++;
			rpc_th->tp_dngl_deagg_cnt_bytes += tp_len;
		}

		/* empty TP buffer (special case: use tp_len to pad for some USB pktsize bugs) */
		if (tp_len == 0) {
			rpc_th->tp_dngl_deagg_cnt_pass++;
			continue;
		} else if (tp_len > 10000 ) {	/* something is wrong */
			/* print out msgs according to value of p  -- in case it is NULL */
			if (p != NULL) {
				RPC_TP_ERR(("DEAGG: iter %d, p(%p data %p pktlen %d)\n",
					iter, p, PKTDATA(osh, p), PKTLEN(osh, p)));
			} else {
				RPC_TP_ERR(("DEAGG: iter %d, p is NULL", iter));
			}
		}

		/* ========= For this TP subframe, find the end, build a chain, sendup ========= */

		/* RPC frame packet chain starts with this packet */
		rpc_prev = NULL;
		rpc_p = p;
		ASSERT(p != NULL);

		/* find the last frag in this rpc chain */
		while ((tp_len >= pktlen) && p) {
			if (dbg_agg)
				RPC_TP_DEAGG(("DEAGG: tp_len %d consumes p(%p pktlen %d)\n", tp_len,
					p, pktlen));
			rpc_prev = p;
			p = PKTNEXT(osh, p);
			tp_len -= pktlen;

			if (p != NULL) {
				pktlen = PKTLEN(osh, p);
			} else {
				if (tp_len != 0) {
					uint totlen, seg;
					totlen = pkttotlen(osh, rpc_p);
					seg = pktsegcnt(rpc_th->osh, rpc_p);

					RPC_TP_ERR(("DEAGG, toss[%d], orig_p %p segcnt %d",
					       iter, orig_p, dbg_data[0]));
					RPC_TP_ERR(("DEAGG,rpc_p %p totlen %d pktl %d tp_len %d\n",
					       rpc_p, totlen, pktlen, tp_len));
					for (i = 1; i <= iter; i++)
						RPC_TP_ERR(("tplen[%d] = %d  ", i, dbg_data[i]));
					RPC_TP_ERR(("\n"));
					p = rpc_p;
					while (p != NULL) {
						RPC_TP_ERR(("this seg len %d\n", PKTLEN(osh, p)));
						p = PKTNEXT(osh, p);
					}

					rpc_th->buf_cnt_inuse -= seg;
					PKTFREE(osh, rpc_p, FALSE);
					rpc_th->tp_dngl_deagg_cnt_badfmt++;

					/* big hammer to recover USB
					 * extern void dngl_reboot(void); dngl_reboot();
					 */
					goto end;
				}
				pktlen = 0;
				break;
			}
		}

		/* fix up the last frag */
		if (tp_len == 0) {
			/* if the whole RPC buffer chain ended at the end of the prev TP buffer,
			 *    end the RPC buffer chain. we are done
			 */
			if (dbg_agg)
				RPC_TP_DEAGG(("DEAGG: END rpc chain p %p len %d\n\n", rpc_prev,
					pktlen));

			PKTSETNEXT(osh, rpc_prev, NULL);
			if (iter > 1) {
				rpc_th->tp_dngl_deagg_cnt_chain++;
				RPC_TP_DEAGG(("this frag %d totlen %d\n", pktlen,
					pkttotlen(osh, orig_p)));
			}

		} else {
			/* if pktlen has more bytes than tp_len, another tp frame must follow
			 *   create a clone of the sub-range of the current TP buffer covered
			 *   by the RPC buffer, attach to the end of the RPC buffer chain
			 *   (cut off the original chain link)
			 *   continue chain looping(p != NULL)
			 */
			void *new_p;
			ASSERT(p != NULL);

			RPC_TP_DEAGG(("DEAGG: cloning %d bytes out of p(%p data %p) len %d\n",
				tp_len, p, PKTDATA(osh, p), pktlen));

			new_p = osl_pktclone(osh, p, 0, tp_len);
			rpc_th->buf_cnt_inuse++;
			rpc_th->tp_dngl_deagg_cnt_clone++;

			RPC_TP_DEAGG(("DEAGG: after clone, newp(%p data %p pktlen %d)\n",
				new_p, PKTDATA(osh, new_p), PKTLEN(osh, new_p)));

			if (rpc_prev) {
				RPC_TP_DEAGG(("DEAGG: chaining: %p->%p(clone)\n", rpc_prev,
					new_p));
				PKTSETNEXT(osh, rpc_prev, new_p);
			} else {
				RPC_TP_DEAGG(("DEAGG: clone %p is a complete rpc pkt\n", new_p));
				rpc_p = new_p;
			}

			PKTPULL(osh, p, tp_len);
			pktlen -= tp_len;
			RPC_TP_DEAGG(("DEAGG: remainder packet p %p data %p pktlen %d\n",
				p, PKTDATA(osh, p), PKTLEN(osh, p)));
		}

		/* !! send up */
		(rpc_th->rx_pkt)(rpc_th->rx_context, rpc_p);
	}

end:
	ASSERT(p == NULL);
}