📄 usb_demo.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
// USB_Demo.cpp
//
// Main source for Mirror example application.
//
// Author: Jon Moore, Marian Ilecko
//
// Revision History:
//
// 06/12/02 (JAM) V1.0.0 - Initial coding.
// 08/29/02 (JAM) V1.0.1 - Use second device handle for LCD mirror input thread.
// 08/30/02 (JAM) V1.0.2 - Use ST vendor ID and 0x8000 sector size for 2MB part.
// 10/21/02 (JAM) V1.0.3 - Fixed hex file format bug; added critical section to
// synch monitor thread and main thread.
// 11/02/02 (JAM) V1.0.5 - Minor message changes; fixed boot flash page register
// bug; flash radio buttons immediately switch to selected
// flash.
// 11/04/02 (JAM) V1.0.6 - Change to erase flash sector rather than entire flash.
//
// 22/09/03 (MI) V1.0.7 - Auto-detection feature
// 25/09/03 (MI) V1.0.7 - Port to Borland C++ Builder in progress
// 29/09/03 (MI) V1.0.7 - Porting finalized
// 01/10/03 (MI) V1.0.7 - Some bugfixes and improvements
// 10/10/03 (MI) V1.0.7 - Rearrangements, commenting
// 11/25/03 (MI) V1.0.9 - Memory leakage bug fixed
// 11/26/03 (MI) V1.1.0 - Some improvements and adjustments
// 11/26/03 (MI) V1.1.1 - Some fixes, added Alt-? keys on some buttons
//
// Copyright (c)2003 ST Microelecronics
// All rights reserved.
//
//---------------------------------------------------------------------------
// This example demo code is provided as is and has no warranty,
// implied or otherwise. You are free to use/modify any of the provided
// code at your own risk in your applications with the expressed limitation
// of liability (see below) so long as your product using the code contains
// at least one uPSD products (device).
//
// LIMITATION OF LIABILITY: NEITHER STMicroelectronics NOR ITS VENDORS OR
// AGENTS SHALL BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF USE, LOSS OF DATA,
// INTERRUPTION OF BUSINESS, NOR FOR INDIRECT, SPECIAL, INCIDENTAL OR
// CONSEQUENTIAL DAMAGES OF ANY KIND WHETHER UNDER THIS AGREEMENT OR
// OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
//---------------------------------------------------------------------------
#include <vcl.h>
#include <setupapi.h>
#include <stdio.h>
#include <DateUtils.hpp>
#pragma hdrstop
#define WIN32 YES
//app_intr.h file needs to know whether it's included into Win32 or 8051 app.
//this is very important 'cause there are certain differences in data types used
//also be careful with compiler options, do not use other data alignments then single-byte!
//we will ensure of this using following directive:
#pragma pack(1)
#include "app_intr.h"
#include "USB_demo.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TmainForm *mainForm;
//---------------------------------------------------------------------------
/////////////////// Macros
#define min(x,y) (((x)<(y))?(x):(y))
#define SELECTED_FLASH ((mainForm->rbMain->Checked==TRUE)?(PRIMARY_FLASH):(SECONDARY_FLASH))
#define SELECTED_SECTOR ((BYTE) mainForm->cbSector->ItemIndex)
// For converting 8051 big endian to x86 little endian format
#define SWAP_UINT16(x) ((((x)&0xff00)>>8) | (((x)&0x00ff)<<8))
#define SWAP_UINT32(x) ((((x)&0xff000000)>>24) | (((x)&0x00ff0000)>>8) | (((x)&0x0000ff00)<<8) | (((x)&0x000000ff)<<24))
/////////////////// Constants
#define MAX_NUM_MMF_ENTRIES 32
#define MAX_SECTOR_SIZE 0x8000
#define VERSION_STR "(v1.1.1)"
#define UPSD_2MB
#define ST_VENDOR_ID 0x0483
#define ST_PRODUCT_ID 0x0000
#define PRIMARY_FLASH_VM 0x92
#define SECONDARY_FLASH_VM 0x8C
/////////////////// Typedefs
typedef struct _HIDD_ATTRIBUTES
{
ULONG Size; // = sizeof (struct _HIDD_ATTRIBUTES)
USHORT VendorID;
USHORT ProductID;
USHORT VersionNumber;
} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
typedef VOID (__stdcall *PHidD_GetProductString)(HANDLE, PVOID, ULONG);
typedef VOID (__stdcall *PHidD_GetHidGuid)(LPGUID);
typedef BOOLEAN (__stdcall *PHidD_GetAttributes)(HANDLE, PHIDD_ATTRIBUTES);
typedef BOOLEAN (__stdcall *PHidD_SetFeature)(HANDLE, PVOID, ULONG);
typedef BOOLEAN (__stdcall *PHidD_GetFeature)(HANDLE, PVOID, ULONG);
typedef struct
{
// The Microsoft HID driver expects a prefix report ID byte
unsigned char reportID;
MCU_CMD report;
} REPORT_BUF, *PREPORT_BUF;
typedef struct
{
int regValue;
int regMask;
int start;
int end;
int length;
int swapValue;
int swapMask;
BOOL swappable;
int swapStart;
int swapEnd;
} MMF_ENTRY, *PMMF_ENTRY;
/////////////////// Globals
HANDLE g_hDevice = INVALID_HANDLE_VALUE;
char g_devicePath[MAX_PATH] = {0};
HANDLE g_hStopEvent = NULL;
CRITICAL_SECTION g_crSection;
MMF_ENTRY g_mmfEntries[MAX_NUM_MMF_ENTRIES];
int g_nMmfEntries = 0;
PHidD_GetProductString HidD_GetProductString = NULL;
PHidD_GetHidGuid HidD_GetHidGuid = NULL;
PHidD_GetAttributes HidD_GetAttributes = NULL;
PHidD_SetFeature HidD_SetFeature = NULL;
PHidD_GetFeature HidD_GetFeature = NULL;
HINSTANCE hHID;
TCHAR displayBuffer[LCD_BUFFER_SIZE];
static HANDLE hInputThread = NULL;
int test_runs,stop_test,time_consumed_for_ReadFlash;
TDateTime t1,t2; // used for measurement of operation's time consumption
//---------------------------------------------------------------------------
/////////////////// OnError()
//
// Generic error handler.
void OnError(char *pszMsg)
{
Application->MessageBox(pszMsg, "Error", MB_OK|MB_ICONEXCLAMATION);
}
//---------------------------------------------------------------------------
// MAIN FORM CONSTRUCTOR, DESTRUCTOR AND MISCELLANEOUS FUNCTIONS
//---------------------------------------------------------------------------
/////////////////// TmainForm()
//
// Most of the initializations are done in mainForm's constructor
//
__fastcall TmainForm::TmainForm(TComponent* Owner)
: TForm(Owner)
{
int sizeof_REPORT_BUF; // we will test if size of output report structure is correct
sizeof_REPORT_BUF = sizeof(REPORT_BUF);
if (sizeof_REPORT_BUF != 65){
Application->MessageBox("Warning: the program has been compiled using data alignment different then single-byte.\nThis affects data structures and prevents the program from correct operation.\nPlease re-compile the program using correct compiler options.","Error",MB_OK|MB_ICONEXCLAMATION);
Application->Terminate();
}
else
{
// The LoadLibrary function maps the specified executable module
// into the address space of the calling process.
hHID = LoadLibrary("HID.DLL"); // assign the handle to variable hHID
// If the function succeeds, the return value is a handle to the module.
// If the function fails, the return value is NULL.
if (!hHID) // Then the error message is generated.
{
OnError("Failed to load HID.DLL.");
}
// The GetProcAddress function returns the address of the specified
// exported dynamic-link library (DLL) function.
// We export only those functions which we need.
HidD_GetProductString = (PHidD_GetProductString)
GetProcAddress(hHID, "HidD_GetProductString");
HidD_GetHidGuid = (PHidD_GetHidGuid)
GetProcAddress(hHID, "HidD_GetHidGuid");
HidD_GetAttributes = (PHidD_GetAttributes)
GetProcAddress(hHID, "HidD_GetAttributes");
HidD_SetFeature = (PHidD_SetFeature)
GetProcAddress(hHID, "HidD_SetFeature");
HidD_GetFeature = (PHidD_GetFeature)
GetProcAddress(hHID, "HidD_GetFeature");
if ( !HidD_GetHidGuid
|| !HidD_GetAttributes
|| !HidD_GetProductString
|| !HidD_SetFeature
|| !HidD_GetFeature )
{
OnError("Couldn't find one or more HID entry points.");
FreeLibrary(hHID);
}
g_hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
InitializeCriticalSection(&g_crSection);
Timer1->Enabled = 1; // enable the auto-detection timer
mainForm->BringToFront();
}
}
//---------------------------------------------------------------------------
/////////////////// FormDestroy()
//
// When closing the form, we close StopEvent handle and free HID library
//
void __fastcall TmainForm::FormDestroy(TObject *Sender)
{
CloseHandle(g_hStopEvent);
FreeLibrary(hHID);
}
//---------------------------------------------------------------------------
/////////////////// FormClose()
//
// Before closing the form, we must stop the LCD-display mirroring thread
//
void __fastcall TmainForm::FormClose(TObject *Sender, TCloseAction &Action)
{
// Stop LCD-display mirroring thread
SetEvent(g_hStopEvent); // set the state of the specified event object to signaled
CloseHandle(hInputThread); // close the input thread's handle
hInputThread = NULL; // clear the handle variable
}
//---------------------------------------------------------------------------
/////////////////// UpdateDisplay()
//
// Displays mirrored data to panel at mainForm.
void __fastcall UpdateDisplay(char *src)
{
src[LCD_BUFFER_SIZE-1] = 0;
mainForm->lbDisplayMirror->Caption = AnsiString(src);
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// CONNECTION AND INPUT THREAD MANAGING ROUTINES
//---------------------------------------------------------------------------
/////////////////// IsConnected()
//
// Checks if connection to the board exists.
//
// Function returns TRUE if the board is connected, or FALSE if it isn't.
BOOL IsConnected()
{
return g_hDevice != INVALID_HANDLE_VALUE;
}
//---------------------------------------------------------------------------
/////////////////// Disconnect()
//
// Closes handle to device and stops LCD mirror input thread.
//
// The function requires one argument - the handle to the thread to close.
void Disconnect(HANDLE hInputThread)
{
if (g_hDevice != INVALID_HANDLE_VALUE)
{
CloseHandle(g_hDevice);
g_hDevice = INVALID_HANDLE_VALUE;
}
// Close handle to input thread
if (hInputThread)
{
// Tell input thread to exit
SetEvent(g_hStopEvent); // set the state of the specified event object to signaled
if (WaitForSingleObject(hInputThread, 3000) != WAIT_OBJECT_0)
{
// OnError("Input thread not exiting in 3 seconds.");
}
CloseHandle(hInputThread); // close the input thread's handle
}
}
//---------------------------------------------------------------------------
/////////////////// OpenDeviceHandle()
//
// Attempts to open a handle to a ST HID device.
//
// If successful, OpenDeviceHandle returns 1 and stores the
// device path in g_devicePath; else OpenDeviceHandle returns 0.
SP_DEVICE_INTERFACE_DATA devData;
SP_INTERFACE_DEVICE_DETAIL_DATA DetailData;
int OpenDeviceHandle()
{
// Get HID GUID
GUID guid; // GUID structure holds a globally unique identifier (GUID),
(HidD_GetHidGuid)(&guid); // which identifies a particular object class and interface.
// Open handle to the set of all HID devices
HDEVINFO hDevInfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
OnError("Failed to open handle to HID device set.");
return 0;
}
devData.cbSize = sizeof(devData);
// For each HID device...
DWORD dwIndex = 0;
bool success;
while (1)
{
success = SetupDiEnumDeviceInterfaces(hDevInfo, 0, &guid, dwIndex, &devData);
if (success == FALSE) // no more devices found
{ // destroy a device information set and free all associated memory
SetupDiDestroyDeviceInfoList(hDevInfo);
return 0;
}
dwIndex++;
DetailData.cbSize = 5;
unsigned long BytesReturned;
success = SetupDiGetDeviceInterfaceDetail(hDevInfo, &devData, &DetailData, 256, &BytesReturned, NULL);
if (success)
{
// Open handle to device
HANDLE hDevice = CreateFile(DetailData.DevicePath, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice != INVALID_HANDLE_VALUE)
{
// Get vendor and product ID values
HIDD_ATTRIBUTES attr;
attr.Size = sizeof(attr);
if ((HidD_GetAttributes)(hDevice, &attr))
{
if ((attr.VendorID == ST_VENDOR_ID) && (attr.ProductID == ST_PRODUCT_ID))
{
// Found our device! Store handle and device path.
g_hDevice = hDevice;
strcpy(g_devicePath, DetailData.DevicePath);
// destroy a device information set and free all associated memory
SetupDiDestroyDeviceInfoList(hDevInfo);
return 1;
}
}
// otherwise close the handle and continue with next device in list
CloseHandle(hDevice);
}
}
}
}
//---------------------------------------------------------------------------
/////////////////// InputThreadProc()
//
// Thread procedure for input thread.
//
// The input thread reads input reports from the device. The input
// reports contain the data for the LCD mirror buffer. The LCD
// mirror buffer data is posted to the dialog box procedure and the
// dialog procedure updates the display edit field.
//
// The device can't send the whole mirror buffer at once. Multiple
// consecutive reports are used to pass the data for the buffer. Each
// input report has a mirror buffer index byte at the start and is
// then followed by the 7 bytes of data at the specified index in the
// LCD mirror buffer.
DWORD WINAPI InputThreadProc(LPVOID pParameter)
{
static TCHAR errorMsg[256];
// Open another handle to the HID device
HANDLE hDevice = CreateFile(g_devicePath, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_OVERLAPPED, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
{
sprintf(errorMsg, "CreateFile failed (Error %d)", GetLastError());
OnError(errorMsg);
return 0;
}
OVERLAPPED ol;
memset(&ol, 0, sizeof(ol));
ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
static char lcdBuffer[LCD_BUFFER_SIZE + 1];
memset(lcdBuffer, 0, sizeof(lcdBuffer));
while (TRUE)
{
// Report buffer (Windows will put a report ID byte at the start)
char report[INPUT_REPORT_SIZE + 1];
// Read input report from device
EnterCriticalSection(&g_crSection);
DWORD cbRet;
ResetEvent(ol.hEvent);
BOOL bRet;
bRet = ReadFile(hDevice, report, sizeof(report), &cbRet, &ol);
LeaveCriticalSection(&g_crSection);
if (!bRet)
{
if (GetLastError() == ERROR_IO_PENDING)
{
// OK - Wait for data to come in or stop event to be set
HANDLE handles[2] = {ol.hEvent, g_hStopEvent};
DWORD waitRet = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
if (waitRet == WAIT_OBJECT_0)
{
// Data came in
bRet = GetOverlappedResult(hDevice, &ol, &cbRet, TRUE);
}
else if (waitRet == (WAIT_OBJECT_0 + 1))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -