以前
こちらでラフなコードを書きましたが、ちゃんとxfpsとパイプで通信できるように修正しました。
この関数で、xfpsのパイプのハンドルを取得します。
HANDLE xfpsInitialize()
{
HANDLE hPipe=INVALID_HANDLE_VALUE;
GUID hidGuid;
HDEVINFO hardwareDeviceInfo;
HidD_GetHidGuid(&hidGuid);
hardwareDeviceInfo=SetupDiGetClassDevs(&hidGuid, NULL, NULL, 0x12);
SP_DEVICE_INTERFACE_DATA sp_devinterfacedata;
sp_devinterfacedata.cbSize=sizeof(SP_DEVICE_INTERFACE_DATA);
for(DWORD MemberIndex=0; ; MemberIndex++){
int ret=SetupDiEnumDeviceInterfaces(hardwareDeviceInfo,
NULL,
&hidGuid,
MemberIndex,
&sp_devinterfacedata);
if(ret==0) break;
DWORD requiredLength, predictedLength;
SetupDiGetDeviceInterfaceDetail(hardwareDeviceInfo,
&sp_devinterfacedata,
NULL,
0,
&requiredLength,
NULL);
predictedLength=requiredLength;
PSP_DEVICE_INTERFACE_DETAIL_DATA psp_devinterfacedetail=
(PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(predictedLength);
psp_devinterfacedetail->cbSize=sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
SetupDiGetDeviceInterfaceDetail(hardwareDeviceInfo,
&sp_devinterfacedata,
psp_devinterfacedetail,
predictedLength,
&requiredLength,
NULL);
HANDLE hHIDDevice=CreateFile(psp_devinterfacedetail->DevicePath,
0x40000000, // GENERIC_WRITE
2,
NULL, // no SECURITY_ATTRIBUTES
3, // OPEN_EXISTING
0x40000000, // FILE_FLAG_OVERLAPPED
NULL);
if(hHIDDevice!=INVALID_HANDLE_VALUE){
HIDD_ATTRIBUTES HIDAttributes;
HIDAttributes.Size=sizeof(ULONG);
HidD_GetAttributes(hHIDDevice, &HIDAttributes);
PHIDP_PREPARSED_DATA HIDPreparsedData;
ret=HidD_GetPreparsedData(hHIDDevice, &HIDPreparsedData);
if(ret){
HIDP_CAPS HIDCaps;
HidP_GetCaps(HIDPreparsedData, &HIDCaps);
// ...
HidD_FreePreparsedData(HIDPreparsedData);
}
CloseHandle(hHIDDevice);
char pipeFileName[MAX_PATH];
if((HIDAttributes.VendorID==0x04b4)&&(HIDAttributes.ProductID==0x0811)){
wsprintf(pipeFileName, "%s\\PIPE1", psp_devinterfacedetail->DevicePath);
hPipe=CreateFile(pipeFileName,
0xc0000000, // GENERIC_WRITE|GENERIC_READ
3, // FILE_SHARE_READ|FILE_SHARE_WRITE
NULL,
3, // OPEN_EXISTING
0,
NULL);
}
}
free(psp_devinterfacedetail);
}
SetupDiDestroyDeviceInfoList(hardwareDeviceInfo);
return hPipe;
}
このパイプに書き込むデータですが、リバースエンジニアリングと
こちらの情報から、以下の50(0x32)バイトを書きこめばよいことがわかります。
#pragma pack(push, 1)
typedef struct
{
unsigned char Reserved0;
unsigned char ReportType;
unsigned char Reserved1;
unsigned char ButtonState1;
unsigned char ButtonState2;
unsigned char PSButtonState;
unsigned char Reserved2;
unsigned char LeftStickX;
unsigned char LeftStickY;
unsigned char RightStickX;
unsigned char RightStickY;
unsigned char Reserved3[4];
unsigned char PressureUp;
unsigned char PressureRight;
unsigned char PressureDown;
unsigned char PressureLeft;
unsigned char PressureL2;
unsigned char PressureR2;
unsigned char PressureL1;
unsigned char PressureR1;
unsigned char PressureTriangle;
unsigned char PressureCircule;
unsigned char PressureCross;
unsigned char PressureSquare;
unsigned char Reserved4[3];
unsigned char Charge;
unsigned char Power;
unsigned char Connection;
unsigned char Reserved5[9];
unsigned short AccelerometerX; // big endian
unsigned short Accelerometer; // big endian
unsigned short AccelerometerZ; // big endian
unsigned short GyrometerX; // big endian
}PS3ControllerData;
#pragma pack(pop)
Reserved5の9バイトは、xfpsが書き込んでる内容をそのまま使いましょう。
rawdata->Reserved5[0] =0x00;
rawdata->Reserved5[1] =0x00;
rawdata->Reserved5[2] =0x00;
rawdata->Reserved5[3] =0x00;
rawdata->Reserved5[4] =0x33;
rawdata->Reserved5[5] =0xfe;
rawdata->Reserved5[6] =0x77;
rawdata->Reserved5[7] =0x01;
rawdata->Reserved5[8] =0xc0;
ということで、自作アプリからPSボタンをプッシュ/リリースできることを確認しました。
さて、次はアナログインターフェースの作成ですね。
世の中のアナログ操作系は大抵はポテンショメータの抵抗値変化によって値を出しているので、AD変換して1チップマイコンに取り込むだけですぐできそうです。
さて、ケーブルを買いに行ってきます♪