Content originally posted in LPCWare by mch0 on Sun Oct 05 03:33:48 MST 2014
Hi,
I can't give a tutorial on HID or C, but I'll try to give you a starter.
uint8_t *:
This is actually a perfect fit for the generic reports.
These are almost always defined as an array of n bytes (see report descriptor) and the uint8_t-pointer just points to the start of the report you want to receive (OUT) or send (IN).
Within the device you might then allocate two static arrays like uint8_t outreport[8] and uint8_t inreport[4].
The host sends an OUT-report with 8 bytes (uint8_t), 7 bytes as defined by your format and a terminating 0 for convenience.
On the host side this could look like this:
char buffer[8];
sprintf(buffer,"%03d:%03d",num1,num2);
hid_write(buffer);
Then these 8 bytes arrive at the device and are (see later) available in the buffer outreport.
On the device side you retrieve them like this:
if (2== sscanf((char*)outbuffer,"%d:%d",&num1,&num2))
{
// got them
...
}
Likewise for the answer you sprintf() on the device side into the inbuffer and sscanf() on the host side.
If your host program is compiled on a windows system make sure that you use ASCII-chars (bytes), not the native WCHAR type (16 bit).
You see, nothing arkward at all, just typecast the uint8_t-pointer to let it point to the type you need.
USB stack usage:
The NXP ROM stack could have been documented a little bit better, but for a simple HID device it's very easy.
The most important thing is to get used to callback functions. The device can NEVER EVER initiate any data transfer, it just can react to events.
So when something happens to an endpoint because THE HOST has done something your program is interrupted, the stack decodes the event and calls the endpoint handler.
Here this is HID_Ep_Hdlr().
You can then look at the event (3rd param) and take actions as appropriate.
Commonly you would react to these events:
USB_EVT_IN: The prepared IN-report has been sent (your ACK).
USB_EVT_OUT_NAK: The host tried to send a report, but the stack told the host to try later again. This is a good place for you to place a read request. Then the next try of the host will be accepted and you will get notified.
Example code:
USBD_API->hw->ReadReqEP(hUsb, pHidCtrl->epout_adr, outbuffer, 8);
USB_EVT_OUT: A new report from the host is availabe and you can retrieve it.
Example code:
n=USBD_API->hw->ReadEP(hUsb, pHidCtrl->epout_adr, outbuffer);
Now assume you want to PREPARE a report to the host:
This could like this (anywhere in the code) for your format:
n=USBD_API->hw->WriteEP(g_hUsb, pHidCtrl->epin_adr, inbuffer, 4);
When the host has retrieved this report you get the USB_EVT_IN event in the callback function.
For a starter or very short actions you can do all required actions within the callback handler.
For actions that take more time better set a flag (volatile variable) and handle the action in the background.
Mike