// // File: // // Written by: David M. Stanhope [voip@fobbit.com] // // General USB Driver Interface // // Thanks to Peter J. Zandvoort [pzand@planetcable.net] // for the code to support multiple devices // #include "vblast.h" #include "vb_usb.h" #include "vb_guid.h" #include "usbdi.h" void set_timeout(void) { // alarm(5); } void clr_timeout(void) { // alarm(0); } void init_network(void) { WORD VersionWanted; WSADATA wsaData ; HANDLE phandle ; VersionWanted = MAKEWORD(2, 0); if(WSAStartup(VersionWanted, &wsaData) != 0) { ERR(("WSAStartup failed\n")) exit(-1); } if((LOBYTE(wsaData.wVersion) != 2) || (HIBYTE(wsaData.wVersion) != 0)) { ERR(("WSAStartup: invalid Winsock version\n")) WSACleanup(); exit(-1); } phandle = GetCurrentProcess(); SetPriorityClass(phandle, HIGH_PRIORITY_CLASS); } void set_non_blocking(SOCKET fd) { unsigned long n = 1; ioctlsocket(fd, FIONBIO, &n); } char * os_name(void) { OSVERSIONINFO info; static char buf[128]; if(buf[0]) { return buf; } memset(&info, 0, sizeof(info)); info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if(GetVersionEx(&info) == 0) { ERR(("GetVersionEx() failed\n")) exit(-1); } if(info.dwPlatformId == VER_PLATFORM_WIN32s) { strcpy(buf, "WIN3.1"); } else if(info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { if(info.dwMinorVersion == 0) { strcpy(buf, "WIN95"); } else if(info.dwMinorVersion < 90) { strcpy(buf, "WIN98"); } else { strcpy(buf, "WINME"); } } else if(info.dwPlatformId == VER_PLATFORM_WIN32_NT) { if(info.dwMajorVersion <= 4) { strcpy(buf, "WINNT"); } else if(info.dwMinorVersion == 0) { strcpy(buf, "WIN2K"); } else { strcpy(buf, "WINXP"); } } else { sprintf(buf, "WIN(%d)", info.dwPlatformId); } sprintf(buf + strlen(buf), " %d.%d.%d", info.dwMajorVersion, info.dwMinorVersion, info.dwBuildNumber ); return buf; } #ifdef ALLOW_KEYBOARD #define KEYBOARD_PORT_RX 8988 #define KEYBOARD_PORT_TX 9088 static SOCKET fd_key = INVALID_SOCKET; static int keyboard_index = -1; static struct sockaddr_in key_send_address; static SOCKET create_key_socket(int port) { // should only be locally accessible return create_socket(SOCK_DGRAM, port, inet_addr("127.0.0.1")); } void keyboard_open(VBLAST *v, int device_index) { if((v->fd_keyboard = create_key_socket(KEYBOARD_PORT_RX + device_index)) == INVALID_SOCKET) { exit(-1); } keyboard_index = device_index; } void keyboard_close(VBLAST *v) { if(v->fd_keyboard != INVALID_SOCKET) { Socket_Close(v->fd_keyboard); v->fd_keyboard = INVALID_SOCKET; } } void keyboard_send(int key) { char buf[1]; MSG1(("KEY(0x%02x)\n", key)) if(fd_key == INVALID_SOCKET) { if(keyboard_index < 0) { return; } // initialization not done if((fd_key= create_key_socket(KEYBOARD_PORT_TX + keyboard_index)) == INVALID_SOCKET) { exit(-1); } // build the 'sendto' address init_address(KEYBOARD_PORT_RX, &key_send_address); key_send_address.sin_addr.s_addr = inet_addr("127.0.0.1"); } buf[0] = key; if(sendto(fd_key, buf, 1, 0, (struct sockaddr *)&key_send_address, sizeof(struct sockaddr_in)) != 1) { ERR(("keyboard_send: error(%s)\n", Socket_Error())) exit(-1); } } #endif // ALLOW_KEYBOARD void init_title(int argc, char *argv[], char *envp[], char *name) { // do nothing, not used under windows } static BOOL GetDeviceInterfacePath( HDEVINFO hDevInfo, PSP_DEVICE_INTERFACE_DATA pDeviceInterfaceData, char *dest, DWORD dwMaxLen ) { PSP_INTERFACE_DEVICE_DETAIL_DATA pDetailData = NULL; ULONG requiredLength = 0; // // allocate a function class device data structure to receive the // goods about this particular device. // SetupDiGetInterfaceDeviceDetail(hDevInfo, pDeviceInterfaceData, // NULL, // probing so no output buffer yet 0, // probing so output buffer length of zero &requiredLength, // NULL); // not interested in the specific dev-node pDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, requiredLength); ZeroMemory( pDetailData, requiredLength ); pDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // // Retrieve the information from Plug and Play. // if(!SetupDiGetDeviceInterfaceDetail(hDevInfo, pDeviceInterfaceData, pDetailData, requiredLength, NULL, NULL)) { ERR(("Error: %ld in GetDeviceInterfacePath\n", GetLastError())) LocalFree(pDetailData); return FALSE; } strncpy(dest,pDetailData->DevicePath, dwMaxLen); LocalFree(pDetailData); return TRUE; } static BOOL GetDevicePath( LPGUID pGuid, DWORD dwIndex, char *dest, DWORD dwMaxLen ) { HDEVINFO hDevInfoList; SP_DEVINFO_DATA DeviceInfoData; SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; BOOL result; // Create a HDEVINFO with all present devices. hDevInfoList = SetupDiGetClassDevs( pGuid, // this guid only 0, // Enumerator 0, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE ); if (hDevInfoList == INVALID_HANDLE_VALUE) { ERR(("Error(%ld) in GetDevicePath:SetupDiGetClassDevs\n", GetLastError())) return FALSE; } // Get the Info for the specific device instance (dwIndex) DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); if (!SetupDiEnumDeviceInfo(hDevInfoList, dwIndex, &DeviceInfoData)) { ERR(("Error(%ld) in GetDevicePath:SetupDiEnumDeviceInfo\n", GetLastError())) SetupDiDestroyDeviceInfoList(hDevInfoList); // Cleanup return FALSE; } // // for the desired interface, get the path // ZeroMemory(&DeviceInterfaceData, sizeof(DeviceInterfaceData)); DeviceInterfaceData.cbSize = sizeof(DeviceInterfaceData); if(!SetupDiEnumDeviceInterfaces( hDevInfoList, &DeviceInfoData, pGuid, 0, &DeviceInterfaceData)) { ERR(("Error(%ld) in GetDevicePath:SetupDiEnumDeviceInterfaces\n", GetLastError())) SetupDiDestroyDeviceInfoList(hDevInfoList); // Cleanup return FALSE; } result = GetDeviceInterfacePath( hDevInfoList, &DeviceInterfaceData, dest, dwMaxLen ); SetupDiDestroyDeviceInfoList(hDevInfoList); // Cleanup return result; } //generated from the GUID registered by the driver itself static char completeDeviceName[256] = ""; // // Routine Description: // // Called by main() to open an instance of our device after // obtaining its name // // Arguments: // // None // // Return Value: // // Device handle on success else NULL // static HANDLE open_file(char *filename, DWORD dwIndex) { int success = 1; HANDLE h; if(!GetDevicePath( (LPGUID) &GUID_CLASS_VOIP_BLASTER, dwIndex, completeDeviceName, sizeof(completeDeviceName) )) { return INVALID_HANDLE_VALUE; } strcat(completeDeviceName, "\\" ); strcat(completeDeviceName, filename); MSG3(("completeDeviceName = (%s)\n", completeDeviceName)) h = CreateFile(completeDeviceName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, NULL); if(h == INVALID_HANDLE_VALUE) { ERR(("Failed to open (%s) = %d\n", completeDeviceName, GetLastError())) success = 0; } else { MSG3(("Opened successfully.\n")) } return h; } // -------------------------------------------------------------------------- #define FORE_BACK_PORT 8888 static HANDLE fd_voice_inp_h = INVALID_HANDLE_VALUE; static HANDLE fd_status_h = INVALID_HANDLE_VALUE; static short fore_back_port = FORE_BACK_PORT ; static void background_reader(HANDLE fd, char *msg, int n) { SOCKET fd_write; struct sockaddr_in foreground; int got, r; u_char rbuf[32]; HANDLE thandle; MSG(("%s: Startup\n", msg)) memset((char *) &foreground, 0, sizeof(foreground)); foreground.sin_family = AF_INET ; foreground.sin_port = htons(fore_back_port) ; foreground.sin_addr.s_addr = inet_addr("127.0.0.1"); if((fd_write = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { ERR(("%s: socket error(%s)\n", msg, Socket_Error())) exit(-1); } set_timeout(); if(connect(fd_write, (struct sockaddr *) &foreground, sizeof(foreground)) == SOCKET_ERROR) { clr_timeout(); ERR(("%s: connect error(%s)\n", msg, Socket_Error())) Socket_Close(fd_write); exit(-1); } clr_timeout(); MSG(("%s: Connected\n", msg)) thandle = GetCurrentThread(); SetThreadPriority(thandle, THREAD_PRIORITY_ABOVE_NORMAL); while(1) { if(ReadFile(fd, rbuf, n, &got, NULL)) { if(got > 0) { dump(msg, rbuf, got); if((r = send(fd_write, rbuf, got, 0)) != got) { if(r < 0) { ERR(("%s: send(%d) error(%s)\n", msg, got, Socket_Error())) } else { ERR(("%s: send(%d) error, ret(%d)\n", msg, got, r)) } Socket_Close(fd_write); exit(-1); } } } } } static void read_voice(void) { background_reader(fd_voice_inp_h, "voice...inp", 20); } static void read_status(void) { background_reader(fd_status_h, "status..inp", 1); } void vblast_device_close(VBLAST *v) { MSG(("vblast_close-start\n")) if(v->fd_voice_out != INVALID_HANDLE_VALUE) { File_Close(v->fd_voice_out); v->fd_voice_out = INVALID_HANDLE_VALUE; } if(fd_voice_inp_h != INVALID_HANDLE_VALUE) { File_Close(fd_voice_inp_h); fd_voice_inp_h = INVALID_HANDLE_VALUE; } if(v->fd_command != INVALID_HANDLE_VALUE) { File_Close(v->fd_command); v->fd_command = INVALID_HANDLE_VALUE; } if(fd_status_h != INVALID_HANDLE_VALUE) { File_Close(fd_status_h); fd_status_h = INVALID_HANDLE_VALUE; } if(v->fd_voice_inp != INVALID_SOCKET) { Socket_Close(v->fd_voice_inp); v->fd_voice_inp = INVALID_SOCKET; } if(v->fd_status != INVALID_SOCKET) { Socket_Close(v->fd_status); v->fd_status = INVALID_SOCKET; } MSG(("vblast_close-done\n")) } VBLAST * vblast_device_open(int uindex) { static VBLAST vb ; int n ; SOCKET fd_accept ; struct sockaddr_in foreground ; fore_back_port = FORE_BACK_PORT + uindex; if((vb.fd_voice_out = open_file("PIPE00", uindex)) == INVALID_HANDLE_VALUE) { ERR(("open of voice output pipe failed\n")) goto done; } if((fd_voice_inp_h = open_file("PIPE01", uindex)) == INVALID_HANDLE_VALUE) { ERR(("open of voice input pipe failed\n")) goto done; } if((vb.fd_command = open_file("PIPE02", uindex)) == INVALID_HANDLE_VALUE) { ERR(("open of command pipe failed\n")) goto done; } if((fd_status_h = open_file("PIPE03", uindex)) == INVALID_HANDLE_VALUE) { ERR(("open of status pipe failed\n")) goto done; } if((fd_accept = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { ERR(("foregound socket error(%s)\n", Socket_Error())) goto done; } n = 1; setsockopt(fd_accept, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n)); memset((char *) &foreground, 0, sizeof(foreground)); foreground.sin_family = AF_INET ; foreground.sin_port = htons(fore_back_port) ; foreground.sin_addr.s_addr = inet_addr("127.0.0.1"); if(bind(fd_accept, (struct sockaddr *) &foreground, sizeof(foreground)) == SOCKET_ERROR) { ERR(("foregound bind error(%s)\n", Socket_Error())) goto done; } if(listen(fd_accept, 5) == SOCKET_ERROR) { ERR(("foreground listen error(%s)\n", Socket_Error())) goto done; } _beginthread((void *) read_voice , 0, NULL); set_timeout(); if((vb.fd_voice_inp = accept(fd_accept, NULL, NULL)) == INVALID_SOCKET) { clr_timeout(); ERR(("foreground voice accept error(%s)\n", Socket_Error())) goto done; } clr_timeout(); _beginthread((void *) read_status, 0, NULL); set_timeout(); if((vb.fd_status = accept(fd_accept, NULL, NULL)) == INVALID_SOCKET) { clr_timeout(); ERR(("foreground status accept error(%s)\n", Socket_Error())) goto done; } clr_timeout(); Socket_Close(fd_accept); return &vb; done: vblast_device_close(&vb); exit(-1); NEED_RETURN(NULL) } int File_Read(HANDLE fd, void *bp, DWORD len) { DWORD got; if(ReadFile(fd, bp, len, &got, NULL)) { return got; } return -1; } int File_Write(HANDLE fd, void *bp, DWORD len) { DWORD wrote; if(WriteFile(fd, bp, len, &wrote, NULL)) { return wrote; } return -1; } int inet_aton(char *s, struct in_addr *ap) { unsigned long t = inet_addr(s); if(t == INADDR_NONE) return 0; if(ap) { ap->s_addr = t; } return 1; } // // The End! //