Перейти к содержанию
    

STM32f103 Custom HID USB -> HIDAPI

Доброго времени суток

пытаюсь понять как работать с Custom HID

на основе статьи https://microtechnics.ru/stm32cube-usb-custom-hid-sozdanie-deskriptorov-ustrojstva/?ysclid=lcfzgdcyrl345227162

в контроллере сделал вот так

Spoiler
__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 (Generic Desktop)
    0x09, 0x01,                  // USAGE (Vendor Usage 1)
    
    // System Parameters
    0xa1, 0x01,                  // COLLECTION (Application)
    0x85, 0x01,                  // REPORT_ID (1)
    0x09, 0x01,                  // USAGE (Vendor Usage 1)
    0x15, 0x00,                  // LOGICAL_MINIMUM (0)
    0x25, 0x01,                  // LOGICAL_MAXIMUM (1)
    0x75, 0x08,                  // REPORT_SIZE (8)
    0x95, 4,                     // REPORT_COUNT (4)
    0xb1, 0x82,                  // FEATURE (Data,Var,Abs,Vol)
    0x85, 0x01,                  // REPORT_ID (1)
    0x09, 0x01,                  // USAGE (Vendor Usage 1)
    0x91, 0x82,                  // OUTPUT (Data,Var,Abs,Vol)
    0x85, 0x02,                  // REPORT_ID (2)
    0x09, 0x02,                  // USAGE (Vendor Usage 2)
    0x75, 0x08,                  // REPORT_SIZE (8)
    0x95, 4,                     // REPORT_COUNT (4)
    0x81, 0x82,                  // INPUT (Data,Var,Abs,Vol)
  /* USER CODE END 0 */
  0xC0    /*     END_COLLECTION	             */
};

static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state)
{
  /* USER CODE BEGIN 6 */
   USBD_CUSTOM_HID_HandleTypeDef     *hhid = (USBD_CUSTOM_HID_HandleTypeDef*)hUsbDeviceFS.pClassData;

  for (uint8_t i = 0; i < 4; i++)

  {

    dataToReceive[i] = hhid->Report_buf[i];

  } 
  
  if(dataToReceive[0]==0x01)
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET);
  else
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
  return (USBD_OK);
  /* USER CODE END 6 */
}
    
В мейне:
    
  /* USER CODE BEGIN 2 */
  dataToSend[0] = 'S';
  dataToSend[1] = 'n';
  dataToSend[2] = 'd';
  dataToSend[3] = '\0';
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    HAL_Delay(1000);
    USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, dataToSend, 4);
    /* USER CODE BEGIN 3 */
  }

Проблемы с тем на базе какой библиотеки на компе код удобней делать. в исходной статье применяли libusb но почему-то не смог найти той версии, по которой делали статью. по другим статьям тоже ничего не вышло

Смотрел WinUSB там вообще не понятно как этим пользоваться

взял HIDAPI на ней по примерам получилось увидеть мою плату но не получается отправить и получить данные

Spoiler
#include <iostream>
#include <windows.h>
#include <winusb.h>
#include <usb.h>

#include "hidapi.h"

