제품 사용법

DM 드라이버 설치하기

하제소프트 DM 서버로부터 전달받은 파일은 압축파일형태로 존재한다. 여기서는 이 파일의 이름을 “dmiiusb_unsigned.zip” 로 정한다. 압축파일의 압축을 해제하면 다음과 같은 디렉토리를 볼 수 있다

압축파일의 압축을 해제한 모습

[그림 1]압축파일의 압축을 해제한 모습

이중에서 DM 드라이버파일은 “driver” 폴더에 포함되어 있으며, SDK 내용은 “sdk"폴더에 포함되어 있다.

드라이버가 포함된 디렉토리(x86)

[그림 2]드라이버가 포함된 디렉토리(x86)

함께 제공되는 배치파일(bat)과 실행파일(exe)은 사용자가 드라이버를 쉽게 설치하고 제거할 수 있도록 돕기 위해서 하제소프트에서 제공하는 유틸리티이다.

결국 최종적으로 드라이버설치에 사용되는 필수파일은 드라이버파일(sys)과 설치파일(inf), 그리고 인증서파일(cer) 이다. 이렇게 3개의 파일만 사용하면 드라이버 설치가 가능하다.

드라이버를 설치하기 이전에 설치파일의 내용을 확인해야 하는데, 이것은 DM 서버에 접수했던 하드웨어정보와 일치하는지를 확인하기 위함이다.

주의할 점은 절대로 설치파일의 내용을 수정하거나, 따로 저장해서는 안된다는 점이다. 함께 제공하는 인증서파일(cer)은 설치파일의 내용이 수정되지 않음을 증명하기 때문이다.

설치파일의 내용 중 일부분

[그림 3]설치파일의 내용 중 일부분

[그림 3]은 설치파일의 내용 중 아래 부분에 있는 내용이다. 이곳에서 현재 선택해서 보여주고 있는 부분이 하드웨어정보가 기술된 부분이다.

그림에서는 현재 하드웨어가 제조사ID(Vendor ID)가 0x13B1, 제품ID(Product ID)가 0x0026 그리고 리비젼 ID가 0x0006 임을 알 수 있다.

이와 같은 정보가 기술된 설치파일은 다른 하드웨어에 사용될 수 없다. 주의해야 한다.

모든 내용이 확인되었다면, 드라이버 설치를 위해서, 함께 제공하는 배치파일을 실행하거나 제어판을 통해서 드라이버 업데이트기능을 사용한다. “배치파일실행: DriverInstall32.BAT”

해당하는 배치파일실행으로 드라이버가 설치되지 않은 경우에는 제어판을 통해서 드라이버 업데이트기능을 사용한다.

SDK 환경 구축하기

DM 이 제공하는 SDK는 Visual Studio 2012(C++) 이상의 환경에서만 사용이 가능하다.

[그림 1]에서 examples디렉토리는 예제솔루션이 포함된 디렉토리이다. (여기서는 예제솔루션을 사용하는 방법은 설명하지 않는다. 새롭게 솔루션을 생성하는 방법위주로 설명하도록 하겠다.)

Include, Lib 디렉토리확인

DM SDK에서는 Include(C++) 파일들과 Lib(C++) 파일들을 제공하고 있다. Visual Studio 프로젝트를 생성하면, 반드시 해당하는 디렉토리 위치를 따로 지정해주어야 한다.

Include, Lib 디렉토리

[그림 4]Include, Lib 디렉토리

해당하는 헤더파일과 라이브러리의 위치를 한 번쯤은 탐색기를 통해서 꼭 확인해둘 필요가 있다. 실제 존재하는 위치를 지정할 때 알아야 하기 때문이다. 특히, Lib 디렉토리를 지정할 때는 32비트와 64비트의 위치를 꼭 확인한다.

DM 은 WOW64 환경을 지원하지 않는다. 따라서, 64비트 윈도우환경에서는 64비트드라이버와 64비트 SDK만을 사용해야 한다.(주의)

새로운 프로젝트 만들기

Visual Studio 2015(여기서는 이 버전을 사용해보도록 하겠다)를 사용해서 새로운 프로젝트를 만들어 본다. MFC기반이나 Console기반 어떤것이든 상관없지만, 여기서는 MFC기반으로 만들어 보도록 하겠다.

Visual Studio 2015 (C++) 프로젝트 만들기

[그림 5]Visual Studio 2015 (C++) 프로젝트 만들기

현재는 다이알로그형태의 프로젝트로 만들었다.( 다른 형태도 가능함 ) 새로운 프로젝트를 하나 만들었으면, DM SDK 의 위치를 알려주어야 한다.

DM SDK 의 Include, Lib 경로를 알려주는 방법은 여러 가지 방법이 있지만, 여기서는 소스 수준에서 알려주는 방법을 소개하기로 한다. 소스 파일 중에서 main의 역할을 수행하는 소스파일(c, c++)을 열어서 적당한 위치에 다음과 같은 문장을 추가한다.

#define DMDLLLIBNAME "MYUSBDRIVERNAMEDLL.lib"

// 현재 예제에서는 라이브러리의 이름이 “MYUSBDRIVERNAMEDLL.lib” 이기 때문에 이와 같이 기술한다. 사용자의 환경은 라이브러리의 이름이 다를 수 있다. [그림 4]를 참고한다.

#ifdef _WIN64        // 64비트 버젼을 만들 때 사용됩니다
#pragma comment(lib,"..\\SDK\\lib\\x64\\" DMDLLLIBNAME)
#else                // 32비트 버젼을 만들 때 사용됩니다
#pragma comment(lib,"..\\SDK\\lib\\x86\\" DMDLLLIBNAME)
#endif

경로는 사용자가 DM SDK의 압축파일을 어느 곳에 압축해제 했는지에 따라 달라지는 부분이기 때문에, 위와 같이 적당한 위치를 알려주어야 한다.

이것은 라이브러리의 위치를 알려주는 방법이다.

다음은 헤더파일을 지칭하는 방법이다. 여기서는 F:\dmtest 폴더아래에 압출을 해제한 경우로 가정한다.

#include "F:\\dmtest\\dmiiusb_unsigned\\packageNoSigned\\sdk\\include\\dmiiwin32.h"
#include "F:\\dmtest\\dmiiusb_unsigned\\packageNoSigned\\SDK\\include\\usb.h"
#include "F:\\dmtest\\dmiiusb_unsigned\\packageNoSigned\\SDK\\include\\dmiisdkcommon.h"
#include "F:\\dmtest\\dmiiusb_unsigned\\packageNoSigned\\SDK\\include\\dmiisdkvcdll_api.h"

이로서 헤더파일과 라이브러리의 파일의 위치가 소스 수준에서 모두 지정되었다.

다음은 MFC 예제솔루션 파일의 소스 내부에 이와 같은 내용을 모두 포함된 예제모습이다.

Visual Studio 2015 (C++) 프로젝트 만들기

[그림-6]Include, Lib 파일의 위치를 소스 내부에 포함시킨 모습

모든 준비는 끝났다. 이제 DM SDK 함수만 사용하면 된다.

DM DLL 위치 확인하기

DM SDK 를 사용하는 프로그램을 개발(빌드)하고 난뒤, 실제로 실행파일을 찾아서 실행할때는 반드시 DM 이 제공한 DLL 파일이 실행파일과 함께 들어 있어야 한다. 32비트와 64비트에서 사용되는 DLL 파일이 서로 다르므로 유의해야 한다

DM 이 제공하는 DLL 파일의 위치

[그림 7]DM 이 제공하는 DLL 파일의 위치

반드시 실행파일은 해당하는 DLL 과 같은 위치에서 실행되어져야 한다.

따라서, 새로운 프로젝트를 생성해서 빌드된 실행파일은 DLL 과 같은 위치에서 실행되도록 설정하는 것이 중요하다.

DM SDK 함수 사용하기

기본적인 함수 사용법은 각각의 함수를 위한 도움말 페이지(웹페이지)를 통해서 확인 할 수 있다. 이곳에서는 DM SDK 함수를 사용하는 예제 샘플을 하나 작성하는 방법을 통해서 처음 DM SDK 함수를 사용하는 독자를 위해 설명하도록 하겠다.

디바이스 열기

DM SDK를 사용하려면, 반드시 DMHandle 을 얻어야 한다. 이 핸들을 얻기 위해서 사용하는 함수이다.

dmStatus = DMDLL_OpenDeviceForInterfaceDeviceStack(
                      TargetIndex,
                      DMBUS_USB,
                      -1,
                      &DMHandle); // Master Handle 열기

TargetIndex 는 복수개의 하드웨어를 위한 인덱스 역할을 수행한다. DM SDK는 같은 종류의 하드웨어를 복수 개 사용하는 것을 지원하고 있다. 사용자는 이곳의 Index 값을 0 부터 사용하여 컴퓨터에서 발견되는 하드웨어 중 첫 번째(0), 두 번째(1), … 이런 식으로 검색할 수 있다. 이렇게 검색된 하드웨어에 대해서 디바이스 열기가 성공적으로 수행되면 DMHandle 값을 얻을 수 있다.

디바이스 닫기

사용이 끝난 DMHandle 을 반납하는 함수이다.

반드시 사용자는 DMDLL_OpenDeviceForInterfaceDeviceStack 함수를 통해서 얻은 DMHandle 이 더 이상 사용되지 않을 때는 반납해야 한다.

파이프 열기

DM SDK가 제공하는 핸들은 디바이스핸들과 파이프핸들이 있다. 디바이스 핸들은 DMHandle 이라고 부른다. 디바이스핸들은 디바이스 전체를 위한 DM SDK함수호출을 돕는다.

반면, 디바이스가 가진 엔드포인트(Endpoint)를 사용하려면 엔드포인트에 대응되는 파이프핸들(DMPipeHandle)을 얻어야 한다.(디폴트엔드포인트제외)

파이프핸들을 얻기 위해서 사용하는 함수는 디바이스 핸들을 얻기 위해서 사용하는 함수와 동일하지만, 3번째 파라미터가 다르다.

DMHANDLE DMPipeHandle;
TargetIndex = 0;
dmStatus = DMDLL_OpenDeviceForInterfaceDeviceStack(
                       TargetIndex,
                       DMBUS_USB,
                       0, // pipenumber.발견되는 첫 번째 파이프를엽니다(디폴트제외)
                       &DMPipeHandle); // Pipe Handle 열기

세 번째 파라미터가 -1 인 경우, DMHandle(디바이스 핸들)을 얻게 된다.

세번째 파라미터가 -1 이 아닌 경우, 파이프핸들을 얻게 된다.

위의 예에서는, 현재 USB 디바이스가 가지고 있는 첫 번째 엔드포인트를 위한 파이프를 열고 있다.(디폴트 엔드포인트를 제외한다)

사용이 끝난 DMPipeHandle 은 반납되어져야 하고, 이때 사용하는 함수는 DMDLL_CloseDevice 함수이다.

DMDLL_CloseDevice(DMPipeHandle);

디스크립터 읽기

DM SDK 가 제공하는 디스크립터의 내용을 위한 모든 메모리는 DM SDK에서 제공한다. 따라서, 사용이 끝난 메모리는 반드시 DMDLL_USBReleaseResources()함수를 통해서 반납해야 한다. 구체적인 사용방법은 도움말 사이트를 참고한다.

디바이스디스크립터를 읽는 방법

PUSB_DEVICE_DESCRIPTOR         pDeviceDesc = NULL;
dmStatus = DMDLL_USBGetDeviceDescriptor
(DMHandle, sizeof(USB_DEVICE_DESCRIPTOR), &pDeviceDesc);

컨피규레이션디스크립터를 읽는 방법(두 번에 걸쳐서 읽어야 전체크기를 알 수 있다)

PUSB_CONFIGURATION_DESCRIPTOR         pConfigDesc = NULL;
Int     wTotalLength = 0;

dmStatus = DMDLL_USBGetConfigurationDescriptor(
                    DMHandle, 
                    0, 
                    sizeof(USB_CONFIGURATION_DESCRIPTOR), 
                    &pConfigDesc);
wTotalLength = pConfigDesc->wTotalLength;
DMDLL_USBReleaseResources(pConfigDesc);

dmStatus = DMDLL_USBGetConfigurationDescriptor(
                    DMHandle, 
                    0, 
                    wTotalLength, 
                    &pConfigDesc);

파이프 정보 읽기

디바이스가 사용하는 엔드포인트를 접근하려면 우선, 디바이스가 어떤 엔드포인트를 가지고 있는 지를 알아야 한다. USB_CONFIGURATION_DESCRIPTOR 를 통해서 , DM SDK는 Pipe 정보를 다음과 같은 함수를 사용해서 제공하기도 한다.

PUSB_PIPE_INFORMATION         pPipeInformation;
dmStatus = DMDLL_USBAcquirePipeInformations(DMHandle, &pPipeInformation);

DMDLL_USBAcquirePipeInformations()함수를 사용하면, pPipeInformation 정보를 얻을 수 있다. pPipeInformation 정보는 디바이스가 가진 모든 엔드포인트(디폴트제외)에 대한 파이프정보를 제공한다.

PUSB_PIPE_INFORMATION         pPipeInformation;
dmStatus = DMDLL_USBAcquirePipeInformations(DMHandle, &pPipeInformation);
if (dmStatus != DMSTAT_SUCCESS)
               return;

// pPipeInformation->nPipes = 열린 파이프 수
int nPipes = 0;
int Pos = 0;

for (nPipes = 0; nPipes < pPipeInformation->nPipes; nPipes ++)
{
     switch (pPipeInformation->Pipe[nPipes].PipeType) // 파이프종류
     {
          case UsbdPipeTypeIsochronous:
               break;
          case UsbdPipeTypeBulk:
               break;
          case UsbdPipeTypeInterrupt:
               break;
          default:
               break;
     }
     pPipeInformation->Pipe[nPipes].EndpointAddress;//엔드포인트주소+방향
     pPipeInformation->Pipe[nPipes].Interval; //엔드포인트서비스인터벌
     pPipeInformation->Pipe[nPipes].MaximumPacketSize;// MaxPacketSize
}
DMDLL_USBReleaseResources(pPipeInformation); // 사용이 끝나면 반납한다

Plug & Play 이벤트 설정

DM SDK는 DM 디바이스를 사용하다 사용자가 장치를 컴퓨터에서 제거하면 이 사실을 알 수 있도록 이벤트를 제공한다. 이와 같은 이벤트를 얻어오는 방법을 소개한다.

HANDLE hEventForPlugOut; // 장치제거와 관련된 이벤트
dmStatus = DMDLL_USBGetPlugOutEvent(DMHandle, &hEventForPlugOut);

위와 같이 얻어온 hEventForPlugOut 이벤트는 WIN32 API WaitForSingleObject()함수에 의해서 동기화목적으로 사용되어질 수 있다. 해당하는 이벤트는 디바이스가 컴퓨터에서 제거될때 항상 시그널된다. 주의!!! 이벤트가 시그널되면 해당하는 디바이스가 컴퓨터에서 제거되었다는 뜻이므로, 사용자는 반드시 사용중인 모든 DM Handle을 반납해야 한다.

전원 관리 모드 설정

DM SDK는 사용자프로그램이 전원절전과 관련된 문맥 보관 및 문맥 복원할 기회를 제공한다. 사용 중인 디바이스가 전원절전모드로 진입된 이후 사라지게 되는 레지스터정보를 미리 보관하고, 이후 다시 전원절전모드에서 빠져나올 때 보관했던 레지스터정보를 사용해서 디바이스의 동작을 복원하는 기회를 가질 수 있다.

dmStatus = DMDLL_SetPowerManagement(DMHandle, PowerChangingCallback, this);

함께 등록하는 PowerChaningCallback 함수는 다음과 같이 작성한다.

void PowerChangingCallback(DMHANDLE DMHandle, int PowerState, PVOID pContext)
{
        switch (PowerState)
        {
               case PowerSystemWorking: // 문맥복원작업을 합니다
                       break;
               case PowerSystemSleeping1: // 문맥보관작업을 합니다
               case PowerSystemSleeping2:
               case PowerSystemSleeping3:
                       break;
               case PowerSystemHibernate: // 문맥보관작업을 합니다
                       break;
               case PowerSystemShutdown:
                       break;
        }
}

