IOCTL 컴퓨터 기본 2008. 12. 14. 01:59
 

IOCTL-based Win32 joystick interface

Introduction

This interface allows PPJoy to represent a virtual joystick interface. A Win32 application provides joystick input to PPJoy via IOCTL calls. PPJoy will feed this input into DirectInput as a joystick; Win32 applications will think the input comes from a real joystick.

Below we present the steps required to open the virtual joystick control device, send input to it and finally close the control device. 

이 방법은 PPJoy가 사용하는 가상 조이스틱 인터페이스의 예를 보여준다.
Win32 어플릿이 PPJoy via IOCTL 호출에 의한 조이스틱 입력을 제공한다.
PPJoy는 조이스틱처럼 DirectInput으로 궤환(?)하여 이것을 입력한다.
;Win32 어플릿은 진짜 조이스틱 처럼 입력된다 생각할 것이다.

Opening a PPJoy virtual joystick

PPJoy creates a control device for each virtual joystick defined. This device is named \\.\PPJoyIOCTL1 for the first virtual joystick through to \\.\PPJoyIOCTL16 for the last one. Before you can send IOCTL commands to the joystick device you need a handle to it:

HANDLE h;
h= CreateFile("\\\\.\\PPJoyIOCTL1",GENERIC_WRITE,FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);

PPJoy는 조이스틱이 정의된 컨트롤 장치를 생성한다.
이것의 이름은 처음엔  \\.\PPJoyIOCTL1 부터 \\.\PPJoyIOCTL16 까지 될 것이다.
사용자가 IOCTL 명령을 조이스틱 장치에 보내기 전에 이 핸들이 필요하다.

Sending data to virtual joystick

Joystick data is placed in a special structure and then sent to PPJoy using the DeviceIoControl() function. The structure consists is defined as follows:

조이스틱 데이터는 특수한 구조체에 위치하고 난 다음 DeviceIoControl() 함수를 통해 PPJoy에 보낸다. 구조체엔 아래와 같은 것이 정의되어 있다.
#pragma pack(push,1)		/* All fields in structure must be byte aligned. */
typedef struct
{
 unsigned long  Signature;             /* Signature to identify packet to PPJoy IOCTL */
 char           NumAnalog;             /* Num of analog values we pass */
 long           Analog[NUM_ANALOG];    /* Analog input values */
 char           NumDigital;            /* Number of digital values we pass */
 char           Digital[NUM_DIGITAL];  /* Digital input values */
} JOYSTICK_STATE;
#pragma pack(pop)

The Signature field should be set to the constant JOYSTICK_STATE_V1 (defined in ppjioctl.h). NumAnalog and NumDigital should be set to the size of axis and button arrays respectively. PPJoy currently supports up to 63 analog and 128 digital values. Extra values in the arrays will be ignored. By default the first 8 analog values will be reported as axes and the first 16 digital values as buttons. Undefined analog values will be centred; undefined digital values will be off/not pressed.

Signature 영역엔 JOYSTICK_STATE_V1 (ppjioctl.h에서 정의된) 의 상수가 위치해야 한다.
NumAnalog 와 NumDigital에는 축의 크기와 각 버튼 배열이 위치해야 한다.
PPJoy는 63개의 아날로그와 128개의 디지탈 값을 지원한다.
배열에 있는 별도의 값은 무시된다.
초기 설정으로는 8개의 아날로그 값이 축으로, 16개의 디지탈 값이 버튼으로 되어있다.
정의되지 않은 아날로그 값은 중립 상태이다.;
정의되지 않은 디지탈 값은 꺼지거나/안 눌러진 것으로 된다.

NOTE: The fields in the structure must be byte aligned with no padding between the fields.

NOTE: 구조체의 영역들은 각 영역사이에서 빈 공간 없이 바이트로 정렬된다.

PPJOY_AXIS_MIN and PPJOY_AXIS_MAX represents the minimum and maximum values for an analog value. For digital values 1 means pressed and 0 is not pressed.

PPJOY_AXIS_MIN 와 PPJOY_AXIS_MAX 는 아날로그 값에서의 최소값과 최대값을 나타낸다.
디지탈 값에서 1은 "눌러짐"을 0은 "안 눌러짐"을 의미한다.


The sequence of axes are as follows: /*축의 시퀀스는 아래의 순서와 같다*/

  • X Position
  • Y Position
  • Z Position
  • Z Rotation
  • Slider
  • X Rotation
  • Y Rotation
  • Dial

PPJoy does not current support changing the number of axes or buttons reported; however extra axes or button can be mapped to "nothing".

PPJoy는 축의 숫자를 바꾸거나 버튼 알림을 통상 지원하지 않는다.;
그러나 별도의 축이나 버튼을 "아무것도 아님"으로 매핑이 가능하다.


A memory dump of the structure with two analog and four digital values looks like this:

구조체의 메모리 덤프를 보면 두개의 아날로그와 네개의 디지탈값이 보여진다.
 43 41 54 53       Header
 02                Two analog values to follow
 xx xx xx xx       Analog value 1 (defaults to X Axis)
 xx xx xx xx       Analog value 2 (defaults to Y Axis)
 04                Four digital values to follow
 xx                Digital value 1 (defaults to Button 1)
 xx                Digital value 2 (defaults to Button 2)
 xx                Digital value 3 (defaults to Button 3)
 xx                Digital value 4 (defaults to Button 4)
After setting the axis and button values in the structure it is passed to PPJoy using DeviceIoControl() with an IOCTL code of IOCTL_PPORTJOY_SET_STATE (defined in ppjioctl.h). This code snippet illustrates:
구조체에서 축과 버튼값을 설정하면 DeviceIoControl() 함수를 통해 PPJoy가 사용할 수 있게 IOCTL_PPORTJOY_SET_STATE (defined in ppjioctl.h)가 IOCTL 코드로 전해진다. 이 코드의 부분을 아래와 같이 나타냈다:
 JOYSTICK_STATE   JoyState;
 DWORD            RetSize;
 DWORD            rc;

 /* Initialise JoyState structure here... */

 if (!DeviceIoControl(h,IOCTL_PPORTJOY_SET_STATE,&JoyState,sizeof(JoyState),NULL,0,&RetSize,NULL))
 {
  rc= GetLastError();
  /* ... */
 }
It is important to check the return code for the DeviceIOControl() funcion. If the control device is still open when the underlying joystick device is deleted the PPortJoy.sys driver cannot unload. In this case GetLastError() will return 2. When you get this error code close the handle to the control device and retry opening the control device.
DeviceIOControl() 함수 동안에 리턴되는 코드를 체크하는 것이 중요하다.
만일 제어 장치가 잠재되어 있는 동안에 여전히 오픈되어 있다면 조이스틱 장치는 PPortJoy.sys 드라이버를
삭제당해 언로드 할 수 없다.
이 경우 GetLastError() 함수는 2를 리턴한다.
이 에러코드가 나오게 되면 제어 장치의 핸들을 닫고, 제어장치의 오프닝을 시도할 것이다.


Closing the virtual joystick

When the Win32 application is no longer using the control device, the control device handle should be closed with the CloseHandle() function. Also see the note above about closing the control device.

Sample application

This is a very simple sample application to demonstrate a Win32 application providing joystick input. It also contains the ppjioctl.h file needed to build other user mode joystick drivers.

Get IOCTLSample sample application (Microsoft Visual C++ 6.0).

1