/* local data */
typedef enum {
REQ_NO_REQ,
REQ_CTRL_READ,
REQ_CTRL_WRITE,
REQ_NO_DATA_CTRL,
} REQ_NUM_T;
static REQ_NUM_T req_num = REQ_NO_REQ;
static void Control_Read( USBD_HANDLE_T hUsb, uint8_t* pData, uint16_t count )
{
((USB_CORE_CTRL_T*)hUsb)->EP0Data.pData = pData;
if ( ((USB_CORE_CTRL_T*)hUsb)->SetupPacket.wLength > HID_ReportDescSize ) {
((USB_CORE_CTRL_T*)hUsb)->EP0Data.Count = count;
}
pUsbApi->core->DataInStage( hUsb );
req_num = REQ_CTRL_READ;
}
#define REQ_TYPE( direction, type, recipient ) ((direction<<7)|(type<<5)|recipient)
#define HID_INTERFACE_NUM 0
ErrorCode_t request_Hdlr( USBD_HANDLE_T hUsb, void* data, uint32_t event )
{
USB_CORE_CTRL_T* pCtrl = (USB_CORE_CTRL_T*)hUsb;
static USB_SETUP_PACKET setup;
switch( event )
{
case USB_EVT_SETUP:
// Get SETUP packet
pUsbApi->hw->ReadSetupPkt( hUsb, USB_ENDPOINT_OUT(0), (uint32_t *)&setup );
// pick up Control Read transfer: Get_Descriptor(HID_REPORT)
pCtrl->EP0Data.Count = setup.wLength; // Number of bytes to transfer
if ( (setup.bmRequestType.B == REQ_TYPE(REQUEST_DEVICE_TO_HOST,REQUEST_STANDARD,REQUEST_TO_INTERFACE) )
&& (setup.bRequest == USB_REQUEST_GET_DESCRIPTOR )
&& (setup.wValue.W == (HID_REPORT_DESCRIPTOR_TYPE<<8) ) // descriptor type | index
&& (setup.wIndex.W == HID_INTERFACE_NUM )
// && (setup.wLength == 0 )
) {
Control_Read( hUsb, (uint8_t*)HID_ReportDescriptor, HID_ReportDescSize );
return LPC_OK;
}
// pick up Control Read transfer: GET_REPORT
if ( (setup.bmRequestType.B == REQ_TYPE(REQUEST_DEVICE_TO_HOST,REQUEST_CLASS,REQUEST_TO_INTERFACE) )
&& (setup.bRequest == HID_REQUEST_GET_REPORT )
&& (setup.wValue.W == (HID_REPORT_INPUT<<8) ) // Report type | Report ID
&& (setup.wIndex.W == HID_INTERFACE_NUM )
// && (setup.wLength == 1 )
) {
Control_Read( hUsb, &loopback_report, 1 );
return LPC_OK;
}
// pick up Control Write transfer: SET_REPORT
if ( (setup.bmRequestType.B == REQ_TYPE(REQUEST_HOST_TO_DEVICE,REQUEST_CLASS,REQUEST_TO_INTERFACE) )
&& (setup.bRequest == HID_REQUEST_SET_REPORT )
&& (setup.wValue.W == (HID_REPORT_OUTPUT<<8) ) // Report type | Report ID
&& (setup.wIndex.W == HID_INTERFACE_NUM )
&& (setup.wLength == 1 )
) {
// set a buffer to receive the data
// pCtrl->EP0Data.pData = pCtrl->EP0Buf;
pCtrl->EP0Data.pData = &loopback_report;
req_num = REQ_CTRL_WRITE;
return LPC_OK;
}
// pick up no-data Control transfer
if ( (setup.bmRequestType.B == REQ_TYPE(REQUEST_HOST_TO_DEVICE,REQUEST_CLASS,REQUEST_TO_INTERFACE) )
&& (setup.bRequest == HID_REQUEST_SET_IDLE )
&& (setup.wValue.W == 0 ) // 0 | Report ID
&& (setup.wIndex.W == HID_INTERFACE_NUM )
&& (setup.wLength == 0 )
) {
//
// process this request, here
//
if (1) { // when processed successfully,
pUsbApi->core->StatusInStage( hUsb ); // move to STATUS stage
} else {
pUsbApi->core->StallEp0( hUsb ); // reject this request
}
req_num = REQ_NO_REQ;
return LPC_OK; // The process of this request finishes by this code
}
break;
case USB_EVT_OUT:
if ( req_num == REQ_CTRL_WRITE ) {
if (pCtrl->EP0Data.Count) { // still data to receive ?
pUsbApi->core->DataOutStage( hUsb ); // receive data
}
if (pCtrl->EP0Data.Count == 0) { // data complete ?
//
// process data on the buffer, here
//
pUsbApi->core->StatusInStage( hUsb );
req_num = REQ_NO_REQ;
}
return LPC_OK;
}
break;
case USB_EVT_IN:
if ( req_num == REQ_CTRL_READ ) {
if ( pCtrl->EP0Data.Count ) {
pUsbApi->core->DataInStage( hUsb );
} else {
pUsbApi->core->StatusOutStage( hUsb );
req_num = REQ_NO_REQ;
}
return LPC_OK;
}
break;
default:
break;
}
req_num = REQ_NO_REQ;
return ERR_USBD_UNHANDLED;
}
|