esp32-snippets icon indicating copy to clipboard operation
esp32-snippets copied to clipboard

ESP32 BLE HID send crush symbols in the product description

Open ARPavel22 opened this issue 7 years ago • 45 comments

Hi, and Thank you for your great work!

I'm trying to create a gamepad for the UNITY. Everything works perfectly. The code works.

But when ESP connect to a computer, one of the parameters of HID is NOT recognized correctly. Most likely it is "PRODUCT NAME".

I think that Chinese people sewed their own hieroglyphics during the testing phase of the motherboard.

You can test the work of a hid with a simple program: Joystic test program http://www.planetpointy.co.uk/joystick-test-application/

Here are screenshots of poor performance:

At first it seems that everything is fine: joytest1

When switching to RAW INPUT program starts freezing because of bad characters: joytest2

Here is from Unity3D editor: joytest3

The problem is not in the name of the Bluetooth device. It is displayed correctly.

Can I change the other settings of the HID device?

ARPavel22 avatar Sep 28 '18 15:09 ARPavel22

You can use those function to setup hid specific parameters: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/BLEHIDDevice.h#L43-L49

chegewara avatar Sep 28 '18 15:09 chegewara

You can use those function to setup hid specific parameters: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/BLEHIDDevice.h#L43-L49

Thank you for the quick response. You showed me the right way to search.

NOTICE: I work with code from this post -> https://github.com/nkolban/esp32-snippets/issues/632

  • Changing the values of PNP I noticed an interesting feature. When the variable reaches the Unity editor, it is inverted:

joytest4

  • This leads to the thought that string manufacture also comes to be broken. Therefore, you can see the hieroglyphs and strange symbols in the name of the device.

  • After i swapped parts of the variable:

//hid-> pnp (0x02, 0x0810, 0xe501, 0x0106);
//CHANGE TO
hid-> pnp (0x02, 0x1008, 0x01e5, 0x0601);
  • I saw that in the UNITY3D editor they came as they should be.

joytest5

  • It seems to me that the bytes of the manufacturer are also inverted It remains to understand how to properly pass on the manufacture data?
    std::string name = "esp-community";
    hid->manufacturer()->setValue(name);

ARPavel22 avatar Sep 29 '18 12:09 ARPavel22

Hi, thanks for testing and explaining how you solved your issue. It is how bluetooth hid works, its so called little endian. Bytes order is swapped. What is strange its manufacturer name, in device manager ive been checking and it was displayed as it should be (some time ago). Could you check it please?

Also for vendorID you can check this site, espressif is 0x02E5(you dont have to use it): https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers

chegewara avatar Sep 29 '18 17:09 chegewara

Isn’t USB little endian?

And all descriptor strings are UNICODE (I think UTF-16)

I think the function, should swap endianness of the vid/pid …

void pnp(uint8_t sig, uint16_t vid, uint16_t pid, uint16_t version);

Just to make ones code cleaner

mitch

From: chegewara [email protected] Sent: Saturday, September 29, 2018 1:47 PM To: nkolban/esp32-snippets [email protected] Cc: Subscribed [email protected] Subject: Re: [nkolban/esp32-snippets] ESP32 BLE HID send crush symbols in the product description (#659)

Hi, thanks for testing and explaining how you solved your issue. It is how bluetooth hid works, its so called little endian. Bytes order is swapped. What is strange its manufacturer name, in device manager ive been checking and it was displayed as it should be (some time ago). Could you check it please?

Also for vendorID you can check this site, espressif is 0x02E5(you dont have to use it): https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/659#issuecomment-425663290 , or mute the thread https://github.com/notifications/unsubscribe-auth/AAtpXyBxMlgbNGbO3IysmuaCBjzsdWqmks5uf7INgaJpZM4W-scp . https://github.com/notifications/beacon/AAtpXwaFCyS4VUs0BVKPYTSsbZUuxH49ks5uf7INgaJpZM4W-scp.gif

mitchjs avatar Sep 29 '18 17:09 mitchjs

The fields in the above table are in the order of LSO to MSO. Where LSO = Least Significant Octet and MSO = Most Significant Octet

https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.pnp_id.xml

chegewara avatar Sep 29 '18 17:09 chegewara

The fields in the above table are in the order of LSO to MSO. Where LSO = Least Significant Octet and MSO = Most Significant Octet

https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.pnp_id.xml

I'm going to test your advice. But first I want to clarify the sequence of variables.

About HID INFO: hid->hidInfo(0x00,0x01);

  1. Country code: 0x00 = without country
  2. Some flags (which I did not understand) but just set 0x01

===================================================================

About PNP:

void BLEHIDDevice::pnp(uint8_t sig, uint16_t vid, uint16_t pid, uint16_t version) 

hid-> pnp (0x02, 0x1008, 0x01e5, 0x0601);
  1. SIG (Vendor ID Source): 0x01 = Bluetooth SIG assigned Company Identifier value from the Assigned Numbers document 0x02 = USB Implementer’s Forum assigned Vendor ID value (Should I use the first? 0x01)

  2. VID (Vendor ID) - Get from list: https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers

  3. PID (Product ID) ??? can i use 0x01?

  4. VERSION (Product Version) ??? can i use 0x01?

===================================================================

And last. What is passed in these two parameters? This is similar to the HID INFO? uint8_t val[] = {0x01, 0x00}; desc->setValue(val, 2);

  void onConnect(BLEServer* pServer){
    Serial.println("connected");
                // workaround after reconnect (see comment below) 
                BLEDescriptor *desc = input->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));
                uint8_t val[] = {0x01, 0x00};
                desc->setValue(val, 2);

                _connected = true;
  }

ARPavel22 avatar Sep 29 '18 20:09 ARPavel22

  1. Im guessing you should use 0x01 since you want to build bluetooth hid device;
  2. To be honest i dont know if you can use espressif VID, esp32 is espressif board but final product is not; you should ask this on espressif/esp-idf github or on esp32.com forum
  3. and 4. You can use whatever you want for PID
  4. Yes. There is no info about value being little endian, but its the same case: https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml

chegewara avatar Sep 29 '18 22:09 chegewara

Another sleepless night with ESP32 BLEt...

  • For a start I want to show is an example of a gamepad I made on a RN42 chip Everything works perfectly. We can see the name of the manufacturer and the name of the joystick. joytest6

  • I tried everything I could. I even changed the source so that it sends one character A to the manufactory on the init of device. const uint8_t pMode[] = {0x14};

BLECharacteristic* 	BLEHIDDevice::manufacturer() {
	m_manufacturerCharacteristic = m_deviceInfoService->createCharacteristic((uint16_t)0x2a29, BLECharacteristic::PROPERTY_READ);
	const uint8_t pMode[] = {0x14};
	m_manufacturerCharacteristic->setValue((uint8_t*)pMode, 1);
	return m_manufacturerCharacteristic;
}
  • I do tests on a PC and on an iPhone. On the iPhone I saw the symbol of the manufactory . joytest10

  • But the PC could not figure it out. In addition, I noticed another strange feature. Each reconnect of the ESP produces different symbols. As if bytes break in different sequences.

joytest71

P.S. :

I need the correct signature of the device in order to find it in the Unity3D input manager. The rest works as it should. The gamepad data is transmitted. So far I need to start another part of the project. But I will also return to this post because I can not finish the project without solving this problem.

ARPavel22 avatar Sep 30 '18 12:09 ARPavel22

As you can see all works fine with iPhone, which means you have issue with unity3d bluetooth library. Like i said, you can check on windows in device manager how your hid device is recognized.

chegewara avatar Sep 30 '18 13:09 chegewara

As you can see all works fine with iPhone, which means you have issue with unity3d bluetooth library. Like i said, you can check on windows in device manager how your hid device is recognized.

Perhaps this is a UNITY3D problem. I'll try to ask a question on their forum. But why then RN42 is recognized correctly?.. https://user-images.githubusercontent.com/38073729/46257090-b0912c80-c4bc-11e8-8067-ec1cb60d934b.png

ARPavel22 avatar Sep 30 '18 13:09 ARPavel22

Could you intercept raw advertising packet from RN42 and from esp32?

chegewara avatar Sep 30 '18 13:09 chegewara

Could you intercept raw advertising packet from RN42 and from esp32?

I will try to grab packets with this soft: https://www.hhdsoftware.com/device-monitoring-studio

If u can advice most simle soft or decision how to do this, please, send here.

ARPavel22 avatar Sep 30 '18 13:09 ARPavel22

I am using app on android, nRF connect.

chegewara avatar Sep 30 '18 13:09 chegewara

I am using app on android, nRF connect.

I do not have an android on hand. Only IOS version of nRF app:

logesp

And there is from device-monitoring-studio:

000000: Descriptor parsing failed. (UP), 2018-09-30 16:46:23,7194741

There is an assumption that there is a shift of a few bytes or something like that because of what everything breaks down.

ARPavel22 avatar Sep 30 '18 13:09 ARPavel22

Hi, any progress here?

chegewara avatar Oct 07 '18 04:10 chegewara

Hi, any progress here?

Hi. Unfortunately, I was busy with the rest of the project and wrote a question to UNITY3D just now.

Here is: https://forum.unity.com/threads/input-system-update.508660/page-7#post-3759496

I look forward to hearing from them and will investigate further.

ARPavel22 avatar Oct 07 '18 08:10 ARPavel22

