📄 ncdevice.c
字号:
// - Advanced devices supporting more than configurations zero and one must
// trap and handle standard requests for: Get Descriptor (Configuration)
// and Set Configuration
PrivDeviceObject->EventCode = NC_DEVICE_EVENT_SET_CONFIGURATION;
*NcStatus = PrivDeviceObject->DeviceEventHandler(PrivDeviceObject);
if ((*NcStatus == NCSTATUS_SUCCESS) || (*NcStatus == NCSTATUS_MORE_PROCESSING_REQUIRED))
{ // Requested configuration is acceptable
*NcStatus = NCSTATUS_SUCCESS;
return;
}
// Requested configuration is NOT acceptable
// - Artificially deconfigure the device
WVALUE_LO = 0;
NcApi_SetConfiguration(PrivDeviceObject);
default:
break;
}
break;
case HOST_TO_DEVICE | STANDARD | RECIPIENT_INTERFACE:
switch (BREQUEST)
{
case CLEAR_FEATURE:
// Feature not supported - add code if desired
break;
case SET_FEATURE:
// Feature not supported - add code if desired
break;
case SET_INTERFACE:
// Default Set Interface handler
// - Simple devices supporting a single interface can let this section
// handle Set Interface requests.
// - See USB 2.0: 9.4.10
// - See also GET_INTERFACE
NCDEBUG(sprintf(SetupPacket_Msg, "SET_INTERFACE: %d AltSetting:%d", WINDEX, WVALUE);)
// Assert: This default Set Interface handler is restricted to configurations
// with a single interface. Clients supporting multiple interfaces should
// trap and parse Set (and Get) Interface requests. See USB 9.4.10
ASSERT(UsbConfiguration->bNumInterfaces == 1);
if ((WVALUE == 0x0000) && (WINDEX == 0x0000))
{ // Alternate setting zero on interface zero
// - Request accepted
// - Nothing else to do!
return;
}
// Request failed
// - Requested interface does not exist in this simple (single interface) configuration
break;
default:
break;
}
break;
case HOST_TO_DEVICE | STANDARD | RECIPIENT_ENDPOINT:
Endpoint = NcApi_FindUsbEp(WINDEX_LO);
if (Endpoint == NULL)
{ // No logical endpoint matching USB endpoint found!
break;
}
switch (BREQUEST)
{
case CLEAR_FEATURE:
case SET_FEATURE:
// Clear Endpoint Feature
if (WVALUE != ENDPOINT_STALL)
{ // Expected wValue to be ENDPOINT_STALL
break;
}
// Set or clear the Endpoint Stall on endpoint specified by wIndex
// Tip: This call may change Page Select
Endpoint->Stall = (BREQUEST == SET_FEATURE)? TRUE: FALSE;
NcApi_EpStall(Endpoint);
Endpoint->EventCode = NC_ENDPOINT_EVENT_SET_CLEAR_STALL;
ASSERT(Endpoint->EndpointEventHandler != NULL);
Endpoint->EndpointEventHandler(Endpoint);
NCDEBUG(sprintf(SetupPacket_Msg, "SET/CLR_FEATURE(STALL): USB Ep:%2.2x)", WINDEX_LO);)
return;
case SYNCH_FRAME:
// Feature not supported - add code if desired
break;
default:
break;
}
break;
case DEVICE_TO_HOST | STANDARD | RECIPIENT_DEVICE:
switch (BREQUEST)
{
case GET_STATUS:
// Get Status (DEVICE)
// - Bit 1: Remote Wakeup enable
// - Bit 0: Currently Self Powered (Important: USB 9.4.5 and Table 9-10 (bmAttributes)
// - See USB 2.0: 9.2.5.2, 9.4.5, table 9-4
if (PrivDeviceObject->HostWakeupEnable)
{ // This device has its remote host wakeup capability enabled
// - Tip: A device with remote wakeup capability may NOT actually
// apply remote wakeup unless specifically enabled by the host
// - Notify host that the device's remote wakeup capability is enabled
lewStatus.Byte[LITTLEEND_LO] = 0x02;
// Assert: A device that does not report Remote Wakeup capability in its
// configuration cannot have have its wakeup capability enabled!
ASSERT(UsbConfiguration->bmAttributes & (1<<5));
}
else
{ // Device does NOT have its host wakeup capability enabled
lewStatus.Byte[LITTLEEND_LO] = 0x00;
}
if (UsbConfiguration->bmAttributes & (1<<6))
{ // The current configuration indicates device is self-powered:
// - A self-powered device does not draw any power from USB, so bMaxPower in
// the Configuration should be zero UNLESS the device can *dynamically*
// switch power sources...
// Assert: This implementation assumes fixed power source policy. Devices that
// can dynamically change power source between bus and self-powered should:
// - Set the Self Powered bit (bit 6) in bmAttributes TRUE (See USB 2.0: Table 9-10)
// - Set bMaxPower to an appropriate non-zero value (See USB 2.0: Table 9-10)
// - Install a Setup Request handler to handle this Get Status (DEVICE) request,
// correctly reporting its power source (self or bus powered)
ASSERT(UsbConfiguration->bMaxPower == 0);
// Indicate device is currently self-powered
lewStatus.Byte[LITTLEEND_LO] |= 0x01;
}
NC_EP0_TRANSFER(&lewStatus, sizeof(lewStatus));
NCDEBUG(sprintf(SetupPacket_Msg, "GET_STATUS [DEVICE]: %4.4x", lewStatus.Word);)
return;
case GET_CONFIGURATION:
// Return the current configuration number
// - USB 2.0: 9.4.2: Length of the data phase for Get Configuration is one
NC_EP0_TRANSFER(&PrivDeviceObject->UsbConfigurationNumber, 1);
NCDEBUG(sprintf(SetupPacket_Msg, SetupPacket_LengthFormat, "GET_CONFIGURATION", 1);)
return;
case GET_DESCRIPTOR:
switch (WVALUE_HI)
{ // High byte of wValue specifies the descriptor type (RECIPIENT_DEVICE, CONFIGURATION, STRING, etc.)
case DEVICE_DESC:
// "Get Device Descriptor" request
ASSERT(PrivDeviceObject->DeviceDescriptor != NULL);
ASSERT(PrivDeviceObject->DeviceDescriptor->bLength == sizeof(USB_DEVICE_DESCRIPTOR));
Length = min(WLENGTH, sizeof(USB_DEVICE_DESCRIPTOR));
NC_EP0_TRANSFER(PrivDeviceObject->DeviceDescriptor, Length)
NCDEBUG(sprintf(SetupPacket_Msg, SetupPacket_LengthFormat, "GET_DESCRIPTOR [DEVICE]", Length);)
return;
case DEVICE_QUALIFIER_DESC:
// "Get Device Qualifier Descriptor" request
ASSERT(PrivDeviceObject->DeviceQualifierDescriptor != NULL);
ASSERT(PrivDeviceObject->DeviceQualifierDescriptor->bLength == sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR));
Length = min(WLENGTH, sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR));
NC_EP0_TRANSFER(PrivDeviceObject->DeviceQualifierDescriptor, Length);
NCDEBUG(sprintf(SetupPacket_Msg, SetupPacket_LengthFormat, "GET_DESCRIPTOR [DEVICE_QUALIFIER]", Length);)
return;
case CONFIGURATION_DESC:
// "Get Configuration" request
// - The Get Configuration request returns the entire configuration: the Configuration
// descriptor, all its Interface descriptors and all its Endpoint desciptors
NcApi_UpdateHsFsConfigurations(PrivDeviceObject);
ASSERT(UsbConfiguration != NULL);
ASSERT(UsbConfiguration->bDescriptorType == CONFIGURATION_DESC);
Length = min(WLENGTH, Sizeof_UsbConfiguration.Word);
NC_EP0_TRANSFER(UsbConfiguration, Length);
NCDEBUG(sprintf(SetupPacket_Msg, SetupPacket_LengthFormat, "GET_DESCRIPTOR [CONFIGURATION]", Length);)
return;
case OTHER_SPEED_CONFIGURATION_DESC:
// "Get Other Speed Configuration Descriptor" request
// - The Get Other Speed Configuration request returns the entire configuration: the Configuration
// descriptor, all its Interface descriptors and all its Endpoint desciptors
NcApi_UpdateHsFsConfigurations(PrivDeviceObject);
ASSERT(UsbConfiguration_OtherSpeed != NULL);
ASSERT(UsbConfiguration_OtherSpeed->bDescriptorType == OTHER_SPEED_CONFIGURATION_DESC);
Length = min(WLENGTH, Sizeof_UsbConfiguration_OtherSpeed.Word);
NC_EP0_TRANSFER(UsbConfiguration_OtherSpeed, Length);
NCDEBUG(sprintf(SetupPacket_Msg, SetupPacket_LengthFormat, "GET_DESCRIPTOR [OTHER_SPEED_CONFIGURATION]", Length);)
return;
case STRING_DESC:
// "Get String Descriptor" request
if ((WVALUE_LO < NCAPI_MAX_USB_STRINGS) && (UsbStrings[WVALUE_LO] != NULL))
{ //
Length = min(UsbStrings[WVALUE_LO]->bLength, WLENGTH);
NC_EP0_TRANSFER(UsbStrings[WVALUE_LO], Length);
NCDEBUG(sprintf(SetupPacket_Msg, SetupPacket_LengthFormat, "GET_DESCRIPTOR [STRING]", Length);)
return;
}
break;
default:
break;
}
break;
default:
break;
}
break;
case DEVICE_TO_HOST | STANDARD | RECIPIENT_INTERFACE:
switch (BREQUEST)
{
case GET_STATUS:
// Return interface status
// - Always zero. See USB 2.0: 9.4.5 (fig 9-5)
NC_EP0_TRANSFER(&lewStatus, WLENGTH);
NCDEBUG(sprintf(SetupPacket_Msg, "GET_STATUS: [INTERFACE]: %4.4x", lewStatus.Word);)
return;
case GET_INTERFACE:
// NetChip's firmware model allows for projects with different interface requirements:
// - The API default Get Interface handler can handle simple devices with a single interface
// - Client's with complex interfaces should specify their own interface handler
// - See USB 2.0: 9.4.4
// - See also SET_INTERFACE
NCPRINTFCOND(VOLUME_MINIMUM, WLENGTH != 1, ("GET_INTERFACE: Warning: Unexpected wLength value\n"));
// Assert: This default Get Interface handler is restricted to configurations
// with a single interface. Clients supporting multiple interfaces should
// install their own Get (and Set) Interface request handler. See USB 9.4.4
ASSERT(UsbConfiguration->bNumInterfaces == 1);
if (WINDEX == 0x0000)
{ // Host requested alternate setting for interface zero
// - Alternate setting for simple device is zero
ASSERT(lewStatus.Word == 0)
NC_EP0_TRANSFER(&lewStatus, 1);
return;
}
// Request failed
// - Requested interface does not exist in this simple (single interface) configuration
break;
default:
break;
}
break;
case DEVICE_TO_HOST | STANDARD | RECIPIENT_ENDPOINT:
switch (BREQUEST)
{
case GET_STATUS:
// Return status of endpoint specified in wIndex
Endpoint = NcApi_FindUsbEp(WINDEX_LO);
if (Endpoint == NULL)
{ // No logical endpoint matching USB endpoint found!
break;
}
#if _NCVIRTUALIZEENDPOINTS
lewStatus.Byte[LITTLEEND_LO] = (BYTE)(Endpoint->Priv.EpRsp & (1<<ENDPOINT_HALT));
#else
NETCHIP_WRITE(PAGESEL, Endpoint->Priv.PhysEp);
lewStatus.Byte[LITTLEEND_LO] = (BYTE)(NETCHIP_READ(EP_RSPSET) & (1<<ENDPOINT_HALT));
#endif
NC_EP0_TRANSFER(&lewStatus, sizeof(lewStatus));
NCDEBUG(sprintf(SetupPacket_Msg, "GET_STATUS: USB Ep:%2.2x: %4.4x", WINDEX_LO, lewStatus.Word);)
return;
default:
break;
}
break;
default:
break;
}
// Parse failed
// - The host's setup request is not known
*NcStatus = NCSTATUS_UNSUCCESSFUL;
}
///////////////////////////////////////////////////////////////////////////////
STATIC void
EpZero_SetupPhase(
void
)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -