Source file: /~heha/mb-iwp/HBM/usbhbm.zip/spider8direkt/spider8direkt.cpp

/* Mit dieser DLL (4 kB) kann man direkt mit einem am USB angeschlossenen Spider8 äredenô
 * ohne das Rudel an DLLs aus dem Spider32-Verzeichnis nutzen zu mⁿssen; ersetzt:
 * Spider32.dll		111 kB
 * intfac32.dll		86 kB
 * interlnk.dll		19 kB
 * Papo32.dll		41 kB
 *   Summe		251 kB
 * Au▀erdem kann man hiermit mit mehreren Spider8 reden,
 * wenn diese mit separaten USB-Adaptern angeschlossen sind.
 * (Diese arbeiten dann allerdings nicht synchron.)
 * Henrik Haftmann, TU Chemnitz, 141111
 */

#include <Windows.h>
#include <SetupAPI.h>
#define T(x) TEXT(x)

struct S8H{
 HANDLE h,w,r;
 OVERLAPPED o;
};

static const GUID spider8usb = {0x1B447280,0x1A9B,0x11D3,0xAD,0xCA,0x44,0x45,0x53,0x54,0x00,0x00};

// ╓ffnet n-ten per USB angeschlossenen Spider8 (0 = erster oder einziger).
// Der zurⁿckgegebene Zeiger sollte nicht weiter analysiert werden,
// sondern dient als Eingabe fⁿr die ⁿbrigen DLL-Funktionen.
// Bei Fehler liefert diese Funktion NULL.
S8H* CALLBACK open(int n=0) {
 S8H *ret=NULL;
 HANDLE devs=SetupDiGetClassDevs(&spider8usb,NULL,0,DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
 if (devs!=INVALID_HANDLE_VALUE) {
  SP_DEVICE_INTERFACE_DATA devinterface;
  devinterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  if (SetupDiEnumDeviceInterfaces(devs, NULL, &spider8usb, n, &devinterface)) {
   struct{
    SP_DEVICE_INTERFACE_DETAIL_DATA id;
    TCHAR space[MAX_PATH];
   }id;
   id.id.cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
   if (SetupDiGetDeviceInterfaceDetail(devs,&devinterface,&id.id,sizeof(id)-2,0,0)) {
    ret=(S8H*)LocalAlloc(LPTR,sizeof(S8H));
    ret->h = CreateFile(id.id.DevicePath,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);
    LPTSTR e = id.id.DevicePath+lstrlen(id.id.DevicePath);
    lstrcpy(e,T("\\1"));	// Der Treiber ist so dΣmlich (bzw. universell) konstruiert
    ret->w = CreateFile(id.id.DevicePath,GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);
    lstrcpy(e,T("\\0"));	// Die intfac32.dll setzt hier "\\PIPE00" dran, usbhbm.sys interessiert sich aber nur fⁿr die letzten Ziffern
    ret->r = CreateFile(id.id.DevicePath,GENERIC_READ,0,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);
    ret->o.hEvent = CreateEvent(0,0,0,0);
   }
  }
  SetupDiDestroyDeviceInfoList(devs);
 }
 return ret;
}	// funktioniert.

// Senden und Empfangen.
// str: Sendedaten, sollte mit '\n' abgeschlossen sein
// strsize = -1: Die LΣnge der Sendedaten ergibt sich aus der Nullterminierung.
// strsize = 0: Nichts wird gesendet
// buf: Empfangsdatenpuffer
// bufsize: positiv fⁿr BinΣrdatenempfang (es werden exakt <bufsize> Bytes gelesen)
//          negativ fⁿr Text-Empfang (es werden maximal <-bufsize> Zeichen gelesen und bei "\r\n" abgebrochen)
//          0: Nichts wird empfangen
// Returnwert: Gelesene Zeichen, einschlie▀lich dem ⁿblicherweise abschlie▀endem "\r\n"
// -2 fⁿr Fehler beim Senden, -1 fⁿr Fehler beim Empfang
// Timeout = 500 ms (fest) fⁿr jede Transaktion)
int CALLBACK sendrecv(S8H *h, const char*str, int strsize, char*buf, int bufsize) {
 if (strsize<0) strsize=lstrlenA(str);
 bool end_crlf=false;
 if (bufsize<0) {bufsize=-bufsize; end_crlf=true;}
 DWORD xfer;
 int i=0;
 while (i!=strsize) {
  if (!WriteFile(h->w,str+i,strsize-i,&xfer,&h->o)	// wom÷glich in USB-Paketstⁿckelung (64 Byte)
  && (GetLastError()!=ERROR_IO_PENDING
  || WaitForSingleObject(h->o.hEvent,500)		// max. ╜ Sekunde auf USB-BulkOut warten
  || !GetOverlappedResult(h->w,&h->o,&xfer,FALSE))) {
   CancelIo(h->w);
   return -2;
  }
  i+=xfer;
 }
 i=0;
 while (i!=bufsize) {
  if (!ReadFile(h->r,buf+i,bufsize-i,&xfer,&h->o)	// wom÷glich in USB-Paketstⁿckelung (64 Byte)
  && (GetLastError()!=ERROR_IO_PENDING
  || WaitForSingleObject(h->o.hEvent,500)		// max. ╜ Sekunde auf Antwort warten
  || !GetOverlappedResult(h->r,&h->o,&xfer,FALSE))) {
   CancelIo(h->r);
   return -1;
  }
  i+=xfer;
  if (end_crlf && i>=2 && buf[i-2]=='\r' && buf[i-1]=='\n') break;
 }
 return i;
}	// funktioniert GENAU SO!

void CALLBACK flush(S8H *h) {
 char buf[256];
 DWORD br;
 while (ReadFile(h->r,buf,sizeof buf,&br,&h->o));	// Lesen bis Ende, blockiert nicht
 if (GetLastError()==ERROR_IO_PENDING) CancelIo(h->r);	// angeschubste Transaktion abbrechen
}

void CALLBACK close(S8H *h) {
 CloseHandle(h->r);
 CloseHandle(h->w);
 CloseHandle(h->h);
 CloseHandle(h->o.hEvent);
 LocalFree(h);
}

// Einfache Testfunktion, Aufruf durch "rundll32 spider8direkt,Test"
// Es leuchtet die gelbe Transfer-LED kurz auf,
// und die rote Error-LED geht aus falls diese an war.
// Im Normalfall zeigt sich ein Meldungsfenster mit dem Fehlerkode, zumeist "0".
// Bei sonstigem Fehler (keine USB-Verbindung) passiert nichts.
//
// Mittels "rundll32 spider8direkt,Test <kommando>" kann man auch alles andere erfragen/setzen.
// Siehe spider8.hlp oder spider8.chm.
// Allerdings kommt bei "OMB?" Quatsch heraus,
// und bei zufΣlligem CRLF im Datenstrom wird vorzeitig abgebrochen.
void CALLBACK TestA(HWND wnd,HINSTANCE,char*cmdline,int) {
 S8H *h=open();
 if (h) {
  flush(h);	// l÷scht noch anstehende Eingabedaten
  char s[256];
  if (lstrlenA(cmdline)) lstrcpynA(s,cmdline,sizeof s-1);
  else lstrcpyA(s,"EST?");
  lstrcatA(s,"\n");
  int len=sendrecv(h,s,-1,s,-(int)(sizeof s-1));	// Senden und Empfangen im Textmodus
  if (len>=0) {
   s[len]=0;
   MessageBoxA(wnd,s,"OK",0);
  }
  close(h);
 }
}
Detected encoding: OEM (CP437)1
Wrong umlauts? - Assume file is ANSI (CP1252) encoded