STM32CubeIDEでUSB対応

# はじめに
STM32CubeIDE環境のUSB対応方法についてまとめました。
あくまで参考として実際のデバイスに合わせた対応をお願いします。

# 環境
OS：Windows10 Pro 2004
IDE:STM32CubeIDE 1.3.0
デバイス：STM32F407 Discovery kit
ホスト：Windows10 Pro 2004

# USBデバイス対応
## Virtual COM Port デバイス
PCに接続するとCOMポートとして通信出来るデバイスの実装方法です。

参考) 
[[STM32メモ] Virtual COM Portを取り敢えず動かす](https://qiita.com/stm32p103/items/fb66c8bd2375a6d70b5e)

上記記事そのままですが、環境やバージョンが異なる点を補足します。

1.プロジェクト作成

通常通りボード仕様に合わせて作成します。
この時、クロック設定として以下赤丸部分に48MHzが供給されるようにしておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120192/337e6e2b-908a-c170-5615-7a9776b7805a.png)

2.USB設定

Connectivityから[USB_OTG_FS]を選び、
Mode:Device_Only
を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120192/3c73b98b-1b61-35af-547c-c942e1d5dd11.png)

3.Middleware設定

USB実装を簡単にする為、Middlewareの"USB_DEVICE"を使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120192/e8f86716-c3f4-3bdb-547f-7d47db707791.png)
Class For FS IPで Communication Device Class (Virtual Port Com)を設定します。

4.実装

アプリケーションコードの必要箇所で、USB_DEVICE/App/usbd_cdc_if.c のCDC_Transmit_FS()を呼び出すと引数のデータがホストに送信されます。
ホストから受信した場合はCDC_Receive_FS()が自動的に呼び出されます。この時の引数に受信データが格納されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120192/2b667ef5-16a4-8d76-f21e-5186ee7446a2.png)

受信データの受け取り処理は、直接 CDC_Receive_FS() に記述する以外では以下のようにも書けます。

```
uint8_t MyReceiveBuff[BUFF_SIZE];
uint32_t MyReceiveLen;

typedef int8_t (* Receive)(uint8_t *Buf, uint32_t *Len);
Receive orgCDCReceiveFunc;
int8_t My_CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
    memcpy(MyReceiveBuff, Buf, *Len);
    MyReceiveLen = *Len;

    return orgCDCReceiveFunc(Buf, Len);
}

void UserInitFunc(void)
{
    orgCDCReceiveFunc = USBD_Interface_fops_FS.Receive;
    USBD_Interface_fops_FS.Receive = My_CDC_Receive_FS;
}
```

## Mouse デバイス
デバイスをマウスやキーボードとしてホストに認識させる方法です。

参考)
[STM32でマウスとキーボードを作る](https://blog.rogiken.org/blog/2018/12/20/stm32%E3%81%A7%E3%83%9E%E3%82%A6%E3%82%B9%E3%81%A8%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E3%82%92%E4%BD%9C%E3%82%8B/)

1.プロジェクト作成

前項目と同様に48MHzを設定します。

2.USB設定

こちらも同様に、Device_Onlyを設定します。

3.Middleware設定

Middlewareの"USB_DEVICE"を使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120192/46b0e938-bdee-33f9-e621-83260f57d0dc.png)
Human Interface Device Class (HID) を設定します。

4.実装

参考記事そのままですが。
USB_DEVICE/App/usb_device.c 辺りで、

```
struct mouseHID_t {
    uint8_t buttons;
    int8_t x;
    int8_t y;
    int8_t wheel;
};

void USB_Mouse_Move(int8_t x, int8_t y)
{
	struct mouseHID_t mouseHID;
	mouseHID.buttons = 0;
	mouseHID.x = x;
	mouseHID.y = y;
	mouseHID.wheel = 0;
	USBD_HID_SendReport(&hUsbDeviceFS, (uint8_t*)&mouseHID, sizeof(struct mouseHID_t));
}
```

という関数を用意して、アプリケーションコードの必要箇所で呼び出すと、
ホストでマウスカーソルが移動します。

# USBホスト対応
STM32のボードをホストとしてUSBデバイスを繋ぐケースです。

## マウス対応
ホストにマウスを接続するケースです。

参考)
[STM32F4DiscoのマイクロUSBをHostとしてHIDをつなぐ](http://neocode.jp/2020/06/01/stm32f4disco-microusb-host-hid/)

1.プロジェクト作成

前項目と同様に48MHzを設定します。

2.USB設定

Host_Onlyを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120192/e2b196dd-175b-36c9-faa8-3c9b102dc6d0.png)

3.Middleware設定

Middlewareの"USB_HOST"を使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120192/71892a1d-cc76-4d46-50c7-359f8273617c.png)
Human Interface Host Class (HID) を設定します。

4.実装

こちらも参考記事そのままです。
USB_HOST/App/usb_host.c 辺りで、以下コードを追加します。

```
void USBH_HID_EventCallback(USBH_HandleTypeDef *phost)
{
	HID_TypeTypeDef hidType;
	HID_KEYBD_Info_TypeDef *keybd_info;
	HID_MOUSE_Info_TypeDef *mouse_info;

	hidType = USBH_HID_GetDeviceType(phost);
	if(hidType == HID_KEYBOARD){
		keybd_info = USBH_HID_GetKeybdInfo(phost);
	}
	else if(hidType == HID_MOUSE){
		mouse_info = USBH_HID_GetMouseInfo(phost);
	}
}
```

接続したマウスを動かすとこのハンドラが呼ばれて、マウスの移動情報を取得することが出来ます。

# 参考情報
USBデバイスとして作成してWindowsなどのホストに接続すると、デバイスマネージャで[STMicroelectronics Virtual COM Port]と認識されます。
もし自社名などにしたい場合は、[USB-IF](https://www.usb.org/)のメンバーとなって[ベンダーID](https://www.usb.org/getting-vendor-id)を割り当てて貰う必要が有ります。

参考)
[USBのベンダーIDとプロダクトIDの話](https://qiita.com/gpsnmeajp/items/8eb8ecf0541032f6de0e)