STM32 HAL Custom HID

tags: Stm32  HAL  usb custom hid  

1. Set up CubeMx

 

2. Code

Modify the structure data in usbd_custom_hid_if.c:

__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
  /* USER CODE BEGIN 0 */
    0x06, 0x00, 0xff,              // USAGE_PAGE (Vendor Defined Page 1)
    0x09, 0x01,                    // USAGE (Vendor Usage 1)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    //   USAGE (Vendor Usage 1)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x95, 0x40,                    //   REPORT_COUNT (64)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0x09, 0x01,                    //   USAGE (Vendor Usage 1)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x95, 0x40,                    //   REPORT_COUNT (64)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)
  /* USER CODE END 0 */
  0xC0    /*     END_COLLECTION                 */
};

Confirm the following three macro definitions in usbd_conf.h:

/*----------Output data length -----------*/

#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE     64
/*----------The length of the message symbol is the length of the CUSTOM_HID_ReportDesc_FS structure-----------*/
#define USBD_CUSTOM_HID_REPORT_DESC_SIZE     34
/*----------This is to set the speed to 5 by default, the speed can reach 16KB, and the speed is 64KB after changing to 1 -------- ---*/
#define CUSTOM_HID_FS_BINTERVAL     0x1

 

Modify the sending and receiving length in the usbd_customhid.h file to 64, the original default value is 0x02

  #define CUSTOM_HID_EPIN_SIZE                  0x40

  #define CUSTOM_HID_EPOUT_SIZE              0x40

 

The USB will trigger an event after receiving the data, in the CUSTOM_HID_OutEvent_FS function in usbd_custom_hid_if.c, the program here sends the data to the upper computer, and the lower computer sends the data back to the upper computer.

static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state)
{
  /* USER CODE BEGIN 6 */
USBD_CUSTOM_HID_HandleTypeDef *hhid; //Define a pointer to the structure of USBD_CUSTOM_HID_HandleTypeDef
hhid = (USBD_CUSTOM_HID_HandleTypeDef*)hUsbDeviceFS.pClassData;//Get the storage address of the USB received data
    USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, hhid->Report_buf, 64);
    return (USBD_OK);
  /* USER CODE END 6 */
}

 

Flash the program into stm32. The following is the host computer code vs2013 unicode console version.

// usb_stm32.cpp: defines the entry point of the console application.
//

#include "stdafx.h"

#include <windows.h>
#include <setupapi.h>
 #include <hidsdi.h>
#include <locale.h>

#pragma comment(lib,"Setupapi.lib")
#pragma comment(lib,"Hid.lib")

#define     USB_VID         0x0483
#define     USB_PID         0x5750

void UsbOperation();
int _tmain(int argc, _TCHAR* argv[])
{
setlocale(LC_ALL, "chs");//Set Chinese display
     UsbOperation();    
    return 0;
}

