■ USB通信2(VC++)                                                          

  
   

■ PIC18F14K50 HIDクラス LED 点灯/消灯 制御・表示
<試作品仕様>
 ・PC(Windows)上のボタンスイッチ×4個をクリックすると PIC18F40K50のキバン上の対応するLEDがON/OFFすること
 ・PCとPIC間のUSB通信はHIDクラスとする。
 ・ボタンスイッチはLEDがONしているときは赤色、OFFの時は灰色とする。
 ・USB通信ONのボタンボタンスイッチをフォーム上にもうけること。 またUSB通信が確立したら”接続完了!”の文字をテキストボックスに表示のこと

 ★ ハード 及びPIC側のソフトは こちらを参照願います 

          

   <プログラム例>

//Form1.h


#pragma once
//Includes
#include <Windows.h>    //Definitions for various common and not so common types like DWORD, PCHAR, HANDLE, etc.
#include <setupapi.h>   //From Platform SDK. Definitions needed for the SetupDixxx() functions, which we use to
                                                //find our plug and play device.

//Modify this value to match the VID and PID in your USB device descriptor.
//Use the formatting: "Vid_xxxx&Pid_xxxx" where xxxx is a 16-bit hexadecimal number.
#define MY_DEVICE_ID  "Vid_04d8&Pid_003F"               //VID = 0x04D8  PID = 0x003F    


namespace CWhiteForm {

        using namespace System;
        using namespace System::ComponentModel;
        using namespace System::Collections;
        using namespace System::Windows::Forms;
        using namespace System::Data;
        using namespace System::Drawing;

        

//-------------------------------------------------------BEGIN CUT AND PASTE BLOCK--------------------------
        using namespace System::Runtime::InteropServices;  //Need this to support "unmanaged" code.

        /*
        In order to use these unmanaged functions from within the managed .NET environment, we need
        to explicitly import the functions which we will be using from other .DLL file(s).  Simply
        including the appropriate header files is not enough. 

        Note: In order to avoid potential name conflicts in the header files (which we still use),
        I have renamed the functions by adding "UM" (unmanaged) onto the end of them.  To find 
        documentation for the functions in MSDN, search for the function name without the extra 
        "UM" attached.
        Note2: In the header files (such as setupapi.h), normally the function names are 
        remapped, depending upon if UNICODE is defined or not.  For example, two versions of the
        function SetupDiGetDeviceInterfaceDetail() exist.  One for UNICODE, and one for ANSI.  
        If the wrong version of the function is called, things won't work correctly.  Therefore,
        in order to make sure the correct one gets called (based on your compiler settings, which
        may or may not define "UNICODE"), it is useful to explicity specify the CharSet when doing
        the DLL import.
        */

        #ifdef UNICODE
        #define Seeifdef        Unicode
        #else
        #define Seeifdef        Ansi
        #endif


        //使用するDLL関数の宣言
        //Returns a HDEVINFO type for a device information set (USB HID devices in
        //our case).  We will need the HDEVINFO as in input parameter for calling many of
        //the other SetupDixxx() functions.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetClassDevs", CallingConvention=CallingConvention::Winapi)]                
        extern "C" HDEVINFO  SetupDiGetClassDevsUM(
                LPGUID  ClassGuid,                                      //Input: Supply the class GUID here. 
                PCTSTR  Enumerator,                                     //Input: Use NULL here, not important for our purposes
                HWND  hwndParent,                                       //Input: Use NULL here, not important for our purposes
                DWORD  Flags);                                          //Input: Flags describing what kind of filtering to use.

        //Gives us "PSP_DEVICE_INTERFACE_DATA" which contains the Interface specific GUID (different
        //from class GUID).  We need the interface GUID to get the device path.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiEnumDeviceInterfaces", CallingConvention=CallingConvention::Winapi)]                                
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiEnumDeviceInterfacesUM(
                HDEVINFO  DeviceInfoSet,                        //Input: Give it the HDEVINFO we got from SetupDiGetClassDevs()
                PSP_DEVINFO_DATA  DeviceInfoData,       //Input (optional)
                LPGUID  InterfaceClassGuid,                     //Input 
                DWORD  MemberIndex,                                     //Input: "Index" of the device you are interested in getting the path for.
                PSP_DEVICE_INTERFACE_DATA  DeviceInterfaceData);//Output: This function fills in an "SP_DEVICE_INTERFACE_DATA" structure.

        //SetupDiDestroyDeviceInfoList() frees up memory by destroying a DeviceInfoList
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiDestroyDeviceInfoList", CallingConvention=CallingConvention::Winapi)]
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiDestroyDeviceInfoListUM(                     
                HDEVINFO  DeviceInfoSet);                       //Input: Give it a handle to a device info list to deallocate from RAM.

        //SetupDiEnumDeviceInfo() fills in an "SP_DEVINFO_DATA" structure, which we need for SetupDiGetDeviceRegistryProperty()
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiEnumDeviceInfo", CallingConvention=CallingConvention::Winapi)]
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiEnumDeviceInfoUM(
                HDEVINFO  DeviceInfoSet,
                DWORD  MemberIndex,
                PSP_DEVINFO_DATA  DeviceInfoData);

        //SetupDiGetDeviceRegistryProperty() gives us the hardware ID, which we use to check to see if it has matching VID/PID
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetDeviceRegistryProperty", CallingConvention=CallingConvention::Winapi)]
        extern "C"      WINSETUPAPI BOOL WINAPI  SetupDiGetDeviceRegistryPropertyUM(
                HDEVINFO  DeviceInfoSet,
                PSP_DEVINFO_DATA  DeviceInfoData,
                DWORD  Property,
                PDWORD  PropertyRegDataType,
                PBYTE  PropertyBuffer,   
                DWORD  PropertyBufferSize,  
                PDWORD  RequiredSize);

        //SetupDiGetDeviceInterfaceDetail() gives us a device path, which is needed before CreateFile() can be used.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetDeviceInterfaceDetail", CallingConvention=CallingConvention::Winapi)]
        extern "C" BOOL SetupDiGetDeviceInterfaceDetailUM(
                HDEVINFO DeviceInfoSet,                                                                         //Input: Wants HDEVINFO which can be obtained from SetupDiGetClassDevs()
                PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,                          //Input: Pointer to an structure which defines the device interface.  
                PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData,     //Output: Pointer to a strucutre, which will contain the device path.
                DWORD DeviceInterfaceDetailDataSize,                                            //Input: Number of bytes to retrieve.
                PDWORD RequiredSize,                                                                            //Output (optional): Te number of bytes needed to hold the entire struct 
                PSP_DEVINFO_DATA DeviceInfoData);                                                       //Output


//  Variables that need to have wide scope.
        HANDLE WriteHandle = INVALID_HANDLE_VALUE;      //Need to get a write "handle" to our device before we can write to it.
        HANDLE ReadHandle = INVALID_HANDLE_VALUE;       //Need to get a read "handle" to our device before we can read from it.
//-------------------------------------------------------END CUT AND PASTE BLOCK-------------------------------------------------------------------------------------

        
        //グローバル変数定義 
//      unsigned int ADCValue;
        int LedMode = 0,        //      LedMode = 0; 消灯 1:点灯
                Led1Mode = 0,   // Led1Mode = 0; 消灯 1:点灯
                Led2Mode = 0,   // Led2Mode = 0; 消灯 1:点灯
                Led3Mode = 0;   // Lee3Mode = 0; 消灯 1:点灯        

        DWORD BytesWritten = 0;
        DWORD BytesRead = 0;
        unsigned char OutputPacketBuffer[65];   //Allocate a memory buffer equal to our endpoint size + 1
        unsigned char InputPacketBuffer[65];


        /// <summary>
        /// Form1 の概要
        /// </summary>
        public ref class Form1 : public System::Windows::Forms::Form
        {
        public:
                Form1(void)     //コンストラクタ
                {
                        InitializeComponent();
                        //
                        //TODO: ここにコンストラクター コードを追加します
                        //
                }

        protected:
                /// <summary>
                /// 使用中のリソースをすべてクリーンアップします。
                /// </summary>
                ~Form1()        //デストラクタ
                {
                        if (components)
                        {
                                delete components;
                        }
                }

        private: System::Windows::Forms::Button^  ConnectBtn;
        private: System::Windows::Forms::Button^  LedSw;

        protected: 

        private: System::Windows::Forms::TextBox^  textBox1;
        private: System::Windows::Forms::Button^  LedSw1;
        private: System::Windows::Forms::Button^  LedSw2;
        private: System::Windows::Forms::Button^  LedSw3;






        private:
                /// <summary>
                /// 必要なデザイナー変数です。
                /// </summary>
                System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
                /// <summary>
                /// デザイナー サポートに必要なメソッドです。このメソッドの内容を
                /// コード エディターで変更しないでください。
                /// </summary>
                void InitializeComponent(void)  //コンポーネントの初期化
                {
                        this->ConnectBtn = (gcnew System::Windows::Forms::Button());
                        this->LedSw = (gcnew System::Windows::Forms::Button());
                        this->textBox1 = (gcnew System::Windows::Forms::TextBox());
                        this->LedSw1 = (gcnew System::Windows::Forms::Button());
                        this->LedSw2 = (gcnew System::Windows::Forms::Button());
                        this->LedSw3 = (gcnew System::Windows::Forms::Button());
                        this->SuspendLayout();
                        // 
                        // ConnectBtn
                        // 
                        this->ConnectBtn->Location = System::Drawing::Point(35, 24);
                        this->ConnectBtn->Name = L"ConnectBtn";
                        this->ConnectBtn->Size = System::Drawing::Size(83, 33);
                        this->ConnectBtn->TabIndex = 0;
                        this->ConnectBtn->Text = L"接続";
                        this->ConnectBtn->UseVisualStyleBackColor = true;
                        this->ConnectBtn->Click += gcnew System::EventHandler(this, &Form1::ConnectBtn_Click);
                        // 
                        // LedSw
                        // 
                        this->LedSw->Location = System::Drawing::Point(35, 97);
                        this->LedSw->Name = L"LedSw";
                        this->LedSw->Size = System::Drawing::Size(75, 59);
                        this->LedSw->TabIndex = 1;
                        this->LedSw->Text = L"LED0";
                        this->LedSw->UseVisualStyleBackColor = true;
                        this->LedSw->Click += gcnew System::EventHandler(this, &Form1::LedSw_Click);
                        // 
                        // textBox1
                        // 
                        this->textBox1->Location = System::Drawing::Point(189, 35);
                        this->textBox1->Name = L"textBox1";
                        this->textBox1->Size = System::Drawing::Size(197, 22);
                        this->textBox1->TabIndex = 2;
                        // 
                        // LedSw1
                        // 
                        this->LedSw1->Location = System::Drawing::Point(147, 97);
                        this->LedSw1->Name = L"LedSw1";
                        this->LedSw1->Size = System::Drawing::Size(75, 59);
                        this->LedSw1->TabIndex = 3;
                        this->LedSw1->Text = L"LED1";
                        this->LedSw1->UseVisualStyleBackColor = true;
                        this->LedSw1->Click += gcnew System::EventHandler(this, &Form1::LedSw1_Click);
                        // 
                        // LedSw2
                        // 
                        this->LedSw2->Location = System::Drawing::Point(263, 97);
                        this->LedSw2->Name = L"LedSw2";
                        this->LedSw2->Size = System::Drawing::Size(75, 59);
                        this->LedSw2->TabIndex = 4;
                        this->LedSw2->Text = L"LED2";
                        this->LedSw2->UseVisualStyleBackColor = true;
                        this->LedSw2->Click += gcnew System::EventHandler(this, &Form1::LedSw2_Click);
                        // 
                        // LedSw3
                        // 
                        this->LedSw3->Location = System::Drawing::Point(379, 97);
                        this->LedSw3->Name = L"LedSw3";
                        this->LedSw3->Size = System::Drawing::Size(75, 59);
                        this->LedSw3->TabIndex = 5;
                        this->LedSw3->Text = L"LED3";
                        this->LedSw3->UseVisualStyleBackColor = true;
                        this->LedSw3->Click += gcnew System::EventHandler(this, &Form1::LedSw3_Click);
                        // 
                        // Form1
                        // 
                        this->AutoScaleDimensions = System::Drawing::SizeF(8, 15);
                        this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
                        this->ClientSize = System::Drawing::Size(498, 214);
                        this->Controls->Add(this->LedSw3);
                        this->Controls->Add(this->LedSw2);
                        this->Controls->Add(this->LedSw1);
                        this->Controls->Add(this->textBox1);
                        this->Controls->Add(this->LedSw);
                        this->Controls->Add(this->ConnectBtn);
                        this->Name = L"Form1";
                        this->Text = L"Form1";
                        this->ResumeLayout(false);
                        this->PerformLayout();

                }
#pragma endregion


        private: System::Void ConnectBtn_Click(System::Object^  sender, System::EventArgs^  e)  //USBパイプ接続
        {
                                 //-------------------------------------------------------BEGIN CUT AND PASTE BLOCK-----------------------------------------------------------------------------------
                /* 
                Before we can "connect" our application to our USB embedded device, we must first find the device.
                A USB bus can have many devices simultaneously connected, so somehow we have to find our device, and only
                our device.  This is done with the Vendor ID (VID) and Product ID (PID).  Each USB product line should have
                a unique combination of VID and PID.  

                Microsoft has created a number of functions which are useful for finding plug and play devices.  Documentation
                for each function used can be found in the MSDN library.  We will be using the following functions:

                SetupDiGetClassDevs()                                   //provided by setupapi.dll, which comes with Windows
                SetupDiEnumDeviceInterfaces()                   //provided by setupapi.dll, which comes with Windows
                GetLastError()                                                  //provided by kernel32.dll, which comes with Windows
                SetupDiDestroyDeviceInfoList()                  //provided by setupapi.dll, which comes with Windows
                SetupDiGetDeviceInterfaceDetail()               //provided by setupapi.dll, which comes with Windows
                SetupDiGetDeviceRegistryProperty()              //provided by setupapi.dll, which comes with Windows
                malloc()                                                                //part of C runtime library, msvcrt.dll?
                CreateFile()                                                    //provided by kernel32.dll, which comes with Windows

                We will also be using the following unusual data types and structures.  Documentation can also be found in
                the MSDN library:

                PSP_DEVICE_INTERFACE_DATA
                PSP_DEVICE_INTERFACE_DETAIL_DATA
                SP_DEVINFO_DATA
                HDEVINFO
                HANDLE
                GUID

                The ultimate objective of the following code is to call CreateFile(), which opens a communications
                pipe to a specific device (such as a HID class USB device endpoint).  CreateFile() returns a "handle" 
                which is needed later when calling ReadFile() or WriteFile().  These functions are used to actually 
                send and receive application related data to/from the USB peripheral device.

                However, in order to call CreateFile(), we first need to get the device path for the USB device
                with the correct VID and PID.  Getting the device path is a multi-step round about process, which
                requires calling several of the SetupDixxx() functions provided by setupapi.dll.
                */


                //Globally Unique Identifier (GUID) for HID class devices.  Windows uses GUIDs to identify things.
                GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}; 

                HDEVINFO DeviceInfoTable = INVALID_HANDLE_VALUE;
                PSP_DEVICE_INTERFACE_DATA InterfaceDataStructure = new SP_DEVICE_INTERFACE_DATA;
                PSP_DEVICE_INTERFACE_DETAIL_DATA DetailedInterfaceDataStructure = new SP_DEVICE_INTERFACE_DETAIL_DATA;
                SP_DEVINFO_DATA DevInfoData;

                DWORD InterfaceIndex = 0;
                DWORD StatusLastError = 0;
                DWORD dwRegType;
                DWORD dwRegSize;
                DWORD StructureSize = 0;
                PBYTE PropertyValueBuffer;
                bool MatchFound = false;
                DWORD ErrorStatus;

                String^ DeviceIDToFind = MY_DEVICE_ID;

                //First populate a list of plugged in devices (by specifying "DIGCF_PRESENT"), which are of the specified class GUID. 
                DeviceInfoTable = SetupDiGetClassDevsUM(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

                //Now look through the list we just populated.  We are trying to see if any of them match our device. 
                while(true)
                {
                        InterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
                        if(SetupDiEnumDeviceInterfacesUM(DeviceInfoTable, NULL, &InterfaceClassGuid, InterfaceIndex, InterfaceDataStructure))
                        {
                                ErrorStatus = GetLastError();
                                if(ERROR_NO_MORE_ITEMS == ErrorStatus)  //Did we reach the end of the list of matching devices in the DeviceInfoTable?
                                {       //Cound not find the device.  Must not have been attached.
                                        SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                        return;         
                                }
                        }
                        else    //Else some other kind of unknown error ocurred...
                        {
                                ErrorStatus = GetLastError();
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                return; 
                        }

                        //Now retrieve the hardware ID from the registry.  The hardware ID contains the VID and PID, which we will then 
                        //check to see if it is the correct device or not.

                        //Initialize an appropriate SP_DEVINFO_DATA structure.  We need this structure for SetupDiGetDeviceRegistryProperty().
                        DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
                        SetupDiEnumDeviceInfoUM(DeviceInfoTable, InterfaceIndex, &DevInfoData);

                        //First query for the size of the hardware ID, so we can know how big a buffer to allocate for the data.
                        SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, NULL, 0, &dwRegSize);

                        //Allocate a buffer for the hardware ID.
                        PropertyValueBuffer = (BYTE *) malloc (dwRegSize);
                        if(PropertyValueBuffer == NULL) //if null, error, couldn't allocate enough memory
                        {       //Can't really recover from this situation, just exit instead.
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                return;         
                        }

                        //Retrieve the hardware IDs for the current device we are looking at.  PropertyValueBuffer gets filled with a 
                        //REG_MULTI_SZ (array of null terminated strings).  To find a device, we only care about the very first string in the
                        //buffer, which will be the "device ID".  The device ID is a string which contains the VID and PID, in the example 
                        //format "Vid_04d8&Pid_003f".
                        SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, PropertyValueBuffer, dwRegSize, NULL);

                        //Now check if the first string in the hardware ID matches the device ID of my USB device.
                        #ifdef UNICODE
                        String^ DeviceIDFromRegistry = gcnew String((wchar_t *)PropertyValueBuffer);
                        #else
                        String^ DeviceIDFromRegistry = gcnew String((char *)PropertyValueBuffer);
                        #endif

                        free(PropertyValueBuffer);              //No longer need the PropertyValueBuffer, free the memory to prevent potential memory leaks
                        textBox1->Text = "Searching Device!";
                        //Convert both strings to lower case.  This makes the code more robust/portable accross OS Versions
                        DeviceIDFromRegistry = DeviceIDFromRegistry->ToLowerInvariant();        
                        DeviceIDToFind = DeviceIDToFind->ToLowerInvariant();                            
                        //Now check if the hardware ID we are looking at contains the correct VID/PID
                        MatchFound = DeviceIDFromRegistry->Contains(DeviceIDToFind);            
                        if(MatchFound == true)
                        {
                                //Device must have been found.  Open read and write handles.  In order to do this, we will need the actual device path first.
                                //We can get the path by calling SetupDiGetDeviceInterfaceDetail(), however, we have to call this function twice:  The first
                                //time to get the size of the required structure/buffer to hold the detailed interface data, then a second time to actually 
                                //get the structure (after we have allocated enough memory for the structure.)
                                DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                                //First call populates "StructureSize" with the correct value
                                SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, NULL, NULL, &StructureSize, NULL);   
                                DetailedInterfaceDataStructure = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(malloc(StructureSize));             //Allocate enough memory
                                if(DetailedInterfaceDataStructure == NULL)      //if null, error, couldn't allocate enough memory
                                {       //Can't really recover from this situation, just exit instead.
                                        SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                        return;         
                                }
                                DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                                 //Now call SetupDiGetDeviceInterfaceDetail() a second time to receive the goods.  
                                SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, DetailedInterfaceDataStructure, StructureSize, NULL, NULL); 

                                //We now have the proper device path, and we can finally open read and write handles to the device.
                                //We store the handles in the global variables "WriteHandle" and "ReadHandle", which we will use later to actually communicate.
                                WriteHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);

                                ErrorStatus = GetLastError();
                                if(ErrorStatus == ERROR_SUCCESS)
                                        textBox1->Text = "Write Enabled.";                              //Make button no longer greyed out
                                ReadHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
                                ErrorStatus = GetLastError();
                                if(ErrorStatus == ERROR_SUCCESS)
                                {
                                        textBox1->Text = "Read Enabled.";                                       //Make label no longer greyed out
                                }
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                               
                                //追加修正部
                                // 接続確認メッセージ準備 
                                OutputPacketBuffer[0] = 0;                                                      // Report ID  
                                OutputPacketBuffer[1] = 0x30;                                           // 接続確認 
                                // 接続確認 コマンド送信
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                // OK受信
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
                                // OK確認 
                                if((InputPacketBuffer[3] == 0x4F)&&(InputPacketBuffer[4] == 0x4B))
                                        textBox1->Text = "接続完了!!";                              // 接続正常完了
                                // 接続完了でタイマ1スタート
//                              timer1->Interval = 1000;
//                              timer1->Enabled = TRUE;
                                return;
                        }

                        InterfaceIndex++;       
                        //Keep looping until we either find a device with matching VID and PID, or until we run out of items.
                }//end of while(true)   
//-------------------------------------------------------END CUT AND PASTE BLOCK-------------------------------------------------------------------------------------

        }



        private: System::Void LedSw_Click(System::Object^  sender, System::EventArgs^  e) 
        {
                                
                OutputPacketBuffer[0] = 0;                                      // Report ID  
                OutputPacketBuffer[1] = 0x31;                           // LED制御コマンド

                OutputPacketBuffer[2] = 0x31;                           // LED0アドレス

                if(LedMode == 0)        //消灯していたなら
                {
                        LedMode = 1;
                        OutputPacketBuffer[3] = 0x31;                   // Led点灯        //0x31 = '1'
                }
                else
                {
                        LedMode = 0;
                        OutputPacketBuffer[3] = 0x30;                   // Led消灯        //0x30 = '0'
                }

                // 送信
                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);


                // 受信
                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
        
                if(InputPacketBuffer[3] == 0x31)LedSw->BackColor =Color:: Red;          // オンなら赤
                else LedSw->BackColor = Color::Gray;            // オフなら緑
        }
        
private: System::Void LedSw1_Click(System::Object^  sender, System::EventArgs^  e)
                 {
                        OutputPacketBuffer[0] = 0;                                      // Report ID  
                        OutputPacketBuffer[1] = 0x31;                           // LED制御コマンド
                        OutputPacketBuffer[2] = 0x32;                           // LED1アドレス
                        if(Led1Mode == 0)       //消灯していたなら
                        {
                                Led1Mode = 1;
                                OutputPacketBuffer[3] = 0x31;                   // Led点灯
                        }
                        else
                        {
                                Led1Mode = 0;
                                OutputPacketBuffer[3] = 0x30;                   // Led消灯
                        }

                        // 送信
                        WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);


                        // 受信
                        ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
        
                        if(InputPacketBuffer[3] == 0x31)LedSw1->BackColor =Color:: Red;         // オンなら赤
                        else LedSw1->BackColor = Color::Gray;           // オフなら緑
                 }

private: System::Void LedSw2_Click(System::Object^  sender, System::EventArgs^  e)
                 {
                        OutputPacketBuffer[0] = 0;                                      // Report ID  
                        OutputPacketBuffer[1] = 0x31;                           // LED制御コマンド
                        OutputPacketBuffer[2] = 0x33;                           // LED2アドレス
                        if(Led2Mode == 0)       //消灯していたなら
                        {
                                Led2Mode = 1;
                                OutputPacketBuffer[3] = 0x31;                   // Led点灯
                        }
                        else
                        {
                                Led2Mode = 0;
                                OutputPacketBuffer[3] = 0x30;                   // Led消灯
                        }

                        // 送信
                        WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);


                        // 受信
                        ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
        
                        if(InputPacketBuffer[3] == 0x31)LedSw2->BackColor =Color:: Red;         // オンなら赤
                        else LedSw2->BackColor = Color::Gray;           // オフなら緑
                        

                 }

private: System::Void LedSw3_Click(System::Object^  sender, System::EventArgs^  e)
                 {
                        OutputPacketBuffer[0] = 0;                                      // Report ID  
                        OutputPacketBuffer[1] = 0x31;                           // LED制御コマンド
                        OutputPacketBuffer[2] = 0x34;                           // LED2アドレス
                        if(Led3Mode == 0)       //消灯していたなら
                        {
                                Led3Mode = 1;
                                OutputPacketBuffer[3] = 0x31;                   // Led点灯
                        }
                        else
                        {
                                Led3Mode = 0;
                                OutputPacketBuffer[3] = 0x30;                   // Led消灯
                        }

                        // 送信
                        WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);


                        // 受信
                        ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
        
                        if(InputPacketBuffer[3] == 0x31)LedSw3->BackColor =Color:: Red;         // オンなら赤
                        else LedSw3->BackColor = Color::Gray;           // オフなら緑


                 }

};//end of class Form1
} 

<実行結果>

 接続ボタンをクリックした後、LED0、LED2、LED3を点灯させたところです。
尚、PIC18F14K50のキバン上には本テーマと関係ない部品が多々搭載されています。





■ PIC18F14K50 HIDクラス スイッチの状態 & 電圧読込

<試作品仕様>
 ・PIC18F14K50のキバン上のスイッチ×3個を押すと PC(Windows)上の対応するovalShape×3個の色が 灰色→オレンジ色に変わること
 ・PCとPIC間のUSB通信はHIDクラスとする。
 ・可変抵抗器×3個により設定される電圧をPIC18F14K50の内蔵ADコンバータで読込、この電圧値[V]をPC上の対応するテキストボックス×3個に表示のこと。
 ・テキストボックスに表示される電圧[V]は、小数点以下2桁とする。
 ・USB通信ONのボタンボタンスイッチをフォーム上にもうけること。 またUSB通信が確立したら”接続完了!”の文字をテキストボックスに表示のこと

 ★ ハード 及びPIC側のソフトは こちらを参照願います 


          

   <プログラム例>

#pragma once
//Includes
#include <Windows.h>    //Definitions for various common and not so common types like DWORD, PCHAR, HANDLE, etc.
#include <setupapi.h>   //From Platform SDK. Definitions needed for the SetupDixxx() functions, which we use to
                                                //find our plug and play device.

//Modify this value to match the VID and PID in your USB device descriptor.
//Use the formatting: "Vid_xxxx&Pid_xxxx" where xxxx is a 16-bit hexadecimal number.
#define MY_DEVICE_ID  "Vid_04d8&Pid_003F"       


namespace CWhiteForm {

        using namespace System;
        using namespace System::ComponentModel;
        using namespace System::Collections;
        using namespace System::Windows::Forms;
        using namespace System::Data;
        using namespace System::Drawing;

//-------------------------------------------------------BEGIN CUT AND PASTE BLOCK-----------------------------------------------------------------------------------
        using namespace System::Runtime::InteropServices;  //Need this to support "unmanaged" code.

        /*
        In order to use these unmanaged functions from within the managed .NET environment, we need
        to explicitly import the functions which we will be using from other .DLL file(s).  Simply
        including the appropriate header files is not enough. 

        Note: In order to avoid potential name conflicts in the header files (which we still use),
        I have renamed the functions by adding "UM" (unmanaged) onto the end of them.  To find 
        documentation for the functions in MSDN, search for the function name without the extra 
        "UM" attached.
        Note2: In the header files (such as setupapi.h), normally the function names are 
        remapped, depending upon if UNICODE is defined or not.  For example, two versions of the
        function SetupDiGetDeviceInterfaceDetail() exist.  One for UNICODE, and one for ANSI.  
        If the wrong version of the function is called, things won't work correctly.  Therefore,
        in order to make sure the correct one gets called (based on your compiler settings, which
        may or may not define "UNICODE"), it is useful to explicity specify the CharSet when doing
        the DLL import.
        */

        #ifdef UNICODE
        #define Seeifdef        Unicode
        #else
        #define Seeifdef        Ansi
        #endif

        //Returns a HDEVINFO type for a device information set (USB HID devices in
        //our case).  We will need the HDEVINFO as in input parameter for calling many of
        //the other SetupDixxx() functions.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetClassDevs", CallingConvention=CallingConvention::Winapi)]                
        extern "C" HDEVINFO  SetupDiGetClassDevsUM(
                LPGUID  ClassGuid,                                      //Input: Supply the class GUID here. 
                PCTSTR  Enumerator,                                     //Input: Use NULL here, not important for our purposes
                HWND  hwndParent,                                       //Input: Use NULL here, not important for our purposes
                DWORD  Flags);                                          //Input: Flags describing what kind of filtering to use.

        //Gives us "PSP_DEVICE_INTERFACE_DATA" which contains the Interface specific GUID (different
        //from class GUID).  We need the interface GUID to get the device path.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiEnumDeviceInterfaces", CallingConvention=CallingConvention::Winapi)]                                
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiEnumDeviceInterfacesUM(
                HDEVINFO  DeviceInfoSet,                        //Input: Give it the HDEVINFO we got from SetupDiGetClassDevs()
                PSP_DEVINFO_DATA  DeviceInfoData,       //Input (optional)
                LPGUID  InterfaceClassGuid,                     //Input 
                DWORD  MemberIndex,                                     //Input: "Index" of the device you are interested in getting the path for.
                PSP_DEVICE_INTERFACE_DATA  DeviceInterfaceData);//Output: This function fills in an "SP_DEVICE_INTERFACE_DATA" structure.

