aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2012-06-11 16:54:35 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2012-06-11 16:54:35 +0000
commitd094e348c5d1a3785289c69c5185bbaca1257de8 (patch)
tree982d1606d57103c8ee2d38e9a11d161a65716640 /os/hal
parentc762926b68f6a6c7f1e71b8acf9b1dd29d6e481f (diff)
downloadChibiOS-d094e348c5d1a3785289c69c5185bbaca1257de8.tar.gz
ChibiOS-d094e348c5d1a3785289c69c5185bbaca1257de8.tar.bz2
ChibiOS-d094e348c5d1a3785289c69c5185bbaca1257de8.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4266 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal')
-rw-r--r--os/hal/include/usb.h10
-rw-r--r--os/hal/platforms/STM32/OTGv1/usb_lld.c163
-rw-r--r--os/hal/platforms/STM32/OTGv1/usb_lld.h44
-rw-r--r--os/hal/src/serial.c4
-rw-r--r--os/hal/src/serial_usb.c115
5 files changed, 232 insertions, 104 deletions
diff --git a/os/hal/include/usb.h b/os/hal/include/usb.h
index 89871ffe6..d2a154949 100644
--- a/os/hal/include/usb.h
+++ b/os/hal/include/usb.h
@@ -416,11 +416,12 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @param[in] iq input queue to be filled with incoming data
+ * @param[in] n maximum number of bytes to copy
*
* @special
*/
-#define usbPrepareQueuedReceive(usbp, ep, iq) \
- usb_lld_prepare_queued_receive(usbp, ep, iq)
+#define usbPrepareQueuedReceive(usbp, ep, iq, n) \
+ usb_lld_prepare_queued_receive(usbp, ep, iq, n)
/**
* @brief Prepares for a transmit transaction on an IN endpoint.
@@ -433,11 +434,12 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @param[in] oq output queue to be fetched for outgoing data
+ * @param[in] n maximum number of bytes to copy
*
* @special
*/
-#define usbPrepareQueuedTransmit(usbp, ep, oq) \
- usb_lld_prepare_queued_transmit(usbp, ep, oq)
+#define usbPrepareQueuedTransmit(usbp, ep, oq, n) \
+ usb_lld_prepare_queued_transmit(usbp, ep, oq, n)
/**
* @brief Returns the exact size of a receive transaction.
diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.c b/os/hal/platforms/STM32/OTGv1/usb_lld.c
index 44d292b8b..fae5f500f 100644
--- a/os/hal/platforms/STM32/OTGv1/usb_lld.c
+++ b/os/hal/platforms/STM32/OTGv1/usb_lld.c
@@ -193,11 +193,12 @@ static uint32_t otg_ram_alloc(USBDriver *usbp, size_t size) {
* @param[in] ep endpoint number
* @param[in] buf buffer where to copy the endpoint data
* @param[in] n maximum number of bytes to copy
- * @return the number of bytes that were effectively written
*
* @notapi
*/
-static void otg_fifo_write(usbep_t ep, const uint8_t *buf, size_t n) {
+static void otg_fifo_write_from_buffer(usbep_t ep,
+ const uint8_t *buf,
+ size_t n) {
volatile uint32_t *fifop;
fifop = OTG_FIFO(ep);
@@ -214,6 +215,55 @@ static void otg_fifo_write(usbep_t ep, const uint8_t *buf, size_t n) {
}
/**
+ * @brief Writes to a TX FIFO fetching data from a queue.
+ *
+ * @param[in] ep endpoint number
+ * @param[in] oqp pointer to an @p OutputQueue object
+ * @param[in] n maximum number of bytes to copy
+ *
+ * @notapi
+ */
+static void otg_fifo_write_from_queue(usbep_t ep,
+ OutputQueue *oqp,
+ size_t n) {
+ size_t nw;
+ uint8_t *bp;
+ volatile uint32_t *fifop;
+
+ fifop = OTG_FIFO(ep);
+
+ /* Fetching data from the queue buffer directly.*/
+ bp = oqp->q_rdptr;
+ nw = (n + 3) / 4;
+ do {
+ uint32_t dw;
+ dw = (uint32_t)*bp++;
+ if (bp >= oqp->q_top)
+ bp = oqp->q_buffer;
+ dw |= (uint32_t)*bp++ << 8;
+ if (bp >= oqp->q_top)
+ bp = oqp->q_buffer;
+ dw |= (uint32_t)*bp++ << 16;
+ if (bp >= oqp->q_top)
+ bp = oqp->q_buffer;
+ dw |= (uint32_t)*bp++ << 24;
+ if (bp >= oqp->q_top)
+ bp = oqp->q_buffer;
+ *fifop = dw;
+ } while (--nw > 0);
+
+ /* Updating queue.*/
+ chSysLockFromIsr();
+ oqp->q_rdptr += n;
+ if (oqp->q_rdptr >= oqp->q_top)
+ oqp->q_rdptr = oqp->q_buffer;
+ oqp->q_counter += n;
+ while (notempty(&oqp->q_waiting))
+ chSchReadyI(fifo_remove(&oqp->q_waiting))->p_u.rdymsg = Q_OK;
+ chSysUnlockFromIsr();
+}
+
+/**
* @brief Reads a packet from the RXFIFO.
*
* @param[out] buf buffer where to copy the endpoint data
@@ -222,7 +272,7 @@ static void otg_fifo_write(usbep_t ep, const uint8_t *buf, size_t n) {
*
* @notapi
*/
-static void otg_fifo_read(uint8_t *buf, size_t n, size_t max) {
+static void otg_fifo_read_to_buffer(uint8_t *buf, size_t n, size_t max) {
volatile uint32_t *fifop;
fifop = OTG_FIFO(0);
@@ -242,6 +292,25 @@ static void otg_fifo_read(uint8_t *buf, size_t n, size_t max) {
}
/**
+ * @brief Reads a packet from the RXFIFO.
+ *
+ * @param[in] oqp pointer to an @p InputQueue object
+ * @param[in] n number of bytes to pull from the FIFO
+ *
+ * @notapi
+ */
+static void otg_fifo_read_to_queue(InputQueue *iqp, size_t n) {
+ size_t nw;
+ volatile uint32_t *fifop;
+
+ fifop = OTG_FIFO(0);
+ nw = (n + 3) / 4;
+ do {
+ uint32_t dw = *fifop;
+ } while (--n > 0);
+}
+
+/**
* @brief Incoming packets handler.
*
* @param[in] usbp pointer to the @p USBDriver object
@@ -258,15 +327,21 @@ static void otg_rxfifo_handler(USBDriver *usbp) {
case GRXSTSP_SETUP_DATA:
cnt = (sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF;
ep = (sts & GRXSTSP_EPNUM_MASK) >> GRXSTSP_EPNUM_OFF;
- otg_fifo_read(usbp->epc[ep]->setup_buf, cnt, 8);
+ otg_fifo_read_to_buffer(usbp->epc[ep]->setup_buf, cnt, 8);
break;
case GRXSTSP_OUT_DATA:
cnt = (sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF;
ep = (sts & GRXSTSP_EPNUM_MASK) >> GRXSTSP_EPNUM_OFF;
- otg_fifo_read(usbp->epc[ep]->out_state->rxbuf, cnt,
- usbp->epc[ep]->out_state->rxsize -
- usbp->epc[ep]->out_state->rxcnt);
- usbp->epc[ep]->out_state->rxbuf += cnt;
+ if (usbp->epc[ep]->out_state->rxqueued) {
+ /* Queue associated.*/
+ }
+ else {
+ otg_fifo_read_to_buffer(usbp->epc[ep]->out_state->mode.linear.rxbuf,
+ cnt,
+ usbp->epc[ep]->out_state->rxsize -
+ usbp->epc[ep]->out_state->rxcnt);
+ usbp->epc[ep]->out_state->mode.linear.rxbuf += cnt;
+ }
usbp->epc[ep]->out_state->rxcnt += cnt;
break;
case GRXSTSP_OUT_GLOBAL_NAK:
@@ -287,12 +362,28 @@ static void otg_rxfifo_handler(USBDriver *usbp) {
static void otg_txfifo_handler(USBDriver *usbp, usbep_t ep) {
uint32_t n;
+ /* Number of bytes remaining in current transaction.*/
n = usbp->epc[ep]->in_state->txsize - usbp->epc[ep]->in_state->txcnt;
if (n > usbp->epc[ep]->in_maxsize)
n = usbp->epc[ep]->in_maxsize;
- otg_fifo_write(ep, usbp->epc[ep]->in_state->txbuf, n);
- usbp->epc[ep]->in_state->txbuf += n;
+
+ if (usbp->epc[ep]->in_state->txqueued) {
+ /* Queue associated.*/
+ otg_fifo_write_from_queue(ep,
+ usbp->epc[ep]->in_state->mode.queue.txqueue,
+ n);
+ }
+ else {
+ /* Linear buffer associated.*/
+ otg_fifo_write_from_buffer(ep,
+ usbp->epc[ep]->in_state->mode.linear.txbuf,
+ n);
+ usbp->epc[ep]->in_state->mode.linear.txbuf += n;
+ }
usbp->epc[ep]->in_state->txcnt += n;
+ /* TODO: Potential issue, txcnt can be less than txsize after the planned
+ number of packets have been received, better disable the interrupt
+ at the end of the transaction in otg_epin_handler().*/
if (usbp->epc[ep]->in_state->txcnt >= usbp->epc[ep]->in_state->txsize) {
/* Transfer finished.*/
OTG->DIEPEMPMSK &= ~DIEPEMPMSK_INEPTXFEM(ep);
@@ -313,14 +404,14 @@ static void otg_epin_handler(USBDriver *usbp, usbep_t ep) {
/* Resets all EP IRQ sources.*/
OTG->ie[ep].DIEPINT = 0xFFFFFFFF;
- if (epint & DIEPINT_TXFE) {
- /* TX FIFO empty or emptying.*/
- otg_txfifo_handler(usbp, ep);
- }
if (epint & DIEPINT_XFRC) {
/* Transmit transfer complete.*/
_usb_isr_invoke_in_cb(usbp, ep);
}
+ if (epint & DIEPINT_TXFE) {
+ /* TX FIFO empty or emptying.*/
+ otg_txfifo_handler(usbp, ep);
+ }
if (epint & DIEPINT_TOC) {
/* Timeouts not handled yet, not sure how to handle.*/
}
@@ -730,9 +821,12 @@ void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep,
uint32_t pcnt;
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
- osp->rxbuf = buf;
- osp->rxsize = n;
- osp->rxcnt = 0;
+ osp->rxqueued = FALSE;
+ osp->rxsize = n;
+ osp->rxcnt = 0;
+ osp->mode.linear.rxbuf = buf;
+
+ /* Transfer initialization.*/
pcnt = (n + usbp->epc[ep]->out_maxsize - 1) / usbp->epc[ep]->out_maxsize;
OTG->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) |
DOEPTSIZ_XFRSIZ(usbp->epc[ep]->out_maxsize);
@@ -753,9 +847,10 @@ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep,
uint32_t pcnt;
USBInEndpointState *isp = usbp->epc[ep]->in_state;
- isp->txbuf = buf;
- isp->txsize = n;
- isp->txcnt = 0;
+ isp->txqueued = FALSE;
+ isp->txsize = n;
+ isp->txcnt = 0;
+ isp->mode.linear.txbuf = buf;
if (n == 0) {
/* Special case, sending zero size packet.*/
@@ -782,12 +877,24 @@ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep,
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @param[in] iq input queue to be filled with incoming data
+ * @param[in] n maximum number of bytes to copy
*
* @special
*/
void usb_lld_prepare_queued_receive(USBDriver *usbp, usbep_t ep,
- InputQueue *iq) {
+ InputQueue *iq, size_t n) {
+ uint32_t pcnt;
+ USBOutEndpointState *osp = usbp->epc[ep]->out_state;
+
+ osp->rxqueued = TRUE;
+ osp->rxsize = n;
+ osp->rxcnt = 0;
+ osp->mode.queue.rxqueue = iq;
+ /* Transfer initialization.*/
+ pcnt = (n + usbp->epc[ep]->out_maxsize - 1) / usbp->epc[ep]->out_maxsize;
+ OTG->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) |
+ DOEPTSIZ_XFRSIZ(usbp->epc[ep]->out_maxsize);
}
/**
@@ -801,12 +908,24 @@ void usb_lld_prepare_queued_receive(USBDriver *usbp, usbep_t ep,
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @param[in] oq output queue to be fetched for outgoing data
+ * @param[in] n maximum number of bytes to copy
*
* @special
*/
void usb_lld_prepare_queued_transmit(USBDriver *usbp, usbep_t ep,
- OutputQueue *oq) {
+ OutputQueue *oq, size_t n) {
+ uint32_t pcnt;
+ USBInEndpointState *isp = usbp->epc[ep]->in_state;
+
+ isp->txqueued = TRUE;
+ isp->txsize = n;
+ isp->txcnt = 0;
+ isp->mode.queue.txqueue = oq;
+ /* Transfer initialization.*/
+ pcnt = (n + usbp->epc[ep]->in_maxsize - 1) / usbp->epc[ep]->in_maxsize;
+ OTG->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(pcnt) |
+ DIEPTSIZ_XFRSIZ(usbp->epc[ep]->in_state->txsize);
}
/**
diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.h b/os/hal/platforms/STM32/OTGv1/usb_lld.h
index 687d788ff..ea0def924 100644
--- a/os/hal/platforms/STM32/OTGv1/usb_lld.h
+++ b/os/hal/platforms/STM32/OTGv1/usb_lld.h
@@ -108,13 +108,13 @@
/*===========================================================================*/
/**
- * @brief Type of an endpoint state structure.
+ * @brief Type of an IN endpoint state structure.
*/
typedef struct {
/**
- * @brief Pointer to the transmission buffer.
+ * @brief Buffer mode, queue or linear.
*/
- const uint8_t *txbuf;
+ bool_t txqueued;
/**
* @brief Requested transmit transfer size.
*/
@@ -123,16 +123,30 @@ typedef struct {
* @brief Transmitted bytes so far.
*/
size_t txcnt;
+ union {
+ struct {
+ /**
+ * @brief Pointer to the transmission buffer.
+ */
+ const uint8_t *txbuf;
+ } linear;
+ struct {
+ /**
+ * @brief Pointer to the output queue.
+ */
+ OutputQueue *txqueue;
+ } queue;
+ } mode;
} USBInEndpointState;
/**
- * @brief Type of an endpoint state structure.
+ * @brief Type of an OUT endpoint state structure.
*/
typedef struct {
/**
- * @brief Pointer to the receive buffer.
+ * @brief Buffer mode, queue or linear.
*/
- uint8_t *rxbuf;
+ bool_t rxqueued;
/**
* @brief Requested receive transfer size.
*/
@@ -141,6 +155,20 @@ typedef struct {
* @brief Received bytes so far.
*/
size_t rxcnt;
+ union {
+ struct {
+ /**
+ * @brief Pointer to the receive buffer.
+ */
+ uint8_t *rxbuf;
+ } linear;
+ struct {
+ /**
+ * @brief Pointer to the input queue.
+ */
+ InputQueue *rxqueue;
+ } queue;
+ } mode;
} USBOutEndpointState;
/**
@@ -378,9 +406,9 @@ extern "C" {
void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep,
const uint8_t *buf, size_t n);
void usb_lld_prepare_queued_receive(USBDriver *usbp, usbep_t ep,
- InputQueue *iq);
+ InputQueue *iq, size_t n);
void usb_lld_prepare_queued_transmit(USBDriver *usbp, usbep_t ep,
- OutputQueue *oq);
+ OutputQueue *oq, size_t n);
void usb_lld_start_out(USBDriver *usbp, usbep_t ep);
void usb_lld_start_in(USBDriver *usbp, usbep_t ep);
void usb_lld_stall_out(USBDriver *usbp, usbep_t ep);
diff --git a/os/hal/src/serial.c b/os/hal/src/serial.c
index 3f06025c6..5b883e16a 100644
--- a/os/hal/src/serial.c
+++ b/os/hal/src/serial.c
@@ -149,8 +149,8 @@ void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify) {
chEvtInit(&sdp->event);
sdp->flags = CHN_NO_ERROR;
sdp->state = SD_STOP;
- chIQInit(&sdp->iqueue, sdp->ib, SERIAL_BUFFERS_SIZE, inotify);
- chOQInit(&sdp->oqueue, sdp->ob, SERIAL_BUFFERS_SIZE, onotify);
+ chIQInit(&sdp->iqueue, sdp->ib, SERIAL_BUFFERS_SIZE, inotify, sdp);
+ chOQInit(&sdp->oqueue, sdp->ob, SERIAL_BUFFERS_SIZE, onotify, sdp);
}
/**
diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c
index 7f1658812..5fec52a68 100644
--- a/os/hal/src/serial_usb.c
+++ b/os/hal/src/serial_usb.c
@@ -117,59 +117,47 @@ static const struct SerialUSBDriverVMT vmt = {
* @brief Notification of data removed from the input queue.
*/
static void inotify(GenericQueue *qp) {
- SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_wrptr;
+ size_t n, maxsize;
+ SerialUSBDriver *sdup = chQGetLink(qp);
-#if 0
- /* Writes to the input queue can only happen when the queue has been
- emptied, then a whole packet is loaded in the queue.*/
+ /* If there is in the queue enough space to hold at least one packet and
+ a transaction is not yet started then a new transaction is started for
+ the available space.*/
+ maxsize = sdup->config->usbp->epc[USB_CDC_DATA_AVAILABLE_EP]->out_maxsize;
if (!usbGetReceiveStatusI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP) &&
- chIQIsEmptyI(&sdup->iqueue)) {
+ ((n = chIQGetEmptyI(&sdup->iqueue)) >= maxsize)) {
chSysUnlock();
- /* Unlocked to make the potentially long read operation preemptable.*/
- size_t n = usbReadPacketBuffer(sdup->config->usbp,
- USB_CDC_DATA_AVAILABLE_EP,
- sdup->iqueue.q_buffer,
- SERIAL_USB_BUFFERS_SIZE);
+ n = (n / maxsize) * maxsize;
+ usbPrepareQueuedReceive(sdup->config->usbp,
+ USB_CDC_DATA_AVAILABLE_EP,
+ &sdup->iqueue, n);
chSysLock();
usbStartReceiveI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP);
- chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE);
- sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer;
- sdup->iqueue.q_counter = n;
- while (notempty(&sdup->iqueue.q_waiting))
- chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK;
}
-#endif
}
/**
* @brief Notification of data inserted into the output queue.
*/
static void onotify(GenericQueue *qp) {
- SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_rdptr;
size_t n;
+ SerialUSBDriver *sdup = chQGetLink(qp);
-#if 0
- /* If there is any data in the output queue then it is sent within a
- single packet and the queue is emptied.*/
- n = chOQGetFullI(&sdup->oqueue);
- if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP)) {
+ /* If there is not an ongoing transaction and the output queue contains
+ data then a new transaction is started.*/
+ if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP) &&
+ ((n = chOQGetFullI(&sdup->oqueue)) > 0)) {
chSysUnlock();
- /* Unlocked to make the potentially long write operation preemptable.*/
- usbWritePacketBuffer(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP,
- sdup->oqueue.q_buffer, n);
+ usbPrepareQueuedTransmit(sdup->config->usbp,
+ USB_CDC_DATA_REQUEST_EP,
+ &sdup->oqueue, n);
chSysLock();
usbStartTransmitI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP);
- chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY);
- sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer;
- sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue);
- while (notempty(&sdup->oqueue.q_waiting))
- chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK;
}
-#endif
}
/*===========================================================================*/
@@ -201,12 +189,8 @@ void sduObjectInit(SerialUSBDriver *sdup) {
chEvtInit(&sdup->event);
sdup->flags = CHN_NO_ERROR;
sdup->state = SDU_STOP;
- chIQInit(&sdup->iqueue, sdup->ib, SERIAL_USB_BUFFERS_SIZE, inotify);
- chOQInit(&sdup->oqueue, sdup->ob, SERIAL_USB_BUFFERS_SIZE, onotify);
- /* This is a dirty trick but those pointers are never used because queues
- are accessed in block mode from the low level.*/
- sdup->iqueue.q_wrptr = (uint8_t *)sdup;
- sdup->oqueue.q_rdptr = (uint8_t *)sdup;
+ chIQInit(&sdup->iqueue, sdup->ib, SERIAL_USB_BUFFERS_SIZE, inotify, sdup);
+ chOQInit(&sdup->oqueue, sdup->ob, SERIAL_USB_BUFFERS_SIZE, onotify, sdup);
}
/**
@@ -299,32 +283,28 @@ bool_t sduRequestsHook(USBDriver *usbp) {
* @param[in] ep endpoint number
*/
void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
- SerialUSBDriver *sdup = usbp->param;
size_t n;
+ SerialUSBDriver *sdup = usbp->param;
+
+ (void)ep;
-#if 0
+ chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY);
chSysLockFromIsr();
- /* If there is any data in the output queue then it is sent within a
- single packet and the queue is emptied.*/
- n = chOQGetFullI(&sdup->oqueue);
- if (n > 0) {
+
+ if ((n = chOQGetFullI(&sdup->oqueue)) > 0) {
/* The endpoint cannot be busy, we are in the context of the callback,
so it is safe to transmit without a check.*/
chSysUnlockFromIsr();
- /* Unlocked to make the potentially long write operation preemptable.*/
- usbWritePacketBuffer(usbp, ep, sdup->oqueue.q_buffer, n);
+ usbPrepareQueuedTransmit(sdup->config->usbp,
+ USB_CDC_DATA_REQUEST_EP,
+ &sdup->oqueue, n);
chSysLockFromIsr();
- usbStartTransmitI(usbp, ep);
- chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY);
- sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer;
- sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue);
- while (notempty(&sdup->oqueue.q_waiting))
- chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK;
+ usbStartTransmitI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP);
}
+
chSysUnlockFromIsr();
-#endif
}
/**
@@ -336,33 +316,32 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
* @param[in] ep endpoint number
*/
void sduDataReceived(USBDriver *usbp, usbep_t ep) {
+ size_t n, maxsize;
SerialUSBDriver *sdup = usbp->param;
-#if 0
+ (void)ep;
+
+ chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE);
chSysLockFromIsr();
- /* Writes to the input queue can only happen when the queue has been
- emptied, then a whole packet is loaded in the queue.*/
- if (chIQIsEmptyI(&sdup->iqueue)) {
+
+ /* Writes to the input queue can only happen when there is enough space
+ to hold at least one packet.*/
+ maxsize = sdup->config->usbp->epc[USB_CDC_DATA_AVAILABLE_EP]->out_maxsize;
+ if ((n = chIQGetEmptyI(&sdup->iqueue)) >= maxsize) {
/* The endpoint cannot be busy, we are in the context of the callback,
so a packet is in the buffer for sure.*/
- size_t n;
-
chSysUnlockFromIsr();
- /* Unlocked to make the potentially long write operation preemptable.*/
- n = usbReadPacketBuffer(usbp, ep, sdup->iqueue.q_buffer,
- SERIAL_USB_BUFFERS_SIZE);
+ n = (n / maxsize) * maxsize;
+ usbPrepareQueuedReceive(sdup->config->usbp,
+ USB_CDC_DATA_AVAILABLE_EP,
+ &sdup->iqueue, n);
chSysLockFromIsr();
- usbStartReceiveI(usbp, ep);
- chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE);
- sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer;
- sdup->iqueue.q_counter = n;
- while (notempty(&sdup->iqueue.q_waiting))
- chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK;
+ usbStartReceiveI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP);
}
+
chSysUnlockFromIsr();
-#endif
}
/**