📄 scope_control.cpp
字号:
// \param None.
//
// This function determines whether or not the required USB device is
// available and, if so, creates a file allowing access to it. The file
// handle is returned on success.
//
// \return Returns a valid file handle on success of INVALID_HANDLE_VALUE
// on failure. In cases of failure, GetLastError() can be called to determine
// the cause.
//
//****************************************************************************
static HANDLE OpenDevice(void)
{
HANDLE hDev = NULL;
char devicePath[MAX_DEVPATH_LENGTH];
BOOL retVal;
//
// Get the path needed to open a file handle on our USB device.
//
retVal = GetDevicePath((LPGUID)&GUID_DEVINTERFACE_LUMINARY_SCOPE,
devicePath,
sizeof(devicePath));
if(retVal != ERROR_SUCCESS)
{
SetLastError(retVal);
return(INVALID_HANDLE_VALUE);
}
//
// Open the file we will use to communicate with the device.
//
hDev = CreateFile((LPCTSTR)devicePath,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
return(hDev);
}
//****************************************************************************
//
// Determines that the required USB device is present, opens it and gathers
// required information to allow us to read and write it.
//
// \param pbDriverInstalled points to a variable which will be written with
// \b true if the driver for the device is found (even if the device itself
// is not connected or \b false if the driver is not installed.
//
// This function is called to initialize the USB device and perform one-off
// setup required to allocate handles allowing the application to read and
// write the device endpoints.
//
// \return Returns \e TRUE on success or \e FALSE on failure. In failing
// cases, GetLastError() can be called to determine the cause.
//
//****************************************************************************
static bool InitializeDevice(bool *pbDriverInstalled)
{
BOOL bResult;
WINUSB_INTERFACE_HANDLE usbHandle;
USB_INTERFACE_DESCRIPTOR ifaceDescriptor;
WINUSB_PIPE_INFORMATION pipeInfo;
UCHAR speed;
ULONG length;
int i;
//
// Determine whether the USB device is present and, if so, generate a
// file handle to allow access to it.
//
devInfo.deviceHandle = OpenDevice();
if(devInfo.deviceHandle == INVALID_HANDLE_VALUE)
{
//
// We were unable to access the device - return a failure.
//
devInfo.bInterfaceFound = (GetLastError() == ERROR_DEV_NOT_EXIST) ?
false : true;
*pbDriverInstalled = devInfo.bInterfaceFound ? true : false;
return(FALSE);
}
else
{
//
// If OpenDevice returns a handle then the interface is present
// (driver is installed) and the device is connected.
//
*pbDriverInstalled = true;
devInfo.bInterfaceFound = true;
}
//
// The device is opened so we now initialize the WinUSB layer passing it
// the device handle.
//
bResult = WinUsb_Initialize(devInfo.deviceHandle, &usbHandle);
if(bResult)
{
//
// If we managed to initialize the WinUSB layer, we now query the
// device descriptor to determine the speed of the device.
//
devInfo.winUSBHandle = usbHandle;
length = sizeof(UCHAR);
bResult = WinUsb_QueryDeviceInformation(devInfo.winUSBHandle,
DEVICE_SPEED,
&length,
&speed);
}
if(bResult)
{
//
// If all is well, now query the interface descriptor. We ask for the
// first interface only since, in the case of the generic bulk device,
// this is all that is available.
//
devInfo.deviceSpeed = speed;
bResult = WinUsb_QueryInterfaceSettings(devInfo.winUSBHandle,
0,
&ifaceDescriptor);
}
if(bResult)
{
//
// We got the interface descriptor so now we enumerate the endpoints
// to find the two we require - one bulk IN endpoint and one bulk OUT
// endpoint.
//
for(i=0;i<ifaceDescriptor.bNumEndpoints;i++)
{
bResult = WinUsb_QueryPipe(devInfo.winUSBHandle, 0, (UCHAR) i,
&pipeInfo);
if((pipeInfo.PipeType == UsbdPipeTypeBulk) &&
USB_ENDPOINT_DIRECTION_IN(pipeInfo.PipeId))
{
devInfo.bulkInPipe = pipeInfo.PipeId;
}
else if((pipeInfo.PipeType == UsbdPipeTypeBulk) &&
USB_ENDPOINT_DIRECTION_OUT(pipeInfo.PipeId))
{
devInfo.bulkOutPipe = pipeInfo.PipeId;
}
else
{
//
// Hmm... we found and endpoint that we didn't expect to see
// on this interface. This tends to imply that there is a
// mismatch between the device configuration and this
// application so we will fail the call after setting an
// appropriate error code for the caller to query.
//
SetLastError(ERROR_NOT_SAME_DEVICE);
bResult = FALSE;
break;
}
}
}
//
// If we see an error reported, free any resources allocated prior to
// returning.
//
if(bResult == FALSE)
{
TerminateDevice(&devInfo);
return(false);
}
else
{
//
// All is well.
//
return(true);
}
}
//****************************************************************************
//
// Cleans up and free resources associated with the USB device communication
// prior to exiting the application.
//
// \param pDevice is a pointer to the device instance data whose resources
// are to be freed.
//
// This function should be called prior to exiting the application to free
// the resources allocated during InitializeDevice().
//
// \return Returns \e TRUE on success or \e FALSE on failure.
//
//****************************************************************************
static bool TerminateDevice(tDeviceInfo *pDevice)
{
BOOL bRetcode = TRUE;
BOOL bRetcode2 = TRUE;
if(pDevice->winUSBHandle)
{
bRetcode = WinUsb_Free(pDevice->winUSBHandle);
}
if(pDevice->deviceHandle)
{
bRetcode2 = CloseHandle(pDevice->deviceHandle);
}
pDevice->bDeviceConnected = false;
pDevice->winUSBHandle = 0;
pDevice->deviceHandle = 0;
if(bRetcode && bRetcode2)
{
return(true);
}
else
{
return(false);
}
}
//****************************************************************************
//
// Sends a single packet and optional additional data to the oscilloscope
// device if it is connected.
//
// \param ucPacketType is the type of packet to send.
// \param ucParam is the packet-specific byte parameter.
// \param ulParam is the packet-specific word parameter.
// \param ulDataLength is the length of the optional packet payload in bytes.
// \param pvData is a pointer to the optional packet payload data.
//
// This function sends a single packet to the oscilloscope of it is currently
// connected. A packet comprises a tScopePacket header structure followed,
// optionally, by a block of data.
//
// \return Returns \e TRUE on success or \e FALSE on failure.
//
//****************************************************************************
static bool SendScopePacket(unsigned char ucPacketType,
unsigned char ucParam,
unsigned long ulParam,
unsigned long ulDataLength,
void *pData)
{
BOOL bResult;
ULONG ulWritten;
tScopePacket sPacket;
//
// We only try to send the packet if we are currently communicating with the
// device.
//
if(devInfo.bDeviceConnected)
{
//
// Populate the packet header.
//
sPacket.ucVersion = SCOPE_PROTOCOL_VERSION_1;
sPacket.ucHdrLength = sizeof(tScopePacket);
sPacket.ucPacketType = ucPacketType;
sPacket.ucParam = ucParam;
sPacket.ulParam = ulParam;
sPacket.ulDataLength = ulDataLength;
//
// Write the user's string to the device.
//
bResult = WinUsb_WritePipe(devInfo.winUSBHandle,
devInfo.bulkOutPipe,
(PUCHAR)&sPacket,
sizeof(tScopePacket),
&ulWritten,
NULL);
if((!bResult) || (ulWritten != sizeof(tScopePacket)))
{
return(FALSE);
}
else
{
//
// If we have optional data to send, append it to the packet.
//
if(ulDataLength != 0)
{
bResult = WinUsb_WritePipe(devInfo.winUSBHandle,
devInfo.bulkOutPipe,
(PUCHAR)pData,
ulDataLength,
&ulWritten,
NULL);
if((!bResult) || (ulWritten != ulDataLength))
{
return(FALSE);
}
}
}
//
// We sent all the data successfully
//
return(TRUE);
}
//
// The device is not connected so there is no point trying to send
// the packet.
//
return(FALSE);
}
//****************************************************************************
//
// Reads a single packet and optional additional data from the oscilloscope,
// blocking until the packet is available.
//
// \param pucPacketType is storage for the type of packet read.
// \param pucParam is storage for the packet-specific byte parameter.
// \param pulParam is storage the packet-specific word parameter.
// \param pulDataLength is storage for the length of the optional packet
// payload in bytes.
// \param ppData is storage for a pointer to the optional packet payload
// data.
//
// This function blocks until a packet is received from the oscilloscope
// then returns information on the packet to the caller. If the packet
// contains an optional data block, this is copied into a buffer whose
// pointer is passed back to the caller.
//
// \note The caller is responsible for freeing the packet whose pointer is
// returned in *ppData in cases where this is not NULL. The pointer must be
// freed using a call to LocalFree().
//
// \return Returns \e TRUE on success or \e FALSE on failure.
//
//****************************************************************************
static bool ScopeWaitPacket(unsigned char *pucPacketType,
unsigned char *pucParam,
unsigned long *pulParam,
unsigned long *pulDataLength,
void **ppData)
{
BOOL bResult;
ULONG ulRead;
tScopePacket sPacket;
//
// Only try to read if the device is connected.
//
if(devInfo.bDeviceConnected)
{
bResult = WinUsb_ReadPipe(devInfo.winUSBHandle,
devInfo.bulkInPipe,
(PUCHAR)&sPacket,
sizeof(tScopePacket),
&ulRead,
NULL);
if((!bResult) || (ulRead != sizeof(tScopePacket)))
{
//
// An error occurred trying to read the packet.
//
return(FALSE);
}
else
{
//
// We got the scope packet header. Make sure that the
// protocol and size fields are as expected.
//
if((sPacket.ucVersion == SCOPE_PROTOCOL_VERSION_1) &&
(sPacket.ucHdrLength == sizeof(tScopePacket)))
{
//
// Packet header seems fine. Do we have any optional data to read?
//
if(sPacket.ulDataLength != 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -