/* * write data from current packet to Transmit FIFO. * restart when done. */ static void bt3c_transmit(struct bt3c_softc *sc) { struct mbuf *m; int count, rlen; uint8_t *rptr; m = sc->sc_txp; if (m == NULL) { sc->sc_flags &= ~BT3C_XMIT; bt3c_start(sc); return; } count = 0; rlen = 0; rptr = mtod(m, uint8_t *); bt3c_set_address(sc, BT3C_TX_FIFO); for(;;) { if (rlen >= m->m_len) { m = m->m_next; if (m == NULL) { m = sc->sc_txp; sc->sc_txp = NULL; if (M_GETCTX(m, void *) == NULL) m_freem(m); else if (!hci_complete_sco(sc->sc_unit, m)) sc->sc_stats.err_tx++; break; }
/* * write data from current packet to Transmit FIFO. * restart when done. */ static void btbc_transmit(struct btbc_softc *sc) { hci_cmd_hdr_t *p; struct mbuf *m; int count, set_baudrate, n, s; uint32_t offset, command; uint8_t *rptr; m = sc->sc_txp; if (m == NULL) { sc->sc_flags &= ~BTBC_XMIT; btbc_start(sc); return; } set_baudrate = 0; p = mtod(m, hci_cmd_hdr_t *); if ((void *)m->m_pktdat == (void *)p) { const uint16_t opcode = htole16(HCI_CMD_ERICSSON_SET_UART_BAUD_RATE); if (p->type == HCI_CMD_PKT && p->opcode == opcode && p->length == 1) { set_baudrate = 1; sc->sc_txp = NULL; /* safe reentrant */ } } count = 0; rptr = mtod(m, uint8_t *); for(;;) { if (m->m_len == 0) { m = m->m_next; if (m == NULL) { m = sc->sc_txp; sc->sc_txp = NULL; if (M_GETCTX(m, void *) == NULL) m_freem(m); else if (!hci_complete_sco(sc->sc_unit, m)) sc->sc_stats.err_tx++; break; }
void ubt_xmit_sco_start1(struct ubt_softc *sc, struct ubt_isoc_xfer *isoc) { struct mbuf *m; uint8_t *buf; int num, len, size, space; if (sc->sc_dying) return; space = sc->sc_scowr_size * UBT_NFRAMES; buf = isoc->buf; len = 0; /* * Fill the request buffer with data from the queue, * keeping any leftover packet on our private hook. * * Complete packets are passed back up to the stack * for disposal, since we can't rely on the controller * to tell us when it has finished with them. */ m = sc->sc_scowr_mbuf; while (space > 0) { if (m == NULL) { crit_enter(); IF_DEQUEUE(&sc->sc_scowr_queue, m); crit_exit(); if (m == NULL) break; m_adj(m, 1); /* packet type */ } if (m->m_pkthdr.len > 0) { size = MIN(m->m_pkthdr.len, space); m_copydata(m, 0, size, buf); m_adj(m, size); buf += size; len += size; space -= size; } if (m->m_pkthdr.len == 0) { sc->sc_stats.sco_tx++; if (!hci_complete_sco(sc->sc_unit, m)) sc->sc_stats.err_tx++; m = NULL; } } sc->sc_scowr_mbuf = m; DPRINTFN(15, "isoc=%p, len=%d, space=%d\n", isoc, len, space); if (len == 0) /* nothing to send */ return; sc->sc_refcnt++; sc->sc_scowr_busy = 1; sc->sc_stats.byte_tx += len; isoc->busy = 1; /* * calculate number of isoc frames and sizes */ for (num = 0 ; len > 0 ; num++) { size = MIN(sc->sc_scowr_size, len); isoc->size[num] = size; len -= size; } usbd_setup_isoc_xfer(isoc->xfer, sc->sc_scowr_pipe, isoc, isoc->size, num, USBD_NO_COPY | USBD_FORCE_SHORT_XFER, ubt_xmit_sco_complete); usbd_transfer(isoc->xfer); }