        //SetupDiDestroyDeviceInfoList() frees up memory by destroying a DeviceInfoList
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiDestroyDeviceInfoList", CallingConvention=CallingConvention::Winapi)]
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiDestroyDeviceInfoListUM(                     
                HDEVINFO  DeviceInfoSet);                       //Input: Give it a handle to a device info list to deallocate from RAM.

        //SetupDiEnumDeviceInfo() fills in an "SP_DEVINFO_DATA" structure, which we need for SetupDiGetDeviceRegistryProperty()
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiEnumDeviceInfo", CallingConvention=CallingConvention::Winapi)]
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiEnumDeviceInfoUM(
                HDEVINFO  DeviceInfoSet,
                DWORD  MemberIndex,
                PSP_DEVINFO_DATA  DeviceInfoData);

        //SetupDiGetDeviceRegistryProperty() gives us the hardware ID, which we use to check to see if it has matching VID/PID
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetDeviceRegistryProperty", CallingConvention=CallingConvention::Winapi)]
        extern "C"      WINSETUPAPI BOOL WINAPI  SetupDiGetDeviceRegistryPropertyUM(
                HDEVINFO  DeviceInfoSet,
                PSP_DEVINFO_DATA  DeviceInfoData,
                DWORD  Property,
                PDWORD  PropertyRegDataType,
                PBYTE  PropertyBuffer,   
                DWORD  PropertyBufferSize,  
                PDWORD  RequiredSize);

        //SetupDiGetDeviceInterfaceDetail() gives us a device path, which is needed before CreateFile() can be used.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetDeviceInterfaceDetail", CallingConvention=CallingConvention::Winapi)]
        extern "C" BOOL SetupDiGetDeviceInterfaceDetailUM(
                HDEVINFO DeviceInfoSet,                                                                         //Input: Wants HDEVINFO which can be obtained from SetupDiGetClassDevs()
                PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,                          //Input: Pointer to an structure which defines the device interface.  
                PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData,     //Output: Pointer to a strucutre, which will contain the device path.
                DWORD DeviceInterfaceDetailDataSize,                                            //Input: Number of bytes to retrieve.
                PDWORD RequiredSize,                                                                            //Output (optional): Te number of bytes needed to hold the entire struct 
                PSP_DEVINFO_DATA DeviceInfoData);                                                       //Output


//  Variables that need to have wide scope.
        HANDLE WriteHandle = INVALID_HANDLE_VALUE;      //Need to get a write "handle" to our device before we can write to it.
        HANDLE ReadHandle = INVALID_HANDLE_VALUE;       //Need to get a read "handle" to our device before we can read from it.
//-------------------------------------------------------END CUT AND PASTE BLOCK-------------------------------------------------------------------------------------


        //グローバル変数定義 
        unsigned int ADCValue;
        DWORD BytesWritten = 0;
        DWORD BytesRead = 0;
        unsigned char OutputPacketBuffer[65];   //Allocate a memory buffer equal to our endpoint size + 1
        unsigned char InputPacketBuffer[65];

        /// <summary>
        /// Form1 の概要
        /// </summary>
        public ref class Form1 : public System::Windows::Forms::Form
        {
        public:
                Form1(void)
                {
                        InitializeComponent();  //
                //      ovalShape1->FillStyle = FillStyle.Solid;        //サポートされていない    //プロパティでFillStyle = Solidを設定する
                                                                                                                //C#のovalShape1.FillStyle = FillStyle.Solid;はサポートされている
                        

                        ovalShape1->FillColor = Color::Gray;    //灰色で塗りつぶし
                        ovalShape2->FillColor = Color::Gray;
                        ovalShape3->FillColor = Color::Gray;
                }

        protected:
                /// <summary>
                /// 使用中のリソースをすべてクリーンアップします。
                /// </summary>
                ~Form1()
                {
                        if (components)
                        {
                                delete components;
                        }
                }
        private: System::Windows::Forms::Button^  ConnectBtn;
        protected: 

        protected: 
        private: System::Windows::Forms::Label^  label1;
        private: System::Windows::Forms::TextBox^  textBox1;
        private: System::Windows::Forms::TextBox^  textBox2;
        private: System::Windows::Forms::Timer^  timer1;
        private: Microsoft::VisualBasic::PowerPacks::ShapeContainer^  shapeContainer1;
        private: Microsoft::VisualBasic::PowerPacks::OvalShape^  ovalShape3;
        private: Microsoft::VisualBasic::PowerPacks::OvalShape^  ovalShape2;
        private: Microsoft::VisualBasic::PowerPacks::OvalShape^  ovalShape1;
        private: System::Windows::Forms::Label^  label2;
        private: System::Windows::Forms::Label^  label3;
        private: System::Windows::Forms::TextBox^  textBox3;
        private: System::Windows::Forms::TextBox^  textBox4;
        private: System::Windows::Forms::Label^  label4;
        private: System::Windows::Forms::Label^  label5;
        private: System::Windows::Forms::Label^  label6;
        private: System::ComponentModel::IContainer^  components;

        private:
                /// <summary>
                /// 必要なデザイナー変数です。
                /// </summary>


#pragma region Windows Form Designer generated code
                /// <summary>
                /// デザイナー サポートに必要なメソッドです。このメソッドの内容を
                /// コード エディターで変更しないでください。
                /// </summary>
                void InitializeComponent(void)
                {
                        this->components = (gcnew System::ComponentModel::Container());
                        this->ConnectBtn = (gcnew System::Windows::Forms::Button());
                        this->label1 = (gcnew System::Windows::Forms::Label());
                        this->textBox1 = (gcnew System::Windows::Forms::TextBox());
                        this->textBox2 = (gcnew System::Windows::Forms::TextBox());
                        this->timer1 = (gcnew System::Windows::Forms::Timer(this->components));
                        this->shapeContainer1 = (gcnew Microsoft::VisualBasic::PowerPacks::ShapeContainer());
                        this->ovalShape3 = (gcnew Microsoft::VisualBasic::PowerPacks::OvalShape());
                        this->ovalShape2 = (gcnew Microsoft::VisualBasic::PowerPacks::OvalShape());
                        this->ovalShape1 = (gcnew Microsoft::VisualBasic::PowerPacks::OvalShape());
                        this->label2 = (gcnew System::Windows::Forms::Label());
                        this->label3 = (gcnew System::Windows::Forms::Label());
                        this->textBox3 = (gcnew System::Windows::Forms::TextBox());
                        this->textBox4 = (gcnew System::Windows::Forms::TextBox());
                        this->label4 = (gcnew System::Windows::Forms::Label());
                        this->label5 = (gcnew System::Windows::Forms::Label());
                        this->label6 = (gcnew System::Windows::Forms::Label());
                        this->SuspendLayout();
                        // 
                        // ConnectBtn
                        // 
                        this->ConnectBtn->Location = System::Drawing::Point(24, 27);
                        this->ConnectBtn->Name = L"ConnectBtn";
                        this->ConnectBtn->Size = System::Drawing::Size(88, 40);
                        this->ConnectBtn->TabIndex = 0;
                        this->ConnectBtn->Text = L"接続";
                        this->ConnectBtn->UseVisualStyleBackColor = true;
                        this->ConnectBtn->Click += gcnew System::EventHandler(this, &Form1::ConnectBtn_Click);
                        // 
                        // label1
                        // 
                        this->label1->AutoSize = true;
                        this->label1->Location = System::Drawing::Point(77, 176);
                        this->label1->Name = L"label1";
                        this->label1->Size = System::Drawing::Size(35, 15);
                        this->label1->TabIndex = 1;
                        this->label1->Text = L"SW1";
                        // 
                        // textBox1
                        // 
                        this->textBox1->Location = System::Drawing::Point(152, 37);
                        this->textBox1->Name = L"textBox1";
                        this->textBox1->Size = System::Drawing::Size(100, 22);
                        this->textBox1->TabIndex = 2;
                        // 
                        // textBox2
                        // 
                        this->textBox2->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 13.8F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
                                static_cast<System::Byte>(128)));
                        this->textBox2->Location = System::Drawing::Point(43, 224);
                        this->textBox2->Name = L"textBox2";
                        this->textBox2->Size = System::Drawing::Size(100, 30);
                        this->textBox2->TabIndex = 3;
                        // 
                        // timer1
                        // 
                        this->timer1->Tick += gcnew System::EventHandler(this, &Form1::timer1_Tick);
                        // 
                        // shapeContainer1
                        // 
                        this->shapeContainer1->Location = System::Drawing::Point(0, 0);
                        this->shapeContainer1->Margin = System::Windows::Forms::Padding(0);
                        this->shapeContainer1->Name = L"shapeContainer1";
                        this->shapeContainer1->Shapes->AddRange(gcnew cli::array< Microsoft::VisualBasic::PowerPacks::Shape^  >(3) {this->ovalShape3, 
                                this->ovalShape2, this->ovalShape1});
                        this->shapeContainer1->Size = System::Drawing::Size(526, 313);
                        this->shapeContainer1->TabIndex = 4;
                        this->shapeContainer1->TabStop = false;
                        // 
                        // ovalShape3
                        // 
                        this->ovalShape3->FillStyle = Microsoft::VisualBasic::PowerPacks::FillStyle::Solid;
                        this->ovalShape3->Location = System::Drawing::Point(393, 95);
                        this->ovalShape3->Name = L"ovalShape3";
                        this->ovalShape3->Size = System::Drawing::Size(65, 65);
                        // 
                        // ovalShape2
                        // 
                        this->ovalShape2->FillStyle = Microsoft::VisualBasic::PowerPacks::FillStyle::Solid;
                        this->ovalShape2->Location = System::Drawing::Point(235, 97);
                        this->ovalShape2->Name = L"ovalShape2";
                        this->ovalShape2->Size = System::Drawing::Size(65, 65);
                        // 
                        // ovalShape1
                        // 
                        this->ovalShape1->FillStyle = Microsoft::VisualBasic::PowerPacks::FillStyle::Solid;
                        this->ovalShape1->Location = System::Drawing::Point(55, 94);
                        this->ovalShape1->Name = L"ovalShape1";
                        this->ovalShape1->Size = System::Drawing::Size(65, 65);
                        // 
                        // label2
                        // 
                        this->label2->AutoSize = true;
                        this->label2->Location = System::Drawing::Point(256, 176);
                        this->label2->Name = L"label2";
                        this->label2->Size = System::Drawing::Size(35, 15);
                        this->label2->TabIndex = 5;
                        this->label2->Text = L"SW2";
                        // 
                        // label3
                        // 
                        this->label3->AutoSize = true;
                        this->label3->Location = System::Drawing::Point(408, 176);
                        this->label3->Name = L"label3";
                        this->label3->Size = System::Drawing::Size(35, 15);
                        this->label3->TabIndex = 6;
                        this->label3->Text = L"SW3";
                        // 
                        // textBox3
                        // 
                        this->textBox3->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 13.8F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
                                static_cast<System::Byte>(128)));
                        this->textBox3->Location = System::Drawing::Point(213, 224);
                        this->textBox3->Name = L"textBox3";
                        this->textBox3->Size = System::Drawing::Size(100, 30);
                        this->textBox3->TabIndex = 7;
                        // 
                        // textBox4
                        // 
                        this->textBox4->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 13.8F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
                                static_cast<System::Byte>(128)));
                        this->textBox4->Location = System::Drawing::Point(387, 224);
                        this->textBox4->Name = L"textBox4";
                        this->textBox4->Size = System::Drawing::Size(100, 30);
                        this->textBox4->TabIndex = 8;
                        // 
                        // label4
                        // 
                        this->label4->AutoSize = true;
                        this->label4->Location = System::Drawing::Point(79, 269);
                        this->label4->Name = L"label4";
                        this->label4->Size = System::Drawing::Size(33, 15);
                        this->label4->TabIndex = 9;
                        this->label4->Text = L"VR1";
                        // 
                        // label5
                        // 
                        this->label5->AutoSize = true;
                        this->label5->Location = System::Drawing::Point(256, 269);
                        this->label5->Name = L"label5";
                        this->label5->Size = System::Drawing::Size(33, 15);
                        this->label5->TabIndex = 10;
                        this->label5->Text = L"VR2";
                        // 
                        // label6
                        // 
                        this->label6->AutoSize = true;
                        this->label6->Location = System::Drawing::Point(422, 269);
                        this->label6->Name = L"label6";
                        this->label6->Size = System::Drawing::Size(33, 15);
                        this->label6->TabIndex = 11;
                        this->label6->Text = L"VR3";
                        // 
                        // Form1
                        // 
                        this->AutoScaleDimensions = System::Drawing::SizeF(8, 15);
                        this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
                        this->ClientSize = System::Drawing::Size(526, 313);
                        this->Controls->Add(this->label6);
                        this->Controls->Add(this->label5);
                        this->Controls->Add(this->label4);
                        this->Controls->Add(this->textBox4);
                        this->Controls->Add(this->textBox3);
                        this->Controls->Add(this->label3);
                        this->Controls->Add(this->label2);
                        this->Controls->Add(this->textBox2);
                        this->Controls->Add(this->textBox1);
                        this->Controls->Add(this->label1);
                        this->Controls->Add(this->ConnectBtn);
                        this->Controls->Add(this->shapeContainer1);
                        this->Name = L"Form1";
                        this->Text = L"Form1";
                        this->ResumeLayout(false);
                        this->PerformLayout();

                }
#pragma endregion
        private: System::Void ConnectBtn_Click(System::Object^  sender, System::EventArgs^  e) 
                         {
                                 
//-------------------------------------------------------BEGIN CUT AND PASTE BLOCK-----------------------------------------------------------------------------------
                /* 
                Before we can "connect" our application to our USB embedded device, we must first find the device.
                A USB bus can have many devices simultaneously connected, so somehow we have to find our device, and only
                our device.  This is done with the Vendor ID (VID) and Product ID (PID).  Each USB product line should have
                a unique combination of VID and PID.  

                Microsoft has created a number of functions which are useful for finding plug and play devices.  Documentation
                for each function used can be found in the MSDN library.  We will be using the following functions:

                SetupDiGetClassDevs()                                   //provided by setupapi.dll, which comes with Windows
                SetupDiEnumDeviceInterfaces()                   //provided by setupapi.dll, which comes with Windows
                GetLastError()                                                  //provided by kernel32.dll, which comes with Windows
                SetupDiDestroyDeviceInfoList()                  //provided by setupapi.dll, which comes with Windows
                SetupDiGetDeviceInterfaceDetail()               //provided by setupapi.dll, which comes with Windows
                SetupDiGetDeviceRegistryProperty()              //provided by setupapi.dll, which comes with Windows
                malloc()                                                                //part of C runtime library, msvcrt.dll?
                CreateFile()                                                    //provided by kernel32.dll, which comes with Windows

                We will also be using the following unusual data types and structures.  Documentation can also be found in
                the MSDN library:

                PSP_DEVICE_INTERFACE_DATA
                PSP_DEVICE_INTERFACE_DETAIL_DATA
                SP_DEVINFO_DATA
                HDEVINFO
                HANDLE
                GUID

                The ultimate objective of the following code is to call CreateFile(), which opens a communications
                pipe to a specific device (such as a HID class USB device endpoint).  CreateFile() returns a "handle" 
                which is needed later when calling ReadFile() or WriteFile().  These functions are used to actually 
                send and receive application related data to/from the USB peripheral device.

                However, in order to call CreateFile(), we first need to get the device path for the USB device
                with the correct VID and PID.  Getting the device path is a multi-step round about process, which
                requires calling several of the SetupDixxx() functions provided by setupapi.dll.
                */


                //Globally Unique Identifier (GUID) for HID class devices.  Windows uses GUIDs to identify things.
                GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}; 

                HDEVINFO DeviceInfoTable = INVALID_HANDLE_VALUE;
                PSP_DEVICE_INTERFACE_DATA InterfaceDataStructure = new SP_DEVICE_INTERFACE_DATA;
                PSP_DEVICE_INTERFACE_DETAIL_DATA DetailedInterfaceDataStructure = new SP_DEVICE_INTERFACE_DETAIL_DATA;
                SP_DEVINFO_DATA DevInfoData;

                DWORD InterfaceIndex = 0;
                DWORD StatusLastError = 0;
                DWORD dwRegType;
                DWORD dwRegSize;
                DWORD StructureSize = 0;
                PBYTE PropertyValueBuffer;
                bool MatchFound = false;
                DWORD ErrorStatus;

                String^ DeviceIDToFind = MY_DEVICE_ID;

                //First populate a list of plugged in devices (by specifying "DIGCF_PRESENT"), which are of the specified class GUID. 
                DeviceInfoTable = SetupDiGetClassDevsUM(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

                //Now look through the list we just populated.  We are trying to see if any of them match our device. 
                while(true)
                {
                        InterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
                        if(SetupDiEnumDeviceInterfacesUM(DeviceInfoTable, NULL, &InterfaceClassGuid, InterfaceIndex, InterfaceDataStructure))
                        {
                                ErrorStatus = GetLastError();
                                if(ERROR_NO_MORE_ITEMS == ErrorStatus)  //Did we reach the end of the list of matching devices in the DeviceInfoTable?
                                {       //Cound not find the device.  Must not have been attached.
                                        SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                        return;         
                                }
                        }
                        else    //Else some other kind of unknown error ocurred...
                        {
                                ErrorStatus = GetLastError();
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                return; 
                        }

                        //Now retrieve the hardware ID from the registry.  The hardware ID contains the VID and PID, which we will then 
                        //check to see if it is the correct device or not.

                        //Initialize an appropriate SP_DEVINFO_DATA structure.  We need this structure for SetupDiGetDeviceRegistryProperty().
                        DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
                        SetupDiEnumDeviceInfoUM(DeviceInfoTable, InterfaceIndex, &DevInfoData);

                        //First query for the size of the hardware ID, so we can know how big a buffer to allocate for the data.
                        SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, NULL, 0, &dwRegSize);

                        //Allocate a buffer for the hardware ID.
                        PropertyValueBuffer = (BYTE *) malloc (dwRegSize);
                        if(PropertyValueBuffer == NULL) //if null, error, couldn't allocate enough memory
                        {       //Can't really recover from this situation, just exit instead.
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                return;         
                        }

                        //Retrieve the hardware IDs for the current device we are looking at.  PropertyValueBuffer gets filled with a 
                        //REG_MULTI_SZ (array of null terminated strings).  To find a device, we only care about the very first string in the
                        //buffer, which will be the "device ID".  The device ID is a string which contains the VID and PID, in the example 
                        //format "Vid_04d8&Pid_003f".
                        SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, PropertyValueBuffer, dwRegSize, NULL);

                        //Now check if the first string in the hardware ID matches the device ID of my USB device.
                        #ifdef UNICODE
                        String^ DeviceIDFromRegistry = gcnew String((wchar_t *)PropertyValueBuffer);
                        #else
                        String^ DeviceIDFromRegistry = gcnew String((char *)PropertyValueBuffer);
                        #endif

                        free(PropertyValueBuffer);              //No longer need the PropertyValueBuffer, free the memory to prevent potential memory leaks
                        textBox1->Text = "Searching Device!";
                        //Convert both strings to lower case.  This makes the code more robust/portable accross OS Versions
                        DeviceIDFromRegistry = DeviceIDFromRegistry->ToLowerInvariant();        
                        DeviceIDToFind = DeviceIDToFind->ToLowerInvariant();                            
                        //Now check if the hardware ID we are looking at contains the correct VID/PID
                        MatchFound = DeviceIDFromRegistry->Contains(DeviceIDToFind);            
                        if(MatchFound == true)
                        {
                                //Device must have been found.  Open read and write handles.  In order to do this, we will need the actual device path first.
                                //We can get the path by calling SetupDiGetDeviceInterfaceDetail(), however, we have to call this function twice:  The first
                                //time to get the size of the required structure/buffer to hold the detailed interface data, then a second time to actually 
                                //get the structure (after we have allocated enough memory for the structure.)
                                DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                                //First call populates "StructureSize" with the correct value
                                SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, NULL, NULL, &StructureSize, NULL);   
                                DetailedInterfaceDataStructure = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(malloc(StructureSize));             //Allocate enough memory
                                if(DetailedInterfaceDataStructure == NULL)      //if null, error, couldn't allocate enough memory
                                {       //Can't really recover from this situation, just exit instead.
                                        SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                        return;         
                                }
                                DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                                 //Now call SetupDiGetDeviceInterfaceDetail() a second time to receive the goods.  
                                SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, DetailedInterfaceDataStructure, StructureSize, NULL, NULL); 

                                //We now have the proper device path, and we can finally open read and write handles to the device.
                                //We store the handles in the global variables "WriteHandle" and "ReadHandle", which we will use later to actually communicate.
                                WriteHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);

                                ErrorStatus = GetLastError();
                                if(ErrorStatus == ERROR_SUCCESS)
                                        textBox1->Text = "Write Enabled.";                              //Make button no longer greyed out
                                ReadHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
                                ErrorStatus = GetLastError();
                                if(ErrorStatus == ERROR_SUCCESS)
                                {
                                        textBox1->Text = "Read Enabled.";                                       //Make label no longer greyed out
                                }
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                               
                                //追加修正部
                                OutputPacketBuffer[0] = 0;                                                      // Report ID  
                                OutputPacketBuffer[1] = 0x30;                                           // 接続確認 
                                
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);

                                if((InputPacketBuffer[3] == 0x4F)&&(InputPacketBuffer[4] == 0x4B))
                                        textBox1->Text = "接続完了!";                               // 接続正常完了

                                //タイマ1スタート
                                timer1->Interval = 100; //インターバル時間:100msec
                                timer1->Enabled = TRUE;
                                return;
                        }

                        InterfaceIndex++;       
                        //Keep looping until we either find a device with matching VID and PID, or until we run out of items.
                }//end of while(true)   
//-------------------------------------------------------END CUT AND PASTE BLOCK-------------------------------------------------------------------------------------


                         }

        private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e)       //インターバルタイマ     //100msec
                         {

                                unsigned int ADCValue;
                                double Volt;

                                //可変抵抗器出力電圧のAD変換値 読込
                
                                OutputPacketBuffer[0] = 0;                                      // Report ID  
                                OutputPacketBuffer[1] = 0x33;                           // 可変抵抗器outのAD変換値読込


                                OutputPacketBuffer[2] = 0x31;                           // VR1
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
                                ADCValue = (InputPacketBuffer[4] * 256) + InputPacketBuffer[3];
                                Volt = (ADCValue * 5.0) / 1024;
                                textBox2->Text = String::Format("{0:F2} [V]",Volt);             //小数点以下2桁にして表示


                                OutputPacketBuffer[2] = 0x32;                           // VR2
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
                                ADCValue = (InputPacketBuffer[4] * 256) + InputPacketBuffer[3];
                                Volt = (ADCValue * 5.0) / 1024;
                                textBox3->Text = String::Format("{0:F2} [V]",Volt);             //小数点以下2桁にして表示


                
                                OutputPacketBuffer[2] = 0x33;                           // VR3
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);      
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
                                ADCValue = (InputPacketBuffer[4] * 256) + InputPacketBuffer[3];
                                Volt = (ADCValue * 5.0) / 1024;
                                textBox4->Text = String::Format("{0:F2} [V]",Volt);             //小数点以下2桁にして表示


                                //スイッチの状態読込
                                
                                OutputPacketBuffer[0] = 0;                                      // Report ID  
                                OutputPacketBuffer[1] = 0x32;                           // SW状態要求コマンド

                                OutputPacketBuffer[2] = 0x31;                           // SW1
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);

                                if(InputPacketBuffer[3] == 0x30)                        // オンか? 
                                        ovalShape1->FillColor = Color::Orange;  //ON ならオレンジ色
                                else
                                        ovalShape1->FillColor = Color::Gray;            // OFFなら灰色


                                OutputPacketBuffer[2] = 0x32;                           // SW2
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);

                                if(InputPacketBuffer[3] == 0x30)                        // オンか? 
                                        ovalShape2->FillColor = Color::Orange;  //ON ならオレンジ色
                                else
                                        ovalShape2->FillColor = Color::Gray;            // OFFなら灰色



                                
                                OutputPacketBuffer[2] = 0x33;                           // SW3
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);

                                if(InputPacketBuffer[3] == 0x30)                        // オンか? 
                                        ovalShape3->FillColor = Color::Orange;  //ON ならオレンジ色
                                else
                                        ovalShape3->FillColor = Color::Gray;            // OFFなら灰色






                        }

                
};
}

 


<実行結果>
 ・接続ボタンをクリックしてUSB接続をした後に スイッチボタンSW1とSW3を押した時のPCのフォーム画面です。
 ・ovalShapeがオレンジ色になっているスイッチはON状態をあらわし、灰色はOFF状態の場合です。
 ・テキストボックスに表示されている値は、PIC18F14K50が読み込んだ電圧値で、小数点以下2桁で表示されています。

  









 PIC32MX795F512L HIDクラス LED点灯/消灯、ADコンバータ読込・表示
 <試作品仕様>
  ・PCとPIC間のUSB通信はHIDクラスとする。
  ・PC(Windows)上のボタンスイッチ×4個をクリックすると PIC32MX795F512Lのキバン上の対応するLEDがON/OFFすること
  ・PCとPIC間のUSB通信はHIDクラスとする。
  ・ボタンスイッチはLEDがONしているときは赤色、OFFの時は灰色とする。
  ・USB通信ONのボタンボタンスイッチをフォーム上にもうけること。 またUSB通信が確立したら”接続完了!”の文字をテキストボックスに表示のこと
  ・PIC32MX795F512Lのキバン上のスイッチ×3個を押すと PC(Windows)上の対応するovalShape×3個の色が 灰色→オレンジ色に変わること
  ・可変抵抗器により設定される電圧をPIC32MX795F512L内蔵ADコンバータで読込、この電圧値[V]をPC上のテキストボックスに表示のこと。
  ・テキストボックスに表示される電圧[V]は、小数点以下2桁とする。
  ・USB通信ONのボタンボタンスイッチをフォーム上にもうけること。 またUSB通信が確立したら”接続完了!”の文字をテキストボックスに表示のこと

 ★ PIC側のハードとソフトは こちらを参照願います 
        

     

          

   <プログラム例>

//Form1.h


#pragma once
//Includes
#include <Windows.h>    //Definitions for various common and not so common types like DWORD, PCHAR, HANDLE, etc.
#include <setupapi.h>   //From Platform SDK. Definitions needed for the SetupDixxx() functions, which we use to
                                                //find our plug and play device.

//Modify this value to match the VID and PID in your USB device descriptor.
//Use the formatting: "Vid_xxxx&Pid_xxxx" where xxxx is a 16-bit hexadecimal number.
#define MY_DEVICE_ID  "Vid_04d8&Pid_003F"               //VID = 0x04D8  PID = 0x003F    





namespace CWhiteForm {

        using namespace System;
        using namespace System::ComponentModel;
        using namespace System::Collections;
        using namespace System::Windows::Forms;
        using namespace System::Data;
        using namespace System::Drawing;


//-------------------------------------------------------BEGIN CUT AND PASTE BLOCK-----------------------------------------------------------------------------------
        using namespace System::Runtime::InteropServices;  //Need this to support "unmanaged" code.

        /*
        In order to use these unmanaged functions from within the managed .NET environment, we need
        to explicitly import the functions which we will be using from other .DLL file(s).  Simply
        including the appropriate header files is not enough. 

        Note: In order to avoid potential name conflicts in the header files (which we still use),
        I have renamed the functions by adding "UM" (unmanaged) onto the end of them.  To find 
        documentation for the functions in MSDN, search for the function name without the extra 
        "UM" attached.
        Note2: In the header files (such as setupapi.h), normally the function names are 
        remapped, depending upon if UNICODE is defined or not.  For example, two versions of the
        function SetupDiGetDeviceInterfaceDetail() exist.  One for UNICODE, and one for ANSI.  
        If the wrong version of the function is called, things won't work correctly.  Therefore,
        in order to make sure the correct one gets called (based on your compiler settings, which
        may or may not define "UNICODE"), it is useful to explicity specify the CharSet when doing
        the DLL import.
        */

        #ifdef UNICODE
        #define Seeifdef        Unicode
        #else
        #define Seeifdef        Ansi
        #endif


        //使用するDLL関数の宣言
        //Returns a HDEVINFO type for a device information set (USB HID devices in
        //our case).  We will need the HDEVINFO as in input parameter for calling many of
        //the other SetupDixxx() functions.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetClassDevs", CallingConvention=CallingConvention::Winapi)]                
        extern "C" HDEVINFO  SetupDiGetClassDevsUM(
                LPGUID  ClassGuid,                                      //Input: Supply the class GUID here. 
                PCTSTR  Enumerator,                                     //Input: Use NULL here, not important for our purposes
                HWND  hwndParent,                                       //Input: Use NULL here, not important for our purposes
                DWORD  Flags);                                          //Input: Flags describing what kind of filtering to use.

        //Gives us "PSP_DEVICE_INTERFACE_DATA" which contains the Interface specific GUID (different
        //from class GUID).  We need the interface GUID to get the device path.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiEnumDeviceInterfaces", CallingConvention=CallingConvention::Winapi)]                                
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiEnumDeviceInterfacesUM(
                HDEVINFO  DeviceInfoSet,                        //Input: Give it the HDEVINFO we got from SetupDiGetClassDevs()
                PSP_DEVINFO_DATA  DeviceInfoData,       //Input (optional)
                LPGUID  InterfaceClassGuid,                     //Input 
                DWORD  MemberIndex,                                     //Input: "Index" of the device you are interested in getting the path for.
                PSP_DEVICE_INTERFACE_DATA  DeviceInterfaceData);//Output: This function fills in an "SP_DEVICE_INTERFACE_DATA" structure.