PowerChangingCallback 함수는 시스템파워의 공급상태가 바뀔때마다 호출된다. 사용자는 이런 상황마다 호출되는 콜백함수를 적절하게 작성하여 문맥보관과 복원작업을 할 수 있다.

데이터 전송하기

디바이스가 가진 엔드포인트를 접근하기 위해서 파이프핸들을 얻은 뒤에 사용자는 해당하는 파이프핸들을 사용해서 여러가지 전송요청을 할 수 있다.

전송요청은 벌크전송, 인터럽트전송이 여기에 포함된다.(DM-II USB 1.0 에서는 등시성전송을 지원하지 않는다)

벌크전송

DMDLL_USBBulkOutTransfer(벌크 OUT)
DMDLL_USBBulkInTransfer(벌크 IN)

인터럽트전송

DMDLL_USBInterruptOutTransfer(인터럽트 OUT)
DMDLL_USBInterruptInTransfer(인터럽트 IN)

벌크 IN 전송의 경우, 보다 빠른 결과를 회신하기 위해서 비동기 읽기기능이 지원된다. 이 기능은 DM SDK 드라이버에 의해서 미리 데이터 읽기작업이 진행되며, 이렇게 읽은 내용은 사용자에 의해서 설정된(변경가능한) 큐에 보관되어, 사용자는 큐에 보관된 내용만 읽어들이는 방식을 비동기 읽기기능으로 정의한다.

비동기 읽기기능을 사용하려면 다음과 같은 몇 가지 작업을 준비해야 한다.

DMDLL_USBStartBulkPipeQueue(
            IN DMHANDLE PipeHandle, 
            IN int  QueueSize,
            IN HANDLE hEvent);
  • 첫 번째 파라미터가 디바이스 핸들이 아니라, 파이프 핸들임을 유의하자.

  • 두 번째 파라미터로 사용되는 값은 Queue 의 크기를 지정한다. 이 값은 반드시 MINIMUM_BULKIN_QUEUE_SIZE 값보다 큰 값을 사용해야 한다.

  • 세 번째 파라미터로 사용되는 이벤트는 해당하는 벌크 Queue 에 데이터가 들어오는 것을 알려주는 용도로 사용되는 시그널이벤트이다

사용자는 WIN32 이벤트를 하나 생성해서, 이곳을 통해서 DM SDK에게 알려준다. 이렇게 알려준 이벤트핸들은 사용이 끝나면 사용자프로그램에 의해서 직접 해제해야 한다(CloseHandle).

이 함수가 성공적인 수행을 하면, 지금부터 백그라운드에서는 고속 벌크 IN 작업이 진행된다. 언제든지 이 작업을 멈추고 싶을 때는, DMDLL_USBStopBulkPipeQueue() 함수를 사용해야 한다.

평상시 이벤트가 시그널되거나, 그렇지 않더라도 언제든지 Queue 에 상태를 확인 할 수 있다. 이것은 DMDLL_USBQueueStatus 함수에 의해서 가능하다.

Queue 에 데이터가 들어있는 것을 확인하면, 사용자는 DMDLL_USBBulkInTransfer 함수를 사용해서 준비된 데이터를 읽을 수 있다. 비동기모드를 사용하는 경우, Queue 에 데이타가 없으면 이 함수는 0 바이트를 읽고 돌아온다.

디폴트 엔드포인터 지원기능

DM SDK는 디폴트엔드포인트와 관련된 작업을 다음 함수를 통해서 지원하고 있다.

DMDLL_USBVendorClassTransfer_LL
DMDLL_USBFeature_LL
DMDLL_USBGetStatus_LL
DMDLL_USBAbortPipe
DMDLL_USBGetStringDescriptor
DMDLL_USBGetDescriptor_LL

파이프 핸들을 사용하는 로우레벨 함수 지원

파이프핸들을 사용하는 고급함수외에 다음과 같은 로우레벨 함수를 추가로 지원하고 있어서, 보다 저급적인 레벨에서 함수사용의 이득을 얻을 수 있다.

DMDLL_USBBulkTransfer_LL
DMDLL_USBInterruptTransfer_LL

results matching ""

    No results matching ""