Hello Daniele
As a reminder (I see that you have invested several months so far trying to get the various examples working).
You can get complete industrial proven USB-HID for keyboards in the uTasker KL26 project that will allow you to complete the work with no further delays (and mix with other composite classes) - you can also simulate the operation for study or software auditing purposes in its KL26 simulator.
The control of the status outputs is in fact very simple and I have attached descriptors (in attached file) as well as the endpoint 0 callback function (code snippet below) which controls the LED status. You may be able to see something so that you can patch one of the various frameworks and examples that you have been experimenting with to solve it in your case.
Generally, however, I wouldn't expect the USB interface part of a keyboard to consume more that a day of actual work effort in a project development.
Regards
Mark
// Endpoint 0 call-back for any non-supported control transfers.
// This can be called with either setup frame content (iType != 0) or with data belonging to following OUT frames.
// TERMINATE_ZERO_DATA must be returned to setup tokens with NO further data, when there is no response sent.
// BUFFER_CONSUMED_EXPECT_MORE is returned when extra data is to be received.
// STALL_ENDPOINT should be returned if the request in the setup frame is not expected.
// Return BUFFER_CONSUMED in all other cases.
//
// If further data is to be received, this may arrive in multiple frames and the call-back needs to manage this to be able to know when the data is complete
//
static int control_callback(unsigned char *ptrData, unsigned short length, int iType)
{
int iRtn = BUFFER_CONSUMED;
switch (iType) {
case STATUS_STAGE_RECEPTION: // this is the status stage of a control transfer - it confirms that the exchange has completed and can be ignored if not of interest to us
return BUFFER_CONSUMED;
case SETUP_DATA_RECEPTION:
{ USB_SETUP_HEADER *ptrSetup = (USB_SETUP_HEADER *)ptrData; // interpret the received data as a setup header
if ((ptrSetup->bmRequestType & ~STANDARD_DEVICE_TO_HOST) != REQUEST_INTERFACE_CLASS) { // 0x21
return STALL_ENDPOINT; // stall on any unsupported request types
}
usExpectedData = ptrSetup->wLength[0]; // the amount of additional data which is expected to arrive from the host belonging to this request
usExpectedData |= (ptrSetup->wLength[1] << 8);
if (ptrSetup->bmRequestType & STANDARD_DEVICE_TO_HOST) { // request for information
usExpectedData = 0; // no data expected to be received by us
switch (ptrSetup->bRequest) {
case USB_REQUEST_GET_DESCRIPTOR: // standard request
if (ptrSetup->wValue[1] == DESCRIPTOR_TYPE_REPORT) {
fnWrite(USB_control, (unsigned char *)&ucKeyboardReport, sizeof(ucKeyboardReport)); // return directly (non-buffered)
}
else {
return STALL_ENDPOINT; // not supported
}
break;
default:
return STALL_ENDPOINT; // stall on any unsupported requests
}
}
else { // command
iRtn = TERMINATE_ZERO_DATA; // acknowledge receipt of the request if we have no data to return (default)
switch (ptrSetup->bRequest) {
case HID_SET_IDLE: // 0x0a - this can silence a report
break; // answer with zero data
case HID_SET_REPORT: // 0x09 - set report
return BUFFER_CONSUMED_EXPECT_MORE; // the present buffer has been consumed but extra data is subsequently expected
default:
return STALL_ENDPOINT; // stall on any unsupported requests
}
}
if (length <= sizeof(USB_SETUP_HEADER)) {
return iRtn; // no extra data in this frame
}
length -= sizeof(USB_SETUP_HEADER); // header handled
ptrData += sizeof(USB_SETUP_HEADER);
}
// Fall through intentionally
//
default: // OUT_DATA_RECEPTION
if (usExpectedData != 0) {
// Handle and control commands here
//
switch (ucCollectingMode) {
default:
fnSetKeyboardOutput(*ptrData); // assumed to be set report with a single byte content
break;
}
ucCollectingMode = 0; // reset to avoid repeat of command when subsequent, invalid commands are received
if (length >= usExpectedData) {
usExpectedData = 0; // all of the expected data belonging to this transfer has been received
return TERMINATE_ZERO_DATA;
}
else {
usExpectedData -= length; // remaining length to be received before transaction has completed
}
return BUFFER_CONSUMED_EXPECT_MORE;
}
break;
}
return iRtn;
}
static void fnSetKeyboardOutput(unsigned char ucOutputs) // assumed to be set report with a single byte content
{
// Directly change the state of outputs according to the states
//
if (ucOutputs & 0x01) {
_SETBITS(B, LED_1);
}
else {
_CLEARBITS(B, LED_1);
}
if (ucOutputs & 0x02) {
_SETBITS(B, LED_2);
}
else {
_CLEARBITS(B, LED_2);
}
}