title: Macos combine HID key inputs from 2 devices
body: <p>I am trying to bind the key shift on my mice to combine it with my keyboards inputs (ex: shift+1, shift+2)</p>
  <p>The keyboard device that I am using is a Razer tartarus and their software doesnt really run well for me on Monterey so I wrote a simple objective-c script to remap the inputs and it works well, I can also remap the input on my mice using the software that comes with it to send key shift, or shift+1 and it works.</p>
  <p>However when I hold shift on the mice and send a key using the keyboard the shift isnt detected anymore. Same happends the other way arround if i hold shift on tartarus and press a button on the mice.</p>
  <p>However i found out if I use my normal keyboard shift and press a button on the mice it detect it has shift+button.</p>
  <p>I am not quite sure what is going on under the hood but i would really love to have a workarround for this as I really need to be able to use shift on mouse + keys on Tartarus keyboard.</p>
  <p>The script that I use to remap keys on the tartarus is the following:</p>
  <pre><code>#import &lt;IOKit/hidsystem/IOHIDEventSystemClient.h&gt;
  #import &lt;IOKit/hidsystem/IOHIDServiceClient.h&gt;
  #import &lt;IOKit/hid/IOHIDUsageTables.h&gt;
  
  static NSArray *matchingKeys(void)
  {
      return @[
          @kIOHIDVendorIDKey,
          @kIOHIDProductIDKey,
          @kIOHIDTransportKey,
          @kIOHIDPrimaryUsageKey,
          @kIOHIDPrimaryUsagePageKey,
          @kIOHIDLocationIDKey,
          @kIOHIDTransportKey,
          @kIOHIDProductKey,
          @kIOHIDManufacturerKey,
          @kIOClassKey
      ];
  }
  
  NSDictionary *createServiceInfoDictionary(IOHIDServiceClientRef service)
  {
      NSMutableDictionary *serviceInfo = [[NSMutableDictionary  alloc] init];
      if (serviceInfo == NULL)
      {
          return serviceInfo;
      }
      [serviceInfo setValue:(NSNumber *)CFBridgingRelease(IOHIDServiceClientGetRegistryID(service)) forKey: @kIORegistryEntryIDKey];
      for (NSString *key in matchingKeys())
      {
          [serviceInfo setValue:CFBridgingRelease(IOHIDServiceClientCopyProperty(service, (__bridge CFStringRef)key)) forKey:key];
      }
      return serviceInfo;
  }
  
  int main(int argc, char *argv[])
  {
      IOHIDEventSystemClientRef system;
      CFArrayRef services;
      uint64_t base_key = 0x700000000;
      //https://developer.apple.com/library/archive/technotes/tn2450/_index.html#//apple_ref/doc/uid/DTS40017618-CH1-KEY_TABLE_USAGES
      //Old keys
      uint64_t key_tab = 0x2B;
      uint64_t key_q = 0x14;
      uint64_t key_w = 0x1A;
      uint64_t key_e = 0x08;
      uint64_t key_r = 0x15;
      uint64_t key_capslock = 0x39;
      uint64_t key_a = 0x04;
      uint64_t key_s = 0x16;
      uint64_t key_d = 0x07;
      uint64_t key_f = 0x09;
      uint64_t key_left_shift = 0xE1;
      uint64_t key_z = 0x1D;
      uint64_t key_x = 0x1B;
      uint64_t key_c = 0x06;
      uint64_t key_left_alt = 0xE2;
      //New keys
      uint64_t key_six = 0x23;
      uint64_t key_seven = 0x24;
      uint64_t key_eight = 0x25;
      uint64_t key_nine = 0x26;
      uint64_t key_zero = 0x27;
      uint64_t key_f6 = 0x3F;
      uint64_t key_f7 = 0x40;
      uint64_t key_f8 = 0x41;
      uint64_t key_f9 = 0x42;
      uint64_t key_f10 = 0x43;
      uint64_t key_f1 = 0x3A;
      uint64_t key_f2 = 0x3B;
      uint64_t key_f3 = 0x3C;
      uint64_t key_f4 = 0x3D;
      uint64_t key_f5 = 0x3E;
      //Mapping
      NSArray *map = @[
          @{@kIOHIDKeyboardModifierMappingSrcKey:@(base_key | key_tab), @kIOHIDKeyboardModifierMappingDstKey:@(base_key | key_six)},
          @{@kIOHIDKeyboardModifierMappingSrcKey:@(base_key | key_q), @kIOHIDKeyboardModifierMappingDstKey:@(base_key | key_seven)},
          @{@kIOHIDKeyboardModifierMappingSrcKey:@(base_key | key_w), @kIOHIDKeyboardModifierMappingDstKey:@(base_key | key_eight)},
          @{@kIOHIDKeyboardModifierMappingSrcKey:@(base_key | key_e), @kIOHIDKeyboardModifierMappingDstKey:@(base_key | key_nine)},
          @{@kIOHIDKeyboardModifierMappingSrcKey:@(base_key | key_r), @kIOHIDKeyboardModifierMappingDstKey:@(base_key | key_zero)},
          @{@kIOHIDKeyboardModifierMappingSrcKey:@(base_key | key_capslock), @kIOHIDKeyboardModifierMappingDstKey:@(base_key | key_f6)},
          @{@kIOHIDKeyboardModifierMappingSrcKey:@(base_key | key_a), @kIOHIDKeyboardModifierMappingDstKey:@(base_key | key_f7)},
          @{@kIOHIDKeyboardModifierMappingSrcKey:@(base_key | key_s), @kIOHIDKeyboardModifierMappingDstKey:@(base_key | key_f8)},
          @{@kIOHIDKeyboardModifierMappingSrcKey:@(base_key | key_d), @kIOHIDKeyboardModifierMappingDstKey:@(base_key | key_f9)},
          @{@kIOHIDKeyboardModifierMappingSrcKey:@(base_key | key_f), @kIOHIDKeyboardModifierMappingDstKey:@(base_key | key_f10)},
          @{@kIOHIDKeyboardModifierMappingSrcKey:@(base_key | key_left_shift), @kIOHIDKeyboardModifierMappingDstKey:@(base_key | key_f1)},
          @{@kIOHIDKeyboardModifierMappingSrcKey:@(base_key | key_z), @kIOHIDKeyboardModifierMappingDstKey:@(base_key | key_f2)},
          @{@kIOHIDKeyboardModifierMappingSrcKey:@(base_key | key_x), @kIOHIDKeyboardModifierMappingDstKey:@(base_key | key_f3)},
          @{@kIOHIDKeyboardModifierMappingSrcKey:@(base_key | key_c), @kIOHIDKeyboardModifierMappingDstKey:@(base_key | key_f4)},
          @{@kIOHIDKeyboardModifierMappingSrcKey:@(base_key | key_left_alt), @kIOHIDKeyboardModifierMappingDstKey:@(base_key | key_f5)}
      ];
      system = IOHIDEventSystemClientCreateSimpleClient(kCFAllocatorDefault);
      services = IOHIDEventSystemClientCopyServices(system);
      for(CFIndex i = 0; i &lt; CFArrayGetCount(services); i++)
      {
          IOHIDServiceClientRef service = (IOHIDServiceClientRef)CFArrayGetValueAtIndex(services, i);
          NSDictionary *serviceInfo = createServiceInfoDictionary (service);
          uint64_t product_id = ((NSNumber *)serviceInfo[@kIOHIDProductIDKey]).unsignedIntValue;
          uint64_t vendor_id = ((NSNumber *)serviceInfo[@kIOHIDVendorIDKey]).unsignedIntValue;
   
          if(IOHIDServiceClientConformsTo(service, kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard))
          {
              if(product_id == 555 &amp;&amp; vendor_id == 5426)//Razer Tartarus V2
              {
                  IOHIDServiceClientSetProperty(service, CFSTR(kIOHIDUserKeyUsageMapKey), (CFArrayRef)map);
              }
          }
      }
      CFRelease(services);
      CFRelease(system);
      return 0;
  }
  </code></pre>