2014-03-28 02:50:40 +01:00
using System ;
using System.Collections.Generic ;
using System.ComponentModel ;
using System.Windows.Forms ;
using DS4Library ;
using System.Runtime.InteropServices ;
using Microsoft.Win32.SafeHandles ;
namespace DS4Control
{
public partial class X360Device : ScpDevice
{
2014-04-30 05:54:41 +02:00
private const String DS3_BUS_CLASS_GUID = "{F679F562-3164-42CE-A4DB-E7DDBE723909}" ;
private const int CONTROLLER_OFFSET = 1 + 10 ; // Device 0 is the virtual USB hub itself, and we leave devices 1-10 available for other software (like the Scarlet.Crush DualShock driver itself)
2014-03-28 02:50:40 +01:00
2014-04-30 05:54:41 +02:00
private int firstController = 1 + 10 ;
// Device 0 is the virtual USB hub itself, and we can leave more available for other software (like the Scarlet.Crush DualShock driver)
public int FirstController
{
get { return firstController ; }
set { firstController = value > 0 ? value : 1 ; }
}
protected Int32 Scale ( Int32 Value , Boolean Flip )
2014-03-28 02:50:40 +01:00
{
Value - = 0x80 ;
if ( Value = = - 128 ) Value = - 127 ;
if ( Flip ) Value * = - 1 ;
return ( Int32 ) ( ( float ) Value * 258.00787401574803149606299212599f ) ;
}
public X360Device ( )
: base ( DS3_BUS_CLASS_GUID )
{
InitializeComponent ( ) ;
}
public X360Device ( IContainer container )
: base ( DS3_BUS_CLASS_GUID )
{
container . Add ( this ) ;
InitializeComponent ( ) ;
}
2014-04-30 05:54:41 +02:00
/ * public override Boolean Open ( int Instance = 0 )
2014-03-28 02:50:40 +01:00
{
if ( base . Open ( Instance ) )
{
}
return true ;
2014-04-30 05:54:41 +02:00
} * /
2014-03-28 02:50:40 +01:00
public override Boolean Open ( String DevicePath )
{
m_Path = DevicePath ;
m_WinUsbHandle = ( IntPtr ) INVALID_HANDLE_VALUE ;
if ( GetDeviceHandle ( m_Path ) )
{
m_IsActive = true ;
}
return true ;
}
public override Boolean Start ( )
{
if ( IsActive )
{
}
return true ;
}
public override Boolean Stop ( )
{
if ( IsActive )
{
//Unplug(0);
}
return base . Stop ( ) ;
}
public override Boolean Close ( )
{
if ( IsActive )
{
Unplug ( 0 ) ;
}
return base . Close ( ) ;
}
2014-04-30 05:54:41 +02:00
public void Parse ( DS4State state , Byte [ ] Output , int device )
2014-03-28 02:50:40 +01:00
{
Output [ 0 ] = 0x1C ;
2014-04-30 05:54:41 +02:00
Output [ 4 ] = ( Byte ) ( device + firstController ) ;
2014-03-28 02:50:40 +01:00
Output [ 9 ] = 0x14 ;
for ( int i = 10 ; i < Output . Length ; i + + )
{
Output [ i ] = 0 ;
}
if ( state . Share ) Output [ 10 ] | = ( Byte ) ( 1 < < 5 ) ; // Back
if ( state . L3 ) Output [ 10 ] | = ( Byte ) ( 1 < < 6 ) ; // Left Thumb
if ( state . R3 ) Output [ 10 ] | = ( Byte ) ( 1 < < 7 ) ; // Right Thumb
if ( state . Options ) Output [ 10 ] | = ( Byte ) ( 1 < < 4 ) ; // Start
if ( state . DpadUp ) Output [ 10 ] | = ( Byte ) ( 1 < < 0 ) ; // Up
if ( state . DpadRight ) Output [ 10 ] | = ( Byte ) ( 1 < < 3 ) ; // Down
if ( state . DpadDown ) Output [ 10 ] | = ( Byte ) ( 1 < < 1 ) ; // Right
if ( state . DpadLeft ) Output [ 10 ] | = ( Byte ) ( 1 < < 2 ) ; // Left
if ( state . L1 ) Output [ 11 ] | = ( Byte ) ( 1 < < 0 ) ; // Left Shoulder
if ( state . R1 ) Output [ 11 ] | = ( Byte ) ( 1 < < 1 ) ; // Right Shoulder
if ( state . Triangle ) Output [ 11 ] | = ( Byte ) ( 1 < < 7 ) ; // Y
if ( state . Circle ) Output [ 11 ] | = ( Byte ) ( 1 < < 5 ) ; // B
if ( state . Cross ) Output [ 11 ] | = ( Byte ) ( 1 < < 4 ) ; // A
if ( state . Square ) Output [ 11 ] | = ( Byte ) ( 1 < < 6 ) ; // X
if ( state . PS ) Output [ 11 ] | = ( Byte ) ( 1 < < 2 ) ; // Guide
2014-05-21 23:42:25 +02:00
if ( state . L2 > Global . getLeftTriggerMiddle ( device ) )
Output [ 12 ] = state . L2 ; // Left Trigger
if ( state . R2 > Global . getRightTriggerMiddle ( device ) )
Output [ 13 ] = state . R2 ; // Right Trigger
2014-03-28 02:50:40 +01:00
Int32 ThumbLX = Scale ( state . LX , false ) ;
Int32 ThumbLY = - Scale ( state . LY , false ) ;
Int32 ThumbRX = Scale ( state . RX , false ) ;
Int32 ThumbRY = - Scale ( state . RY , false ) ;
2014-05-21 23:42:25 +02:00
if ( state . LX > 127 + Global . getLSDeadzone ( device ) | | state . LX < 127 - Global . getLSDeadzone ( device ) )
{
Output [ 14 ] = ( Byte ) ( ( ThumbLX > > 0 ) & 0xFF ) ; // LX
Output [ 15 ] = ( Byte ) ( ( ThumbLX > > 8 ) & 0xFF ) ;
}
if ( state . LY > 127 + Global . getLSDeadzone ( device ) | | state . LY < 127 - Global . getLSDeadzone ( device ) )
{
Output [ 16 ] = ( Byte ) ( ( ThumbLY > > 0 ) & 0xFF ) ; // LY
Output [ 17 ] = ( Byte ) ( ( ThumbLY > > 8 ) & 0xFF ) ;
}
2014-03-28 02:50:40 +01:00
2014-05-21 23:42:25 +02:00
if ( state . RX > 127 + Global . getRSDeadzone ( device ) | | state . RX < 127 - Global . getRSDeadzone ( device ) )
{
Output [ 18 ] = ( Byte ) ( ( ThumbRX > > 0 ) & 0xFF ) ; // RX
Output [ 19 ] = ( Byte ) ( ( ThumbRX > > 8 ) & 0xFF ) ;
}
if ( state . LY > 127 + Global . getLSDeadzone ( device ) | | state . RY < 127 - Global . getRSDeadzone ( device ) )
{
Output [ 20 ] = ( Byte ) ( ( ThumbRY > > 0 ) & 0xFF ) ; // RY
Output [ 21 ] = ( Byte ) ( ( ThumbRY > > 8 ) & 0xFF ) ;
}
2014-03-28 02:50:40 +01:00
}
2014-04-30 05:54:41 +02:00
public Boolean Plugin ( Int32 Serial )
2014-03-28 02:50:40 +01:00
{
if ( IsActive )
{
Int32 Transfered = 0 ;
Byte [ ] Buffer = new Byte [ 16 ] ;
Buffer [ 0 ] = 0x10 ;
Buffer [ 1 ] = 0x00 ;
Buffer [ 2 ] = 0x00 ;
Buffer [ 3 ] = 0x00 ;
2014-04-30 05:54:41 +02:00
Serial + = firstController ;
2014-03-28 02:50:40 +01:00
Buffer [ 4 ] = ( Byte ) ( ( Serial > > 0 ) & 0xFF ) ;
Buffer [ 5 ] = ( Byte ) ( ( Serial > > 8 ) & 0xFF ) ;
Buffer [ 6 ] = ( Byte ) ( ( Serial > > 16 ) & 0xFF ) ;
Buffer [ 7 ] = ( Byte ) ( ( Serial > > 24 ) & 0xFF ) ;
return DeviceIoControl ( m_FileHandle , 0x2A4000 , Buffer , Buffer . Length , null , 0 , ref Transfered , IntPtr . Zero ) ;
}
return false ;
}
2014-04-30 05:54:41 +02:00
public Boolean Unplug ( Int32 Serial )
2014-03-28 02:50:40 +01:00
{
if ( IsActive )
{
Int32 Transfered = 0 ;
Byte [ ] Buffer = new Byte [ 16 ] ;
Buffer [ 0 ] = 0x10 ;
Buffer [ 1 ] = 0x00 ;
Buffer [ 2 ] = 0x00 ;
Buffer [ 3 ] = 0x00 ;
2014-04-30 05:54:41 +02:00
Serial + = firstController ;
2014-03-28 02:50:40 +01:00
Buffer [ 4 ] = ( Byte ) ( ( Serial > > 0 ) & 0xFF ) ;
Buffer [ 5 ] = ( Byte ) ( ( Serial > > 8 ) & 0xFF ) ;
Buffer [ 6 ] = ( Byte ) ( ( Serial > > 16 ) & 0xFF ) ;
Buffer [ 7 ] = ( Byte ) ( ( Serial > > 24 ) & 0xFF ) ;
return DeviceIoControl ( m_FileHandle , 0x2A4004 , Buffer , Buffer . Length , null , 0 , ref Transfered , IntPtr . Zero ) ;
}
return false ;
}
2014-04-30 05:54:41 +02:00
public Boolean UnplugAll ( ) //not yet implemented, not sure if will
{
if ( IsActive )
{
Int32 Transfered = 0 ;
Byte [ ] Buffer = new Byte [ 16 ] ;
Buffer [ 0 ] = 0x10 ;
Buffer [ 1 ] = 0x00 ;
Buffer [ 2 ] = 0x00 ;
Buffer [ 3 ] = 0x00 ;
return DeviceIoControl ( m_FileHandle , 0x2A4004 , Buffer , Buffer . Length , null , 0 , ref Transfered , IntPtr . Zero ) ;
}
return false ;
}
2014-03-28 02:50:40 +01:00
2014-04-30 05:54:41 +02:00
public Boolean Report ( Byte [ ] Input , Byte [ ] Output )
2014-03-28 02:50:40 +01:00
{
if ( IsActive )
{
Int32 Transfered = 0 ;
return DeviceIoControl ( m_FileHandle , 0x2A400C , Input , Input . Length , Output , Output . Length , ref Transfered , IntPtr . Zero ) & & Transfered > 0 ;
}
return false ;
}
}
}