Changes to Serial_USB, unfinished.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8630 35acf78f-673a-0410-8e92-d51de3d6d3f4master
parent
7979de6953
commit
2f7be482b1
|
@ -51,7 +51,7 @@ typedef struct io_buffers_queue io_buffers_queue_t;
|
||||||
*
|
*
|
||||||
* @param[in] iodbp the buffers queue pointer
|
* @param[in] iodbp the buffers queue pointer
|
||||||
*/
|
*/
|
||||||
typedef void (*dbnotify_t)(io_buffers_queue_t *bqp);
|
typedef void (*bqnotify_t)(io_buffers_queue_t *bqp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Structure of a generic buffers queue.
|
* @brief Structure of a generic buffers queue.
|
||||||
|
@ -104,7 +104,7 @@ struct io_buffers_queue {
|
||||||
/**
|
/**
|
||||||
* @brief Data notification callback.
|
* @brief Data notification callback.
|
||||||
*/
|
*/
|
||||||
dbnotify_t notify;
|
bqnotify_t notify;
|
||||||
/**
|
/**
|
||||||
* @brief Application defined field.
|
* @brief Application defined field.
|
||||||
*/
|
*/
|
||||||
|
@ -171,7 +171,7 @@ typedef io_buffers_queue_t output_buffers_queue_t;
|
||||||
#define bqGetLinkX(bqp) ((bqp)->link)
|
#define bqGetLinkX(bqp) ((bqp)->link)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Evaluates to @p TRUE if the specified input buffered queue is empty.
|
* @brief Evaluates to @p TRUE if the specified input buffers queue is empty.
|
||||||
*
|
*
|
||||||
* @param[in] ibqp pointer to an @p input_buffers_queue_t structure
|
* @param[in] ibqp pointer to an @p input_buffers_queue_t structure
|
||||||
* @return The queue status.
|
* @return The queue status.
|
||||||
|
@ -183,7 +183,7 @@ typedef io_buffers_queue_t output_buffers_queue_t;
|
||||||
#define ibqIsEmptyI(ibqp) ((bool)(bqSpaceI(ibqp) == 0U))
|
#define ibqIsEmptyI(ibqp) ((bool)(bqSpaceI(ibqp) == 0U))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Evaluates to @p TRUE if the specified input buffered queue is full.
|
* @brief Evaluates to @p TRUE if the specified input buffers queue is full.
|
||||||
*
|
*
|
||||||
* @param[in] ibqp pointer to an @p input_buffers_queue_t structure
|
* @param[in] ibqp pointer to an @p input_buffers_queue_t structure
|
||||||
* @return The queue status.
|
* @return The queue status.
|
||||||
|
@ -194,6 +194,31 @@ typedef io_buffers_queue_t output_buffers_queue_t;
|
||||||
*/
|
*/
|
||||||
#define ibqIsFullI(ibqp) ((bool)(((ibqp)->bwrptr == (ibqp)->brdptr) && \
|
#define ibqIsFullI(ibqp) ((bool)(((ibqp)->bwrptr == (ibqp)->brdptr) && \
|
||||||
((ibqp)->bcounter != 0U)))
|
((ibqp)->bcounter != 0U)))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Evaluates to @p true if the specified output buffers queue is empty.
|
||||||
|
*
|
||||||
|
* @param[in] obqp pointer to an @p output_buffers_queue_t structure
|
||||||
|
* @return The queue status.
|
||||||
|
* @retval false if the queue is not empty.
|
||||||
|
* @retval true if the queue is empty.
|
||||||
|
*
|
||||||
|
* @iclass
|
||||||
|
*/
|
||||||
|
#define obqIsEmptyI(oqp) ((bool)(((obqp)->bwrptr == (obqp)->brdptr) && \
|
||||||
|
((obqp)->bcounter != 0U)))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Evaluates to @p true if the specified output buffers queue is full.
|
||||||
|
*
|
||||||
|
* @param[in] obqp pointer to an @p output_buffers_queue_t structure
|
||||||
|
* @return The queue status.
|
||||||
|
* @retval false if the queue is not full.
|
||||||
|
* @retval true if the queue is full.
|
||||||
|
*
|
||||||
|
* @iclass
|
||||||
|
*/
|
||||||
|
#define obqIsFullI(obqp) ((bool)(bqSpaceI(obqp) == 0U))
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -205,15 +230,30 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
void ibqObjectInit(io_buffers_queue_t *ibqp, uint8_t *bp,
|
void ibqObjectInit(io_buffers_queue_t *ibqp, uint8_t *bp,
|
||||||
size_t size, size_t n,
|
size_t size, size_t n,
|
||||||
dbnotify_t infy, void *link);
|
bqnotify_t infy, void *link);
|
||||||
void ibqResetI(input_buffers_queue_t *ibqp);
|
void ibqResetI(input_buffers_queue_t *ibqp);
|
||||||
uint8_t *ibqGetEmptyBufferI(input_buffers_queue_t *ibqp);
|
uint8_t *ibqGetEmptyBufferI(input_buffers_queue_t *ibqp);
|
||||||
void ibqPostBufferI(input_buffers_queue_t *ibqp, size_t size);
|
void ibqPostFullBufferI(input_buffers_queue_t *ibqp, size_t size);
|
||||||
msg_t ibqGetDataTimeoutI(input_buffers_queue_t *ibqp, systime_t timeout);
|
msg_t ibqGetFullBufferTimeoutS(input_buffers_queue_t *ibqp,
|
||||||
void ibqReleaseDataI(input_buffers_queue_t *ibqp);
|
systime_t timeout);
|
||||||
|
void ibqReleaseEmptyBufferI(input_buffers_queue_t *ibqp);
|
||||||
msg_t ibqGetTimeout(input_buffers_queue_t *ibqp, systime_t timeout);
|
msg_t ibqGetTimeout(input_buffers_queue_t *ibqp, systime_t timeout);
|
||||||
size_t ibqReadTimeout(input_buffers_queue_t *ibqp, uint8_t *bp,
|
size_t ibqReadTimeout(input_buffers_queue_t *ibqp, uint8_t *bp,
|
||||||
size_t n, systime_t timeout);
|
size_t n, systime_t timeout);
|
||||||
|
void obqObjectInit(output_buffers_queue_t *obqp, uint8_t *bp,
|
||||||
|
size_t size, size_t n,
|
||||||
|
bqnotify_t onfy, void *link);
|
||||||
|
void obqResetI(output_buffers_queue_t *obqp);
|
||||||
|
uint8_t *obqGetFullBufferI(output_buffers_queue_t *obqp,
|
||||||
|
size_t *sizep);
|
||||||
|
void obqReleaseEmptyBufferI(output_buffers_queue_t *obqp);
|
||||||
|
msg_t obqGetEmptyBufferTimeoutS(output_buffers_queue_t *obqp,
|
||||||
|
systime_t timeout);
|
||||||
|
void obqPostFullBufferI(output_buffers_queue_t *obqp, size_t size);
|
||||||
|
msg_t obqPutTimeout(output_buffers_queue_t *obqp, uint8_t b,
|
||||||
|
systime_t timeout);
|
||||||
|
size_t obqWriteTimeout(output_buffers_queue_t *obqp, const uint8_t *bp,
|
||||||
|
size_t n, systime_t timeout);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -121,6 +121,14 @@
|
||||||
#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
|
#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
|
||||||
#define SERIAL_USB_BUFFERS_SIZE 256
|
#define SERIAL_USB_BUFFERS_SIZE 256
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Serial over USB number of buffers.
|
||||||
|
* @note The default is 2 buffers.
|
||||||
|
*/
|
||||||
|
#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__)
|
||||||
|
#define SERIAL_USB_BUFFERS_NUMBER 2
|
||||||
|
#endif
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -192,14 +200,16 @@ typedef struct {
|
||||||
_base_asynchronous_channel_data \
|
_base_asynchronous_channel_data \
|
||||||
/* Driver state.*/ \
|
/* Driver state.*/ \
|
||||||
sdustate_t state; \
|
sdustate_t state; \
|
||||||
/* Input queue.*/ \
|
/* Input buffers queue.*/ \
|
||||||
input_queue_t iqueue; \
|
input_buffers_queue_t ibqueue; \
|
||||||
/* Output queue.*/ \
|
/* Output queue.*/ \
|
||||||
output_queue_t oqueue; \
|
output_buffers_queue_t obqueue; \
|
||||||
/* Input buffer.*/ \
|
/* Input buffer.*/ \
|
||||||
uint8_t ib[SERIAL_USB_BUFFERS_SIZE]; \
|
uint8_t ib[BQ_BUFFER_SIZE(SERIAL_USB_BUFFERS_NUMBER, \
|
||||||
|
SERIAL_USB_BUFFERS_SIZE)]; \
|
||||||
/* Output buffer.*/ \
|
/* Output buffer.*/ \
|
||||||
uint8_t ob[SERIAL_USB_BUFFERS_SIZE]; \
|
uint8_t ob[BQ_BUFFER_SIZE(SERIAL_USB_BUFFERS_NUMBER, \
|
||||||
|
SERIAL_USB_BUFFERS_SIZE)]; \
|
||||||
/* End of the mandatory fields.*/ \
|
/* End of the mandatory fields.*/ \
|
||||||
/* Current configuration data.*/ \
|
/* Current configuration data.*/ \
|
||||||
const SerialUSBConfig *config;
|
const SerialUSBConfig *config;
|
||||||
|
|
|
@ -49,10 +49,9 @@
|
||||||
/**
|
/**
|
||||||
* @brief Initializes an input buffers queue object.
|
* @brief Initializes an input buffers queue object.
|
||||||
*
|
*
|
||||||
* @param[out] ibqp pointer to the @p io_buffers_queue_t object
|
* @param[out] ibqp pointer to the @p input_buffers_queue_t object
|
||||||
* @param[in] bp pointer to a memory area allocated for buffers
|
* @param[in] bp pointer to a memory area allocated for buffers
|
||||||
* @param[in] size buffer size, including the size field which is the
|
* @param[in] size buffers size
|
||||||
* size of a @p size_t
|
|
||||||
* @param[in] n number of buffers
|
* @param[in] n number of buffers
|
||||||
* @param[in] infy callback called when a buffer is returned to the queue
|
* @param[in] infy callback called when a buffer is returned to the queue
|
||||||
* @param[in] link application defined pointer
|
* @param[in] link application defined pointer
|
||||||
|
@ -61,16 +60,16 @@
|
||||||
*/
|
*/
|
||||||
void ibqObjectInit(input_buffers_queue_t *ibqp, uint8_t *bp,
|
void ibqObjectInit(input_buffers_queue_t *ibqp, uint8_t *bp,
|
||||||
size_t size, size_t n,
|
size_t size, size_t n,
|
||||||
dbnotify_t infy, void *link) {
|
bqnotify_t infy, void *link) {
|
||||||
|
|
||||||
osalDbgCheck((ibqp != NULL) && (bp != NULL) && (size >= sizeof(size_t) + 2));
|
osalDbgCheck((ibqp != NULL) && (bp != NULL) && (size >= 2));
|
||||||
|
|
||||||
osalThreadQueueObjectInit(&ibqp->waiting);
|
osalThreadQueueObjectInit(&ibqp->waiting);
|
||||||
ibqp->bcounter = 0;
|
ibqp->bcounter = 0;
|
||||||
ibqp->brdptr = bp;
|
ibqp->brdptr = bp;
|
||||||
ibqp->bwrptr = bp;
|
ibqp->bwrptr = bp;
|
||||||
ibqp->btop = bp + (size * n); /* Pre-calculated for speed. */
|
ibqp->btop = bp + ((size + sizeof (size_t)) * n);
|
||||||
ibqp->bsize = size;
|
ibqp->bsize = size + sizeof (size_t);
|
||||||
ibqp->bn = n;
|
ibqp->bn = n;
|
||||||
ibqp->buffers = bp;
|
ibqp->buffers = bp;
|
||||||
ibqp->ptr = NULL;
|
ibqp->ptr = NULL;
|
||||||
|
@ -124,14 +123,14 @@ uint8_t *ibqGetEmptyBufferI(input_buffers_queue_t *ibqp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Posts a new filled buffer in the queue.
|
* @brief Posts a new filled buffer to the queue.
|
||||||
*
|
*
|
||||||
* @param[in] ibqp pointer to the @p input_buffers_queue_t object
|
* @param[in] ibqp pointer to the @p input_buffers_queue_t object
|
||||||
* @param[in] size used size of the buffer
|
* @param[in] size used size of the buffer
|
||||||
*
|
*
|
||||||
* @iclass
|
* @iclass
|
||||||
*/
|
*/
|
||||||
void ibqPostBufferI(input_buffers_queue_t *ibqp, size_t size) {
|
void ibqPostFullBufferI(input_buffers_queue_t *ibqp, size_t size) {
|
||||||
|
|
||||||
osalDbgCheckClassI();
|
osalDbgCheckClassI();
|
||||||
osalDbgAssert(!ibqIsFullI(ibqp), "buffers queue full");
|
osalDbgAssert(!ibqIsFullI(ibqp), "buffers queue full");
|
||||||
|
@ -151,7 +150,7 @@ void ibqPostBufferI(input_buffers_queue_t *ibqp, size_t size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the next data-filled buffer from the queue.
|
* @brief Gets the next filled buffer from the queue.
|
||||||
* @note The function always acquires the same buffer if called repeatedly.
|
* @note The function always acquires the same buffer if called repeatedly.
|
||||||
* @post After calling the function the fields @p ptr and @p top are set
|
* @post After calling the function the fields @p ptr and @p top are set
|
||||||
* at beginning and end of the buffer data or @NULL if the queue
|
* at beginning and end of the buffer data or @NULL if the queue
|
||||||
|
@ -168,11 +167,12 @@ void ibqPostBufferI(input_buffers_queue_t *ibqp, size_t size) {
|
||||||
* @retval MSG_TIMEOUT if the specified time expired.
|
* @retval MSG_TIMEOUT if the specified time expired.
|
||||||
* @retval MSG_RESET if the queue has been reset.
|
* @retval MSG_RESET if the queue has been reset.
|
||||||
*
|
*
|
||||||
* @iclass
|
* @sclass
|
||||||
*/
|
*/
|
||||||
msg_t ibqGetDataTimeoutI(input_buffers_queue_t *ibqp, systime_t timeout) {
|
msg_t ibqGetFullBufferTimeoutS(input_buffers_queue_t *ibqp,
|
||||||
|
systime_t timeout) {
|
||||||
|
|
||||||
osalDbgCheckClassI();
|
osalDbgCheckClassS();
|
||||||
|
|
||||||
while (ibqIsEmptyI(ibqp)) {
|
while (ibqIsEmptyI(ibqp)) {
|
||||||
msg_t msg = osalThreadEnqueueTimeoutS(&ibqp->waiting, timeout);
|
msg_t msg = osalThreadEnqueueTimeoutS(&ibqp->waiting, timeout);
|
||||||
|
@ -189,14 +189,14 @@ msg_t ibqGetDataTimeoutI(input_buffers_queue_t *ibqp, systime_t timeout) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Releases the data buffer back in the queue.
|
* @brief Releases the buffer back in the queue.
|
||||||
* @note The object callback is called after releasing the buffer.
|
* @note The object callback is called after releasing the buffer.
|
||||||
*
|
*
|
||||||
* @param[out] ibqp pointer to the @p input_buffers_queue_t object
|
* @param[in] ibqp pointer to the @p input_buffers_queue_t object
|
||||||
*
|
*
|
||||||
* @iclass
|
* @iclass
|
||||||
*/
|
*/
|
||||||
void ibqReleaseDataI(input_buffers_queue_t *ibqp) {
|
void ibqReleaseEmptyBufferI(input_buffers_queue_t *ibqp) {
|
||||||
|
|
||||||
osalDbgCheckClassI();
|
osalDbgCheckClassI();
|
||||||
osalDbgAssert(!ibqIsEmptyI(ibqp), "buffers queue empty");
|
osalDbgAssert(!ibqIsEmptyI(ibqp), "buffers queue empty");
|
||||||
|
@ -238,10 +238,13 @@ void ibqReleaseDataI(input_buffers_queue_t *ibqp) {
|
||||||
msg_t ibqGetTimeout(input_buffers_queue_t *ibqp, systime_t timeout) {
|
msg_t ibqGetTimeout(input_buffers_queue_t *ibqp, systime_t timeout) {
|
||||||
msg_t msg;
|
msg_t msg;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
/* This condition indicates that a new buffer must be acquired.*/
|
/* This condition indicates that a new buffer must be acquired.*/
|
||||||
if (ibqp->ptr == NULL) {
|
if (ibqp->ptr == NULL) {
|
||||||
msg = ibqGetDataTimeoutI(ibqp, timeout);
|
msg = ibqGetFullBufferTimeoutS(ibqp, timeout);
|
||||||
if (msg != MSG_OK) {
|
if (msg != MSG_OK) {
|
||||||
|
chSysUnlock();
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -253,9 +256,11 @@ msg_t ibqGetTimeout(input_buffers_queue_t *ibqp, systime_t timeout) {
|
||||||
/* If the current buffer has been fully read then it is returned as
|
/* If the current buffer has been fully read then it is returned as
|
||||||
empty in the queue.*/
|
empty in the queue.*/
|
||||||
if (ibqp->ptr >= ibqp->top) {
|
if (ibqp->ptr >= ibqp->top) {
|
||||||
ibqReleaseDataI(ibqp);
|
ibqReleaseEmptyBufferI(ibqp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,11 +307,13 @@ size_t ibqReadTimeout(input_buffers_queue_t *ibqp, uint8_t *bp,
|
||||||
in this case next becomes a very high number because the system
|
in this case next becomes a very high number because the system
|
||||||
time is an unsigned type.*/
|
time is an unsigned type.*/
|
||||||
if (next_timeout > timeout) {
|
if (next_timeout > timeout) {
|
||||||
|
osalSysUnlock();
|
||||||
return MSG_TIMEOUT;
|
return MSG_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg_t msg = ibqGetDataTimeoutI(ibqp, next_timeout);
|
msg_t msg = ibqGetFullBufferTimeoutS(ibqp, next_timeout);
|
||||||
if (msg != MSG_OK) {
|
if (msg != MSG_OK) {
|
||||||
|
osalSysUnlock();
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,7 +337,309 @@ size_t ibqReadTimeout(input_buffers_queue_t *ibqp, uint8_t *bp,
|
||||||
|
|
||||||
/* Has the current data buffer been finished? if so then release it.*/
|
/* Has the current data buffer been finished? if so then release it.*/
|
||||||
if (ibqp->ptr >= ibqp->top) {
|
if (ibqp->ptr >= ibqp->top) {
|
||||||
ibqReleaseDataI(ibqp);
|
ibqReleaseEmptyBufferI(ibqp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
osalSysUnlock();
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes an output buffers queue object.
|
||||||
|
*
|
||||||
|
* @param[out] obqp pointer to the @p output_buffers_queue_t object
|
||||||
|
* @param[in] bp pointer to a memory area allocated for buffers
|
||||||
|
* @param[in] size buffers size
|
||||||
|
* @param[in] n number of buffers
|
||||||
|
* @param[in] onfy callback called when a buffer is posted in the queue
|
||||||
|
* @param[in] link application defined pointer
|
||||||
|
*
|
||||||
|
* @init
|
||||||
|
*/
|
||||||
|
void obqObjectInit(output_buffers_queue_t *obqp, uint8_t *bp,
|
||||||
|
size_t size, size_t n,
|
||||||
|
bqnotify_t onfy, void *link) {
|
||||||
|
|
||||||
|
osalDbgCheck((obqp != NULL) && (bp != NULL) && (size >= 2));
|
||||||
|
|
||||||
|
osalThreadQueueObjectInit(&obqp->waiting);
|
||||||
|
obqp->bcounter = n;
|
||||||
|
obqp->brdptr = bp;
|
||||||
|
obqp->bwrptr = bp;
|
||||||
|
obqp->btop = bp + ((size + sizeof (size_t)) * n);
|
||||||
|
obqp->bsize = size + sizeof (size_t);
|
||||||
|
obqp->bn = n;
|
||||||
|
obqp->buffers = bp;
|
||||||
|
obqp->ptr = NULL;
|
||||||
|
obqp->top = NULL;
|
||||||
|
obqp->notify = onfy;
|
||||||
|
obqp->link = link;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resets an output buffers queue.
|
||||||
|
* @details All the data in the output buffers queue is erased and lost, any
|
||||||
|
* waiting thread is resumed with status @p MSG_RESET.
|
||||||
|
* @note A reset operation can be used by a low level driver in order to
|
||||||
|
* obtain immediate attention from the high level layers.
|
||||||
|
*
|
||||||
|
* @param[in] obqp pointer to the @p output_buffers_queue_t object
|
||||||
|
*
|
||||||
|
* @iclass
|
||||||
|
*/
|
||||||
|
void obqResetI(output_buffers_queue_t *obqp) {
|
||||||
|
|
||||||
|
osalDbgCheckClassI();
|
||||||
|
|
||||||
|
obqp->bcounter = bqSizeX(obqp);
|
||||||
|
obqp->brdptr = obqp->buffers;
|
||||||
|
obqp->bwrptr = obqp->buffers;
|
||||||
|
obqp->ptr = NULL;
|
||||||
|
obqp->top = NULL;
|
||||||
|
osalThreadDequeueAllI(&obqp->waiting, MSG_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the next filled buffer from the queue.
|
||||||
|
* @note The function always returns the same buffer if called repeatedly.
|
||||||
|
*
|
||||||
|
* @param[in] obqp pointer to the @p output_buffers_queue_t object
|
||||||
|
* @param[out] sizep pointer to the filled buffer size
|
||||||
|
* @return A pointer to the filled buffer.
|
||||||
|
* @retval NULL if the queue is empty.
|
||||||
|
*
|
||||||
|
* @iclass
|
||||||
|
*/
|
||||||
|
uint8_t *obqGetFullBufferI(output_buffers_queue_t *obqp,
|
||||||
|
size_t *sizep) {
|
||||||
|
|
||||||
|
osalDbgCheckClassI();
|
||||||
|
|
||||||
|
if (obqIsEmptyI(obqp)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buffer size.*/
|
||||||
|
*sizep = *((size_t *)obqp->brdptr);
|
||||||
|
|
||||||
|
return obqp->brdptr + sizeof (size_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Releases the next filled buffer back in the queue.
|
||||||
|
*
|
||||||
|
* @param[in] obqp pointer to the @p output_buffers_queue_t object
|
||||||
|
*
|
||||||
|
* @iclass
|
||||||
|
*/
|
||||||
|
void obqReleaseEmptyBufferI(output_buffers_queue_t *obqp) {
|
||||||
|
|
||||||
|
osalDbgCheckClassI();
|
||||||
|
osalDbgAssert(!obqIsEmptyI(obqp), "buffers queue empty");
|
||||||
|
|
||||||
|
/* Freeing a buffer slot in the queue.*/
|
||||||
|
obqp->bcounter++;
|
||||||
|
obqp->brdptr += obqp->bsize;
|
||||||
|
if (obqp->brdptr >= obqp->btop) {
|
||||||
|
obqp->brdptr = obqp->buffers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the next empty buffer from the queue.
|
||||||
|
* @note The function always acquires the same buffer if called repeatedly.
|
||||||
|
* @post After calling the function the fields @p ptr and @p top are set
|
||||||
|
* at beginning and end of the buffer data or @NULL if the queue
|
||||||
|
* is empty.
|
||||||
|
*
|
||||||
|
* @param[in] obqp pointer to the @p output_buffers_queue_t object
|
||||||
|
* @param[in] timeout the number of ticks before the operation timeouts,
|
||||||
|
* the following special values are allowed:
|
||||||
|
* - @a TIME_IMMEDIATE immediate timeout.
|
||||||
|
* - @a TIME_INFINITE no timeout.
|
||||||
|
* .
|
||||||
|
* @return The operation status.
|
||||||
|
* @retval MSG_OK if a buffer has been acquired.
|
||||||
|
* @retval MSG_TIMEOUT if the specified time expired.
|
||||||
|
* @retval MSG_RESET if the queue has been reset.
|
||||||
|
*
|
||||||
|
* @sclass
|
||||||
|
*/
|
||||||
|
msg_t obqGetEmptyBufferTimeoutS(output_buffers_queue_t *obqp,
|
||||||
|
systime_t timeout) {
|
||||||
|
|
||||||
|
osalDbgCheckClassS();
|
||||||
|
|
||||||
|
while (obqIsEmptyI(obqp)) {
|
||||||
|
msg_t msg = osalThreadEnqueueTimeoutS(&obqp->waiting, timeout);
|
||||||
|
if (msg < MSG_OK) {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setting up the "current" buffer and its boundary.*/
|
||||||
|
obqp->ptr = obqp->brdptr + sizeof (size_t);
|
||||||
|
obqp->top = obqp->ptr + *((size_t *)obqp->brdptr);
|
||||||
|
|
||||||
|
return MSG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Posts a new filled buffer to the queue.
|
||||||
|
* @note The object callback is called after releasing the buffer.
|
||||||
|
*
|
||||||
|
* @param[in] obqp pointer to the @p output_buffers_queue_t object
|
||||||
|
* @param[in] size used size of the buffer
|
||||||
|
*
|
||||||
|
* @iclass
|
||||||
|
*/
|
||||||
|
void obqPostFullBufferI(output_buffers_queue_t *obqp, size_t size) {
|
||||||
|
|
||||||
|
osalDbgCheckClassI();
|
||||||
|
osalDbgAssert(!obqIsFullI(obqp), "buffers queue full");
|
||||||
|
|
||||||
|
/* Writing size field in the buffer.*/
|
||||||
|
*((size_t *)obqp->bwrptr) = size;
|
||||||
|
|
||||||
|
/* Posting the buffer in the queue.*/
|
||||||
|
obqp->bcounter--;
|
||||||
|
obqp->bwrptr += obqp->bsize;
|
||||||
|
if (obqp->bwrptr >= obqp->btop) {
|
||||||
|
obqp->bwrptr = obqp->buffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No "current" buffer.*/
|
||||||
|
obqp->ptr = NULL;
|
||||||
|
|
||||||
|
/* Notifying the buffer release.*/
|
||||||
|
if (obqp->notify != NULL) {
|
||||||
|
obqp->notify(obqp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Output queue write with timeout.
|
||||||
|
* @details This function writes a byte value to an output queue. If
|
||||||
|
* the queue is full then the calling thread is suspended until a
|
||||||
|
* new buffer is freed in the queue or a timeout occurs.
|
||||||
|
*
|
||||||
|
* @param[in] obqp pointer to the @p output_buffers_queue_t object
|
||||||
|
* @param[in] timeout the number of ticks before the operation timeouts,
|
||||||
|
* the following special values are allowed:
|
||||||
|
* - @a TIME_IMMEDIATE immediate timeout.
|
||||||
|
* - @a TIME_INFINITE no timeout.
|
||||||
|
* .
|
||||||
|
* @return A byte value from the queue.
|
||||||
|
* @retval MSG_TIMEOUT if the specified time expired.
|
||||||
|
* @retval MSG_RESET if the queue has been reset.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
msg_t obqPutTimeout(output_buffers_queue_t *obqp, uint8_t b,
|
||||||
|
systime_t timeout) {
|
||||||
|
msg_t msg;
|
||||||
|
|
||||||
|
osalSysLock();
|
||||||
|
|
||||||
|
/* This condition indicates that a new buffer must be acquired.*/
|
||||||
|
if (obqp->ptr == NULL) {
|
||||||
|
msg = obqGetEmptyBufferTimeoutS(obqp, timeout);
|
||||||
|
if (msg != MSG_OK) {
|
||||||
|
chSysUnlock();
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Writing the byte to the buffer.*/
|
||||||
|
obqp->bcounter--;
|
||||||
|
*obqp->bwrptr++ = b;
|
||||||
|
|
||||||
|
/* If the current buffer has been fully written then it is posted as
|
||||||
|
full in the queue.*/
|
||||||
|
if (obqp->ptr >= obqp->top) {
|
||||||
|
obqPostFullBufferI(obqp, obqp->bsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
osalSysUnlock();
|
||||||
|
|
||||||
|
return MSG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Output queue write with timeout.
|
||||||
|
* @details The function writes data from a buffer to an output queue. The
|
||||||
|
* operation completes when the specified amount of data has been
|
||||||
|
* transferred or after the specified timeout or if the queue has
|
||||||
|
* been reset.
|
||||||
|
* @note The function is not atomic, if you need atomicity it is suggested
|
||||||
|
* to use a semaphore or a mutex for mutual exclusion.
|
||||||
|
*
|
||||||
|
* @param[in] obqp pointer to the @p output_buffers_queue_t object
|
||||||
|
* @param[in] bp pointer to the data buffer
|
||||||
|
* @param[in] n the maximum amount of data to be transferred, the
|
||||||
|
* value 0 is reserved
|
||||||
|
* @param[in] timeout the number of ticks before the operation timeouts,
|
||||||
|
* the following special values are allowed:
|
||||||
|
* - @a TIME_IMMEDIATE immediate timeout.
|
||||||
|
* - @a TIME_INFINITE no timeout.
|
||||||
|
* .
|
||||||
|
* @return The number of bytes effectively transferred.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
size_t obqWriteTimeout(output_buffers_queue_t *obqp, const uint8_t *bp,
|
||||||
|
size_t n, systime_t timeout) {
|
||||||
|
size_t r = 0;
|
||||||
|
systime_t deadline;
|
||||||
|
|
||||||
|
osalSysLock();
|
||||||
|
|
||||||
|
/* Time window for the whole operation.*/
|
||||||
|
deadline = osalOsGetSystemTimeX() + timeout;
|
||||||
|
|
||||||
|
while (r < n) {
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
/* This condition indicates that a new buffer must be acquired.*/
|
||||||
|
if (obqp->ptr == NULL) {
|
||||||
|
systime_t next_timeout = deadline - osalOsGetSystemTimeX();
|
||||||
|
|
||||||
|
/* Handling the case where the system time went past the deadline,
|
||||||
|
in this case next becomes a very high number because the system
|
||||||
|
time is an unsigned type.*/
|
||||||
|
if (next_timeout > timeout) {
|
||||||
|
osalSysUnlock();
|
||||||
|
return MSG_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg_t msg = obqGetEmptyBufferTimeoutS(obqp, next_timeout);
|
||||||
|
if (msg != MSG_OK) {
|
||||||
|
osalSysUnlock();
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Size of the space available in the current buffer.*/
|
||||||
|
size = obqp->top - obqp->ptr;
|
||||||
|
if (size > n - r) {
|
||||||
|
size = n - r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copying the chunk into the read buffer, the operation is performed
|
||||||
|
outside the critical zone.*/
|
||||||
|
osalSysUnlock();
|
||||||
|
memcpy(obqp->ptr, bp, size);
|
||||||
|
osalSysLock();
|
||||||
|
|
||||||
|
/* Updating the pointers and the counter.*/
|
||||||
|
r += size;
|
||||||
|
bp += size;
|
||||||
|
obqp->ptr += size;
|
||||||
|
|
||||||
|
/* Has the current data buffer been finished? if so then release it.*/
|
||||||
|
if (obqp->ptr >= obqp->top) {
|
||||||
|
obqPostFullBufferI(obqp, obqp->bsize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
osalSysUnlock();
|
osalSysUnlock();
|
||||||
|
|
|
@ -59,7 +59,7 @@ static size_t write(void *ip, const uint8_t *bp, size_t n) {
|
||||||
if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
|
if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return oqWriteTimeout(&((SerialUSBDriver *)ip)->oqueue, bp,
|
return obqWriteTimeout(&((SerialUSBDriver *)ip)->obqueue, bp,
|
||||||
n, TIME_INFINITE);
|
n, TIME_INFINITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ static size_t read(void *ip, uint8_t *bp, size_t n) {
|
||||||
if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
|
if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return iqReadTimeout(&((SerialUSBDriver *)ip)->iqueue, bp,
|
return ibqReadTimeout(&((SerialUSBDriver *)ip)->ibqueue, bp,
|
||||||
n, TIME_INFINITE);
|
n, TIME_INFINITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ static msg_t put(void *ip, uint8_t b) {
|
||||||
if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
|
if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
|
||||||
return MSG_RESET;
|
return MSG_RESET;
|
||||||
|
|
||||||
return oqPutTimeout(&((SerialUSBDriver *)ip)->oqueue, b, TIME_INFINITE);
|
return obqPutTimeout(&((SerialUSBDriver *)ip)->obqueue, b, TIME_INFINITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static msg_t get(void *ip) {
|
static msg_t get(void *ip) {
|
||||||
|
@ -85,7 +85,7 @@ static msg_t get(void *ip) {
|
||||||
if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
|
if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
|
||||||
return MSG_RESET;
|
return MSG_RESET;
|
||||||
|
|
||||||
return iqGetTimeout(&((SerialUSBDriver *)ip)->iqueue, TIME_INFINITE);
|
return ibqGetTimeout(&((SerialUSBDriver *)ip)->ibqueue, TIME_INFINITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static msg_t putt(void *ip, uint8_t b, systime_t timeout) {
|
static msg_t putt(void *ip, uint8_t b, systime_t timeout) {
|
||||||
|
@ -93,7 +93,7 @@ static msg_t putt(void *ip, uint8_t b, systime_t timeout) {
|
||||||
if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
|
if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
|
||||||
return MSG_RESET;
|
return MSG_RESET;
|
||||||
|
|
||||||
return oqPutTimeout(&((SerialUSBDriver *)ip)->oqueue, b, timeout);
|
return obqPutTimeout(&((SerialUSBDriver *)ip)->obqueue, b, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static msg_t gett(void *ip, systime_t timeout) {
|
static msg_t gett(void *ip, systime_t timeout) {
|
||||||
|
@ -101,7 +101,7 @@ static msg_t gett(void *ip, systime_t timeout) {
|
||||||
if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
|
if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
|
||||||
return MSG_RESET;
|
return MSG_RESET;
|
||||||
|
|
||||||
return iqGetTimeout(&((SerialUSBDriver *)ip)->iqueue, timeout);
|
return ibqGetTimeout(&((SerialUSBDriver *)ip)->ibqueue, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t timeout) {
|
static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t timeout) {
|
||||||
|
@ -109,7 +109,7 @@ static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t timeout) {
|
||||||
if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
|
if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return oqWriteTimeout(&((SerialUSBDriver *)ip)->oqueue, bp, n, timeout);
|
return obqWriteTimeout(&((SerialUSBDriver *)ip)->obqueue, bp, n, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t timeout) {
|
static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t timeout) {
|
||||||
|
@ -117,7 +117,7 @@ static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t timeout) {
|
||||||
if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
|
if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return iqReadTimeout(&((SerialUSBDriver *)ip)->iqueue, bp, n, timeout);
|
return ibqReadTimeout(&((SerialUSBDriver *)ip)->ibqueue, bp, n, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct SerialUSBDriverVMT vmt = {
|
static const struct SerialUSBDriverVMT vmt = {
|
||||||
|
@ -126,13 +126,12 @@ static const struct SerialUSBDriverVMT vmt = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Notification of data removed from the input queue.
|
* @brief Notification of empty buffer released into the input buffers queue.
|
||||||
*
|
*
|
||||||
* @param[in] qp the queue pointer.
|
* @param[in] bqp the buffers queue pointer.
|
||||||
*/
|
*/
|
||||||
static void inotify(io_queue_t *qp) {
|
static void ibnotify(io_buffers_queue_t *bqp) {
|
||||||
size_t n, maxsize;
|
SerialUSBDriver *sdup = bqGetLinkX(bqp);
|
||||||
SerialUSBDriver *sdup = qGetLink(qp);
|
|
||||||
|
|
||||||
/* If the USB driver is not in the appropriate state then transactions
|
/* If the USB driver is not in the appropriate state then transactions
|
||||||
must not be started.*/
|
must not be started.*/
|
||||||
|
@ -141,18 +140,16 @@ static void inotify(io_queue_t *qp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there is in the queue enough space to hold at least one packet and
|
/* Checking if there is already a transaction ongoing on the endpoint.*/
|
||||||
a transaction is not yet started then a new transaction is started for
|
|
||||||
the available space.*/
|
|
||||||
maxsize = sdup->config->usbp->epc[sdup->config->bulk_out]->out_maxsize;
|
|
||||||
if (!usbGetReceiveStatusI(sdup->config->usbp, sdup->config->bulk_out)) {
|
if (!usbGetReceiveStatusI(sdup->config->usbp, sdup->config->bulk_out)) {
|
||||||
if ((n = iqGetEmptyI(&sdup->iqueue)) >= maxsize) {
|
/* Trying to get a free buffer.*/
|
||||||
|
uint8_t *buf = ibqGetEmptyBufferI(&sdup->ibqueue);
|
||||||
|
if (buf != NULL) {
|
||||||
|
/* Buffer found, starting a new transaction.*/
|
||||||
osalSysUnlock();
|
osalSysUnlock();
|
||||||
|
|
||||||
n = (n / maxsize) * maxsize;
|
usbPrepareReceive(sdup->config->usbp, sdup->config->bulk_out,
|
||||||
usbPrepareQueuedReceive(sdup->config->usbp,
|
buf, SERIAL_USB_BUFFERS_SIZE);
|
||||||
sdup->config->bulk_out,
|
|
||||||
&sdup->iqueue, n);
|
|
||||||
|
|
||||||
osalSysLock();
|
osalSysLock();
|
||||||
(void) usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out);
|
(void) usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out);
|
||||||
|
@ -161,13 +158,13 @@ static void inotify(io_queue_t *qp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Notification of data inserted into the output queue.
|
* @brief Notification of filled buffer inserted into the output buffers queue.
|
||||||
*
|
*
|
||||||
* @param[in] qp the queue pointer.
|
* @param[in] bqp the buffers queue pointer.
|
||||||
*/
|
*/
|
||||||
static void onotify(io_queue_t *qp) {
|
static void obnotify(io_buffers_queue_t *bqp) {
|
||||||
size_t n;
|
size_t n;
|
||||||
SerialUSBDriver *sdup = qGetLink(qp);
|
SerialUSBDriver *sdup = bqGetLinkX(bqp);
|
||||||
|
|
||||||
/* If the USB driver is not in the appropriate state then transactions
|
/* If the USB driver is not in the appropriate state then transactions
|
||||||
must not be started.*/
|
must not be started.*/
|
||||||
|
@ -176,15 +173,15 @@ static void onotify(io_queue_t *qp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there is not an ongoing transaction and the output queue contains
|
/* Checking if there is already a transaction ongoing on the endpoint.*/
|
||||||
data then a new transaction is started.*/
|
|
||||||
if (!usbGetTransmitStatusI(sdup->config->usbp, sdup->config->bulk_in)) {
|
if (!usbGetTransmitStatusI(sdup->config->usbp, sdup->config->bulk_in)) {
|
||||||
if ((n = oqGetFullI(&sdup->oqueue)) > 0U) {
|
/* Trying to get a full buffer.*/
|
||||||
|
uint8_t *buf = obqGetFullBufferI(&sdup->obqueue, &n);
|
||||||
|
if (buf != NULL) {
|
||||||
|
/* Buffer found, starting a new transaction.*/
|
||||||
osalSysUnlock();
|
osalSysUnlock();
|
||||||
|
|
||||||
usbPrepareQueuedTransmit(sdup->config->usbp,
|
usbPrepareTransmit(sdup->config->usbp, sdup->config->bulk_in, buf, n);
|
||||||
sdup->config->bulk_in,
|
|
||||||
&sdup->oqueue, n);
|
|
||||||
|
|
||||||
osalSysLock();
|
osalSysLock();
|
||||||
(void) usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in);
|
(void) usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in);
|
||||||
|
@ -220,8 +217,12 @@ void sduObjectInit(SerialUSBDriver *sdup) {
|
||||||
sdup->vmt = &vmt;
|
sdup->vmt = &vmt;
|
||||||
osalEventObjectInit(&sdup->event);
|
osalEventObjectInit(&sdup->event);
|
||||||
sdup->state = SDU_STOP;
|
sdup->state = SDU_STOP;
|
||||||
iqObjectInit(&sdup->iqueue, sdup->ib, SERIAL_USB_BUFFERS_SIZE, inotify, sdup);
|
ibqObjectInit(&sdup->ibqueue, sdup->ib,
|
||||||
oqObjectInit(&sdup->oqueue, sdup->ob, SERIAL_USB_BUFFERS_SIZE, onotify, sdup);
|
SERIAL_USB_BUFFERS_SIZE, SERIAL_USB_BUFFERS_NUMBER,
|
||||||
|
ibnotify, sdup);
|
||||||
|
obqObjectInit(&sdup->obqueue, sdup->ob,
|
||||||
|
SERIAL_USB_BUFFERS_SIZE, SERIAL_USB_BUFFERS_NUMBER,
|
||||||
|
obnotify, sdup);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -295,8 +296,8 @@ void sduDisconnectI(SerialUSBDriver *sdup) {
|
||||||
|
|
||||||
/* Queues reset in order to signal the driver stop to the application.*/
|
/* Queues reset in order to signal the driver stop to the application.*/
|
||||||
chnAddFlagsI(sdup, CHN_DISCONNECTED);
|
chnAddFlagsI(sdup, CHN_DISCONNECTED);
|
||||||
iqResetI(&sdup->iqueue);
|
ibqResetI(&sdup->ibqueue);
|
||||||
iqResetI(&sdup->oqueue);
|
obqResetI(&sdup->obqueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -307,16 +308,22 @@ void sduDisconnectI(SerialUSBDriver *sdup) {
|
||||||
* @iclass
|
* @iclass
|
||||||
*/
|
*/
|
||||||
void sduConfigureHookI(SerialUSBDriver *sdup) {
|
void sduConfigureHookI(SerialUSBDriver *sdup) {
|
||||||
USBDriver *usbp = sdup->config->usbp;
|
uint8_t *buf;
|
||||||
|
|
||||||
iqResetI(&sdup->iqueue);
|
ibqResetI(&sdup->ibqueue);
|
||||||
oqResetI(&sdup->oqueue);
|
obqResetI(&sdup->obqueue);
|
||||||
chnAddFlagsI(sdup, CHN_CONNECTED);
|
chnAddFlagsI(sdup, CHN_CONNECTED);
|
||||||
|
|
||||||
/* Starts the first OUT transaction immediately.*/
|
/* Starts the first OUT transaction immediately.*/
|
||||||
usbPrepareQueuedReceive(usbp, sdup->config->bulk_out, &sdup->iqueue,
|
buf = ibqGetEmptyBufferI(&sdup->ibqueue);
|
||||||
usbp->epc[sdup->config->bulk_out]->out_maxsize);
|
|
||||||
(void) usbStartReceiveI(usbp, sdup->config->bulk_out);
|
osalDbgAssert(buf != NULL, "no free buffer");
|
||||||
|
|
||||||
|
usbPrepareReceive(sdup->config->usbp, sdup->config->bulk_out,
|
||||||
|
buf, SERIAL_USB_BUFFERS_SIZE);
|
||||||
|
// usbPrepareQueuedReceive(usbp, sdup->config->bulk_out, &sdup->iqueue,
|
||||||
|
// usbp->epc[sdup->config->bulk_out]->out_maxsize);
|
||||||
|
(void) usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -364,6 +371,7 @@ bool sduRequestsHook(USBDriver *usbp) {
|
||||||
* @param[in] ep endpoint number
|
* @param[in] ep endpoint number
|
||||||
*/
|
*/
|
||||||
void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
|
void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
|
||||||
|
uint8_t *buf;
|
||||||
size_t n;
|
size_t n;
|
||||||
SerialUSBDriver *sdup = usbp->in_params[ep - 1U];
|
SerialUSBDriver *sdup = usbp->in_params[ep - 1U];
|
||||||
|
|
||||||
|
@ -372,8 +380,33 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
|
||||||
}
|
}
|
||||||
|
|
||||||
osalSysLockFromISR();
|
osalSysLockFromISR();
|
||||||
|
|
||||||
|
/* Signaling that space is available in the output queue.*/
|
||||||
chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY);
|
chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY);
|
||||||
|
|
||||||
|
/* Freeing the buffer just transmitted.*/
|
||||||
|
obqReleaseEmptyBufferI(&sdup->obqueue);
|
||||||
|
|
||||||
|
/* Checking if there is a buffer ready for transmission.*/
|
||||||
|
buf = obqGetFullBufferI(&sdup->obqueue, &n);
|
||||||
|
if (buf != NULL) {
|
||||||
|
/* The endpoint cannot be busy, we are in the context of the callback,
|
||||||
|
so it is safe to transmit without a check.*/
|
||||||
|
osalSysUnlockFromISR();
|
||||||
|
|
||||||
|
usbPrepareTransmit(usbp, ep, buf, n);
|
||||||
|
|
||||||
|
osalSysLockFromISR();
|
||||||
|
(void) usbStartTransmitI(usbp, ep);
|
||||||
|
osalSysUnlockFromISR();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There could be a partial buffer being filled, special case.*/
|
||||||
|
/* TODO */
|
||||||
|
#error "SERIAL USB UNDERGOING CHANGES, NOT FINISHED YET"
|
||||||
|
|
||||||
|
#if 0
|
||||||
/*lint -save -e9013 [15.7] There is no else because it is not needed.*/
|
/*lint -save -e9013 [15.7] There is no else because it is not needed.*/
|
||||||
if ((n = oqGetFullI(&sdup->oqueue)) > 0U) {
|
if ((n = oqGetFullI(&sdup->oqueue)) > 0U) {
|
||||||
/* The endpoint cannot be busy, we are in the context of the callback,
|
/* The endpoint cannot be busy, we are in the context of the callback,
|
||||||
|
@ -402,6 +435,7 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
|
||||||
/*lint -restore*/
|
/*lint -restore*/
|
||||||
|
|
||||||
osalSysUnlockFromISR();
|
osalSysUnlockFromISR();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -413,7 +447,7 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
|
||||||
* @param[in] ep endpoint number
|
* @param[in] ep endpoint number
|
||||||
*/
|
*/
|
||||||
void sduDataReceived(USBDriver *usbp, usbep_t ep) {
|
void sduDataReceived(USBDriver *usbp, usbep_t ep) {
|
||||||
size_t n, maxsize;
|
uint8_t *buf;
|
||||||
SerialUSBDriver *sdup = usbp->out_params[ep - 1U];
|
SerialUSBDriver *sdup = usbp->out_params[ep - 1U];
|
||||||
|
|
||||||
if (sdup == NULL) {
|
if (sdup == NULL) {
|
||||||
|
@ -421,8 +455,32 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) {
|
||||||
}
|
}
|
||||||
|
|
||||||
osalSysLockFromISR();
|
osalSysLockFromISR();
|
||||||
|
|
||||||
|
/* Signaling that data is available in the input queue.*/
|
||||||
chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE);
|
chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE);
|
||||||
|
|
||||||
|
/* Posting the filled buffer in the queue.*/
|
||||||
|
ibqPostFullBufferI(&sdup->ibqueue,
|
||||||
|
usbGetReceiveTransactionSizeI(sdup->config->usbp,
|
||||||
|
sdup->config->bulk_out));
|
||||||
|
|
||||||
|
/* The endpoint cannot be busy, we are in the context of the callback,
|
||||||
|
so a packet is in the buffer for sure. Trying to get a free buffer
|
||||||
|
for the next transaction.*/
|
||||||
|
buf = ibqGetEmptyBufferI(&sdup->ibqueue);
|
||||||
|
if (buf != NULL) {
|
||||||
|
/* Buffer found, starting a new transaction.*/
|
||||||
|
osalSysUnlockFromISR();
|
||||||
|
|
||||||
|
usbPrepareReceive(sdup->config->usbp, sdup->config->bulk_out,
|
||||||
|
buf, SERIAL_USB_BUFFERS_SIZE);
|
||||||
|
|
||||||
|
osalSysLockFromISR();
|
||||||
|
(void) usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out);
|
||||||
|
}
|
||||||
|
osalSysUnlockFromISR();
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Writes to the input queue can only happen when there is enough space
|
/* Writes to the input queue can only happen when there is enough space
|
||||||
to hold at least one packet.*/
|
to hold at least one packet.*/
|
||||||
maxsize = usbp->epc[ep]->out_maxsize;
|
maxsize = usbp->epc[ep]->out_maxsize;
|
||||||
|
@ -438,6 +496,7 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) {
|
||||||
(void) usbStartReceiveI(usbp, ep);
|
(void) usbStartReceiveI(usbp, ep);
|
||||||
}
|
}
|
||||||
osalSysUnlockFromISR();
|
osalSysUnlockFromISR();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue