Increase Report Size From 64 bytes to 256 bytes CUSTOM USB HID? - usb

I want to transfer 256 bytes from host to stm32f103 device over USB Custom HID interface
Currently, 64 bytes Read/Write is Working
Following is the Report Descriptor in my stm32:
/** Usb HID report descriptor. */
static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END ={
0x06,0x00,0xFF, //Usage Page 0xff00
0x09, 0x01, //USAGE (Pointer)
0xA1,0x01, //Collection (application)
//Input Report
0x19,0x01, //Usage Minimum
0x29,0x40, //Usage Minimum
0x15,0x00, //Logical Minimum
0x26,0xFF,0x00, //Logical Minimum
0x75,0x08, //report size : 8-bit field size
0x95, CUSTOM_HID_EPIN_SIZE,//Report count
0x81,0x02, //Input (data, array, Abs)
//Output Report
0x19,0x01, //usage Minimum
0x29,0x40, //usage Minimum
0x75,0x08, //report size : 8-bit field size
0x95,CUSTOM_HID_EPOUT_SIZE,//Report Count
0x91,0x02, //Output (data, array, Abs)
0xC0 //END_COLLECTION
};
If, I am changing the CUSTOM_HID_EPIN_SIZE,CUSTOM_HID_EPOUT_SIZE to 256, my USB device is not recognized.
I need some help to modify the report descriptor to support 256 byte transfer
Thanks

Related

BTLE ServiceData is always null

I am working on a react-native Android app using react-native-ble-plx for BTLE support, and Windows 10 using the .NET API Windows.Devices.Bluetooth.GenericAttributeProfile for the GATT server/peripheral.
When I add any "ServiceData" to the advertising payload in the Windows GATT service, the scanned device's 'serviceData' payload is always null in the react-native client.
In the Windows 10 server, if the GattServiceProviderAdvertisingParameters.ServiceData property is not null, then the service advertisement status is GattServiceProviderAdvertisementStatus.StartedWithoutAllAdvertisementData. (When leaving 'ServiceData' set to null, it is GattServiceProviderAdvertisementStatus.Started, as expected).
Using the Silicon Labs "EFR Connect" app in android, it also does not show any ServiceData for the device in the advertising packet.
Using WireShark with BTVS to inspect the packets on the Windows machine, it does show the Service Data bytes, and the controller shows a 'Success' response.
Here is the code where I set up the ServiceData in Windows:
...
GattServiceProviderAdvertisingParameters advParameters = new GattServiceProviderAdvertisingParameters
{
IsConnectable = _peripheralSupported,
IsDiscoverable = true,
ServiceData = GetServiceData().AsBuffer()
};
_serviceProvider.AdvertisementStatusChanged += ServiceProvider_AdvertisementStatusChanged;
_serviceProvider.StartAdvertising(advParameters);
...
private byte[] GetServiceData()
{
var flagsData = new List<byte> { 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
flagsData.AddRange(new List<byte>(Encoding.ASCII.GetBytes("ABCDEFGHIJKLMNOP")));
return flagsData.ToArray();
}
Here is the code in the react-native scanner:
public scanDevices(
timeoutSeconds: number,
listener: (error: string | null, scannedDevice: IPhoenixDevice | null) => void,
): void {
console.log('Entered PhoenixDeviceManager.scanDevices');
this.isScanning = true;
try {
this.scannedDevices.length = 0; // Clear array of devices
this.bleManager.startDeviceScan(this.serviceUUIDs, null, (error, scannedDevice) => {
console.log('In device scan callback');
if (error) {
console.warn(error);
listener(`Error message: ${error.message}, reason: ${error.reason}`, null);
}
if (!scannedDevice) {
console.log('scannedDevice is null');
} else if (!this.scannedDevices.some((d) => d.id === scannedDevice.id)) {
this.scannedDevices.push(scannedDevice);
listener(null, new PhoenixDevice(scannedDevice.id, scannedDevice.name));
console.log(
`Device discovered, id: ${scannedDevice.id}, name: ${scannedDevice.name}, localName: ${scannedDevice.localName}, serviceData: ${scannedDevice.serviceData}`,
);
}
});
const timeoutMs = timeoutSeconds * 1000;
// stop scanning devices after specified number of seconds
setTimeout(() => {
this.stopScanning();
}, timeoutMs);
} catch (error) {
console.error(error);
this.stopScanning();
}
}
Here is the WireShark trace running on Windows 10 showing the packet containing the ServiceData (and the Success response):
Frame 499: 84 bytes on wire (672 bits), 84 bytes captured (672 bits) on interface TCP#127.0.0.1:24352, id 0
Bluetooth
Bluetooth HCI H4
Bluetooth HCI Command - LE Set Extended Advertising Data
Command Opcode: LE Set Extended Advertising Data (0x2037)
Parameter Total Length: 80
Advertising Handle: 0x02
Data Operation: Complete scan response data (0x03)
Fragment Preference: The Controller should not fragment or should minimize fragmentation of Host data (0x01)
Data Length: 76
Advertising Data
Flags
Length: 2
Type: Flags (0x01)
000. .... = Reserved: 0x0
...1 .... = Simultaneous LE and BR/EDR to Same Device Capable (Host): true (0x1)
.... 1... = Simultaneous LE and BR/EDR to Same Device Capable (Controller): true (0x1)
.... .0.. = BR/EDR Not Supported: false (0x0)
.... ..1. = LE General Discoverable Mode: true (0x1)
.... ...0 = LE Limited Discoverable Mode: false (0x0)
16-bit Service Class UUIDs
Length: 3
Type: 16-bit Service Class UUIDs (0x03)
UUID 16: Device Information (0x180a)
128-bit Service Class UUIDs
Length: 17
Type: 128-bit Service Class UUIDs (0x07)
Custom UUID: caecface-e1d9-11e6-bf01-fe55135034f0 (Unknown)
Service Data - 128 bit UUID
Length: 50
Type: Service Data - 128 bit UUID (0x21)
Custom UUID: caecface-e1d9-11e6-bf01-fe55135034f0 (Unknown)
Service Data: ffff0000000000000000000000000000004142434445464748494a4b4c4d4e4f50
[Response in frame: 500]
[Command-Response Delta: 1.889ms]
Frame 500: 7 bytes on wire (56 bits), 7 bytes captured (56 bits) on interface TCP#127.0.0.1:24352, id 0
Bluetooth
Bluetooth HCI H4
Bluetooth HCI Event - Command Complete
Event Code: Command Complete (0x0e)
Parameter Total Length: 4
Number of Allowed Command Packets: 1
Command Opcode: LE Set Extended Advertising Data (0x2037)
0010 00.. .... .... = Opcode Group Field: LE Controller Commands (0x08)
.... ..00 0011 0111 = Opcode Command Field: LE Set Extended Advertising Data (0x037)
Status: Success (0x00)
[Command in frame: 499]
[Command-Response Delta: 1.889ms]
I've also tried using the exact code verbatim in this example and it has the exact same problem:
https://github.com/ProH4Ck/treadmill-bridge/blob/98e683e2380178319972af522d9251f44350a448/src/TreadmillBridge/Services/VirtualTreadmill/VirtualTreadmillService.cs#L90
Does anyone know what the problem might be?

can I get 255 packets from VCP (virtual COM Port)?

I know the default setting value for 'VIRTUAL_COM_PORT_DATA_SIZE 64' at usb_desc.h for STM32 Library.
however, I want to get the 255 bytes at one time due to the long packets of our project.
So I have changed the following modify code point, I couldn't get the right value with problem for 'USB defect problem'.
/****** usb_prop.c **********/
DEVICE_PROP Device_Property = {
Virtual_Com_Port_init,
Virtual_Com_Port_Reset,
Virtual_Com_Port_Status_In,
Virtual_Com_Port_Status_Out,
Virtual_Com_Port_Data_Setup,
Virtual_Com_Port_NoData_Setup,
Virtual_Com_Port_Get_Interface_Setting,
Virtual_Com_Port_GetDeviceDescriptor,
Virtual_Com_Port_GetConfigDescriptor,
Virtual_Com_Port_GetStringDescriptor,
0,
0xFF /*MAX PACKET SIZE*/ // default : 0x40
};
/****** usb_desc.c **********/
/* USB Standard Device Descriptor */
const uint8_t Virtual_Com_Port_DeviceDescriptor[] = {
0x12, /* bLength */
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x00,
0x02, /* bcdUSB = 2.00 */
0x02, /* bDeviceClass: CDC */
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
0xFF, /* bMaxPacketSize0 */ // default : 0x40
0x83,
0x04, /* idVendor = 0x0483 */
0x40,
0x57, /* idProduct = 0x7540 */
0x00,
0x02, /* bcdDevice = 2.00 */
1, /* Index of string descriptor describing manufacturer */
2, /* Index of string descriptor describing product */
3, /* Index of string descriptor describing the device's serial number */
0x01 /* bNumConfigurations */ };
/****** usb_desc.h **********/
#define VIRTUAL_COM_PORT_DATA_SIZE 255 // 0xFF, default : 64
please tell me how to modify in order to send as 255 bytes from USB packets.
You can't do it this way. The size of the packet is USB endpoint related and for the FS USB it is always 64 bytes. My advice is: do not modify any descriptors unless you really know what are you doing (which is not the case here).
How to receive larger chunks of data:
create a buffer
when data arrives copy it (append) to that buffer
check if you have received all data needed
if not go to point (2) else goto point(5)
Do something with the data (your large packet)
Reset the buffer and goto point 2

USB HID difference between "Get Input Report" and "Input report"

I'm implementing a custom HID device that has the following interface:
0x06, 0xA0, 0xFF, // Usage Page (Vendor Defined 0xFFA0)
0x09, 0x01, // Usage (0x01)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // Report ID (1)
0x15, 0x00, // Logical Minimum (0)
0x26, 0x01, 0x00, // Logical Maximum (1)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x85, 0x01, // Report ID (1)
0x15, 0x00, // Logical Minimum (0)
0x26, 0x01, 0x00, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x02, // Report Count (2)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x75, 0x06, // Report Size (6)
0x95, 0x01, // Report Count (1)
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x85, 0x03, // Report ID (1)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0xFF, // Logical Maximum (65535)
0x75, 0x10, // Report Size (16)
0x95, 0x01, // Report Count (1)
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0, // End Collection
When I plug this device into the computer through a USB logic analyzer I see it enumerate, then something (I'm not sure what, any ideas?) uses the HID report descriptor to intelligently grab a bunch of reports:
(control)(endpoint 0) Get Input Report[1]
(control)(endpoint 0) Get Feature Report[1]
The "Get Input Report" entry confused me as I thought input reports were sent via an interrupt transfer. If I use usbhid's hid_write, I see the following entry, so I must be at least half right about input reports being sent via interrupt transfers...:
(interrupt)(endpoint 1) Input Report[1]"
I have been unable to find information that describes the difference between control "get input reports" and interrupt "input report" transfers which I am hoping one of you will know about.
Why do control "get input reports" exist?
Why not just have the spec mandate a "get feature report" entry exist for every "input report" id entry?
Why is whatever is grabbing input/feature reports for every defined input/feature report using a control transfer for the input reports vs. an interrupt transfer?
Have a look at USB HID v1.1. There is definition for Get_Report request on page 51:
This request is useful at initialization time for absolute items and for determining the state of feature items. This request is not intended to be used for polling the device state on a regular basis.
Here, this is exactly what the driver is doing: it is retrieving the various reports to initialize its current state. Note the host cannot request the device to send a report on its interrupt pipe. Hence the request on control pipe.
Chapter 4.4 explains various endpoints usage.
Also note feature reports and input reports do not address the same data, even if they have the same report ID (report IDs are per report type).

STM32 USB HID reports

For the past two weeks I have been trying to configure my card (STM32F4) to dialogue with USB HID with a PC under Windows 7. I make success with this descriptor:
__ALIGN_BEGIN static uint8_t HID_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
0x06, 0xFF, 0x00, // USAGE_PAGE (Vendor Page: 0xFF00)
0x09, 0x01, // USAGE (Demo Kit)
0xa1, 0x01, // COLLECTION (Application)
//0x85, 0x01, // REPORT_ID (1)
0x09, 0x02, // USAGE (DATA)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff,0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x04, // REPORT_COUNT (4)
0x81, 0x02, // INPUT (Data,Var,Abs,Vol)
0xc0 // END_COLLECTION
};
Like this, Windows recognizeS my card like a compliant HID component.
Now if I want to send 32 bit data like a uint32, Windows recognizes the card, but it sees an error to tell that it can't start it! My descriptor:
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
0x06, 0xFF, 0x00, // USAGE_PAGE (Vendor Page: 0xFF00)
0x09, 0x01, // USAGE (Demo Kit)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x02, // USAGE (DATA)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x27, 0xff,0xff,0xff,0xff, // LOGICAL_MAXIMUM (65535)
0x75, 0x20, // REPORT_SIZE (32)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs,Vol)
0xc0 // END_COLLECTION
};
I didn't understand why it din't work!
After that, I use USBlyser to scan my other USB device on my PC, and I take this descriptor about my spacespilot 3D mouse:
Endpoint Descriptor 83 3 In, Interrupt, 16 ms
Offset Field Size Value Description
0 bLength 1 07h
1 bDescriptorType 1 05h Endpoint
2 bEndpointAddress 1 83h 3 In
3 bmAttributes 1 03h Interrupt
1..0: Transfer Type ......11 Interrupt
7..2: Reserved 000000..
4 wMaxPacketSize 2 0007h 7 bytes
6 bInterval 1 08h 16 ms
Interface 1 HID Report Descriptor Multi-Axis Controller
Item Tag (Value) Raw Data
Usage Page (Generic Desktop) 05 01
Usage (Multi-Axis Controller) 09 08
Collection (Application) A1 01
Collection (Physical) A1 00
Report ID (1) 85 01
Logical Minimum (-500) 16 0C FE
Logical Maximum (500) 26 F4 01
Physical Minimum (-32768) 36 00 80
Physical Maximum (32767) 46 FF 7F
Usage (X) 09 30
Usage (Y) 09 31
Usage (Z) 09 32
Report Size (16) 75 10
Report Count (3) 95 03
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
End Collection C0
If I try this, it works fine:
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x08, //Usage (Multi-Axis Controller)
0xa1, 0x01, // COLLECTION (Application)
0xa1, 0x00, // Collection (Physical)
0x85, 0x01, // Report ID (1)
0x16,0x0c,0xfe, // Logical minimum (-500)
0x26,0xf4,0x01, // Logical maximum (500)
0x35,0x00, // Physical Minimum (0)
0x46,0xff,0x00, // Physical Maximum (255)
0x09,0x30, // Usage(X)
0x09,0x31, // Usage(Y)
0x09,0x32, // Usage(Z)
0x09,0x33, // Usage(RX)
0x09,0x34, // Usage(RY)
0x09,0x35, // //Usage(RZ)
0x75, 0x08, // REPORT_SIZE (16)
0x95, 0x06, // REPORT_COUNT (6)
0x81, 0x02, // INPUT (Data,Var,Abs,Vol)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
};
But if I try the same descriptor that my 3D mouse:
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x08, // Usage (Multi-Axis Controller)
0xa1, 0x01, // COLLECTION (Application)
0xa1, 0x00, // Collection (Physical)
0x85, 0x01, // Report ID (1)
0x16,0x0c,0xfe, // Logical minimum (-500)
0x26,0xf4,0x01, // Logical maximum (500)
0x35,0x00,0x80, // Physical Minimum (-32768)
0x46,0xff,0x7f, // Physical Maximum (32767)
0x09,0x30, // Usage(X)
0x09,0x31, // Usage(Y)
0x09,0x32, // Usage(Z)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x02, // INPUT (Data,Var,Abs,Vol)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
};
Windows gives me the same error, and it can't start the device!!!
What is wrong? Do I need a special driver for Windows to send 32 bit data (int32)? For information, I use the HID library for my application PC side.
How can I resolve this?
The LOGICAL_MAXIMUM four-byte descriptor tag (0x27) is only valid up to 0x7FFFFFFF as it is describing a maximum for a signed int data field. If you want to describe an unsigned int data field you would need to use the LOGICAL_MAXIMUM 8 byte descriptor tag like this:
0x28, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00
Your second example would work, I think. Except for the typo for the Physical maximum descriptor tag. It should be 0x36, not 0x35.
When I tried your last descriptor (using my Arduino USBComposite library for STM32F1), Windows gave me an error about the descriptor having an unknown item. But when I changed the 0x35 in the Physical Minimum line to 0x36, Windows recognized the item.

Union struct: printing struct member of type uint32_t skips two bytes and prints wrong value

Need help with union struct. I'm receiving byte stream that consists of various packets, so I'm putting the byte data into union struct and accessing needed data via struct members. The problem is with uint32_t type member - the read skips its two bytes and shows wrong value when accessing via its member. Here's full demo code:
PacketUtils.h
#include <stdint.h>
typedef struct {
uint8_t startSymbol;
uint8_t packetType;
uint32_t deviceId;
uint16_t packetCRC;
} PacketData;
typedef union {
uint8_t *bytes; // stores raw bytes
PacketData *packet;
} Packet;
// Puts bytes into predefined struct
void getPacketFromBytes(void *bytes, Packet *packetRef);
PacketUtils.c
#include <stdio.h>
#include "UnionStruct.h"
void getPacketFromBytes(void *bytes, Packet *packetRef)
{
uint8_t *rawBytes = (uint8_t *)bytes;
packetRef->bytes = rawBytes;
}
Calling code:
// sample byte data
uint8_t packetBytes[] = {0x11, 0x02, 0x01, 0x01, 0x01, 0x03, 0xbb, 0xbd};
Packet packetRef;
getPacketFromBytes(packetBytes, &packetRef);
printf("%x\n", packetRef.packet->startSymbol); // good - prints 0x11
printf("%x\n", packetRef.packet->packetType); // good - prints 0x02
printf("%x\n", packetRef.packet->deviceId); // bad - prints bd bb 03 01
printf("%x\n", packetRef.packet->packetCRC); // bad - prints 36 80 (some next values in memory)
Everything is OK when PacketData struct consist of uint8_t or uint16_t type members then the print shows correct values. However, printing deviceId of type uint32_t skips two bytes (0x01 0x01) and grabs last 4 bytes. Printing packetCRC prints the values out of given byte array - some two values in memory, like packetBytes[12] and packetBytes[13]. I can't figure out why it skips two bytes...
The problem is due to the fields being padded out to default alignment on your platform. On most modern architectures 32-bit values are most efficient when read/written to a 32-bit word aligned address.
In gcc you can avoid this by using a special attribute to indicate that the structure is "packed". See here:
http://gcc.gnu.org/onlinedocs/gcc-3.3.6/gcc/Type-Attributes.html
So struct definition would look something like this:
typedef struct {
uint8_t startSymbol;
uint8_t packetType;
uint32_t deviceId;
uint16_t packetCRC;
} PacketData __attribute__((packed));
The 32-bit number will be aligned on a 4-byte boundary only. If you move it to the start of your struct, it may just work as you want.
Processors usually are optimised to fetch data on multiples of the datum size - 4 bytes for 32-bit, 8 bytes for 64-bit... - and the compiler knows this and adds gaps into the data structures to make sure that the processor can fetch the data efficiently.
If you don't want to deal with the padding and can't move the data structure around, you could define
typedef struct {
uint8_t startSymbol;
uint8_t packetType;
uint16_t deviceIdLow;
uint16_t deviceIdHigh;
uint16_t packetCRC;
} PacketData;
and then just write
uint32_t deviceID = packetRef.packet->deviceIdLow | (packetRef.packet->deviceIdLow << 16);