/* PsychAllocOutStructArray() -If argument is optional we allocate the structure even if the argument is not present. If this bothers you, then check within the subfunction for the presense of a return argument before creating the struct array. We allocate space regardeless of whether the argument is present because this is consistant with other "PsychAllocOut*" functions which behave this way because in some situations subfunctions might derive returned results from values stored in an optional argument. -If position is -1 then don't attempt to return the created structure to the calling environment. Instead just allocate the structure and return it in pStruct. This is how to create a structure which is embeded within another structure using PsychSetStructArrayStructArray(). Note that we use -1 as the flag and not NULL because NULL is 0 and 0 is reserved for future use as a reference to the subfunction name, of if none then the function name. */ boolean PsychAllocOutStructArray( int position, PsychArgRequirementType isRequired, int numElements, int numFields, const char **fieldNames, PsychGenericScriptType **pStruct) { mxArray **mxArrayOut; int structArrayNumDims=2; int structArrayDims[2]; PsychError matchError; Boolean putOut; structArrayDims[0]=1; structArrayDims[1]=numElements; if(position !=kPsychNoArgReturn){ //Return the result to both the C caller and the scripting environment. PsychSetReceivedArgDescriptor(position, PsychArgOut); PsychSetSpecifiedArgDescriptor(position, PsychArgOut, PsychArgType_structArray, isRequired, 1,1,numElements,numElements,0,0); *pStruct = mxCreateStructArray(structArrayNumDims, structArrayDims, numFields, fieldNames); matchError=PsychMatchDescriptors(); putOut=PsychAcceptOutputArgumentDecider(isRequired, matchError); if(putOut){ mxArrayOut = PsychGetOutArgMxPtr(position); *mxArrayOut=*pStruct; } return(putOut); }else{ //Return the result only to the C caller. Ignore "required". *pStruct = mxCreateStructArray(structArrayNumDims, structArrayDims, numFields, fieldNames); return(TRUE); } }
/* PsychAllocOutCellArray() -If argument is optional we allocate the structure even if the argument is not present. If this behavior bothers you, then check within your code for the presense of a return argument before creating the struct array. We allocate space regardeless of whether the argument is present because this is consistant with other "PsychAllocOut*" functions which behave this way because in some situations subfunctions might derive returned results from values stored in an optional argument. -If position is -1 then don't attempt to return the created structure to the calling environment. Instead just allocate the structure and return it in pStruct. This is how to create a structure which is embeded within another structure using PsychSetStructArrayStructArray(). Note that we use -1 as the flag and not NULL because NULL is 0 and 0 is reserved for future use as a reference to the subfunction name, of if none then the function name. */ boolean PsychAllocOutCellVector( int position, PsychArgRequirementType isRequired, int numElements, PsychGenericScriptType **pCell) { mxArray **mxArrayOut; int cellArrayNumDims=2; int cellArrayDims[2]; PsychError matchError; Boolean putOut; cellArrayDims[0]=1; cellArrayDims[1]=numElements; if(position != kPsychNoArgReturn){ //Return the result to both the C caller and the scripting environment. PsychSetReceivedArgDescriptor(position, PsychArgOut); PsychSetSpecifiedArgDescriptor(position, PsychArgOut, PsychArgType_cellArray, isRequired, 1,1,numElements,numElements,0,0); *pCell = mxCreateCellArray(cellArrayNumDims, cellArrayDims); mxArrayOut = PsychGetOutArgMxPtr(position); matchError=PsychMatchDescriptors(); putOut=PsychAcceptOutputArgumentDecider(isRequired, matchError); if(putOut) *mxArrayOut=*pCell; return(putOut); }else{ //Return the result only to the C caller, not to the calling environment. Ignore "required". *pCell = mxCreateCellArray(cellArrayNumDims, cellArrayDims); return(TRUE); } }
PsychError PSYCHHIDReceiveReportsStop(void) { long error=0; int deviceIndex; mxArray **outErr; PsychPushHelp(useString,synopsisString,seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumOutputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(1)); PsychCopyInIntegerArg(1,TRUE,&deviceIndex); error=ReceiveReportsStop(deviceIndex); outErr=PsychGetOutArgMxPtr(1); if(outErr!=NULL){ char *name="",*description=""; const char *fieldNames[]={"n", "name", "description"}; mxArray *fieldValue; PsychHIDErrors(NULL, error,&name,&description); // Get error name and description, if available. *outErr=mxCreateStructMatrix(1,1,3,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); } return(PsychError_none); }
// GiveMeReports is called solely by PsychHIDGiveMeReports, but the code resides here // in PsychHIDReceiveReports because it uses the typedefs and static variables that // are defined solely in this file. The linked lists of reports are unknown outside of this file. PsychError GiveMeReports(int deviceIndex,int reportBytes) { mwSize dims[]={1,1}; mxArray **outReports; ReportStruct *r,*rTail; const char *fieldNames[]={"report", "device", "time"}; mxArray *fieldValue; unsigned char *reportBuffer; int i,n; unsigned int j; long error=0; double now; CountReports("GiveMeReports beginning."); outReports=PsychGetOutArgMxPtr(1); r=deviceReportsPtr[deviceIndex]; n=0; while(r!=NULL){ n++; rTail=r; r=r->next; } *outReports=mxCreateStructMatrix(1,n,3,fieldNames); r=deviceReportsPtr[deviceIndex]; PsychGetPrecisionTimerSeconds(&now); for(i=n-1;i>=0;i--){ // assert(r!=NULL); if(r->error)error=r->error; dims[0]=1; //printf("%2d: r->bytes %2d, reportBytes %4d, -%4.1f s\n",i,(int)r->bytes,(int)reportBytes, now-r->time); if(r->bytes> (unsigned int) reportBytes)r->bytes=reportBytes; dims[1]=r->bytes; fieldValue=mxCreateNumericArray(2,(void *)dims,mxUINT8_CLASS,mxREAL); reportBuffer=(void *)mxGetData(fieldValue); for(j=0;j<r->bytes;j++)reportBuffer[j]=r->report[j]; if(fieldValue==NULL)PrintfExit("Couldn't allocate report array."); mxSetField(*outReports,i,"report",fieldValue); fieldValue=mxCreateDoubleMatrix(1,1,mxREAL); *mxGetPr(fieldValue)=(double)r->deviceIndex; mxSetField(*outReports,i,"device",fieldValue); fieldValue=mxCreateDoubleMatrix(1,1,mxREAL); *mxGetPr(fieldValue)=r->time; mxSetField(*outReports,i,"time",fieldValue); r=r->next; } if(deviceReportsPtr[deviceIndex]!=NULL){ // transfer all these now-obsolete reports to the free list rTail->next=freeReportsPtr; freeReportsPtr=deviceReportsPtr[deviceIndex]; deviceReportsPtr[deviceIndex]=NULL; } CountReports("GiveMeReports end."); return error; }
boolean PsychAssignOutStructArray( int position, PsychArgRequirementType isRequired, PsychGenericScriptType *pStruct) { mxArray **mxArrayOut; PsychError matchError; Boolean putOut; PsychSetReceivedArgDescriptor(position, PsychArgOut); PsychSetSpecifiedArgDescriptor(position, PsychArgOut, PsychArgType_structArray, isRequired, 1,1,0,kPsychUnboundedArraySize,0,0); matchError=PsychMatchDescriptors(); putOut=PsychAcceptOutputArgumentDecider(isRequired, matchError); if(putOut){ mxArrayOut = PsychGetOutArgMxPtr(position); *mxArrayOut=pStruct; } return(putOut); }
PsychError PSYCHHIDGiveMeReports(void) { long error=0; int deviceIndex; int reportBytes=1024; mxArray **outErr; pRecDevice device; PsychPushHelp(useString,synopsisString,seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumOutputArgs(2)); PsychErrorExit(PsychCapNumInputArgs(2)); PsychCopyInIntegerArg(1,TRUE,&deviceIndex); PsychCopyInIntegerArg(2,false,&reportBytes); PsychHIDVerifyInit(); device=PsychHIDGetDeviceRecordPtrFromIndex(deviceIndex); if(!HIDIsValidDevice(device))PrintfExit("PsychHID:GiveMeReports: Invalid device.\n"); // reports error=GiveMeReports(deviceIndex,reportBytes); // PsychHIDReceiveReports.c // err outErr=PsychGetOutArgMxPtr(2); // outErr==NULL if optional argument is absent. if(outErr!=NULL){ const char *fieldNames[]={"n", "name", "description"}; mxArray *fieldValue; char *name="",*description=""; PsychHIDErrors(error,&name,&description); // Get error name and description, if available. *outErr=mxCreateStructMatrix(1,1,3,fieldNames); fieldValue=mxCreateString(name); mxSetField(*outErr,0,"name",fieldValue); fieldValue=mxCreateString(description); mxSetField(*outErr,0,"description",fieldValue); fieldValue=mxCreateDoubleMatrix(1,1,mxREAL); *mxGetPr(fieldValue)=(double)error; mxSetField(*outErr,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 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 PSYCHHIDSetReport(void) { long error; pRecDevice device; int deviceIndex; int reportType; // kIOHIDReportTypeInput=0, kIOHIDReportTypeOutput=1, or kIOHIDReportTypeFeature=2 int reportID; unsigned char *reportBuffer; int reportSize; const mxArray *report; mxArray **outErr; int i; PsychPushHelp(useString,synopsisString,seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumOutputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(4)); outErr=PsychGetOutArgMxPtr(1); assert(outErr!=NULL); PsychCopyInIntegerArg(1,TRUE,&deviceIndex); PsychCopyInIntegerArg(2,TRUE,&reportType); PsychCopyInIntegerArg(3,TRUE,&reportID); report=PsychGetInArgMxPtr(4); reportBuffer=(void *)mxGetPr(report); assert(reportBuffer!=NULL); switch(mxGetClassID(report)){ case mxCHAR_CLASS: case mxINT8_CLASS: case mxUINT8_CLASS: case mxINT16_CLASS: case mxUINT16_CLASS: case mxINT32_CLASS: case mxUINT32_CLASS: break; default: PrintfExit("\"report\" array must be char or integer (8-, 16-, or 32-bit)."); break; } reportSize=mxGetElementSize(report)*mxGetNumberOfElements(report); PsychHIDVerifyInit(); device=PsychHIDGetDeviceRecordPtrFromIndex(deviceIndex); if(reportSize>0 && reportID!=0) *reportBuffer=0xff&reportID; // copy low byte of reportID to first byte of report. // Apple defines constants for the reportType with values (0,1,2) that are one less that those specified by USB (1,2,3). assert(kIOHIDReportTypeInput==0 && kIOHIDReportTypeOutput==1 && kIOHIDReportTypeFeature==2); if(reportType==0){ printf("SetReport(reportType %d, reportID %d, report ",reportType,reportID); for(i=0;i<reportSize;i++)printf("%d ",(int)reportBuffer[i]); printf(")\n"); error=0; }else{ if(1){ IOHIDDeviceInterface122 **interface; interface=(IOHIDDeviceInterface122 **)(device->interface); if(interface)error=(*interface)->setReport(interface,reportType-1,reportID,reportBuffer,(UInt32)reportSize,50,NULL,NULL,NULL); else PrintfExit("PsychHID SetReport: Bad interface.\n"); }else error=HIDSetReport(device,reportType-1,reportID,reportBuffer,(UInt32)reportSize); } if(reportID==0x11){ PsychGetPrecisionTimerSeconds(&AInScanStart); } //if(error)printf("Warning: PsychHID: HIDSetReport error %ld (0x%lx).",error,error); if(0){ *outErr=mxCreateDoubleMatrix(1,1,mxREAL); if(*outErr==NULL)PrintfExit("Couldn't allocate \"err\"."); *mxGetPr(*outErr)=(double)error; }else{ const char *fieldNames[]={"n", "name", "description"}; char *name="",*description=""; mxArray *fieldValue; PsychHIDErrors(error,&name,&description); *outErr=mxCreateStructMatrix(1,1,3,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); } 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); }