qmk: Make a layer respond to two modifier keys being pressed? - qmk

In a qmk_firmware configuration, I can map a single modifier key to a new keymap layer using MO(x).
How can I do this such that two modifier keys must be pressed simultaneously?
Example: I would like to map [Fn][Ctrl]-[d] to generate a Unicode delta, [Fn][Ctrl]-[e] to generate a Unicode epsilon, etc.

You have to put your specific code into the custom Quantum function process_record_user:
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
// enter your code for [Fn][Ctrl]-[α] here
return true;
}
You can try the Quantum tab in the Firmware Builder. Even if it is end-of-life, you'll see, what is meant.
You can also set UNICODEMAP_ENABLE = yes and use the Unicode Map.

Something like this should do (half) the trick:
In function layer_state_set_user, check for layer Fn (some bit arithmetic similar to update_tri_layer_state) and the Ctrl state (get_mods() & MOD_MASK_CTRL). When in Fn layer and Ctrl is down, deactivate Ctrl (del_mods(MOD_MASK_CTRL)) and return state | x; otherwise return state & ~x.
Unfortunately, this will probably require Ctrl to be pressed before Fn.
At least that's what happens in my similar shift + layer _L4 => layer _S_L4 implementation in my keymap. It requires shift to be pressed before LT(_L4,…).
For the other direction (_L4 + shift => _S_L4), I have MO(_S_L4) on the shift keys in layer _L4, but that is somehow disabled by my layer_state_set_user.

What should "Fn + E" and "Fn + D" do (when Ctrl is not held)? For sake of example, I'll assume you want them to do PgUp and PgDn.
Here is how I would go about implementing this:
Enable Unicode input: In rules.mk, add UNICODEMAP_ENABLE = yes. In config.h, add #define UNICODE_SELECTED_MODES UC_WINC if you are on Windows. See the Unicode documentation for other OSs and options.
Define an "Fn" layer in the keymap.
Define a couple custom keycodes, and place them in the Fn layer at the d and e positions.
Handle the custom keys in process_record_user(), using get_mods() to test whether Ctrl is held. See also macros that respond to mods. Then use send_unicode_string() to type the Unicode symbol itself.
Code sketch:
// Copyright 2022 Google LLC.
// SPDX-License-Identifier: Apache-2.0
enum layers { BASE, FN, /* Other layers... */ };
enum custom_keycodes {
UPDIR = SAFE_RANGE,
FN_E,
FN_D,
// Other custom keys...
};
const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
[BASE] = LAYOUT(...),
[FN] = LAYOUT(..., FN_E, ..., FN_D, ...),
...
};
const uint32_t unicode_map[] PROGMEM = {};
static void symbol_key(uint16_t* registered_key,
keyrecord_t* record,
uint16_t default_keycode,
const char* symbol,
const char* uppercase_symbol) {
if (record->event.pressed) { // On key press.
const uint8_t mods = get_mods();
const bool ctrl_held = (mods & MOD_MASK_CTRL) != 0;
const bool shifted = (mods & MOD_MASK_SHIFT) != 0;
if (ctrl_held) { // Is the Ctrl mod held?
unregister_mods(MOD_MASK_CTRL); // Clear the Ctrl mod.
// Type Unicode symbol according to whether shift is active.
send_unicode_string(shifted ? uppercase_symbol : symbol);
*registered_key = KC_NO;
} else {
*registered_key = default_keycode;
register_code16(*registered_key);
}
} else { // On key release.
unregister_code16(*registered_key);
*registered_key = KC_NO;
}
}
bool process_record_user(uint16_t keycode, keyrecord_t* record) {
const uint8_t mods = get_mods();
const bool ctrl_held = (mods & MOD_MASK_CTRL) != 0;
const bool shifted = (mods & MOD_MASK_SHIFT) != 0;
switch (keycode) {
case FN_E: {
static uint16_t registered_key = KC_NO;
symbol_key(&registered_key, record, KC_PGUP, "ε", "Ε");
} return false;
case FN_D: {
static uint16_t registered_key = KC_NO;
symbol_key(&registered_key, record, KC_PGDN, "δ", "Δ");
} return false;
}
return true;
}

Related

I can't read keydatas (buttons' press values) with SPI between XMC4800 and STLED316

