📄 usbs_upd985xx.c
字号:
}
}
// An endpoint 0 receive has completed. This could be a new control
// message. Or it could be the data for a previous control message. Or
// it could be a new control message when expecting the data from
// a previous one. The ep0.rx_expecting_data field indicates
// whether or not a new control message is expected.
//
// At times an interrupt triggers and there is an rx indication for a
// zero-byte transfer. Such a transfer may be followed immediately by
// a real transfer. It is not understood why the zero-byte transfer
// occurs. They are ignored by the drain_rx_mailbox() code, to make
// sure that there is at most one valid rx indicator at a time.
static void
ep0_rx_dsr(void)
{
// Start by checking the rx indicator to make sure that a packet
// really has been received.
if (!ep0.rx_indicator_valid) {
drain_rx_mailbox();
if (!ep0.rx_indicator_valid) {
// Do not assert, in case of a spurious interrupt for a
// zero-byte transfer.
return;
}
}
// We have a valid receive, with the data held in uncached->ep0_rx_buffer.
// Are we expecting the remaining data of a control transfer?
if (ep0.rx_expecting_data) {
// Was this data interrupted by a new setup packet?
if (0 != (ep0.rx_indicator.status & RXMBOX_STATUS_SETUP_SETUP)) {
// NOTE: it is not clear from the documentation exactly what
// happens here, e.g. is it guaranteed that the new control
// packet appears at the start of the buffer rather than
// after any data previously received? Given typical
// USB host-side implementations this scenario is considered
// sufficiently unlikely that no further investigation has
// been carried out.
// Inform higher-level code that the receive has been aborted.
if ((usbs_control_return (*)(usbs_control_endpoint*, int)) 0 != ep0.common.complete_fn) {
(*ep0.common.complete_fn)(&ep0.common, -EIO);
}
ep0.rx_expecting_data = false;
ep0.common.buffer = (unsigned char*) 0;
ep0.common.buffer_size = 0;
ep0.common.fill_buffer_fn = 0;
ep0.common.complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, int)) 0;
// Fall through the main control message handling code below.
} else {
// Data was expected and received. Transfer the data to the
// user's buffer, and perform completion.
usbs_control_return result;
cyg_uint32 size = ep0.rx_indicator.status & RXMBOX_STATUS_SIZE_MASK;
CYG_ASSERT( (usbs_control_return (*)(usbs_control_endpoint*, int))0 != ep0.common.complete_fn, \
"A completion function should be provided for OUT control messages");
CYG_ASSERT(size == ep0.common.buffer_size, "Inconsistency between buffer and transfer sizes");
memcpy(ep0.common.buffer, uncached->ep0_rx_buffer, size);
result = (*ep0.common.complete_fn)(&ep0.common, 0);
ep0.common.buffer = (unsigned char*) 0;
ep0.common.buffer_size = 0;
ep0.common.complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, int)) 0;
ep0.rx_expecting_data = false;
// Start another receive for the next control message.
// Note that there has been a window where there was no receive
// in progress for endpoint 0, even though according to the
// USB spec a device must always be able to accept new
// control messages.
ep0_start_rx(8);
return;
}
}
// When we get here we should have an eight-byte control message
// in uncached->ep0_rx_buffer. This should get moved into
// the ep0.common.control_buffer so that higher-level code sees
// it in the appropriate location.
CYG_ASSERT((ep0.rx_indicator.address == &(uncached->ep0_rx_bufdescs[0])) || \
(ep0.rx_indicator.address == &(uncached->ep0_rx_bufdescs[2])), \
"Received ep0 data should involve the ep0 rx buffer descriptor");
CYG_ASSERT(8 == (ep0.rx_indicator.status & RXMBOX_STATUS_SIZE_MASK), "Control messages should be 8 bytes");
memcpy(ep0.common.control_buffer, uncached->ep0_rx_buffer, 8);
// If we have received a control packet then any reset signals really
// will have come from the host and must be processed normally.
// Make sure that reset interrupts are no longer masked off.
if (0 == (*USBS_IMR2 & IBUS_SWAP32(USBS_GSR2_URST))) {
*USBS_IMR2 |= IBUS_SWAP32(USBS_GSR2_URST); FLUSH_IBUS();
usbs_upd985xx_gsr2_mask |= USBS_GSR2_URST;
}
{
usbs_control_return result = USBS_CONTROL_RETURN_UNKNOWN;
usb_devreq* req = (usb_devreq*) ep0.common.control_buffer;
int length, direction, protocol, recipient;
// Now we need to do some decoding of the data. A non-zero
// length field indicates that there will be a subsequent
// IN or OUT phase. The direction is controlled by the
// top bit of the first byte. The protocol is determined
// by other bits of the top byte.
length = (req->length_hi << 8) | req->length_lo;
direction = req->type & USB_DEVREQ_DIRECTION_MASK;
protocol = req->type & USB_DEVREQ_TYPE_MASK;
recipient = req->type & USB_DEVREQ_RECIPIENT_MASK;
DBG(("ep0, new control request: type %x, code %x\n", req->type, req->request));
DBG((" %s, length %d, value hi %x lo %x, index hi %x lo %x\n",
(USB_DEVREQ_DIRECTION_OUT == direction) ? "out" : "in",
length, req->value_hi, req->value_lo, req->index_hi, req->index_lo));
if (USB_DEVREQ_TYPE_STANDARD == protocol) {
// First see if the request can be handled entirely in
// this module.
if (USB_DEVREQ_SET_ADDRESS == req->request) {
// The USB device address should be in value_lo.
// No more data is expected.
int old_state = ep0.common.state;
int address = req->value_lo;
if ((0 != length) || (address > 127)) {
result = USBS_CONTROL_RETURN_STALL;
} else {
*USBS_GMR = (*USBS_GMR & ~(USBS_GMR_FA_MASK | USBS_GMR_VT)) | (address << USBS_GMR_FA_SHIFT); FLUSH_IBUS();
result = USBS_CONTROL_RETURN_HANDLED;
}
// Switch to addressed state, informing higher-level
// code of this.
if (USBS_STATE_ADDRESSED != (old_state & USBS_STATE_MASK)) {
ep0.common.state = USBS_STATE_ADDRESSED;
if ((void (*)(usbs_control_endpoint*, void*, usbs_state_change, int))0 != ep0.common.state_change_fn) {
(*ep0.common.state_change_fn)(&ep0.common, ep0.common.state_change_data,
USBS_STATE_CHANGE_ADDRESSED, old_state);
}
}
// End of SET_ADDRESS handling
} else if (USB_DEVREQ_GET_STATUS == req->request) {
// GET_STATUS on the device as a whole is used to
// check the remote-wakeup and self-powered bits.
// GET_STATUS on an endpoint is used to determine
// the halted condition.
// GET_STATUS on anything else has to be left to
// other code.
if (USB_DEVREQ_RECIPIENT_DEVICE == recipient) {
// The host should expect two bytes back.
if ((2 == length) && (USB_DEVREQ_DIRECTION_IN == direction)) {
ep0.common.control_buffer[0] = 0; // Not self-powered, no remote wakeup
ep0.common.control_buffer[1] = 0;
ep0.common.buffer = ep0.common.control_buffer;
ep0.common.buffer_size = 2;
result = USBS_CONTROL_RETURN_HANDLED;
} else {
result = USBS_CONTROL_RETURN_STALL;
}
} else if (USB_DEVREQ_RECIPIENT_ENDPOINT == recipient) {
if ((2 == length) && (USB_DEVREQ_DIRECTION_IN == direction)) {
int endpoint = req->index_lo;
if (0 == endpoint) {
// get-status on endpoint 0 is either undefined or always valid.
// endpoint 0 is always up.
ep0.common.control_buffer[0] = 0;
result = USBS_CONTROL_RETURN_HANDLED;
}
#ifdef CYGPKG_DEVS_USB_UPD985XX_EP3
else if (((USB_DEVREQ_INDEX_DIRECTION_IN | 3) == endpoint) &&
(USBS_STATE_CONFIGURED == (ep0.common.state & USBS_STATE_MASK))) {
ep0.common.control_buffer[0] = ep3.common.halted;
result = USBS_CONTROL_RETURN_HANDLED;
}
#endif
#ifdef CYGPKG_DEVS_USB_UPD985XX_EP4
else if (((USB_DEVREQ_INDEX_DIRECTION_OUT | 4) == endpoint) &&
(USBS_STATE_CONFIGURED == (ep0.common.state & USBS_STATE_MASK))) {
ep0.common.control_buffer[0] = ep4.common.halted;
result = USBS_CONTROL_RETURN_HANDLED;
}
#endif
#ifdef CYGPKG_DEVS_USB_UPD985XX_EP5
else if (((USB_DEVREQ_INDEX_DIRECTION_IN | 5) == endpoint) &&
(USBS_STATE_CONFIGURED == (ep0.common.state & USBS_STATE_MASK))) {
ep0.common.control_buffer[0] = ep5.common.halted;
result = USBS_CONTROL_RETURN_HANDLED;
}
#endif
else {
// An invalid endpoint has been specified or the
// endpoint can only be examined in configured state.
result = USBS_CONTROL_RETURN_STALL;
}
if (USBS_CONTROL_RETURN_HANDLED == result) {
ep0.common.control_buffer[1] = 0;
ep0.common.buffer = ep0.common.control_buffer;
ep0.common.buffer_size = 2;
}
} else {
result = USBS_CONTROL_RETURN_STALL;
}
} // Endpoint or device get-status
} else if (USB_DEVREQ_CLEAR_FEATURE == req->request) {
// CLEAR_FEATURE operates in much the same way as
// GET_STATUS
if (USB_DEVREQ_RECIPIENT_DEVICE == recipient) {
// No data should be transferred, and only remote-wakeup can be cleared.
if ((0 != length) || (USB_DEVREQ_FEATURE_DEVICE_REMOTE_WAKEUP != req->value_lo)) {
result = USBS_CONTROL_RETURN_STALL;
} else {
// Clearing remote-wakeup is a no-op.
result = USBS_CONTROL_RETURN_HANDLED;
}
} else if (USB_DEVREQ_RECIPIENT_ENDPOINT == recipient) {
// The only feature that can be cleared is endpoint-halt, no data should be transferred.
if ((0 != length) || (USB_DEVREQ_FEATURE_ENDPOINT_HALT != req->value_lo)) {
result = USBS_CONTROL_RETURN_STALL;
} else {
int endpoint = req->index_lo;
if (0 == endpoint) {
// Clearing halt on endpoint 0 is always a no-op since that endpoint cannot be halted
}
#ifdef CYGPKG_DEVS_USB_UPD985XX_EP3
else if (((USB_DEVREQ_INDEX_DIRECTION_IN | 3) == endpoint) &&
(USBS_STATE_CONFIGURED == (ep0.common.state & USBS_STATE_MASK))) {
ep3_set_halted(&ep3.common, false);
result = USBS_CONTROL_RETURN_HANDLED;
}
#endif
#ifdef CYGPKG_DEVS_USB_UPD985XX_EP4
else if (((USB_DEVREQ_INDEX_DIRECTION_OUT | 4) == endpoint) &&
(USBS_STATE_CONFIGURED == (ep0.common.state & USBS_STATE_MASK))) {
ep4_set_halted(&ep4.common, false);
result = USBS_CONTROL_RETURN_HANDLED;
}
#endif
#ifdef CYGPKG_DEVS_USB_UPD985XX_EP5
else if (((USB_DEVREQ_INDEX_DIRECTION_IN | 5) == endpoint) &&
(USBS_STATE_CONFIGURED == (ep0.common.state & USBS_STATE_MASK))) {
ep5_set_halted(&ep5.common, false);
result = USBS_CONTROL_RETURN_HANDLED;
}
#endif
else {
// Invalid endpoint or not in configured state.
result = USBS_CONTROL_RETURN_STALL;
}
}
} // Endpoing or device clear-feature
} else if (USB_DEVREQ_SET_FEATURE == req->request) {
// SET_FEATURE also operates in much the same way as
// GET_STATUS
if (USB_DEVREQ_RECIPIENT_DEVICE == recipient) {
// The only valid feature that can be set is remote-wakeup,
// which is not supported by this driver.
result = USBS_CONTROL_RETURN_STALL;
} else if (USB_DEVREQ_RECIPIENT_ENDPOINT == recipient) {
// Only the halt condition can be set, and no data should be transferred.
// Halting endpoint 0 should probably be disallowed although the
// standard does not explicitly say so.
if ((0 != length) ||
(USB_DEVREQ_FEATURE_ENDPOINT_HALT != req->value_lo) ||
(USBS_STATE_CONFIGURED != (ep0.common.state & USBS_STATE_MASK))) {
result = USBS_CONTROL_RETURN_STALL;
} else {
int endpoint = req->index_lo;
if (0) {
}
#ifdef CYGPKG_DEVS_USB_UPD985XX_EP3
else if ((USB_DEVREQ_INDEX_DIRECTION_IN | 3) == endpoint) {
ep3_set_halted(&ep3.common, true);
result = USBS_CONTROL_RETURN_HANDLED;
}
#endif
#ifdef CYGPKG_DEVS_USB_UPD985XX_EP4
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -