GR-PEACHによるHIDクラスを用いたUSBDeviceとPC間の通信について

25 Jul 2017

GR-PEACHを使ってPC間とのUSBHID通信を試みています。

GR-PEACHからPCへの通信に成功したものの、 PCからGR-PEACHへの通信はできていません。

PC側のプログラムの確認はUSB通信できるマイコンがないため出来ていません。

GR-PEACHのコードについては、 USBHID_HelloWorldをUSBDevice.cpp中の#define DEBUGをアンコメントし、最新版で使用しています。

その際得られた出力が以下でfailとなっています。 また改行があるべきところに、改行がなかったりなどしており(再現取れています)、 通信が出来ない原因の可能性ではないかと考えています。

failという出力は正常動作なのか failの出力は通信が出来ないことに関係しているのか GR-PEACH側のコードが原因と考えられる点がある場合、どのように対処すると良いのか。 教えていただけないでしょうか。宜しくお願いいたします。

(以下DEBUGによる出力) dataTransferDirection: 1 Type: 0 Recipient: 0 bRequest: 6 wValue: 256 wIndex: 0 wLength: 64 get descr: type: 1 device descr EP0IN dataTransferDirection: 1 Type: 0 Recipient: 0 bRequest: 6 wValue: 256 wIndex: 0 wLength: 18 get descr: type: 1 device descr EP0IN dataTransferDirection: 1 Type: 0 Recipient: 0 bRequest: 6 wValue: 512 wIndex: 0 wLength: 9 get descr: type: 2 conf descr request EP0IN dataTransferDirection: 1 Type: 0 Recipient: 0 bRequest: 6 wValue: 768 wIndex: 0 wLength: 255 get descr: type: 3 str descriptor 1 EP0IN dataTransferDirection: 1 Type: 0 Recipient: 0 bRequest: 6 wValue: 771 wIndex: 1033 wLength: 255 get descr: type: 3 str descriptor 4 EP0IN dataTransferDirection: 1 Type: 0 Recipient: 0 bRequest: 6 wValue: 512 wIndex: 0 wLength: 255 get descr: type: 2 conf descr request EP0IN dataTransferDirection: 1 Type: 0 Recipient: 0 bRequest: 6 wValue: 768 wIndex: 0 wLength: 255 get descr: type: 3 str descriptor 1 EP0IN dataTransferDirection: 1 Type: 0 Recipient: 0 bRequest: 6 wValue: 770 wIndex: 1033 wLength: 255 get descr: type: 3 str descriptor 3 EP0IN dataTransferDirection: 1 Type: 0 Recipient: 0 bRequest: 6 wValue: 768 wIndex: 0 wLength: 255 get descr: type: 3 str descriptor 1 EP0IN dataTransferDirection: 1 Type: 0 Recipient: 0 bRequest: 6 wValue: 770 wIndex: 1033 wLength: 255 get descr: type: 3 str descriptor 3 EP0IN dataTransferDirection: 1 Type: 0 Recipient: 0 bRequest: 6 wValue: 256 wIndex: 0 wLength: 18 get descr: type: 1 device descr EP0IN dataTransferDirection: 1 Type: 0 Recipient: 0 bRequest: 6 wValue: 512 wIndex: 0 wLength: 9 get descr: type: 2 conf descr request EP0IN dataTransferDirection: 1 Type: 0 Recipient: 0 bRequest: 6 wValue: 512 wIndex: 0 wLength: 41 get descr: type: 2 conf descr request EP0IN dataTransferDirection: 0 Type: 0 Recipient: 0 bRequest: 9 wValue: 1 wIndex: 0 wLength: 0dataTransferDirection: 0 Type: 1 Recipient: 1 bRequest: 10 wValue: 0 wIndex: 0 wLength: 0 fail!!!! dataTransferDirection: 1 Type: 0 Recipient: 1 bRequest: 6 wValue: 8704 wIndex: 0 wLength: 91 EP0IN

02 Aug 2017

PCからGR-PEACHへの通信が正常に動作しない現象を確認しました。
PCからのインタラプトOUT転送に対してACKを返せていないようで、GR-PEACH側のコードに何かしらの問題がありそうです。
詳細については調査中です。

DEBUG機能有効時にfailが表示される件については直接的な問題はないと思います。
fallが表示されるのは、PCからのSET_IDLEリクエスト時で、このリクエストに対してmbedボードからPCへは特にレスポンスを返す必要がありません。
以下のようにSET_IDLEリクエスト時のUSBCallback_request()応答がtrueになるように変更するとfallの表示が出なくなります。

USBHID.cpp

bool USBHID::USBCallback_request() {

    ・・・省略・・・

    if (transfer->setup.bmRequestType.Type == CLASS_TYPE)
    {
        switch (transfer->setup.bRequest)
        {
             case SET_REPORT:
                // First byte will be used for report ID
                outputReport.data[0] = transfer->setup.wValue & 0xff;
                outputReport.length = transfer->setup.wLength + 1;

                transfer->remaining = sizeof(outputReport.data) - 1;
                transfer->ptr = &outputReport.data[1];
                transfer->direction = HOST_TO_DEVICE;
                transfer->notify = true;
                success = true;
#if(1) // ★追加
                break;
            case SET_IDLE:
                success = true;
                break;
#endif
            default:
                break;
        }
    }

    return success;
}

改行については、printfの出力が全て出力される前に別の割り込み処理内からprintfが実行された為に、直前のprintf出力の終端が文字化けしているのではないかと予想します。こちらも通信ができない症状に対して直接的な影響は無いと思います。

25 Aug 2017

Daiki Kato様

対応していただき、ありがとうございました。

PCと通信できない主な原因は、 PCからのインタラプトOUT転送に対してACKを返せていないことで、 それはGR-PEACH側のコードに問題がありそうなことについて承知しました。

そして指摘のとおりコードを変更したところ、Failは出なくなりました。 また、改行の問題についても理解しました。

不明な点がありましたら、こちらに書き込みします。 よろしくお願いいたします。

2017/08/25 追記 通信が出来ない原因であるPC(USBHost)からのインタラプトOUT転送に対してACKが返せていないという問題は、 レジスタの設定変更といったライブラリの変更などで対応ができる問題なのでしょうか。

問題解決の目処は立っていますでしょうか?

質問ばかりでお手数をおかけして申し訳ございませんが宜しくお願いいたします。

23 Oct 2017

返信が遅れまして申し訳ございません。
USBMouseやUSBKeyboardが正常に動作していることから、割り込み処理内から「USBDevice::readEP」を実行するとうまく動いているようです。
(継承クラスで「EPINT_OUT_callback()」を定義し、その中で「USBDevice::readEP」を実行している場合は動作する)

暫定対策ですが、以下の方法で動かすことはできます。

下記ファイルをプロジェクト内に作成(main.cppが置いてある位置など)、USBHID_HelloWorld main.cpp内のUSBHIDクラスの代わりにUSBHID_testクラスを使用する。

USBHID_test.h

#ifndef USB_HID_TEST_H
#define USB_HID_TEST_H

#include "USBHID.h"

class USBHID_test: public USBHID
{
public:
    USBHID_test(uint8_t output_report_length = 64, uint8_t input_report_length = 64, uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0006, uint16_t product_release = 0x0001, bool connect = true):
        USBHID(output_report_length, input_report_length, vendor_id, product_id, product_release, connect)
    {
        ep_call_back = false;
        bytesRead = 0;
    };

    bool read(HID_REPORT * report)
    {
        if (!configured()) {
            return false;
        }

        while (readNB(report) == false) {
            ;
        }
        return true;
    }

    bool readNB(HID_REPORT * report)
    {
        if (!configured()) {
            return false;
        }

        if (ep_call_back == false) {
            return false;
        }

        memcpy(report->data, read_buf, bytesRead);
        report->length = bytesRead;
        ep_call_back = false;
        return true;
    }

protected:
    bool EPINT_OUT_callback()
    {
        if (ep_call_back) {
            return false;
        }
        ep_call_back = true;
        USBDevice::readEP(EPINT_OUT, read_buf, &bytesRead, MAX_HID_REPORT_SIZE);

        // We activate the endpoint to be able to recceive data
        if (!readStart(EPINT_OUT, MAX_HID_REPORT_SIZE)) {
            return false;
        }
        return true;
    }

private:
    uint32_t bytesRead;
    uint8_t read_buf[65];
    bool    ep_call_back;
};

#endif
23 Oct 2017

「USBHAL_RZ_A1H.cpp」を以下のように変更すれば、「USBHID_test.h」を作成しなくても動くようになると思います。

USBHAL_RZ_A1H.cpp

EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t max_size)
{
・・・省略・・・
    switch (pipe_status) {
        case DEVDRV_USBF_PIPE_IDLE:
        case DEVDRV_USBF_PIPE_WAIT:
            usbx_api_function_set_pid_nak(pipe);
            usbx_api_function_clear_pipe_status(pipe);

            usbx_api_function_start_receive_transfer(pipe, max_size, recv_buffer);
#if(1) //変更
           status = EP_PENDING;
#endif
            break;

        default:
           status = EP_PENDING;
           break;
    }

    return status;
}

EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *buffer, uint32_t *bytes_read )
{
    uint32_t pipe = EP2PIPE(endpoint);
    uint16_t pipe_status;
    uint16_t err;
    EP_STATUS status = EP_PENDING;


#if(1) //変更
#else
    if (EPx_read_status != DEVDRV_USBF_PIPE_WAIT) {
        return status;
    }
#endif

    pipe_status = usbx_api_function_check_pipe_status(pipe, bytes_read);
    switch (pipe_status) {
#if(1) //変更
        case DEVDRV_USBF_PIPE_IDLE:
        case DEVDRV_USBF_PIPE_DONE:
#else
        case DEVDRV_USBF_PIPE_IDLE:
            return EP_COMPLETED;

        case DEVDRV_USBF_PIPE_DONE:
            return EP_COMPLETED;
#endif

        case DEVDRV_USBF_PIPE_WAIT:
            break;

        default:
            return status;
    }
・・・省略・・・
}
27 Oct 2017

回答していただきありがとうございます。

これから、動作を確認していきたいと思っています。 質問や問題がある際には、ここでご相談させていただきます。

よろしくお願い致します。

31 Oct 2017

USBHID_test.hファイルを追加することによって、PCとGR-PEACHとの双方向でUSBHID通信が出来ることを確認しました。

親切に対応して頂きありがとうございました。 今後とも何卒よろしくお願い申し上げます。