I use SPI communication between XMC4800 and STLED316 led controller. I can write datas to the display on STLED316.However, I can't read keydatas (by keyscan feature of STLED, it is written by STLED316 datasheet). I have some codes for write and read. I suppose command address or register address to send a byte to STLED is wrong. I couldn't figure out if they are the problem or something else. I simplified the codes. I used SPI_MASTER API for communication. write_7segg is working but can't use keydata's specific bits to use button press values (0,1). I need to use key press (keydata) values to change something on the display. If someone worked with STLED316 before, it maybe more understandable. Finally, STLED316 has a 5-digit display and 5 buttons with keyscan feature. read[0] = STLED316_DATA_RD = 0x40, read[1] = STLED316_READ_PAGE = 0x08, keydata[0] = STLED316_ADDR_KEY_DATA1 = 0x01. Here the codes are:
keydata = read_keyscan();
if ((((keydata) & 0x01) == 1) && (current_mode == 0)) {
write_7segg(4, arServo_Numbers[0]);
write_7segg(3, arServo_Numbers[0]);
write_7segg(2, arServo_Characters[23]);
write_7segg(1, arServo_Numbers[0]);
write_7segg(0, arServo_Characters[15]);
}
void write_7segg(unsigned char DisplayNumber, unsigned char Segments) {
// DIGITAL_IO_SetOutputLow(&DIGITAL_IO_0);
Buffer[0] = DisplayNumber;
Buffer[1] = Segments;
DIGITAL_IO_SetOutputLow(&DIGITAL_IO_8);
SPI_MASTER_Transmit(&SPI_MASTER_01,Buffer, 2);
DIGITAL_IO_SetOutputHigh(&DIGITAL_IO_8);
uint8_t readData(uint8_t address){
uint8_t sendByte = read[0]|read[1]|address;
uint8_t readByte = 0;
DIGITAL_IO_SetOutputLow(&DIGITAL_IO_8);
SPI_MASTER_Transfer(&SPI_MASTER_01,&sendByte, &readByte, 1);
DIGITAL_IO_SetOutputHigh(&DIGITAL_IO_8);
return readByte;
}
uint16_t read_keyscan(void){
uint16_t keyState = 0;
keyState = readData(keys[1]) << 8;
keyState = readData(keys[0]);
return keyState;
}

How to get selected adapter's MAC address in WinPcap?

For example, when program runs, I entered 1 as input and wanted to get MAC address of that interface in here. How can I do that?
I did a lot of work trying to figure out how to both get the mac address for an arbitrary interface under Windows, and matching that to the device info you get back from WinPCap.
A lot of posts say you should use GetAdaptersInfo or similar functions to get the mac address, but unfortunately, those functions only work with an interface that has ipv4 or ipv6 bound to it. I had a network card that purposely wasn't bound to anything, so that Windows wouldn't send any data over it.
GetIfTable(), however, seems to actually get you every interface on the system (there were 40 some odd on mine). It has the hardware mac address for each interface, so you just need to match it to the corresponding WinPCap device. The device name in WinPCap has a long GUID, which is also present in the name field of the interface table entries you get from GetIfTable. The names don't match exactly, though, so you have to extract the GUID from each name and match that. An additional complication is that the name field in the WinPCap device is a regular character string, but the name in the data you get from GetIfTable is a wide character string. The code below worked for me on two different systems, one Windows 7 and another Windows 10. I used the Microsoft GetIfTable example code as a starting point:
#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib, "IPHLPAPI.lib")
#include <pcap.h>
// Compare the guid parts of both names and see if they match
int compare_guid(wchar_t *wszPcapName, wchar_t *wszIfName)
{
wchar_t *pc, *ic;
// Find first { char in device name from pcap
for (pc = wszPcapName; ; ++pc)
{
if (!*pc)
return -1;
if (*pc == L'{'){
pc++;
break;
}
}
// Find first { char in interface name from windows
for (ic = wszIfName; ; ++ic)
{
if (!*ic)
return 1;
if (*ic == L'{'){
ic++;
break;
}
}
// See if the rest of the GUID string matches
for (;; ++pc,++ic)
{
if (!pc)
return -1;
if (!ic)
return 1;
if ((*pc == L'}') && (*ic == L'}'))
return 0;
if (*pc != *ic)
return *ic - *pc;
}
}
// Find mac address using GetIFTable, since the GetAdaptersAddresses etc functions
// ony work with adapters that have an IP address
int get_mac_address(pcap_if_t *d, u_char mac_addr[6])
{
// Declare and initialize variables.
wchar_t* wszWideName = NULL;
DWORD dwSize = 0;
DWORD dwRetVal = 0;
int nRVal = 0;
unsigned int i;
/* variables used for GetIfTable and GetIfEntry */
MIB_IFTABLE *pIfTable;
MIB_IFROW *pIfRow;
// Allocate memory for our pointers.
pIfTable = (MIB_IFTABLE *)malloc(sizeof(MIB_IFTABLE));
if (pIfTable == NULL) {
return 0;
}
// Make an initial call to GetIfTable to get the
// necessary size into dwSize
dwSize = sizeof(MIB_IFTABLE);
dwRetVal = GetIfTable(pIfTable, &dwSize, FALSE);
if (dwRetVal == ERROR_INSUFFICIENT_BUFFER) {
free(pIfTable);
pIfTable = (MIB_IFTABLE *)malloc(dwSize);
if (pIfTable == NULL) {
return 0;
}
dwRetVal = GetIfTable(pIfTable, &dwSize, FALSE);
}
if (dwRetVal != NO_ERROR)
goto done;
// Convert input pcap device name to a wide string for compare
{
size_t stISize,stOSize;
stISize = strlen(d->name) + 1;
wszWideName = malloc(stISize * sizeof(wchar_t));
if (!wszWideName)
goto done;
mbstowcs_s(&stOSize,wszWideName,stISize, d->name, stISize);
}
for (i = 0; i < pIfTable->dwNumEntries; i++) {
pIfRow = (MIB_IFROW *)& pIfTable->table[i];
if (!compare_guid(wszWideName, pIfRow->wszName)){
if (pIfRow->dwPhysAddrLen != 6)
continue;
memcpy(mac_addr, pIfRow->bPhysAddr, 6);
nRVal = 1;
break;
}
}
done:
if (pIfTable != NULL)
free(pIfTable);
pIfTable = NULL;
if (wszWideName != NULL)
free(wszWideName);
wszWideName = NULL;
return nRVal;
}

Vulkan depth image binding error

Hi I am trying to bind depth memory buffer but I get an error saying as below. I have no idea why this error is popping up.
The depth format is VK_FORMAT_D16_UNORM and the usage is VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT. I have read online that the TILING shouldnt be linear but then I get a different error. Thanks!!!
The code for creating and binding the image is as below.
VkImageCreateInfo imageInfo = {};
// If the depth format is undefined, use fallback as 16-byte value
if (Depth.format == VK_FORMAT_UNDEFINED) {
Depth.format = VK_FORMAT_D16_UNORM;
}
const VkFormat depthFormat = Depth.format;
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(*deviceObj->gpu, depthFormat, &props);
if (props.linearTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
imageInfo.tiling = VK_IMAGE_TILING_LINEAR;
}
else if (props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
}
else {
std::cout << "Unsupported Depth Format, try other Depth formats.\n";
exit(-1);
}
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.pNext = NULL;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.format = depthFormat;
imageInfo.extent.width = width;
imageInfo.extent.height = height;
imageInfo.extent.depth = 1;
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.samples = NUM_SAMPLES;
imageInfo.queueFamilyIndexCount = 0;
imageInfo.pQueueFamilyIndices = NULL;
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
imageInfo.flags = 0;
// User create image info and create the image objects
result = vkCreateImage(deviceObj->device, &imageInfo, NULL, &Depth.image);
assert(result == VK_SUCCESS);
// Get the image memory requirements
VkMemoryRequirements memRqrmnt;
vkGetImageMemoryRequirements(deviceObj->device, Depth.image, &memRqrmnt);
VkMemoryAllocateInfo memAlloc = {};
memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
memAlloc.pNext = NULL;
memAlloc.allocationSize = 0;
memAlloc.memoryTypeIndex = 0;
memAlloc.allocationSize = memRqrmnt.size;
// Determine the type of memory required with the help of memory properties
pass = deviceObj->memoryTypeFromProperties(memRqrmnt.memoryTypeBits, 0, /* No requirements */ &memAlloc.memoryTypeIndex);
assert(pass);
// Allocate the memory for image objects
result = vkAllocateMemory(deviceObj->device, &memAlloc, NULL, &Depth.mem);
assert(result == VK_SUCCESS);
// Bind the allocated memeory
result = vkBindImageMemory(deviceObj->device, Depth.image, Depth.mem, 0);
assert(result == VK_SUCCESS);
Yes, linear tiling may not be supported for depth usage Images.
Consult the specification and Valid Usage section of VkImageCreateInfo. The capability is queried by vkGetPhysicalDeviceFormatProperties and vkGetPhysicalDeviceImageFormatProperties commands. Though depth formats are "opaque", so there is not much reason to use linear tiling.
This you seem to be doing in your code.
But the error informs you that you are trying to use a memory type that is not allowed for the given Image. Use vkGetImageMemoryRequirements command to query which memory types are allowed.
Possibly you have some error there (you are using 0x1 which is obviously not part of 0x84 per the message). You may want to reuse the example code in the Device Memory chapter of the specification. Provide your memoryTypeFromProperties implementation for more specific answer.
I accidentally set the typeIndex to 1 instead of i and it works now. In my defense I have been vulkan coding the whole day and my eyes are bleeding :). Thanks for the help.
bool VulkanDevice::memoryTypeFromProperties(uint32_t typeBits, VkFlags
requirementsMask, uint32_t *typeIndex)
{
// Search memtypes to find first index with those properties
for (uint32_t i = 0; i < 32; i++) {
if ((typeBits & 1) == 1) {
// Type is available, does it match user properties?
if ((memoryProperties.memoryTypes[i].propertyFlags & requirementsMask) == requirementsMask) {
*typeIndex = i;// was set to 1 :(
return true;
}
}
typeBits >>= 1;
}
// No memory types matched, return failure
return false;
}

What is the grammar of rule of this code in Objective-C or in C language?

I'm reading the code of Mach Ports, I want to know what's the paradigm of a piece of code. I mean I knew the grammar of struct of objective-c, but I don't know what grammar of message.header = (mach_msg_header_t) {......};
The complete code is below.
natural_t data;
mach_port_t port;
struct {
mach_msg_header_t header;
mach_msg_body_t body;
mach_msg_type_descriptor_t type;
} message;
message.header = (mach_msg_header_t) {
.msgh_remote_port = port,
.msgh_local_port = MACH_PORT_NULL,
.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0),
.msgh_size = sizeof(message)
};
The header is assigned to the type-casted mach_msg_header_t pseudo constructor that initializes some of the fields. A break down of the structure is available here : http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/ (partially pasted below)
typedef struct {
mach_msg_bits_t msgh_bits;
mach_msg_size_t msgh_size;
mach_port_t msgh_remote_port;
mach_port_t msgh_local_port;
mach_port_seqno_t msgh_seqno;
mach_msg_id_t msgh_id;
} mach_msg_header_t;
The bit you referenced, does the assignment of the low level fields in the structure and copy into the header.
message.header = (mach_msg_header_t) {
.msgh_remote_port = port,
.msgh_local_port = MACH_PORT_NULL,
.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0),
.msgh_size = sizeof(message)
};

