USB_DEVICE_HID_REQUEST_GET_PROTOCOL bug in LPC546 SDK 2.7.0.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

USB_DEVICE_HID_REQUEST_GET_PROTOCOL bug in LPC546 SDK 2.7.0.

912 Views
emblink182
Contributor III

I have recently updated SDK to 2.7.0 for LPC546 in my project and noticed set/get protocol errors during USB CV tests. 

The problem is in usb_device_hid.c file

                    case USB_DEVICE_HID_REQUEST_GET_PROTOCOL:
                        /* Get protocol request, classCallback is initialized in classInit of
                           s_UsbDeviceClassInterfaceMap,
                           it is from the second parameter of classInit */
                        error = hidHandle->configStruct->classCallback(
                            (class_handle_t)hidHandlekUSB_DeviceHidEventGetIdle, &hidHandle->protocol);
                        controlRequest->buffer = &hidHandle->protocol;
                        break;

kUsb_DeviceHidEventGetIdle should be replaced with kUsb_DeviceHidEventGetProtocol.

SDK 2.8.0 also has the same issue.

The second thing I want to pay attention to are these pieces of code.

                    case USB_DEVICE_HID_REQUEST_GET_IDLE:
                        /* Get idle request, classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
                           it is from the second parameter of classInit */
                        error = hidHandle->configStruct->classCallback(
                            (class_handle_t)hidHandle, kUSB_DeviceHidEventGetIdle, &hidHandle->idleRate);
                        controlRequest->buffer = &hidHandle->idleRate;
                        break;

 

                    case USB_DEVICE_HID_REQUEST_SET_IDLE:
                        /* Set idle request */
                        {
                            hidHandle->idleRate = (controlRequest->setup->wValue & 0xFF00U) >> 0x08U;
                            /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
                               it is from the second parameter of classInit */
                            error = hidHandle->configStruct->classCallback(
                                (class_handle_t)hidHandle, kUSB_DeviceHidEventSetIdle, &hidHandle->idleRate);
                        }
                        break;

pastedImage_2.png

From USB hid spec follows that get/set idle requests can be done to a particular report ID.

Report ID field - If the lower byte of wValue is zero, then the idle rate applies to all input reports generated by the device. When the lower byte of wValue is nonzero, then the idle rate only applies to the Report ID specified by the value of the lower byte.

But the parameters that are passed to a class Callback doesn't give info about the Report ID. Maybe I missing something but seem like this case is not handled properly.

Labels (2)
0 Kudos
2 Replies

799 Views
Sabina_Bruce
NXP Employee
NXP Employee

Hello Alex,

Hope you are doing well.

Firstly, thank you for reporting this bug. I will report it to our SDK team for review and correction.

Both set and get idle requests are configured that all the idlerate applies to all report IDs. As you may see in the description for both of these requests either the higher or lower byte is 0 which means all report IDs. This makes it portable to be able to be used by different devices which may have varying report IDs. So the driver can be used throughout. You may apply custom changes if you would like to specify a certain report ID only.

Hope this helps!

Best Regards,

Sabina

-----------------------------------------------------------------------------------------------------------------------

Note: If this post answers your question, please click the Correct Answer button. Thank you!

----------------------------------------------------------------------------------------------------------------------- 

0 Kudos

799 Views
emblink182
Contributor III

Hi Sabina. Thank you for your answer. But I can't agree with the next 2 statements.

1) Both set and get idle requests are configured that all the idlerate applies to all report IDs.

Yes, and this is not how it should be by USB hid specification.

2) As you may see in the description for both of these requests either the higher or lower byte is 0 which means all report IDs.

This is not correct.

The specification tells that only if the lower byte of wValue is zero, then the idle rate applies to all input
reports generated by the device. When the lower byte of wValue is nonzero, then the idle rate only applies to the Report ID specified by the value of the lower byte.

Seem like SDK code assumes that lower byte always is 0, but it's not always true.

In order to fix this, in both cases of set/get idle last argument should be changed

                        error = hidHandle->configStruct->classCallback(
                            (class_handle_t)hidHandle, kUSB_DeviceHidEventSetIdle, &hidHandle->idleRate);

with

                            error = hidHandle->configStruct->classCallback(
                                (class_handle_t)hidHandle, kUSB_DeviceHidEventSetIdle, &controlRequest->setup->wValue);

This will allow set and get idle rate for particular Report Id or to all of them as expected by USB hid spec.

I can make modifications of the SDK source code but it's not convenient and requires copy/pasting for every SDK update.

Here's the code from 2.2.0 SDK.

                    case USB_DEVICE_HID_REQUEST_GET_IDLE:
                        /* Get idle request */
                        error = hidHandle->configStruct->classCallback(
                            (class_handle_t)hidHandle, kUSB_DeviceHidEventGetIdle, &hidHandle->idleRate);
                        controlRequest->buffer = &hidHandle->idleRate;
                        break;

                    case USB_DEVICE_HID_REQUEST_SET_IDLE:
                        /* Set idle request */
                        {
                            hidHandle->idleRate = (controlRequest->setup->wValue & 0xFF00U) >> 0x08U;
                            error = hidHandle->configStruct->classCallback(
                                (class_handle_t)hidHandle, kUSB_DeviceHidEventSetIdle, &controlRequest->setup->wValue);
                        }
                        break;

I expect to see wValue in both callbacks, and from there decide how to apply it.

Here is a USB CV example of how the host may behave and set/get different idle rates for different Report Ids.

pastedImage_2.png

0 Kudos