I m stuck with a problem related to winusbReadpipe function. I m using Pic18f4550 Mc(XC8 Compiler) and VC ++ 2013 (MFC).
I my just trying to read and write to/from Device /Host. The sample Programme provide by Microchip is working fine and I am able to send Data to all Endpoints 01, 02, 03 in Device from Host.
However I am unable to read any feedback from Device to Host. I’m reading and writing data in two separate threads. My idea is to just read feedback of Button pressed in My demo board or at least an echo back command. It seems ,it just enter once in read function and then get stalled. Not Sure about this.
I tried searching over internet and implemented all suggestion given in Different forums but till date no success. worst is I m trying to post my query on Microchip forum but could not get myself registered , it always says administrator will approve my id but nothing has happened yet.
Below is my code both Device side and Host Side. Pls tell me if anything else is required from my side.
I look forwad for your support on this .
Thanks,
Rahul
VC++ code:
Read Thread Code
UINT CUsbHighSpeedDlg::ReadThread()
{
while (true)
{
if (AttachedState == TRUE) //Do not try to use the read/write handles unless the USB device is attached and ready
{
m_DebugVal7.SetWindowTextW(TEXT("INSIDE read //pipe"));
WinUsb_ReadPipe(MyWinUSBInterfaceHandle, 0x81, &INBuffer[0], 64, &BytesRead, NULL);
if (INBuffer[0] = 0x81)
{
m_DebugVal5.SetWindowTextW(TEXT("button true"));
}
if ((INBuffer[0] = 0x81) && (INBuffer[1] = 0x00))
{
PushbuttonPressed = TRUE;
m_DebugVal5.SetWindowTextW(TEXT("button true"));
}
if ((INBuffer[0] = 0x81) && (INBuffer[1] = 0x01))
{
PushbuttonPressed = FALSE;
m_DebugVal6.SetWindowTextW(TEXT("button False"));
}
}
} return 0;
}
Header files declared in VC++ for using read/writepipe function
//WinUsb_Initialize() needs to be called before the application can begin sending/receiving data with the USB device.
[DllImport("Winusb.dll", CharSet = CharSet::Seeifdef, EntryPoint = "WinUsb_Initialize", CallingConvention = CallingConvention::Winapi)]
BOOL __stdcall WinUsb_Initialize(
_In_ HANDLE DeviceHandle,
_Out_ PWINUSB_INTERFACE_HANDLE InterfaceHandle
);
//WinUsb_WritePipe() is the basic function used to write data to the USB device (sends data to OUT endpoints on the device)
[DllImport("winusb.dll", CharSet = CharSet::Seeifdef, EntryPoint = "WinUsb_WritePipe", CallingConvention = CallingConvention::Winapi)]
BOOL __stdcall WinUsb_WritePipe(
_In_ WINUSB_INTERFACE_HANDLE InterfaceHandle,
_In_ UCHAR PipeID,
_In_ PUCHAR Buffer,
_In_ ULONG BufferLength,
_Out_opt_ PULONG LengthTransferred,
_In_opt_ LPOVERLAPPED Overlapped
);
//WinUsb_ReadPipe() is the basic function used to read data from the USB device (polls for and obtains data from
//IN endpoints on the device)
[DllImport("winusb.dll", CharSet = CharSet::Seeifdef, EntryPoint = "WinUsb_ReadPipe", CallingConvention = CallingConvention::Winapi)]
BOOL __stdcall WinUsb_ReadPipe(
_In_ WINUSB_INTERFACE_HANDLE InterfaceHandle,
_In_ UCHAR PipeID,
_Out_ PUCHAR Buffer,
_In_ ULONG BufferLength,
_Out_opt_ PULONG LengthTransferred,
_In_opt_ LPOVERLAPPED Overlapped
);
//WinUsb_SetPipePolicy() can be used to configure the behavior of the WinUSB use of the specified endpoint
[DllImport("winusb.dll", CharSet = CharSet::Seeifdef, EntryPoint = "WinUsb_SetPipePolicy", CallingConvention = CallingConvention::Winapi)]
BOOL __stdcall WinUsb_SetPipePolicy(
_In_ WINUSB_INTERFACE_HANDLE InterfaceHandle,
_In_ UCHAR PipeID,
_In_ ULONG PolicyType,
_In_ ULONG ValueLength,
_In_ PVOID Value
);
//WinUsb_Free() is used to free up resources/close the handle that was returned when calling WinUsb_Initialize()
[DllImport("winusb.dll", CharSet = CharSet::Seeifdef, EntryPoint = "WinUsb_Free", CallingConvention = CallingConvention::Winapi)]
BOOL __stdcall WinUsb_Free(
_In_ WINUSB_INTERFACE_HANDLE InterfaceHandle
);
//WinUsb_FlushPipe() is used to discard any data that may be "cached in a pipe".
[DllImport("winusb.dll", CharSet = CharSet::Seeifdef, EntryPoint = "WinUsb_Free", CallingConvention = CallingConvention::Winapi)]
BOOL __stdcall WinUsb_FlushPipe(
_In_ WINUSB_INTERFACE_HANDLE InterfaceHandle,
_In_ UCHAR PipeID
);
Microcontroller code
Variable declaration Section
#elif defined(__XC8) && defined(FIXED_ADDRESS_MEMORY)
USB_VOLATILE uint8_t EP1OUTEvenBuffer[64] @ EP1_EVEN_DATA_BUFFER_ADDRESS;
USB_VOLATILE uint8_t EP1OUTOddBuffer[64] @ EP1_ODD_DATA_BUFFER_ADDRESS;
USB_VOLATILE uint8_t EP2OUTEvenBuffer[64] @ EP2_EVEN_DATA_BUFFER_ADDRESS;
USB_VOLATILE uint8_t EP2OUTOddBuffer[64] @ EP2_ODD_DATA_BUFFER_ADDRESS;
USB_VOLATILE uint8_t EP3OUTEvenBuffer[64] @ EP3_EVEN_DATA_BUFFER_ADDRESS;
USB_VOLATILE uint8_t EP3OUTOddBuffer[64] @ EP3_ODD_DATA_BUFFER_ADDRESS;
USB_VOLATILE uint8_t EP1INEvenBuffer[64] @ EP1IN_EVEN_DATA_BUFFER_ADDRESS;
USB_VOLATILE uint8_t EP1INOddBuffer[64] @ EP1IN_ODD_DATA_BUFFER_ADDRESS;
#else
#define FIXED_ADDRESS_MEMORY
#define EP1_EVEN_DATA_BUFFER_ADDRESS 0x480
#define EP1_ODD_DATA_BUFFER_ADDRESS 0x4C0
#define EP2_EVEN_DATA_BUFFER_ADDRESS 0x500
#define EP2_ODD_DATA_BUFFER_ADDRESS 0x540
#define EP3_EVEN_DATA_BUFFER_ADDRESS 0x580
#define EP3_ODD_DATA_BUFFER_ADDRESS 0x5C0
#define EP1IN_EVEN_DATA_BUFFER_ADDRESS 0x600 // NEW MEMORY ADDRESS DECLARED
#define EP1IN_ODD_DATA_BUFFER_ADDRESS 0x640// NEW MEMORY ADDRESS DECLARED
#endif //FIXED_MEMORY_ADDRESS
Descriptor
/* Device Descriptor */
const USB_DEVICE_DESCRIPTOR device_dsc=
{
0x12, // Size of this descriptor in bytes
USB_DESCRIPTOR_DEVICE, // DEVICE descriptor type
0x0200, // USB Spec Release Number in BCD format
0x00, // Class Code
0x00, // Subclass code
0x00, // Protocol code
USB_EP0_BUFF_SIZE, // Max packet size for EP0, see usb_config.h
0x04D8, // Vendor ID: 0x04D8 is Microchip's Vendor ID
0x0052, // Product ID: 0x0052
0x0000, // Device release number in BCD format
0x01, // Manufacturer string index
0x02, // Product string index
0x00, // Device serial number string index
0x01 // Number of possible configurations
};
/* Configuration 1 Descriptor */
const uint8_t configDescriptor1[]={
/* Configuration Descriptor */
0x09,//sizeof(USB_CFG_DSC), // Size of this descriptor in bytes
USB_DESCRIPTOR_CONFIGURATION, // CONFIGURATION descriptor type
0x2E,0x00, // Total length of data for this cfg
1, // Number of interfaces in this cfg
1, // Index value of this configuration
0, // Configuration string index
_DEFAULT | _SELF, // Attributes, see usb_device.h
50, // Max power consumption (2X mA)
/* Interface Descriptor */
0x09,//sizeof(USB_INTF_DSC), // Size of this descriptor in bytes
USB_DESCRIPTOR_INTERFACE, // INTERFACE descriptor type
0, // Interface Number
0, // Alternate Setting Number
4, // Number of endpoints in this intf
0xFF, // Class code
0xFF, // Subclass code
0xFF, // Protocol code
0, // Interface string index
/* Endpoint Descriptor */
0x07, /*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
_EP01_OUT, //EndpointAddress
_BULK, //Attributes
64,0x00, //size
1, //Interval
0x07, /*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
_EP02_OUT, //EndpointAddress
_BULK, //Attributes
64,0x00, //size
1, //Interval
0x07, /*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
_EP03_OUT, //EndpointAddress
_BULK, //Attributes
64,0x00, //size
1, //Interval
0x07, /*sizeof(USB_EP_DSC)*/// New Endpoint for Sending Data To Host
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor
_EP01_IN, //EndpointAddress// VALUE MODIFED FOR SENDING DATA
_BULK, //Attributes
64,0x00, //size
1 //Interval
};
Initialization of USB for Bulk Transfer
void APP_DeviceVendorThroughputTestInitialize()
{
EP1OUTEvenHandle = NULL;
EP2OUTEvenHandle = NULL;
EP3OUTEvenHandle = NULL;
EP1INEvenHandle = NULL;
EP1OUTOddHandle = NULL;
EP2OUTOddHandle = NULL;
EP3OUTOddHandle = NULL;
EP1INOddHandle = NULL;
//Now that we are configured, enable the endpoints for use in the demo
// and start the initial transfers
USBEnableEndpoint(_EP01_OUT,USB_OUT_ENABLED|USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
USBEnableEndpoint(2,USB_OUT_ENABLED|USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
USBEnableEndpoint(4,USB_OUT_ENABLED|USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
USBEnableEndpoint(_EP01_IN,USB_OUT_ENABLED|USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
//Prepare the OUT endpoints to receive the first packets from the host.
EP1OUTEvenHandle = USBTransferOnePacket(_EP01_OUT, OUT_FROM_HOST,(uint8_t*)&EP1OUTEvenBuffer,64); //First 64-bytes of data sent to EP1 OUT will arrive in the even buffer.
EP1OUTOddHandle = USBTransferOnePacket(_EP01_OUT, OUT_FROM_HOST,(uint8_t*)&EP1OUTOddBuffer,64); //Second 64-bytes of data sent to EP1 OUT will arrive in the odd buffer.
EP1OUTEvenNeedsServicingNext = true; //Used to keep track of which buffer will contain the next sequential data packet.
EP2OUTEvenHandle = USBTransferOnePacket(2, OUT_FROM_HOST,(uint8_t*)&EP2OUTEvenBuffer,64);
EP2OUTOddHandle = USBTransferOnePacket(2, OUT_FROM_HOST,(uint8_t*)&EP2OUTOddBuffer,64);
EP2OUTEvenNeedsServicingNext = true; //Used to keep track of which buffer will contain the next sequential data packet.
EP3OUTEvenHandle = USBTransferOnePacket(4, OUT_FROM_HOST,(uint8_t*)&EP3OUTEvenBuffer,64);
EP3OUTOddHandle = USBTransferOnePacket(4, OUT_FROM_HOST,(uint8_t*)&EP3OUTOddBuffer,64);
EP3OUTEvenNeedsServicingNext = true; //Used to keep track of which buffer will contain the next sequential data packet.
EP1INEvenHandle = USBTransferOnePacket(_EP01_IN, IN_TO_HOST,(uint8_t*)&EP1INEvenBuffer,64); //First 64-bytes of data RECIVE to EP3 IN will arrive in the even buffer.
// EP1INOddHandle = USBTransferOnePacket(_EP01_IN, IN_TO_HOST,(uint8_t*)&EP1INOddBuffer,64); //Second 64-bytes of data RECIVE to EP3 IN will arrive in the odd buffer.
// EP1INEvenNeedsServicingNext = true;
}
Code for data Transfer, Note : _EP01_Out =0x01 & _EP01_IN =0x81
if(EP1OUTEvenNeedsServicingNext == true) //Check which buffer (even/odd) the next set of data is going to arrive in
{
if(!USBHandleBusy(EP1OUTEvenHandle)) //Check if the endpoint has received any data from the host.
{
PORTDbits.RD1=1;
PORTDbits.RD2=0;
switch(EP1OUTEvenBuffer[0]) //Data arrived, check what kind of command might be in the packet of data.
{
case 0x81: //Get push button state command from PC application.
EP1INEvenBuffer[0] = 0x81;
EP1INEvenHandle = USBTransferOnePacket(_EP01_IN, IN_TO_HOST,(uint8_t*)&EP1INEvenBuffer,64);
break;
case 0x82: //Toggle LED(s) command from PC application.
LATDbits.LD3=0;
break;
case 0x80: //Toggle LED(s) command from PC application.
LATDbits.LD3=1;
break;
EP1OUTEvenHandle = USBTransferOnePacket(_EP01_OUT, OUT_FROM_HOST,(uint8_t*)&EP1OUTEvenBuffer,64);
EP1OUTEvenNeedsServicingNext = false;
}
}
else //else EP1OUTOdd needs servicing next
{
if(!USBHandleBusy(EP1OUTOddHandle)) //Check if the endpoint has received any data from the host.
{
PORTDbits.RD1=0;
PORTDbits.RD2=1;
switch(EP1OUTOddBuffer[0]) //Data arrived, check what kind of command might be in the packet of data.
{
case 0x81:
EP1INEvenBuffer[0] = 0x81;
EP1INEvenHandle = USBTransferOnePacket(_EP01_IN, IN_TO_HOST,(uint8_t*)&EP1INEvenBuffer,64);
break;
case 0x82: //Toggle LED(s) command from PC application.
LATDbits.LD3=0;
break;
case 0x80: //Toggle LED(s) command from PC application.
LATDbits.LD3=1;
break;
}
EP1OUTOddHandle = USBTransferOnePacket(_EP01_OUT, OUT_FROM_HOST,(uint8_t*)&EP1OUTOddBuffer,64);
EP1OUTEvenNeedsServicingNext = true;
}
}
End of code