mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-03-14 21:10:07 +01:00
3361 lines
106 KiB
C++
3361 lines
106 KiB
C++
/*
|
|
## Cypress CyAPI C++ library source file (CyAPI.cpp)
|
|
## =======================================================
|
|
##
|
|
## Copyright Cypress Semiconductor Corporation, 2009-2012,
|
|
## All Rights Reserved
|
|
## UNPUBLISHED, LICENSED SOFTWARE.
|
|
##
|
|
## CONFIDENTIAL AND PROPRIETARY INFORMATION
|
|
## WHICH IS THE PROPERTY OF CYPRESS.
|
|
##
|
|
## Use of this file is governed
|
|
## by the license agreement included in the file
|
|
##
|
|
## <install>/license/license.rtf
|
|
##
|
|
## where <install> is the Cypress software
|
|
## install root directory path.
|
|
##
|
|
## =======================================================
|
|
*/
|
|
#ifndef WINVER
|
|
#define WINVER 0x0500
|
|
#endif
|
|
|
|
#include <objbase.h>
|
|
#include <setupapi.h>
|
|
#include <stdio.h>
|
|
#include "cyioctl.h"
|
|
#include "CyAPI.h"
|
|
#include "UsbdStatus.h"
|
|
#include "dbt.h"
|
|
|
|
const char API_VERSION[8] = "1.3.2.0";
|
|
|
|
UINT SPI_FLASH_PAGE_SIZE_IN_BYTE = 256;
|
|
UINT SPI_FLASH_SECTOR_SIZE_IN_BYTE = (64 * 1024);
|
|
UINT CYWB_BL_MAX_BUFFER_SIZE_WHEN_USING_EP0_TRANSPORT = BUFSIZE_UPORT; //(8 * 512); // 4KB
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// The USB Device Class
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Constructor
|
|
CCyUSBDevice::CCyUSBDevice(HANDLE hnd, GUID guid, BOOL bOpen)
|
|
{
|
|
hDevice = INVALID_HANDLE_VALUE;
|
|
hDevNotification = 0;
|
|
hHndNotification = 0;
|
|
|
|
DevNum = 0;
|
|
CfgNum = 0;
|
|
IntfcNum = 0; // The current selected interface's bInterfaceNumber
|
|
IntfcIndex = 0; // The entry in the Config's interfaces table matching to IntfcNum and AltSetting
|
|
|
|
Devices = 0;
|
|
Interfaces = 0;
|
|
AltInterfaces = 0;
|
|
Configs = 0;
|
|
|
|
DrvGuid = guid;
|
|
hWnd = hnd;
|
|
LastError = 0;
|
|
|
|
EndPoints = NULL;
|
|
ControlEndPt = NULL;
|
|
IsocInEndPt = NULL;
|
|
IsocOutEndPt = NULL;
|
|
BulkInEndPt = NULL;
|
|
BulkOutEndPt = NULL;
|
|
InterruptInEndPt = NULL;
|
|
InterruptOutEndPt = NULL;
|
|
|
|
USBCfgs[0] = NULL;
|
|
USBCfgs[1] = NULL;
|
|
USBConfigDescriptors[0] = NULL;
|
|
USBConfigDescriptors[1] = NULL;
|
|
pUsbBosDescriptor = NULL;
|
|
UsbBos = NULL;
|
|
|
|
ZeroMemory(Manufacturer, USB_STRING_MAXLEN);
|
|
ZeroMemory(Product, USB_STRING_MAXLEN);
|
|
ZeroMemory(SerialNumber, USB_STRING_MAXLEN);
|
|
ZeroMemory(DeviceName, USB_STRING_MAXLEN);
|
|
ZeroMemory(FriendlyName, USB_STRING_MAXLEN);
|
|
|
|
|
|
if (hnd) RegisterForPnpEvents(hnd);
|
|
|
|
if (bOpen) Open(DevNum);
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
CCyUSBDevice::~CCyUSBDevice(void)
|
|
{
|
|
|
|
Close();
|
|
|
|
if (hDevNotification) {
|
|
if (! UnregisterDeviceNotification(hDevNotification))
|
|
throw "Failed to close the device notification handle.";
|
|
|
|
hDevNotification = 0;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//______________________________________________________________________________
|
|
//
|
|
// It is expected that the device will only expose a single Config via the
|
|
// Windows USB HCD stack. The driver doesn't even expose an IOCTL for setting
|
|
// the configuration.
|
|
//
|
|
// This method just initializes a bunch of important variables, most important
|
|
// of which is the call to SetAltIntfcParams( ).
|
|
|
|
void CCyUSBDevice::SetConfig(UCHAR cfg){
|
|
|
|
if (!USBCfgs[0]) return;
|
|
|
|
CfgNum = 0;
|
|
if ((USBCfgs[0]) && (USBCfgs[0]->iConfiguration == cfg)) CfgNum = cfg;
|
|
if ((USBCfgs[1]) && (USBCfgs[1]->iConfiguration == cfg)) CfgNum = cfg;
|
|
|
|
ConfigValue = USBCfgs[CfgNum]->bConfigurationValue;
|
|
ConfigAttrib = USBCfgs[CfgNum]->bmAttributes;
|
|
MaxPower = USBCfgs[CfgNum]->MaxPower;
|
|
Interfaces = USBCfgs[CfgNum]->bNumInterfaces;
|
|
AltInterfaces = USBCfgs[CfgNum]->AltInterfaces;
|
|
IntfcNum = USBCfgs[CfgNum]->Interfaces[0]->bInterfaceNumber;
|
|
|
|
UCHAR a = AltIntfc(); // Get the current alt setting from the device
|
|
SetAltIntfcParams(a); // Initializes endpts, IntfcIndex, etc. without actually setting the AltInterface
|
|
|
|
if (USBCfgs[CfgNum]->Interfaces[IntfcIndex]) {
|
|
IntfcClass = USBCfgs[CfgNum]->Interfaces[IntfcIndex]->bInterfaceClass;
|
|
IntfcSubClass = USBCfgs[CfgNum]->Interfaces[IntfcIndex]->bInterfaceSubClass;
|
|
IntfcProtocol = USBCfgs[CfgNum]->Interfaces[IntfcIndex]->bInterfaceProtocol;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
|
|
UCHAR CCyUSBDevice::ConfigCount(void){
|
|
|
|
if (hDevice == INVALID_HANDLE_VALUE) return (UCHAR) NULL;
|
|
|
|
return Configs;
|
|
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
UCHAR CCyUSBDevice::IntfcCount(void){
|
|
|
|
if (hDevice == INVALID_HANDLE_VALUE) return (UCHAR) NULL;
|
|
|
|
return Interfaces;
|
|
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
// This method is not currently exposed because the driver does not support
|
|
// selection of the interface. This is because the Windows USB hub driver
|
|
// creates a new device node for each interface.
|
|
/*
|
|
void CCyUSBDevice::SetInterface(UCHAR i){
|
|
if (i < NumInterfaces) IntfcNum = i;
|
|
|
|
if (Configs[CfgNum]) {
|
|
for (int j=0; j < Configs[CfgNum]->bAltInterfaces; j++)
|
|
if ( (Configs[CfgNum]->Interfaces[j]->bInterfaceNumber == IntfcNum) &&
|
|
(Configs[CfgNum]->Interfaces[j]->bAlternateSetting == AltSetting) ) {
|
|
|
|
|
|
// TODO: Select the specified interface via the driver
|
|
|
|
|
|
|
|
IntfcIndex = j;
|
|
return;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
//______________________________________________________________________________
|
|
|
|
UCHAR CCyUSBDevice::AltIntfc(void){
|
|
|
|
UCHAR alt;
|
|
if (IoControl(IOCTL_ADAPT_GET_ALT_INTERFACE_SETTING, &alt, 1))
|
|
return alt;
|
|
else
|
|
return 0xFF;
|
|
}
|
|
|
|
|
|
//______________________________________________________________________________
|
|
|
|
void CCyUSBDevice::SetAltIntfcParams(UCHAR alt){
|
|
|
|
// Find match of IntfcNum and alt in table of interfaces
|
|
if (USBCfgs[CfgNum]) {
|
|
for (int j=0; j < USBCfgs[CfgNum]->AltInterfaces; j++)
|
|
if ( //(USBCfgs[CfgNum]->Interfaces[j]->bInterfaceNumber == IntfcNum) &&
|
|
(USBCfgs[CfgNum]->Interfaces[j]->bAlternateSetting == alt) ) {
|
|
|
|
IntfcIndex = j;
|
|
IntfcClass = USBCfgs[CfgNum]->Interfaces[j]->bInterfaceClass;
|
|
IntfcSubClass = USBCfgs[CfgNum]->Interfaces[j]->bInterfaceSubClass;;
|
|
IntfcProtocol = USBCfgs[CfgNum]->Interfaces[j]->bInterfaceProtocol;;
|
|
|
|
SetEndPointPtrs();
|
|
return;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyUSBDevice::SetAltIntfc(UCHAR alt){
|
|
|
|
bool bSuccess = false;
|
|
|
|
if (alt == AltIntfc()) return true;
|
|
|
|
// Find match of IntfcNum and alt in table of interfaces
|
|
if (USBCfgs[CfgNum]) {
|
|
for (int j=0; j < USBCfgs[CfgNum]->AltInterfaces; j++)
|
|
if ( //(USBCfgs[CfgNum]->Interfaces[j]->bInterfaceNumber == IntfcNum) &&
|
|
(USBCfgs[CfgNum]->Interfaces[j]->bAlternateSetting == alt) ) {
|
|
|
|
IntfcIndex = j;
|
|
|
|
// Actually change to the alt interface, calling the driver
|
|
bSuccess = IoControl(IOCTL_ADAPT_SELECT_INTERFACE, &alt, 1L);
|
|
|
|
IntfcClass = USBCfgs[CfgNum]->Interfaces[j]->bInterfaceClass;
|
|
IntfcSubClass = USBCfgs[CfgNum]->Interfaces[j]->bInterfaceSubClass;;
|
|
IntfcProtocol = USBCfgs[CfgNum]->Interfaces[j]->bInterfaceProtocol;;
|
|
|
|
SetEndPointPtrs();
|
|
return bSuccess;
|
|
}
|
|
}
|
|
|
|
return bSuccess;
|
|
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
// Returns the total number of alternate interfaces for the current interface
|
|
|
|
UCHAR CCyUSBDevice::AltIntfcCount(void) {
|
|
|
|
if (USBCfgs[CfgNum])
|
|
return USBCfgs[CfgNum]->Interfaces[IntfcIndex]->bAltSettings - 1;
|
|
|
|
return 0; // The primary interface is not considered an Alt interface
|
|
// even though it does have an AltSetting value (0)
|
|
|
|
}
|
|
|
|
|
|
//______________________________________________________________________________
|
|
|
|
UCHAR CCyUSBDevice::EndPointCount(void) {
|
|
|
|
if (hDevice == INVALID_HANDLE_VALUE) return (UCHAR) NULL;
|
|
|
|
if (USBCfgs[CfgNum])
|
|
return USBCfgs[CfgNum]->Interfaces[IntfcIndex]->bNumEndpoints+1; // Include EndPt0
|
|
|
|
return (UCHAR) NULL;
|
|
}
|
|
|
|
|
|
//______________________________________________________________________________
|
|
|
|
void CCyUSBDevice::GetDeviceName(void) {
|
|
|
|
ZeroMemory(DeviceName, USB_STRING_MAXLEN);
|
|
|
|
if (hDevice == INVALID_HANDLE_VALUE) return;
|
|
|
|
IoControl(IOCTL_ADAPT_GET_DEVICE_NAME, (PUCHAR)DeviceName, USB_STRING_MAXLEN);
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
void CCyUSBDevice::GetFriendlyName(void) {
|
|
|
|
ZeroMemory(FriendlyName, USB_STRING_MAXLEN);
|
|
|
|
if (hDevice == INVALID_HANDLE_VALUE) return;
|
|
|
|
IoControl(IOCTL_ADAPT_GET_FRIENDLY_NAME, (PUCHAR)FriendlyName, USB_STRING_MAXLEN);
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
void CCyUSBDevice::GetUSBAddress(void) {
|
|
|
|
if (hDevice == INVALID_HANDLE_VALUE) {
|
|
USBAddress = 0;
|
|
return;
|
|
}
|
|
|
|
bool bRetVal = IoControl(IOCTL_ADAPT_GET_ADDRESS, &USBAddress, 1L);
|
|
if (!bRetVal || BytesXfered == 0) USBAddress = 0;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
void CCyUSBDevice::GetDriverVer(void) {
|
|
|
|
if (hDevice == INVALID_HANDLE_VALUE) {
|
|
DriverVersion = (ULONG) NULL;
|
|
return;
|
|
}
|
|
|
|
bool bRetVal = IoControl(IOCTL_ADAPT_GET_DRIVER_VERSION, (PUCHAR) &DriverVersion, sizeof(ULONG));
|
|
if (!bRetVal || BytesXfered == 0) DriverVersion = 0;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
void CCyUSBDevice::GetUSBDIVer(void) {
|
|
|
|
if (hDevice == INVALID_HANDLE_VALUE) {
|
|
USBDIVersion = (ULONG) NULL;
|
|
return;
|
|
}
|
|
|
|
bool bRetVal = IoControl(IOCTL_ADAPT_GET_USBDI_VERSION, (PUCHAR) &USBDIVersion, sizeof(ULONG));
|
|
if (!bRetVal || BytesXfered == 0) USBDIVersion = 0;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
UCHAR CCyUSBDevice::DeviceCount(void){
|
|
|
|
//SP_DEVINFO_DATA devInfoData;
|
|
SP_DEVICE_INTERFACE_DATA devInterfaceData;
|
|
|
|
//Open a handle to the plug and play dev node.
|
|
//SetupDiGetClassDevs() returns a device information set that contains info on all
|
|
// installed devices of a specified class which are present.
|
|
HDEVINFO hwDeviceInfo = SetupDiGetClassDevs ( (LPGUID) &DrvGuid,
|
|
NULL,
|
|
NULL,
|
|
DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);
|
|
|
|
Devices = 0;
|
|
|
|
if (hwDeviceInfo != INVALID_HANDLE_VALUE) {
|
|
|
|
//SetupDiEnumDeviceInterfaces() returns information about device interfaces
|
|
// exposed by one or more devices. Each call returns information about one interface.
|
|
//The routine can be called repeatedly to get information about several interfaces
|
|
// exposed by one or more devices.
|
|
|
|
devInterfaceData.cbSize = sizeof(devInterfaceData);
|
|
|
|
// Count the number of devices
|
|
int i=0;
|
|
Devices = 0;
|
|
bool bDone = false;
|
|
|
|
while (!bDone) {
|
|
BOOL bRetVal = SetupDiEnumDeviceInterfaces (hwDeviceInfo, 0, (LPGUID) &DrvGuid,
|
|
i, &devInterfaceData);
|
|
|
|
if (bRetVal)
|
|
Devices++;
|
|
else {
|
|
DWORD dwLastError = GetLastError();
|
|
if (dwLastError == ERROR_NO_MORE_ITEMS) bDone = TRUE;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
SetupDiDestroyDeviceInfoList(hwDeviceInfo);
|
|
}
|
|
|
|
return Devices;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyUSBDevice::CreateHandle(UCHAR dev){
|
|
|
|
Devices = DeviceCount();
|
|
|
|
if (!Devices) return false;
|
|
|
|
if (dev > (Devices - 1)) return false; //dev = Devices-1;
|
|
|
|
SP_DEVINFO_DATA devInfoData;
|
|
SP_DEVICE_INTERFACE_DATA devInterfaceData;
|
|
PSP_INTERFACE_DEVICE_DETAIL_DATA functionClassDeviceData;
|
|
SP_INTERFACE_DEVICE_DETAIL_DATA tmpInterfaceDeviceDetailData;
|
|
|
|
ULONG requiredLength = 0;
|
|
int deviceNumber = dev;
|
|
|
|
HANDLE hFile;
|
|
|
|
//Open a handle to the plug and play dev node.
|
|
//SetupDiGetClassDevs() returns a device information set that contains info on all
|
|
// installed devices of a specified class which are present.
|
|
HDEVINFO hwDeviceInfo = SetupDiGetClassDevs ( (LPGUID) &DrvGuid,
|
|
NULL,
|
|
NULL,
|
|
DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);
|
|
|
|
if (hwDeviceInfo != INVALID_HANDLE_VALUE) {
|
|
|
|
//SetupDiEnumDeviceInterfaces() returns information about device interfaces
|
|
// exposed by one or more devices. Each call returns information about one interface.
|
|
//The routine can be called repeatedly to get information about several interfaces
|
|
// exposed by one or more devices.
|
|
|
|
devInterfaceData.cbSize = sizeof(devInterfaceData);
|
|
|
|
if (SetupDiEnumDeviceInterfaces ( hwDeviceInfo, 0, (LPGUID) &DrvGuid,
|
|
deviceNumber, &devInterfaceData)) {
|
|
//Allocate a function class device data structure to receive the goods about this
|
|
// particular device.
|
|
SetupDiGetInterfaceDeviceDetail ( hwDeviceInfo, &devInterfaceData, NULL, 0,
|
|
&requiredLength, NULL);
|
|
|
|
ULONG predictedLength = requiredLength;
|
|
|
|
functionClassDeviceData = (PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc (predictedLength);
|
|
functionClassDeviceData->cbSize = sizeof (SP_INTERFACE_DEVICE_DETAIL_DATA);
|
|
devInfoData.cbSize = sizeof(devInfoData);
|
|
//Retrieve the information from Plug and Play */
|
|
if (SetupDiGetInterfaceDeviceDetail (hwDeviceInfo,
|
|
&devInterfaceData,
|
|
functionClassDeviceData,
|
|
predictedLength,
|
|
&requiredLength,
|
|
&devInfoData)) {
|
|
|
|
/* NOTE : x64 packing issue ,requiredLength return 5byte size of the (SP_INTERFACE_DEVICE_DETAIL_DATA) and functionClassDeviceData needed sizeof functionClassDeviceData 8byte */
|
|
int pathLen = requiredLength - (sizeof (tmpInterfaceDeviceDetailData.cbSize)+sizeof (tmpInterfaceDeviceDetailData.DevicePath));
|
|
//int pathLen = requiredLength - functionClassDeviceData->cbSize;
|
|
|
|
memcpy (DevPath, functionClassDeviceData->DevicePath, pathLen);
|
|
DevPath[pathLen] = 0;
|
|
|
|
hFile = CreateFile (DevPath,
|
|
GENERIC_WRITE | GENERIC_READ,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_FLAG_OVERLAPPED,
|
|
NULL);
|
|
|
|
DWORD errCode = GetLastError();
|
|
free(functionClassDeviceData);
|
|
SetupDiDestroyDeviceInfoList(hwDeviceInfo);
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
LastError = GetLastError();
|
|
return false;
|
|
}
|
|
// hDevice, DevNum, USBDeviceDescriptor, and Configs are data members
|
|
hDevice = hFile;
|
|
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
SetupDiDestroyDeviceInfoList(hwDeviceInfo);
|
|
|
|
}
|
|
|
|
// Got here by failing at some point
|
|
|
|
hDevice = INVALID_HANDLE_VALUE;
|
|
DevNum = 0;
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyUSBDevice::Open(UCHAR dev){
|
|
|
|
// If this CCyUSBDevice object already has the driver open, close it.
|
|
if (hDevice != INVALID_HANDLE_VALUE)
|
|
Close();
|
|
|
|
|
|
|
|
if (CreateHandle(dev)) {
|
|
DevNum = dev;
|
|
|
|
// Important call: Gets the device descriptor data from the device
|
|
GetDevDescriptor();
|
|
|
|
// Gets the language IDs and selects English, if avail
|
|
SetStringDescrLanguage();
|
|
|
|
GetString(Manufacturer,USBDeviceDescriptor.iManufacturer);
|
|
GetString(Product,USBDeviceDescriptor.iProduct);
|
|
GetString(SerialNumber,USBDeviceDescriptor.iSerialNumber);
|
|
|
|
// Get BOS descriptor
|
|
if ((BcdUSB & BCDUSBJJMASK) == USB30MAJORVER)
|
|
{
|
|
if(GetInternalBosDescriptor()) // USB3.0 specific descriptor
|
|
{
|
|
try
|
|
{
|
|
UsbBos = new CCyUSBBOS(hDevice,pUsbBosDescriptor);
|
|
}
|
|
catch(char *Str)
|
|
{
|
|
char *Str1 = Str;// just to ignore warning
|
|
MessageBox(NULL,"Please correct firmware BOS descriptor table","Wrong BOS Descriptor",(UINT) NULL);
|
|
Close(); // Close the device handle.
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
GetUSBAddress();
|
|
GetDeviceName();
|
|
GetFriendlyName();
|
|
GetDriverVer();
|
|
GetUSBDIVer();
|
|
GetSpeed();
|
|
|
|
// Gets the config (including interface and endpoint) descriptors from the device
|
|
for (int i=0; i<Configs; i++)
|
|
{
|
|
GetCfgDescriptor(i);
|
|
try
|
|
{
|
|
if (USBConfigDescriptors[i])
|
|
{
|
|
if((BcdUSB & BCDUSBJJMASK) == USB20MAJORVER)
|
|
USBCfgs[i] = new CCyUSBConfig(hDevice,USBConfigDescriptors[i]);
|
|
else
|
|
{
|
|
UCHAR usb30Dummy =1;
|
|
USBCfgs[i] = new CCyUSBConfig(hDevice,USBConfigDescriptors[i],usb30Dummy);
|
|
}
|
|
}
|
|
}
|
|
catch(char *Str)
|
|
{
|
|
char *Str1 = Str; // just to ignore warning
|
|
MessageBox(NULL,"Please correct firmware descriptor table","Wrong Device Configuration",(UINT) NULL);
|
|
Close(); // Close the device handle.
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Manually configure the Control Endpoint (EPT 0)
|
|
ControlEndPt = new CCyControlEndPoint(hDevice, NULL);
|
|
ControlEndPt->DscLen = 7;
|
|
ControlEndPt->DscType = 5;
|
|
ControlEndPt->Address = 0;
|
|
ControlEndPt->Attributes = 0;
|
|
ControlEndPt->MaxPktSize = MaxPacketSize;
|
|
ControlEndPt->Interval = 0;
|
|
|
|
// We succeeded in openning a handle to the device. But, the device
|
|
// is not returning descriptors properly. We don't call Close( ) because
|
|
// we want to leave the hDevice intact, giving the user the opportunity
|
|
// to call the Reset( ) method
|
|
if (!USBCfgs[0] || !USBCfgs[0]->Interfaces[0])
|
|
return false;
|
|
|
|
// This call sets values for ConfigVal, ConfigAttrib, MaxPower, etc.
|
|
SetConfig(0);
|
|
|
|
// If we registered for device notification, also register the handle
|
|
// This is necessary in order to receive notification of removal (allowing us to close)
|
|
// before the device re-connects (for such things as our ReConnect method).
|
|
if (hDevNotification) {
|
|
DEV_BROADCAST_HANDLE hFilter;
|
|
hFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
|
|
hFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
|
|
hFilter.dbch_handle = hDevice;
|
|
|
|
hHndNotification = RegisterDeviceNotification(hWnd, (PVOID) &hFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// Got here by failing at some point
|
|
|
|
hDevice = INVALID_HANDLE_VALUE;
|
|
DevNum = 0;
|
|
return false;
|
|
}
|
|
|
|
|
|
//______________________________________________________________________________
|
|
|
|
void CCyUSBDevice::DestroyHandle(void){
|
|
|
|
if ( hDevice != INVALID_HANDLE_VALUE ) {
|
|
|
|
if (hHndNotification)
|
|
if (! UnregisterDeviceNotification(hHndNotification))
|
|
{
|
|
LastError = GetLastError();
|
|
throw "Failed to close the handle notification handle.";
|
|
}
|
|
|
|
if (! CloseHandle(hDevice))
|
|
{
|
|
LastError = GetLastError();
|
|
throw "Failed to close handle to driver.";
|
|
}
|
|
|
|
hDevice = INVALID_HANDLE_VALUE;
|
|
hHndNotification = 0;
|
|
}
|
|
|
|
}
|
|
//______________________________________________________________________________
|
|
|
|
void CCyUSBDevice::Close(void){
|
|
|
|
DestroyHandle();
|
|
ZeroMemory(&USBDeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
|
|
|
|
if(pUsbBosDescriptor)
|
|
{
|
|
free(pUsbBosDescriptor);
|
|
pUsbBosDescriptor =NULL;
|
|
}
|
|
if(UsbBos)
|
|
{
|
|
delete UsbBos ;
|
|
UsbBos = NULL;
|
|
}
|
|
// Clean-up dynamically allocated objects
|
|
for (int i=0; i<Configs; i++)
|
|
if (USBConfigDescriptors[i]) {
|
|
free(USBConfigDescriptors[i]);
|
|
USBConfigDescriptors[i] = NULL;
|
|
delete USBCfgs[i];
|
|
USBCfgs[i] = NULL;
|
|
}
|
|
|
|
|
|
// Reset the private pointers
|
|
ControlEndPt = NULL;
|
|
IsocInEndPt = NULL;
|
|
IsocOutEndPt = NULL;
|
|
BulkInEndPt = NULL;
|
|
BulkOutEndPt = NULL;
|
|
InterruptInEndPt = NULL;
|
|
InterruptOutEndPt = NULL;
|
|
|
|
Devices = 0;
|
|
Configs = 0;
|
|
Interfaces = 0;
|
|
AltInterfaces = 0;
|
|
|
|
}
|
|
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyUSBDevice::IoControl(ULONG cmd, PUCHAR XferBuf, ULONG len){
|
|
|
|
if ( hDevice == INVALID_HANDLE_VALUE ) return false;
|
|
BOOL bDioRetVal = DeviceIoControl (hDevice, cmd, XferBuf, len, XferBuf, len, &BytesXfered, NULL);
|
|
if(!bDioRetVal)LastError = GetLastError();
|
|
return (bDioRetVal && (BytesXfered == len));
|
|
}
|
|
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyUSBDevice::GetInternalBosDescriptor()
|
|
{
|
|
ULONG length = sizeof(SINGLE_TRANSFER) + sizeof(USB_BOS_DESCRIPTOR);
|
|
PUCHAR buf = new UCHAR[length];
|
|
ZeroMemory (buf, length);
|
|
|
|
PSINGLE_TRANSFER pSingleTransfer = (PSINGLE_TRANSFER) buf;
|
|
pSingleTransfer->SetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST;
|
|
pSingleTransfer->SetupPacket.bmReqType.Type = 0;
|
|
pSingleTransfer->SetupPacket.bmReqType.Recipient = 0;
|
|
pSingleTransfer->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
|
pSingleTransfer->SetupPacket.wVal.hiByte = USB_BOS_DESCRIPTOR_TYPE;
|
|
pSingleTransfer->SetupPacket.wVal.lowByte = 0;
|
|
pSingleTransfer->SetupPacket.wLength = sizeof(USB_BOS_DESCRIPTOR);
|
|
pSingleTransfer->SetupPacket.ulTimeOut = 5;
|
|
pSingleTransfer->BufferLength = pSingleTransfer->SetupPacket.wLength;
|
|
pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER);
|
|
|
|
bool bRetVal = IoControl(IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, buf, length);
|
|
UsbdStatus = pSingleTransfer->UsbdStatus;
|
|
NtStatus = pSingleTransfer->NtStatus;
|
|
|
|
if (bRetVal) {
|
|
PUSB_BOS_DESCRIPTOR BosDesc = (PUSB_BOS_DESCRIPTOR)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset);
|
|
USHORT BosDescLength= BosDesc->wTotalLength;
|
|
|
|
length = sizeof(SINGLE_TRANSFER) + BosDescLength;
|
|
PUCHAR buf2 = new UCHAR[length];
|
|
ZeroMemory (buf2, length);
|
|
|
|
pSingleTransfer = (PSINGLE_TRANSFER) buf2;
|
|
pSingleTransfer->SetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST;
|
|
pSingleTransfer->SetupPacket.bmReqType.Type = 0;
|
|
pSingleTransfer->SetupPacket.bmReqType.Recipient = 0;
|
|
pSingleTransfer->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
|
pSingleTransfer->SetupPacket.wVal.hiByte = USB_BOS_DESCRIPTOR_TYPE;
|
|
pSingleTransfer->SetupPacket.wVal.lowByte = 0;
|
|
pSingleTransfer->SetupPacket.wLength = BosDescLength;
|
|
pSingleTransfer->SetupPacket.ulTimeOut = 5;
|
|
pSingleTransfer->BufferLength = pSingleTransfer->SetupPacket.wLength;
|
|
pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER);
|
|
|
|
bRetVal = IoControl(IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, buf2, length);
|
|
UsbdStatus = pSingleTransfer->UsbdStatus;
|
|
NtStatus = pSingleTransfer->NtStatus;
|
|
|
|
if (bRetVal)
|
|
{
|
|
pUsbBosDescriptor = (PUSB_BOS_DESCRIPTOR)malloc(BosDescLength);
|
|
memcpy(pUsbBosDescriptor, (PVOID)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset), BosDescLength);
|
|
}
|
|
|
|
delete[] buf2;
|
|
|
|
}
|
|
|
|
delete[] buf;
|
|
return bRetVal;
|
|
}
|
|
void CCyUSBDevice::GetDevDescriptor(void)
|
|
{
|
|
|
|
ULONG length = sizeof(SINGLE_TRANSFER) + sizeof(USB_DEVICE_DESCRIPTOR);
|
|
PUCHAR buf = new UCHAR[length];
|
|
ZeroMemory (buf, length);
|
|
|
|
//USB_DEVICE_DESCRIPTOR devDescriptor;
|
|
ZeroMemory (&USBDeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
|
|
|
|
PSINGLE_TRANSFER pSingleTransfer = (PSINGLE_TRANSFER) buf;
|
|
pSingleTransfer->SetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST;
|
|
pSingleTransfer->SetupPacket.bmReqType.Type = 0;
|
|
pSingleTransfer->SetupPacket.bmReqType.Recipient = 0;
|
|
pSingleTransfer->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
|
pSingleTransfer->SetupPacket.wVal.hiByte = USB_DEVICE_DESCRIPTOR_TYPE;
|
|
pSingleTransfer->SetupPacket.wLength = sizeof(USB_DEVICE_DESCRIPTOR);
|
|
pSingleTransfer->SetupPacket.ulTimeOut = 5;
|
|
pSingleTransfer->BufferLength = pSingleTransfer->SetupPacket.wLength;
|
|
pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER);
|
|
|
|
bool bRetVal = IoControl(IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, buf, length);
|
|
UsbdStatus = pSingleTransfer->UsbdStatus;
|
|
NtStatus = pSingleTransfer->NtStatus;
|
|
|
|
if (bRetVal) {
|
|
memcpy(&USBDeviceDescriptor, (PVOID)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset), sizeof(USB_DEVICE_DESCRIPTOR));
|
|
|
|
BcdUSB = USBDeviceDescriptor.bcdUSB;
|
|
VendorID = USBDeviceDescriptor.idVendor;
|
|
ProductID = USBDeviceDescriptor.idProduct;
|
|
DevClass = USBDeviceDescriptor.bDeviceClass;
|
|
DevSubClass = USBDeviceDescriptor.bDeviceSubClass;
|
|
DevProtocol = USBDeviceDescriptor.bDeviceProtocol;
|
|
if((BcdUSB & BCDUSBJJMASK) == USB20MAJORVER)
|
|
MaxPacketSize = USBDeviceDescriptor.bMaxPacketSize0;
|
|
else
|
|
MaxPacketSize = (1<<USBDeviceDescriptor.bMaxPacketSize0);
|
|
|
|
BcdDevice = USBDeviceDescriptor.bcdDevice;
|
|
Configs = USBDeviceDescriptor.bNumConfigurations;
|
|
}
|
|
|
|
delete[] buf;
|
|
|
|
//return devDescriptor;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
void CCyUSBDevice::SetStringDescrLanguage(void) {
|
|
|
|
// Get the header to find-out the number of languages, size of lang ID list
|
|
ULONG length = sizeof(SINGLE_TRANSFER) + sizeof(USB_COMMON_DESCRIPTOR);
|
|
PUCHAR buf = new UCHAR[length];
|
|
ZeroMemory (buf, length);
|
|
|
|
USB_COMMON_DESCRIPTOR cmnDescriptor;
|
|
ZeroMemory (&cmnDescriptor, sizeof(USB_COMMON_DESCRIPTOR));
|
|
|
|
PSINGLE_TRANSFER pSingleTransfer = (PSINGLE_TRANSFER) buf;
|
|
pSingleTransfer->SetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST;
|
|
pSingleTransfer->SetupPacket.bmReqType.Type = 0;
|
|
pSingleTransfer->SetupPacket.bmReqType.Recipient = 0;
|
|
pSingleTransfer->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
|
pSingleTransfer->SetupPacket.wVal.hiByte = USB_STRING_DESCRIPTOR_TYPE;
|
|
pSingleTransfer->SetupPacket.wVal.lowByte = 0;
|
|
pSingleTransfer->SetupPacket.wLength = sizeof(USB_COMMON_DESCRIPTOR);
|
|
pSingleTransfer->SetupPacket.ulTimeOut = 5;
|
|
pSingleTransfer->BufferLength = pSingleTransfer->SetupPacket.wLength;
|
|
pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER);
|
|
|
|
bool bRetVal = IoControl(IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, buf, length);
|
|
UsbdStatus = pSingleTransfer->UsbdStatus;
|
|
|
|
if (bRetVal) {
|
|
memcpy(&cmnDescriptor, (PVOID)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset), sizeof(USB_COMMON_DESCRIPTOR));
|
|
|
|
int LangIDs = (cmnDescriptor.bLength - 2 ) / 2;
|
|
|
|
// Get the entire descriptor, all LangIDs
|
|
length = sizeof(SINGLE_TRANSFER) + cmnDescriptor.bLength;
|
|
PUCHAR buf2 = new UCHAR[length];
|
|
ZeroMemory (buf2, length);
|
|
|
|
pSingleTransfer = (PSINGLE_TRANSFER) buf2;
|
|
pSingleTransfer->SetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST;
|
|
pSingleTransfer->SetupPacket.bmReqType.Type = 0;
|
|
pSingleTransfer->SetupPacket.bmReqType.Recipient = 0;
|
|
pSingleTransfer->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
|
pSingleTransfer->SetupPacket.wVal.hiByte = USB_STRING_DESCRIPTOR_TYPE;
|
|
pSingleTransfer->SetupPacket.wVal.lowByte = 0;
|
|
pSingleTransfer->SetupPacket.wLength = cmnDescriptor.bLength;
|
|
pSingleTransfer->SetupPacket.ulTimeOut = 5;
|
|
pSingleTransfer->BufferLength = pSingleTransfer->SetupPacket.wLength;
|
|
pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER);
|
|
|
|
bRetVal = IoControl(IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, buf2, length);
|
|
|
|
UsbdStatus = pSingleTransfer->UsbdStatus;
|
|
|
|
if (bRetVal) {
|
|
PUSB_STRING_DESCRIPTOR IDs = (PUSB_STRING_DESCRIPTOR) (buf2 + sizeof(SINGLE_TRANSFER));
|
|
|
|
StrLangID =(LangIDs) ? IDs[0].bString[0] : 0;
|
|
|
|
for (int i=0; i<LangIDs; i++) {
|
|
USHORT id = IDs[i].bString[0];
|
|
if (id == 0x0409) StrLangID = id;
|
|
}
|
|
|
|
}
|
|
|
|
delete[] buf2;
|
|
|
|
}
|
|
|
|
delete[] buf;
|
|
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
void CCyUSBDevice::GetString(wchar_t *str, UCHAR sIndex)
|
|
{
|
|
// Get the header to find-out the number of languages, size of lang ID list
|
|
ULONG length = sizeof(SINGLE_TRANSFER) + sizeof(USB_COMMON_DESCRIPTOR);
|
|
PUCHAR buf = new UCHAR[length];
|
|
ZeroMemory (buf, length);
|
|
|
|
USB_COMMON_DESCRIPTOR cmnDescriptor;
|
|
ZeroMemory (&cmnDescriptor, sizeof(USB_COMMON_DESCRIPTOR));
|
|
|
|
PSINGLE_TRANSFER pSingleTransfer = (PSINGLE_TRANSFER) buf;
|
|
pSingleTransfer->SetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST;
|
|
pSingleTransfer->SetupPacket.bmReqType.Type = 0;
|
|
pSingleTransfer->SetupPacket.bmReqType.Recipient = 0;
|
|
pSingleTransfer->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
|
pSingleTransfer->SetupPacket.wVal.hiByte = USB_STRING_DESCRIPTOR_TYPE;
|
|
pSingleTransfer->SetupPacket.wVal.lowByte = sIndex;
|
|
pSingleTransfer->SetupPacket.wIndex = StrLangID;
|
|
pSingleTransfer->SetupPacket.wLength = sizeof(USB_COMMON_DESCRIPTOR);
|
|
pSingleTransfer->SetupPacket.ulTimeOut = 5;
|
|
pSingleTransfer->BufferLength = pSingleTransfer->SetupPacket.wLength;
|
|
pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER);
|
|
|
|
bool bRetVal = IoControl(IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, buf, length);
|
|
UsbdStatus = pSingleTransfer->UsbdStatus;
|
|
NtStatus = pSingleTransfer->NtStatus;
|
|
|
|
if (bRetVal) {
|
|
memcpy(&cmnDescriptor, (PVOID)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset), sizeof(USB_COMMON_DESCRIPTOR));
|
|
|
|
// Get the entire descriptor
|
|
length = sizeof(SINGLE_TRANSFER) + cmnDescriptor.bLength;
|
|
PUCHAR buf2 = new UCHAR[length];
|
|
ZeroMemory (buf2, length);
|
|
|
|
pSingleTransfer = (PSINGLE_TRANSFER) buf2;
|
|
pSingleTransfer->SetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST;
|
|
pSingleTransfer->SetupPacket.bmReqType.Type = 0;
|
|
pSingleTransfer->SetupPacket.bmReqType.Recipient = 0;
|
|
pSingleTransfer->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
|
pSingleTransfer->SetupPacket.wVal.hiByte = USB_STRING_DESCRIPTOR_TYPE;
|
|
pSingleTransfer->SetupPacket.wVal.lowByte = sIndex;
|
|
pSingleTransfer->SetupPacket.wIndex = StrLangID;
|
|
pSingleTransfer->SetupPacket.wLength = cmnDescriptor.bLength;
|
|
pSingleTransfer->SetupPacket.ulTimeOut = 5;
|
|
pSingleTransfer->BufferLength = pSingleTransfer->SetupPacket.wLength;
|
|
pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER);
|
|
|
|
bRetVal = IoControl(IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, buf2, length);
|
|
UsbdStatus = pSingleTransfer->UsbdStatus;
|
|
NtStatus = pSingleTransfer->NtStatus;
|
|
|
|
UCHAR bytes = (buf2[sizeof(SINGLE_TRANSFER)]);
|
|
UCHAR signature = (buf2[sizeof(SINGLE_TRANSFER)+1]);
|
|
|
|
if (bRetVal && (bytes>2) && (signature == 0x03)) {
|
|
ZeroMemory (str, USB_STRING_MAXLEN);
|
|
memcpy(str, (PVOID)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset+2), bytes-2);
|
|
}
|
|
|
|
delete[] buf2;
|
|
|
|
}
|
|
|
|
delete[] buf;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
void CCyUSBDevice::GetCfgDescriptor(int descIndex)
|
|
{
|
|
|
|
ULONG length = sizeof(SINGLE_TRANSFER) + sizeof(USB_CONFIGURATION_DESCRIPTOR);
|
|
PUCHAR buf = new UCHAR[length];
|
|
ZeroMemory (buf, length);
|
|
|
|
PSINGLE_TRANSFER pSingleTransfer = (PSINGLE_TRANSFER) buf;
|
|
pSingleTransfer->SetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST;
|
|
pSingleTransfer->SetupPacket.bmReqType.Type = 0;
|
|
pSingleTransfer->SetupPacket.bmReqType.Recipient = 0;
|
|
pSingleTransfer->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
|
pSingleTransfer->SetupPacket.wVal.hiByte = USB_CONFIGURATION_DESCRIPTOR_TYPE;
|
|
pSingleTransfer->SetupPacket.wVal.lowByte = descIndex;
|
|
pSingleTransfer->SetupPacket.wLength = sizeof(USB_CONFIGURATION_DESCRIPTOR);
|
|
pSingleTransfer->SetupPacket.ulTimeOut = 5;
|
|
pSingleTransfer->BufferLength = pSingleTransfer->SetupPacket.wLength;
|
|
pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER);
|
|
|
|
bool bRetVal = IoControl(IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, buf, length);
|
|
UsbdStatus = pSingleTransfer->UsbdStatus;
|
|
NtStatus = pSingleTransfer->NtStatus;
|
|
|
|
if (bRetVal) {
|
|
PUSB_CONFIGURATION_DESCRIPTOR configDesc = (PUSB_CONFIGURATION_DESCRIPTOR)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset);
|
|
USHORT configDescLength= configDesc->wTotalLength;
|
|
|
|
length = sizeof(SINGLE_TRANSFER) + configDescLength;
|
|
PUCHAR buf2 = new UCHAR[length];
|
|
ZeroMemory (buf2, length);
|
|
|
|
pSingleTransfer = (PSINGLE_TRANSFER) buf2;
|
|
pSingleTransfer->SetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST;
|
|
pSingleTransfer->SetupPacket.bmReqType.Type = 0;
|
|
pSingleTransfer->SetupPacket.bmReqType.Recipient = 0;
|
|
pSingleTransfer->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
|
pSingleTransfer->SetupPacket.wVal.hiByte = USB_CONFIGURATION_DESCRIPTOR_TYPE;
|
|
pSingleTransfer->SetupPacket.wVal.lowByte = descIndex;
|
|
pSingleTransfer->SetupPacket.wLength = configDescLength;
|
|
pSingleTransfer->SetupPacket.ulTimeOut = 5;
|
|
pSingleTransfer->BufferLength = pSingleTransfer->SetupPacket.wLength;
|
|
pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER);
|
|
|
|
bRetVal = IoControl(IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, buf2, length);
|
|
UsbdStatus = pSingleTransfer->UsbdStatus;
|
|
NtStatus = pSingleTransfer->NtStatus;
|
|
|
|
if (bRetVal){
|
|
USBConfigDescriptors[descIndex] = (PUSB_CONFIGURATION_DESCRIPTOR)malloc(configDescLength);
|
|
memcpy(USBConfigDescriptors[descIndex], (PVOID)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset), configDescLength);
|
|
}
|
|
|
|
delete[] buf2;
|
|
|
|
}
|
|
|
|
delete[] buf;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyUSBDevice::Reset()
|
|
{
|
|
return IoControl(IOCTL_ADAPT_RESET_PARENT_PORT, NULL, 0);
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyUSBDevice::ReConnect()
|
|
{
|
|
return IoControl(IOCTL_ADAPT_CYCLE_PORT, NULL, 0);
|
|
}
|
|
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyUSBDevice::Suspend()
|
|
{
|
|
if (PowerState() == 4) return true;
|
|
|
|
ULONG state = 4;
|
|
bool ret = IoControl(IOCTL_ADAPT_SET_DEVICE_POWER_STATE, (PUCHAR) &state, sizeof(state));
|
|
|
|
if ( 0 == state) return ret;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyUSBDevice::Resume()
|
|
{
|
|
if (PowerState() == 1) return true;
|
|
|
|
ULONG state = 1;
|
|
bool ret = IoControl(IOCTL_ADAPT_SET_DEVICE_POWER_STATE, (PUCHAR) &state, sizeof(state));
|
|
|
|
if ( 0 == state) return ret;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
//______________________________________________________________________________
|
|
|
|
void CCyUSBDevice::GetSpeed()
|
|
{
|
|
ULONG speed = 0;
|
|
bHighSpeed = false;
|
|
bSuperSpeed = false;
|
|
|
|
IoControl(IOCTL_ADAPT_GET_DEVICE_SPEED, (PUCHAR) &speed, sizeof(speed));
|
|
|
|
bHighSpeed = (speed == DEVICE_SPEED_HIGH);
|
|
bSuperSpeed = (speed == DEVICE_SPEED_SUPER);
|
|
}
|
|
|
|
|
|
//______________________________________________________________________________
|
|
|
|
UCHAR CCyUSBDevice::PowerState()
|
|
{
|
|
ULONG state;
|
|
bool rval = IoControl(IOCTL_ADAPT_GET_DEVICE_POWER_STATE, (PUCHAR) &state, sizeof(state));
|
|
|
|
UCHAR s = (UCHAR) NULL;
|
|
|
|
if (rval) s = (UCHAR) state;
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
//______________________________________________________________________________
|
|
|
|
CCyUSBEndPoint * CCyUSBDevice::EndPointOf(UCHAR addr) //throw(...)
|
|
{
|
|
|
|
if (addr == 0) return ControlEndPt;
|
|
|
|
CCyUSBEndPoint *ept;
|
|
|
|
int n = EndPointCount();
|
|
|
|
for (int i=0; i<n; i++) {
|
|
ept = USBCfgs[CfgNum]->Interfaces[IntfcIndex]->EndPoints[i];
|
|
|
|
if (ept)
|
|
{
|
|
if (addr == ept->Address) return ept; }
|
|
else
|
|
throw "Failed to find endpoint.";
|
|
}
|
|
|
|
return NULL; // Error
|
|
|
|
}
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyUSBDevice::GetBosDescriptor(PUSB_BOS_DESCRIPTOR descr)
|
|
{
|
|
if ((BcdUSB & BCDUSBJJMASK) == USB30MAJORVER)
|
|
{
|
|
if(UsbBos!=NULL)
|
|
{
|
|
descr->bLength = UsbBos->bLength;
|
|
descr->bDescriptorType = UsbBos->bDescriptorType;
|
|
descr->bNumDeviceCaps = UsbBos->bNumDeviceCaps;
|
|
descr->wTotalLength = UsbBos->wTotalLength;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
bool CCyUSBDevice::GetBosUSB20DeviceExtensionDescriptor(PUSB_BOS_USB20_DEVICE_EXTENSION descr)
|
|
{
|
|
if ((BcdUSB & BCDUSBJJMASK) == USB30MAJORVER)
|
|
{
|
|
if(UsbBos->pUSB20_DeviceExt != NULL)
|
|
{
|
|
descr->bLength = UsbBos->pUSB20_DeviceExt->bLength;
|
|
descr->bDescriptorType = UsbBos->pUSB20_DeviceExt->bDescriptorType;
|
|
descr->bDevCapabilityType = UsbBos->pUSB20_DeviceExt->bDevCapabilityType;
|
|
descr->bmAttribute = UsbBos->pUSB20_DeviceExt->bmAttribute;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
bool CCyUSBDevice::GetBosContainedIDDescriptor(PUSB_BOS_CONTAINER_ID descr)
|
|
{
|
|
if ((BcdUSB & BCDUSBJJMASK) == USB30MAJORVER)
|
|
{
|
|
if(UsbBos->pContainer_ID != NULL)
|
|
{
|
|
descr->bLength = UsbBos->pContainer_ID->bLength;
|
|
descr->bDescriptorType = UsbBos->pContainer_ID->bDescriptorType;
|
|
descr->bDevCapabilityType = UsbBos->pContainer_ID->bDevCapabilityType;
|
|
descr->bReserved = UsbBos->pContainer_ID->bReserved;
|
|
for (int i=0;i<USB_BOS_CAPABILITY_TYPE_CONTAINER_ID_SIZE;i++)
|
|
descr->ContainerID[i] = UsbBos->pContainer_ID->ContainerID[i];
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
bool CCyUSBDevice::GetBosSSCapabilityDescriptor(PUSB_BOS_SS_DEVICE_CAPABILITY descr)
|
|
{
|
|
if ((BcdUSB & BCDUSBJJMASK) == USB30MAJORVER)
|
|
{
|
|
if(UsbBos->pSS_DeviceCap != NULL)
|
|
{
|
|
descr->bLength = UsbBos->pSS_DeviceCap->bLength;
|
|
descr->bDescriptorType = UsbBos->pSS_DeviceCap->bDescriptorType;
|
|
descr->bDevCapabilityType = UsbBos->pSS_DeviceCap->bDevCapabilityType;
|
|
descr->bFunctionalitySupporte = UsbBos->pSS_DeviceCap->bFunctionalitySupporte;
|
|
descr->bmAttribute = UsbBos->pSS_DeviceCap->bmAttribute;
|
|
descr->bU1DevExitLat = UsbBos->pSS_DeviceCap->bU1DevExitLat;
|
|
descr->wSpeedsSuported = UsbBos->pSS_DeviceCap->SpeedsSuported;
|
|
descr->bU2DevExitLat = UsbBos->pSS_DeviceCap->bU2DevExitLat;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
//______________________________________________________________________________
|
|
|
|
void CCyUSBDevice::GetDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR descr)
|
|
{
|
|
// Copy the internal private data to the passed parameter
|
|
*descr = USBDeviceDescriptor;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
void CCyUSBDevice::GetConfigDescriptor(PUSB_CONFIGURATION_DESCRIPTOR descr)
|
|
{
|
|
// Copy the internal private data to the passed parameter
|
|
*descr = *USBConfigDescriptors[CfgNum];
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
void CCyUSBDevice::GetIntfcDescriptor(PUSB_INTERFACE_DESCRIPTOR descr)
|
|
{
|
|
CCyUSBInterface *i = USBCfgs[CfgNum]->Interfaces[IntfcIndex];
|
|
|
|
// Copy the internal private data to the passed parameter
|
|
descr->bLength = i->bLength;
|
|
descr->bDescriptorType = i->bDescriptorType;
|
|
descr->bInterfaceNumber = i->bInterfaceNumber;
|
|
descr->bAlternateSetting = i->bAlternateSetting;
|
|
descr->bNumEndpoints = i->bNumEndpoints;
|
|
descr->bInterfaceClass = i->bInterfaceClass;
|
|
descr->bInterfaceSubClass = i->bInterfaceSubClass;
|
|
descr->bInterfaceProtocol = i->bInterfaceProtocol;
|
|
descr->iInterface = i->iInterface;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
CCyUSBConfig CCyUSBDevice::GetUSBConfig(int index)
|
|
{
|
|
// Rarely (i.e. never) have more than 1 Configuration
|
|
int i = (index > (Configs-1)) ? 0 : index;
|
|
|
|
return *USBCfgs[i]; // Invoke the copy constructor
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
void CCyUSBDevice::UsbdStatusString(ULONG stat, PCHAR str)
|
|
{
|
|
//CString tmp; // MFC Version
|
|
//String tmp;
|
|
|
|
char StateStr[24];
|
|
char StatusStr[64];
|
|
ZeroMemory(StateStr,24);
|
|
ZeroMemory(StatusStr,64);
|
|
|
|
if (! USBD_STATUS(stat)) {
|
|
sprintf(StateStr,"[state=SUCCESS ");
|
|
sprintf(StatusStr,"status=USBD_STATUS_SUCCESS]");
|
|
} else {
|
|
|
|
switch(USBD_STATE(stat)) {
|
|
case USBD_STATUS_SUCCESS: sprintf(StateStr," [state=SUCCESS "); break;
|
|
case USBD_STATUS_PENDING: sprintf(StateStr," [state=PENDING "); break;
|
|
case USBD_STATUS_HALTED: sprintf(StateStr," [state=STALLED "); break;
|
|
case USBD_STATUS_ERROR: sprintf(StateStr," [state=ERROR "); break;
|
|
default: break;
|
|
}
|
|
|
|
switch(stat|0xC0000000L) { // Note: error typedefs have both error and stall bit set
|
|
case USBD_STATUS_CRC: sprintf(StatusStr,"status=USBD_STATUS_CRC]"); break;
|
|
case USBD_STATUS_BTSTUFF: sprintf(StatusStr,"status=USBD_STATUS_BTSTUFF]"); break;
|
|
case USBD_STATUS_DATA_TOGGLE_MISMATCH: sprintf(StatusStr,"status=USBD_STATUS_DATA_TOGGLE_MISMATCH]"); break;
|
|
case USBD_STATUS_STALL_PID: sprintf(StatusStr,"status=USBD_STATUS_STALL_PID]"); break;
|
|
case USBD_STATUS_DEV_NOT_RESPONDING: sprintf(StatusStr,"status=USBD_STATUS_DEV_NOT_RESPONDING]"); break;
|
|
case USBD_STATUS_PID_CHECK_FAILURE: sprintf(StatusStr,"status=USBD_STATUS_PID_CHECK_FAILURE]"); break;
|
|
case USBD_STATUS_UNEXPECTED_PID: sprintf(StatusStr,"status=USBD_STATUS_UNEXPECTED_PID]"); break;
|
|
case USBD_STATUS_DATA_OVERRUN: sprintf(StatusStr,"status=USBD_STATUS_DATA_OVERRUN]"); break;
|
|
case USBD_STATUS_DATA_UNDERRUN: sprintf(StatusStr,"status=USBD_STATUS_DATA_UNDERRUN]"); break;
|
|
case USBD_STATUS_RESERVED1: sprintf(StatusStr,"status=USBD_STATUS_RESERVED1]"); break;
|
|
case USBD_STATUS_RESERVED2: sprintf(StatusStr,"status=USBD_STATUS_RESERVED2]"); break;
|
|
case USBD_STATUS_BUFFER_OVERRUN: sprintf(StatusStr,"status=USBD_STATUS_BUFFER_OVERRUN]"); break;
|
|
case USBD_STATUS_BUFFER_UNDERRUN: sprintf(StatusStr,"status=USBD_STATUS_BUFFER_UNDERRUN]"); break;
|
|
case USBD_STATUS_NOT_ACCESSED: sprintf(StatusStr,"status=USBD_STATUS_NOT_ACCESSED]"); break;
|
|
case USBD_STATUS_FIFO: sprintf(StatusStr,"status=USBD_STATUS_FIFO]"); break;
|
|
|
|
case USBD_STATUS_ENDPOINT_HALTED: sprintf(StatusStr,"status=USBD_STATUS_ENDPOINT_HALTED]"); break;
|
|
case USBD_STATUS_NO_MEMORY: sprintf(StatusStr,"status=USBD_STATUS_NO_MEMORY]"); break;
|
|
case USBD_STATUS_INVALID_URB_FUNCTION: sprintf(StatusStr,"status=USBD_STATUS_INVALID_URB_FUNCTION]"); break;
|
|
case USBD_STATUS_INVALID_PARAMETER: sprintf(StatusStr,"status=USBD_STATUS_INVALID_PARAMETER]"); break;
|
|
case USBD_STATUS_ERROR_BUSY: sprintf(StatusStr,"status=USBD_STATUS_ERROR_BUSY]"); break;
|
|
case USBD_STATUS_REQUEST_FAILED: sprintf(StatusStr,"status=USBD_STATUS_REQUEST_FAILED]"); break;
|
|
case USBD_STATUS_INVALID_PIPE_HANDLE: sprintf(StatusStr,"status=USBD_STATUS_INVALID_PIPE_HANDLE]"); break;
|
|
case USBD_STATUS_NO_BANDWIDTH: sprintf(StatusStr,"status=USBD_STATUS_NO_BANDWIDTH]"); break;
|
|
case USBD_STATUS_INTERNAL_HC_ERROR: sprintf(StatusStr,"status=USBD_STATUS_INTERNAL_HC_ERROR]"); break;
|
|
case USBD_STATUS_ERROR_SHORT_TRANSFER: sprintf(StatusStr,"status=USBD_STATUS_ERROR_SHORT_TRANSFER]"); break;
|
|
case USBD_STATUS_BAD_START_FRAME: sprintf(StatusStr,"status=USBD_STATUS_BAD_START_FRAME]"); break;
|
|
case USBD_STATUS_ISOCH_REQUEST_FAILED: sprintf(StatusStr,"status=USBD_STATUS_ISOCH_REQUEST_FAILED]"); break;
|
|
case USBD_STATUS_FRAME_CONTROL_OWNED: sprintf(StatusStr,"status=USBD_STATUS_FRAME_CONTROL_OWNED]"); break;
|
|
case USBD_STATUS_FRAME_CONTROL_NOT_OWNED:sprintf(StatusStr,"status=USBD_STATUS_FRAME_CONTROL_NOT_OWNED]"); break;
|
|
case USBD_STATUS_CANCELED: sprintf(StatusStr,"status=USBD_STATUS_CANCELED]"); break;
|
|
case USBD_STATUS_CANCELING: sprintf(StatusStr,"status=USBD_STATUS_CANCELING]"); break;
|
|
|
|
default: sprintf(StatusStr,"status=UNKNOWN]"); break;
|
|
}
|
|
}
|
|
|
|
sprintf(str, "%s%s", StateStr, StatusStr);
|
|
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
// This method is called from Open, just after ControlEndPt has been instantiated
|
|
// It also gets called whenever a different Alt Interface setting is made
|
|
void CCyUSBDevice::SetEndPointPtrs(void)
|
|
{
|
|
if (Configs == 0) return;
|
|
if (Interfaces == 0) return;
|
|
|
|
EndPoints = USBCfgs[CfgNum]->Interfaces[IntfcIndex]->EndPoints;
|
|
EndPoints[0] = ControlEndPt;
|
|
int eptCount = EndPointCount() - 1;
|
|
|
|
IsocInEndPt = NULL;
|
|
IsocOutEndPt = NULL;
|
|
BulkInEndPt = NULL;
|
|
BulkOutEndPt = NULL;
|
|
InterruptInEndPt = NULL;
|
|
InterruptOutEndPt = NULL;
|
|
|
|
for (int i=0; i<eptCount; i++) {
|
|
UCHAR bIn = EndPoints[i+1]->Address & 0x80;
|
|
UCHAR attrib = EndPoints[i+1]->Attributes;
|
|
|
|
|
|
EndPoints[i+1]->XferMode = XMODE_DIRECT;
|
|
|
|
if ((IsocInEndPt == NULL) && (attrib == 1) && bIn) IsocInEndPt = (CCyIsocEndPoint *)EndPoints[i+1];
|
|
if ((BulkInEndPt == NULL) && (attrib == 2) && bIn) BulkInEndPt = (CCyBulkEndPoint *)EndPoints[i+1];
|
|
if ((InterruptInEndPt == NULL) && (attrib == 3) && bIn) InterruptInEndPt = (CCyInterruptEndPoint *)EndPoints[i+1];
|
|
|
|
if ((IsocOutEndPt == NULL) && (attrib == 1) && !bIn) IsocOutEndPt = (CCyIsocEndPoint *)EndPoints[i+1];
|
|
if ((BulkOutEndPt == NULL) && (attrib == 2) && !bIn) BulkOutEndPt = (CCyBulkEndPoint *)EndPoints[i+1];
|
|
if ((InterruptOutEndPt == NULL) && (attrib == 3) && !bIn) InterruptOutEndPt = (CCyInterruptEndPoint *)EndPoints[i+1];
|
|
}
|
|
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyUSBDevice::RegisterForPnpEvents(HANDLE Handle)
|
|
{
|
|
DEV_BROADCAST_DEVICEINTERFACE dFilter = {0};
|
|
dFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
|
|
dFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
|
dFilter.dbcc_classguid = DrvGuid;
|
|
|
|
hDevNotification = RegisterDeviceNotification(Handle, (PVOID) &dFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
|
|
if (!hDevNotification)
|
|
{
|
|
LastError = GetLastError();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// The USB Interface Class
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// The Copy Constructor
|
|
CCyUSBInterface::CCyUSBInterface(CCyUSBInterface &ifc)
|
|
{
|
|
bLength = ifc.bLength;
|
|
bDescriptorType = ifc.bDescriptorType;
|
|
bInterfaceNumber = ifc.bInterfaceNumber;
|
|
bAlternateSetting = ifc.bAlternateSetting;
|
|
bNumEndpoints = ifc.bNumEndpoints;
|
|
bInterfaceClass = ifc.bInterfaceClass;
|
|
bInterfaceSubClass = ifc.bInterfaceSubClass;
|
|
bInterfaceProtocol = ifc.bInterfaceProtocol;
|
|
iInterface = ifc.iInterface;
|
|
|
|
wTotalLength = ifc.wTotalLength;
|
|
|
|
int i;
|
|
|
|
for (i=0; i<MAX_ENDPTS; i++) EndPoints[i] = NULL;
|
|
|
|
for (i=0; i<MAX_ENDPTS; i++)
|
|
if (ifc.EndPoints[i]){
|
|
|
|
if (ifc.EndPoints[i]->Attributes == 0) {
|
|
CCyControlEndPoint *e = (CCyControlEndPoint*)ifc.EndPoints[i];
|
|
EndPoints[i] = new CCyControlEndPoint(*e);
|
|
}
|
|
|
|
if (ifc.EndPoints[i]->Attributes == 1) {
|
|
CCyIsocEndPoint *e = (CCyIsocEndPoint*)ifc.EndPoints[i];
|
|
EndPoints[i] = new CCyIsocEndPoint(*e);
|
|
}
|
|
|
|
if (ifc.EndPoints[i]->Attributes == 2) {
|
|
CCyBulkEndPoint *e = (CCyBulkEndPoint*)ifc.EndPoints[i];
|
|
EndPoints[i] = new CCyBulkEndPoint(*e);
|
|
}
|
|
|
|
if (ifc.EndPoints[i]->Attributes == 3) {
|
|
CCyInterruptEndPoint *e = (CCyInterruptEndPoint*)ifc.EndPoints[i];
|
|
EndPoints[i] = new CCyInterruptEndPoint(*e);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
CCyUSBInterface::CCyUSBInterface(HANDLE handle, PUSB_INTERFACE_DESCRIPTOR pIntfcDescriptor)
|
|
{
|
|
|
|
PUSB_ENDPOINT_DESCRIPTOR endPtDesc;
|
|
|
|
bLength = pIntfcDescriptor->bLength;
|
|
bDescriptorType = pIntfcDescriptor->bDescriptorType;
|
|
bInterfaceNumber = pIntfcDescriptor->bInterfaceNumber;
|
|
bAlternateSetting = pIntfcDescriptor->bAlternateSetting;
|
|
bNumEndpoints = pIntfcDescriptor->bNumEndpoints;
|
|
bInterfaceClass = pIntfcDescriptor->bInterfaceClass;
|
|
bInterfaceSubClass = pIntfcDescriptor->bInterfaceSubClass;
|
|
bInterfaceProtocol = pIntfcDescriptor->bInterfaceProtocol;
|
|
iInterface = pIntfcDescriptor->iInterface;
|
|
|
|
bAltSettings = 0;
|
|
wTotalLength = bLength;
|
|
|
|
PUCHAR desc = (PUCHAR)pIntfcDescriptor + pIntfcDescriptor->bLength;
|
|
|
|
int i;
|
|
int unexpected = 0;
|
|
|
|
for (i=0; i<MAX_ENDPTS; i++) EndPoints[i] = NULL;
|
|
|
|
for (i=0; i<bNumEndpoints; i++) {
|
|
|
|
endPtDesc = (PUSB_ENDPOINT_DESCRIPTOR) (desc);
|
|
wTotalLength += endPtDesc->bLength;
|
|
|
|
// We leave slot [0] empty to hold THE obligatory EndPoint Zero control endpoint
|
|
if (endPtDesc->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE) {
|
|
switch (endPtDesc->bmAttributes ) {
|
|
case 0:
|
|
EndPoints[i+1] = new CCyControlEndPoint(handle, endPtDesc);
|
|
break;
|
|
case 1:
|
|
EndPoints[i+1] = new CCyIsocEndPoint(handle, endPtDesc);
|
|
break;
|
|
case 2:
|
|
EndPoints[i+1] = new CCyBulkEndPoint(handle, endPtDesc);
|
|
break;
|
|
case 3:
|
|
EndPoints[i+1] = new CCyInterruptEndPoint(handle, endPtDesc);
|
|
break;
|
|
}
|
|
|
|
desc += endPtDesc->bLength;
|
|
} else {
|
|
|
|
unexpected++;
|
|
if (unexpected < 12) { // Sanity check - prevent infinite loop
|
|
|
|
// This may have been a class-specific descriptor (like HID). Skip it.
|
|
desc += endPtDesc->bLength;
|
|
|
|
// Stay in the loop, grabbing the next descriptor
|
|
i--;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
CCyUSBInterface::CCyUSBInterface(HANDLE handle, PUSB_INTERFACE_DESCRIPTOR pIntfcDescriptor,UCHAR usb30Dummy)
|
|
{
|
|
|
|
PUSB_ENDPOINT_DESCRIPTOR endPtDesc;
|
|
|
|
bLength = pIntfcDescriptor->bLength;
|
|
bDescriptorType = pIntfcDescriptor->bDescriptorType;
|
|
bInterfaceNumber = pIntfcDescriptor->bInterfaceNumber;
|
|
bAlternateSetting = pIntfcDescriptor->bAlternateSetting;
|
|
bNumEndpoints = pIntfcDescriptor->bNumEndpoints;
|
|
bInterfaceClass = pIntfcDescriptor->bInterfaceClass;
|
|
bInterfaceSubClass = pIntfcDescriptor->bInterfaceSubClass;
|
|
bInterfaceProtocol = pIntfcDescriptor->bInterfaceProtocol;
|
|
iInterface = pIntfcDescriptor->iInterface;
|
|
|
|
bAltSettings = 0;
|
|
wTotalLength = bLength;
|
|
|
|
PUCHAR desc = (PUCHAR)pIntfcDescriptor + pIntfcDescriptor->bLength;
|
|
|
|
int i;
|
|
int unexpected = 0;
|
|
|
|
for (i=0; i<MAX_ENDPTS; i++) EndPoints[i] = NULL;
|
|
|
|
for (i=0; i<bNumEndpoints; i++)
|
|
{
|
|
bool bSSDec = false;
|
|
endPtDesc = (PUSB_ENDPOINT_DESCRIPTOR) (desc);
|
|
desc += endPtDesc->bLength;
|
|
|
|
PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR ssendPtDesc = (PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR)desc;
|
|
wTotalLength += endPtDesc->bLength;
|
|
|
|
// We leave slot [0] empty to hold THE obligatory EndPoint Zero control endpoint
|
|
if (ssendPtDesc != NULL)
|
|
bSSDec = (ssendPtDesc->bDescriptorType == USB_SUPERSPEED_ENDPOINT_COMPANION);
|
|
|
|
if ((endPtDesc->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE) && bSSDec)
|
|
{
|
|
switch (endPtDesc->bmAttributes )
|
|
{
|
|
case 0:
|
|
EndPoints[i+1] = new CCyControlEndPoint(handle, endPtDesc);
|
|
break;
|
|
case 1:
|
|
EndPoints[i+1] = new CCyIsocEndPoint(handle, endPtDesc,ssendPtDesc);
|
|
break;
|
|
case 2:
|
|
EndPoints[i+1] = new CCyBulkEndPoint(handle, endPtDesc,ssendPtDesc);
|
|
break;
|
|
case 3:
|
|
EndPoints[i+1] = new CCyInterruptEndPoint(handle, endPtDesc,ssendPtDesc);
|
|
break;
|
|
}
|
|
|
|
desc += ssendPtDesc->bLength;
|
|
wTotalLength += ssendPtDesc->bLength;
|
|
|
|
}
|
|
else if (endPtDesc->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE)
|
|
{
|
|
switch (endPtDesc->bmAttributes )
|
|
{
|
|
case 0:
|
|
EndPoints[i+1] = new CCyControlEndPoint(handle, endPtDesc);
|
|
break;
|
|
case 1:
|
|
EndPoints[i+1] = new CCyIsocEndPoint(handle, endPtDesc);
|
|
break;
|
|
case 2:
|
|
EndPoints[i+1] = new CCyBulkEndPoint(handle, endPtDesc);
|
|
break;
|
|
case 3:
|
|
EndPoints[i+1] = new CCyInterruptEndPoint(handle, endPtDesc);
|
|
break;
|
|
}
|
|
|
|
//desc += endPtDesc->bLength; // THis a bug for the composite device
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
unexpected++;
|
|
if (unexpected < 12) { // Sanity check - prevent infinite loop
|
|
|
|
// This may have been a class-specific descriptor (like HID). Skip it.
|
|
desc += endPtDesc->bLength;
|
|
|
|
// Stay in the loop, grabbing the next descriptor
|
|
i--;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
CCyUSBInterface::~CCyUSBInterface(void) {
|
|
|
|
for (int i=0; i<MAX_ENDPTS; i++)
|
|
if (EndPoints[i])
|
|
{
|
|
delete EndPoints[i];
|
|
EndPoints[i] = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// The USB Config Class
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CCyUSBConfig::CCyUSBConfig(void)
|
|
{
|
|
bLength = 0;
|
|
bDescriptorType = 0;
|
|
wTotalLength = 0;
|
|
bNumInterfaces = 0;
|
|
AltInterfaces = 0;
|
|
bConfigurationValue = 0;
|
|
iConfiguration = 0;
|
|
bmAttributes = 0;
|
|
MaxPower = 0;
|
|
|
|
for (int i=0; i<MAX_INTERFACES; i++) Interfaces[i] = NULL;
|
|
|
|
}
|
|
|
|
|
|
// The Copy Constructor
|
|
CCyUSBConfig::CCyUSBConfig(CCyUSBConfig &cfg)
|
|
{
|
|
bLength = cfg.bLength;
|
|
bDescriptorType = cfg.bDescriptorType;
|
|
wTotalLength = cfg.wTotalLength;
|
|
bNumInterfaces = cfg.bNumInterfaces;
|
|
AltInterfaces = cfg.AltInterfaces;
|
|
bConfigurationValue = cfg.bConfigurationValue;
|
|
iConfiguration = cfg.iConfiguration;
|
|
bmAttributes = cfg.bmAttributes;
|
|
MaxPower = cfg.MaxPower;
|
|
AltInterfaces = cfg.AltInterfaces;
|
|
|
|
int i;
|
|
|
|
for (i=0; i<MAX_INTERFACES; i++) Interfaces[i] = NULL;
|
|
|
|
for (i=0; i<AltInterfaces; i++)
|
|
Interfaces[i] = new CCyUSBInterface(*cfg.Interfaces[i]);
|
|
|
|
}
|
|
|
|
|
|
CCyUSBConfig::CCyUSBConfig(HANDLE handle, PUSB_CONFIGURATION_DESCRIPTOR pConfigDescr){
|
|
|
|
PUSB_INTERFACE_DESCRIPTOR interfaceDesc;
|
|
int i;
|
|
|
|
bLength = pConfigDescr->bLength;
|
|
bDescriptorType = pConfigDescr->bDescriptorType;
|
|
wTotalLength = pConfigDescr->wTotalLength;
|
|
bNumInterfaces = pConfigDescr->bNumInterfaces;
|
|
AltInterfaces = 0;
|
|
bConfigurationValue = pConfigDescr->bConfigurationValue;
|
|
iConfiguration = pConfigDescr->iConfiguration;
|
|
bmAttributes = pConfigDescr->bmAttributes;
|
|
MaxPower = pConfigDescr->MaxPower;
|
|
|
|
int tLen = pConfigDescr->wTotalLength;
|
|
|
|
PUCHAR desc = (PUCHAR)pConfigDescr + pConfigDescr->bLength;
|
|
int bytesConsumed = pConfigDescr->bLength;
|
|
|
|
for (i=0; i<MAX_INTERFACES; i++) Interfaces[i] = NULL;
|
|
|
|
i = 0;
|
|
do {
|
|
interfaceDesc = (PUSB_INTERFACE_DESCRIPTOR) (desc);
|
|
|
|
if (interfaceDesc->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) {
|
|
Interfaces[i] = new CCyUSBInterface(handle, interfaceDesc);
|
|
i++;
|
|
AltInterfaces++; // Actually the total number of interfaces for the config
|
|
bytesConsumed += Interfaces[i-1]->wTotalLength;
|
|
} else {
|
|
// Unexpected descriptor type
|
|
// Just skip it and go on - could have thrown an exception instead
|
|
// since this indicates that the descriptor structure is invalid.
|
|
bytesConsumed += interfaceDesc->bLength;
|
|
}
|
|
|
|
|
|
desc = (PUCHAR) pConfigDescr + bytesConsumed;
|
|
|
|
} while ((bytesConsumed < tLen) && (i<MAX_INTERFACES)); // Only support 8 total interfaces
|
|
|
|
|
|
// Count the alt interfaces for each interface number
|
|
for (i=0; i<AltInterfaces; i++) {
|
|
|
|
Interfaces[i]->bAltSettings = 0;
|
|
|
|
for (int j=0; j<AltInterfaces; j++) // Walk the list looking for identical bInterfaceNumbers
|
|
if (Interfaces[i]->bInterfaceNumber == Interfaces[j]->bInterfaceNumber)
|
|
Interfaces[i]->bAltSettings++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
CCyUSBConfig::CCyUSBConfig(HANDLE handle, PUSB_CONFIGURATION_DESCRIPTOR pConfigDescr,UCHAR usb30Dummy)
|
|
{
|
|
|
|
PUSB_INTERFACE_DESCRIPTOR interfaceDesc;
|
|
int i;
|
|
|
|
bLength = pConfigDescr->bLength;
|
|
bDescriptorType = pConfigDescr->bDescriptorType;
|
|
wTotalLength = pConfigDescr->wTotalLength;
|
|
bNumInterfaces = pConfigDescr->bNumInterfaces;
|
|
AltInterfaces = 0;
|
|
bConfigurationValue = pConfigDescr->bConfigurationValue;
|
|
iConfiguration = pConfigDescr->iConfiguration;
|
|
bmAttributes = pConfigDescr->bmAttributes;
|
|
MaxPower = pConfigDescr->MaxPower;
|
|
|
|
int tLen = pConfigDescr->wTotalLength;
|
|
|
|
PUCHAR desc = (PUCHAR)pConfigDescr + pConfigDescr->bLength;
|
|
int bytesConsumed = pConfigDescr->bLength;
|
|
|
|
for (i=0; i<MAX_INTERFACES; i++) Interfaces[i] = NULL;
|
|
|
|
i = 0;
|
|
do {
|
|
interfaceDesc = (PUSB_INTERFACE_DESCRIPTOR) (desc);
|
|
|
|
if (interfaceDesc->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) {
|
|
Interfaces[i] = new CCyUSBInterface(handle, interfaceDesc,usb30Dummy);
|
|
i++;
|
|
AltInterfaces++; // Actually the total number of interfaces for the config
|
|
bytesConsumed += Interfaces[i-1]->wTotalLength;
|
|
} else {
|
|
// Unexpected descriptor type
|
|
// Just skip it and go on - could have thrown an exception instead
|
|
// since this indicates that the descriptor structure is invalid.
|
|
bytesConsumed += interfaceDesc->bLength;
|
|
}
|
|
|
|
|
|
desc = (PUCHAR) pConfigDescr + bytesConsumed;
|
|
|
|
} while ((bytesConsumed < tLen) && (i<MAX_INTERFACES)); // Only support 8 total interfaces
|
|
|
|
|
|
// Count the alt interfaces for each interface number
|
|
for (i=0; i<AltInterfaces; i++) {
|
|
|
|
Interfaces[i]->bAltSettings = 0;
|
|
|
|
for (int j=0; j<AltInterfaces; j++) // Walk the list looking for identical bInterfaceNumbers
|
|
if (Interfaces[i]->bInterfaceNumber == Interfaces[j]->bInterfaceNumber)
|
|
Interfaces[i]->bAltSettings++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//______________________________________________________________________________
|
|
|
|
CCyUSBConfig::~CCyUSBConfig(void){
|
|
|
|
for (int i=0; i<MAX_INTERFACES; i++)
|
|
if (Interfaces[i]) {
|
|
|
|
// Detect the first non-zero EndPoints[0] - the control endpoint -
|
|
// and delete it. Then, make sure all other interfaces have 0 as
|
|
// the value for EndPoints[0], as anything else would be a redundant
|
|
// reference to the control endpoint and cause an error when trying
|
|
// to delete it a second time.
|
|
|
|
if (Interfaces[i]->EndPoints[0] != 0)
|
|
{
|
|
delete Interfaces[i]->EndPoints[0];
|
|
|
|
for (int j=0; j<MAX_INTERFACES; j++)
|
|
if (Interfaces[j])
|
|
Interfaces[j]->EndPoints[0] = NULL;
|
|
}
|
|
|
|
delete Interfaces[i];
|
|
Interfaces[i] = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// The CCyEndPoint ABSTRACT Class
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CCyUSBEndPoint::CCyUSBEndPoint(void)
|
|
{
|
|
hDevice = INVALID_HANDLE_VALUE;
|
|
|
|
DscLen = 0;
|
|
DscType = 0;
|
|
Address = 0;
|
|
Attributes = 0;
|
|
MaxPktSize = 0;
|
|
Interval = 0;
|
|
TimeOut = 10000; // 10 Sec timeout is default
|
|
bIn = false;
|
|
XferMode = XMODE_DIRECT;
|
|
LastError = 0;
|
|
// Initialize the SS companion descriptor with zero, as this constructore will be called for usb2.0 device
|
|
ssdscLen =0;
|
|
ssdscType =0;
|
|
ssmaxburst=0; /* Maximum number of packets endpoint can send in one burst*/
|
|
ssbmAttribute=0; // store endpoint attribute like for bulk it will be number of streams
|
|
ssbytesperinterval=0;
|
|
}
|
|
|
|
// Copy constructor
|
|
CCyUSBEndPoint::CCyUSBEndPoint(CCyUSBEndPoint& ept)
|
|
{
|
|
hDevice = ept.hDevice;
|
|
|
|
DscLen = ept.DscLen;
|
|
DscType = ept.DscType;
|
|
Address = ept.Address;
|
|
Attributes = ept.Attributes;
|
|
MaxPktSize = ept.MaxPktSize;
|
|
Interval = ept.Interval;
|
|
TimeOut = ept.TimeOut;
|
|
bIn = ept.bIn;
|
|
XferMode = ept.XferMode;
|
|
ssdscLen =ept.ssdscLen;
|
|
ssdscType =ept.ssdscType;
|
|
ssmaxburst=ept.ssmaxburst; /* Maximum number of packets endpoint can send in one burst*/
|
|
ssbmAttribute=ept.ssbmAttribute; // store endpoint attribute like for bulk it will be number of streams
|
|
ssbytesperinterval=ept.ssbytesperinterval;
|
|
LastError = 0;
|
|
}
|
|
|
|
CCyUSBEndPoint::CCyUSBEndPoint(HANDLE hDev, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor)
|
|
{
|
|
|
|
hDevice = hDev;
|
|
|
|
if (pEndPtDescriptor) {
|
|
PktsPerFrame = (pEndPtDescriptor->wMaxPacketSize & 0x1800) >> 11;
|
|
PktsPerFrame++;
|
|
|
|
DscLen = pEndPtDescriptor->bLength;
|
|
DscType = pEndPtDescriptor->bDescriptorType;
|
|
Address = pEndPtDescriptor->bEndpointAddress;
|
|
Attributes = pEndPtDescriptor->bmAttributes;
|
|
MaxPktSize = (pEndPtDescriptor->wMaxPacketSize & 0x7ff) * PktsPerFrame;
|
|
Interval = pEndPtDescriptor->bInterval;
|
|
bIn = ((Address & 0x80) == 0x80);
|
|
}
|
|
|
|
TimeOut = 10000; // 10 Sec timeout is default
|
|
|
|
XferMode = XMODE_DIRECT; // Normally, use Direct xfers
|
|
|
|
// Initialize the SS companion descriptor with zero, as this constructore will be called for usb2.0 device
|
|
ssdscLen =0;
|
|
ssdscType =0;
|
|
ssmaxburst=0; /* Maximum number of packets endpoint can send in one burst*/
|
|
ssbmAttribute=0; // store endpoint attribute like for bulk it will be number of streams
|
|
ssbytesperinterval=0;
|
|
|
|
}
|
|
|
|
|
|
CCyUSBEndPoint::CCyUSBEndPoint(HANDLE hDev, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor,USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR* SSEndPtDescriptor)
|
|
{
|
|
|
|
hDevice = hDev;
|
|
|
|
if (pEndPtDescriptor) {
|
|
PktsPerFrame = (pEndPtDescriptor->wMaxPacketSize & 0x1800) >> 11;
|
|
PktsPerFrame++;
|
|
|
|
DscLen = pEndPtDescriptor->bLength;
|
|
DscType = pEndPtDescriptor->bDescriptorType;
|
|
Address = pEndPtDescriptor->bEndpointAddress;
|
|
Attributes = pEndPtDescriptor->bmAttributes;
|
|
MaxPktSize = (pEndPtDescriptor->wMaxPacketSize & 0x7ff) * PktsPerFrame;
|
|
Interval = pEndPtDescriptor->bInterval;
|
|
bIn = ((Address & 0x80) == 0x80);
|
|
}
|
|
|
|
TimeOut = 10000; // 10 Sec timeout is default
|
|
|
|
XferMode = XMODE_DIRECT; // Normally, use Direct xfers
|
|
|
|
if(SSEndPtDescriptor != NULL)
|
|
{
|
|
ssdscLen =SSEndPtDescriptor->bLength;
|
|
ssdscType =SSEndPtDescriptor->bDescriptorType;
|
|
ssmaxburst=SSEndPtDescriptor->bMaxBurst; /* Maximum number of packets endpoint can send in one burst*/
|
|
MaxPktSize *=(ssmaxburst+1);
|
|
ssbmAttribute=SSEndPtDescriptor->bmAttributes; // store endpoint attribute like for bulk it will be number of streams
|
|
if((Attributes & 0x03) ==1) // MULT is valid for Isochronous transfer only
|
|
MaxPktSize*=((SSEndPtDescriptor->bmAttributes & 0x03)+1); // Adding the MULT fields.
|
|
|
|
ssbytesperinterval=SSEndPtDescriptor->bBytesPerInterval;
|
|
|
|
}
|
|
else
|
|
{
|
|
// Initialize the SS companion descriptor with zero
|
|
ssdscLen =0;
|
|
ssdscType =0;
|
|
ssmaxburst=0; /* Maximum number of packets endpoint can send in one burst*/
|
|
ssbmAttribute=0; // store endpoint attribute like for bulk it will be number of streams
|
|
ssbytesperinterval=0;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyUSBEndPoint::Reset(void)
|
|
{
|
|
DWORD dwBytes = 0;
|
|
bool RetVal = false;
|
|
|
|
RetVal = (DeviceIoControl(hDevice,
|
|
IOCTL_ADAPT_RESET_PIPE,
|
|
&Address,
|
|
sizeof(UCHAR),
|
|
NULL,
|
|
0,
|
|
&dwBytes,
|
|
0) !=0);
|
|
|
|
if(!RetVal) LastError = GetLastError();
|
|
return RetVal;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyUSBEndPoint::Abort(void)
|
|
{
|
|
DWORD dwBytes = 0;
|
|
bool RetVal = false;
|
|
OVERLAPPED ov;
|
|
|
|
memset(&ov,0,sizeof(ov));
|
|
ov.hEvent = CreateEvent(NULL,false,false,NULL);
|
|
|
|
RetVal = (DeviceIoControl(hDevice,
|
|
IOCTL_ADAPT_ABORT_PIPE,
|
|
&Address,
|
|
sizeof(UCHAR),
|
|
NULL,
|
|
0,
|
|
&dwBytes,
|
|
&ov)!=0);
|
|
if(!RetVal)
|
|
{
|
|
DWORD LastError = GetLastError();
|
|
if(LastError == ERROR_IO_PENDING)
|
|
WaitForSingleObject(ov.hEvent,1000);
|
|
}
|
|
CloseHandle(ov.hEvent);
|
|
return true;
|
|
|
|
}
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyUSBEndPoint::XferData(PUCHAR buf, LONG &bufLen, CCyIsoPktInfo* pktInfos)
|
|
{
|
|
|
|
OVERLAPPED ovLapStatus;
|
|
memset(&ovLapStatus,0,sizeof(OVERLAPPED));
|
|
|
|
ovLapStatus.hEvent = CreateEvent(NULL, false, false, NULL);
|
|
|
|
PUCHAR context = BeginDataXfer(buf, bufLen, &ovLapStatus);
|
|
bool wResult = WaitForIO(&ovLapStatus);
|
|
bool fResult = FinishDataXfer(buf, bufLen, &ovLapStatus, context, pktInfos);
|
|
|
|
CloseHandle(ovLapStatus.hEvent);
|
|
|
|
return wResult && fResult;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyUSBEndPoint::XferData(PUCHAR buf, LONG &bufLen, CCyIsoPktInfo* pktInfos, bool pktMode)
|
|
{
|
|
if ((bIn == false) || (pktMode == false))
|
|
{
|
|
return XferData(buf, bufLen);
|
|
}
|
|
else
|
|
{
|
|
int size = 0;
|
|
LONG xferLen = (LONG)MaxPktSize;
|
|
bool status = true;
|
|
PUCHAR ptr = buf;
|
|
|
|
while (status && (size < bufLen))
|
|
{
|
|
if ((bufLen - size) < MaxPktSize)
|
|
xferLen = bufLen - size;
|
|
|
|
status = XferData(ptr, xferLen);
|
|
if (status)
|
|
{
|
|
ptr += xferLen;
|
|
size += xferLen;
|
|
|
|
if (xferLen < MaxPktSize)
|
|
break;
|
|
}
|
|
}
|
|
|
|
bufLen = size;
|
|
if (bufLen > 0)
|
|
return true;
|
|
return status;
|
|
}
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyUSBEndPoint::FinishDataXfer(PUCHAR buf, LONG &bufLen, OVERLAPPED *ov, PUCHAR pXmitBuf, CCyIsoPktInfo* pktInfos)
|
|
{
|
|
DWORD bytes = 0;
|
|
bool rResult = (GetOverlappedResult(hDevice, ov, &bytes, FALSE)!=0);
|
|
|
|
PSINGLE_TRANSFER pTransfer = (PSINGLE_TRANSFER) pXmitBuf;
|
|
bufLen = (bytes) ? bytes - pTransfer->BufferOffset : 0;
|
|
bytesWritten = bufLen;
|
|
|
|
UsbdStatus = pTransfer->UsbdStatus;
|
|
NtStatus = pTransfer->NtStatus;
|
|
|
|
if (bIn && (XferMode == XMODE_BUFFERED) && (bufLen > 0)) {
|
|
UCHAR *ptr = (PUCHAR)pTransfer + pTransfer->BufferOffset;
|
|
memcpy (buf, ptr, bufLen);
|
|
}
|
|
|
|
// If a buffer was provided, pass-back the Isoc packet info records
|
|
if (pktInfos && (bufLen > 0)) {
|
|
ZeroMemory(pktInfos, pTransfer->IsoPacketLength);
|
|
PUCHAR pktPtr = pXmitBuf + pTransfer->IsoPacketOffset;
|
|
memcpy(pktInfos, pktPtr, pTransfer->IsoPacketLength);
|
|
}
|
|
|
|
delete[] pXmitBuf; // [] Changed in 1.5.1.3
|
|
|
|
return rResult && (UsbdStatus == 0) && (NtStatus == 0);
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
PUCHAR CCyUSBEndPoint::BeginBufferedXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov)
|
|
{
|
|
if ( hDevice == INVALID_HANDLE_VALUE ) return NULL;
|
|
|
|
int iXmitBufSize = sizeof (SINGLE_TRANSFER) + bufLen;
|
|
PUCHAR pXmitBuf = new UCHAR[iXmitBufSize];
|
|
ZeroMemory (pXmitBuf, iXmitBufSize);
|
|
|
|
PSINGLE_TRANSFER pTransfer = (PSINGLE_TRANSFER) pXmitBuf;
|
|
pTransfer->ucEndpointAddress = Address;
|
|
pTransfer->IsoPacketLength = 0;
|
|
pTransfer->BufferOffset = sizeof (SINGLE_TRANSFER);
|
|
pTransfer->BufferLength = bufLen;
|
|
|
|
// Copy buf into pXmitBuf
|
|
UCHAR *ptr = (PUCHAR) pTransfer + pTransfer->BufferOffset;
|
|
memcpy (ptr, buf, bufLen);
|
|
|
|
DWORD dwReturnBytes;
|
|
|
|
DeviceIoControl (hDevice,
|
|
IOCTL_ADAPT_SEND_NON_EP0_TRANSFER,
|
|
pXmitBuf,
|
|
iXmitBufSize,
|
|
pXmitBuf,
|
|
iXmitBufSize,
|
|
&dwReturnBytes,
|
|
ov);
|
|
|
|
UsbdStatus = pTransfer->UsbdStatus;
|
|
NtStatus = pTransfer->NtStatus;
|
|
|
|
LastError = GetLastError();
|
|
return pXmitBuf;
|
|
}
|
|
|
|
|
|
|
|
//______________________________________________________________________________
|
|
PUCHAR CCyUSBEndPoint::BeginDirectXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov)
|
|
{
|
|
if ( hDevice == INVALID_HANDLE_VALUE ) return NULL;
|
|
|
|
int iXmitBufSize = sizeof (SINGLE_TRANSFER);
|
|
PUCHAR pXmitBuf = new UCHAR[iXmitBufSize];
|
|
ZeroMemory (pXmitBuf, iXmitBufSize);
|
|
|
|
PSINGLE_TRANSFER pTransfer = (PSINGLE_TRANSFER) pXmitBuf;
|
|
pTransfer->ucEndpointAddress = Address;
|
|
pTransfer->IsoPacketLength = 0;
|
|
pTransfer->BufferOffset = 0;
|
|
pTransfer->BufferLength = 0;
|
|
|
|
DWORD dwReturnBytes;
|
|
DeviceIoControl (hDevice,
|
|
IOCTL_ADAPT_SEND_NON_EP0_DIRECT,
|
|
pXmitBuf,
|
|
iXmitBufSize,
|
|
buf,
|
|
bufLen,
|
|
&dwReturnBytes,
|
|
ov);
|
|
|
|
UsbdStatus = pTransfer->UsbdStatus;
|
|
NtStatus = pTransfer->NtStatus;
|
|
|
|
LastError = GetLastError();
|
|
return pXmitBuf;
|
|
}
|
|
|
|
|
|
|
|
//______________________________________________________________________________
|
|
// Unlike WaitForIO, this method does not record the bytes written or reset the
|
|
// endpoint if errors occurred. This method is called from the application level
|
|
// in conjunction with BeginDataXfer and FinishDataXfer
|
|
|
|
bool CCyUSBEndPoint::WaitForXfer(OVERLAPPED *ov, ULONG tOut)
|
|
{
|
|
|
|
//if (LastError == ERROR_SUCCESS) return true; // The command completed
|
|
|
|
//if (LastError == ERROR_IO_PENDING)
|
|
{
|
|
DWORD waitResult = WaitForSingleObject(ov->hEvent,tOut);
|
|
|
|
if (waitResult == WAIT_TIMEOUT) return false;
|
|
|
|
if (waitResult == WAIT_OBJECT_0) return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyUSBEndPoint::WaitForIO(OVERLAPPED *ovLapStatus)
|
|
{
|
|
LastError = GetLastError();
|
|
DWORD retcode =1;
|
|
|
|
if (LastError == ERROR_SUCCESS) return true; // The command completed
|
|
|
|
if (LastError == ERROR_IO_PENDING) {
|
|
DWORD waitResult = WaitForSingleObject(ovLapStatus->hEvent,TimeOut);
|
|
|
|
if (waitResult == WAIT_OBJECT_0) return true;
|
|
|
|
if (waitResult == WAIT_TIMEOUT)
|
|
{
|
|
Abort();
|
|
//// Wait for the stalled command to complete - should be done already
|
|
//retcode = WaitForSingleObject(ovLapStatus->hEvent,50); // Wait for 50 milisecond
|
|
Sleep(50);
|
|
|
|
//if(retcode == WAIT_TIMEOUT || retcode==WAIT_FAILED)
|
|
//{// Worst case condition , in multithreaded environment if user set time out to ZERO and cancel the IO the requiest, rarely first Abort() fail to cancel the IO, so reissueing second Abort(0.
|
|
//Abort();
|
|
//retcode = WaitForSingleObject(ovLapStatus->hEvent,INFINITE);
|
|
|
|
//}
|
|
}
|
|
}
|
|
|
|
return (retcode==0) ? true:false;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
ULONG CCyUSBEndPoint::GetXferSize(void){
|
|
|
|
ULONG ulTransferSize;
|
|
DWORD BytesXfered;
|
|
|
|
if (hDevice == INVALID_HANDLE_VALUE) return (ULONG) NULL;
|
|
|
|
SET_TRANSFER_SIZE_INFO SetTransferInfo;
|
|
|
|
ulTransferSize = 0;
|
|
SetTransferInfo.EndpointAddress = Address;
|
|
SetTransferInfo.TransferSize = ulTransferSize;
|
|
|
|
BOOL bRetVal = DeviceIoControl(hDevice,
|
|
IOCTL_ADAPT_GET_TRANSFER_SIZE,
|
|
&SetTransferInfo, sizeof(SET_TRANSFER_SIZE_INFO),
|
|
&SetTransferInfo, sizeof(SET_TRANSFER_SIZE_INFO),
|
|
&BytesXfered,
|
|
NULL);
|
|
|
|
if (bRetVal && BytesXfered >= sizeof(SET_TRANSFER_SIZE_INFO))
|
|
ulTransferSize = SetTransferInfo.TransferSize;
|
|
else
|
|
LastError = GetLastError();
|
|
|
|
return ulTransferSize;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
void CCyUSBEndPoint::SetXferSize(ULONG xfer){
|
|
|
|
if (hDevice == INVALID_HANDLE_VALUE) return;
|
|
|
|
DWORD BytesXfered;
|
|
SET_TRANSFER_SIZE_INFO SetTransferInfo;
|
|
|
|
if(MaxPktSize==0)
|
|
return;
|
|
// Force a multiple of MaxPktSize
|
|
ULONG pkts = (xfer % MaxPktSize) ? 1+(xfer / MaxPktSize) : (xfer / MaxPktSize);
|
|
ULONG xferSize = pkts * MaxPktSize;
|
|
|
|
SetTransferInfo.EndpointAddress = Address;
|
|
SetTransferInfo.TransferSize = xferSize;
|
|
|
|
if(DeviceIoControl(hDevice,
|
|
IOCTL_ADAPT_SET_TRANSFER_SIZE,
|
|
&SetTransferInfo, sizeof(SET_TRANSFER_SIZE_INFO),
|
|
&SetTransferInfo, sizeof(SET_TRANSFER_SIZE_INFO),
|
|
&BytesXfered,
|
|
NULL)==false)
|
|
{
|
|
LastError = GetLastError();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// The CCyControlEndPoint Class
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CCyControlEndPoint::CCyControlEndPoint(void):CCyUSBEndPoint()
|
|
{
|
|
|
|
Target = TGT_DEVICE;
|
|
ReqType = REQ_VENDOR;
|
|
Direction = DIR_TO_DEVICE;
|
|
|
|
ReqCode = 0;
|
|
Value = 0;
|
|
Index = 0;
|
|
|
|
XferMode = XMODE_BUFFERED;
|
|
|
|
}
|
|
|
|
// Copy Constructor
|
|
CCyControlEndPoint::CCyControlEndPoint(CCyControlEndPoint& ept):CCyUSBEndPoint(ept)
|
|
{
|
|
|
|
Target = ept.Target;
|
|
ReqType = ept.ReqType;
|
|
Direction = ept.Direction;
|
|
|
|
ReqCode = ept.ReqCode;
|
|
Value = ept.Value;
|
|
Index = ept.Index;
|
|
|
|
XferMode = ept.XferMode;
|
|
}
|
|
|
|
|
|
CCyControlEndPoint::CCyControlEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor) :
|
|
CCyUSBEndPoint(h, pEndPtDescriptor)
|
|
{
|
|
Target = TGT_DEVICE;
|
|
ReqType = REQ_VENDOR;
|
|
Direction = DIR_TO_DEVICE;
|
|
|
|
ReqCode = 0;
|
|
Value = 0;
|
|
Index = 0;
|
|
|
|
XferMode = XMODE_BUFFERED;
|
|
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyControlEndPoint::Read(PUCHAR buf, LONG &bufLen)
|
|
{
|
|
Direction = DIR_FROM_DEVICE;
|
|
return XferData(buf, bufLen);
|
|
}
|
|
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyControlEndPoint::Write(PUCHAR buf, LONG &bufLen)
|
|
{
|
|
Direction = DIR_TO_DEVICE;
|
|
return XferData(buf, bufLen);
|
|
}
|
|
|
|
|
|
//______________________________________________________________________________
|
|
|
|
PUCHAR CCyControlEndPoint::BeginDataXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov)
|
|
{
|
|
union {
|
|
struct {
|
|
UCHAR Recipient:5;
|
|
UCHAR Type:2;
|
|
UCHAR Direction:1;
|
|
} bmRequest;
|
|
|
|
UCHAR bmReq;
|
|
};
|
|
|
|
if ( hDevice == INVALID_HANDLE_VALUE ) return NULL;
|
|
|
|
bmRequest.Recipient = Target;
|
|
bmRequest.Type = ReqType;
|
|
bmRequest.Direction = Direction;
|
|
|
|
bIn = (Direction == DIR_FROM_DEVICE);
|
|
|
|
int iXmitBufSize = sizeof (SINGLE_TRANSFER) + bufLen;
|
|
UCHAR *pXmitBuf = new UCHAR[iXmitBufSize];
|
|
ZeroMemory (pXmitBuf, iXmitBufSize);
|
|
|
|
// The Control Endpoint has a 1 sec resolution on its timeout
|
|
// But, TimeOut is in milliseconds.
|
|
ULONG tmo = ((TimeOut > 0) && (TimeOut < 1000)) ? 1 : TimeOut / 1000;
|
|
|
|
PSINGLE_TRANSFER pTransfer = (PSINGLE_TRANSFER) pXmitBuf;
|
|
pTransfer->SetupPacket.bmRequest = bmReq;
|
|
pTransfer->SetupPacket.bRequest = ReqCode;
|
|
pTransfer->SetupPacket.wValue = Value;
|
|
pTransfer->SetupPacket.wIndex = Index;
|
|
pTransfer->SetupPacket.wLength = (USHORT)bufLen;
|
|
pTransfer->SetupPacket.ulTimeOut = tmo; // Seconds, not milliseconds
|
|
pTransfer->ucEndpointAddress = 0x00; // control pipe
|
|
pTransfer->IsoPacketLength = 0;
|
|
pTransfer->BufferOffset = sizeof (SINGLE_TRANSFER);
|
|
pTransfer->BufferLength = bufLen;
|
|
|
|
// Copy buf into pXmitBuf
|
|
UCHAR *ptr = pXmitBuf + sizeof (SINGLE_TRANSFER);
|
|
memcpy (ptr, buf, bufLen);
|
|
|
|
DWORD dwReturnBytes;
|
|
DeviceIoControl (hDevice,
|
|
IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER,
|
|
pXmitBuf,
|
|
iXmitBufSize,
|
|
pXmitBuf,
|
|
iXmitBufSize,
|
|
&dwReturnBytes,
|
|
ov);
|
|
|
|
// Note that this method leaves pXmitBuf allocated. It will get deleted in
|
|
// FinishDataXfer.
|
|
|
|
LastError = GetLastError();
|
|
return pXmitBuf;
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// The CCyIsocEndPoint Class
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CCyIsocEndPoint::CCyIsocEndPoint(void) : CCyUSBEndPoint()
|
|
{
|
|
}
|
|
|
|
CCyIsocEndPoint::CCyIsocEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor) :
|
|
CCyUSBEndPoint(h, pEndPtDescriptor)
|
|
{
|
|
}
|
|
CCyIsocEndPoint::CCyIsocEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor,USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR* SSEndPtDescriptor) :
|
|
CCyUSBEndPoint(h, pEndPtDescriptor,SSEndPtDescriptor)
|
|
{
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
PUCHAR CCyIsocEndPoint::BeginDataXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov)
|
|
{
|
|
if ( hDevice == INVALID_HANDLE_VALUE ) return NULL;
|
|
|
|
if (XferMode == XMODE_DIRECT)
|
|
return BeginDirectXfer(buf, bufLen, ov);
|
|
else
|
|
return BeginBufferedXfer(buf, bufLen, ov);
|
|
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
PUCHAR CCyIsocEndPoint::BeginBufferedXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov)
|
|
{
|
|
if ( hDevice == INVALID_HANDLE_VALUE ) return NULL;
|
|
|
|
int pkts;
|
|
if(MaxPktSize)
|
|
pkts = bufLen / MaxPktSize; // Number of packets implied by bufLen & pktSize
|
|
else
|
|
{
|
|
pkts = 0;
|
|
return NULL;
|
|
}
|
|
|
|
if (bufLen % MaxPktSize) pkts++;
|
|
|
|
if (pkts == 0) return NULL;
|
|
|
|
int iXmitBufSize = sizeof (SINGLE_TRANSFER) + (pkts * sizeof(ISO_PACKET_INFO)) + bufLen;
|
|
UCHAR *pXmitBuf = new UCHAR[iXmitBufSize];
|
|
ZeroMemory (pXmitBuf, iXmitBufSize);
|
|
|
|
PSINGLE_TRANSFER pTransfer = (PSINGLE_TRANSFER) pXmitBuf;
|
|
pTransfer->ucEndpointAddress = Address;
|
|
pTransfer->IsoPacketOffset = sizeof (SINGLE_TRANSFER);
|
|
pTransfer->IsoPacketLength = pkts * sizeof(ISO_PACKET_INFO);
|
|
pTransfer->BufferOffset = sizeof (SINGLE_TRANSFER) + pTransfer->IsoPacketLength;
|
|
pTransfer->BufferLength = bufLen;
|
|
|
|
// Copy buf into pXmitBuf
|
|
UCHAR *ptr = pXmitBuf + pTransfer->BufferOffset;
|
|
memcpy (ptr, buf, bufLen);
|
|
|
|
DWORD dwReturnBytes = 0;
|
|
|
|
DeviceIoControl (hDevice,
|
|
IOCTL_ADAPT_SEND_NON_EP0_TRANSFER,
|
|
pXmitBuf,
|
|
iXmitBufSize,
|
|
pXmitBuf,
|
|
iXmitBufSize,
|
|
&dwReturnBytes,
|
|
ov);
|
|
|
|
// Note that this method leaves pXmitBuf allocated. It will get deleted in
|
|
// FinishDataXfer.
|
|
|
|
UsbdStatus = pTransfer->UsbdStatus;
|
|
NtStatus = pTransfer->NtStatus;
|
|
|
|
LastError = GetLastError();
|
|
return pXmitBuf;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
PUCHAR CCyIsocEndPoint::BeginDirectXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov)
|
|
{
|
|
if ( hDevice == INVALID_HANDLE_VALUE ) return NULL;
|
|
|
|
int pkts;
|
|
if(MaxPktSize)
|
|
pkts = bufLen / MaxPktSize; // Number of packets implied by bufLen & pktSize
|
|
else
|
|
{
|
|
pkts = 0;
|
|
return NULL;
|
|
}
|
|
|
|
if (bufLen % MaxPktSize) pkts++;
|
|
|
|
if (pkts == 0) return NULL;
|
|
|
|
int iXmitBufSize = sizeof (SINGLE_TRANSFER) + (pkts * sizeof(ISO_PACKET_INFO));
|
|
UCHAR *pXmitBuf = new UCHAR[iXmitBufSize];
|
|
ZeroMemory (pXmitBuf, iXmitBufSize);
|
|
|
|
PSINGLE_TRANSFER pTransfer = (PSINGLE_TRANSFER) pXmitBuf;
|
|
pTransfer->ucEndpointAddress = Address;
|
|
pTransfer->IsoPacketOffset = sizeof (SINGLE_TRANSFER);
|
|
pTransfer->IsoPacketLength = pkts * sizeof(ISO_PACKET_INFO);
|
|
pTransfer->BufferOffset = 0;
|
|
pTransfer->BufferLength = 0;
|
|
|
|
DWORD dwReturnBytes = 0;
|
|
DeviceIoControl (hDevice,
|
|
IOCTL_ADAPT_SEND_NON_EP0_DIRECT,
|
|
pXmitBuf,
|
|
iXmitBufSize,
|
|
buf,
|
|
bufLen,
|
|
&dwReturnBytes,
|
|
ov);
|
|
|
|
// Note that this method leaves pXmitBuf allocated. It will get deleted in
|
|
// FinishDataXfer.
|
|
|
|
UsbdStatus = pTransfer->UsbdStatus;
|
|
NtStatus = pTransfer->NtStatus;
|
|
|
|
LastError = GetLastError();
|
|
return pXmitBuf;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// The CCyFX3Device Class
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
CCyFX3Device::CCyFX3Device()
|
|
{
|
|
}
|
|
CCyFX3Device::~CCyFX3Device()
|
|
{
|
|
}
|
|
bool CCyFX3Device::Ep0VendorCommand(vendorCmdData cmdData)
|
|
{
|
|
ControlEndPt->Target = TGT_DEVICE ;
|
|
ControlEndPt->ReqType = REQ_VENDOR ;
|
|
ControlEndPt->ReqCode = cmdData.opCode ;
|
|
ControlEndPt->Direction = (cmdData.isRead) ? DIR_FROM_DEVICE : DIR_TO_DEVICE ;
|
|
|
|
ControlEndPt->Value = (cmdData.addr & 0xFFFF);
|
|
ControlEndPt->Index = ((cmdData.addr >> 16) & 0xFFFF);
|
|
|
|
int maxpkt = ControlEndPt->MaxPktSize;
|
|
|
|
long len = cmdData.size;
|
|
|
|
/* Handle the case where transfer length is 0 (used to send the Program Entry) */
|
|
if (cmdData.size == 0)
|
|
return ControlEndPt->XferData(cmdData.buf, len, NULL);
|
|
else
|
|
{
|
|
bool bRetCode = false;
|
|
long Stagelen = 0;
|
|
int BufIndex = 0;
|
|
while (len > 0)
|
|
{
|
|
if (len >= 65535)
|
|
Stagelen = 65535;
|
|
else
|
|
Stagelen = (len) % 65535;
|
|
|
|
/* Allocate the buffer */
|
|
PUCHAR StageBuf = new UCHAR[Stagelen];
|
|
|
|
if (!cmdData.isRead)
|
|
{
|
|
/*write operation */
|
|
for (int i = 0; i < Stagelen; i++)
|
|
StageBuf[i] = cmdData.buf[BufIndex + i];
|
|
}
|
|
|
|
bRetCode = ControlEndPt->XferData(StageBuf, Stagelen, NULL);
|
|
if (!bRetCode)
|
|
{
|
|
if(StageBuf)
|
|
delete[] StageBuf;
|
|
|
|
return false;
|
|
}
|
|
|
|
if (cmdData.isRead)
|
|
{
|
|
/*read operation */
|
|
for (int i = 0; i < Stagelen; i++)
|
|
cmdData.buf[BufIndex + i] = StageBuf[i];
|
|
}
|
|
|
|
if(StageBuf)
|
|
delete[] StageBuf;
|
|
|
|
len -= Stagelen;
|
|
BufIndex += Stagelen;
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
/* Function to transmit data on the control endpoint. */
|
|
bool CCyFX3Device::DownloadBufferToDevice(UINT start_addr, USHORT count, UCHAR *data_buf, UCHAR opCode)
|
|
{
|
|
vendorCmdData cmdData;
|
|
cmdData.addr = start_addr;
|
|
|
|
cmdData.isRead = 0;
|
|
cmdData.buf = data_buf;
|
|
cmdData.opCode = opCode;
|
|
cmdData.size = count;
|
|
|
|
return Ep0VendorCommand(cmdData);
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
/* Function to read data using control endpoint. */
|
|
bool CCyFX3Device::UploadBufferFromDevice(UINT start_addr, USHORT count, UCHAR *data_buf, UCHAR opCode)
|
|
{
|
|
vendorCmdData cmdData;
|
|
cmdData.addr = start_addr;
|
|
|
|
cmdData.isRead = 1;
|
|
cmdData.buf = data_buf;
|
|
cmdData.opCode = opCode;
|
|
cmdData.size = count;
|
|
|
|
return Ep0VendorCommand(cmdData);
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
/* This function sends out the 0xA0 vendor request for transferring the control to
|
|
program entry point.
|
|
*/
|
|
bool CCyFX3Device::SetProgramEntry (UCHAR opCode,UINT start_addr)
|
|
{
|
|
vendorCmdData cmdData;
|
|
cmdData.addr = ((start_addr >> 16) | (start_addr << 16)); /* swap LSB and MSB */
|
|
|
|
cmdData.isRead = 0;
|
|
cmdData.buf = NULL;
|
|
cmdData.opCode = opCode;
|
|
cmdData.size = 0;
|
|
|
|
return Ep0VendorCommand(cmdData);
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyFX3Device::IsBootLoaderRunning()
|
|
{
|
|
/*Dire : in, Target : Device, ReqCode:0xA0,wValue:0x0000,wIndex:0x0000 */
|
|
/* This function checks for bootloader,it will return false if it is not running. */
|
|
UCHAR buf[1];
|
|
long len = 1;
|
|
bool ret;
|
|
UCHAR opCode = 0xA0; // Vendore command
|
|
|
|
vendorCmdData cmdData;
|
|
|
|
cmdData.addr = 0x0000;
|
|
|
|
cmdData.isRead = true;
|
|
cmdData.buf = buf;
|
|
cmdData.opCode = opCode;
|
|
cmdData.size = len;
|
|
|
|
/* Value = isErase, index = sector number */
|
|
ret = Ep0VendorCommand(cmdData);
|
|
return ret;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
FX3_FWDWNLOAD_ERROR_CODE CCyFX3Device::EraseSectorOfSPIFlash(UINT SectorNumber, UCHAR opCode)
|
|
{
|
|
vendorCmdData cmdData;
|
|
bool ret;
|
|
UCHAR buf[1];
|
|
UINT buflen = 0;
|
|
buf[0] = 1;
|
|
|
|
cmdData.addr = (1 + (SectorNumber << 16));
|
|
|
|
cmdData.isRead = false;
|
|
cmdData.buf = buf;
|
|
cmdData.opCode = opCode;
|
|
cmdData.size = buflen;
|
|
|
|
/* Value = isErase, index = sector number */
|
|
ret = Ep0VendorCommand(cmdData);
|
|
if (ret)
|
|
{
|
|
/* Check the status of erase. Value should be 0 */
|
|
buflen = 1;
|
|
cmdData.size = buflen;
|
|
while (buf[0] != 0)
|
|
{
|
|
cmdData.isRead = true;
|
|
cmdData.addr = (0 + (SectorNumber << 16));
|
|
if (!Ep0VendorCommand(cmdData))
|
|
return FAILED;
|
|
}
|
|
}
|
|
else
|
|
return FAILED;
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
bool CCyFX3Device::WriteToSPIFlash(PUCHAR Buf, UINT buflen, UINT ByteAddress, UCHAR opCode)
|
|
{
|
|
vendorCmdData cmdData;
|
|
cmdData.addr = ((ByteAddress / SPI_FLASH_PAGE_SIZE_IN_BYTE) << 16); // swap LSB and MSB
|
|
|
|
cmdData.isRead = 0;
|
|
cmdData.buf = Buf;
|
|
cmdData.opCode = opCode;
|
|
cmdData.size = buflen;
|
|
|
|
return Ep0VendorCommand(cmdData);
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
FX3_FWDWNLOAD_ERROR_CODE CCyFX3Device::DownloadUserIMGtoSPIFLASH(PUCHAR buffer_p, UINT fw_size, UCHAR opCode)
|
|
{
|
|
/* The size of the image needs to be rounded to a multiple of the SPI page size. */
|
|
UINT ImageSizeInPage = (fw_size + SPI_FLASH_PAGE_SIZE_IN_BYTE - 1) / SPI_FLASH_PAGE_SIZE_IN_BYTE;
|
|
UINT TotalNumOfByteToWrote = ImageSizeInPage * SPI_FLASH_PAGE_SIZE_IN_BYTE;
|
|
/* Sectors needs to be erased in case of SPI. Sector size = 64k. Page Size = 256 bytes. 1 Sector = 256 pages. */
|
|
/* Calculate the number of sectors needed to write firmware image and erase them. */
|
|
UINT NumOfSector = fw_size / SPI_FLASH_SECTOR_SIZE_IN_BYTE;
|
|
if ((fw_size % SPI_FLASH_SECTOR_SIZE_IN_BYTE) != 0)
|
|
NumOfSector++;
|
|
|
|
/* Erase the sectors */
|
|
for (UINT i = 0; i < NumOfSector; i++)
|
|
{
|
|
if (EraseSectorOfSPIFlash(i, opCode) != SUCCESS)
|
|
return SPILASH_ERASE_FAILED;
|
|
}
|
|
|
|
/*Write the firmware to the SPI flash */
|
|
UINT numberOfBytesLeftToWrite = TotalNumOfByteToWrote; /* Current number of bytes left to write */
|
|
|
|
UINT FwFilePointer = 0;
|
|
UINT massStorageByteAddress = 0; /* Current Mass Storage Byte Address */
|
|
|
|
PUCHAR WriteBuf = new UCHAR[CYWB_BL_MAX_BUFFER_SIZE_WHEN_USING_EP0_TRANSPORT];
|
|
|
|
while (numberOfBytesLeftToWrite > 0)
|
|
{
|
|
UINT numberOfBytesToWrite = CYWB_BL_MAX_BUFFER_SIZE_WHEN_USING_EP0_TRANSPORT;
|
|
|
|
if (numberOfBytesLeftToWrite < CYWB_BL_MAX_BUFFER_SIZE_WHEN_USING_EP0_TRANSPORT)
|
|
{
|
|
numberOfBytesToWrite = numberOfBytesLeftToWrite;
|
|
}
|
|
|
|
/* Trigger a mass storage write... */
|
|
for (UINT i = 0; i < numberOfBytesToWrite; i++)
|
|
{
|
|
if ((FwFilePointer + i) < fw_size)
|
|
WriteBuf[i] = buffer_p[i + FwFilePointer];
|
|
}
|
|
opCode = 0xC2; // Operation code to Write to SPI
|
|
if (WriteToSPIFlash(WriteBuf, numberOfBytesToWrite, massStorageByteAddress, opCode) == false)
|
|
{
|
|
if(WriteBuf)
|
|
delete[] WriteBuf;
|
|
|
|
return FAILED;
|
|
}
|
|
|
|
/* Adjust pointers */
|
|
numberOfBytesLeftToWrite -= numberOfBytesToWrite;
|
|
FwFilePointer += numberOfBytesToWrite;
|
|
massStorageByteAddress += numberOfBytesToWrite;
|
|
}
|
|
|
|
if(WriteBuf)
|
|
delete[] WriteBuf;
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
FX3_FWDWNLOAD_ERROR_CODE CCyFX3Device::DownloadUserIMGtoI2CE2PROM(PUCHAR buffer_p, UINT fw_size, UCHAR opCode)
|
|
{
|
|
int STAGE_SIZE = BUFSIZE_UPORT;
|
|
PUCHAR downloadbuf = new UCHAR[STAGE_SIZE];
|
|
|
|
int NoOfStage = ((int)fw_size / STAGE_SIZE);
|
|
long LastStage = ((int)fw_size % STAGE_SIZE);
|
|
UINT DownloadAddress = 0;
|
|
long FwImagePtr = 0;
|
|
long StageSize = STAGE_SIZE;
|
|
|
|
//Get the I2C addressing size
|
|
UCHAR ImgI2CSizeByte = buffer_p[2]; // the 2nd byte of the IMG file will tell us the I2EPROM internal addressing.
|
|
UINT AddresingStageSize = 0;
|
|
ImgI2CSizeByte = ((ImgI2CSizeByte >> 1) & 0x07); // Bit3:1 represent the addressing
|
|
bool IsMicroShipE2Prom = false;
|
|
|
|
switch (ImgI2CSizeByte)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
return I2CE2PROM_UNKNOWN_I2C_SIZE;
|
|
case 2:
|
|
AddresingStageSize = (4 * 1024); // 4KByte
|
|
break;
|
|
case 3:
|
|
AddresingStageSize = (8 * 1024); // 8KByte
|
|
break;
|
|
case 4:
|
|
AddresingStageSize = (16 * 1024); // 16KByte
|
|
break;
|
|
case 5:
|
|
AddresingStageSize = (32 * 1024); // 32KByte
|
|
break;
|
|
case 6:
|
|
AddresingStageSize = (64 * 1024); // 64KByte
|
|
break;
|
|
case 7:
|
|
IsMicroShipE2Prom = true; // 128KByte Addressing for Microchip.
|
|
AddresingStageSize = (64 * 1024); // 64KByte // case 7 represent 128Kbyte but it follow 64Kbyte addressing
|
|
break;
|
|
default:
|
|
{
|
|
if(downloadbuf)
|
|
delete[] downloadbuf;
|
|
|
|
return I2CE2PROM_UNKNOWN_I2C_SIZE;
|
|
}
|
|
}
|
|
|
|
|
|
ControlEndPt->Target = TGT_DEVICE ;
|
|
ControlEndPt->ReqType = REQ_VENDOR ;
|
|
ControlEndPt->ReqCode = opCode ;
|
|
ControlEndPt->Direction = DIR_TO_DEVICE ;
|
|
|
|
ControlEndPt->Value = (DownloadAddress & 0xFFFF);
|
|
ControlEndPt->Index = ((DownloadAddress >> 16) & 0xFFFF);
|
|
int maxpkt = ControlEndPt->MaxPktSize;
|
|
|
|
for (int i = 0; i < NoOfStage; i++)
|
|
{
|
|
/* Copy data from main buffer to tmp buffer */
|
|
for (long j = 0; j < STAGE_SIZE; j++)
|
|
downloadbuf[j] = buffer_p[FwImagePtr + j];
|
|
|
|
if (!ControlEndPt->XferData(downloadbuf, StageSize, NULL))
|
|
{
|
|
if(downloadbuf)
|
|
delete[] downloadbuf;
|
|
|
|
return FAILED;
|
|
}
|
|
|
|
FwImagePtr += STAGE_SIZE;
|
|
ControlEndPt->Index += (WORD)StageSize;
|
|
|
|
/////
|
|
// Address calculation done in the below box
|
|
if (IsMicroShipE2Prom)
|
|
{//Microchip Addressing(0-(1-64),4(64 to 128),1(128 to 192 ),5(192 to 256))
|
|
if (FwImagePtr >= (128 * 1024))
|
|
{
|
|
if ((FwImagePtr % AddresingStageSize) == 0)
|
|
{
|
|
if (ControlEndPt->Value == 0x04)
|
|
ControlEndPt->Value = 0x01;
|
|
else
|
|
ControlEndPt->Value = 0x05;
|
|
|
|
ControlEndPt->Index = 0;
|
|
}
|
|
}
|
|
else if ((FwImagePtr % AddresingStageSize) == 0)
|
|
{
|
|
ControlEndPt->Value = 0x04;
|
|
ControlEndPt->Index = 0;
|
|
}
|
|
}
|
|
else
|
|
{//ATMEL addressing sequential
|
|
if ((FwImagePtr % AddresingStageSize)==0)
|
|
{// Increament the Value field to represent the address and reset the Index value to zero.
|
|
ControlEndPt->Value += 0x01;
|
|
if(ControlEndPt->Value>=8)
|
|
ControlEndPt->Value = 0x0; //reset the Address to ZERO
|
|
|
|
ControlEndPt->Index = 0;
|
|
}
|
|
}
|
|
/////
|
|
|
|
|
|
}
|
|
|
|
if (LastStage != 0)
|
|
{
|
|
/*check for last stage */
|
|
|
|
for (long j = 0; j < LastStage; j++)
|
|
downloadbuf[j] = buffer_p[FwImagePtr + j];
|
|
|
|
if ((LastStage % maxpkt) != 0)
|
|
{
|
|
/* make it multiple of max packet size */
|
|
int diff = (maxpkt - (LastStage % maxpkt));
|
|
for (int j = LastStage; j < (LastStage + diff); j++)
|
|
downloadbuf[j] = 0;
|
|
|
|
LastStage += diff;
|
|
}
|
|
|
|
if (!ControlEndPt->XferData(downloadbuf, LastStage, NULL))
|
|
{
|
|
if(downloadbuf)
|
|
delete[] downloadbuf;
|
|
|
|
return FAILED;
|
|
}
|
|
|
|
/*Failure Case:
|
|
The device does not return failure message when file size is more than 128KByte and only one 128Byte E2PROM on the DVK.
|
|
Solution:
|
|
Read back the last stage data to confirm that all data transferred successfully.*/
|
|
ControlEndPt->ReqCode = 0xBB;
|
|
ControlEndPt->Direction = DIR_FROM_DEVICE;
|
|
if (!ControlEndPt->XferData(downloadbuf, LastStage, NULL))
|
|
{
|
|
if(downloadbuf)
|
|
delete[] downloadbuf;
|
|
|
|
return FAILED;
|
|
}
|
|
}
|
|
|
|
if(downloadbuf)
|
|
delete[] downloadbuf;
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
FX3_FWDWNLOAD_ERROR_CODE CCyFX3Device::DownloadFwToRam(PUCHAR buffer_p, UINT fw_size, UCHAR opCode)
|
|
{
|
|
UCHAR downloadBuffer[BUFSIZE_UPORT];
|
|
UCHAR uploadbuffer[BUFSIZE_UPORT];
|
|
bool isTrue = true;
|
|
UINT ComputeCheckSum = 0;
|
|
UINT ExpectedCheckSum = 0;
|
|
INT fwImagePtr = 0;
|
|
UINT SectionLength = 0;
|
|
UINT SectionAddress;
|
|
UINT DownloadAddress;
|
|
UINT ProgramEntry;
|
|
|
|
/* Initialize computed checksum */
|
|
ComputeCheckSum = 0;
|
|
|
|
/* Check "CY" signature (0x43,0x59) and download the firmware image */
|
|
if ((buffer_p[fwImagePtr] != 0x43) || (buffer_p[fwImagePtr + 1] != 0x59))
|
|
{ /*signature doesn't match */
|
|
return INVALID_FWSIGNATURE;
|
|
}
|
|
|
|
/* Skip the two bytes signature and the following two bytes */
|
|
fwImagePtr += 4;
|
|
|
|
/* Download one section at a time to the device, compute checksum, and upload-verify it */
|
|
while (isTrue)
|
|
{
|
|
/* Get section length (4 bytes) and convert it from 32-bit word count to byte count */
|
|
CYWB_BL_4_BYTES_COPY(&SectionLength, &buffer_p[fwImagePtr]);
|
|
fwImagePtr += 4;
|
|
|
|
SectionLength = SectionLength << 2;
|
|
|
|
/* If length = 0, the transfer is complete */
|
|
if (SectionLength == 0) break;
|
|
|
|
/* Get section address (4 bytes) */
|
|
CYWB_BL_4_BYTES_COPY(&SectionAddress, &buffer_p[fwImagePtr]);
|
|
fwImagePtr += 4;
|
|
|
|
/* Download BUFSIZE_UPORT maximum bytes at a time */
|
|
INT bytesLeftToDownload = SectionLength;
|
|
DownloadAddress = SectionAddress;
|
|
|
|
while (bytesLeftToDownload > 0)
|
|
{
|
|
INT bytesToTransfer = BUFSIZE_UPORT;
|
|
if (bytesLeftToDownload < BUFSIZE_UPORT)
|
|
bytesToTransfer = bytesLeftToDownload;
|
|
|
|
/* sanity check for incomplete fw with valid signatures.
|
|
Note: bytesToTransfer should never be greater then fw length i.e buflen */
|
|
if (bytesToTransfer > (INT)fw_size)
|
|
return CORRUPT_FIRMWARE_IMAGE_FILE;
|
|
|
|
memcpy(downloadBuffer, (void *)(buffer_p + fwImagePtr), bytesToTransfer);
|
|
|
|
/* Compute checksum: Here transferLength is assumed to be a multiple of 4. If it is not, the checksum will fail anyway */
|
|
for (INT index = 0; index < bytesToTransfer; index += 4)
|
|
{
|
|
UINT buf32bits = 0;
|
|
CYWB_BL_4_BYTES_COPY(&buf32bits, &downloadBuffer[index]);
|
|
ComputeCheckSum += buf32bits;
|
|
}
|
|
|
|
/*The FPGA does not seem to always be reliable: if an error is encountered, try again twice */
|
|
INT maxTryCount = 3;
|
|
for (INT tryCount = 1; tryCount <= maxTryCount; tryCount++)
|
|
{
|
|
/* Download one buffer worth of data to the device */
|
|
if (!DownloadBufferToDevice(DownloadAddress, bytesToTransfer, downloadBuffer, opCode))
|
|
{
|
|
/* Check if we exceeded the max try count */
|
|
if (tryCount == maxTryCount)
|
|
{
|
|
/* Failure while downloading firmware to the device. Abort */
|
|
return FAILED;
|
|
}
|
|
else
|
|
{
|
|
/* F/W buffer download failure. Trying writing/verifying current buffer again... */
|
|
continue;
|
|
}
|
|
}
|
|
|
|
memset (uploadbuffer, 0, bytesToTransfer);
|
|
|
|
if (!UploadBufferFromDevice(DownloadAddress, bytesToTransfer, uploadbuffer, opCode))
|
|
{
|
|
/* Check if we exceeded the max try count */
|
|
if (tryCount == maxTryCount)
|
|
{
|
|
/* Failure while uploading firmware from the device for verification. Abort */
|
|
return FAILED;
|
|
}
|
|
else
|
|
{
|
|
/* F/W buffer upload failure. Trying writing/verifying current buffer again... */
|
|
continue;
|
|
}
|
|
}
|
|
|
|
for (int count = 0; count < bytesToTransfer; count++)
|
|
{
|
|
if (downloadBuffer[count] != uploadbuffer[count])
|
|
{
|
|
/* Check if we exceeded the max try count */
|
|
if (tryCount == maxTryCount)
|
|
{
|
|
/* Uploaded firmware data does not match downloaded data. Abort */
|
|
return FAILED;
|
|
}
|
|
else
|
|
{
|
|
/* Uploaded data does not match downloaded data. Trying writing/verifying current buffer again...*/
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
DownloadAddress += bytesToTransfer;
|
|
fwImagePtr += bytesToTransfer;
|
|
bytesLeftToDownload -= bytesToTransfer;
|
|
|
|
/* Sanity check */
|
|
if (fwImagePtr > (INT)fw_size)
|
|
return INCORRECT_IMAGE_LENGTH;
|
|
}
|
|
}
|
|
|
|
/* Get Program Entry Address(4 bytes) */
|
|
CYWB_BL_4_BYTES_COPY(&ProgramEntry, &buffer_p[fwImagePtr]);
|
|
fwImagePtr += 4;
|
|
|
|
/* Get expected checksum (4 bytes) */
|
|
CYWB_BL_4_BYTES_COPY(&ExpectedCheckSum, &buffer_p[fwImagePtr]);
|
|
fwImagePtr += 4;
|
|
|
|
/* Compare computed checksum against expected value */
|
|
if (ComputeCheckSum != ExpectedCheckSum)
|
|
{
|
|
/* CheckSum mismatch. Expected=0x" << std::hex << expectedCheckSum << " Computed=0x" << std::hex << computedCheckSum; */
|
|
}
|
|
|
|
/* Transfer execution to Program Entry */
|
|
UCHAR dummyBuffer[1];
|
|
// Few of the xHCI driver stack have issue with Control IN transfer,due to that below request fails ,
|
|
// Control IN transfer is ZERO lenght packet , and it does not have any impact on execution of firmware.
|
|
//if (!DownloadBufferToDevice(ProgramEntry, 0, dummyBuffer, opCode))
|
|
//{
|
|
// /* Downloading Program Entry failed */
|
|
// return FAILED;
|
|
//}
|
|
DownloadBufferToDevice(ProgramEntry, 0, dummyBuffer, opCode);
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
FX3_FWDWNLOAD_ERROR_CODE CCyFX3Device::DownloadFw(char *fileName, FX3_FWDWNLOAD_MEDIA_TYPE enMediaType)
|
|
{
|
|
UINT fwSize = 0;
|
|
PUCHAR FwImage;
|
|
FILE *FwImagePtr;
|
|
int error;
|
|
|
|
// error = fopen_s(&FwImagePtr, fileName, "rb");
|
|
FwImagePtr = fopen( fileName, "rb");
|
|
if (FwImagePtr == NULL)
|
|
return INVALID_FILE;
|
|
|
|
/* Find the length of the image */
|
|
fseek (FwImagePtr, 0, SEEK_END);
|
|
fwSize = ftell(FwImagePtr);
|
|
fseek (FwImagePtr, 0, SEEK_SET);
|
|
|
|
/* Allocate memory for the image */
|
|
FwImage = new unsigned char[fwSize];
|
|
|
|
if (FwImage == NULL)
|
|
return INVALID_FILE;
|
|
|
|
if (fwSize <= 0)
|
|
{
|
|
fclose (FwImagePtr);
|
|
return INVALID_FILE;
|
|
}
|
|
|
|
/* Read into buffer */
|
|
fread (FwImage, fwSize, 1, FwImagePtr);
|
|
fclose (FwImagePtr);
|
|
|
|
FX3_FWDWNLOAD_ERROR_CODE ErroCode = SUCCESS;
|
|
// call api to download the image
|
|
if (enMediaType == RAM)
|
|
ErroCode = DownloadFwToRam(FwImage, fwSize, 0xA0);
|
|
else if (enMediaType == I2CE2PROM)
|
|
ErroCode = DownloadUserIMGtoI2CE2PROM(FwImage, fwSize, 0xBA);
|
|
else if (enMediaType == SPIFLASH)
|
|
ErroCode = DownloadUserIMGtoSPIFLASH(FwImage, fwSize, 0xC4);
|
|
else
|
|
ErroCode = INVALID_MEDIA_TYPE;
|
|
|
|
if(FwImage)
|
|
delete[] FwImage;
|
|
|
|
return ErroCode;
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
CCyIsoPktInfo* CCyIsocEndPoint::CreatePktInfos(LONG bufLen, int &packets)
|
|
{
|
|
if(MaxPktSize==0)
|
|
return NULL;
|
|
|
|
packets = bufLen / MaxPktSize; // Number of packets implied by bufLen & pktSize
|
|
if (bufLen % MaxPktSize) packets++;
|
|
|
|
if (packets) {
|
|
CCyIsoPktInfo *isoPktInfos = new CCyIsoPktInfo[packets];
|
|
return isoPktInfos;
|
|
} else
|
|
return NULL;
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// The CCyBulkEndPoint Class
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CCyBulkEndPoint::CCyBulkEndPoint(void) : CCyUSBEndPoint()
|
|
{
|
|
}
|
|
|
|
CCyBulkEndPoint::CCyBulkEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor) :
|
|
CCyUSBEndPoint(h, pEndPtDescriptor)
|
|
{
|
|
|
|
}
|
|
CCyBulkEndPoint::CCyBulkEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor,USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR* SSEndPtDescriptor):
|
|
CCyUSBEndPoint(h, pEndPtDescriptor,SSEndPtDescriptor)
|
|
{
|
|
|
|
}
|
|
//______________________________________________________________________________
|
|
|
|
PUCHAR CCyBulkEndPoint::BeginDataXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov)
|
|
{
|
|
if ( hDevice == INVALID_HANDLE_VALUE ) return NULL;
|
|
|
|
if (XferMode == XMODE_DIRECT)
|
|
return BeginDirectXfer(buf, bufLen, ov);
|
|
else
|
|
return BeginBufferedXfer(buf, bufLen, ov);
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// The CCyInterruptEndPoint Class
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CCyInterruptEndPoint::CCyInterruptEndPoint(void) : CCyUSBEndPoint()
|
|
{
|
|
}
|
|
|
|
CCyInterruptEndPoint::CCyInterruptEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor) :
|
|
CCyUSBEndPoint(h, pEndPtDescriptor)
|
|
{
|
|
|
|
}
|
|
CCyInterruptEndPoint::CCyInterruptEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor,USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR* SSEndPtDescriptor):
|
|
CCyUSBEndPoint(h, pEndPtDescriptor,SSEndPtDescriptor)
|
|
{
|
|
}
|
|
|
|
//______________________________________________________________________________
|
|
|
|
PUCHAR CCyInterruptEndPoint::BeginDataXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov)
|
|
{
|
|
if ( hDevice == INVALID_HANDLE_VALUE ) return NULL;
|
|
|
|
if (XferMode == XMODE_DIRECT)
|
|
return BeginDirectXfer(buf, bufLen, ov);
|
|
else
|
|
return BeginBufferedXfer(buf, bufLen, ov);
|
|
|
|
}
|
|
CCyUSBBOS::CCyUSBBOS(void)
|
|
{
|
|
// initialize to null
|
|
pUSB20_DeviceExt = NULL;
|
|
pSS_DeviceCap = NULL;
|
|
pContainer_ID = NULL;
|
|
}
|
|
CCyUSBBOS::~CCyUSBBOS()
|
|
{
|
|
if(pContainer_ID)
|
|
{
|
|
delete pContainer_ID;
|
|
pContainer_ID = NULL;
|
|
}
|
|
if(pUSB20_DeviceExt)
|
|
{
|
|
delete pUSB20_DeviceExt;
|
|
pUSB20_DeviceExt = NULL;
|
|
}
|
|
if(pSS_DeviceCap)
|
|
{
|
|
delete pSS_DeviceCap;
|
|
pSS_DeviceCap = NULL;
|
|
}
|
|
}
|
|
|
|
CCyUSBBOS::CCyUSBBOS(HANDLE h,PUSB_BOS_DESCRIPTOR pBosDescrData)
|
|
{
|
|
// initialize to null
|
|
pUSB20_DeviceExt = NULL;
|
|
pSS_DeviceCap = NULL;
|
|
pContainer_ID = NULL;
|
|
|
|
bLength = pBosDescrData->bLength;
|
|
bDescriptorType = pBosDescrData->bDescriptorType;
|
|
bNumDeviceCaps = pBosDescrData->bNumDeviceCaps;
|
|
wTotalLength = pBosDescrData->wTotalLength;
|
|
|
|
int totallen = wTotalLength;
|
|
totallen -=pBosDescrData->bLength;
|
|
|
|
if (totallen < 0)
|
|
return;
|
|
|
|
UCHAR* DevCap = (byte*)((byte*)pBosDescrData + pBosDescrData->bLength); // get nex descriptor
|
|
|
|
for (int i = 0; i < bNumDeviceCaps; i++)
|
|
{
|
|
//check capability type
|
|
switch (DevCap[USB_BOS_DEVICE_CAPABILITY_TYPE_INDEX])
|
|
{
|
|
case USB_BOS_CAPABILITY_TYPE_USB20_EXT:
|
|
{
|
|
PUSB_BOS_USB20_DEVICE_EXTENSION pUSB20_ext = (PUSB_BOS_USB20_DEVICE_EXTENSION)DevCap;
|
|
totallen -= pUSB20_ext->bLength;
|
|
DevCap = (byte *)DevCap +pUSB20_ext->bLength;
|
|
pUSB20_DeviceExt = new CCyBosUSB20Extesnion(h, pUSB20_ext);
|
|
break;
|
|
}
|
|
case USB_BOS_CAPABILITY_TYPE_SUPERSPEED_USB:
|
|
{
|
|
PUSB_BOS_SS_DEVICE_CAPABILITY pSS_Capability = (PUSB_BOS_SS_DEVICE_CAPABILITY)DevCap;
|
|
totallen -= pSS_Capability->bLength;
|
|
DevCap = (byte*)DevCap + pSS_Capability->bLength;
|
|
pSS_DeviceCap = new CCyBosSuperSpeedCapability(h, pSS_Capability);
|
|
break;
|
|
}
|
|
case USB_BOS_CAPABILITY_TYPE_CONTAINER_ID:
|
|
{
|
|
PUSB_BOS_CONTAINER_ID pUSB_ContainerID = (PUSB_BOS_CONTAINER_ID)DevCap;
|
|
totallen -= pUSB_ContainerID->bLength;
|
|
DevCap = (byte*)DevCap + pUSB_ContainerID->bLength;
|
|
pContainer_ID = new CCyBosContainerID(h, pUSB_ContainerID);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if(totallen<0)
|
|
break;
|
|
}
|
|
}
|
|
CCyBosUSB20Extesnion::CCyBosUSB20Extesnion(void)
|
|
{}
|
|
CCyBosUSB20Extesnion::CCyBosUSB20Extesnion(HANDLE h,PUSB_BOS_USB20_DEVICE_EXTENSION pBosUsb20ExtDesc)
|
|
{
|
|
bLength = pBosUsb20ExtDesc->bLength;
|
|
bDescriptorType = pBosUsb20ExtDesc->bDescriptorType;
|
|
bDevCapabilityType = pBosUsb20ExtDesc->bDevCapabilityType;
|
|
bmAttribute = pBosUsb20ExtDesc->bmAttribute;
|
|
}
|
|
CCyBosSuperSpeedCapability::CCyBosSuperSpeedCapability(void)
|
|
{}
|
|
CCyBosSuperSpeedCapability::CCyBosSuperSpeedCapability(HANDLE h,PUSB_BOS_SS_DEVICE_CAPABILITY pUSB_SuperSpeedUsb)
|
|
{
|
|
bLength = pUSB_SuperSpeedUsb->bLength;
|
|
bDescriptorType = pUSB_SuperSpeedUsb->bDescriptorType;
|
|
bDevCapabilityType = pUSB_SuperSpeedUsb->bDevCapabilityType;
|
|
bFunctionalitySupporte = pUSB_SuperSpeedUsb->bFunctionalitySupporte;
|
|
SpeedsSuported = pUSB_SuperSpeedUsb->wSpeedsSuported;
|
|
bmAttribute = pUSB_SuperSpeedUsb->bmAttribute;
|
|
bU1DevExitLat = pUSB_SuperSpeedUsb->bU1DevExitLat;
|
|
bU2DevExitLat = pUSB_SuperSpeedUsb->bU2DevExitLat;
|
|
}
|
|
CCyBosContainerID::CCyBosContainerID(void)
|
|
{}
|
|
CCyBosContainerID::CCyBosContainerID(HANDLE handle, PUSB_BOS_CONTAINER_ID pUSB_ContainerID)
|
|
{
|
|
bLength = pUSB_ContainerID->bLength;
|
|
bDescriptorType = pUSB_ContainerID->bDescriptorType;
|
|
bDevCapabilityType = pUSB_ContainerID->bDevCapabilityType;
|
|
for (int i = 0; i < USB_BOS_CAPABILITY_TYPE_CONTAINER_ID_SIZE; i++)
|
|
ContainerID[i] = pUSB_ContainerID->ContainerID[i];
|
|
}
|