📄 file.cpp
字号:
// 232usb Copyright (c) 2003 Zoroyoshi, SOFTCLUB, Japan
// See source.txt for detail
#include <windows.h>
#include <winioctl.h>
#include "usbdi.h"
#include "common.h"
#include "file.h"
#include "device.h"
extern "C" BOOL
COM_Deinit(device_extension* dx)
{
dmesg(L"_deinit x%x\n", dx);
dx->deinit();
return 1;
};
extern "C" HANDLE
COM_Init(ULONG context)
{
dmesg(L"_init %s\n", context);
//device_extension was allocated by USBDeviceAttach
HKEY key;
if(RegOpenKeyEx( HKEY_LOCAL_MACHINE, (PCWCH)context, 0, 0, &key)) return 0;
DWORD rt;
device_extension *dx;
DWORD rd= sizeof(dx);
int rc= RegQueryValueEx(key, L"ClientInfo", 0, &rt, (BYTE*)&dx, &rd);
RegCloseKey(key);
if(rc||rt!=REG_DWORD) return 0;
dmesg(L"dx=x%x\n", dx);
dx->init();
return(dx);
};
extern "C" BOOL
COM_PowerUp(device_extension* dx)
{
// dmesg(L"_powerup\n");
return 1;
};
extern "C" BOOL
COM_PowerDown(device_extension* dx)
{
// dmesg(L"_powerdown\n"); never call file functions when power-down
return 1;
};
extern "C" HANDLE
COM_Open(device_extension* dx, DWORD access, DWORD share)
{
dmesg(L"_open x%x x%x x%x\n", dx, access, share);
if(dx==0) return 0;
BOOL rc= TRUE;
file_extension *fx= (file_extension*)LocalAlloc(LPTR, sizeof(file_extension));
if(fx==0) return 0;
dmesg(L"<alloc-fx%x>\n", fx);
fx->dx= dx;
//fx prologue
fx->access= access;
fx->share= share;
fx->ref= 0;
fx->waitevent= CreateEvent(0, 0, 0, 0);
fx->waitmask= 0;
fx->waitbit= 0;
fx->waituse= 0;
WaitForSingleObject(dx->listlock, INFINITE);
file_extension* oldlist= dx->list;
dx->list= fx; fx->list= oldlist;
SetEvent(dx->listlock);
if(oldlist==0) {
dmesg(L"first open\n");
dx->open();
};
dmesg(L"fx=x%x\n", fx);
return fx;
};
void
waitRef(device_extension* dx, file_extension* fx)
{
int retry= 0;
for(;;) {
SetEvent(fx->waitevent);
if(dx) SetEvent(dx->readevent);
if(dx) SetEvent(dx->writeevent);
if(fx->ref==0) break;
if(++retry>10) break;
Sleep(100);
};
};
extern "C" BOOL
COM_Close(file_extension* fx)
{
dmesg(L"_close x%x\n", fx);
device_extension *dx= (device_extension*)InterlockedExchange((long*)&fx->dx, 0);
waitRef(dx, fx);
if(dx) {
int closef= 0;
file_extension* list;
WaitForSingleObject(dx->listlock, INFINITE);
for(list= (file_extension*)dx; list&&list->list!=fx; list= list->list) ;
if(list) {
list->list= fx->list;
if(dx->list==0) closef= 1;
};
SetEvent(dx->listlock);
if(closef) dx->close();
};
//fx epilogue(CloseHandle..)
CloseHandle(fx->waitevent);
LocalFree(fx);
dmesg(L"<free-fx%x> closed\n", fx);
return 1;
};
extern "C" ULONG
COM_Read(file_extension* fx, PUCHAR buf, ULONG len)
{
dmesg(L"_read\n");
device_extension *dx= fx->dx;
if(dx==0) { SetLastError(ERROR_INVALID_HANDLE); return(ULONG)-1; };
if((fx->access&GENERIC_READ)==0) {
SetLastError(ERROR_INVALID_ACCESS);
return(ULONG)-1;
};
if(InterlockedTestExchange(&dx->readuse, 0, 1)!=0) {
SetLastError(ERROR_ACCESS_DENIED);
return(ULONG)-1;
};
InterlockedIncrement(&fx->ref);
DWORD tt= dx->timeout.ReadTotalTimeoutMultiplier;
if(tt==MAXDWORD) tt= 0;
DWORD ti= dx->timeout.ReadIntervalTimeout;
if(ti==MAXDWORD) ti= 0;
else if(ti==0) ti= MAXDWORD;
else ti+= tt*8; //fifo size.. true for usb?
tt= tt*len+dx->timeout.ReadTotalTimeoutConstant;
if(tt==0&&ti!=0) tt= MAXDWORD;
DWORD tc= GetTickCount();
//tt: total ; 0=immediate/.../MAXDWORD=infinite
//ti: interval ; 0=immediate/.../MAXDWORD=infinite
ULONG rc= 0; //read bytes
while(len>0) {
if(fx->dx==0) break; //closed
if(dx->readuse!=1) break; //abort
int sz= dx->recvin-dx->recvout;
if(sz==0) { //wait for data..
DWORD to;
if(tt!=0&&tt!=MAXDWORD) {
to= GetTickCount()-tc;
if(to>tt) to= 0; else to= tt-to;
} else to= tt;
if(rc&&ti<to) to= ti;
if(to==0) break; //timeout
if(WaitForSingleObject(dx->readevent, to)==WAIT_TIMEOUT) break; //timeout
} else {
if(sz<0) sz+= RECVSIZE;
int rest= sz-len;
if(sz>(int)len) sz= (int)len;
int a= RECVSIZE-dx->recvout;
if(sz<a) {
memcpy(buf, dx->recvbuf+dx->recvout, sz);
dx->recvout+= sz;
} else {
memcpy(buf, dx->recvbuf+dx->recvout, a);
memcpy(buf+a, dx->recvbuf, sz-a);
dx->recvout= sz-a;
};
buf+= sz; len-= sz; rc+= sz;
if(dx->recvflow==1&&rest<RECVSIZE/4) { //flow control
int code= 0;
if(dx->dcb.fRtsControl==RTS_CONTROL_HANDSHAKE) code|= 2;
if(dx->dcb.fDtrControl==DTR_CONTROL_HANDSHAKE) code|= 1;
if(code) dx->setlinestate(code, code);
if(dx->dcb.fInX) {
USB_TRANSFER ut= dx->uf->lpIssueBulkTransfer(dx->sendpipe, 0, 0
, USB_OUT_TRANSFER, 1, &dx->dcb.XonChar, 0);
if(ut) dx->uf->lpCloseTransfer(ut);
};
dx->recvflow= 0;
};
};
};
dx->readuse= 0;
InterlockedDecrement(&fx->ref);
return(rc);
};
extern "C" ULONG
COM_Write(file_extension* fx, PUCHAR buf, ULONG len)
{
dmesg(L"_write\n");
device_extension *dx= fx->dx;
if(dx==0) { SetLastError(ERROR_INVALID_HANDLE); return(ULONG)-1; };
if((fx->access&GENERIC_WRITE)==0) {
SetLastError(ERROR_INVALID_ACCESS);
return(ULONG)-1;
};
if(InterlockedTestExchange(&dx->writeuse, 0, 1)!=0) {
SetLastError(ERROR_ACCESS_DENIED);
return(ULONG)-1;
};
InterlockedIncrement(&fx->ref);
DWORD pkt= dx->sendendp->Descriptor.wMaxPacketSize;
if(pkt>SENDPKT) pkt= SENDPKT;
DWORD tt= dx->timeout.WriteTotalTimeoutConstant+dx->timeout.WriteTotalTimeoutMultiplier*len;
if(tt==0) tt= MAXDWORD;
DWORD tc= GetTickCount();
ULONG rc= 0; //wrote bytes
while(len>0) {
EnterCriticalSection(&dx->flowcs);
if((dx->dcb.fOutxCtsFlow&&!((dx->usbmode&1)==0||(dx->linein&0x80))
||dx->dcb.fOutxDsrFlow&&!(dx->linein&2)
||dx->dcb.fOutX&&dx->sendxoff)
||dx->dcb.fInX&&!dx->dcb.fTXContinueOnXoff&&dx->recvflow) { //flow controlled
LeaveCriticalSection(&dx->flowcs);
DWORD to;
if(tt!=MAXDWORD) {
to= GetTickCount()-tc;
if(to>tt) to= 0; else to= tt-to;
} else to= tt;
if(to==0) break; //timeout
if(WaitForSingleObject(dx->writeevent, to)==WAIT_TIMEOUT) break; //timeout occurs
if(fx->dx==0) break; //closed
if(dx->writeuse!=1) break; //abort
continue; //continue to next event...
};
DWORD sz= len; if(sz>pkt) sz= pkt;
USB_TRANSFER ut= dx->uf->lpIssueBulkTransfer(dx->sendpipe, notifyevent, dx->writeevent
, USB_OUT_TRANSFER, sz, buf, 0);
LeaveCriticalSection(&dx->flowcs);
if(ut==0) break; //error
DWORD rf= 0;
for(;;) {
DWORD to;
if(tt!=MAXDWORD) {
to= GetTickCount()-tc;
if(to>tt) to= 0; else to= tt-to;
} else to= tt;
if(to==0) break; //timeout occurs
if(WaitForSingleObject(dx->writeevent, to)==WAIT_TIMEOUT) break; //timeout occurs
if(fx->dx==0) break; //closed
if(dx->writeuse!=1) break; //abort
if(rf= dx->uf->lpIsTransferComplete(ut)) break; //transfer complete
};
if(rf==0) dx->uf->lpAbortTransfer(ut, 0);
DWORD rt= ~0;
sz= 0;
dx->uf->lpGetTransferStatus(ut, &sz, &rt);
dx->uf->lpCloseTransfer(ut);
if(sz>len) sz= len; //guard
buf+= sz; len-= sz; rc+= sz;
if(rf==0) break; //timeout/closed/abort
if(rt!=0) break; //end transfer
};
dx->writeuse= 0;
InterlockedDecrement(&fx->ref);
return(rc);
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -