24bit USB Sample Rate Support - windows

My question is quite similar to this question: Link, but i am not allowed to comment.
I'm implementing a PIC32 as a soundcard, and i now have a working USB audio stream, supporting 16-bit at 32kHz and 48kHz sample rates. I now want to change the bit depth to 24-bit, so i change my USB Descriptors to:
bSubFrameSize = 0x03, // 3 bytes per sample
bBitResolution = 0x18, // 24-bit resolution
When i do this, he bit resolution is changed as it is suppose to, but in the properties of the microphone, the dropdown menu where i could change the sampling frequency is grey.
I havn't changed anything in the endpoint descriptors, where both 32kHz and 48kHz still is supported.
My USB topology has 1 Audio control interface with a couple of Units, and 2 Audio Streaming Interfaces, for streaming IN and OUT.
Marc O answered his question by saying that something in his Input Terminal, i have tried changing wChannelConfig but i doesn't work.
I have tried Uninstalling and Installing the device drivers, but doesn't work.
What more do i need to change in the descriptors, to be able to select the sampling Frequency?
Thanks :)
Edit: Added Descriptor code and descriped progress
When i changed the no of channels to 2, and made the wChannelConfig = 0x03 -> right + Left Front, i saw the the field on he picture change to: "2 channel, 24 bit, 48000 Hz (Studio Quality)", but it still didn't make the dropdown menu white, and i couldn't change sample rate.
Below i've added the Audio funcion descriptors:
//CD
0x09, // Size : 9 Bytes
USB_DESCRIPTOR_CONFIGURATION, // Configuration Descriptor (0x02)
0x10, // Total length in bytes of data returned
0x01, // 2. Byte af Total Length
0x05, // Number of Interfaces: 5 3 Audio + 2 Comm
0x01, // Configuration Value, Value to use as an argument to select this configuration
0x00, // iConfiguration, Index of String Descriptor describing this configuration
_DEFAULT | _SELF, // bmAttributes, selfpowered
0xFA, // Maximum Power : 250 mA
// ######## Audio Control Interface Descriptor
//ID - Interface Descriptor
0x09, // Size : 9 Bytes
USB_DESCRIPTOR_INTERFACE, // Interface Descriptor (0x04)
0x00, // Number of Interface: Interface nr 0
0x00, // Value used to select alternative setting
0x00, // Number of Endpoints used for this interface, 0
AUDIO_DEVICE, // Class Code (Assigned by USB Org), AUDIO
AUDIOCONTROL, // Subclass Code (Assigned by USB Org), AUDIOCONTROL
0x00, // Protocol Code (Assigned by USB Org)
0x00, // Index of String Descriptor Describing this interface
// HEADER
0x0A, // Size : 10 Bytes
CS_INTERFACE, // CS_INTERFACE Descriptor Type
HEADER, // HEADER descriptor subtype
0x00,0x01, // Audio Device compliant to the USB Audio specification version 1.00
0x46,0x00, // 64 bytes - Total number of bytes returned for the class-specific AudioControl interface descriptor. // Includes the combined length of this descriptor header and all Unit and Terminal descriptors.
0x02, // bInCollection -> Number of streaming interfaces = 2
0x01, // en form for index: "AudioStreaming interface 1 belongs to this AudioControl interface."
0x02, // beskriver nok streaming interface 2's index
// INPUT_TERMINAL ID = 1 USB Stream
0x0B, // size : 12 bytes
CS_INTERFACE, // CS_INTERFACE Descriptor Type
INPUT_TERMINAL, // INPUT_TERMINAL - Descriptor subtype = 2
INPUT_TER_USB, // ID of this Input Terminal. // Constant uniquely identifying the Terminal within the audio function.
USB_STREAMING, // wTerminalType -> 0x0101 = USB streamming
0x00, // bAssocTerminal -> 0x00 = No association.
0x02, // bNrChannels -> 0x01 two channel.
0x03, // wChannelConfig -> 0x03 = right + Left Front
0x00, // iChannelNames -> 0x00 = Unused.
0x00, // iTerminal -> 0x00 = Unused.
// INPUT_TERMINAL ID = 4 MICROPHONE
0x0B, // size : 12 bytes
CS_INTERFACE, // CS_INTERFACE Descriptor Type
INPUT_TERMINAL, // INPUT_TERMINAL - Descriptor subtype
INPUT_TER_MIC, // bTerminalID -> ID of this Input Terminal = 4
MICROPHONE, // wTerminalType -> 0x0201 = Microphone
0x00, // bAssocTerminal -> 0x00 = No association.
0x02, // bNrChannels -> 0x01 one channel.
0x03, // wChannelConfig -> 0x03 = right + Left Front
0x00, // iChannelNames -> 0x00 = Unused.
0x00, // iTerminal -> 0x00 = Unused.
// OUTPUT_TERMINAL ID = 3 SPEAKER
0x09, // size : 9 Bytes
CS_INTERFACE, // CS_INTERFACE Descriptor Type
OUTPUT_TERMINAL, // OUTPUT_TERMINAL - Descriptor subtype
OUTPUT_TER_SPEAK, // bTerminalID -> ID of this Output Terminal = 3
SPEAKER, // wTerminalType -> 0x0301 = Speaker
0x00, // bAssocTerminal -> 0x00 = Unused
FEATURE_OUT, // bSourceID -> 0x02 = From Input Terminal ID 2 = USB stream
0x00, // iTerminal -> 0x00 = Unused.
// OUTPUT_TERMINAL ID = 6 USB Stream
0x09, // Size : 9 Bytes
CS_INTERFACE, // CS_INTERFACE Descriptor Type
OUTPUT_TERMINAL, // OUTPUT_TERMINAL - Descriptor subtype
OUTPUT_TER_USB, // bTerminalID -> ID of this Output Terminal = 6
USB_STREAMING, // wTerminalType -> 0x0101 = USB streaming
0x00, // bAssocTerminal -> 0x00 = Unused
FEATURE_IN, // bSourceID -> 0x05 = Feature Unit that sets IN features SOURCE = 5 (Feature_IN)
0x00, // iTerminal -> 0x00 = Unused.
// FEATURE_UNIT ID = 2
0x0A, // Size : 10 Bytes
CS_INTERFACE, // CS_INTERFACE Descriptor Type
FEATURE_UNIT, // FEATURE_UNIT - Descriptor subtype
FEATURE_OUT, // bUnitID -> ID 2
INPUT_TER_USB, // bSourceID -> 0x01 = connected to Input Terminal 1 SOURCE = 1 (Input USB)
0x01, // bControlSize -> 0x01 = 1 Byte
0x03, // bmaControls(n = channel nr) -> 0x03 = Mute + volume
0x03, // bmaControls(n = channel nr) -> 0x03 = Mute + volume
0x00, // bmaControls(n = channel nr) -> 0x00 = no master control
0x00, // iFeature -> string Descriptor Unused
// FEATURE_UNIT ID = 5
0x0A, // Size : 9 Bytes
CS_INTERFACE, // CS_INTERFACE Descriptor Type
FEATURE_UNIT, // FEATURE_UNIT - Descriptor subtype
FEATURE_IN, // bUnitID -> ID 5
INPUT_TER_MIC, // bSourceID -> 0x04 = Connected to Unit ID 4 SOURCE = 4 (Input Mic.)
0x01, // bControlSize -> 0x01 = 1 Byte
0x03, // bmaControls(1) -> 0b0000011 = Mute + Volume no. of Channels +1 = no. of bmaControls
0x03, // bmaControls(2) -> 0b0000011 = Mute + Volume no. of Channels +1 = no. of bmaControls
0x00, // bmaControls(3) -> 0x00 = No controls supperted no. of Channels +1 = no. of bmaControls
0x00, // iFeature -> string Descriptor Unused
// ######## AUDIO STREAM INTERFACE 1 OUT SPEAKER
//ID // Alternate Setting 0 - 0 endpoint
0x09, // Size : 9 Bytes
USB_DESCRIPTOR_INTERFACE, // Interface Descriptor (0x04)
0x01, // bInterfaceNumber -> 0x01 Interface ID = 1
0x00, // bAlternateSetting -> 0x00 = index of this interface's alternate setting
0x00, // bNumEndpoints -> 0x00 = 0 Endpoints to this interface
AUDIO_DEVICE, // bInterfaceClass -> 0x01 = Audio Interface
AUDIOSTREAMING, // bInterfaceSubclass -> 0x02 = AUDIO_STREAMING
0x00, // bInterfaceProtocol -> 0x00 = Unused
0x00, // iInterface -> 0x00 = Unused
//ID // Alternate Setting 1 - 1 endpoint
0x09, // Size : 9 Bytes
USB_DESCRIPTOR_INTERFACE, // Interface Descriptor (0x04)
0x01, // bInterfaceNumber -> 0x01 Interface ID = 1
0x01, // bAlternateSetting -> 0x01 = index of this interface's alternate setting
0x01, // bNumEndpoints -> 0x01 = 1 Endpoints to this interface
0x01, // bInterfaceClass -> 0x01 = Audio Interface
0x02, // bInterfaceSubclass -> 0x02 = AUDIO_STREAMING
0x00, // bInterfaceProtocol -> 0x00 = Unused
0x00, // iInterface -> 0x00 = Unused
// ASID GENERAL
0x07, // Size : 7 Bytes
CS_INTERFACE, // CS_INTERFACE Descriptor Type
AS_GENERAL, // bDescriptorSubtype -> 0x01 = GENERAL subtype
0x01, // bTerminalLink -> 0x01 = The Terminal ID of the Terminal to which the endpoint of this interface is connected.
0x01, // bDelay -> 0x01 = Delay (delta) introduced by the data path (see Section 3.4, ?Inter Channel Synchronization? - in Audio Devices). Expressed in number of frames.
0x01,0x00, // wFormatTag -> 0x0001 = PCM
// ASID FORMAT_TYPE
0x0E, // Size : 14 Bytes
CS_INTERFACE, // CS_INTERFACE Descriptor Type
FORMAT_TYPE, // bDescriptorSubtype -> 0x02 = FORMAT_TYPE
0x01, // bFormatType -> 0x01 = FORMAT_TYPE_I -> ref: A.1.1 Audio Data Format Type I Codes -> Audio Data Format Dok
0x02, // bNrChannels -> 0x02 = Two channels
BYTES_PR_SAMPLE, // bSubFrameSize -> 0x03 = 3 bytes pr audio subframe
BIT_RESOLUTION, // bBitResolution -> 0x18 = 24 bit pr sample
0x02, // bSamFreqType -> 0x02 = 2 sample frequencies supported
0x00,0x7D,0x00, // tSamFreq -> 0x7D00 = 32000 Hz
0x80,0xBB,0x00, // tSamFreq -> 0xBB80 = 48000 Hz
//ED ENDPOINT OUT
0x09, // Size : 9 Bytes
USB_DESCRIPTOR_ENDPOINT, // 0x05 -> ENDPOINT Descriptor Type
0x01, // bEndpointAddress -> 0x01 = adress 1, OUT, -> ref 9.6.6 Endpoint -> usb_20 Dok
0x09, // bmAttributes -> 0b00001001 -> Bits 0-1 = 01 = Isochronous , Bits 2-3 = 10 = Adaptive
AUDIO_MAX_SAMPLES * sizeof ( AUDIO_PLAY_SAMPLE ), AUDIO_MAX_SAMPLES * sizeof ( AUDIO_PLAY_SAMPLE )>>8,
0x01, // bInterval -> 0x01 = 1 millisecond
0x00, // Unused
0x00, // Unused
//AS ENDPOINT
0x07, // Size : 7 Bytes
CS_ENDPOINT, // CS_ENDPOINT
EP_GENERAL, // bDescriptorSubtype -> 0x01 = GENERAL
SAMPLING_FREQ_CONTROL, // bmAttributes -> 0b00000001 = Bit 1 = 1 => Sample Freq Control is supported by this endpoint
0x00, // bLockDelayUnits -> 0x00 = Indicates the units used for the wLockDelay field: 0 = Undefined
0x00,0x00, // the time it takes this endpoint to reliably lock its internal clock recovery circuitry.
// ######## AUDIO STREAM INTERFACE 2 IN MICROPHONE
//ID // Alternate Setting 0 - 0 endpoint
0x09, // Size : 9 Bytes
USB_DESCRIPTOR_INTERFACE, // Interface Descriptor (0x04)
0x02, // bInterfaceNumber -> 0x02 Interface ID = 2
0x00, // bAlternateSetting -> 0x00 = Value used to select this alternate setting for the interface identified in the prior field
0x00, // bNumEndpoints -> 0x00 = 0 -> Number of endpoints used by this interface
AUDIO_DEVICE, // bInterfaceClass -> 0x01 = 1 = AUDIO
AUDIOSTREAMING, // bInterfaceSubClass -> 0x02 = AUDIO_STREAMING
0x00, // bInterfaceProtocol -> 0x00 = Unused
0x00, // iInterface -> 0x00 = Unused -> Index of string descriptor.
//ID // Alternate Setting 1 - 1 endpoint
0x09, // Size : 9 Bytes
USB_DESCRIPTOR_INTERFACE, // Interface Descriptor (0x04)
0x02, // bInterfaceNumber -> 0x02 Interface ID = 2
0x01, // bAlternateSetting -> 0x01 = Value used to select this alternate setting for the interface identified in the prior field
0x01, // bNumEndpoints -> 0x01 = 1 -> Number of endpoints used by this interface
0x01, // bInterfaceClass -> 0x01 = 1 = AUDIO
0x02, // bInterfaceSubClass -> 0x02 = AUDIO_STREAMING
0x00, // bInterfaceProtocol -> 0x00 = Unused
0x00, // iInterface -> 0x00 = Unused -> Index of string descriptor.
// ASID GENERAL
0x07, // Size : 7 Bytes
CS_INTERFACE, // CS_INTERFACE Descriptor Type
AS_GENERAL, // GENERAL Descriptor
0x06, // bTerminalLink -> 0x06 = The Terminal ID of the Terminal to which the endpoint of this interface is connected. = 6
0x01, // bDelay -> 0x01 = Delay (delta) introduced by the data path (see Section 3.4, ?Inter Channel Synchronization? - in Audio Devices). Expressed in number of frames.
0x01,0x00, // wFormatTag -> 0x0001 = PCM
// ASID FORMAT_TYPE
0x0E, // Size : 14 Bytes
CS_INTERFACE, // CS_INTERFACE Descriptor Type
FORMAT_TYPE, // bDescriptorSubtype -> 0x02 = FORMAT_TYPE
0x01, // bFormatType -> 0x01 = FORMAT_TYPE_I -> ref: A.1.1 Audio Data Format Type I Codes -> Audio Data Format Dok
0x02, // bNrChannels -> 0x02 = Two channels
BYTES_PR_SAMPLE, // bSubFrameSize -> 0x03 = 3 bytes pr audio subframe
BIT_RESOLUTION, // bBitResolution -> 0x18 = 24 bit pr sample
0x02, // bSamFreqType -> 0x02 = 2 sample frequencies supported
0x00,0x7D,0x00, // tSamFreq -> 0x7D00 = 32000 Hz
0x80,0xBB,0x00, // tSamFreq -> 0xBB80 = 48000 Hz
//ED ENDPOINT IN
0x09, // Size : 9 Bytes
USB_DESCRIPTOR_ENDPOINT, // 0x05 -> ENDPOINT Descriptor Type
0x82, // bEndpointAddress -> 0x82 = adress 2, IN, -> ref 9.6.6 Endpoint -> usb_20 Dok
0x05, // bmAttributes -> 0b00000101 -> Bits 0-1 = 01 = Isochronous , Bits 2-3 = 01 = Asynchronous
AUDIO_MAX_SAMPLES * sizeof ( AUDIO_PLAY_SAMPLE ), AUDIO_MAX_SAMPLES * sizeof ( AUDIO_PLAY_SAMPLE )>>8,
0x01, // bInterval -> 0x01 = 1 millisecond
0x00, // unused
0x00, // unused
//AS ENDPOINT
0x07, // Size : 7 Bytes
CS_ENDPOINT, // bDescriptorType -> 0x25 = CS_ENDPOINT
EP_GENERAL, // bDescriptorSubtype -> 0x01 = GENERAL
SAMPLING_FREQ_CONTROL, // bmAttributes -> 0b00000001 = Bit 1 = 1 => Sample Freq Control is supported by this endpoint
0x00, // bLockDelayUnits -> 0x00 = Indicates the units used for the wLockDelay field: 0 = Undefined
0x00,0x00, // the time it takes this endpoint to reliably lock its internal clock recovery circuitry.

This post is quite old but my reply maybe helpful to others facing the same difficulty.
I noticed that windows does not make changes to the installed drivers when the interface changes. You must manually uninstall the windows driver for your device and let windows reinstall it either on USB re-connection or reset of the device.

Related

Audio frame sample type in PCM?

So I'm taking CMSampleBufferRef buffers with audio content.
AudioStreamBasicDescription is as follows
{
mSampleRate: 44100.000000
mFormatID: 'lpcm'
mFormatFlags: 0xe
mBytesPerPacket: 4
mFramesPerPacket: 1
mBytesPerFrame: 4
mChannelsPerFrame: 2
mBitsPerChannel: 16
}
Apparently a it's an interleaved video with 2 bytes per channel = sample size.
What is the encoding of this sample size? Is that a (short) int? Is a frame consisting of 2 shorts? Or one int? or one float? How do I know this?
I guess it's 32bpp interleaved audio, correct?
A value of 0xe for mFormatFlags is 0b1110 which equates to:
kAudioFormatFlagIsBigEndian = (1U << 1), // 0x2
kAudioFormatFlagIsSignedInteger = (1U << 2), // 0x4
kAudioFormatFlagIsPacked = (1U << 3), // 0x8
So a frame consists of two interleaved big-endian int16_t samples.

Read Data ST25DV

I made my own board with an STM32L031K6 and an ST25DV64K NFC chip. I am using the android App "NFC Tools". I can read the UID of the NFC chip with the app, so the antenna is correctly tuned. I can also read the UID with the microcontroleur via the I2C bus. When I write into the eeprom memory of the NFC chip with the microcontroleur, I can't read the data with the NFC app. It says that the tag is empty. I think I am missing a configuration, but I can't find which one.
Here is my code, executed once:
uint8_t ToWrite = 15;
uint8_t Password[17] = {0}; //Default password is"00000000"
Password[8] = 0x09; //Validation Code
// ST25DV_Address_E21 0x57 << 1; // Device select code= 0b1010111 ; E2 = 1
Password_Address = 0x900
HAL_I2C_Mem_Write(&hi2c1, ST25DV_Address_E21, Password_Address, 2, Password, 17, 0xFFF);
HAL_Delay(200);
//Read the UID
HAL_I2C_Mem_Read(&hi2c1, ST25DV_Address_E21, 0x18, 2, UID_Read, 8, 0xFFF); // This line works, UID displayed in the app and in the debugger are the same
HAL_Delay(500);
//Write some data in the eepprom memory (first address: 0x00)
for(int i = 0; i< 250; i++)
{
ToWrite++;
HAL_I2C_Mem_Write(&hi2c1,ST25DV_Address_E21, i, 2, &ToWrite, 1, 0xFF);
}
When you are writing the data in the EEPROM from address/block 0, you are simply overwriting the capability container values with all zeros. The correct way to do is initialize your tag, then write the data from block 4 and onwards.
The CC values look something like this:
0xE1, /* (block 0) */
0x40, /* (block 1) */
0x40, /* (block 2) */
0x05 /* (block 3) */
Followed by other key header values depending on the NDEF message type. Here I am illustrating for NDEF TEXT:
0x03, /*(block 4) NDEF message type (block 4) */
0x0D, /*(block 5) NDEF message length (blobk 5) eg, 13 byte message starting from here */
0xD1, /*(block 6) NDEF Record header: MB = 1, ME = 1, CF = 0, SR = 1, IL = 0, TNF = 001 > 0xD1 */
0x01, /*(block 7) Type length */
0x09, /*(block 8) Payload length = 9 (from language code) */
0x54, /*(block 9) Msg Type = Text */
0x02, /*(block 10) Language code size */
0x65, /*(block 11) Language = English, 'e', */
0x6E, /*(block 12) 'n', */
'A', /*(block 13+)Payload data */
'B',
'C',
'D',
'E',
'F'
A good reading resource to understand the NDEF payload format is here.
Hope this helps!

GoLang bitwise calculation

I have a buffer :
buffer := bytes.NewBuffer([]byte{
0x85, 0x02, 0xFF, 0xFF,
0x00, 0x01, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x03,
0x41, 0x42, 0x43,
})
I am trying to return the int value of buffer[8:24]
I get
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]
Not sure how to shift such a large section. of the byte.
new to this. Any help would be great. my initial approach was
requestid := (uint64(buffer.Bytes()[8]&0xff)<<24 + uint64(buffer.Bytes()[9]&0xff)<<16 + uint64(buffer.Bytes()[10]&0xff)<<8 + uint64(buffer.Bytes()[11]&0xff.....)))
but this got tedious, and I know there has to be an easier way.
You have to do the manual bit shifting and OR'ing, but your code can be cleaned up by removing all those buffer.Bytes() calls.
You also do not need the &0xff parts. What n&0xff does, is clear out all bits outside of the 0-255 range. Since each value in the buffer is already a byte (0-255), these operations do nothing at all. If we want to do 22 & 255, we get the following:
Hexadecimal | Decimal | Binary
--------------|-------------|----------------------
x 0x16 | 22 | 00010110
y 0xff | 255 | 11111111
--------------|-------------|---------------------- AND (&)
0x16 | 22 | 00010110 = x
As you can see, the operation has no effect at all. Replace x with any 8-bit value and you will see the same result. The outcome of x & 0xff is always x.
Additionally, when you assign to the requestId, you start by shifting by 24 bits. This tells me you are reading a 32-bit integer. Why then do you continue reading values beyond 32 bits and converting it all to a 64 bit integer?
If you are reading a 64-bit int in Big Endian, try this:
data := buf.Bytes()[8:]
requestid := uint64(data[0])<<56 | uint64(data[1])<<48 |
uint64(data[2])<<40 | uint64(data[3])<<32 |
uint64(data[4])<<24 | uint64(data[5])<<16 |
uint64(data[6])<<8 | uint64(data[7])
If you are reading a 64-bit int in Little Endian, try this:
data := buf.Bytes()[8:]
requestid := uint64(data[7])<<56 | uint64(data[6])<<48 |
uint64(data[5])<<40 | uint64(data[4])<<32 |
uint64(data[3])<<24 | uint64(data[2])<<16 |
uint64(data[1])<<8 | uint64(data[0])
If you are reading a 32-bit int in Big Endian, try this:
data := buf.Bytes()[8:]
requestid := uint32(data[0])<<24 | uint32(data[1])<<16 |
uint32(data[2])<<8 | uint32(data[3])
If you are reading a 32-bit int in Little Endian, try this:
data := buf.Bytes()[8:]
requestid := uint32(data[3])<<24 | uint32(data[2])<<16 |
uint32(data[1])<<8 | uint32(data[0])
binary package
Alternatively, you can use the encoding/binary package:
var value uint64
err := binary.Read(buf, binary.LittleEndian, &value)
....

Is [0x02, 0x03, 0x00] valid data?

I am trying to write a program that returns valid data according to a message protocol within a byte[] array.
I have:
STX: 0x02
ETX: 0X03
DLE: 0x10 //Delimiter
Valid data is when the byte[] array contains STX, ETX, data and a correctly calculated LRC, for example:
byte[] validMsg1 = {0x02, // STX
0x10,0x2,0xA,0x10,0x10,0x7,0x8, // Data 2 A 10 7 8
0x03, // ETX
0x2^0xA^0x10^0x7^0x8^0x03}; // LRC calculated from the data (with the DLE removed) plus the ETX
Invalid data example:
byte[] invalidMsg1 = {0x02, // STX
0x10,0x2,0xA, // Data 2 A
0x03, // ETX
0x2^0xA^0x10^0x7^0x8^0x03,
0x02, //STX
0x05,0x44};
The byte might also contain random values around the valid data:
byte[] validMsgWithRandomData1 = {0x32,0x32,0x32, //Random data
0x02, // STX
0x31,0x32,0x10,0x02,0x33, // Data 31 32 02 33
0x03, // ETX
0x31^0x32^0x02^0x33^0x03,// LRC calculated from the data (with the DLE removed) plus the ETX
0x2,0x3,0x00,0x02 //Random data
};
My problems is that when I use the message with random data in and have 0x2,0x3,0x00,0x02 it breaks because it sees 0x02 and 0x03 as the STX and ETX and then it calculates LRC which results in 0x03 which results in this being returned: 0x2,0x3,0x00 with the last 0x03 seens as the LRC.
Question is this valid data:
byte[] data = {
0x02, // STX
0x03, // ETX
0x00, // LRC
};
I am supposed to return the most recent valid data which is that but there is better data within this which is:
byte[] validData = {
0x02, // STX
0x31,0x32,0x10,0x02,0x33, // Data 31 32 02 33
0x03, // ETX
0x31^0x32^0x02^0x33^0x03,// LRC calculated from the data (with the DLE removed) plus the ETX
};

Where can I find a list of Mac virtual key codes?

I'm using CGEventCreateKeyboardEvent and need to know what CGKeyCode values to use.
Specifically, I am after the key code for the Command key. The docs give examples for other keys: z is 6, shift is 56.
There must be a list of Mac virtual keycodes somewhere?
Below is a list of the common key codes for quick reference, taken from Events.h.
If you need to use these keycodes in an application, you should include the Carbon framework:
Objective-C:
#include <Carbon/Carbon.h>
Swift:
import Carbon.HIToolbox
You can then use the kVK_ANSI_A constants directly.
WARNING
The key constants reference physical keys on the keyboard. Their output changes if the typist is using a different keyboard layout. The letters in the constants correspond only to the U.S. QWERTY keyboard layout.
For example, the left ring-finger key on the homerow:
QWERTY keyboard layout > s > kVK_ANSI_S > "s"
Dvorak keyboard layout > o > kVK_ANSI_S > "o"
Strategies for layout-agnostic conversion of keycode to string, and vice versa, are discussed here:
How to convert ASCII character to CGKeyCode?
From Events.h:
/*
* Summary:
* Virtual keycodes
*
* Discussion:
* These constants are the virtual keycodes defined originally in
* Inside Mac Volume V, pg. V-191. They identify physical keys on a
* keyboard. Those constants with "ANSI" in the name are labeled
* according to the key position on an ANSI-standard US keyboard.
* For example, kVK_ANSI_A indicates the virtual keycode for the key
* with the letter 'A' in the US keyboard layout. Other keyboard
* layouts may have the 'A' key label on a different physical key;
* in this case, pressing 'A' will generate a different virtual
* keycode.
*/
enum {
kVK_ANSI_A = 0x00,
kVK_ANSI_S = 0x01,
kVK_ANSI_D = 0x02,
kVK_ANSI_F = 0x03,
kVK_ANSI_H = 0x04,
kVK_ANSI_G = 0x05,
kVK_ANSI_Z = 0x06,
kVK_ANSI_X = 0x07,
kVK_ANSI_C = 0x08,
kVK_ANSI_V = 0x09,
kVK_ANSI_B = 0x0B,
kVK_ANSI_Q = 0x0C,
kVK_ANSI_W = 0x0D,
kVK_ANSI_E = 0x0E,
kVK_ANSI_R = 0x0F,
kVK_ANSI_Y = 0x10,
kVK_ANSI_T = 0x11,
kVK_ANSI_1 = 0x12,
kVK_ANSI_2 = 0x13,
kVK_ANSI_3 = 0x14,
kVK_ANSI_4 = 0x15,
kVK_ANSI_6 = 0x16,
kVK_ANSI_5 = 0x17,
kVK_ANSI_Equal = 0x18,
kVK_ANSI_9 = 0x19,
kVK_ANSI_7 = 0x1A,
kVK_ANSI_Minus = 0x1B,
kVK_ANSI_8 = 0x1C,
kVK_ANSI_0 = 0x1D,
kVK_ANSI_RightBracket = 0x1E,
kVK_ANSI_O = 0x1F,
kVK_ANSI_U = 0x20,
kVK_ANSI_LeftBracket = 0x21,
kVK_ANSI_I = 0x22,
kVK_ANSI_P = 0x23,
kVK_ANSI_L = 0x25,
kVK_ANSI_J = 0x26,
kVK_ANSI_Quote = 0x27,
kVK_ANSI_K = 0x28,
kVK_ANSI_Semicolon = 0x29,
kVK_ANSI_Backslash = 0x2A,
kVK_ANSI_Comma = 0x2B,
kVK_ANSI_Slash = 0x2C,
kVK_ANSI_N = 0x2D,
kVK_ANSI_M = 0x2E,
kVK_ANSI_Period = 0x2F,
kVK_ANSI_Grave = 0x32,
kVK_ANSI_KeypadDecimal = 0x41,
kVK_ANSI_KeypadMultiply = 0x43,
kVK_ANSI_KeypadPlus = 0x45,
kVK_ANSI_KeypadClear = 0x47,
kVK_ANSI_KeypadDivide = 0x4B,
kVK_ANSI_KeypadEnter = 0x4C,
kVK_ANSI_KeypadMinus = 0x4E,
kVK_ANSI_KeypadEquals = 0x51,
kVK_ANSI_Keypad0 = 0x52,
kVK_ANSI_Keypad1 = 0x53,
kVK_ANSI_Keypad2 = 0x54,
kVK_ANSI_Keypad3 = 0x55,
kVK_ANSI_Keypad4 = 0x56,
kVK_ANSI_Keypad5 = 0x57,
kVK_ANSI_Keypad6 = 0x58,
kVK_ANSI_Keypad7 = 0x59,
kVK_ANSI_Keypad8 = 0x5B,
kVK_ANSI_Keypad9 = 0x5C
};
/* keycodes for keys that are independent of keyboard layout*/
enum {
kVK_Return = 0x24,
kVK_Tab = 0x30,
kVK_Space = 0x31,
kVK_Delete = 0x33,
kVK_Escape = 0x35,
kVK_Command = 0x37,
kVK_Shift = 0x38,
kVK_CapsLock = 0x39,
kVK_Option = 0x3A,
kVK_Control = 0x3B,
kVK_RightShift = 0x3C,
kVK_RightOption = 0x3D,
kVK_RightControl = 0x3E,
kVK_Function = 0x3F,
kVK_F17 = 0x40,
kVK_VolumeUp = 0x48,
kVK_VolumeDown = 0x49,
kVK_Mute = 0x4A,
kVK_F18 = 0x4F,
kVK_F19 = 0x50,
kVK_F20 = 0x5A,
kVK_F5 = 0x60,
kVK_F6 = 0x61,
kVK_F7 = 0x62,
kVK_F3 = 0x63,
kVK_F8 = 0x64,
kVK_F9 = 0x65,
kVK_F11 = 0x67,
kVK_F13 = 0x69,
kVK_F16 = 0x6A,
kVK_F14 = 0x6B,
kVK_F10 = 0x6D,
kVK_F12 = 0x6F,
kVK_F15 = 0x71,
kVK_Help = 0x72,
kVK_Home = 0x73,
kVK_PageUp = 0x74,
kVK_ForwardDelete = 0x75,
kVK_F4 = 0x76,
kVK_End = 0x77,
kVK_F2 = 0x78,
kVK_PageDown = 0x79,
kVK_F1 = 0x7A,
kVK_LeftArrow = 0x7B,
kVK_RightArrow = 0x7C,
kVK_DownArrow = 0x7D,
kVK_UpArrow = 0x7E
};
Macintosh Toolbox Essentials illustrates the physical locations of these virtual key codes for the Apple Extended Keyboard II in Figure 2-10:
The more canonical reference is in <HIToolbox/Events.h>:
/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h
In newer Versions of MacOS the "Events.h" moved to here:
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h
Found an answer here.
So:
Command key is 55
Shift is 56
Caps Lock 57
Option is 58
Control is 59.
Here are the all keycodes.
Here is a table with some keycodes for the three platforms. It is based on a US Extended keyboard layout.
http://web.archive.org/web/20100501161453/http://www.classicteck.com/rbarticles/mackeyboard.php
Or, there is an app in the Mac App Store named "Key Codes". Download it to see the keycodes of the keys you press.
Key Codes:
https://itunes.apple.com/tr/app/key-codes/id414568915?l=tr&mt=12
I found this wonderful article while doing the research for LibOS.
P.S: Mac's virtual key codes are the worst
In addition to the keycodes supplied in other answers, there are also "usage IDs" used for key remapping in the newer APIs introduced in macOS Sierra:
Technical Note TN2450
Remapping Keys in macOS 10.12 Sierra
Under macOS Sierra 10.12, the mechanism for key remapping was changed. This Technical Note is for developers of key remapping software so that they can update their software to support macOS Sierra 10.12. We present 2 solutions for implementing key remapping functionality for macOS 10.12 in this Technical Note.
https://developer.apple.com/library/archive/technotes/tn2450/_index.html
Keyboard a and A - 0x04
Keyboard b and B - 0x05
Keyboard c and C - 0x06
Keyboard d and D - 0x07
Keyboard e and E - 0x08
...
macOS 10.12+
Since macOS Sierra 10.12, keyCode has been according to the Universal Serial Bus HID Usage Tables (go to section: 10 Keyboard/Keypad Page, page 51).
Usage Usage ID (hex)
Keyboard a and A 0x04
Keyboard b and B 0x05
Keyboard c and C 0x06
Keyboard d and D 0x07
Keyboard e and E 0x08
Keyboard f and F 0x09
Keyboard g and G 0x0A
Keyboard h and H 0x0B
Keyboard i and I 0x0C
Keyboard j and J 0x0D
Keyboard k and K 0x0E
Keyboard l and L 0x0F
Keyboard m and M 0x10
Keyboard n and N 0x11
Keyboard o and O 0x12
Keyboard p and P 0x13
Keyboard q and Q 0x14
Keyboard r and R 0x15
Keyboard s and S 0x16
Keyboard t and T 0x17
Keyboard u and U 0x18
Keyboard v and V 0x19
Keyboard w and W 0x1A
Keyboard x and X 0x1B
Keyboard y and Y 0x1C
Keyboard z and Z 0x1D
Keyboard 1 and ! 0x1E
Keyboard 2 and # 0x1F
Keyboard 3 and # 0x20
Keyboard 4 and $ 0x21
Keyboard 5 and % 0x22
Keyboard 6 and ^ 0x23
Keyboard 7 and & 0x24
Keyboard 8 and * 0x25
Keyboard 9 and ( 0x26
Keyboard 0 and ) 0x27
Keyboard Return (Enter) 0x28
Keyboard Escape 0x29
Keyboard Delete (Backspace)0x2A
Keyboard Tab 0x2B
Keyboard Spacebar 0x2C
Keyboard - and _ 0x2D
Keyboard = and + 0x2E
Keyboard [ and { 0x2F
Keyboard ] and } 0x30
Keyboard \ and | 0x31
Keyboard Non-US # and ~ 0x32
Keyboard ; and : 0x33
Keyboard ' and " 0x34
Keyboard Grave Accent and Tilde 0x35
Keyboard , and "<" 0x36
Keyboard . and ">" 0x37
Keyboard / and ? 0x38
Keyboard Caps Lock 0x39
Keyboard F1 0x3A
Keyboard F2 0x3B
Keyboard F3 0x3C
Keyboard F4 0x3D
Keyboard F5 0x3E
Keyboard F6 0x3F
Keyboard F7 0x40
Keyboard F8 0x41
Keyboard F9 0x42
Keyboard F10 0x43
Keyboard F11 0x44
Keyboard F12 0x45
Keyboard Print Screen 0x46
Keyboard Scroll Lock 0x47
Keyboard Pause 0x48
Keyboard Insert 0x49
Keyboard Home 0x4A
Keyboard Page Up 0x4B
Keyboard Delete Forward 0x4C
Keyboard End 0x4D
Keyboard Page Down 0x4E
Keyboard Right Arrow 0x4F
Keyboard Left Arrow 0x50
Keyboard Down Arrow 0x51
Keyboard Up Arrow 0x52
Keypad Num Lock and Clear 0x53
Keypad / 0x54
Keypad * 0x55
Keypad - 0x56
Keypad + 0x57
Keypad Enter 0x58
Keypad 1 and End 0x59
Keypad 2 and Down Arrow 0x5A
Keypad 3 and Page Down 0x5B
Keypad 4 and Left Arrow 0x5C
Keypad 5 0x5D
Keypad 6 and Right Arrow 0x5E
Keypad 7 and Home 0x5F
Keypad 8 and Up Arrow 0x60
Keypad 9 and Page Up 0x61
Keypad 0 and Insert 0x62
Keypad . and Delete 0x63
Keyboard Non-US \ and | 0x64
Keyboard Application 0x65
Keyboard Power 0x66
Keypad = 0x67
Keyboard F13 0x68
Keyboard F14 0x69
Keyboard F15 0x6A
Keyboard F16 0x6B
Keyboard F17 0x6C
Keyboard F18 0x6D
Keyboard F19 0x6E
Keyboard F20 0x6F
Keyboard F21 0x70
Keyboard F22 0x71
Keyboard F23 0x72
Keyboard F24 0x73
Keyboard Left Control 0xE0
Keyboard Left Shift 0xE1
Keyboard Left Alt 0xE2
Keyboard Left GUI 0xE3
Keyboard Right Control 0xE4
Keyboard Right Shift 0xE5
Keyboard Right Alt 0xE6
Keyboard Right GUI 0xE7
Here's some prebuilt Objective-C dictionaries if anyone wants to type ansi characters:
NSDictionary *lowerCaseCodes = #{
#"Q" : #(12),
#"W" : #(13),
#"E" : #(14),
#"R" : #(15),
#"T" : #(17),
#"Y" : #(16),
#"U" : #(32),
#"I" : #(34),
#"O" : #(31),
#"P" : #(35),
#"A" : #(0),
#"S" : #(1),
#"D" : #(2),
#"F" : #(3),
#"G" : #(5),
#"H" : #(4),
#"J" : #(38),
#"K" : #(40),
#"L" : #(37),
#"Z" : #(6),
#"X" : #(7),
#"C" : #(8),
#"V" : #(9),
#"B" : #(11),
#"N" : #(45),
#"M" : #(46),
#"0" : #(29),
#"1" : #(18),
#"2" : #(19),
#"3" : #(20),
#"4" : #(21),
#"5" : #(23),
#"6" : #(22),
#"7" : #(26),
#"8" : #(28),
#"9" : #(25),
#" " : #(49),
#"." : #(47),
#"," : #(43),
#"/" : #(44),
#";" : #(41),
#"'" : #(39),
#"[" : #(33),
#"]" : #(30),
#"\\" : #(42),
#"-" : #(27),
#"=" : #(24)
};
NSDictionary *shiftCodes = #{ // used in conjunction with the shift key
#"<" : #(43),
#">" : #(47),
#"?" : #(44),
#":" : #(41),
#"\"" : #(39),
#"{" : #(33),
#"}" : #(30),
#"|" : #(42),
#")" : #(29),
#"!" : #(18),
#"#" : #(19),
#"#" : #(20),
#"$" : #(21),
#"%" : #(23),
#"^" : #(22),
#"&" : #(26),
#"*" : #(28),
#"(" : #(25),
#"_" : #(27),
#"+" : #(24)
};

Resources