        //SetupDiDestroyDeviceInfoList() frees up memory by destroying a DeviceInfoList
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiDestroyDeviceInfoList", CallingConvention=CallingConvention::Winapi)]
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiDestroyDeviceInfoListUM(                     
                HDEVINFO  DeviceInfoSet);                       //Input: Give it a handle to a device info list to deallocate from RAM.

        //SetupDiEnumDeviceInfo() fills in an "SP_DEVINFO_DATA" structure, which we need for SetupDiGetDeviceRegistryProperty()
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiEnumDeviceInfo", CallingConvention=CallingConvention::Winapi)]
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiEnumDeviceInfoUM(
                HDEVINFO  DeviceInfoSet,
                DWORD  MemberIndex,
                PSP_DEVINFO_DATA  DeviceInfoData);

        //SetupDiGetDeviceRegistryProperty() gives us the hardware ID, which we use to check to see if it has matching VID/PID
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetDeviceRegistryProperty", CallingConvention=CallingConvention::Winapi)]
        extern "C"      WINSETUPAPI BOOL WINAPI  SetupDiGetDeviceRegistryPropertyUM(
                HDEVINFO  DeviceInfoSet,
                PSP_DEVINFO_DATA  DeviceInfoData,
                DWORD  Property,
                PDWORD  PropertyRegDataType,
                PBYTE  PropertyBuffer,   
                DWORD  PropertyBufferSize,  
                PDWORD  RequiredSize);

        //SetupDiGetDeviceInterfaceDetail() gives us a device path, which is needed before CreateFile() can be used.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetDeviceInterfaceDetail", CallingConvention=CallingConvention::Winapi)]
        extern "C" BOOL SetupDiGetDeviceInterfaceDetailUM(
                HDEVINFO DeviceInfoSet,                                                                         //Input: Wants HDEVINFO which can be obtained from SetupDiGetClassDevs()
                PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,                          //Input: Pointer to an structure which defines the device interface.  
                PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData,     //Output: Pointer to a strucutre, which will contain the device path.
                DWORD DeviceInterfaceDetailDataSize,                                            //Input: Number of bytes to retrieve.
                PDWORD RequiredSize,                                                                            //Output (optional): Te number of bytes needed to hold the entire struct 
                PSP_DEVINFO_DATA DeviceInfoData);                                                       //Output


//  Variables that need to have wide scope.
        HANDLE WriteHandle = INVALID_HANDLE_VALUE;      //Need to get a write "handle" to our device before we can write to it.
        HANDLE ReadHandle = INVALID_HANDLE_VALUE;       //Need to get a read "handle" to our device before we can read from it.
//-------------------------------------------------------END CUT AND PASTE BLOCK-------------------------------------------------------------------------------------

        //グローバル変数定義 
        int Led0Mode = 0,       // LedMode = 0; 消灯 1:点灯
                Led1Mode = 0,   // Led1Mode = 0; 消灯 1:点灯
                Led2Mode = 0,   // Led2Mode = 0; 消灯 1:点灯
                Led3Mode = 0;   // Lee3Mode = 0; 消灯 1:点灯        

        
        DWORD BytesWritten = 0;
        DWORD BytesRead = 0;
        unsigned char OutputPacketBuffer[65];   //Allocate a memory buffer equal to our endpoint size + 1
        unsigned char InputPacketBuffer[65];



        /// <summary>
        /// Form1 の概要
        /// </summary>
        public ref class Form1 : public System::Windows::Forms::Form
        {
        public:
                Form1(void)
                {
                        InitializeComponent();
                        //
                        //TODO: ここにコンストラクター コードを追加します
                        //
                }

        protected:
                /// <summary>
                /// 使用中のリソースをすべてクリーンアップします。
                /// </summary>
                ~Form1()
                {
                        if (components)
                        {
                                delete components;
                        }
                }
        private: System::Windows::Forms::GroupBox^  groupBox1;
        private: System::Windows::Forms::Button^  Led0Btn;
        protected: 

        private: System::Windows::Forms::Button^  ConnectBtn;
        private: System::Windows::Forms::TextBox^  textBox1;
        private: System::Windows::Forms::Button^  Led1Btn;
        private: System::Windows::Forms::Button^  Led2Btn;
        private: System::Windows::Forms::Button^  Led3Btn;
        private: System::Windows::Forms::GroupBox^  groupBox2;
        private: System::Windows::Forms::Label^  label3;
        private: System::Windows::Forms::Label^  label2;
        private: System::Windows::Forms::Label^  label1;
        private: Microsoft::VisualBasic::PowerPacks::ShapeContainer^  shapeContainer1;
        private: Microsoft::VisualBasic::PowerPacks::OvalShape^  ovalShape3;
        private: Microsoft::VisualBasic::PowerPacks::OvalShape^  ovalShape2;
        private: Microsoft::VisualBasic::PowerPacks::OvalShape^  ovalShape1;
        private: System::Windows::Forms::Timer^  timer1;
        private: System::Windows::Forms::GroupBox^  groupBox3;
        private: System::Windows::Forms::TextBox^  textBox2;
        private: System::ComponentModel::IContainer^  components;

        private:
                /// <summary>
                /// 必要なデザイナー変数です。
                /// </summary>


#pragma region Windows Form Designer generated code
                /// <summary>
                /// デザイナー サポートに必要なメソッドです。このメソッドの内容を
                /// コード エディターで変更しないでください。
                /// </summary>
                void InitializeComponent(void)
                {
                        this->components = (gcnew System::ComponentModel::Container());
                        this->groupBox1 = (gcnew System::Windows::Forms::GroupBox());
                        this->Led3Btn = (gcnew System::Windows::Forms::Button());
                        this->Led2Btn = (gcnew System::Windows::Forms::Button());
                        this->Led1Btn = (gcnew System::Windows::Forms::Button());
                        this->Led0Btn = (gcnew System::Windows::Forms::Button());
                        this->ConnectBtn = (gcnew System::Windows::Forms::Button());
                        this->textBox1 = (gcnew System::Windows::Forms::TextBox());
                        this->groupBox2 = (gcnew System::Windows::Forms::GroupBox());
                        this->label3 = (gcnew System::Windows::Forms::Label());
                        this->label2 = (gcnew System::Windows::Forms::Label());
                        this->label1 = (gcnew System::Windows::Forms::Label());
                        this->shapeContainer1 = (gcnew Microsoft::VisualBasic::PowerPacks::ShapeContainer());
                        this->ovalShape3 = (gcnew Microsoft::VisualBasic::PowerPacks::OvalShape());
                        this->ovalShape2 = (gcnew Microsoft::VisualBasic::PowerPacks::OvalShape());
                        this->ovalShape1 = (gcnew Microsoft::VisualBasic::PowerPacks::OvalShape());
                        this->timer1 = (gcnew System::Windows::Forms::Timer(this->components));
                        this->groupBox3 = (gcnew System::Windows::Forms::GroupBox());
                        this->textBox2 = (gcnew System::Windows::Forms::TextBox());
                        this->groupBox1->SuspendLayout();
                        this->groupBox2->SuspendLayout();
                        this->groupBox3->SuspendLayout();
                        this->SuspendLayout();
                        // 
                        // groupBox1
                        // 
                        this->groupBox1->BackColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(0)), static_cast<System::Int32>(static_cast<System::Byte>(192)), 
                                static_cast<System::Int32>(static_cast<System::Byte>(192)));
                        this->groupBox1->Controls->Add(this->Led3Btn);
                        this->groupBox1->Controls->Add(this->Led2Btn);
                        this->groupBox1->Controls->Add(this->Led1Btn);
                        this->groupBox1->Controls->Add(this->Led0Btn);
                        this->groupBox1->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 10.2F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
                                static_cast<System::Byte>(128)));
                        this->groupBox1->Location = System::Drawing::Point(24, 63);
                        this->groupBox1->Name = L"groupBox1";
                        this->groupBox1->Size = System::Drawing::Size(501, 122);
                        this->groupBox1->TabIndex = 0;
                        this->groupBox1->TabStop = false;
                        this->groupBox1->Text = L"LED OnOff照光スイッチ";
                        // 
                        // Led3Btn
                        // 
                        this->Led3Btn->Location = System::Drawing::Point(347, 44);
                        this->Led3Btn->Name = L"Led3Btn";
                        this->Led3Btn->Size = System::Drawing::Size(105, 57);
                        this->Led3Btn->TabIndex = 3;
                        this->Led3Btn->Text = L"LED3";
                        this->Led3Btn->UseVisualStyleBackColor = true;
                        this->Led3Btn->Click += gcnew System::EventHandler(this, &Form1::Led3Btn_Click);
                        // 
                        // Led2Btn
                        // 
                        this->Led2Btn->Location = System::Drawing::Point(236, 44);
                        this->Led2Btn->Name = L"Led2Btn";
                        this->Led2Btn->Size = System::Drawing::Size(105, 57);
                        this->Led2Btn->TabIndex = 2;
                        this->Led2Btn->Text = L"LED2";
                        this->Led2Btn->UseVisualStyleBackColor = true;
                        this->Led2Btn->Click += gcnew System::EventHandler(this, &Form1::Led2Btn_Click);
                        // 
                        // Led1Btn
                        // 
                        this->Led1Btn->Location = System::Drawing::Point(125, 44);
                        this->Led1Btn->Name = L"Led1Btn";
                        this->Led1Btn->Size = System::Drawing::Size(105, 57);
                        this->Led1Btn->TabIndex = 1;
                        this->Led1Btn->Text = L"LED1";
                        this->Led1Btn->UseVisualStyleBackColor = true;
                        this->Led1Btn->Click += gcnew System::EventHandler(this, &Form1::Led1Btn_Click);
                        // 
                        // Led0Btn
                        // 
                        this->Led0Btn->Location = System::Drawing::Point(15, 44);
                        this->Led0Btn->Name = L"Led0Btn";
                        this->Led0Btn->Size = System::Drawing::Size(104, 57);
                        this->Led0Btn->TabIndex = 0;
                        this->Led0Btn->Text = L"LED0";
                        this->Led0Btn->UseVisualStyleBackColor = true;
                        this->Led0Btn->Click += gcnew System::EventHandler(this, &Form1::Led0Btn_Click);
                        // 
                        // ConnectBtn
                        // 
                        this->ConnectBtn->Location = System::Drawing::Point(24, 12);
                        this->ConnectBtn->Name = L"ConnectBtn";
                        this->ConnectBtn->Size = System::Drawing::Size(75, 33);
                        this->ConnectBtn->TabIndex = 1;
                        this->ConnectBtn->Text = L"接続";
                        this->ConnectBtn->UseVisualStyleBackColor = true;
                        this->ConnectBtn->Click += gcnew System::EventHandler(this, &Form1::ConnectBtn_Click);
                        // 
                        // textBox1
                        // 
                        this->textBox1->Location = System::Drawing::Point(149, 18);
                        this->textBox1->Name = L"textBox1";
                        this->textBox1->Size = System::Drawing::Size(161, 22);
                        this->textBox1->TabIndex = 2;
                        // 
                        // groupBox2
                        // 
                        this->groupBox2->BackColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(0)), static_cast<System::Int32>(static_cast<System::Byte>(192)), 
                                static_cast<System::Int32>(static_cast<System::Byte>(192)));
                        this->groupBox2->Controls->Add(this->label3);
                        this->groupBox2->Controls->Add(this->label2);
                        this->groupBox2->Controls->Add(this->label1);
                        this->groupBox2->Controls->Add(this->shapeContainer1);
                        this->groupBox2->Location = System::Drawing::Point(24, 204);
                        this->groupBox2->Name = L"groupBox2";
                        this->groupBox2->Size = System::Drawing::Size(446, 114);
                        this->groupBox2->TabIndex = 3;
                        this->groupBox2->TabStop = false;
                        this->groupBox2->Text = L"スイッチ状態検出";
                        // 
                        // label3
                        // 
                        this->label3->AutoSize = true;
                        this->label3->Location = System::Drawing::Point(307, 90);
                        this->label3->Name = L"label3";
                        this->label3->Size = System::Drawing::Size(72, 15);
                        this->label3->TabIndex = 3;
                        this->label3->Text = L"SW3(RD7)";
                        // 
                        // label2
                        // 
                        this->label2->AutoSize = true;
                        this->label2->Location = System::Drawing::Point(189, 90);
                        this->label2->Name = L"label2";
                        this->label2->Size = System::Drawing::Size(72, 15);
                        this->label2->TabIndex = 2;
                        this->label2->Text = L"SW2(RD6)";
                        // 
                        // label1
                        // 
                        this->label1->AutoSize = true;
                        this->label1->Location = System::Drawing::Point(83, 90);
                        this->label1->Name = L"label1";
                        this->label1->Size = System::Drawing::Size(80, 15);
                        this->label1->TabIndex = 1;
                        this->label1->Text = L"SW1(RD13)";
                        // 
                        // shapeContainer1
                        // 
                        this->shapeContainer1->Location = System::Drawing::Point(3, 18);
                        this->shapeContainer1->Margin = System::Windows::Forms::Padding(0);
                        this->shapeContainer1->Name = L"shapeContainer1";
                        this->shapeContainer1->Shapes->AddRange(gcnew cli::array< Microsoft::VisualBasic::PowerPacks::Shape^  >(3) {this->ovalShape3, 
                                this->ovalShape2, this->ovalShape1});
                        this->shapeContainer1->Size = System::Drawing::Size(440, 93);
                        this->shapeContainer1->TabIndex = 0;
                        this->shapeContainer1->TabStop = false;
                        // 
                        // ovalShape3
                        // 
                        this->ovalShape3->FillStyle = Microsoft::VisualBasic::PowerPacks::FillStyle::Solid;
                        this->ovalShape3->Location = System::Drawing::Point(307, 7);
                        this->ovalShape3->Name = L"ovalShape3";
                        this->ovalShape3->Size = System::Drawing::Size(50, 50);
                        // 
                        // ovalShape2
                        // 
                        this->ovalShape2->FillStyle = Microsoft::VisualBasic::PowerPacks::FillStyle::Solid;
                        this->ovalShape2->Location = System::Drawing::Point(193, 10);
                        this->ovalShape2->Name = L"ovalShape2";
                        this->ovalShape2->Size = System::Drawing::Size(50, 50);
                        // 
                        // ovalShape1
                        // 
                        this->ovalShape1->FillStyle = Microsoft::VisualBasic::PowerPacks::FillStyle::Solid;
                        this->ovalShape1->Location = System::Drawing::Point(81, 10);
                        this->ovalShape1->Name = L"ovalShape1";
                        this->ovalShape1->Size = System::Drawing::Size(50, 50);
                        // 
                        // timer1
                        // 
                        this->timer1->Tick += gcnew System::EventHandler(this, &Form1::timer1_Tick);
                        // 
                        // groupBox3
                        // 
                        this->groupBox3->BackColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(0)), static_cast<System::Int32>(static_cast<System::Byte>(192)), 
                                static_cast<System::Int32>(static_cast<System::Byte>(192)));
                        this->groupBox3->Controls->Add(this->textBox2);
                        this->groupBox3->Location = System::Drawing::Point(137, 345);
                        this->groupBox3->Name = L"groupBox3";
                        this->groupBox3->Size = System::Drawing::Size(228, 71);
                        this->groupBox3->TabIndex = 4;
                        this->groupBox3->TabStop = false;
                        this->groupBox3->Text = L"電圧検出";
                        // 
                        // textBox2
                        // 
                        this->textBox2->Font = (gcnew System::Drawing::Font(L"MS UI Gothic", 13.8F, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, 
                                static_cast<System::Byte>(128)));
                        this->textBox2->Location = System::Drawing::Point(60, 21);
                        this->textBox2->Name = L"textBox2";
                        this->textBox2->Size = System::Drawing::Size(129, 30);
                        this->textBox2->TabIndex = 0;
                        // 
                        // Form1
                        // 
                        this->AutoScaleDimensions = System::Drawing::SizeF(8, 15);
                        this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
                        this->ClientSize = System::Drawing::Size(537, 466);
                        this->Controls->Add(this->groupBox3);
                        this->Controls->Add(this->groupBox2);
                        this->Controls->Add(this->textBox1);
                        this->Controls->Add(this->ConnectBtn);
                        this->Controls->Add(this->groupBox1);
                        this->Name = L"Form1";
                        this->Text = L"Form1";
                        this->groupBox1->ResumeLayout(false);
                        this->groupBox2->ResumeLayout(false);
                        this->groupBox2->PerformLayout();
                        this->groupBox3->ResumeLayout(false);
                        this->groupBox3->PerformLayout();
                        this->ResumeLayout(false);
                        this->PerformLayout();

                }
#pragma endregion
        private: System::Void ConnectBtn_Click(System::Object^  sender, System::EventArgs^  e) 
                         {
                                 
                                 //-------------------------------------------------------BEGIN CUT AND PASTE BLOCK-----------------------------------------------------------------------------------
                /* 
                Before we can "connect" our application to our USB embedded device, we must first find the device.
                A USB bus can have many devices simultaneously connected, so somehow we have to find our device, and only
                our device.  This is done with the Vendor ID (VID) and Product ID (PID).  Each USB product line should have
                a unique combination of VID and PID.  

                Microsoft has created a number of functions which are useful for finding plug and play devices.  Documentation
                for each function used can be found in the MSDN library.  We will be using the following functions:

                SetupDiGetClassDevs()                                   //provided by setupapi.dll, which comes with Windows
                SetupDiEnumDeviceInterfaces()                   //provided by setupapi.dll, which comes with Windows
                GetLastError()                                                  //provided by kernel32.dll, which comes with Windows
                SetupDiDestroyDeviceInfoList()                  //provided by setupapi.dll, which comes with Windows
                SetupDiGetDeviceInterfaceDetail()               //provided by setupapi.dll, which comes with Windows
                SetupDiGetDeviceRegistryProperty()              //provided by setupapi.dll, which comes with Windows
                malloc()                                                                //part of C runtime library, msvcrt.dll?
                CreateFile()                                                    //provided by kernel32.dll, which comes with Windows

                We will also be using the following unusual data types and structures.  Documentation can also be found in
                the MSDN library:

                PSP_DEVICE_INTERFACE_DATA
                PSP_DEVICE_INTERFACE_DETAIL_DATA
                SP_DEVINFO_DATA
                HDEVINFO
                HANDLE
                GUID

                The ultimate objective of the following code is to call CreateFile(), which opens a communications
                pipe to a specific device (such as a HID class USB device endpoint).  CreateFile() returns a "handle" 
                which is needed later when calling ReadFile() or WriteFile().  These functions are used to actually 
                send and receive application related data to/from the USB peripheral device.

                However, in order to call CreateFile(), we first need to get the device path for the USB device
                with the correct VID and PID.  Getting the device path is a multi-step round about process, which
                requires calling several of the SetupDixxx() functions provided by setupapi.dll.
                */


                //Globally Unique Identifier (GUID) for HID class devices.  Windows uses GUIDs to identify things.
                GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}; 

                HDEVINFO DeviceInfoTable = INVALID_HANDLE_VALUE;
                PSP_DEVICE_INTERFACE_DATA InterfaceDataStructure = new SP_DEVICE_INTERFACE_DATA;
                PSP_DEVICE_INTERFACE_DETAIL_DATA DetailedInterfaceDataStructure = new SP_DEVICE_INTERFACE_DETAIL_DATA;
                SP_DEVINFO_DATA DevInfoData;

                DWORD InterfaceIndex = 0;
                DWORD StatusLastError = 0;
                DWORD dwRegType;
                DWORD dwRegSize;
                DWORD StructureSize = 0;
                PBYTE PropertyValueBuffer;
                bool MatchFound = false;
                DWORD ErrorStatus;

                String^ DeviceIDToFind = MY_DEVICE_ID;

                //First populate a list of plugged in devices (by specifying "DIGCF_PRESENT"), which are of the specified class GUID. 
                DeviceInfoTable = SetupDiGetClassDevsUM(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

                //Now look through the list we just populated.  We are trying to see if any of them match our device. 
                while(true)
                {
                        InterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
                        if(SetupDiEnumDeviceInterfacesUM(DeviceInfoTable, NULL, &InterfaceClassGuid, InterfaceIndex, InterfaceDataStructure))
                        {
                                ErrorStatus = GetLastError();
                                if(ERROR_NO_MORE_ITEMS == ErrorStatus)  //Did we reach the end of the list of matching devices in the DeviceInfoTable?
                                {       //Cound not find the device.  Must not have been attached.
                                        SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                        return;         
                                }
                        }
                        else    //Else some other kind of unknown error ocurred...
                        {
                                ErrorStatus = GetLastError();
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                return; 
                        }

                        //Now retrieve the hardware ID from the registry.  The hardware ID contains the VID and PID, which we will then 
                        //check to see if it is the correct device or not.

                        //Initialize an appropriate SP_DEVINFO_DATA structure.  We need this structure for SetupDiGetDeviceRegistryProperty().
                        DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
                        SetupDiEnumDeviceInfoUM(DeviceInfoTable, InterfaceIndex, &DevInfoData);

                        //First query for the size of the hardware ID, so we can know how big a buffer to allocate for the data.
                        SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, NULL, 0, &dwRegSize);

                        //Allocate a buffer for the hardware ID.
                        PropertyValueBuffer = (BYTE *) malloc (dwRegSize);
                        if(PropertyValueBuffer == NULL) //if null, error, couldn't allocate enough memory
                        {       //Can't really recover from this situation, just exit instead.
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                return;         
                        }

                        //Retrieve the hardware IDs for the current device we are looking at.  PropertyValueBuffer gets filled with a 
                        //REG_MULTI_SZ (array of null terminated strings).  To find a device, we only care about the very first string in the
                        //buffer, which will be the "device ID".  The device ID is a string which contains the VID and PID, in the example 
                        //format "Vid_04d8&Pid_003f".
                        SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, PropertyValueBuffer, dwRegSize, NULL);

                        //Now check if the first string in the hardware ID matches the device ID of my USB device.
                        #ifdef UNICODE
                        String^ DeviceIDFromRegistry = gcnew String((wchar_t *)PropertyValueBuffer);
                        #else
                        String^ DeviceIDFromRegistry = gcnew String((char *)PropertyValueBuffer);
                        #endif

                        free(PropertyValueBuffer);              //No longer need the PropertyValueBuffer, free the memory to prevent potential memory leaks
                        textBox1->Text = "Searching Device!";
                        //Convert both strings to lower case.  This makes the code more robust/portable accross OS Versions
                        DeviceIDFromRegistry = DeviceIDFromRegistry->ToLowerInvariant();        
                        DeviceIDToFind = DeviceIDToFind->ToLowerInvariant();                            
                        //Now check if the hardware ID we are looking at contains the correct VID/PID
                        MatchFound = DeviceIDFromRegistry->Contains(DeviceIDToFind);            
                        if(MatchFound == true)
                        {
                                //Device must have been found.  Open read and write handles.  In order to do this, we will need the actual device path first.
                                //We can get the path by calling SetupDiGetDeviceInterfaceDetail(), however, we have to call this function twice:  The first
                                //time to get the size of the required structure/buffer to hold the detailed interface data, then a second time to actually 
                                //get the structure (after we have allocated enough memory for the structure.)
                                DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                                //First call populates "StructureSize" with the correct value
                                SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, NULL, NULL, &StructureSize, NULL);   
                                DetailedInterfaceDataStructure = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(malloc(StructureSize));             //Allocate enough memory
                                if(DetailedInterfaceDataStructure == NULL)      //if null, error, couldn't allocate enough memory
                                {       //Can't really recover from this situation, just exit instead.
                                        SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                        return;         
                                }
                                DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                                 //Now call SetupDiGetDeviceInterfaceDetail() a second time to receive the goods.  
                                SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, DetailedInterfaceDataStructure, StructureSize, NULL, NULL); 

                                //We now have the proper device path, and we can finally open read and write handles to the device.
                                //We store the handles in the global variables "WriteHandle" and "ReadHandle", which we will use later to actually communicate.
                                WriteHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);

                                ErrorStatus = GetLastError();
                                if(ErrorStatus == ERROR_SUCCESS)
                                        textBox1->Text = "Write Enabled.";                              //Make button no longer greyed out
                                ReadHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
                                ErrorStatus = GetLastError();
                                if(ErrorStatus == ERROR_SUCCESS)
                                {
                                        textBox1->Text = "Read Enabled.";                                       //Make label no longer greyed out
                                }
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.


                                //追加修正部
                                // 接続確認メッセージ準備 
                                OutputPacketBuffer[0] = 0;                                                      // Report ID  
                                OutputPacketBuffer[1] = 0x30;                                           // 接続確認 
                                // 接続確認 コマンド送信
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                // OK受信
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
                                // OK確認 
                                if((InputPacketBuffer[3] == 0x4F)&&(InputPacketBuffer[4] == 0x4B))      //"OK"  //O: 0x4F //K: 0x4B
                                        textBox1->Text = "接続完了!!";                              // 接続正常完了

                                

                                // 接続完了でタイマ1スタート
                                timer1->Interval = 100;
                                timer1->Enabled = TRUE;


                                return;
                        }

                        InterfaceIndex++;       
                        //Keep looping until we either find a device with matching VID and PID, or until we run out of items.
                }//end of while(true)   
//-------------------------------------------------------END CUT AND PASTE BLOCK-------------------------------------------------------------------------------------

                         }
        private: System::Void Led0Btn_Click(System::Object^  sender, System::EventArgs^  e)
                         {
                                OutputPacketBuffer[0] = 0;                                      // Report ID  
                                OutputPacketBuffer[1] = 0x80;                           // LED制御コマンド

                                OutputPacketBuffer[2] = 0x30;                           // LED0アドレス

                                if(Led0Mode == 0)       //消灯していたなら
                                {
                                        Led0Mode = 1;
                                        OutputPacketBuffer[3] = 0x31;                   // Led点灯        //0x31 = '1'
                                }
                                else
                                {
                                        Led0Mode = 0;
                                        OutputPacketBuffer[3] = 0x30;                   // Led消灯        //0x30 = '0'
                                }

                                // 送信
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                // 受信
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
        
                                if(InputPacketBuffer[3] == 0x31)Led0Btn->BackColor =Color:: Red;                // オンなら赤
                                else Led0Btn->BackColor = Color::Gray;          // オフなら灰色

                         }
private: System::Void Led1Btn_Click(System::Object^  sender, System::EventArgs^  e) 
                 {
                        OutputPacketBuffer[0] = 0;                                      // Report ID  
                        OutputPacketBuffer[1] = 0x80;                           // LED制御コマンド

                        OutputPacketBuffer[2] = 0x31;                           // LED1アドレス

                        if(Led1Mode == 0)       //消灯していたなら
                        {
                                Led1Mode = 1;
                                OutputPacketBuffer[3] = 0x31;                   // Led点灯        //0x31 = '1'
                        }
                        else
                        {
                                Led1Mode = 0;
                                OutputPacketBuffer[3] = 0x30;                   // Led消灯        //0x30 = '0'
                        }

                        // 送信
                        WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                        // 受信
                        ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
        
                        if(InputPacketBuffer[4] == 0x31)Led1Btn->BackColor =Color:: Red;                // オンなら赤
                        else Led1Btn->BackColor = Color::Gray;          // オフなら灰色
                 }
private: System::Void Led2Btn_Click(System::Object^  sender, System::EventArgs^  e)
                 {
                        OutputPacketBuffer[0] = 0;                                      // Report ID  
                        OutputPacketBuffer[1] = 0x80;                           // LED制御コマンド

                        OutputPacketBuffer[2] = 0x32;                           // LED1アドレス

                        if(Led2Mode == 0)       //消灯していたなら
                        {
                                Led2Mode = 1;
                                OutputPacketBuffer[3] = 0x31;                   // Led点灯        //0x31 = '1'
                        }
                        else
                        {
                                Led2Mode = 0;
                                OutputPacketBuffer[3] = 0x30;                   // Led消灯        //0x30 = '0'
                        }

                        // 送信
                        WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                        // 受信
                        ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
        
                        if(InputPacketBuffer[5] == 0x31)Led2Btn->BackColor =Color:: Red;                // オンなら赤
                        else Led2Btn->BackColor = Color::Gray;          // オフなら灰色



                 }
private: System::Void Led3Btn_Click(System::Object^  sender, System::EventArgs^  e)
                 {
                        OutputPacketBuffer[0] = 0;                                      // Report ID  
                        OutputPacketBuffer[1] = 0x80;                           // LED制御コマンド

                        OutputPacketBuffer[2] = 0x33;                           // LED1アドレス

                        if(Led3Mode == 0)       //消灯していたなら
                        {
                                Led3Mode = 1;
                                OutputPacketBuffer[3] = 0x31;                   // Led点灯        //0x31 = '1'
                        }
                        else
                        {
                                Led3Mode = 0;
                                OutputPacketBuffer[3] = 0x30;                   // Led消灯        //0x30 = '0'
                        }

                        // 送信
                        WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                        // 受信
                        ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
        
                        if(InputPacketBuffer[6] == 0x31)Led3Btn->BackColor =Color:: Red;                // オンなら赤
                        else Led3Btn->BackColor = Color::Gray;          // オフなら灰色



                 }
