USB synchronous API, to be completed.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8648 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
ae70b0edce
commit
eb0c1ac0c3
|
@ -236,6 +236,14 @@
|
||||||
/* Driver pre-compile time settings. */
|
/* Driver pre-compile time settings. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enables synchronous APIs.
|
||||||
|
* @note Disabling this option saves both code and data space.
|
||||||
|
*/
|
||||||
|
#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
|
||||||
|
#define USB_USE_WAIT TRUE
|
||||||
|
#endif
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Derived constants and error checks. */
|
/* Derived constants and error checks. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -537,10 +545,24 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
|
||||||
*
|
*
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
|
#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
|
||||||
#define _usb_isr_invoke_in_cb(usbp, ep) { \
|
#define _usb_isr_invoke_in_cb(usbp, ep) { \
|
||||||
(usbp)->transmitting &= ~(1 << (ep)); \
|
(usbp)->transmitting &= ~(1 << (ep)); \
|
||||||
|
if ((usbp)->epc[ep]->in_cb != NULL) { \
|
||||||
(usbp)->epc[ep]->in_cb(usbp, ep); \
|
(usbp)->epc[ep]->in_cb(usbp, ep); \
|
||||||
|
} \
|
||||||
|
osalSysLockFromISR(); \
|
||||||
|
osalThreadResumeI(&(usbp)->epc[ep]->in_state->thread, MSG_OK); \
|
||||||
|
osalSysUnlockFromISR(); \
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#define _usb_isr_invoke_in_cb(usbp, ep) { \
|
||||||
|
(usbp)->transmitting &= ~(1 << (ep)); \
|
||||||
|
if ((usbp)->epc[ep]->in_cb != NULL) { \
|
||||||
|
(usbp)->epc[ep]->in_cb(usbp, ep); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Common ISR code, OUT endpoint event.
|
* @brief Common ISR code, OUT endpoint event.
|
||||||
|
@ -550,10 +572,25 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
|
||||||
*
|
*
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
|
#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
|
||||||
#define _usb_isr_invoke_out_cb(usbp, ep) { \
|
#define _usb_isr_invoke_out_cb(usbp, ep) { \
|
||||||
(usbp)->receiving &= ~(1 << (ep)); \
|
(usbp)->receiving &= ~(1 << (ep)); \
|
||||||
|
if ((usbp)->epc[ep]->out_cb != NULL) { \
|
||||||
(usbp)->epc[ep]->out_cb(usbp, ep); \
|
(usbp)->epc[ep]->out_cb(usbp, ep); \
|
||||||
|
} \
|
||||||
|
osalSysLockFromISR(); \
|
||||||
|
osalThreadResumeI(&(usbp)->epc[ep]->out_state->thread, \
|
||||||
|
usbGetReceiveTransactionSizeI(usbp, ep)); \
|
||||||
|
osalSysUnlockFromISR(); \
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#define _usb_isr_invoke_out_cb(usbp, ep) { \
|
||||||
|
(usbp)->receiving &= ~(1 << (ep)); \
|
||||||
|
if ((usbp)->epc[ep]->out_cb != NULL) { \
|
||||||
|
(usbp)->epc[ep]->out_cb(usbp, ep); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -577,6 +614,10 @@ extern "C" {
|
||||||
const uint8_t *buf, size_t n);
|
const uint8_t *buf, size_t n);
|
||||||
bool usbStartReceiveI(USBDriver *usbp, usbep_t ep);
|
bool usbStartReceiveI(USBDriver *usbp, usbep_t ep);
|
||||||
bool usbStartTransmitI(USBDriver *usbp, usbep_t ep);
|
bool usbStartTransmitI(USBDriver *usbp, usbep_t ep);
|
||||||
|
#if USB_USE_WAIT == TRUE
|
||||||
|
msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n);
|
||||||
|
msg_t usbTransmit(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n);
|
||||||
|
#endif
|
||||||
bool usbStallReceiveI(USBDriver *usbp, usbep_t ep);
|
bool usbStallReceiveI(USBDriver *usbp, usbep_t ep);
|
||||||
bool usbStallTransmitI(USBDriver *usbp, usbep_t ep);
|
bool usbStallTransmitI(USBDriver *usbp, usbep_t ep);
|
||||||
void _usb_reset(USBDriver *usbp);
|
void _usb_reset(USBDriver *usbp);
|
||||||
|
|
|
@ -422,9 +422,9 @@ static void otg_epout_handler(USBDriver *usbp, usbep_t ep) {
|
||||||
osp->rxsize = osp->totsize - osp->rxsize;
|
osp->rxsize = osp->totsize - osp->rxsize;
|
||||||
osp->rxcnt = 0;
|
osp->rxcnt = 0;
|
||||||
usb_lld_prepare_receive(usbp, ep);
|
usb_lld_prepare_receive(usbp, ep);
|
||||||
chSysLockFromISR();
|
osalSysLockFromISR();
|
||||||
usb_lld_start_out(usbp, ep);
|
usb_lld_start_out(usbp, ep);
|
||||||
chSysUnlockFromISR();
|
osalSysUnlockFromISR();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* End on OUT transfer.*/
|
/* End on OUT transfer.*/
|
||||||
|
@ -1005,7 +1005,7 @@ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
|
||||||
|
|
||||||
/* OUT endpoint activation or deactivation.*/
|
/* OUT endpoint activation or deactivation.*/
|
||||||
otgp->oe[ep].DOEPTSIZ = 0;
|
otgp->oe[ep].DOEPTSIZ = 0;
|
||||||
if (usbp->epc[ep]->out_cb != NULL) {
|
if (usbp->epc[ep]->out_maxsize != 0) {
|
||||||
otgp->oe[ep].DOEPCTL = ctl | DOEPCTL_MPSIZ(usbp->epc[ep]->out_maxsize);
|
otgp->oe[ep].DOEPCTL = ctl | DOEPCTL_MPSIZ(usbp->epc[ep]->out_maxsize);
|
||||||
otgp->DAINTMSK |= DAINTMSK_OEPM(ep);
|
otgp->DAINTMSK |= DAINTMSK_OEPM(ep);
|
||||||
}
|
}
|
||||||
|
@ -1016,7 +1016,7 @@ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
|
||||||
|
|
||||||
/* IN endpoint activation or deactivation.*/
|
/* IN endpoint activation or deactivation.*/
|
||||||
otgp->ie[ep].DIEPTSIZ = 0;
|
otgp->ie[ep].DIEPTSIZ = 0;
|
||||||
if (usbp->epc[ep]->in_cb != NULL) {
|
if (usbp->epc[ep]->in_maxsize != 0) {
|
||||||
/* FIFO allocation for the IN endpoint.*/
|
/* FIFO allocation for the IN endpoint.*/
|
||||||
fsize = usbp->epc[ep]->in_maxsize / 4;
|
fsize = usbp->epc[ep]->in_maxsize / 4;
|
||||||
if (usbp->epc[ep]->in_multiplier > 1)
|
if (usbp->epc[ep]->in_multiplier > 1)
|
||||||
|
|
|
@ -226,6 +226,12 @@ typedef struct {
|
||||||
* @brief Pointer to the transmission linear buffer.
|
* @brief Pointer to the transmission linear buffer.
|
||||||
*/
|
*/
|
||||||
const uint8_t *txbuf;
|
const uint8_t *txbuf;
|
||||||
|
#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
|
||||||
|
/**
|
||||||
|
* @brief Waiting thread.
|
||||||
|
*/
|
||||||
|
thread_reference_t thread;
|
||||||
|
#endif
|
||||||
/* End of the mandatory fields.*/
|
/* End of the mandatory fields.*/
|
||||||
/**
|
/**
|
||||||
* @brief Total transmit transfer size.
|
* @brief Total transmit transfer size.
|
||||||
|
@ -249,6 +255,12 @@ typedef struct {
|
||||||
* @brief Pointer to the receive linear buffer.
|
* @brief Pointer to the receive linear buffer.
|
||||||
*/
|
*/
|
||||||
uint8_t *rxbuf;
|
uint8_t *rxbuf;
|
||||||
|
#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
|
||||||
|
/**
|
||||||
|
* @brief Waiting thread.
|
||||||
|
*/
|
||||||
|
thread_reference_t thread;
|
||||||
|
#endif
|
||||||
/* End of the mandatory fields.*/
|
/* End of the mandatory fields.*/
|
||||||
/**
|
/**
|
||||||
* @brief Total transmit transfer size.
|
* @brief Total transmit transfer size.
|
||||||
|
@ -278,14 +290,14 @@ typedef struct {
|
||||||
usbepcallback_t setup_cb;
|
usbepcallback_t setup_cb;
|
||||||
/**
|
/**
|
||||||
* @brief IN endpoint notification callback.
|
* @brief IN endpoint notification callback.
|
||||||
* @details This field must be set to @p NULL if the IN endpoint is not
|
* @details This field must can be set to @p NULL if callback is not
|
||||||
* used.
|
* required.
|
||||||
*/
|
*/
|
||||||
usbepcallback_t in_cb;
|
usbepcallback_t in_cb;
|
||||||
/**
|
/**
|
||||||
* @brief OUT endpoint notification callback.
|
* @brief OUT endpoint notification callback.
|
||||||
* @details This field must be set to @p NULL if the OUT endpoint is not
|
* @details This field must can be set to @p NULL if callback is not
|
||||||
* used.
|
* required.
|
||||||
*/
|
*/
|
||||||
usbepcallback_t out_cb;
|
usbepcallback_t out_cb;
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -345,13 +345,6 @@ void usbInitEndpointI(USBDriver *usbp, usbep_t ep,
|
||||||
osalDbgAssert(usbp->epc[ep] == NULL, "already initialized");
|
osalDbgAssert(usbp->epc[ep] == NULL, "already initialized");
|
||||||
|
|
||||||
/* Logically enabling the endpoint in the USBDriver structure.*/
|
/* Logically enabling the endpoint in the USBDriver structure.*/
|
||||||
if (epcp->in_state != NULL) {
|
|
||||||
memset(epcp->in_state, 0, sizeof(USBInEndpointState));
|
|
||||||
}
|
|
||||||
if (epcp->out_state != NULL) {
|
|
||||||
memset(epcp->out_state, 0, sizeof(USBOutEndpointState));
|
|
||||||
}
|
|
||||||
|
|
||||||
usbp->epc[ep] = epcp;
|
usbp->epc[ep] = epcp;
|
||||||
|
|
||||||
/* Low level endpoint activation.*/
|
/* Low level endpoint activation.*/
|
||||||
|
@ -399,11 +392,17 @@ void usbDisableEndpointsI(USBDriver *usbp) {
|
||||||
* @special
|
* @special
|
||||||
*/
|
*/
|
||||||
void usbPrepareReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) {
|
void usbPrepareReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) {
|
||||||
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
|
USBOutEndpointState *osp;
|
||||||
|
|
||||||
|
osalDbgCheck((usbp != NULL) && (ep <= USB_MAX_ENDPOINTS));
|
||||||
|
|
||||||
|
osp = usbp->epc[ep]->out_state;
|
||||||
osp->rxbuf = buf;
|
osp->rxbuf = buf;
|
||||||
osp->rxsize = n;
|
osp->rxsize = n;
|
||||||
osp->rxcnt = 0;
|
osp->rxcnt = 0;
|
||||||
|
#if USB_USE_WAIT == TRUE
|
||||||
|
osp->thread = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
usb_lld_prepare_receive(usbp, ep);
|
usb_lld_prepare_receive(usbp, ep);
|
||||||
}
|
}
|
||||||
|
@ -424,11 +423,17 @@ void usbPrepareReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) {
|
||||||
*/
|
*/
|
||||||
void usbPrepareTransmit(USBDriver *usbp, usbep_t ep,
|
void usbPrepareTransmit(USBDriver *usbp, usbep_t ep,
|
||||||
const uint8_t *buf, size_t n) {
|
const uint8_t *buf, size_t n) {
|
||||||
USBInEndpointState *isp = usbp->epc[ep]->in_state;
|
USBInEndpointState *isp;
|
||||||
|
|
||||||
|
osalDbgCheck((usbp != NULL) && (ep <= USB_MAX_ENDPOINTS));
|
||||||
|
|
||||||
|
isp = usbp->epc[ep]->in_state;
|
||||||
isp->txbuf = buf;
|
isp->txbuf = buf;
|
||||||
isp->txsize = n;
|
isp->txsize = n;
|
||||||
isp->txcnt = 0;
|
isp->txcnt = 0;
|
||||||
|
#if USB_USE_WAIT == TRUE
|
||||||
|
isp->thread = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
usb_lld_prepare_transmit(usbp, ep);
|
usb_lld_prepare_transmit(usbp, ep);
|
||||||
}
|
}
|
||||||
|
@ -450,7 +455,7 @@ void usbPrepareTransmit(USBDriver *usbp, usbep_t ep,
|
||||||
bool usbStartReceiveI(USBDriver *usbp, usbep_t ep) {
|
bool usbStartReceiveI(USBDriver *usbp, usbep_t ep) {
|
||||||
|
|
||||||
osalDbgCheckClassI();
|
osalDbgCheckClassI();
|
||||||
osalDbgCheck(usbp != NULL);
|
osalDbgCheck((usbp != NULL) && (ep <= USB_MAX_ENDPOINTS));
|
||||||
|
|
||||||
if (usbGetReceiveStatusI(usbp, ep)) {
|
if (usbGetReceiveStatusI(usbp, ep)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -478,7 +483,7 @@ bool usbStartReceiveI(USBDriver *usbp, usbep_t ep) {
|
||||||
bool usbStartTransmitI(USBDriver *usbp, usbep_t ep) {
|
bool usbStartTransmitI(USBDriver *usbp, usbep_t ep) {
|
||||||
|
|
||||||
osalDbgCheckClassI();
|
osalDbgCheckClassI();
|
||||||
osalDbgCheck(usbp != NULL);
|
osalDbgCheck((usbp != NULL) && (ep <= USB_MAX_ENDPOINTS));
|
||||||
|
|
||||||
if (usbGetTransmitStatusI(usbp, ep)) {
|
if (usbGetTransmitStatusI(usbp, ep)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -489,6 +494,63 @@ bool usbStartTransmitI(USBDriver *usbp, usbep_t ep) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
|
||||||
|
/**
|
||||||
|
* @brief Performs a receive transaction on an OUT endpoint.
|
||||||
|
*
|
||||||
|
* @param[in] usbp pointer to the @p USBDriver object
|
||||||
|
* @param[in] ep endpoint number
|
||||||
|
* @param[out] buf buffer where to copy the received data
|
||||||
|
* @param[in] n transaction size. It is recommended a multiple of
|
||||||
|
* the packet size because the excess is discarded.
|
||||||
|
*
|
||||||
|
* @return The received data effective size, it can be less than
|
||||||
|
* the amount specified.
|
||||||
|
* @retval MSG_RESET operation aborted by a reset.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) {
|
||||||
|
msg_t msg;
|
||||||
|
|
||||||
|
usbPrepareReceive(usbp, ep, buf, n);
|
||||||
|
|
||||||
|
osalSysLock();
|
||||||
|
usbStartReceiveI(usbp, ep);
|
||||||
|
msg = osalThreadSuspendS(&usbp->epc[ep]->out_state->thread);
|
||||||
|
osalSysUnlock();
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Performs a transmit transaction on an IN endpoint.
|
||||||
|
*
|
||||||
|
* @param[in] usbp pointer to the @p USBDriver object
|
||||||
|
* @param[in] ep endpoint number
|
||||||
|
* @param[in] buf buffer where to fetch the data to be transmitted
|
||||||
|
* @param[in] n transaction size
|
||||||
|
*
|
||||||
|
* @return The operation status.
|
||||||
|
* @retval MSG_OK operation performed successfully.
|
||||||
|
* @retval MSG_RESET operation aborted by a reset.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
msg_t usbTransmit(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n) {
|
||||||
|
msg_t msg;
|
||||||
|
|
||||||
|
usbPrepareTransmit(usbp, ep, buf, n);
|
||||||
|
|
||||||
|
osalSysLock();
|
||||||
|
usbStartReceiveI(usbp, ep);
|
||||||
|
msg = osalThreadSuspendS(&usbp->epc[ep]->in_state->thread);
|
||||||
|
osalSysUnlock();
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
#endif /* USB_USE_WAIT == TRUE */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stalls an OUT endpoint.
|
* @brief Stalls an OUT endpoint.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue