diff options
Diffstat (limited to 'common_functions.c')
-rw-r--r-- | common_functions.c | 820 |
1 files changed, 820 insertions, 0 deletions
diff --git a/common_functions.c b/common_functions.c new file mode 100644 index 0000000..388b4b0 --- /dev/null +++ b/common_functions.c @@ -0,0 +1,820 @@ +#include "common.h" +#include "common_functions.h" +#include "I2CSPI.h" +#include "deviceRW.h" +#include "fileIO.h" +#include "progAVR.h" + + +#define FALSE 0 +#define TRUE (!0) +#define MinDly 0 + + +void ProgID(); +int CheckS1(); +char** strings; //!localized strings +int saveLog=0,programID=0,load_osccal=0,load_BKosccal=0; +int use_osccal=1,use_BKosccal=0; +int load_calibword=0,max_err=200; +int AVRlock=0x100,AVRfuse=0x100,AVRfuse_h=0x100,AVRfuse_x=0x100; +int ICDenable=0,ICDaddr=0x1FF0; +int FWVersion=0,HwID=0; +FILE* logfile=0; +char LogFileName[512]=""; +char loadfile[512]="",savefile[512]=""; +char CoffFileName[512]=""; +WORD *memCODE_W=0; +int size=0,sizeW=0,sizeEE=0,sizeCONFIG=0,sizeUSERID=0; +unsigned char *memCODE=0,*memEE=0,memID[64],memCONFIG[48],memUSERID[8]; +double hvreg=0; +int RWstop=0; +int forceConfig=0; +char str[4096]; + +void printMsg(const char* msg) +{ +#ifdef OPGUI + MsgBox(msg); +#else + PrintMessage(msg); + fflush(stdout); + getchar(); +#endif +} + +#if !defined _WIN32 && !defined __CYGWIN__ //Linux + int fd = -1; + #if defined hiddevIO && defined OPGUI + struct hiddev_report_info rep_info_i,rep_info_u; + struct hiddev_usage_ref_multi ref_multi_i,ref_multi_u; + #endif + unsigned char bufferU[128],bufferI[128]; +#else //Windows + unsigned char bufferU0[128],bufferI0[128]; + unsigned char *bufferU,*bufferI; + DWORD NumberOfBytesRead,BytesWritten; + ULONG Result; + HANDLE WriteHandle,ReadHandle; + OVERLAPPED HIDOverlapped; + HANDLE hEventObject; +#endif + +/// +///Start HV regulator +int StartHVReg(double V){ + int j=0,z; + int vreg=(int)(V*10.0); + if(saveLog&&logfile) fprintf(logfile,"StartHVReg(%.2f)\n",V); + DWORD t0,t; + if(V==-1){ + bufferU[j++]=VREG_DIS; //disable HV regulator + bufferU[j++]=FLUSH; + PacketIO(5); + msDelay(40); + return -1; + } + t=t0=GetTickCount(); + bufferU[j++]=VREG_EN; //enable HV regulator + bufferU[j++]=SET_VPP; + bufferU[j++]=vreg; + bufferU[j++]=SET_PARAMETER; + bufferU[j++]=SET_T3; + bufferU[j++]=2000>>8; + bufferU[j++]=2000&0xff; + bufferU[j++]=WAIT_T3; + bufferU[j++]=READ_ADC; + bufferU[j++]=FLUSH; + for(;j<DIMBUF;j++) bufferU[j]=0x0; + PacketIO(5); + msDelay(20); + for(z=0;z<DIMBUF-2&&bufferI[z]!=READ_ADC;z++); + int v=(bufferI[z+1]<<8)+bufferI[z+2]; +// PrintMessage2("v=%d=%fV\n",v,v/G); + if(v==0){ + PrintMessage(strings[S_lowUsbV]); //"Tensione USB troppo bassa (VUSB<4.5V)\r\n" + return 0; + } + j=0; + bufferU[j++]=WAIT_T3; + bufferU[j++]=READ_ADC; + bufferU[j++]=FLUSH; + for(;j<DIMBUF;j++) bufferU[j]=0x0; + for(;(v<(vreg/10.0-1)*G||v>(vreg/10.0+1)*G)&&t<t0+1500;t=GetTickCount()){ + PacketIO(5); + msDelay(20); + for(z=0;z<DIMBUF-2&&bufferI[z]!=READ_ADC;z++); + v=(bufferI[z+1]<<8)+bufferI[z+2]; + if(HwID==3) v>>=2; //if 12 bit ADC +// PrintMessage2("v=%d=%fV\n",v,v/G); + } + if(v>(vreg/10.0+1)*G){ + PrintMessage(strings[S_HiVPP]); //"Attenzione: tensione regolatore troppo alta\r\n\r\n" + return 0; + } + else if(v<(vreg/10.0-1)*G){ + PrintMessage(strings[S_LowVPP]); //"Attenzione: tensione regolatore troppo bassa\r\n\r\n" + return 0; + } + else if(v==0){ + PrintMessage(strings[S_lowUsbV]); //"Tensione USB troppo bassa (VUSB<4.5V)\r\n" + return 0; + } + else{ + PrintMessage2(strings[S_reg],t-t0,v/G); //"Regolatore avviato e funzionante dopo T=%d ms VPP=%.1f\r\n\r\n" + if(saveLog&&logfile) fprintf(logfile,strings[S_reg],t-t0,v/G); + return vreg; + } +} + +/// +///Read programmer ID +void ProgID() +{ + if(DeviceDetected!=1) return; + int j=0; + bufferU[j++]=PROG_RST; + bufferU[j++]=FLUSH; + for(;j<DIMBUF;j++) bufferU[j]=0x0; + PacketIO(2); + for(j=0;j<DIMBUF-7&&bufferI[j]!=PROG_RST;j++); + PrintMessage3(strings[S_progver],bufferI[j+1],bufferI[j+2],bufferI[j+3]); //"FW versione %d.%d.%d\r\n" + FWVersion=(bufferI[j+1]<<16)+(bufferI[j+2]<<8)+bufferI[j+3]; + PrintMessage3(strings[S_progid],bufferI[j+4],bufferI[j+5],bufferI[j+6]); //"ID Hw: %d.%d.%d" + HwID=bufferI[j+6]; + if(HwID==1) PrintMessage(" (18F2550)\r\n\r\n"); + else if(HwID==2) PrintMessage(" (18F2450)\r\n\r\n"); + else if(HwID==3) PrintMessage(" (18F2458/2553)\r\n\r\n"); + else if(HwID==4) PrintMessage(" (18F25K50)\r\n\r\n"); + else if(HwID==5) PrintMessage(" (18F25K50 all-in-one variant)\r\n\r\n"); + else PrintMessage(" (?)\r\n\r\n"); +#ifdef OPGUI + // Disable 3.3V check and hide the option for all-in-one board. Enable and show for others + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b_V33check), HwID==5 ? TRUE : FALSE); + gtk_widget_set_visible(GTK_WIDGET(b_V33check), HwID==5 ? FALSE : TRUE); +#endif +} +/// +///Check if a 3.3V regulator is present +int CheckV33Regulator() +{ + int i,j=0; + if(skipV33check) return 1; + bufferU[j++]=WRITE_RAM; + bufferU[j++]=0x0F; + bufferU[j++]=0x93; + bufferU[j++]=0xFE; //B0 = output + bufferU[j++]=EXT_PORT; + bufferU[j++]=0x01; //B0=1 + bufferU[j++]=0; + bufferU[j++]=READ_RAM; + bufferU[j++]=0x0F; + bufferU[j++]=0x81; //Check if B1=1 + bufferU[j++]=EXT_PORT; + bufferU[j++]=0x00; //B0=0 + bufferU[j++]=0; + bufferU[j++]=READ_RAM; + bufferU[j++]=0x0F; + bufferU[j++]=0x81; //Check if B1=0 + bufferU[j++]=WRITE_RAM; + bufferU[j++]=0x0F; + bufferU[j++]=0x93; + bufferU[j++]=0xFF; //BX = input + bufferU[j++]=FLUSH; + for(;j<DIMBUF;j++) bufferU[j]=0x0; + PacketIO(5); + for(j=0;j<DIMBUF-3&&bufferI[j]!=READ_RAM;j++); + i=bufferI[j+3]&0x2; //B1 should be high + for(j+=3;j<DIMBUF-3&&bufferI[j]!=READ_RAM;j++); + return (i+(bufferI[j+3]&0x2))==2?1:0; +} + +/// +///Check if S1 is pressed +int CheckS1() +{ + int i,j=0; + bufferU[j++]=READ_RAM; + bufferU[j++]=0x0F; + if (HwID==5) { //all-in-one board + bufferU[j++]=0x80; // Read PORTA + } + else { //std board + bufferU[j++]=0x84; //READ PORTE + } + bufferU[j++]=FLUSH; + for(;j<DIMBUF;j++) bufferU[j]=0x0; + PacketIO(5); + for(j=0;j<DIMBUF-3&&bufferI[j]!=READ_RAM;j++); + if (HwID==5) { //all-in-one board + i=bufferI[j+3]&0x80; //i=A7 + return i?1:0; //A7=1 when switch pressed (active high) + } + else { //std board + i=bufferI[j+3]&0x8; //i=E3 + return i?0:1; //S1 open -> E3=1 (active low) + } +} + +/// +///Execute hardware test +#ifdef OPGUI +void TestHw(GtkWidget *widget,GtkWindow* parent) +#else +void TestHw(void) +#endif +{ +#ifndef DEBUG + if(DeviceDetected!=1) return; +#endif + char str[256]; + StartHVReg(13); + int j=0; + printMsg(strings[I_TestHW]); //"Test hardware ..." + bufferU[j++]=SET_CK_D; + bufferU[j++]=0x0; + bufferU[j++]=EN_VPP_VCC; //VDD+VPP + bufferU[j++]=0x5; + bufferU[j++]=FLUSH; + for(;j<DIMBUF;j++) bufferU[j]=0x0; + PacketIO(5); + strcpy(str,strings[I_TestMSG]); + strcat(str,"\n VDDU=5V\n VPPU=13V\n PGD(RB5)=0V\n PGC(RB6)=0V\n PGM(RB7)=0V"); + printMsg(str); + j=0; + bufferU[j++]=SET_CK_D; + bufferU[j++]=0x15; + bufferU[j++]=EN_VPP_VCC; + bufferU[j++]=0x1; //VDD + bufferU[j++]=FLUSH; + for(;j<DIMBUF;j++) bufferU[j]=0x0; + PacketIO(5); + strcpy(str,strings[I_TestMSG]); + strcat(str,"\n VDDU=5V\n VPPU=0V\n PGD(RB5)=5V\n PGC(RB6)=5V\n PGM(RB7)=5V"); + printMsg(str); + j=0; + bufferU[j++]=SET_CK_D; + bufferU[j++]=0x1; + bufferU[j++]=EN_VPP_VCC; + bufferU[j++]=0x4; //VPP + bufferU[j++]=FLUSH; + for(;j<DIMBUF;j++) bufferU[j]=0x0; + PacketIO(5); + strcpy(str,strings[I_TestMSG]); + strcat(str,"\n VDDU=0V\n VPPU=13V\n PGD(RB5)=5V\n PGC(RB6)=0V\n PGM(RB7)=0V"); + printMsg(str); + j=0; + bufferU[j++]=SET_CK_D; + bufferU[j++]=0x4; + bufferU[j++]=EN_VPP_VCC; + bufferU[j++]=0x0; + bufferU[j++]=FLUSH; + for(;j<DIMBUF;j++) bufferU[j]=0x0; + PacketIO(5); + strcpy(str,strings[I_TestMSG]); + strcat(str,"\n VDDU=0V\n VPPU=0V\n PGD(RB5)=0V\n PGC(RB6)=5V\n PGM(RB7)=0V"); + printMsg(str); + j=0; + bufferU[j++]=SET_CK_D; + bufferU[j++]=0x0; + bufferU[j++]=EN_VPP_VCC; + bufferU[j++]=0x0; + bufferU[j++]=FLUSH; + for(;j<DIMBUF;j++) bufferU[j]=0x0; + PacketIO(5); + if(FWVersion>=0x900){ //IO test + int j=0,i,x,r; + strcpy(str,"0000000000000"); + PrintMessage("IO test\nRC|RA|--RB--|\n"); + for(i=0;i<13;i++){ + x=1<<i; + j=0; + bufferU[j++]=EN_VPP_VCC; + bufferU[j++]=0x0; + bufferU[j++]=SET_PORT_DIR; + bufferU[j++]=0x0; //TRISB + bufferU[j++]=0x0; //TRISA-C (RC7:RC6:RA5:RA4:RA3:X:X:X) + bufferU[j++]=EXT_PORT; + bufferU[j++]=x&0xFF; //PORTB + bufferU[j++]=(x>>5)&0xFF; //PORTA-C + bufferU[j++]=READ_B; + bufferU[j++]=READ_AC; + bufferU[j++]=FLUSH; + for(;j<DIMBUF;j++) bufferU[j]=0x0; + PacketIO(5); + for(j=0;j<DIMBUF-1&&bufferI[j]!=READ_B;j++); + r=bufferI[j+1]; + for(j+=2;j<DIMBUF-1&&bufferI[j]!=READ_AC;j++); + r+=(bufferI[j+1]&0xF8)<<5; + for(j=0;j<13;j++) str[12-j]=x&(1<<j)?'1':'0'; + PrintMessage(str); + PrintMessage1(" (%s)\n",r==x?"OK":strings[S_ErrSing]); + } + } +} + +/// +///Wait for X milliseconds +void msDelay(double delay) +{ +#if !defined _WIN32 && !defined __CYGWIN__ + long x=(int)(delay*1000.0); + usleep(x>MinDly?x:MinDly); +#else +// Sleep((long)ceil(delay)>MinDly?(long)ceil(delay):MinDly); + __int64 stop,freq,timeout; + QueryPerformanceCounter((LARGE_INTEGER *)&stop); + QueryPerformanceFrequency((LARGE_INTEGER *)&freq); + timeout=stop+delay*freq/1000.0; + while(stop<timeout) QueryPerformanceCounter((LARGE_INTEGER *)&stop); +#endif +} + +#if !defined _WIN32 && !defined __CYGWIN__ //Linux +/// +/// Get system time +DWORD GetTickCount(){ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec*1000+tv.tv_usec/1000; +/* + struct timeb now; + ftime(&now); + return now.time*1000+now.millitm; +*/ +} +#endif + +/// +///Write data packet, wait for X milliseconds, read response +///real waiting happens only if the desired delay is greater than 40ms; +///in case of smaller delays the function simply waits for a response (up to 50ms) +/// +void PacketIO(double delay){ + #define TIMEOUT 50 + if(saveLog&&logfile) fprintf(logfile,"PacketIO(%.2f)\n",delay); + int delay0=delay; +#if !defined _WIN32 && !defined __CYGWIN__ //Linux + struct timespec ts; + uint64_t start,stop; + fd_set set; + struct timeval timeout; + int rv,i; + FD_ZERO(&set); /* clear the set */ + FD_SET(fd, &set); /* add our file descriptor to the set */ + timeout.tv_sec = 0; + timeout.tv_usec = TIMEOUT*1000; + clock_gettime( CLOCK_REALTIME, &ts ); + start=ts.tv_nsec/1000; + delay-=TIMEOUT-10; //shorter delays are covered by 50ms timeout + if(delay<MinDly) delay=MinDly; + #ifndef hiddevIO //use raw USB device + //wait before writing +/* rv = select(fd + 1, NULL, &set, NULL, &timeout); //wait for write event + if(rv == -1){ + PrintMessage(strings[S_ErrSing]); //error + if(saveLog&&logfile) fprintf(logfile,strings[S_ErrSing]); + return; + } + else if(rv == 0){ + PrintMessage(strings[S_comTimeout]); //"comm timeout\r\n" + if(saveLog&&logfile) fprintf(logfile,strings[S_comTimeout]); + return; + }*/ + //write + int res = write(fd,bufferU,DIMBUF); + if (res < 0) { + printf("Error: %d\n", errno); + perror("write"); + } + usleep((int)(delay*1000.0)); + //wait before reading + rv = select(fd + 1, &set, NULL, NULL, &timeout); //wait for event + if(rv == -1){ + PrintMessage(strings[S_ErrSing]); /*error*/ + if(saveLog&&logfile) fprintf(logfile,strings[S_ErrSing]); + return; + } + else if(rv == 0){ + PrintMessage(strings[S_comTimeout]); /*"comm timeout\r\n"*/ + if(saveLog&&logfile) fprintf(logfile,strings[S_comTimeout]); + return; + } + //read + res = read(fd, bufferI, DIMBUF); + if (res < 0) { + perror("read"); + } + #else //use hiddev device (old method) + struct hiddev_event ev[80]; + int n=DIMBUF; + for(i=0;i<DIMBUF;i++) ref_multi_u.values[i]=bufferU[i]; + //write + ioctl(fd, HIDIOCSUSAGES, &ref_multi_u); + ioctl(fd,HIDIOCSREPORT, &rep_info_u); + usleep((int)(delay*1000.0)); + //read + rv = select(fd + 1, &set, NULL, NULL, &timeout); //wait for event + if(rv == -1){ + PrintMessage(strings[S_ErrSing]); /*error*/ + if(saveLog&&logfile) fprintf(logfile,strings[S_ErrSing]); + } + else if(rv == 0){ + PrintMessage(strings[S_comTimeout]); /*"comm timeout\r\n"*/ + if(saveLog&&logfile) fprintf(logfile,strings[S_comTimeout]); + } + else{ + // ioctl(fd, HIDIOCGUSAGES, &ref_multi_i); + // ioctl(fd,HIDIOCGREPORT, &rep_info_i); + #undef read() + rv=read(fd, ev,sizeof(struct hiddev_event) *n); + for(i=0;(ev[0].value!=bufferU[0])&&i<40;i++){ //read too early; try again after 5ms + msDelay(5); + rv=read(fd, ev,sizeof(struct hiddev_event) *n); + if(saveLog&&logfile) fprintf(logfile,"Packet not ready, wait extra time\n"); + } + if(i==40) fprintf(logfile,"Cannot read correct packet!!\n"); + for(i=0;i<n;i++) bufferI[i]=ev[i].value&0xFF; + } + #endif + clock_gettime( CLOCK_REALTIME, &ts ); + stop = ts.tv_nsec / 1000; + if(saveLog&&logfile){ + WriteLogIO(); + fprintf(logfile,"T=%.2f ms (%+.2f ms)\n",(stop-start)/1000.0,(stop-start)/1000.0-delay0); + if(bufferU[0]!=bufferI[0]) fprintf(logfile,"Cannot read correct packet!!\n"); + } +#else //Windows + __int64 start,stop,freq,timeout; + QueryPerformanceCounter((LARGE_INTEGER *)&start); + QueryPerformanceFrequency((LARGE_INTEGER *)&freq); + delay-=TIMEOUT-10; //shorter delays are covered by 50ms timeout + if(delay<MinDly) delay=MinDly; + //write + Result = WriteFile(WriteHandle,bufferU0,DIMBUF+1,&BytesWritten,NULL); + QueryPerformanceCounter((LARGE_INTEGER *)&stop); + timeout=stop+delay*freq/1000.0; + while(stop<timeout) QueryPerformanceCounter((LARGE_INTEGER *)&stop); + //read + Result = ReadFile(ReadHandle,bufferI0,DIMBUF+1,&NumberOfBytesRead,(LPOVERLAPPED) &HIDOverlapped); + Result = WaitForSingleObject(hEventObject,TIMEOUT); + if(saveLog&&logfile) WriteLogIO(); + ResetEvent(hEventObject); + if(Result!=WAIT_OBJECT_0){ + PrintMessage(strings[S_comTimeout]); /*"comm timeout\r\n"*/ + if(saveLog&&logfile) fprintf(logfile,strings[S_comTimeout]); + } + QueryPerformanceCounter((LARGE_INTEGER *)&stop); + if(saveLog&&logfile) fprintf(logfile,"T=%.2f ms (%+.2f ms)\n",(stop-start)*1000.0/freq,(stop-start)*1000.0/freq-delay0); +#endif +} + + +/// +///Find the USB peripheral with proper vid&pid code +/// return 0 if not found +int FindDevice(int vid,int pid){ + int MyDeviceDetected = FALSE; +#if !defined _WIN32 && !defined __CYGWIN__ //Linux + #ifndef hiddevIO //use raw USB device + struct hidraw_devinfo device_info; + int i=-1; + if(path[0]==0){ //search all devices + if((fd = open("/dev/openprogrammer", O_RDWR|O_NONBLOCK))>0){ //try with this first + sprintf(path,"/dev/openprogrammer"); + ioctl(fd, HIDIOCGRAWINFO, &device_info); + if(device_info.vendor==vid&&device_info.product==pid) i=0; + else{ + close(fd); + i=-1; + } + } + if(i){ + for(i=0;i<16;i++){ + sprintf(path,"/dev/hidraw%d",i); + if((fd = open(path, O_RDWR|O_NONBLOCK))>0){ + ioctl(fd, HIDIOCGRAWINFO, &device_info); + if(device_info.vendor==vid&&device_info.product==pid) break; + else close(fd); + } + } + } + if(i==16){ + PrintMessage(strings[S_noprog]); + path[0]=0; + return 0; + } + } + else{ //user supplied path + if((fd = open(path, O_RDWR|O_NONBLOCK)) < 0) { + PrintMessage1(strings[S_DevPermission],path); //"cannot open %s, make sure you have read permission on it",path); + return 0; + } + ioctl(fd, HIDIOCGRAWINFO, &device_info); + if(device_info.vendor!=vid||device_info.product!=pid){ + PrintMessage(strings[S_noprog]); + return 0; + } + } + printf(strings[S_progDev],path); + return 1; + #else //use hiddev device (old method) + struct hiddev_devinfo device_info; + int i=-1; + if(path[0]==0){ //search all devices + if((fd = open("/dev/openprogrammer", O_RDONLY ))>0){ //try with this first + ioctl(fd, HIDIOCGDEVINFO, &device_info); + if(device_info.vendor==vid&&device_info.product==pid) i=0; + else{ + close(fd); + i=-1; + } + } + if(i){ + for(i=0;i<16;i++){ + sprintf(path,"/dev/usb/hiddev%d",i); + if((fd = open(path, O_RDONLY ))>0){ + ioctl(fd, HIDIOCGDEVINFO, &device_info); + if(device_info.vendor==vid&&device_info.product==pid) break; + else close(fd); + } + } + } + if(i==16){ + PrintMessage(strings[S_noprog]); + path[0]=0; + return 0; + } + } + else{ //user supplied path + if ((fd = open(path, O_RDONLY )) < 0) { + PrintMessage1(strings[S_DevPermission],path); //"cannot open %s, make sure you have read permission on it",path); + return 0; + } + ioctl(fd, HIDIOCGDEVINFO, &device_info); + if(device_info.vendor!=vid||device_info.product!=pid){ + PrintMessage(strings[S_noprog]); + return 0; + } + } + #ifndef OPGUI + printf(strings[S_progDev],path); + #endif + MyDeviceDetected = TRUE; + rep_info_u.report_type=HID_REPORT_TYPE_OUTPUT; + rep_info_i.report_type=HID_REPORT_TYPE_INPUT; + rep_info_u.report_id=rep_info_i.report_id=HID_REPORT_ID_FIRST; + rep_info_u.num_fields=rep_info_i.num_fields=1; + ref_multi_u.uref.report_type=HID_REPORT_TYPE_OUTPUT; + ref_multi_i.uref.report_type=HID_REPORT_TYPE_INPUT; + ref_multi_u.uref.report_id=ref_multi_i.uref.report_id=HID_REPORT_ID_FIRST; + ref_multi_u.uref.field_index=ref_multi_i.uref.field_index=0; + ref_multi_u.uref.usage_index=ref_multi_i.uref.usage_index=0; + ref_multi_u.num_values=ref_multi_i.num_values=DIMBUF; + #endif +#else //Windows + PSP_DEVICE_INTERFACE_DETAIL_DATA detailData; + HANDLE DeviceHandle; + HANDLE hDevInfo; + GUID HidGuid; + char MyDevicePathName[1024]; + ULONG Length; + ULONG Required; + typedef struct _HIDD_ATTRIBUTES { + ULONG Size; + USHORT VendorID; + USHORT ProductID; + USHORT VersionNumber; + } HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; + typedef void (__stdcall*GETHIDGUID) (OUT LPGUID HidGuid); + typedef BOOLEAN (__stdcall*GETATTRIBUTES)(IN HANDLE HidDeviceObject,OUT PHIDD_ATTRIBUTES Attributes); + typedef BOOLEAN (__stdcall*SETNUMINPUTBUFFERS)(IN HANDLE HidDeviceObject,OUT ULONG NumberBuffers); + typedef BOOLEAN (__stdcall*GETNUMINPUTBUFFERS)(IN HANDLE HidDeviceObject,OUT PULONG NumberBuffers); + typedef BOOLEAN (__stdcall*GETFEATURE) (IN HANDLE HidDeviceObject, OUT PVOID ReportBuffer, IN ULONG ReportBufferLength); + typedef BOOLEAN (__stdcall*SETFEATURE) (IN HANDLE HidDeviceObject, IN PVOID ReportBuffer, IN ULONG ReportBufferLength); + typedef BOOLEAN (__stdcall*GETREPORT) (IN HANDLE HidDeviceObject, OUT PVOID ReportBuffer, IN ULONG ReportBufferLength); + typedef BOOLEAN (__stdcall*SETREPORT) (IN HANDLE HidDeviceObject, IN PVOID ReportBuffer, IN ULONG ReportBufferLength); + typedef BOOLEAN (__stdcall*GETMANUFACTURERSTRING) (IN HANDLE HidDeviceObject, OUT PVOID ReportBuffer, IN ULONG ReportBufferLength); + typedef BOOLEAN (__stdcall*GETPRODUCTSTRING) (IN HANDLE HidDeviceObject, OUT PVOID ReportBuffer, IN ULONG ReportBufferLength); + typedef BOOLEAN (__stdcall*GETINDEXEDSTRING) (IN HANDLE HidDeviceObject, IN ULONG StringIndex, OUT PVOID ReportBuffer, IN ULONG ReportBufferLength); + HIDD_ATTRIBUTES Attributes; + SP_DEVICE_INTERFACE_DATA devInfoData; + int LastDevice = FALSE; + int MemberIndex = 0; + LONG Result; + Length=0; + detailData=NULL; + DeviceHandle=NULL; + HMODULE hHID=0; + GETHIDGUID HidD_GetHidGuid=0; + GETATTRIBUTES HidD_GetAttributes=0; + SETNUMINPUTBUFFERS HidD_SetNumInputBuffers=0; + GETNUMINPUTBUFFERS HidD_GetNumInputBuffers=0; + GETFEATURE HidD_GetFeature=0; + SETFEATURE HidD_SetFeature=0; + GETREPORT HidD_GetInputReport=0; + SETREPORT HidD_SetOutputReport=0; + GETMANUFACTURERSTRING HidD_GetManufacturerString=0; + GETPRODUCTSTRING HidD_GetProductString=0; + hHID = LoadLibrary("hid.dll"); + if(!hHID){ + PrintMessage("Can't find hid.dll"); + return 0; + } + HidD_GetHidGuid=(GETHIDGUID)GetProcAddress(hHID,"HidD_GetHidGuid"); + HidD_GetAttributes=(GETATTRIBUTES)GetProcAddress(hHID,"HidD_GetAttributes"); + HidD_SetNumInputBuffers=(SETNUMINPUTBUFFERS)GetProcAddress(hHID,"HidD_SetNumInputBuffers"); + HidD_GetNumInputBuffers=(GETNUMINPUTBUFFERS)GetProcAddress(hHID,"HidD_GetNumInputBuffers"); + HidD_GetFeature=(GETFEATURE)GetProcAddress(hHID,"HidD_GetFeature"); + HidD_SetFeature=(SETFEATURE)GetProcAddress(hHID,"HidD_SetFeature"); + HidD_GetInputReport=(GETREPORT)GetProcAddress(hHID,"HidD_GetInputReport"); + HidD_SetOutputReport=(SETREPORT)GetProcAddress(hHID,"HidD_SetOutputReport"); + HidD_GetManufacturerString=(GETMANUFACTURERSTRING)GetProcAddress(hHID,"HidD_GetManufacturerString"); + HidD_GetProductString=(GETPRODUCTSTRING)GetProcAddress(hHID,"HidD_GetProductString"); + if(HidD_GetHidGuid==NULL\ + ||HidD_GetAttributes==NULL\ + ||HidD_GetFeature==NULL\ + ||HidD_SetFeature==NULL\ + ||HidD_GetInputReport==NULL\ + ||HidD_SetOutputReport==NULL\ + ||HidD_GetManufacturerString==NULL\ + ||HidD_GetProductString==NULL\ + ||HidD_SetNumInputBuffers==NULL\ + ||HidD_GetNumInputBuffers==NULL) return 0; + HMODULE hSAPI=0; + hSAPI = LoadLibrary("setupapi.dll"); + if(!hSAPI){ + PrintMessage("Can't find setupapi.dll"); + return 0; + } + typedef HDEVINFO (WINAPI* SETUPDIGETCLASSDEVS) (CONST GUID*,PCSTR,HWND,DWORD); + typedef BOOL (WINAPI* SETUPDIENUMDEVICEINTERFACES) (HDEVINFO,PSP_DEVINFO_DATA,CONST GUID*,DWORD,PSP_DEVICE_INTERFACE_DATA); + typedef BOOL (WINAPI* SETUPDIGETDEVICEINTERFACEDETAIL) (HDEVINFO,PSP_DEVICE_INTERFACE_DATA,PSP_DEVICE_INTERFACE_DETAIL_DATA_A,DWORD,PDWORD,PSP_DEVINFO_DATA); + typedef BOOL (WINAPI* SETUPDIDESTROYDEVICEINFOLIST) (HDEVINFO); + SETUPDIGETCLASSDEVS SetupDiGetClassDevsA=0; + SETUPDIENUMDEVICEINTERFACES SetupDiEnumDeviceInterfaces=0; + SETUPDIGETDEVICEINTERFACEDETAIL SetupDiGetDeviceInterfaceDetailA=0; + SETUPDIDESTROYDEVICEINFOLIST SetupDiDestroyDeviceInfoList=0; + SetupDiGetClassDevsA=(SETUPDIGETCLASSDEVS) GetProcAddress(hSAPI,"SetupDiGetClassDevsA"); + SetupDiEnumDeviceInterfaces=(SETUPDIENUMDEVICEINTERFACES) GetProcAddress(hSAPI,"SetupDiEnumDeviceInterfaces"); + SetupDiGetDeviceInterfaceDetailA=(SETUPDIGETDEVICEINTERFACEDETAIL) GetProcAddress(hSAPI,"SetupDiGetDeviceInterfaceDetailA"); + SetupDiDestroyDeviceInfoList=(SETUPDIDESTROYDEVICEINFOLIST) GetProcAddress(hSAPI,"SetupDiDestroyDeviceInfoList"); + if(SetupDiGetClassDevsA==NULL\ + ||SetupDiEnumDeviceInterfaces==NULL\ + ||SetupDiDestroyDeviceInfoList==NULL\ + ||SetupDiGetDeviceInterfaceDetailA==NULL) return 0; + /* + The following code is adapted from Usbhidio_vc6 application example by Jan Axelson + for more information see see http://www.lvr.com/hidpage.htm + */ + /* + API function: HidD_GetHidGuid + Get the GUID for all system HIDs. + Returns: the GUID in HidGuid. + */ + HidD_GetHidGuid(&HidGuid); + /* + API function: SetupDiGetClassDevs + Returns: a handle to a device information set for all installed devices. + Requires: the GUID returned by GetHidGuid. + */ + hDevInfo=SetupDiGetClassDevs(&HidGuid,NULL,NULL,DIGCF_PRESENT|DIGCF_INTERFACEDEVICE); + devInfoData.cbSize = sizeof(devInfoData); + //Step through the available devices looking for the one we want. + //Quit on detecting the desired device or checking all available devices without success. + MemberIndex = 0; + LastDevice = FALSE; + do + { + /* + API function: SetupDiEnumDeviceInterfaces + On return, MyDeviceInterfaceData contains the handle to a + SP_DEVICE_INTERFACE_DATA structure for a detected device. + Requires: + The DeviceInfoSet returned in SetupDiGetClassDevs. + The HidGuid returned in GetHidGuid. + An index to specify a device. + */ + Result=SetupDiEnumDeviceInterfaces (hDevInfo, 0, &HidGuid, MemberIndex, &devInfoData); + if (Result != 0) + { + //A device has been detected, so get more information about it. + /* + API function: SetupDiGetDeviceInterfaceDetail + Returns: an SP_DEVICE_INTERFACE_DETAIL_DATA structure + containing information about a device. + To retrieve the information, call this function twice. + The first time returns the size of the structure in Length. + The second time returns a pointer to the data in DeviceInfoSet. + Requires: + A DeviceInfoSet returned by SetupDiGetClassDevs + The SP_DEVICE_INTERFACE_DATA structure returned by SetupDiEnumDeviceInterfaces. + The final parameter is an optional pointer to an SP_DEV_INFO_DATA structure. + This application doesn't retrieve or use the structure. + If retrieving the structure, set + MyDeviceInfoData.cbSize = length of MyDeviceInfoData. + and pass the structure's address. + */ + //Get the Length value. + //The call will return with a "buffer too small" error which can be ignored. + Result = SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInfoData, NULL, 0, &Length, NULL); + //Allocate memory for the hDevInfo structure, using the returned Length. + detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(Length); + //Set cbSize in the detailData structure. + detailData -> cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); + //Call the function again, this time passing it the returned buffer size. + Result = SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInfoData, detailData, Length,&Required, NULL); + // Open a handle to the device. + // To enable retrieving information about a system mouse or keyboard, + // don't request Read or Write access for this handle. + /* + API function: CreateFile + Returns: a handle that enables reading and writing to the device. + Requires: + The DevicePath in the detailData structure + returned by SetupDiGetDeviceInterfaceDetail. + */ + DeviceHandle=CreateFile(detailData->DevicePath, + 0, FILE_SHARE_READ|FILE_SHARE_WRITE, + (LPSECURITY_ATTRIBUTES)NULL,OPEN_EXISTING, 0, NULL); + /* + API function: HidD_GetAttributes + Requests information from the device. + Requires: the handle returned by CreateFile. + Returns: a HIDD_ATTRIBUTES structure containing + the Vendor ID, Product ID, and Product Version Number. + Use this information to decide if the detected device is + the one we're looking for. + */ + //Set the Size to the number of bytes in the structure. + Attributes.Size = sizeof(Attributes); + Result = HidD_GetAttributes(DeviceHandle,&Attributes); + //Is it the desired device? + MyDeviceDetected = FALSE; + if (Attributes.VendorID == vid) + { + if (Attributes.ProductID == pid) + { + //Both the Vendor ID and Product ID match. + MyDeviceDetected = TRUE; + strcpy(MyDevicePathName,detailData->DevicePath); + // Get a handle for writing Output reports. + WriteHandle=CreateFile(detailData->DevicePath, + GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, + (LPSECURITY_ATTRIBUTES)NULL,OPEN_EXISTING,0,NULL); + //Get a handle to the device for the overlapped ReadFiles. + ReadHandle=CreateFile(detailData->DevicePath, + GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,(LPSECURITY_ATTRIBUTES)NULL, + OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL); + if (hEventObject) CloseHandle(hEventObject); + hEventObject = CreateEvent(NULL,TRUE,TRUE,""); + //Set the members of the overlapped structure. + HIDOverlapped.hEvent = hEventObject; + HIDOverlapped.Offset = 0; + HIDOverlapped.OffsetHigh = 0; + Result=HidD_SetNumInputBuffers(DeviceHandle,64); + } + else + //The Product ID doesn't match. + CloseHandle(DeviceHandle); + } + else + //The Vendor ID doesn't match. + CloseHandle(DeviceHandle); + //Free the memory used by the detailData structure (no longer needed). + free(detailData); + } + else + //SetupDiEnumDeviceInterfaces returned 0, so there are no more devices to check. + LastDevice=TRUE; + //If we haven't found the device yet, and haven't tried every available device, + //try the next one. + MemberIndex = MemberIndex + 1; + } //do + while ((LastDevice == FALSE) && (MyDeviceDetected == FALSE)); + //Free the memory reserved for hDevInfo by SetupDiClassDevs. + SetupDiDestroyDeviceInfoList(hDevInfo); + + #ifndef OPGUI + if(info&&MyDeviceDetected == TRUE){ + char string[1024]; + PrintMessage3("Device detected: vid=0x%04X pid=0x%04X\nPath: %s\n",vid,pid,MyDevicePathName); + if(HidD_GetManufacturerString(DeviceHandle,string,sizeof(string))==TRUE) wprintf(L"Manufacturer string: %s\n",string); + if(HidD_GetProductString(DeviceHandle,string,sizeof(string))==TRUE) wprintf(L"Product string: %s\n",string); + } + #endif +#endif + if (MyDeviceDetected == FALSE){ + PrintMessage(strings[S_noprog]); //"Programmer not detected\r\n" + //gtk_statusbar_push(status_bar,statusID,strings[S_noprog]); + } + else{ + PrintMessage(strings[S_prog]); //"Programmer detected\r\n"); +#ifdef OPGUI + PrintMessage2("VID=0x%04X PID=0x%04X\r\n",vid,pid); +#endif + //gtk_statusbar_push(status_bar,statusID,strings[S_prog]); + } + return MyDeviceDetected; +} + |