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

USB custom hid, длина пакета

Всем привет!

Пытаюсь запуститить Custom HID на stm32f103c8t6, пример стандартный, вот отсюда STM32Cube_FW_F1_V1.8.0

дескриптор репорта взял из примеров от микрочипа 

__ALIGN_BEGIN static uint8_t
  CustomHID_ReportDesc[29] __ALIGN_END = {
    0x06, 0x00, 0xFF,       // Usage Page = 0xFF00 (Vendor Defined Page 1)
    0x09, 0x01,             // Usage (Vendor Usage 1)
    0xA1, 0x01,             // Collection (Application)
    0x19, 0x01,             //      Usage Minimum 
    0x29, 0x40,             //      Usage Maximum   //64 input usages total (0x01 to 0x40)
    0x15, 0x00,             //      Logical Minimum (data bytes in the report may have minimum value = 0x00)
    0x26, 0xFF, 0x00,       //      Logical Maximum (data bytes in the report may have maximum value = 0x00FF = unsigned 255)
    0x75, 0x08,             //      Report Size: 8-bit field size
    0x95, 0x40,             //      Report Count: Make sixty-four 8-bit fields (the next time the parser hits an "Input", "Output", or "Feature" item)
    0x81, 0x00,             //      Input (Data, Array, Abs): Instantiates input packet fields based on the above report size, count, logical min/max, and usage.
    0x19, 0x01,             //      Usage Minimum 
    0x29, 0x40,             //      Usage Maximum 	//64 output usages total (0x01 to 0x40)
    0x91, 0x00,             //      Output (Data, Array, Abs): Instantiates output packet fields.  Uses same report size and count as "Input" fields, since nothing new/different was specified to the parser since the "Input" item.
    0xC0                   // End Collection
}; 

Так как здесь id репорта не указан, видимо он нулевой, и длина пакета 64 байта, правильно? 

Вот код из контроллера, размер буфера 64 байта, в нулевой байт приходит команда с компа.

static int8_t CustomHID_OutEvent(uint8_t event_idx, uint8_t state)
{
  uint8_t rxData[USBD_CUSTOMHID_OUTREPORT_BUF_SIZE]; // 64 байта
  
  USBD_CUSTOM_HID_HandleTypeDef *hhid = (USBD_CUSTOM_HID_HandleTypeDef *)USBD_Device.pClassData;
  
  for (uint8_t i = 0; i < USBD_CUSTOMHID_OUTREPORT_BUF_SIZE; i++)
  {
    rxData[i] = hhid->Report_buf[i];
  }

  if(rxData[0] == 0x80)
  {
    BSP_LED_Toggle(LED1);
  }

Вот кусок проги для компа

//Check if this thread should send a Toggle LED(s) command to the firmware.  ToggleLEDsPending will get set
//by the ToggleLEDs_btn click event handler function if the user presses the button on the form.
if (ToggleLEDsPending == true)
{
  OUTBuffer[0] = 0x0;			//The first byte is the "Report ID" and does not get sent over the USB bus.  Always set = 0.
  OUTBuffer[1] = 0x80;			//0x80 is the "Toggle LED(s)" command in the firmware
  for (uint i = 2; i < 65; i++)	//This loop is not strictly necessary.  Simply initializes unused bytes to
      OUTBuffer[i] = 0xFF;		//0xFF for lower EMI and power consumption when driving the USB cable.
  //Now send the packet to the USB firmware on the microcontroller
  WriteFile(WriteHandleToUSBDevice, OUTBuffer, 65, ref BytesWritten, IntPtr.Zero);	//Blocking function, unless an "overlapped" structure is used
  ToggleLEDsPending = false;
}

Здесь размер буфера 65 байт,  нулевой байт Report ID, и первый - команда.

Подскажите, почему так происходит, нулевой байт пересылается в контроллер? Почему у нас буфер 65 байт, а не 64? Т.е. получается в контроллер идет пакет длиной 64+1?

И еще один вопрос, после перепрошивки фирмваре контроллера, можно как-то сделать, чтобы он определялся компом безе передергивания юсб?

Спасибо!

 

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


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

29 minutes ago, compote said:

Подскажите, почему так происходит, нулевой байт пересылается в контроллер?

 

29 minutes ago, compote said:

The first byte is the "Report ID" and does not get sent over the USB bus.

 

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


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

Так это и не понимаю, поэтому и вопрос. Куда этот байт идет, и почему он отправляется, если он в контроллер не идет?  Если его изменить, например, написать 0x01, то контроллер уже не видит пакета, значит все таки этот байт как участвует в процессе-) 

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


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

Report ID отправляется по шине только в том случае, если его значение не равно нулю. Нужен для разделения нескольких report'ов на одной конечной точке.

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


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

12 минут назад, aaarrr сказал:

Report ID отправляется по шине только в том случае, если его значение не равно нулю

Спасибо! Получается, если Report_ID = 1, то тогда программа на компе будет отправлять 64 байта, а не 65 байт, где нулевой байт будет Report_ID и останется еще 63 байта для данных, так? Т.е. Report_ID будет входить в длину пакета 64 байта? Или все таки Report_ID в любом случае не входит в 64 байта? Просто не пойму, на стороне контроллера пакет 64 байта, на компе 65 байт. 

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


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

 

Цитата

Здесь размер буфера 65 байт,  нулевой байт Report ID, и первый - команда.

Подскажите, почему так происходит, нулевой байт пересылается в контроллер? Почему у нас буфер 65 байт, а не 64? Т.е. получается в контроллер идет пакет длиной 64+1? 

Размер буфера везде должен быть 64 байта, больше F103 не тянет. Report ID входит в состав этого буфера, как нулевой байт. Посылать тоже надо все 64 байта, а не 65, хотя лишнее девайс может отрезать сам, если прошивку для него писал умный человек :).

 

Цитата

И еще один вопрос, после перепрошивки фирмваре контроллера, можно как-то сделать, чтобы он определялся компом безе передергивания юсб?

Перед инициализацией USB опустите ногу PA12 (линия USB+) вниз до земли и подержите так 1 секунду. После инициализации USB вам эо уже не удастся сдеалть, т.к. PA12 будет переключена на альтенативную функцию.

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


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

6 минут назад, Xenia сказал:

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

Спасибо! Понятно, что размер буфера на контроллере 64 байта, но с компа идет 65 байт, куда один байт девается?

Пробовал проверять, если нулевой байт на компе, меняешь на 0x01, то пакет не доходит, нулевой байт как раз и есть Report_ID. Затем попробовал отправить команду не в первом байте, а со смещением 64 байта, команда на контроллере будет по смещению 63 байта. Т.е. получатся на контроллер приходит пакет данных 64 байта, а Report_ID идет отдельно?

может неправльно задаю вопрос, давайте вот так

Почему WriteFile отправляет 65 байт, а не 64, где нулевой Report_ID?

WriteFile(WriteHandleToUSBDevice, OUTBuffer, 65, ref BytesWritten, IntPtr.Zero);

 

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


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

1 час назад, compote сказал:

Почему WriteFile отправляет 65 байт, а не 64, где нулевой Report_ID?


WriteFile(WriteHandleToUSBDevice, OUTBuffer, 65, ref BytesWritten, IntPtr.Zero);

WriteFile отправляет ровно столько, сколько ему указали. Спросите себя сами, зачем вы ему число 65 наквасили.
 Тем более что размер массива OUTBuffer[] вы не указали, а я телепатическими способностями не обладаю.

 

Еще раз повторю: OUTBuffer[] должен быть длиной 64 байта, посылать его надо с самого начала все его 64 байта. При этом нулевой байт (OUTBuffer[0]) резервируется под служебные цели, а следующие за ним остальные 63 байта можете заполнять, чем хотите.

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


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

10 часов назад, Xenia сказал:

Спросите себя сами, зачем вы ему число 65 наквасили

Вот у меня и нет на это ответа, зачем ему столько наквасили-) Это рабочий пример из MLA от Microchip.

10 часов назад, Xenia сказал:

размер массива OUTBuffer[]