Maybe there is some option to change name parsing to utf8? Because it looks like it is parsed with unicode standard probably.

chegewara avatar Oct 07 '18 15:10 chegewara

Maybe there is some option to change name parsing to utf8? Because it looks like it is parsed with unicode standard probably.

Good news. I received a response from the Unity team: https://forum.unity.com/threads/input-system-update.508660/page-7#post-3763249

We may be close to closing the issue...

ARPavel22 avatar Oct 08 '18 22:10 ARPavel22

Ok, now you can tell them that they are wrong. This is bluetooth specs. https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.manufacturer_name_string.xml Of course they can say that you can send UTF-16 as array of uint8 bytes. You seems to have 2 options. Ask them to add UTF-8 support or convert name in unity from UTF8 to UTF16.

@ARPavel22 or send name from esp32 in UTF16

chegewara avatar Oct 08 '18 22:10 chegewara

@ARPavel22 Are you using generic library in unity or did you have to buy ble library from asset store? I would like to play with unity hid too.

chegewara avatar Oct 08 '18 22:10 chegewara

@ARPavel22 Are you using generic library in unity or did you have to buy ble library from asset store? I would like to play with unity hid too.

There is new official INPUT SYSTEM (but in development yet): https://github.com/Unity-Technologies/InputSystem

For working with it repo you need Unity 2018.2.10f1 or upper

ARPavel22 avatar Oct 08 '18 22:10 ARPavel22

Great, i will try it. Ive been searching for ble library but before i could not find any for free. Time to run unity3d. Thanks.

chegewara avatar Oct 08 '18 22:10 chegewara

Great, i will try it. Ive been searching for ble library but before i could not find any for free. Time to run unity3d. Thanks.

I don't use BLE assets from store Just connect ESP32 BLE HID to my PC and its work. All connected HID devices found in Unity3D input manager automatically.

DOWNLOAD UNITY3D

ARPavel22 avatar Oct 08 '18 22:10 ARPavel22

@ARPavel22 Could you share your unity3d code? At least part with hid device. I see unity3d input plugin is under development so i can see what i can do to help.

chegewara avatar Oct 08 '18 22:10 chegewara

@ARPavel22 Could you share your unity3d code? At least part with hid device. I see unity3d input plugin is under development so i can see what i can do to help.

I did not write the code for joystick data processing. For now, I'm trying to figure out the device name.

  • Just download the repository of INPUT SYSTEM. (This is ready to open Unity3D project) https://github.com/Unity-Technologies/InputSystem
  • Then open the Unity.
  • Choose to OPEN a project.
  • Choose the unzipped folder of "InputSystem" (master).
  • Open the project.
  • And look in the window of the Input Debugger:

inp Then in the list of devices, double-click on the MOUSE to test and you will see all the parameters.

In this window you can see all the parameters of HID devices:

  • HID parameters.
  • button presses.
  • gamepad axes.
  • ect.

ARPavel22 avatar Oct 08 '18 23:10 ARPavel22

Ok, the problem is hard to solve. Unity devs are using standard windows HidD_GetManufacturerString. This function suppose to return wchar string. I have no idea how it should read hid this ble hid descriptor. Its not unity devs fault (my bad), you should rather ask microsoft community/devs why utf8 string which is properly read and parsed by windows drivers cant be passed properly in HidD_GetManufacturerString.

chegewara avatar Oct 09 '18 01:10 chegewara

Ok, the problem is hard to solve. Unity devs are using standard windows HidD_GetManufacturerString. This function suppose to return wchar string. I have no idea how it should read hid this ble hid descriptor. Its not unity devs fault (my bad), you should rather ask microsoft community/devs why utf8 string which is properly read and parsed by windows drivers cant be passed properly in HidD_GetManufacturerString.

https://forum.unity.com/threads/input-system-update.508660/page-7#post-3764593

ARPavel22 avatar Oct 09 '18 01:10 ARPavel22

How do I change this three files:

  • BLEHIDDevice.cpp
  • BLEHIDDevice.h
  • BLECharacteristic.h

to send string in UTF16?

my c++ is bad.

ARPavel22 avatar Oct 09 '18 02:10 ARPavel22

try this in your unity code: https://docs.microsoft.com/en-us/dotnet/api/system.text.encoder?view=netframework-4.7.2

https://docs.microsoft.com/en-us/dotnet/api/system.text.utf8encoding?view=netframework-4.7.2

chegewara avatar Oct 09 '18 02:10 chegewara

try this in your unity code: https://docs.microsoft.com/en-us/dotnet/api/system.text.encoder?view=netframework-4.7.2

It does not work. Unity3D gives access to the string already parsed. And it is either empty or mistakenly chosen manufactory of another connected device.

ARPavel22 avatar Oct 09 '18 04:10 ARPavel22