// Handle incoming data from USB void FfbOnUsbData(uint8_t* data, uint16_t len) { uint8_t effectId = data[1]; // effectBlockIndex is always the second byte. switch (data[0]) // reportID { case 1: FfbHandle_SetEffect((USB_FFBReport_SetEffect_Output_Data_t*)data); break; case 2: SetEnvelope((USB_FFBReport_SetEnvelope_Output_Data_t*)data, &gEffectStates[effectId]); break; case 3: SetCondition((USB_FFBReport_SetCondition_Output_Data_t*)data, &gEffectStates[effectId]); break; case 4: SetPeriodic((USB_FFBReport_SetPeriodic_Output_Data_t*)data, &gEffectStates[effectId]); break; case 5: SetConstantForce((USB_FFBReport_SetConstantForce_Output_Data_t*)data, &gEffectStates[effectId]); break; case 6: SetRampForce((USB_FFBReport_SetRampForce_Output_Data_t*)data, &gEffectStates[effectId]); break; case 7: FfbHandle_SetCustomForceData((USB_FFBReport_SetCustomForceData_Output_Data_t*)data); break; case 8: FfbHandle_SetDownloadForceSample((USB_FFBReport_SetDownloadForceSample_Output_Data_t*)data); break; case 9: break; case 10: FfbHandle_EffectOperation((USB_FFBReport_EffectOperation_Output_Data_t*)data); break; case 11: FfbHandle_BlockFree((USB_FFBReport_BlockFree_Output_Data_t*)data); break; case 12: FfbHandle_DeviceControl((USB_FFBReport_DeviceControl_Output_Data_t*)data); break; case 13: FfbHandle_DeviceGain((USB_FFBReport_DeviceGain_Output_Data_t*)data); break; case 14: FfbHandle_SetCustomForce((USB_FFBReport_SetCustomForce_Output_Data_t*)data); break; default: break; }; }
static int token_out(PADState *ps, uint8_t *data, int len) { LinuxPADState *s = (LinuxPADState*)ps; uint8_t idx = 1 - s->padState.port; if(idx>1) return 0; memcpy(&ffdata,data, sizeof(ffdata)); //if(idx!=0)return 0; Dbg("FFB 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x0%4X\n", ffdata.reportid, ffdata.index, ffdata.data1, ffdata.data2, *(int*)((char*)&ffdata + 4) ); switch(ffdata.reportid) { case 0xF8: //TODO needed? if(ffdata.index == 5) sendCrap = true; //TODO guess-work //if(ffdata.index == 3) // SetAutoCenter(s, 100); break; case 9: { //not handled } break; case 0x13: //some games issue this command on pause //if(ffdata.reportid == 19 && ffdata.data2 == 0)break; if(ffdata.index == 0x8) SetConstantForce(s, 127); //data1 looks like previous force sent with reportid 0x11 //TODO unset spring else if(ffdata.index == 3) SetSpringForce(s, 127); //Dbg("FFB 0x%X, 0x%X, 0x%X\n", ffdata.reportid, ffdata.index, ffdata.data1); break; case 0x11://constant force { //handle calibration commands //if(!calibrating) { SetConstantForce(s, ffdata.data1); } } break; case 0x21: if(ffdata.index == 0xB) { //if(!calibrating) { //TODO guess-work SetAutoCenter(s, 100); //SetSpringForce(s, ffdata.data1); //spring is broken? } break; } //drop through case 0xFE://autocenter? case 0xFF://autocenter? case 0xF4://autocenter? //{ // SetAutoCenter(s, 0); //} //break; case 0xF5://autocenter? { SetAutoCenter(s, 0); //just release force SetConstantForce(s, 127); } break; case 0xF1: //DF/GTF and GT3 //if(!calibrating) { SetConstantForce(s, ffdata.pad1); } break; case 0xF3://initialize { //SetAutoCenter(s, 0xFFFFUL); } break; } return len; }