private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e)
                 {
                         unsigned int ADCValue;
                                double Volt;

                        //可変抵抗器出力電圧のAD変換値 読込
                
                        OutputPacketBuffer[0] = 0;                                      // Report ID  
                        OutputPacketBuffer[1] = 0x82;                           // 可変抵抗器outのAD変換値読込

                        OutputPacketBuffer[2] = 0x31;                           // VR1
                        WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);

                        //対応するエンドポイント
                        //InputPacketBuffer[3](Windows側)vs ToSendDataBuffer[2](PIC側)
                        //InputPacketBuffer[4](Windows側)vs ToSendDataBuffer[3](PIC側)
                        ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
                        ADCValue = (InputPacketBuffer[4] * 256) + InputPacketBuffer[3];
                        Volt = (ADCValue * 5.0) / 1024;
                        textBox2->Text = String::Format("{0:F2} [V]",Volt);             //小数点以下2桁にして表示



                         //スイッチの状態読込
                                
                                OutputPacketBuffer[0] = 0;                                      // Report ID  
                                OutputPacketBuffer[1] = 0x81;                           // SW状態要求コマンド

                                OutputPacketBuffer[2] = 0x31;                           // SW1
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);

                                //ovalShape: FillStyleのpropertyはSolidに設定のこと//コマンドでは設定できない!!
                                if(InputPacketBuffer[3] == 0x30)                        // オンか? 
                                        ovalShape1->FillColor = Color::Orange;  //ON ならオレンジ色
                                else
                                        ovalShape1->FillColor = Color::Gray;            // OFFなら灰色

                                //ovalShape: FillStyleのpropertyはSolidに設定のこと//コマンドでは設定できない!!
                                OutputPacketBuffer[2] = 0x32;                           // SW2
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);

                                if(InputPacketBuffer[3] == 0x30)                        // オンか? 
                                        ovalShape2->FillColor = Color::Orange;  //ON ならオレンジ色
                                else
                                        ovalShape2->FillColor = Color::Gray;            // OFFなら灰色

                                //ovalShape: FillStyleのpropertyはSolidに設定のこと//コマンドでは設定できない!!
                                OutputPacketBuffer[2] = 0x33;                           // SW3
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);

                                if(InputPacketBuffer[3] == 0x30)                        // オンか? 
                                        ovalShape3->FillColor = Color::Orange;  //ON ならオレンジ色
                                else
                                        ovalShape3->FillColor = Color::Gray;            // OFFなら灰色
                 }
};
}

}
 

<実行結果>

 PC画面のLED0,LED2、LED3ボタンをクリックして キバン上のLEDを点灯させたあと、キバン上のSW1とSW3をおした時のPCのスクリーンショット画像とキバンの写真です。
ADコンバータで検出された電圧が ダイアログのテキストボックスに小数点以下2桁で3.53[V}と表示されています。

パソコン画面の
  ダイアログ
PIC32MX795F512L キバン上で
  SW1 とSW3を押したところ




■ PIC32MX795F512L  HIDクラス 漢字を含む文字列の送受信

  PIC32MX795F512Lにキャラクタ液晶を接続した USB通信 送受信の例を紹介します。   → PIC側ハード&ソフト

以下のソフトは、 マイクロチップ社のライブラリ microchip_solutions_v2013-06-15\USB\Simple Demo - Windows Software \Microsoft Visual C++ 2005 Expressに収納されているVC++Cのサンプルプログラムを参考にして作成したものです。


<試作品仕様>
 ・PC側からデータをPIC側にUSB HIDクラス通信で送信する。
 ・送信文字コードはシフトJISを使用する
 ・PIC側では受信した文字列を液晶上段に、受信データに基づき返信したデータを液晶下段に表示する。
 ・PC側でも受信したデータをリストボックスに表示する。
 ・PC側からの送信データ 及びPIC側からの返信データは以下とする。
     @ U.K.       →  London
     A America    →  Washington
     B Japan      →  0x938c(東)0x8b9e(京)
     C 中(0x9286)国 (0x8D91)   → 北(0x966B)京(0x8B9E)
     D I am a boy.   →  Pardon ?


  

          

   <プログラム例>


//Form1.h


#pragma once
//Includes
#include <Windows.h>    //Definitions for various common and not so common types like DWORD, PCHAR, HANDLE, etc.
#include <setupapi.h>   //From Platform SDK. Definitions needed for the SetupDixxx() functions, which we use to
                                                //find our plug and play device.
#include <Winusb.h>             // WINUSB_INTERFACE_HANDLE(インターフェース用ハンドル)が定義されている       

#include <msclr/marshal.h>      //マーシャリング関係関数用

//Modify this value to match the VID and PID in your USB device descriptor.
//Use the formatting: "Vid_xxxx&Pid_xxxx" where xxxx is a 16-bit hexadecimal number.
#define MY_DEVICE_ID  "Vid_04d8&Pid_003F"               //VID = 0x04D8  PID = 0x003F    




namespace CWhiteForm {

        using namespace System;
        using namespace System::ComponentModel;
        using namespace System::Collections;
        using namespace System::Windows::Forms;
        using namespace System::Data;
        using namespace System::Drawing;

        using namespace System::Text;//エンコードクラスを使用する場合要追加
        using namespace msclr::interop; //マーシャリング関係関数用

        //-------------------------------------------------------BEGIN CUT AND PASTE BLOCK-----------------------------------------------------------------------------------
        using namespace System::Runtime::InteropServices;  //Need this to support "unmanaged" code.

        /*
        In order to use these unmanaged functions from within the managed .NET environment, we need
        to explicitly import the functions which we will be using from other .DLL file(s).  Simply
        including the appropriate header files is not enough. 

        Note: In order to avoid potential name conflicts in the header files (which we still use),
        I have renamed the functions by adding "UM" (unmanaged) onto the end of them.  To find 
        documentation for the functions in MSDN, search for the function name without the extra 
        "UM" attached.
        Note2: In the header files (such as setupapi.h), normally the function names are 
        remapped, depending upon if UNICODE is defined or not.  For example, two versions of the
        function SetupDiGetDeviceInterfaceDetail() exist.  One for UNICODE, and one for ANSI.  
        If the wrong version of the function is called, things won't work correctly.  Therefore,
        in order to make sure the correct one gets called (based on your compiler settings, which
        may or may not define "UNICODE"), it is useful to explicity specify the CharSet when doing
        the DLL import.
        */

        #ifdef UNICODE
        #define Seeifdef        Unicode
        #else
        #define Seeifdef        Ansi
        #endif


        //使用するDLL関数の宣言
        //Returns a HDEVINFO type for a device information set (USB HID devices in
        //our case).  We will need the HDEVINFO as in input parameter for calling many of
        //the other SetupDixxx() functions.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetClassDevs", CallingConvention=CallingConvention::Winapi)]                
        extern "C" HDEVINFO  SetupDiGetClassDevsUM(
                LPGUID  ClassGuid,                                      //Input: Supply the class GUID here. 
                PCTSTR  Enumerator,                                     //Input: Use NULL here, not important for our purposes
                HWND  hwndParent,                                       //Input: Use NULL here, not important for our purposes
                DWORD  Flags);                                          //Input: Flags describing what kind of filtering to use.

        //Gives us "PSP_DEVICE_INTERFACE_DATA" which contains the Interface specific GUID (different
        //from class GUID).  We need the interface GUID to get the device path.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiEnumDeviceInterfaces", CallingConvention=CallingConvention::Winapi)]                                
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiEnumDeviceInterfacesUM(
                HDEVINFO  DeviceInfoSet,                        //Input: Give it the HDEVINFO we got from SetupDiGetClassDevs()
                PSP_DEVINFO_DATA  DeviceInfoData,       //Input (optional)
                LPGUID  InterfaceClassGuid,                     //Input 
                DWORD  MemberIndex,                                     //Input: "Index" of the device you are interested in getting the path for.
                PSP_DEVICE_INTERFACE_DATA  DeviceInterfaceData);//Output: This function fills in an "SP_DEVICE_INTERFACE_DATA" structure.

        //SetupDiDestroyDeviceInfoList() frees up memory by destroying a DeviceInfoList
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiDestroyDeviceInfoList", CallingConvention=CallingConvention::Winapi)]
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiDestroyDeviceInfoListUM(                     
                HDEVINFO  DeviceInfoSet);                       //Input: Give it a handle to a device info list to deallocate from RAM.

        //SetupDiEnumDeviceInfo() fills in an "SP_DEVINFO_DATA" structure, which we need for SetupDiGetDeviceRegistryProperty()
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiEnumDeviceInfo", CallingConvention=CallingConvention::Winapi)]
        extern "C" WINSETUPAPI BOOL WINAPI  SetupDiEnumDeviceInfoUM(
                HDEVINFO  DeviceInfoSet,
                DWORD  MemberIndex,
                PSP_DEVINFO_DATA  DeviceInfoData);

        //SetupDiGetDeviceRegistryProperty() gives us the hardware ID, which we use to check to see if it has matching VID/PID
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetDeviceRegistryProperty", CallingConvention=CallingConvention::Winapi)]
        extern "C"      WINSETUPAPI BOOL WINAPI  SetupDiGetDeviceRegistryPropertyUM(
                HDEVINFO  DeviceInfoSet,
                PSP_DEVINFO_DATA  DeviceInfoData,
                DWORD  Property,
                PDWORD  PropertyRegDataType,
                PBYTE  PropertyBuffer,   
                DWORD  PropertyBufferSize,  
                PDWORD  RequiredSize);

        //SetupDiGetDeviceInterfaceDetail() gives us a device path, which is needed before CreateFile() can be used.
        [DllImport("setupapi.dll" , CharSet = CharSet::Seeifdef, EntryPoint="SetupDiGetDeviceInterfaceDetail", CallingConvention=CallingConvention::Winapi)]
        extern "C" BOOL SetupDiGetDeviceInterfaceDetailUM(
                HDEVINFO DeviceInfoSet,                                                                         //Input: Wants HDEVINFO which can be obtained from SetupDiGetClassDevs()
                PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,                          //Input: Pointer to an structure which defines the device interface.  
                PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData,     //Output: Pointer to a strucutre, which will contain the device path.
                DWORD DeviceInterfaceDetailDataSize,                                            //Input: Number of bytes to retrieve.
                PDWORD RequiredSize,                                                                            //Output (optional): Te number of bytes needed to hold the entire struct 
                PSP_DEVINFO_DATA DeviceInfoData);                                                       //Output

        //USBデバイスとのパイプ(エンドポイント)に書き込む関数
        //WinUsb_WritePipe() is the basic function used to write data to the USB device (sends data to OUT endpoints on the device)
        [DllImport("winusb.dll" , CharSet = CharSet::Seeifdef, EntryPoint="WinUsb_WritePipe")]
        extern "C" BOOL WinUsb_WritePipe(
                WINUSB_INTERFACE_HANDLE InterfaceHandle,
                UCHAR PipeID,
                PUCHAR Buffer,
                ULONG BufferLength,
                PULONG LengthTransferred,
                LPOVERLAPPED Overlapped);

        //USBデバイスとのパイプ(エンドポイント)からデータを読み込む関数
        //WinUsb_ReadPipe() is the basic function used to read data from the USB device (polls for and obtains data from
        //IN endpoints on the device)
        [DllImport("winusb.dll" , CharSet = CharSet::Seeifdef, EntryPoint="WinUsb_ReadPipe")]
        extern "C" BOOL WinUsb_ReadPipe(
                WINUSB_INTERFACE_HANDLE InterfaceHandle,        //The interface handle that WinUsb_Initialize returned. 
                UCHAR PipeID,   //An 8-bit value that consists of a 7-bit address and a direction bit.
                                                //This parameter corresponds to the bEndpointAddress field in the endpoint descriptor. 

                PUCHAR Buffer,  //A caller-allocated buffer that receives the data that is read. 

                ULONG BufferLength,     //The maximum number of bytes to read. This number must be less than or equal to the size, in bytes, of Buffer. 

                PULONG LengthTransferred,       //A pointer to a ULONG variable that receives the actual number of bytes that were copied into Buffer. 

                LPOVERLAPPED Overlapped);       //An optional pointer to an OVERLAPPED structure that is used for asynchronous operations. If this
                                                                        //parameter is specified, WinUsb_ReadPipe returns immediately rather than waiting synchronously 
                                                                        //for the operation to complete before returning. An event is signaled when the operation is complete. 



//  Variables that need to have wide scope.
        HANDLE WriteHandle = INVALID_HANDLE_VALUE;      //Need to get a write "handle" to our device before we can write to it.
        HANDLE ReadHandle = INVALID_HANDLE_VALUE;       //Need to get a read "handle" to our device before we can read from it.
//-------------------------------------------------------END CUT AND PASTE BLOCK-------------------------------------------------------------------------------------

        
        //グローバル変数定義

        
        DWORD BytesWritten = 0;         //書き込んだバイト数
        DWORD BytesRead = 0;            //読み込んだバイト数
        unsigned char OutputPacketBuffer[65];   //Allocate a memory buffer equal to our endpoint size + 1
        unsigned char InputPacketBuffer[65];

        
//グローバル変数
        HANDLE MyDeviceHandle = INVALID_HANDLE_VALUE;           //USBデバイス用のハンドル
        WINUSB_INTERFACE_HANDLE MyWinUSBInterfaceHandle;        //インターフェース用ハンドル
                                                                                                                //And then can call WinUsb_Initialize() to get the interface handle
                                                                                                                //which is needed for doing other operations with the device (like
                                                                                                                //reading and writing to the USB device).




