转载请标明是引用于 http://blog.csdn.net/chenyujing1234
欢迎大家提出意见,一起讨论!
需要源码的可以与我联系.
在我的一篇文章 Window XP驱动开发(十二) 驱动应用程序端 (原理分析)
中讲到了驱动应用程序端的开发原理。
这里针对CY7C68013A供应商提供的 .sys .inf及提供的.lib文件进行应用程序端的开发。
先看一下界面效果:
一、环境
到 http://www.cypress.com/?rID=34870 下载 CY7C68013的组件开发安装程序。
下载后得到
安装后得到驱动安装文件与应用程序开发库:
图一:
二、应用程序开发
现在我们就基于CyAPI.lib进行三次开发。
1、首先将 CyAPI.lib 与 CyAPI.lib加入到我们工程的链接中。(相对简单,不介绍了)
2、代码实现:
2、1 创建CCyUSBDevice接口
USBDevice = new CCyUSBDevice(m_hWnd); // Create an instance of CCyUSBDevice
2、2 获得设备列表,并找开设备。用:
UCHAR DeviceCount(void);
bool Open(UCHAR dev);
获得端点列表,用:
UCHAR EndPointCount(void);
void CBulkLoopDlg::OnRefreshBtn()
{
int i;
// if we are currently running loopback, stop
if (XferThread)
{
bLooping = false;
InEndpt->Abort();
InEndpt->Reset();
OutEndpt->Abort();
OutEndpt->Reset();
m_StartBtn.SetWindowText("Start");
}
// clear the combo boxes
m_DeviceListComBox.ResetContent();
m_InEndptComBox.ResetContent();
m_OutEndptComBox.ResetContent();
// make sure there is at lesat one device out there
if (USBDevice->DeviceCount())
{
// search for all connected devices, and add them to the device
// combo box
for (i = 0; i < USBDevice->DeviceCount(); i++)
{
USBDevice->Open(i);
m_DeviceListComBox.AddString(USBDevice->DeviceName);
}
m_DeviceListComBox.SetCurSel(0);
OnSelchangeDeviceListCombox(); // This will set the device index and load the ep lists
}
}
void CBulkLoopDlg::OnSelchangeDeviceListCombox()
{
int i;
char s[12];
DeviceIndex = m_DeviceListComBox.GetCurSel();
USBDevice->Open(DeviceIndex);
// 获得端点数目
int epts = USBDevice->EndPointCount();
CCyUSBEndPoint *endpt;
// Load the endpoint combo boxes
// 跳过端点0,因为我们知道它是控制端点
for (i=1; i<epts; i++)
{
endpt = USBDevice->EndPoints[i];
if (endpt->Attributes == 2) // Bulk
{
sprintf(s, "0x%02X", endpt->Address);
if (endpt->Address & 0x80) // In 端点
{
m_InEndptComBox.AddString(s);
m_InEndptComBox.SetItemData(m_InEndptComBox.GetCount()-1,i);
}
else // Out端点
{
m_OutEndptComBox.AddString(s);
m_OutEndptComBox.SetItemData(m_OutEndptComBox.GetCount()-1,i);
}
}
}
m_InEndptComBox.SetCurSel(0);
m_OutEndptComBox.SetCurSel(0);
OnSelchangeInCombox(); // Set the InEndpt member
OnSelchangeOutCombox(); // Set the OutEndpt member
}
2、3 根据选定的In端点与Out 端点进行数据传输.
Loop线程函数是 XferLoop,用到的函数有:
PUCHAR BeginDataXfer(PUCHAR buf, LONG len, OVERLAPPED *ov);
bool WaitForXfer(OVERLAPPED *ov, ULONG tOut);
bool FinishDataXfer(PUCHAR buf, LONG &len, OVERLAPPED *ov, PUCHAR pXmitBuf, CCyIsoPktInfo* pktInfos = NULL);
void CBulkLoopDlg::OnStartBtn()
{
if (XferThread) {
bLooping = false;
// InEndpt->Abort();
// InEndpt->Reset();
// OutEndpt->Abort();
// OutEndpt->Reset();
m_StartBtn.SetWindowText("Start");
} else {
char s[12];
ZeroMemory(s,12);
m_XferSize.GetLine(0,s,8);
LONG xfer = atol(s);
if (xfer > 2048) {
xfer = 2048;
m_XferSize.SetWindowText("2048");
}
USBDevice->Open(DeviceIndex);
OutEndpt = USBDevice->EndPoints[m_OutEndptComBox.GetItemData(m_OutEndptComBox.GetCurSel())];
InEndpt = USBDevice->EndPoints[m_InEndptComBox.GetItemData(m_InEndptComBox.GetCurSel())];
// Launch the looping thread (Calls XferLoop() function, above.)
if (xfer && USBDevice->IsOpen()) {
bLooping = true;
XferThread = AfxBeginThread(XferLoop, this);
}
m_StartBtn.SetWindowText("Stop");
}
}
UINT XferLoop( LPVOID params ) {
OVERLAPPED outOvLap, inOvLap;
CBulkLoopDlg *dlg = (CBulkLoopDlg *) params;
char s[24]; ZeroMemory(s, 24);
dlg->m_XferSize.GetLine(0,s,8);
LONG xfer = atol(s);
PUCHAR data = new UCHAR[xfer]; ZeroMemory(data,xfer);
PUCHAR inData = new UCHAR[xfer]; ZeroMemory(inData,xfer);
outOvLap.hEvent = CreateEvent(NULL, false, false, "CYUSB_OUT");
inOvLap.hEvent = CreateEvent(NULL, false, false, "CYUSB_IN");
dlg->m_SeedValue.GetLine(0,s,8);
LONG seed = atol(s);
int stopOnError = dlg->m_StopOnErrorChkBox.GetCheck();
stuffBuff(data,xfer,seed,dlg->m_FillPatternComBox.GetCurSel());
dlg->m_StatusLabel.SetWindowText(" STATUS: Transferring data . . .");
dlg->m_SuccessCount.SetWindowText("0");
dlg->m_FailureCount.SetWindowText("0");
bool success;
LONG nSuccess = 0;
LONG nFailure = 0;
if (dlg->m_DisableTimeoutChkBox.GetCheck())
{
dlg->OutEndpt->TimeOut = 0;
dlg->InEndpt->TimeOut = 0;
}
else
{
dlg->OutEndpt->TimeOut = 2000;
dlg->InEndpt->TimeOut = 2000;
}
for (;dlg->bLooping;) {
LONG outlen,inlen,len;
outlen = inlen = len = xfer; // Use temp var because XferData can change the value of len
// 发送数据给USB设备
UCHAR *outContext = dlg->OutEndpt->BeginDataXfer(data,outlen,&outOvLap);
// 从USB设备中读到数据
UCHAR *inContext = dlg->InEndpt->BeginDataXfer(inData,inlen,&inOvLap);
// 等待
dlg->OutEndpt->WaitForXfer(&outOvLap,2000);
dlg->InEndpt->WaitForXfer(&inOvLap,2000);
// 完成数据传输
success = dlg->OutEndpt->FinishDataXfer(data, outlen, &outOvLap,outContext);
success = dlg->InEndpt->FinishDataXfer(inData,inlen, &inOvLap,inContext);
if (success) {
bool pass = (memcmp(data,inData,len) == 0);
if (pass)
nSuccess++;
else
nFailure++;
} else
nFailure++;
sprintf(s,"%d",nSuccess);
dlg->m_SuccessCount.SetWindowText(s);
sprintf(s,"%d",nFailure);
dlg->m_FailureCount.SetWindowText(s);
if ((!success) && stopOnError) dlg->bLooping = false;
}
CloseHandle(outOvLap.hEvent);
CloseHandle(inOvLap.hEvent);
delete [] data;
delete [] inData;
dlg->m_StatusLabel.SetWindowText(" STATUS: Stopped");
dlg->XferThread = NULL;
dlg->USBDevice->Close();
return true;
}
三、测试方法
1、加载此应用程序对应的CY7C68013固件
固件源码在CYPRESS提供的安装包下:
设计方法请看我的另一篇文章:<<>>
这里我们得把得到的bulkloop.hex单片机文件写入的CY7C里。
我们采用的工具是CYPRESS提供的工具: CyConsole.exe
(1)在运行界面下打开EZ-USB Interface选项界面
(2)选择Download按钮,将选择bulkloop.hex
(3)写入bulkloop.hex文件后,我们在设备管理器中发现此设备变化无法识别了。
这是因为我们之前的驱动是建立的VID:04B4 PID:8613 基础上的。
而现在我们的VID与PID变了,所以找不到驱动:
为什么PID发生了变化?这是因为bulkloop.hex改变了PID。请看我的文章:
<<http://blog.csdn.net/chenyujing1234/article/details/7722669>>
接下来我们修改CyUsb.inf文件。
2、修改CyUsb.Inf(请将以下的8613改为我们实际的PID,eg: 1004)
中的CyUSB.chm里有讲到怎么对CyUSB.INF进行修改,使之在具体的应该中使用.
1、1 增加设备的标识符到驱动中
把 图一中的CyUSB.inf中的;%VID_XXXX&PID_XXXX.DeviceDesc%=CyUsb, USB\VID_XXXX&PID_XXXX
改为:
%VID_04B4&PID_8613.DeviceDesc%=CyUsb, USB\VID_04B4&PID_8613
1、2 替换Cypress 串,使之与自己的公司描述更确切。
CYUSB_Provider = "Cypress"
CYUSB_Company = "Cypress Semiconductor Corporation"
CYUSB_Description = "Cypress Generic USB Driver"
CYUSB_DisplayName = "Cypress USB Generic"
1、3 执行一个通用的GUID
应用程序软件通过驱动的的GUID访问驱动,每一个Window系统的驱动都应该有一个唯一的GUID。
因为可能会有不同的硬件供应商,这样就会有很多CYUSB.SYS的实例。我们可以通过GUIDGEN.exe来产生我们
自己的GUID。并把此GUI写在CyUSB.inf中
CYUSB.GUID="{AE18AA60-7F6A-11d4-97DD-00010229B959}"
1、4 在启动时执行一个脚本
CYUSB.sys驱动在启动时能被配置到默认的控制端点(端点0)。
为了配置设备使之能表现控制传输,我们用CyConsole.exe来创建一个脚本文件。
我们保存此脚本文件为MyDevice.SPT,把此文件放到.INF文件下。
目的是让此脚夫本文件把固件镜像下载到设备中。
1、4、1 在CyUSB.inf中的 [CYUSB.AddReg.Guid]下添加
HKR,,DriverEXECSCRIPT,,%CYUSB.EXECSCRIPT%
1、4、2 在[Strings]下添加
CYUSB.EXECSCRIPT="\systemroot\system32\MyDevice\MyDevice.spt"
2、强制系统用CYUSB.sys驱动
由于cyusb.inf文件中没有提供DefaultInstall 默认安装节点,但我们可以通过EzDriverInstaller安装(请参见:http://blog.csdn.net/chenyujing1234/article/details/7676812)
安装完后,我们的应用程序才有意义,接下来开始测试应用程序了。