Objective C - How to receive two int in same parameter

I need to write a method like this:
-(void)doStuff:(int)options;
Based in the a typedef enum like this:
typedef enum
{
FirstOption,
SecondOption,
ThirdOption
} MyOptions
What I need to to do in order to be able to call the method in this way (i.e. calling the method with more than one option "enabled":
[self doStuff:(FirstOption | ThirdOption)];
Do I need to setup the typedef enum differently? And how I check the options received in the method, a simple if (options == ...)?
What you call for is a bit array. Define your options like this:
enum MyOptions
{
FirstOption = 0x01, // first bit
SecondOption = 0x02, // second bit
ThirdOption = 0x04, // third bit
... = 0x08 ...
};
Combine the options like you suggested, with |, and test for them with & (options & SecondOption).
- (void) doStuff: (MyOptions) options
{
if ( options & FirstOption )
{
// do something fancy
}
if ( options & SecondOption )
{
// do something awesome
}
if ( (options & SecondOption) && ( options & ThirdOption) )
{
// do something sublime
}
}
I'm no expert at Obj-C, but in other languages I would use flags. If each value is a power of two, then it will have only one bit set for that value. You can use that bit as a bool for a particular option.
FirstOption = 1
SecondOption = 2
ThirdOption = 4
FirstAndThird = FirstOption | ThirdOption; // Binary Or sets the bits
// Binary And checks the bits
IsFirst = FirstAndThird & FirstOption == FirstOption; // is true
IsSecond = FirstAndThird & SecondOption == SecondOption; // is false
IsThird = FirstAndThird & ThirdOption == ThirdOption; // is true
This question may also be of use.