//Get device path and device description at the same time
void GetDevPath(TCHAR *pStrDevPath)
{
    TCHAR szDevPath[MAX_PATH] = { 0 };

    TCHAR szVid[20] = { 0 };
    TCHAR szPid[20] = { 0 };

    _stprintf_s(szVid, _T("vid_%04x"), USB_VID);
    _stprintf_s(szPid, _T("pid_%04x"), USB_PID);

    GUID Guid;
    HidD_GetHidGuid(&Guid);

    HDEVINFO info;
    info = SetupDiGetClassDevs(&Guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

    if (info == INVALID_HANDLE_VALUE)
    {
        return;
    }

    DWORD devIndex;
    SP_INTERFACE_DEVICE_DATA ifData;
    ifData.cbSize = sizeof(ifData);

    for (devIndex = 0; SetupDiEnumDeviceInterfaces(info, NULL, &Guid, devIndex, &ifData); ++devIndex)
    {
        DWORD needed;

        SetupDiGetDeviceInterfaceDetail(info, &ifData, NULL, 0, &needed, NULL);

        PSP_INTERFACE_DEVICE_DETAIL_DATA detail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)new BYTE[needed];
        detail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
        SP_DEVINFO_DATA did = { sizeof(SP_DEVINFO_DATA) };

        if (SetupDiGetDeviceInterfaceDetail(info, &ifData, detail, needed, NULL, &did))
        {
            if ((_tcsstr(detail->DevicePath, szVid) == NULL) || (_tcsstr(detail->DevicePath,szPid) == NULL ))
            {
                delete[](PBYTE)detail;
                continue;
            }

            _tprintf(_T("dev path: %s\r\n"), detail->DevicePath);
            _tcscpy_s(pStrDevPath, MAX_PATH, (TCHAR *)detail->DevicePath);
         
            TCHAR szProduct[MAX_PATH] = { 0 };
            if (SetupDiGetDeviceRegistryProperty(info, &did, SPDRP_DEVICEDESC, NULL, (PBYTE)szProduct, MAX_PATH, NULL))
            {
                _tprintf(_T("dev Prod: %s\r\n"), szProduct);
            }

            delete[](PBYTE)detail;
            break;
        }

        delete[](PBYTE)detail;
    }
    SetupDiDestroyDeviceInfoList(info); 
}

