ysjoyreader.cpp
Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <unistd.h>
00003 #include <stdlib.h>
00004 #include <ctype.h>
00005 #include <sys/errno.h>
00006 #include <sysexits.h>
00007 #include <IOKit/hid/IOHIDLib.h>
00008 
00009 
00010 
00011 
00012 #include "ysjoyreader.h"
00013 
00014 
00015 YsJoyReaderElement::YsJoyReaderElement()
00016 {
00017         exist=0;
00018         elem=NULL;
00019         value=0;
00020 }
00021 
00022 YsJoyReaderAxis::YsJoyReaderAxis()
00023 {
00024         min=0;
00025         max=0;
00026         scaledMin=0;
00027         scaledMax=0;
00028         calibCenter=0;
00029         calibMin=0;
00030         calibMax=0;
00031 }
00032 
00033 double YsJoyReaderAxis::GetCalibratedValue(void) const
00034 {
00035         double calib;
00036 
00037         if(calibCenter<value && calibMax!=calibCenter)
00038         {
00039                 calib=(double)(value-calibCenter)/(double)(calibMax-calibCenter);
00040         }
00041         else if(value<calibCenter && calibMin!=calibCenter)
00042         {
00043                 calib=(double)(value-calibCenter)/(double)(calibCenter-calibMin);
00044         }
00045         else
00046         {
00047                 return 0.0;
00048         }
00049 
00050         if(calib>1.0)
00051         {
00052                 calib=1.0;
00053         }
00054         if(calib<-1.0)
00055         {
00056                 calib=-1.0;
00057         }
00058 
00059         return calib;
00060 }
00061 
00062 void YsJoyReaderAxis::CaptureCenter(void)
00063 {
00064         calibCenter=value;
00065 }
00066 
00067 void YsJoyReaderAxis::BeginCaptureMinMax(void)
00068 {
00069         calibMin=calibCenter+1000;
00070         calibMax=calibCenter-1000;
00071 }
00072 
00073 void YsJoyReaderAxis::CaptureMinMax(void)
00074 {
00075         if(value<calibMin)
00076         {
00077                 calibMin=value;
00078         }
00079         if(value>calibMax)
00080         {
00081                 calibMax=value;
00082         }
00083 }
00084 
00085 void YsJoyReaderAxis::CenterFromMinMax(void)
00086 {
00087         calibCenter=(calibMin+calibMax)/2;
00088 }
00089 
00090 YsJoyReaderButton::YsJoyReaderButton()
00091 {
00092 }
00093 
00094 YsJoyReaderHatSwitch::YsJoyReaderHatSwitch()
00095 {
00096         valueNeutral=0;
00097         value0Deg=1;
00098         value90Deg=3;
00099         value180Deg=5;
00100         value270Deg=7;
00101 }
00102 
00103 int YsJoyReaderHatSwitch::GetDiscreteValue(void) const
00104 {
00105         if(value==valueNeutral)
00106         {
00107                 return 0;
00108         }
00109         else if(value==value0Deg)
00110         {
00111                 return 1;
00112         }
00113         else if(value==value90Deg)
00114         {
00115                 return 3;
00116         }
00117         else if(value==value180Deg)
00118         {
00119                 return 5;
00120         }
00121         else if(value270Deg==value)
00122         {
00123                 return 7;
00124         }
00125         else if(value0Deg<value && value<value90Deg)
00126         {
00127                 return 2;
00128         }
00129         else if(value90Deg<value && value<value180Deg)
00130         {
00131                 return 4;
00132         }
00133         else if(value180Deg<value && value<value270Deg)
00134         {
00135                 return 6;
00136         }
00137         else if(value270Deg<value)
00138         {
00139                 return 8;
00140         }
00141         return 0;
00142 }
00143 
00144 
00145 IOHIDManagerRef YsJoyReader::hidManager=NULL;
00146 CFMutableArrayRef YsJoyReader::devArray=NULL;
00147 
00148 YsJoyReader::YsJoyReader()
00149 {
00150         hidDev=NULL;
00151 }
00152 
00153 int YsJoyReader::SetUpInterface(int joyId,IOHIDDeviceRef hidDev)
00154 {
00155         this->joyId=joyId;
00156 
00157         if(hidDev!=NULL)
00158         {
00159                 CFArrayRef elemAry=IOHIDDeviceCopyMatchingElements(hidDev,NULL,0);
00160                 int nElem=(int)CFArrayGetCount(elemAry);
00161                 int isMouse=0,isJoystick=0,isKeyboard=0,isGamePad=0;
00162 
00163                 printf("This HID Device has %d elements.\n",nElem);
00164 
00165                 int j;
00166                 for(j=0; j<nElem; j++)
00167                 {
00168                         IOHIDElementRef elem=(IOHIDElementRef)CFArrayGetValueAtIndex(elemAry,j);
00169                         IOHIDElementType elemType=IOHIDElementGetType(elem);
00170                         unsigned int usage=IOHIDElementGetUsage(elem);
00171                         unsigned int usagePage=IOHIDElementGetUsagePage(elem);
00172 
00173                         printf("Element %3d",j);
00174                         switch(elemType)
00175                         {
00176                         case kIOHIDElementTypeInput_ScanCodes:
00177                                 printf(" ScanCode  ");
00178                                 break;
00179                         case kIOHIDElementTypeInput_Misc:
00180                                 printf(" Misc      ");
00181                                 break;
00182                         case kIOHIDElementTypeInput_Button:
00183                                 printf(" Button    ");
00184                                 break;
00185                         case kIOHIDElementTypeInput_Axis:
00186                                 printf(" Axis      ");
00187                                 break;
00188                         case kIOHIDElementTypeOutput:
00189                                 printf(" Output    ");
00190                                 break;
00191                         case kIOHIDElementTypeFeature:
00192                                 printf(" Feature   ");
00193                                 break;
00194                         case kIOHIDElementTypeCollection:
00195                                 printf(" Collection");
00196                                 break;
00197                         }
00198 
00199                         printf("  Usage %3d  UsagePage %3d\n",usage,usagePage);
00200 
00201                         if(kHIDPage_GenericDesktop==usagePage)
00202                         {
00203                                 switch(usage)
00204                                 {
00205                                 case kHIDUsage_GD_Mouse:
00206                                         printf("    Can function as mouse\n");
00207                                         isMouse=1;
00208                                         break;
00209                                 case kHIDUsage_GD_Keyboard:
00210                                         printf("    Can function as Keyboard\n");
00211                                         isKeyboard=1;
00212                                         break;
00213                                 case kHIDUsage_GD_Joystick:
00214                                         printf("    Can function as Joystick\n");
00215                                         isJoystick=1;
00216                                         break;
00217                                 case kHIDUsage_GD_GamePad:
00218                                         printf("    Can function as GamePad\n");
00219                                         isGamePad=1;
00220                                         break;
00221                                 }
00222                         }
00223                 }
00224 
00225                 if(0!=isJoystick)
00226                 {
00227                         int nAxis=0;
00228                         int nHat=0;
00229 
00230                         int j;
00231                         for(j=0; j<nElem; j++)
00232                         {
00233                                 IOHIDElementRef elem=(IOHIDElementRef)CFArrayGetValueAtIndex(elemAry,j);
00234                                 IOHIDElementType elemType=IOHIDElementGetType(elem);
00235                                 unsigned int usage=IOHIDElementGetUsage(elem);
00236                                 unsigned int usagePage=IOHIDElementGetUsagePage(elem);
00237                                 // The following two returned 0 and 255
00238                                 // IOHIDElementGetPhysicalMin(elem);
00239                                 // IOHIDElementGetPhysicalMax(elem);
00240                                 int min=IOHIDElementGetLogicalMin(elem);
00241                                 int max=IOHIDElementGetLogicalMax(elem);
00242                                 int scaledMin=min;
00243                                 int scaledMax=max;
00244 
00245                                 if(elemType==kIOHIDElementTypeInput_Misc ||
00246                                    elemType==kIOHIDElementTypeInput_Button ||
00247                                    elemType==kIOHIDElementTypeInput_Axis ||
00248                                    elemType==kIOHIDElementTypeInput_ScanCodes)
00249                                 {
00250                                         switch(usagePage)
00251                                         {
00252                                         case kHIDPage_GenericDesktop:
00253                                                 switch(usage)
00254                                                 {
00255                                                 case kHIDUsage_GD_Mouse:
00256                                                         break;
00257                                                 case kHIDUsage_GD_Keyboard:
00258                                                         break;
00259                                                 case kHIDUsage_GD_Joystick:
00260                                                         break;
00261                                                 case kHIDUsage_GD_GamePad:
00262                                                         break;
00263                                                 case kHIDUsage_GD_X:
00264                                                         printf("    This element is for X-Axis (%d->%d) Scaled(%d->%d)\n",min,max,scaledMin,scaledMax);
00265                                                         AddAxis(nAxis++,elem,min,max,scaledMin,scaledMax);
00266                                                         break;
00267                                                 case kHIDUsage_GD_Y:
00268                                                         printf("    This element is for Y-Axis (%d->%d) Scaled(%d->%d)\n",min,max,scaledMin,scaledMax);
00269                                                         AddAxis(nAxis++,elem,min,max,scaledMin,scaledMax);
00270                                                         break;
00271                                                 case kHIDUsage_GD_Z:
00272                                                         printf("    This element is for Z-Axis (%d->%d) Scaled(%d->%d)\n",min,max,scaledMin,scaledMax);
00273                                                         AddAxis(nAxis++,elem,min,max,scaledMin,scaledMax);
00274                                                         break;
00275                                                 case kHIDUsage_GD_Rx:
00276                                                         printf("    This element is for Rx-Axis (%d->%d) Scaled(%d->%d)\n",min,max,scaledMin,scaledMax);
00277                                                         AddAxis(nAxis++,elem,min,max,scaledMin,scaledMax);
00278                                                         break;
00279                                                 case kHIDUsage_GD_Ry:
00280                                                         printf("    This element is for Ry-Axis (%d->%d) Scaled(%d->%d)\n",min,max,scaledMin,scaledMax);
00281                                                         AddAxis(nAxis++,elem,min,max,scaledMin,scaledMax);
00282                                                         break;
00283                                                 case kHIDUsage_GD_Rz:
00284                                                         printf("    This element is for Rz-Axis (%d->%d) Scaled(%d->%d)\n",min,max,scaledMin,scaledMax);
00285                                                         AddAxis(nAxis++,elem,min,max,scaledMin,scaledMax);
00286                                                         break;
00287                                                 case kHIDUsage_GD_Slider:
00288                                                         printf("    This element is for Slider (%d->%d) Scaled(%d->%d)\n",min,max,scaledMin,scaledMax);
00289                                                         AddAxis(nAxis++,elem,min,max,scaledMin,scaledMax);
00290                                                         break;
00291                                                 case kHIDUsage_GD_Wheel:
00292                                                         printf("    This element is for Wheel (%d->%d) Scaled(%d->%d)\n",min,max,scaledMin,scaledMax);
00293                                                         break;
00294                                                 case kHIDUsage_GD_Hatswitch:
00295                                                         printf("    This element is for Hatswitch (%d->%d) Scaled(%d->%d)\n",min,max,scaledMin,scaledMax);
00296                                                         if(nHat<YsJoyReaderMaxNumHatSwitch)
00297                                                         {
00298                                                                 hatSwitch[nHat].exist=1;
00299                                                                 hatSwitch[nHat].elem=elem;
00300                                                                 CFRetain(elem);
00301                                                                 nHat++;
00302                                                         }
00303                                                         break;
00304                                                 }
00305                                                 break;
00306                                         case kHIDPage_Button:
00307                                                 printf("    This element is for Button %d\n",usage-1);
00308                                                 usage--;
00309                                                 if(0<=usage && usage<YsJoyReaderMaxNumButton)
00310                                                 {
00311                                                         button[usage].exist=1;
00312                                                         button[usage].elem=elem;
00313                                                         CFRetain(elem);
00314                                                 }
00315                                                 break;
00316                                         }
00317                                 }
00318                         }
00319                         CFRelease(elemAry);
00320                         this->hidDev=hidDev;
00321                         return 1;
00322 
00323                 }
00324                 CFRelease(elemAry);
00325         }
00326 
00327         return 0;
00328 }
00329 
00330 void YsJoyReader::Read(void)
00331 {
00332         int i;
00333         IOHIDValueRef valueRef;
00334         for(i=0; i<YsJoyReaderMaxNumAxis; i++)
00335         {
00336                 if(axis[i].exist!=0)
00337                 {
00338                         IOHIDDeviceGetValue(hidDev,axis[i].elem,&valueRef);
00339                         axis[i].value=IOHIDValueGetIntegerValue(valueRef);
00340                 }
00341         }
00342         for(i=0; i<YsJoyReaderMaxNumButton; i++)
00343         {
00344                 if(button[i].exist!=0)
00345                 {
00346                         IOHIDDeviceGetValue(hidDev,button[i].elem,&valueRef);
00347                         button[i].value=IOHIDValueGetIntegerValue(valueRef);
00348                 }
00349         }
00350         for(i=0; i<YsJoyReaderMaxNumHatSwitch; i++)
00351         {
00352                 if(hatSwitch[i].exist!=0)
00353                 {
00354                         IOHIDDeviceGetValue(hidDev,hatSwitch[i].elem,&valueRef);
00355 
00356                         double scaled=IOHIDValueGetScaledValue(valueRef,kIOHIDValueScaleTypePhysical);
00357                         if(scaled<-0.001 || 359.999<scaled)
00358                         {
00359                                 hatSwitch[i].value=0;
00360                         }
00361                         else
00362                         {
00363                                 hatSwitch[i].value=1+(int)((scaled+22.5)/45.0);
00364                         }
00365                 }
00366         }
00367 }
00368 
00369 void YsJoyReader::ReleaseInterface(void)
00370 {
00371         if(hidDev!=NULL)
00372         {
00373                 // Honestly, I don't know what to do.
00374                 //
00375                 // Should I do
00376                 //   CFRelease(hidDev);
00377                 // ?
00378                 //
00379                 // This hidDev was copied from a copy of IOHIDManager's device list.
00380                 // Who owns it?  Why did I have to make a copy?
00381                 // 
00382                 // The Creare Rule implies that I have the ownership.
00383                 // http://developer.apple.com/mac/library/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html#//apple_ref/doc/uid/20001148-SW1
00384                 //
00385                 // Then, I suppose I should release it.  Am I right?
00386                 CFRelease(hidDev);
00387                 hidDev=NULL;
00388         }
00389 }
00390 
00391 void YsJoyReader::AddAxis(int axisId,IOHIDElementRef elem,int min,int max,int scaledMin,int scaledMax)
00392 {
00393         if(0<=axisId && axisId<YsJoyReaderMaxNumAxis)
00394         {
00395                 axis[axisId].exist=1;
00396                 axis[axisId].elem=elem;
00397                 axis[axisId].min=min;
00398                 axis[axisId].max=max;
00399                 axis[axisId].scaledMin=scaledMin;
00400                 axis[axisId].scaledMax=scaledMax;
00401 
00402                 axis[axisId].calibCenter=(min+max)/2;
00403                 axis[axisId].calibMin=min;
00404                 axis[axisId].calibMax=max;
00405 
00406                 CFRetain(elem);
00407         }
00408 }
00409 
00410 void CFSetCopyCallBack(const void *value,void *context)
00411 {
00412         CFArrayAppendValue((CFMutableArrayRef)context,value);
00413 }
00414 
00415 int YsJoyReader::SetUpJoystick(int &nJoystick,YsJoyReader joystick[],int maxNumJoystick)
00416 {
00417         nJoystick=0;
00418 
00419         if(NULL==hidManager)
00420         {
00421                 hidManager=IOHIDManagerCreate(kCFAllocatorDefault,kIOHIDOptionsTypeNone);
00422         }
00423 
00424         if(NULL!=hidManager)
00425         {
00426                 IOHIDManagerSetDeviceMatching(hidManager,NULL);  // Just enumrate all devices
00427                 IOHIDManagerOpen(hidManager,kIOHIDOptionsTypeNone);
00428 
00429                 CFSetRef copyOfDevices=IOHIDManagerCopyDevices(hidManager);
00430                 if(NULL!=devArray)
00431                 {
00432                         CFRelease(devArray);
00433                         devArray=NULL;
00434                 }
00435                 devArray=CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks);
00436                 CFSetApplyFunction(copyOfDevices,CFSetCopyCallBack,(void *)devArray);
00437 
00438                 CFIndex nDev=CFArrayGetCount(devArray);
00439 
00440                 printf("%d devices found\n",(int)nDev);
00441 
00442                 CFRelease(copyOfDevices);
00443 
00444 
00445 
00446                 int i;
00447                 for(i=0; i<nDev && nJoystick<maxNumJoystick; i++)
00448                 {
00449                         IOHIDDeviceRef hidDev=(IOHIDDeviceRef)CFArrayGetValueAtIndex(devArray,i);
00450                         if(joystick[nJoystick].SetUpInterface(nJoystick,hidDev)!=0)
00451                         {
00452                                 nJoystick++;
00453                                 // CFRelease(hidDev);  // Doesn't it destroy integrity of devArray?
00454                         }
00455                 }
00456         }
00457 
00458         return nJoystick;
00459 }
00460 
00461 int YsJoyReader::WriteCalibInfoFile(FILE *fp) const
00462 {
00463         int i;
00464         fprintf(fp,"BGNJOY %d\n",joyId);
00465         for(i=0; i<YsJoyReaderMaxNumAxis; i++)
00466         {
00467                 if(0!=axis[i].exist)
00468                 {
00469                         fprintf(fp,"AXSINF %d %d %d %d\n",i,axis[i].calibCenter,axis[i].calibMin,axis[i].calibMax);
00470                 }
00471         }
00472 #ifdef YSJOYREADER_USE_HAT_CALIBRATION
00473         for(i=0; i<YsJoyReaderMaxNumHatSwitch; i++)
00474         {
00475                 if(0!=hatSwitch[i].exist)
00476                 {
00477                         fprintf(fp,"HATINF %d %d %d %d %d %d\n",
00478                             i,
00479                             hatSwitch[i].valueNeutral,
00480                             hatSwitch[i].value0Deg,
00481                             hatSwitch[i].value90Deg,
00482                             hatSwitch[i].value180Deg,
00483                             hatSwitch[i].value270Deg);
00484                 }
00485         }
00486 #endif
00487         fprintf(fp,"ENDJOY\n");
00488         return 1;
00489 }
00490 
00491 int YsJoyReader::ReadCalibInfoFile(FILE *fp)
00492 {
00493         char str[256];
00494         while(fgets(str,255,fp)!=NULL)
00495         {
00496                 if(strncmp(str,"AXSINF",6)==0)
00497                 {
00498                         int axisId,cen,min,max;
00499                         sscanf(str,"%*s %d %d %d %d",&axisId,&cen,&min,&max);
00500                         if(0<=axisId && axisId<YsJoyReaderMaxNumAxis)
00501                         {
00502                                 axis[axisId].calibCenter=cen;
00503                                 axis[axisId].calibMin=min;
00504                                 axis[axisId].calibMax=max;
00505                         }
00506                 }
00507 #ifdef YSJOYREADER_USE_HAT_CALIBRATION
00508                 else if(strncmp(str,"HATINF",6)==0)
00509                 {
00510                         int hatId;
00511                         int valueNeutral=0,value0Deg=1,value90Deg=3,value180Deg=5,value270Deg=7;
00512                         sscanf(str,"%*s %d %d %d %d %d %d",&hatId,&valueNeutral,&value0Deg,&value90Deg,&value180Deg,&value270Deg);
00513                         if(0<=hatId && hatId<YsJoyReaderMaxNumHatSwitch)
00514                         {
00515                                 hatSwitch[hatId].valueNeutral=valueNeutral;
00516                                 hatSwitch[hatId].value0Deg=value0Deg;
00517                                 hatSwitch[hatId].value90Deg=value90Deg;
00518                                 hatSwitch[hatId].value180Deg=value180Deg;
00519                                 hatSwitch[hatId].value270Deg=value270Deg;
00520                         }
00521                 }
00522 #endif
00523                 else if(strncmp(str,"ENDJOY",6)==0)
00524                 {
00525                         return 1;
00526                 }
00527         }
00528         return 0;
00529 }
00530 
00531 int YsJoyReaderSetUpJoystick(int &nJoystick,YsJoyReader joystick[],int maxNumJoystick)
00532 {
00533         return YsJoyReader::SetUpJoystick(nJoystick,joystick,maxNumJoystick);
00534 }
00535 
00536 
00537 extern "C" FILE *YsJoyReaderOpenJoystickCalibrationFileC(const char mode[]);
00538 
00539 FILE *YsJoyReaderOpenJoystickCalibrationFile(const char mode[])
00540 {
00541   return YsJoyReaderOpenJoystickCalibrationFileC(mode);
00542 }
00543 
00544 int YsJoyReaderSaveJoystickCalibrationInfo(int nJoystick,YsJoyReader joystick[])
00545 {
00546         FILE *fp;
00547         fp=YsJoyReaderOpenJoystickCalibrationFile("w");
00548 
00549         if(fp!=NULL)
00550         {
00551                 int i;
00552                 for(i=0; i<nJoystick; i++)
00553                 {
00554                         joystick[i].WriteCalibInfoFile(fp);
00555                 }
00556 
00557                 fclose(fp);
00558                 return 1;
00559         }
00560         return 0;
00561 }
00562 
00563 int YsJoyReaderLoadJoystickCalibrationInfo(int nJoystick,YsJoyReader joystick[])
00564 {
00565         FILE *fp;
00566         fp=YsJoyReaderOpenJoystickCalibrationFile("r");
00567 
00568         if(fp!=NULL)
00569         {
00570                 char str[256];
00571                 while(fgets(str,255,fp)!=NULL)
00572                 {
00573                         if(strncmp(str,"BGNJOY",6)==0)
00574                         {
00575                                 int joyId;
00576                                 sscanf(str,"%*s %d",&joyId);
00577                                 if(0<=joyId && joyId<nJoystick)
00578                                 {
00579                                         joystick[joyId].ReadCalibInfoFile(fp);
00580                                 }
00581                         }
00582                 }
00583                 fclose(fp);
00584                 return 1;
00585         }
00586         return 0;
00587 }


hrpsys
Author(s): AIST, Fumio Kanehiro
autogenerated on Wed May 15 2019 05:02:19