        /// <summary>
        /// Form1 の概要
        /// </summary>
        public ref class Form1 : public System::Windows::Forms::Form
        {
        public:
                Form1(void)
                {
                        InitializeComponent();
                        comboBox1->Items->Clear();
                        comboBox1->Items->Insert(0,"U.K.              ");
                        comboBox1->Items->Insert(1,"America           ");
                        comboBox1->Items->Insert(2,"Japan             ");
                        comboBox1->Items->Insert(3,"中国              ");
                        //comboBox1->Items->Insert(3,"Chuugoku          ");
                        comboBox1->Items->Insert(4,"I am a boy.           ");
                        comboBox1->SelectedIndex = 0; 

                        SendBtn->Enabled = false;       //送信ボタンをディスイネーブル化

                        textBox1->Text = "未接続";
                        textBox1->ForeColor = Color::Red;
                }

        protected:
                /// <summary>
                /// 使用中のリソースをすべてクリーンアップします。
                /// </summary>
                ~Form1()
                {
                        if (components)
                        {
                                delete components;
                        }
                }



#pragma endregion
        private: System::Void ConnectBtn_Click(System::Object^  sender, System::EventArgs^  e) 
                         {


                                 
                                 
                                 //-------------------------------------------------------BEGIN CUT AND PASTE BLOCK-----------------------------------------------------------------------------------
                /*
                Before we can "connect" our application to our USB embedded device, we must first find the device.
                A USB bus can have many devices simultaneously connected, so somehow we have to find our device, and only
                our device.  This is done with the Vendor ID (VID) and Product ID (PID).  Each USB product line should have
                a unique combination of VID and PID.  

                Microsoft has created a number of functions which are useful for finding plug and play devices.  Documentation
                for each function used can be found in the MSDN library.  We will be using the following functions:

                SetupDiGetClassDevs()                                   //provided by setupapi.dll, which comes with Windows
                SetupDiEnumDeviceInterfaces()                   //provided by setupapi.dll, which comes with Windows
                GetLastError()                                                  //provided by kernel32.dll, which comes with Windows
                SetupDiDestroyDeviceInfoList()                  //provided by setupapi.dll, which comes with Windows
                SetupDiGetDeviceInterfaceDetail()               //provided by setupapi.dll, which comes with Windows
                SetupDiGetDeviceRegistryProperty()              //provided by setupapi.dll, which comes with Windows
                malloc()                                                                //part of C runtime library, msvcrt.dll?
                CreateFile()                                                    //provided by kernel32.dll, which comes with Windows

                We will also be using the following unusual data types and structures.  Documentation can also be found in
                the MSDN library:

                PSP_DEVICE_INTERFACE_DATA
                PSP_DEVICE_INTERFACE_DETAIL_DATA
                SP_DEVINFO_DATA
                HDEVINFO
                HANDLE
                GUID

                The ultimate objective of the following code is to call CreateFile(), which opens a communications
                pipe to a specific device (such as a HID class USB device endpoint).  CreateFile() returns a "handle" 
                which is needed later when calling ReadFile() or WriteFile().  These functions are used to actually 
                send and receive application related data to/from the USB peripheral device.

                However, in order to call CreateFile(), we first need to get the device path for the USB device
                with the correct VID and PID.  Getting the device path is a multi-step round about process, which
                requires calling several of the SetupDixxx() functions provided by setupapi.dll.
                */






                //Globally Unique Identifier (GUID) for HID class devices.  Windows uses GUIDs to identify things.
                GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}; 

                HDEVINFO DeviceInfoTable = INVALID_HANDLE_VALUE;
                PSP_DEVICE_INTERFACE_DATA InterfaceDataStructure = new SP_DEVICE_INTERFACE_DATA;
                PSP_DEVICE_INTERFACE_DETAIL_DATA DetailedInterfaceDataStructure = new SP_DEVICE_INTERFACE_DETAIL_DATA;
                SP_DEVINFO_DATA DevInfoData;

                DWORD InterfaceIndex = 0;
                DWORD StatusLastError = 0;
                DWORD dwRegType;
                DWORD dwRegSize;
                DWORD StructureSize = 0;
                PBYTE PropertyValueBuffer;
                bool MatchFound = false;
                DWORD ErrorStatus;

                String^ DeviceIDToFind = MY_DEVICE_ID;

                //First populate a list of plugged in devices (by specifying "DIGCF_PRESENT"), which are of the specified class GUID. 
                DeviceInfoTable = SetupDiGetClassDevsUM(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

                //Now look through the list we just populated.  We are trying to see if any of them match our device. 
                while(true)
                {
                        InterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
                        if(SetupDiEnumDeviceInterfacesUM(DeviceInfoTable, NULL, &InterfaceClassGuid, InterfaceIndex, InterfaceDataStructure))
                        {
                                ErrorStatus = GetLastError();
                                if(ERROR_NO_MORE_ITEMS == ErrorStatus)  //Did we reach the end of the list of matching devices in the DeviceInfoTable?
                                {       //Cound not find the device.  Must not have been attached.
                                        SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                        return;         
                                }
                        }
                        else    //Else some other kind of unknown error ocurred...
                        {
                                ErrorStatus = GetLastError();
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                return; 
                        }

                        //Now retrieve the hardware ID from the registry.  The hardware ID contains the VID and PID, which we will then 
                        //check to see if it is the correct device or not.

                        //Initialize an appropriate SP_DEVINFO_DATA structure.  We need this structure for SetupDiGetDeviceRegistryProperty().
                        DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
                        SetupDiEnumDeviceInfoUM(DeviceInfoTable, InterfaceIndex, &DevInfoData);

                        //First query for the size of the hardware ID, so we can know how big a buffer to allocate for the data.
                        SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, NULL, 0, &dwRegSize);

                        //Allocate a buffer for the hardware ID.
                        PropertyValueBuffer = (BYTE *) malloc (dwRegSize);
                        if(PropertyValueBuffer == NULL) //if null, error, couldn't allocate enough memory
                        {       //Can't really recover from this situation, just exit instead.
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                return;         
                        }

                        //Retrieve the hardware IDs for the current device we are looking at.  PropertyValueBuffer gets filled with a 
                        //REG_MULTI_SZ (array of null terminated strings).  To find a device, we only care about the very first string in the
                        //buffer, which will be the "device ID".  The device ID is a string which contains the VID and PID, in the example 
                        //format "Vid_04d8&Pid_003f".
                        SetupDiGetDeviceRegistryPropertyUM(DeviceInfoTable, &DevInfoData, SPDRP_HARDWAREID, &dwRegType, PropertyValueBuffer, dwRegSize, NULL);

                        //Now check if the first string in the hardware ID matches the device ID of my USB device.
                        #ifdef UNICODE
                        String^ DeviceIDFromRegistry = gcnew String((wchar_t *)PropertyValueBuffer);
                        #else
                        String^ DeviceIDFromRegistry = gcnew String((char *)PropertyValueBuffer);
                        #endif

                        free(PropertyValueBuffer);              //No longer need the PropertyValueBuffer, free the memory to prevent potential memory leaks
                        textBox1->Text = "Searching Device!";
                        //Convert both strings to lower case.  This makes the code more robust/portable accross OS Versions
                        DeviceIDFromRegistry = DeviceIDFromRegistry->ToLowerInvariant();        
                        DeviceIDToFind = DeviceIDToFind->ToLowerInvariant();                            
                        //Now check if the hardware ID we are looking at contains the correct VID/PID
                        MatchFound = DeviceIDFromRegistry->Contains(DeviceIDToFind);            
                        if(MatchFound == true)
                        {
                                //Device must have been found.  Open read and write handles.  In order to do this, we will need the actual device path first.
                                //We can get the path by calling SetupDiGetDeviceInterfaceDetail(), however, we have to call this function twice:  The first
                                //time to get the size of the required structure/buffer to hold the detailed interface data, then a second time to actually 
                                //get the structure (after we have allocated enough memory for the structure.)
                                DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                                //First call populates "StructureSize" with the correct value
                                SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, NULL, NULL, &StructureSize, NULL);   
                                DetailedInterfaceDataStructure = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(malloc(StructureSize));             //Allocate enough memory
                                if(DetailedInterfaceDataStructure == NULL)      //if null, error, couldn't allocate enough memory
                                {       //Can't really recover from this situation, just exit instead.
                                        SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.
                                        return;         
                                }
                                DetailedInterfaceDataStructure->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
                                 //Now call SetupDiGetDeviceInterfaceDetail() a second time to receive the goods.  
                                SetupDiGetDeviceInterfaceDetailUM(DeviceInfoTable, InterfaceDataStructure, DetailedInterfaceDataStructure, StructureSize, NULL, NULL); 

                                //We now have the proper device path, and we can finally open read and write handles to the device.
                                //We store the handles in the global variables "WriteHandle" and "ReadHandle", which we will use later to actually communicate.
                                WriteHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);

                                ErrorStatus = GetLastError();
                                if(ErrorStatus == ERROR_SUCCESS)
                                        textBox1->Text = "Write Enabled.";                              //Make button no longer greyed out
                                ReadHandle = CreateFile((DetailedInterfaceDataStructure->DevicePath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
                                ErrorStatus = GetLastError();
                                if(ErrorStatus == ERROR_SUCCESS)
                                {
                                        textBox1->Text = "Read Enabled.";                                       //Make label no longer greyed out
                                }
                                SetupDiDestroyDeviceInfoListUM(DeviceInfoTable);        //Clean up the old structure we no longer need.


                                //追加修正部
                                // 接続確認メッセージ準備 
                                OutputPacketBuffer[0] = 0;                                                      // Report ID  
                                OutputPacketBuffer[1] = 0x30;                                           // 接続確認 
                                // 接続確認 コマンド送信
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                                // OK受信
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
                                // OK確認 
                                if((InputPacketBuffer[3] == 0x4F)&&(InputPacketBuffer[4] == 0x4B))      //"OK"  //O: 0x4F //K: 0x4B
                                        textBox1->Text = "接続完了!!";                              // 接続正常完了
                                        textBox1->ForeColor = Color::Blue;                      //文字色→青色

                                        listBox1->Items->Clear();
                                        SendBtn->Enabled = true;        //送信ボタン→イネーブル


                                return;
                        }

                        InterfaceIndex++;       
                        //Keep looping until we either find a device with matching VID and PID, or until we run out of items.
                }//end of while(true)   
//-------------------------------------------------------END CUT AND PASTE BLOCK-------------------------------------------------------------------------------------

                         }
private: System::Void SendBtn_Click(System::Object^  sender, System::EventArgs^  e)
                 {

                         
                        int i;
                        int iy;

                        array <Byte>^ bytesArry = gcnew array<Byte>(65);        //マネージ形式の配列の宣言
                        Encoding^ encSjis = Encoding::GetEncoding("shift-jis");   //シフトJISのエンコードクラスを宣言 & インスタンス生成
                        Encoding^ encUni = Encoding::GetEncoding("unicode");  //ユニコード(UCS-16)のエンコードクラスを宣言 & インスタンス生成


                        String^ strSend = comboBox1->Text;

                        richTextBox1-> Clear();
                        richTextBox2-> Clear();
                        richTextBox3-> Clear();

                        if (!strSend->EndsWith("\r")) strSend += "\r";  //改行が無かったら \rを追加する
                        bytesArry = encSjis->GetBytes( strSend ); //'送信文字をunicode→Shift-jisに変換してをByte配列に格納

                        for(i = 2; i < bytesArry->Length - 1 ; i++)OutputPacketBuffer[i] = bytesArry[i - 2];            //マネージ形式の配列をC言語の配列に変換

                        OutputPacketBuffer[0] = 0;                                      // Report ID  
                        OutputPacketBuffer[1] = 0x80;                           // 制御コマンド


                        //リッチテキスト
                                 array<String^>^ mBX = gcnew array<String^>(65);        //アスキー文字のメモリ    //マネージ配列を定義
                                 array<String^>^ mBX16 = gcnew array<String^>(65);      //16進数のメモリ      //マネージ配列を定義


                                                                          iy = 0;
                                 for each(char s in OutputPacketBuffer) //charの配列BX[64]すべてに対して実行
                                 {
                                         char ch = (char)OutputPacketBuffer[iy];
                                         char* ptr;
                                         ptr = &ch;
                                         mBX[iy] = marshal_as<String^>(ptr);             //配列の値をマーシャリング
                                         int Ix = (int)OutputPacketBuffer[iy];
                                         mBX16[iy] = Convert::ToString(Ix,16); //整数を16進表示の文字列に変換する

                                         richTextBox1->SelectedText =                   //リッチテキストに表示
                                         String::Format("OutBuf[{0}]:     {1},       {2}       0x{3}\r",iy,mBX[iy],Ix,mBX16[iy]);

                                         iy++;

                                 }




                        // 送信
                                WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
                        //       受信
                                ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);
        

                        
                        for(i = 0; i < 17;  i++)
                        {
                                        bytesArry[i] = InputPacketBuffer[i + 1];                //マネージ型配列作成
                        }

                

                                richTextBox2->SelectedText = String::Format("InputBuffer[0]={0:X} ",InputPacketBuffer[0]); //リッチテキストに表示
                                richTextBox2->SelectedText = String::Format("InputBuffer[1]={0:X} ",InputPacketBuffer[1]);
                                richTextBox2->SelectedText = String::Format("InputBuffer[2]={0:X} ",InputPacketBuffer[2]); 
                                richTextBox2->SelectedText = String::Format("InputBuffer[3]={0:X} ",InputPacketBuffer[3]);
                                richTextBox2->SelectedText = String::Format("InputBuffer[4]={0:X} ",InputPacketBuffer[4]); 
                                richTextBox2->SelectedText = String::Format("InputBuffer[5]={0:X} ",InputPacketBuffer[5]);
                                richTextBox2->SelectedText = String::Format("InputBuffer[6]={0:X} ",InputPacketBuffer[6]); 
                                richTextBox2->SelectedText = String::Format("InputBuffer[7]={0:X} ",InputPacketBuffer[7]);
                                richTextBox2->SelectedText = String::Format("InputBuffer[8]={0:X} ",InputPacketBuffer[8]); 
                                richTextBox2->SelectedText = String::Format("InputBuffer[9]={0:X} ",InputPacketBuffer[9]);



                

                                richTextBox3->SelectedText = String::Format("bytesArry[0]={0:X} ",bytesArry[0]);        //リッチテキストに表示
                                richTextBox3->SelectedText = String::Format("bytesArry[1]={0:X} ",bytesArry[1]);
                                richTextBox3->SelectedText = String::Format("bytesArry[2]={0:X} ",bytesArry[2]);
                                richTextBox3->SelectedText = String::Format("bytesArry[3]={0:X} ",bytesArry[3]);
                                richTextBox3->SelectedText = String::Format("bytesArry[4]={0:X} ",bytesArry[4]);
                                richTextBox3->SelectedText = String::Format("bytesArry[5]={0:X} ",bytesArry[5]);
                                richTextBox3->SelectedText = String::Format("bytesArry[6]={0:X} ",bytesArry[6]);
                                richTextBox3->SelectedText = String::Format("bytesArry[7]={0:X} ",bytesArry[7]);
                                richTextBox3->SelectedText = String::Format("bytesArry[8]={0:X} ",bytesArry[8]);
                                richTextBox3->SelectedText = String::Format("bytesArry[9]={0:X} ",bytesArry[9]);




                        
                        array<Byte>^byteUni = Encoding::Convert(encSjis, encUni, bytesArry); //shift-jis からunicodeに変換する
          
                        
                        String^ strUni = encUni->GetString(byteUni); //配列をunicodeの文字列に変換

                        
                        listBox1->Items->Add(strUni);
                 }
};
}

.......
.......



<実行結果>
 
PIC32MX795F512Lの液晶
上段: PCからの受信文字列
下段: PCへの返信文字列
PC画面
USB接続が
    未接続の状態
-
接続ボタンをクリックして
  USB接続が
    確立した状態
-
コンボボックスから
”U.K.”を選択して送信し、
返信をリストボックスに
     受信した状態
次に、コンボボックスから
”America”を選択して送信し、
返信をリストボックスに
     受信した状態
次に、コンボボックスから
”Japan”を選択して送信し、
返信をリストボックスに
     受信した状態
次に、コンボボックスから
”中国”を選択して送信し、
返信をリストボックスに
     受信した状態
最後に、コンボボックスから
”I am a boy”を選択して送信し、
返信をリストボックスに
     受信した状態

     

          

   <プログラム例>

main() { }