HANDLE OpenHidevice(TCHAR *pstrDevPath)
{
    HANDLE hidHandle = NULL;
    
    hidHandle = CreateFile(pstrDevPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    if (hidHandle != INVALID_HANDLE_VALUE)
    {
        PHIDD_ATTRIBUTES Attributes = (PHIDD_ATTRIBUTES)malloc(sizeof(HIDD_ATTRIBUTES));
        if (HidD_GetAttributes(hidHandle, Attributes))
        {
            printf("Info:  VID->0x%X PID->0x%X VersionNum->0x%X\r\n", Attributes->VendorID, Attributes->ProductID, Attributes->VersionNumber);
        }
    }
    return hidHandle;
}


void GetDeviceCapabilities(HANDLE hidDevObj, HIDP_CAPS &hidCaps)
{
    PHIDP_PREPARSED_DATA    hidPredata;
    HidD_GetPreparsedData(hidDevObj, &hidPredata);

    HidP_GetCaps(hidPredata, &hidCaps);

    printf("%s%X\r\n", "Usage Page:                      \t\t", hidCaps.UsagePage);
    printf("%s%d\r\n", "Input Report Byte Length:        \t\t", hidCaps.InputReportByteLength);
    printf("%s%d\r\n", "Output Report Byte Length:       \t\t", hidCaps.OutputReportByteLength);
    printf("%s%d\r\n", "Feature Report Byte Length:      \t\t", hidCaps.FeatureReportByteLength);
    printf("%s%d\r\n", "Number of Link Collection Nodes: \t\t", hidCaps.NumberLinkCollectionNodes);
    printf("%s%d\r\n", "Number of Input Button Caps:     \t\t", hidCaps.NumberInputButtonCaps);
    printf("%s%d\r\n", "Number of InputValue Caps:       \t\t", hidCaps.NumberInputValueCaps);
    printf("%s%d\r\n", "Number of InputData Indices:     \t\t", hidCaps.NumberInputDataIndices);
    printf("%s%d\r\n", "Number of Output Button Caps:    \t\t", hidCaps.NumberOutputButtonCaps);
    printf("%s%d\r\n", "Number of Output Value Caps:     \t\t", hidCaps.NumberOutputValueCaps);
    printf("%s%d\r\n", "Number of Output Data Indices:   \t\t", hidCaps.NumberOutputDataIndices);
    printf("%s%d\r\n", "Number of Feature Button Caps:   \t\t", hidCaps.NumberFeatureButtonCaps);
    printf("%s%d\r\n", "Number of Feature Value Caps:    \t\t", hidCaps.NumberFeatureValueCaps);
    printf("%s%d\r\n", "Number of Feature Data Indices:  \t\t", hidCaps.NumberFeatureDataIndices);
    HidD_FreePreparsedData(hidPredata);
}
 
void ReadUsbData(HANDLE hHidDevObj, DWORD dwCnt )
{
    DWORD NumberOfBytesRead;
    BYTE InputReport[256] = { 0 };
    BYTE OutputReport[256] = { 0 };
    DWORD bytes = 0;
    int Result = 0;

    for (DWORD i = 0; i < dwCnt; i++)
    {
        OutputReport[i] = (BYTE)i;
    }

    while (TRUE)
    {
        if (hHidDevObj != INVALID_HANDLE_VALUE)
        {
            //CancelIo(hHidDevObj);
OutputReport[1] ++;//OutputReport[0] represents the report ID
            Result = WriteFile(hHidDevObj, OutputReport, dwCnt, &bytes, NULL);
            Result = ReadFile(hHidDevObj, &InputReport, dwCnt, &NumberOfBytesRead, NULL);
            for (DWORD i = 0; i < dwCnt; i++)
            {
                printf(" %d ", InputReport[i]);
            } 
        }

        Sleep(1000);
        printf("\r\n\r\n");
    }
}

void UsbOperation()
{
    TCHAR strDevicePath[MAX_PATH] = { 0 };
    HANDLE HidDeviceObject = INVALID_HANDLE_VALUE;
    HIDP_CAPS hidCap = { 0 };
    
    BYTE OutputReport[256] = { 0 };

    GetDevPath(strDevicePath);
    HidDeviceObject = OpenHidevice(strDevicePath);
    GetDeviceCapabilities(HidDeviceObject, hidCap);
    ReadUsbData(HidDeviceObject, hidCap.InputReportByteLength);
}

 

Test Results:

Intelligent Recommendation

usb hid communication STM32

Android USB_HID communication document Because I have been studying stm32 and need to use USB hid communication, I studied Android and stm32 for USB hid communication. At present, normal communication...

STM32-HAL

In order to use STM32 cubeMX tool to quickly complete the design, I plan to change from StdPeriph_Lib to HAL_Driver. When using cubeMX for the first time, it feels like entering the era of graphical i...

Development of custom HID equipment based on stm32 and communication with host computer (with source code)

At present, the mainstream Android mobile phone data connection lines, Mini-usb, Micro-usb, Type-c, products follow the mainstream, non-networked devices, abandon ST-LINK, JLINK, and directly upgrade ...

Custom HID&amp;DFU

General description The HID (human interface device) class primarily consists of devices that are used by humans to control the operation of computer systems. Typical examples of HID class devices are...

Custom USB HID device

Advantages of HID equipment: Windows system comes with HID device driver, so you don’t have to develop the driver yourself. Advantages of custom HID device: If it is not a custom HID, such as a ...

More Recommendation

STM32 USB slave HID analysis

STM32 USB slave HID analysis Chip: STM32F407VE Compiler: KEIL5 Author: SY Date: 2017-7-20 16:01:26 Overview willSTM32ofUSBInitialized toUSBSlave, using standardHIDprotocol. The control board comes wit...

STM32 create HID project (1)

Well, these days I finally started to relax again. Let’s continue the keyboard project. Last time I designed the circuit on the keyboard side. However, I decided to revise it. One is the wireles...

[STM32 HAL] HAL library and CUBEMX

HAL library Full title Hardware Abstract Layer (Abstract Impression Layer) is heightabstractBase, mentionabstractI don't know if you have any ideas, is it?abstractIt means it is difficult to understan...

[STM32] screen initialization in STM32 HAL

8080 interface and RGB interface of the screen (icode9.com) Based on STM32F429 RGB screen using _ hducollins blog - CSDN blog STM32Cubemx Development Road - LTDC Drive STM32F429i-Discover Show _iot - ...

Stm32 hal printf redirect

Usart1 configuration is as follows Open the interrupt (can also not open, just open it) Clock configuration: If it is not strictly required, it should be matched according to the software. If it is an...

Copyright  DMCA © 2018-2026 - All Rights Reserved - www.programmersought.com  User Notice

Top