⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 file.cpp

📁 HPC上的RS232 USB Driver .该软件比PL2303专用驱动强
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -