www.pudn.com > Usb_Project.rar > usb_diag_lib.c
//////////////////////////////////////////////////////////////// // File - USB_DIAG_LIB.C // // Utility functions for communication with USB devices // using WinDriver's API. // // Copyright (c) 2003 - 2004 Jungo Ltd. http://www.jungo.com // //////////////////////////////////////////////////////////////// // use in wizard's device-specific generated code #include "c:\windriver/include/wdu_lib.h" #include "c:\windriver/include/status_strings.h" #include "c:\windriver/include/utils.h" #include "c:\windriver/samples/shared/usb_diag_lib.h" #include#include #include #include #include #ifdef _USE_SPECIFIC_KERNEL_DRIVER_ #undef WD_Open #define WD_Open WD_OpenKernelHandle #if defined(UNIX) #undef WD_FUNCTION #define WD_FUNCTION(wFuncNum,h,pParam,dwSize,fWait) ((ULONG) ioctl((int)(h), wFuncNum, pParam)) #endif #endif #include "usb_diag_lib.h" #include #include #include #if !defined(ERR) #define ERR printf #endif #define TRANSFER_TIMEOUT 30000 // in msecs static FILE * log_file = NULL; static HANDLE _g_hDevice; typedef struct { DWORD dwListenPipeNum; DWORD dwWritePipeNum; HANDLE hDevice; DWORD dwPacketSize; PVOID pContext; BOOL fStopped; HANDLE hThread; DWORD dwError; } USB_LISTEN_PIPE; static USB_LISTEN_PIPE ListenPipe; // Function: CloseListening() // Stop listening to USB device pipe void CloseListening(USB_LISTEN_PIPE *pListenPipe); // Function: ListenToPipe() // Start listening to a USB device pipe void ListenToPipe(USB_LISTEN_PIPE *pListenPipe); // Function: pipeType2Str() // Returns a string identifying the pipe type // Parameters: // pipeType [in] pipe type // Return Value: // String containing the description of the pipe char *pipeType2Str(ULONG pipeType) { char *res = "unknown"; switch (pipeType) { case PIPE_TYPE_CONTROL: res = "Control"; break; case PIPE_TYPE_ISOCHRONOUS: res = "Isochronous"; break; case PIPE_TYPE_BULK: res = "Bulk"; break; case PIPE_TYPE_INTERRUPT: res = "Interrupt"; break; } return res; } void PrintTime(unsigned char * str) { char datetime_buf[10]; struct _timeb tstruct; /* Display operating system-style date and time. */ _strtime( datetime_buf); printf( "\n %s %s", str, datetime_buf ); _ftime( &tstruct ); printf( ".%3.3u", tstruct.millitm ); _strdate( datetime_buf); printf( " Date: %s \n", datetime_buf ); } void LogTime(unsigned char * str) { char datetime_buf[10]; struct _timeb tstruct; /* Display operating system-style date and time. */ _strtime( datetime_buf); fprintf(log_file, "\n %s %s", str, datetime_buf ); _ftime( &tstruct ); fprintf(log_file, ".%3.3u", tstruct.millitm ); _strdate( datetime_buf); fprintf(log_file, " Date: %s \n", datetime_buf ); } /* frame received */ unsigned long recv_frame_buf[16]; #define recv_frame_len recv_frame_buf[15] unsigned long send_frame_buf[16]; #define send_frame_len send_frame_buf[15] // input of command from user static char line[256]; #define BYTES_IN_LINE 16 #define HEX_CHARS_PER_BYTE 3 #define HEX_STOP_POS BYTES_IN_LINE*HEX_CHARS_PER_BYTE // Function: PrintHexBuffer() // Print a buffer in HEX format // Parameters: // pBuffer [in] pointer to buffer // dwBytes [in] number of bytes to print // Return Value: // None void PrintHexBuffer(PVOID pBuffer, DWORD dwBytes) { PBYTE pData = (PBYTE) pBuffer; CHAR pHex[HEX_STOP_POS+1]; CHAR pAscii[BYTES_IN_LINE+1]; DWORD offset; DWORD i; if (!dwBytes) { printf("\nNULL\n"); return; } for (offset=0; offset =0x20) ? pData[offset] : '.'); } // print the last line. fill with blanks if needed if (offset%BYTES_IN_LINE) { for (i=(offset%BYTES_IN_LINE)*HEX_CHARS_PER_BYTE; i hThread) return; printf("Stop listening to pipe\n"); pListenPipe->fStopped = TRUE; WDU_HaltTransfer(pListenPipe->hDevice, pListenPipe->dwListenPipeNum); ThreadWait(pListenPipe->hThread); pListenPipe->hThread = NULL; } void OpenLogFile(const char * fname) { char datetime_buf[10]; if(log_file == NULL) { log_file = fopen( fname, "a"); if(log_file == NULL) { printf("Open log file fail\n"); } else { _strdate( datetime_buf); fprintf(log_file, "-------------- Date: %s ", datetime_buf ); _strtime( datetime_buf); fprintf(log_file, "Time: %s -------------\n", datetime_buf ); } } } void CloseLogFile(void) { if(log_file != NULL) { fclose(log_file); log_file = NULL; } } // Function: PrintHexBuffer() // Print a buffer in HEX format // Parameters: // pBuffer [in] pointer to buffer // dwBytes [in] number of bytes to print // Return Value: // None void LogHexBuffer(PVOID pBuffer, DWORD dwBytes) { PBYTE pData = (PBYTE) pBuffer; CHAR pHex[HEX_STOP_POS+1]; CHAR pAscii[BYTES_IN_LINE+1]; DWORD offset; DWORD i; if (!dwBytes) { fprintf(log_file, "\nNULL\n"); return; } for (offset=0; offset =0x20) ? pData[offset] : '.'); } // print the last line. fill with blanks if needed if (offset%BYTES_IN_LINE) { for (i=(offset%BYTES_IN_LINE)*HEX_CHARS_PER_BYTE; i dwWritePipeNum, 0, 0, send_ptr, (send_frame_len>16) ? 16 : send_frame_len, &dwBytesTransferred, SetupPacket, TRANSFER_TIMEOUT); if(dwBytesTransferred <= 16) { send_frame_len -= dwBytesTransferred; } else { //impossible send_frame_len = 0; } if(frame_finished) { frame_finished = 0; /* Display operating system-style date and time. */ LogTime("TX Time:"); } if(dwError) { // if(log_file) { fprintf(log_file, "PipeSend error code %X\n", dwError); } printf("PipeSend error code %X\n", dwError); break; } else { LogHexBuffer(send_ptr, dwBytesTransferred); } send_ptr += dwBytesTransferred; totalTransferred += dwBytesTransferred; if(dwBytesTransferred != 16) { frame_finished = 1; } } return totalTransferred; } extern int RF_USB_recv_frame(unsigned char * frame, unsigned int flen); int RF_USB_send_frame(unsigned char * frame, unsigned int flen) { int rc = 0; if(_g_hDevice == NULL) { return -1; } if(!frame) { return -1; } if(flen > (sizeof(send_frame_buf)-sizeof(long))) { return -1; } memcpy(((unsigned char *)&send_frame_buf[0]), frame, flen); send_frame_len = flen; if(ListenPipe.hDevice) { WDU_HaltTransfer(ListenPipe.hDevice, ListenPipe.dwListenPipeNum); } return rc; } typedef int (* RF_USB_RTS_FUNC)(void); RF_USB_RTS_FUNC RF_USB_RTS; // Function: PipeHandlerThread() // Callback function, which listens to a pipe continuously when there is data // available in the pipe // Parameters: // pParam [in] contains the relevant pipe information // Return Value: // None void DLLCALLCONV PipeHandlerThread(void * pParam) { static DWORD dwErrorLast; DWORD dwError; USB_LISTEN_PIPE *pListenPipe = (USB_LISTEN_PIPE*) pParam; PVOID buf = malloc(pListenPipe->dwPacketSize); DWORD frame_finished = 1; DWORD dwBytesTransferred; int rc; for (;;) { if(send_frame_len) { PipeSend(pParam); recv_frame_len = 0; } dwError = WDU_Transfer(pListenPipe->hDevice, pListenPipe->dwListenPipeNum, TRUE, 0, buf, pListenPipe->dwPacketSize, &dwBytesTransferred, NULL, TRANSFER_TIMEOUT); if (pListenPipe->fStopped) { if(log_file) { fprintf(log_file, "Stoped\n"); } printf("Stoped\n"); break; } if (dwError) { if(dwError == WD_IRP_CANCELED) { continue; } if(dwError == WD_TIME_OUT_EXPIRED) { } else if(dwError == WD_DEVICE_NOT_FOUND) { } else if(dwErrorLast != dwError) { if(log_file) { fprintf(log_file, "PipeHandlerThread error code %X\n", dwError); } printf("PipeHandlerThread error code %X\n", dwError); } pListenPipe->dwError = dwError; } else { if((dwBytesTransferred == 0) && (recv_frame_len == 0)) { if(RF_USB_RTS) { RF_USB_RTS(); } continue; } if(frame_finished) { frame_finished = 0; /* Display operating system-style date and time. */ LogTime("RX Time:"); } LogHexBuffer(buf, dwBytesTransferred);; // PrintHexBuffer(buf, dwBytesTransferred); if((recv_frame_len + dwBytesTransferred) > (sizeof(recv_frame_buf)-sizeof(long))) { recv_frame_len = 0; } memcpy(((unsigned char *)&recv_frame_buf[0])+recv_frame_len, buf, dwBytesTransferred); recv_frame_len += dwBytesTransferred; if(dwBytesTransferred != 16) { rc = RF_USB_recv_frame((unsigned char *)&recv_frame_buf[0], recv_frame_len); if(rc != 0) { printf("CRC ERROR\n"); } recv_frame_len = 0; frame_finished = 1; } } //flush file fflush(log_file); } free(buf); } // Function: ListenToPipe() // Start listening to a USB device pipe // Parameters: // pListenPipe [in] pipe to listen to // Return Value: // None void ListenToPipe(USB_LISTEN_PIPE *pListenPipe) { // start the running thread pListenPipe->fStopped = FALSE; printf("Start listening to pipe\n"); pListenPipe->dwError = ThreadStart(&pListenPipe->hThread, PipeHandlerThread, (PVOID) pListenPipe); } // Function: ListenToPipe() // Start listening to a USB device pipe // Parameters: // pListenPipe [in] pipe to listen to // Return Value: // None void Start_ListenToPipe(DWORD PipeNum) { HANDLE hDevice = _g_hDevice; WDU_DEVICE *pDevice; USB_LISTEN_PIPE *pListenPipe = & ListenPipe; DWORD dwError; WDU_ALTERNATE_SETTING *pAltSet; WDU_PIPE_INFO *pPipes; BYTE i=0; if(hDevice == NULL) { //no device found return; } if(ListenPipe.hDevice != NULL) { //already started return; } dwError = WDU_GetDeviceInfo(hDevice, &pDevice); if (dwError) { ERR("ReadWritePipesMenu: WDU_GetDeviceInfo() failed: error 0x%lx (\"%s\")\n", dwError, Stat2Str(dwError)); return; } pAltSet = pDevice->pActiveInterface->pActiveAltSetting; pPipes = pAltSet->pPipes; // search for the pipe if (PipeNum) { for (i=0; i Descriptor.bNumEndpoints; i++) if (pPipes[i].dwNumber==PipeNum) break; if (i >= pAltSet->Descriptor.bNumEndpoints) { printf("The pipe number 0x%lx does not exist.\n", PipeNum); return; } } BZERO(ListenPipe); ListenPipe.dwListenPipeNum = PipeNum; ListenPipe.dwWritePipeNum = PipeNum & (~0x80); ListenPipe.hDevice = hDevice; ListenPipe.dwPacketSize = pPipes[i].dwMaximumPacketSize; // start the running thread pListenPipe->fStopped = FALSE; printf("Start listening to pipe\n"); recv_frame_len = 0; send_frame_len = 0; pListenPipe->dwError = ThreadStart(&pListenPipe->hThread, PipeHandlerThread, (PVOID) pListenPipe); } void Stop_ListenToPipe(DWORD PipeNum) { USB_LISTEN_PIPE *pListenPipe = & ListenPipe; if(ListenPipe.hDevice) { CloseListening(pListenPipe); ListenPipe.hDevice = NULL; } } // Function: GetHexChar(void) // Get next character from user // Parameters: // None // Return Value: // Character received int GetHexChar(void) { int ch; ch = getchar(); if (!isxdigit(ch)) return -1; if (isdigit(ch)) return ch - '0'; else return toupper(ch) - 'A' + 10; } // Function: GetHexBuffer() // Get hex buffer from user // Parameters: // pBuffer [in] pointer to buffer // dwBytes [in] length of buffer // Return Value: // Size of buffer received DWORD GetHexBuffer(PVOID pBuffer, DWORD dwBytes) { DWORD i; PBYTE pData = (PBYTE)pBuffer; int res; int ch; for (i=0; i Descriptor.bNumEndpoints) { printf(" no pipes are defined for this device other than the default pipe (number 0).\n"); return; } for (p=0; p Descriptor.bNumEndpoints; p++) { pPipe = &pAltSet->pPipes[p]; printf(" pipe num. 0x%lx: packet size %ld, type %s, dir %s, interval %ld (ms)\n", pPipe->dwNumber, pPipe->dwMaximumPacketSize, pipeType2Str(pPipe->type), pPipe->direction==WDU_DIR_IN ? "In" : pPipe->direction==WDU_DIR_OUT ? "Out" : "In & Out", pPipe->dwInterval); } } static void PrintEndpoints(WDU_ALTERNATE_SETTING *pAltSet) { BYTE endp; WDU_ENDPOINT_DESCRIPTOR *pEndp; for (endp=0; endp Descriptor.bNumEndpoints; endp++) { pEndp = &pAltSet->pEndpointDescriptors[endp]; printf(" end-point address: 0x%02x, attributes: 0x%x, max packet %d, Interval: %d\n", pEndp->bEndpointAddress, pEndp->bmAttributes, pEndp->wMaxPacketSize, pEndp->bInterval); } } // Function: PrintDeviceConfigurations() // Prints the device's configurations information // Parameters: // hDevice [in] handle to the USB device // Return Value: // None void PrintDeviceConfigurations(HANDLE hDevice) { DWORD dwError; WDU_DEVICE *pDevice = NULL; DWORD ifc, alt; UINT32 iConf; WDU_CONFIGURATION *pConf; WDU_INTERFACE *pInterface; WDU_ALTERNATE_SETTING *pAltSet; dwError = WDU_GetDeviceInfo(hDevice, &pDevice); if (dwError) { ERR("PrintDeviceConfigurations: WDU_GetDeviceInfo failed: error 0x%lx (\"%s\")\n", dwError, Stat2Str(dwError)); goto Exit; } printf("This device has %d configurations:\n", pDevice->Descriptor.bNumConfigurations); for (iConf=0; iConf Descriptor.bNumConfigurations; iConf++) { printf(" %d. configuration value %d (has %ld interfaces)\n", iConf, pDevice->pConfigs[iConf].Descriptor.bConfigurationValue, pDevice->pConfigs[iConf].dwNumInterfaces); } iConf = 0; if (pDevice->Descriptor.bNumConfigurations>1) { printf("Please enter the configuration index to display (dec - zero based): "); fgets(line, sizeof(line), stdin); sscanf(line, "%d", &iConf); if (iConf >= pDevice->Descriptor.bNumConfigurations) { printf("ERROR: invalid configuration index, valid values are 0-%d\n", pDevice->Descriptor.bNumConfigurations); goto Exit; } } pConf = &pDevice->pConfigs[iConf]; printf("The configuration indexed %d has %ld interface(s):\n", iConf, pConf->dwNumInterfaces); for (ifc=0; ifc dwNumInterfaces; ifc++) { pInterface = &pConf->pInterfaces[ifc]; printf("interface no. %d:\n", pInterface->pAlternateSettings[0].Descriptor.bInterfaceNumber); for (alt=0; alt dwNumAltSettings; alt++) { pAltSet = &pInterface->pAlternateSettings[alt]; printf(" alternate: %d, endpoints: %d, class: 0x%x, subclass: 0x%x, protocol: 0x%x\n", pAltSet->Descriptor.bAlternateSetting, pAltSet->Descriptor.bNumEndpoints, pAltSet->Descriptor.bInterfaceClass, pAltSet->Descriptor.bInterfaceSubClass, pAltSet->Descriptor.bInterfaceProtocol); PrintEndpoints(pAltSet); } printf("\n"); } printf("\n"); Exit: if (pDevice) WDU_PutDeviceInfo(pDevice); } // Function: ReadWritePipesMenu() // Displays menu to read/write from the device's pipes // Parameters: // hDevice [in] handle to the USB device // Return Value: // None void ReadWritePipesMenu(HANDLE hDevice) { DWORD dwError; WDU_DEVICE *pDevice; WDU_ALTERNATE_SETTING *pAltSet; WDU_PIPE_INFO *pPipes; BYTE SetupPacket[8]; DWORD cmd, dwPipeNum, dwSize, dwBytesTransferred; BYTE i=0; VOID *pBuffer; USB_LISTEN_PIPE listenPipe; int c; dwError = WDU_GetDeviceInfo(hDevice, &pDevice); if (dwError) { ERR("ReadWritePipesMenu: WDU_GetDeviceInfo() failed: error 0x%lx (\"%s\")\n", dwError, Stat2Str(dwError)); return; } pAltSet = pDevice->pActiveInterface->pActiveAltSetting; pPipes = pAltSet->pPipes; PrintPipesInfo(pAltSet); do { printf("\n"); printf("Read/Write from/to device's pipes\n"); printf("---------------------\n"); printf("1. Read from pipe\n"); printf("2. Write to pipe\n"); printf("3. Listen to pipe (contiguous read)\n"); printf("99. Main menu\n"); printf("Enter option: "); cmd = 0; fgets(line, sizeof(line), stdin); sscanf(line, "%ld", &cmd); if (cmd==99) break; if (cmd<1 || cmd>3) continue; printf("Please enter the pipe number (hex): 0x"); fgets(line, sizeof(line), stdin); dwPipeNum=0; sscanf(line, "%lx", &dwPipeNum); // search for the pipe if (dwPipeNum) { for (i=0; i Descriptor.bNumEndpoints; i++) if (pPipes[i].dwNumber==dwPipeNum) break; if (i >= pAltSet->Descriptor.bNumEndpoints) { printf("The pipe number 0x%lx does not exist, please try again.\n", dwPipeNum); continue; } } switch (cmd) { case 1: case 2: if (!dwPipeNum || pPipes[i].type==PIPE_TYPE_CONTROL) { printf("Please enter setup packet (hex - 8 bytes): "); GetHexBuffer((PVOID) SetupPacket, 8); } printf("Please enter the size of the buffer (dec): "); fgets(line, sizeof(line), stdin); sscanf(line, "%ld", &dwSize); pBuffer = malloc(dwSize); if (!pBuffer) { ERR("cannot alloc memory\n"); break; } if (cmd==2) { printf("Please enter the input buffer (hex): "); GetHexBuffer(pBuffer, dwSize); } dwError = WDU_Transfer(hDevice, dwPipeNum? pPipes[i].dwNumber : 0, cmd==1, 0, pBuffer, dwSize, &dwBytesTransferred, SetupPacket, TRANSFER_TIMEOUT); if (dwError) ERR("ReadWritePipesMenu: WDU_Transfer() failed: error 0x%lx (\"%s\")\n", dwError, Stat2Str(dwError)); else { printf("Transferred %ld bytes\n", dwBytesTransferred); if (cmd==1) PrintHexBuffer(pBuffer, dwBytesTransferred); } free(pBuffer); break; case 3: if (!dwPipeNum || pPipes[i].type==PIPE_TYPE_CONTROL) { printf("Cannot listen to control pipes.\n"); break; } BZERO(listenPipe); listenPipe.dwListenPipeNum = dwPipeNum; listenPipe.hDevice = hDevice; listenPipe.dwPacketSize = pPipes[i].dwMaximumPacketSize; printf("Press to start listening. While listening, press to stop\n\n"); getchar(); ListenToPipe(&listenPipe); if (listenPipe.dwError) { ERR("ReadWritePipesMenu: error listening to pipe 0x%lx: error 0x%lx (\"%s\")\n", dwPipeNum, listenPipe.dwError, Stat2Str(listenPipe.dwError)); break; } while ((c=getchar())!=10) {} // ESC code CloseListening(&listenPipe); if (listenPipe.dwError) ERR("ReadWritePipesMenu: WDU_Transfer failed: error 0x%lx (\"%s\")\n", listenPipe.dwError, Stat2Str(listenPipe.dwError)); break; } } while (1); if (pDevice) WDU_PutDeviceInfo(pDevice); }