void print_device(struct hid_device_info* cur_dev) {
    printf("Device Found\n  type: %04hx %04hx\n  path: %s\n  serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
    printf("\n");
    printf("  Manufacturer: %ls\n", cur_dev->manufacturer_string);
    printf("  Product:      %ls\n", cur_dev->product_string);
    printf("  Release:      %hx\n", cur_dev->release_number);
    printf("  Interface:    %d\n", cur_dev->interface_number);
    printf("  Usage (page): 0x%hx (0x%hx)\n", cur_dev->usage, cur_dev->usage_page);
    printf("  Bus type: %d\n", cur_dev->bus_type);
    printf("\n");
}

void print_devices(struct hid_device_info* cur_dev) {
    while (cur_dev) {
        print_device(cur_dev);
        cur_dev = cur_dev->next;
    }
}

int main(int argc, char* argv[])
{
    (void)argc;
    (void)argv;

    int res;
    unsigned char buf[256];
#define MAX_STR 255
    wchar_t wstr[MAX_STR];
    hid_device* handle;
    int i;

   // struct hid_device_info* devs;

    if (hid_init())
        return -1;

   // devs = hid_enumerate(0x0, 0x0);
   // print_devices(devs);
   // hid_free_enumeration(devs);

    // Set up the command buffer.
    memset(buf, 0x00, sizeof(buf));
    buf[0] = 0x01;
    buf[1] = 0x81;


    // Open the device using the VID, PID,
    // and optionally the Serial number.
    ////handle = hid_open(0x4d8, 0x3f, L"12345");
    handle = hid_open(0x0485, 0x5752, NULL);
    if (!handle) {
        printf("unable to open device\n");
        hid_exit();
        return 1;
    }

    // Read the Manufacturer String
    wstr[0] = 0x0000;
    res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
    if (res < 0)
        printf("Unable to read manufacturer string\n");
    printf("Manufacturer String: %ls\n", wstr);

    // Read the Product String
    wstr[0] = 0x0000;
    res = hid_get_product_string(handle, wstr, MAX_STR);
    if (res < 0)
        printf("Unable to read product string\n");
    printf("Product String: %ls\n", wstr);

    // Read the Serial Number String
    wstr[0] = 0x0000;
    res = hid_get_serial_number_string(handle, wstr, MAX_STR);
    if (res < 0)
        printf("Unable to read serial number string\n");
    printf("Serial Number String: (%d) %ls", wstr[0], wstr);
    printf("\n");

    struct hid_device_info* info = hid_get_device_info(handle);
    if (info == NULL) {
        printf("Unable to get device info\n");
    }
    else {
        print_devices(info);
    }
/*
    // Read Indexed String 1
    wstr[0] = 0x0000;
    res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
    if (res < 0)
        printf("Unable to read indexed string 1\n");
    printf("Indexed String 1: %ls\n", wstr);
    */
    // Set the hid_read() function to be non-blocking.
    hid_set_nonblocking(handle, 1);


    struct
    {
        uint8_t reportID;
        uint8_t data[4];
    } report;

    report.reportID = 0x01;
    report.data[0] = 0x01;
    res = hid_write(handle, (const unsigned char*)&report, sizeof(report));
    if (res < 0) {
        printf("Unable to write(report): %ls\n", hid_error(handle));
    }

    res = hid_send_feature_report(handle, (const unsigned char*)&report, sizeof(report));
    if (res < 0) {
        printf("((Unable to send a feature report)).\n");
    }






    buf[0] = 0x81;
    res = hid_get_feature_report(handle, buf, 5);
    if (res < 0) {
        printf("Unable to get a feature report: %ls\n", hid_error(handle));
    }
    else {
        // Print out the returned buffer.
        printf("Feature Report\n   ");
        for (i = 0; i < res; i++)
            printf("%02x ", (unsigned int)buf[i]);
        printf("\n");
    }
    memset(buf, 0, sizeof(buf));
    // Send a Feature Report to the device
    buf[0] = 0x01;
    buf[1] = 0x01;
    buf[2] = 0x01;
    buf[3] = 0x01;
    buf[4] = 0x01;
    res = hid_send_feature_report(handle, buf, 4);
    if (res < 0) {
        printf("Unable to send a feature report.\n");
    }

    
    
    
    
    memset(buf, 0, sizeof(buf));

    // Toggle LED (cmd 0x80). The first byte is the report number (0x1).
    buf[0] = 0x01;
    buf[1] = 0x01;
    buf[2] = 0x01;
    res = hid_write(handle, buf, 4);
    if (res < 0) {
        printf("Unable to write(): %ls\n", hid_error(handle));
    }
    memset(buf, 0, sizeof(buf));

    // Request state (cmd 0x81). The first byte is the report number (0x1).
    buf[0] = 0x01;
    buf[1] = 0x81;
    hid_write(handle, buf, 4);
    if (res < 0) {
        printf("Unable to write()/2: %ls\n", hid_error(handle));
    }
    
    // Read requested state. hid_read() has been set to be
    // non-blocking by the call to hid_set_nonblocking() above.
    // This loop demonstrates the non-blocking nature of hid_read().    res = 0;
    i = 0;
    while (res == 0) {
        res = hid_read(handle, buf, 4);
        if (res == 0) {
            printf("waiting...\n");
        }
        if (res < 0) {
            printf("Unable to read(): %ls\n", hid_error(handle));
            break;
        }

        i++;
        if (i >= 10) { /* 10 tries by 500 ms - 5 seconds of waiting*/
            printf("read() timeout\n");
            break;
        }

        Sleep(500);

    }

    if (res > 0) {
        printf("Data read:\n   ");
        // Print out the returned buffer.
        for (i = 0; i < res; i++)
            printf("%02x ", (unsigned int)buf[i]);
        printf("\n");
    }

    hid_close(handle);

    /* Free static HIDAPI objects. */
    hid_exit();

#ifdef _WIN32
    system("pause");
#endif

    return 0;
}

Кто какие библиотеки использует? Может у кого есть рабочий пример для стороны контроллера и компа?

Изменено пользователем haker_fox
Длинный код нужно прятать под спойлер.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот функции записи и чтения данных HID-устройства из моего проекта. В программе используется HID API с отслеживанием событий подключения и отключения устройств.

Spoiler
int CCDevWritePacket(hid_device *hiddev, unsigned char *buff, int len)
{
	unsigned char repbuf[CCREP_SIZE+1];
	int wr = 0, writed = 0, bwrited = 0;;

	while (len > 0)
	{
		wr = len;
		if (wr > CCREP_SIZE-2)
			wr = CCREP_SIZE-2;

		repbuf[0] = CCREP_ID;
		repbuf[1] = wr;
		memcpy(repbuf+2, buff+bwrited, wr);
		if ((writed = hid_write(hiddev, repbuf, CCREP_SIZE+1)) < wr)
		{
			return 1;
		}
		len -= wr;
		bwrited += wr;
	}

	return 0;
}
// -----------------------------------------------------------------------------------





int CCDevReadPacket(hid_device *hiddev, unsigned char *buff)
{
	unsigned char repbuf[CCREP_SIZE+1];
	GFPACKET *pack = (GFPACKET*)buff;
	DWORD	rd = 0, readed = 0;
	BOOL	fullpacket = false;
	while (1)
	{
		if ((rd = hid_read_timeout(hiddev, repbuf, CCREP_SIZE+1, 1000)) < CCREP_SIZE)
		{
			return 1;
		}
		if (repbuf[0] == CCREP_ID)
		{
			memcpy(buff+readed, repbuf+2, repbuf[1]);
			readed += repbuf[1];
			if (readed > 7)
			{
				if (readed == pack->dlen + 8)
				{
					unsigned short crc = 0;
					unsigned short *pcrc = (unsigned short*)(buff+6+pack->dlen);
					for (DWORD i = 0; i < readed-2; i++)
						crc += buff[i];
					if (pack->header == PID_HEADER && crc == *pcrc)
						fullpacket = true;
					break;
				}
			}
			if (readed > 1100)
				break;
		}
	}
	if (fullpacket)
		return 0;
	return 1;
}
// -----------------------------------------------------------------------------------




 

Изменено пользователем haker_fox
Длинный код нужно прятать под спойлер.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Модератор: длинный код прячем под спойлер. Это кнопка с глазом на панели редактора. Потом самим же удобнее читать тему, не пролистывая километровые простыни кода.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...