0

I'm trying to make HID on STM32 board. But i stuck with next problem: I don't understand where my mistake, i passing a pointer to struct which contains data for report function, but when i try to compile code i get next messsage: argument of type "keyboardHID *" is incompatible with parametr of type "uint8_t *" I write code in the same way like man from this video https://www.youtube.com/watch?v=tj1_hsQ5PR0. In his case, this is not a critical error and code compiles.

My struct:

typedef struct
{
    uint8_t MODIFIER;
    uint8_t RESERVED;
    uint8_t KEYCODE1;
    uint8_t KEYCODE2;
    uint8_t KEYCODE3;
    uint8_t KEYCODE4;
    uint8_t KEYCODE5;
    uint8_t KEYCODE6;
} keyboardHID;

keyboardHID keyboardhid = {0,0,0,0,0,0,0,0}; // it should be like this, not differently

Code that modifies structure elements and sends reports to the computer:

keyboardhid.MODIFIER = 0x02;  // left Shift
        keyboardhid.KEYCODE1 = 0x04;  // press 'a'
        keyboardhid.KEYCODE2 = 0x05;  // press 'b'
        USBD_HID_SendReport(&hUsbDeviceFS, &keyboardhid, sizeof (keyboardhid));
        HAL_Delay (50);
        
        keyboardhid.MODIFIER = 0x00;  // shift release
        keyboardhid.KEYCODE1 = 0x00;  // release key
        keyboardhid.KEYCODE2 = 0x00;  // release key
        USBD_HID_SendReport(&hUsbDeviceFS, &keyboardhid, sizeof (keyboardhid));
        HAL_Delay (1000);
Pablo
  • 9
  • 1
  • 4
    The message is clear. You're using a `keyboardhid *` in a place where a `uint8_t *` is expected. Your compiler is helpful and issues a diagnostic. **IF YOU ARE CERTAIN IT'S OK** you can try a cast `USBD_HID_SendReport(&hUsbDeviceFS, (uint8_t*)&keyboardhid, sizeof (keyboardhid));`... but don't tell anybody I even suggested this. Again, for extra emphasis: **ONLY DO THIS IF YOU'RE CERTAIN IT'S OK**. – pmg Apr 28 '21 at 19:53
  • Thanks for the answer. It works and that's enough for me – Pablo Apr 28 '21 at 20:04
  • A man who teaches programming in a video is not to be taken seriously. – Armali Apr 29 '21 at 06:50

1 Answers1

1

C allows implicit pointer conversions only to void*. Types uint8_t and keyboardHID are not compatible, neither their pointer. I assume that uint8_t is unsigned char but C standard does not require it.

Usually, functions that process memory directly should use void* like memcpy() or memset() but it looks that USBD_HID_SendReport() is not following this convention.

You can:

  1. Cast &keyboardhid to uint8_t*. It's safe because character types have the least alignment requirements. Moreover, characters are an explicit exception to strict aliasing rules.

  2. Use &keyboardhid.MODIFIER. C standard requires the address of the structure to be the same as an address of its first element. IMO, it is the most obscure way.

  3. Use an union.

union {
  keyboardHID keyboardhid;
  uint8_t bytes[sizeof(keyboardHID)];
} u;

And pass u.bytes to USBD_HID_SendReport().

I would go for option 1 as it is the simplest and safe. Option 3 will be the best if keyboardhid had to be cast to something other than void* or a pointer to character type (i.e. uint32_t*).

tstanisl
  • 13,520
  • 2
  • 25
  • 40