Byte[] OUTBuffer = new byte[65];

10 часов назад, Xenia сказал:

OUTBuffer[] должен быть длиной 64 байта, посылать его надо с самого начала все его 64 байта. При этом нулевой байт (OUTBuffer[0]) резервируется под служебные цели, а следующие за ним остальные 63 байта можете заполнять, чем хотите

В этом и вопрос, прога работает, приходит на контроллер  весь массив, кроме нулевого байта-) , т.е. OUTBuffer[1] ... OUTBuffer[64]

Если на компе OUTBuffer[1] = 0x80, то вот этот код на контроллере работает, т.е. в нулевом адресе пакета приходит этот байт, а не ноль, который был на компе. 

if(rxData[0] == 0x80)
  {
    BSP_LED_Toggle(LED1);
  }

Может быть, если Report_ID = 0, то все 64 байта пакета отдаются под данные? Чуть позже покажу скрин из отладки с данными из пакета.

 

Заполняем буфер на PC, размерность 65 байт, полностью отправляем

Screenshot_4.thumb.jpg.a1f480e7e11fa5035720f9296d183cae.jpg

 

вот что приходит на контроллер

Screenshot_1.thumb.jpg.19033c45930d2d569f39efa1789e9140.jpg

 

Screenshot_2.thumb.jpg.44a4f88506182688344afbb463597822.jpg

 

Т.е. с PC отправляем 65 байт, приходит на контроллер 64 байта, котороые можно полностью использовать под данные. Что это за нулевой байт отправляемый с PC, которй не доходит до контроллера.

Спасибо!

Изменено пользователем compote

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


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

Если отправляешь 65 байт должно дойти именно 65 , но в два захода сначала первый пакет 64 байта, затем второй 1 байт . Нулевой или не полный пакет (менее 64 байт ) говорит об окончаний запроса . Если сделаешь размер точки 8 байт , то уйдёт 8 пакетов по 8 байт и 9 пакет 1 байт.

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


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

13 минут назад, геннадий75 сказал:

отправляешь 65 байт должно дойти именно 65

Два последних скрина, пришло 64 байта, нулевой байт на контроллере, это первый на PC. Нулевой же байт на PC потерялся. 

Немного почитал, пишут, что если Report_ID = 0, то все данные пакета отдаются под данные.  

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


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

10 минут назад, compote сказал:

Немного почитал, пишут, что если Report_ID = 0, то все данные пакета отдаются под данные.  

И как вторая сторона отличит этот пакет с первым байтом данных, равным 1 от другого, у которого в первом байте передается report_id = 1?

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


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

4 minutes ago, Сергей Борщ said:

И как вторая сторона отличит этот пакет с первым байтом данных, равным 1 от другого, у которого в первом байте передается report_id = 1?

Так вторая сторона по определению в курсе, должен быть Report ID, или нет.

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


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

19 минут назад, Сергей Борщ сказал:

И как вторая сторона отличит этот пакет с первым байтом данных, равным 1 от другого, у которого в первом байте передается report_id = 1?

Скорее всего по дескриптору репорта. 

Осталось только понять, если Report ID не равен нулю, с компа надо отправлять 64 байта?-)

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


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

1 час назад, compote сказал:

Скорее всего по дескриптору репорта. 

Поставьте себя на место второй стороны. Вот пришел пакет. Как вы его будете разбирать? Как только вы осознаете, что вторая сторона никак не сможет различать такие посылки - вы поймете, что вы или прочитали какой-то ненадежный источник, или поняли его неправильно. В Device Class Definition for Human Interface Devices (HID) четко сказано:
 

Цитата

If no Report ID item tags are present in the Report descriptor, it can be assumed that only one Input, Output, and Feature report structure exists and together they represent all of the device’s data.

...

If a device has multiple report structures, all data transfers start with a 1-byte identifier prefix that indicates which report structure applies to the transfer.

Т.е. если ваше устройство имеет только один тип Report-а, то он не передается. И номер его совершенно ни при чем. Во всех остальных случаях ReportID передается.

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


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

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

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

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

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

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

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

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

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

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