PsychError PSYCHHIDReceiveReports(void) { long error=0; int deviceIndex; mxArray **mxErrPtr; const mxArray *mxOptions,*mx; PsychPushHelp(useString,synopsisString,seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumOutputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(2)); PsychCopyInIntegerArg(1,TRUE,&deviceIndex); if(deviceIndex < 0 || deviceIndex >= MAXDEVICEINDEXS) PrintfExit("Sorry. Can't cope with deviceNumber %d (more than %d). Please tell [email protected]",deviceIndex, (int) MAXDEVICEINDEXS-1); /* "\"options.print\" =1 (default 0) enables diagnostic printing of a summary of each report when our callback routine receives it. " "\"options.printCrashers\" =1 (default 0) enables diagnostic printing of the creation of the callback source and its addition to the CFRunLoop. " "\"options.maxReports\" (default 10000) allocate space for at least this many reports, shared among all devices. " "\"options.maxReportSize\" (default 65) allocate this many bytes per report. " */ //optionsPrintReportSummary=0; // options.print //optionsPrintCrashers=0; // options.printCrashers //optionsMaxReports=10000; // options.maxReports //optionsMaxReportSize=65; // options.maxReportSize //optionsSecs=0.010; // options.secs mxOptions=PsychGetInArgMxPtr(2); if(mxOptions!=NULL){ mx=mxGetField(mxOptions,0,"print"); if(mx!=NULL)optionsPrintReportSummary=(psych_bool)mxGetScalar(mx); mx=mxGetField(mxOptions,0,"printCrashers"); if(mx!=NULL)optionsPrintCrashers=(psych_bool)mxGetScalar(mx); mx=mxGetField(mxOptions,0,"secs"); if(mx!=NULL)optionsSecs=mxGetScalar(mx); mx=mxGetField(mxOptions,0,"consistencyChecks"); if(mx!=NULL)optionsConsistencyChecks=(psych_bool)mxGetScalar(mx); // Changing maxReports or maxReportSize triggers a reallocation of // buffer memory: mx=mxGetField(mxOptions,0,"maxReports"); if(mx!=NULL) { oneShotRealloc = TRUE; optionsMaxReports = (int) mxGetScalar(mx); } mx=mxGetField(mxOptions,0,"maxReportSize"); if(mx!=NULL) { oneShotRealloc = TRUE; optionsMaxReportSize = (int) mxGetScalar(mx); } } // Sanity check: if(optionsMaxReports < 1) PsychErrorExitMsg(PsychError_user, "PsychHID ReceiveReports: Sorry, requested maxReports count must be at least 1!"); if(optionsMaxReportSize < 1) PsychErrorExitMsg(PsychError_user, "PsychHID ReceiveReports: Sorry, requested maxReportSize must be at least 1 byte!"); if(optionsMaxReportSize > MAXREPORTSIZE) { printf("PsychHID ReceiveReports: Sorry, requested maximum report size %d bytes exceeds built-in maximum of %d bytes.\n", optionsMaxReportSize, (int) MAXREPORTSIZE); PsychErrorExitMsg(PsychError_user, "Invalid option.maxReportSize provided!"); } // Start reception of reports: This will also allocate memory for the reports // on first invocation for this deviceIndex: error = ReceiveReports(deviceIndex); mxErrPtr=PsychGetOutArgMxPtr(1); if(mxErrPtr!=NULL){ const char *fieldNames[]={"n", "name", "description"}; char *name="",*description=""; mxArray *fieldValue; PsychHIDErrors(NULL, error,&name,&description); // Get error name and description, if available. *mxErrPtr=mxCreateStructMatrix(1,1,3,fieldNames); fieldValue=mxCreateString(name); if(fieldValue==NULL)PrintfExit("PSYCHHIDReceiveReports: Couldn't allocate \"err\"."); mxSetField(*mxErrPtr,0,"name",fieldValue); fieldValue=mxCreateString(description); if(fieldValue==NULL)PrintfExit("PSYCHHIDReceiveReports: Couldn't allocate \"err\"."); mxSetField(*mxErrPtr,0,"description",fieldValue); fieldValue=mxCreateDoubleMatrix(1,1,mxREAL); if(fieldValue==NULL)PrintfExit("PSYCHHIDReceiveReports: Couldn't allocate \"err\"."); *mxGetPr(fieldValue)=(double)error; mxSetField(*mxErrPtr,0,"n",fieldValue); } return(PsychError_none); }
PsychError PSYCHHIDReceiveReports(void) { long error=0; int deviceIndex; mxArray **mxErrPtr; const mxArray *mxOptions,*mx; PsychPushHelp(useString,synopsisString,seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumOutputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(2)); PsychCopyInIntegerArg(1,TRUE,&deviceIndex); /* "\"options.print\" =1 (default 0) enables diagnostic printing of a summary of each report when our callback routine receives it. " "\"options.printCrashers\" =1 (default 0) enables diagnostic printing of the creation of the callback source and its addition to the CFRunLoop. " "\"options.maxReports\" (default 10000) allocate space for at least this many reports, shared among all devices. " "\"options.maxReportSize\" (default 64) allocate this many bytes per report. " */ //optionsPrintReportSummary=0; // options.print //optionsPrintCrashers=0; // options.printCrashers //optionsMaxReports=10000; // options.maxReports //optionsMaxReportSize=64; // options.maxReportSize //optionsSecs=0.010; // options.secs mxOptions=PsychGetInArgMxPtr(2); if(mxOptions!=NULL){ mx=mxGetField(mxOptions,0,"print"); if(mx!=NULL)optionsPrintReportSummary=(psych_bool)mxGetScalar(mx); mx=mxGetField(mxOptions,0,"printCrashers"); if(mx!=NULL)optionsPrintCrashers=(psych_bool)mxGetScalar(mx); mx=mxGetField(mxOptions,0,"maxReports"); if(mx!=NULL)optionsMaxReports=(int)mxGetScalar(mx); mx=mxGetField(mxOptions,0,"maxReportSize"); if(mx!=NULL)optionsMaxReportSize=(int)mxGetScalar(mx); mx=mxGetField(mxOptions,0,"secs"); if(mx!=NULL)optionsSecs=mxGetScalar(mx); mx=mxGetField(mxOptions,0,"consistencyChecks"); if(mx!=NULL)optionsConsistencyChecks=(psych_bool)mxGetScalar(mx); } if(optionsMaxReports>MAXREPORTS)printf("PsychHID ReceiveReports: Sorry, maxReports is fixed at %d.\n",(int)MAXREPORTS); if(optionsMaxReportSize>MAXREPORTSIZE)printf("PsychHID ReceiveReports: Sorry, maxReportSize is fixed at %d.\n",(int)MAXREPORTSIZE); error=ReceiveReports(deviceIndex); mxErrPtr=PsychGetOutArgMxPtr(1); if(mxErrPtr!=NULL){ const char *fieldNames[]={"n", "name", "description"}; char *name="",*description=""; mxArray *fieldValue; PsychHIDErrors(NULL, error,&name,&description); // Get error name and description, if available. *mxErrPtr=mxCreateStructMatrix(1,1,3,fieldNames); fieldValue=mxCreateString(name); if(fieldValue==NULL)PrintfExit("PSYCHHIDReceiveReports: Couldn't allocate \"err\"."); mxSetField(*mxErrPtr,0,"name",fieldValue); fieldValue=mxCreateString(description); if(fieldValue==NULL)PrintfExit("PSYCHHIDReceiveReports: Couldn't allocate \"err\"."); mxSetField(*mxErrPtr,0,"description",fieldValue); fieldValue=mxCreateDoubleMatrix(1,1,mxREAL); if(fieldValue==NULL)PrintfExit("PSYCHHIDReceiveReports: Couldn't allocate \"err\"."); *mxGetPr(fieldValue)=(double)error; mxSetField(*mxErrPtr,0,"n",fieldValue); } return(PsychError_none); }
PsychError PSYCHHIDGetReport(void) { long error=0; pRecDevice device; int deviceIndex; int reportType; // 1=input, 2=output, 3=feature unsigned char *reportBuffer; UInt32 reportBytes=0; int reportBufferSize=0; int reportID=0; long dims[]={1,1}; mxArray **outReport,**outErr; char *name="",*description="",string[256]; IOHIDDeviceInterface122** interface=NULL; boolean reportAvailable; double reportTime; PsychPushHelp(useString,synopsisString,seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumOutputArgs(2)); PsychErrorExit(PsychCapNumInputArgs(4)); PsychCopyInIntegerArg(1,TRUE,&deviceIndex); PsychCopyInIntegerArg(2,TRUE,&reportType); PsychCopyInIntegerArg(3,TRUE,&reportID); PsychCopyInIntegerArg(4,TRUE,&reportBufferSize); outReport=PsychGetOutArgMxPtr(1); outErr=PsychGetOutArgMxPtr(2); // outErr==NULL if optional argument is absent. dims[0]=1; dims[1]=reportBufferSize; *outReport=mxCreateNumericArray(2,(void *)dims,mxUINT8_CLASS,mxREAL); if(*outReport==NULL)PrintfExit("Couldn't allocate report array."); reportBuffer=(void *)mxGetData(*outReport); if(reportBuffer==NULL)PrintfExit("Couldn't allocate report buffer."); reportBytes=reportBufferSize; PsychHIDVerifyInit(); device=PsychHIDGetDeviceRecordPtrFromIndex(deviceIndex); if(!HIDIsValidDevice(device))PrintfExit("PsychHID:GetReport: Invalid device.\n"); interface=device->interface; if(interface==NULL)PrintfExit("PsychHID:GetReport: No interface for device.\n"); if(reportType==0){ printf("GetReport(reportType %d, reportID %d, reportBytes %d)\n",reportType,reportID,(int)reportBytes); }else{ // Apple defines constants for the reportType with values (0,1,2) that are one less that those specified by USB (1,2,3). if(0){ // HIDGetReport error=HIDGetReport(device,reportType-1,reportID,reportBuffer,&reportBytes); } if(0){ // getReport error=(*interface)->getReport(interface,reportType-1,reportID,reportBuffer,&reportBytes,-1,nil,nil,nil); } if(0){ // handleReport } if(1){ // using setInterruptReportHandlerCallback and CFRunLoopRunInMode error=ReceiveReports(deviceIndex); error=GiveMeReport(deviceIndex,&reportAvailable,reportBuffer,&reportBytes,&reportTime); }else{ // using getReport if(error==0)reportAvailable=1; PsychGetPrecisionTimerSeconds(&reportTime); } } if(outReport==NULL)PrintfExit("Output argument is required."); // I think MATLAB always provides this. if(error==0 && reportBytes>reportBufferSize){ error=2; name="Warning"; description=string; sprintf(description,"GetReport overflow. Expected %ld but received %ld bytes.",(long)reportBufferSize,(long)reportBytes); } if(error==0 && reportBytes<reportBufferSize){ // Reduce the declared size of the array to that of the received report. if(reportBytes>0)error=3; name="Warning"; description=string; sprintf(description,"GetReport expected %ld but received %ld bytes.",(long)reportBufferSize,(long)reportBytes); mxSetN(*outReport,reportBytes); } if(outErr!=NULL){ const char *fieldNames[]={"n", "name", "description", "reportLength", "reportTime"}; mxArray *fieldValue; PsychHIDErrors(error,&name,&description); // Get error name and description, if available. *outErr=mxCreateStructMatrix(1,1,5,fieldNames); fieldValue=mxCreateString(name); if(fieldValue==NULL)PrintfExit("Couldn't allocate \"err\"."); mxSetField(*outErr,0,"name",fieldValue); fieldValue=mxCreateString(description); if(fieldValue==NULL)PrintfExit("Couldn't allocate \"err\"."); mxSetField(*outErr,0,"description",fieldValue); fieldValue=mxCreateDoubleMatrix(1,1,mxREAL); if(fieldValue==NULL)PrintfExit("Couldn't allocate \"err\"."); *mxGetPr(fieldValue)=(double)error; mxSetField(*outErr,0,"n",fieldValue); fieldValue=mxCreateDoubleMatrix(1,1,mxREAL); if(fieldValue==NULL)PrintfExit("Couldn't allocate \"err\"."); if(reportAvailable)*mxGetPr(fieldValue)=(double)reportBytes; else *mxGetPr(fieldValue)=-1.0; mxSetField(*outErr,0,"reportLength",fieldValue); fieldValue=mxCreateDoubleMatrix(1,1,mxREAL); if(fieldValue==NULL)PrintfExit("Couldn't allocate \"err\"."); *mxGetPr(fieldValue)=reportTime; mxSetField(*outErr,0,"reportTime",fieldValue); } return(PsychError_none); }