void
    terminate(void)
    {
      refresh_timer_.terminate();

      clear_remapclasses();
    }
 void
 refresh(void)
 {
   // We use timer to prevent deadlock of lock_. (refresh may be called in the remap_key, remap_consumer, *).
   enum {
     DELAY = 1,
   };
   refresh_timer_.setTimeoutMS(DELAY);
 }
示例#3
0
    void
    terminate(void)
    {
      refresh_timer_.terminate();

      clear_xml();

      IOLockWrapper::free(lock_);
    }
    void
    initialize(IOWorkLoop& workloop)
    {
      statusmessage_[0] = '\0';
      lastmessage_[0] = '\0';
      remapclasses_ = NULL;
      enabled_remapclasses_ = NULL;

      refresh_timer_.initialize(&workloop, NULL, refresh_timer_callback);
    }
示例#5
0
    void
    initialize(IOWorkLoop& workloop)
    {
      lock_ = IOLockWrapper::alloc();
      statusmessage_[0] = '\0';
      lastmessage_[0] = '\0';
      remapclasses_ = NULL;
      enabled_remapclasses_ = NULL;

      refresh_timer_.initialize(&workloop, NULL, refresh_core);
    }
示例#6
0
void CALLBACK TimerCallbackWrapper(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
{
    TimerWrapper* wrapper = reinterpret_cast<TimerWrapper*>(lpParameter);
    wrapper->Callback(wrapper->Parameter);
}
  namespace RemapClassManager {
    TimerWrapper refresh_timer_;

    char statusmessage_[BRIDGE_USERCLIENT_STATUS_MESSAGE_MAXLEN];
    char lastmessage_[BRIDGE_USERCLIENT_STATUS_MESSAGE_MAXLEN];
    bool isEventInputQueueDelayEnabled_ = false;

    Vector_RemapClassPointer* remapclasses_ = NULL;
    Vector_RemapClassPointer* enabled_remapclasses_ = NULL;

    // ======================================================================
    static void
    refresh_timer_callback(OSObject* owner, IOTimerEventSource* sender)
    {
      if (! remapclasses_) {
        IOLOG_ERROR("RemapClassManager::refresh_core remapclasses_ == NULL.\n");
        return;
      }

      // ----------------------------------------
      if (enabled_remapclasses_) {
        delete enabled_remapclasses_;
      }
      enabled_remapclasses_ = new Vector_RemapClassPointer();
      if (! enabled_remapclasses_) return;

      // ----------------------------------------
      KeyboardRepeat::cancel();

      statusmessage_[0] = '\0';

      isEventInputQueueDelayEnabled_ = false;

      for (size_t i = 0; i < remapclasses_->size(); ++i) {
        RemapClass* p = (*remapclasses_)[i];
        if (! p) continue;

        if (p->enabled()) {
          enabled_remapclasses_->push_back(p);

          const char* msg = p->get_statusmessage();
          if (msg) {
            strlcat(statusmessage_, msg, sizeof(statusmessage_));
            strlcat(statusmessage_, " ", sizeof(statusmessage_));
          }

          if (p->is_simultaneouskeypresses()) {
            isEventInputQueueDelayEnabled_ = true;
          }
        }
      }

      if (strcmp(statusmessage_, lastmessage_) != 0) {
        strlcpy(lastmessage_, statusmessage_, sizeof(lastmessage_));

        int index = BRIDGE_USERCLIENT_STATUS_MESSAGE_EXTRA;
        CommonData::clear_statusmessage(index);
        CommonData::append_statusmessage(index, statusmessage_);
        CommonData::send_notification_statusmessage(index);
      }
    }

    // ======================================================================

    void
    initialize(IOWorkLoop& workloop)
    {
      statusmessage_[0] = '\0';
      lastmessage_[0] = '\0';
      remapclasses_ = NULL;
      enabled_remapclasses_ = NULL;

      refresh_timer_.initialize(&workloop, NULL, refresh_timer_callback);
    }

    static void
    clear_remapclasses(void)
    {
      VirtualKey::VK_CONFIG::clear_items();

      if (enabled_remapclasses_) {
        delete enabled_remapclasses_;
        enabled_remapclasses_ = NULL;
      }

      if (remapclasses_) {
        for (size_t i = 0; i < remapclasses_->size(); ++i) {
          RemapClass* p = (*remapclasses_)[i];
          if (p) {
            delete p;
          }
        }
        delete remapclasses_;
        remapclasses_ = NULL;
      }
    }

    void
    terminate(void)
    {
      refresh_timer_.terminate();

      clear_remapclasses();
    }

    bool
    load_remapclasses_initialize_vector(const uint32_t* const remapclasses_initialize_vector, mach_vm_size_t vector_size)
    {
      // ------------------------------------------------------------
      // clean previous resources and setup new resources.
      clear_remapclasses();

      remapclasses_ = new Vector_RemapClassPointer();
      if (! remapclasses_) {
        IOLOG_ERROR("%s remapclasses_ == NULL.\n", __FUNCTION__);
        goto error;
      }

      // ------------------------------------------------------------
      // Validate vector_size

      // "vector_size" is byte of remapclasses_initialize_vector. (!= count of items.)
      // Confirming vector_size is a multiple of sizeof(uint32_t).
      if ((vector_size % sizeof(uint32_t)) != 0) {
        IOLOG_ERROR("%s (vector_size %% sizeof(uint32_t)) != 0. (%d)\n", __FUNCTION__, static_cast<int>(vector_size));
        goto error;
      }

      // change vector_size to num of uint32_t.
      vector_size /= sizeof(uint32_t);
      // Then, we can treat "remapclasses_initialize_vector + vector_size" as valid.

      if (vector_size < 2) {
        IOLOG_ERROR("%s vector_size < 2. (%d)\n", __FUNCTION__, static_cast<int>(vector_size));
        goto error;
      }
      if (vector_size > RemapClass::MAX_ALLOCATION_COUNT) {
        IOLOG_ERROR("%s too large vector_size. (%d)\n", __FUNCTION__, static_cast<int>(vector_size));
        goto error;
      }

      // ------------------------------------------------------------
      {
        const uint32_t* p = remapclasses_initialize_vector;
        uint32_t version = *p++;
        uint32_t count   = *p++;

        if (version != BRIDGE_REMAPCLASS_INITIALIZE_VECTOR_FORMAT_VERSION) {
          IOLOG_ERROR("%s version mismatch.\n", __FUNCTION__);
          goto error;
        }
        if (count > RemapClass::MAX_CONFIG_COUNT) {
          IOLOG_ERROR("%s too many count. (%d)\n", __FUNCTION__, count);
          goto error;
        }

        // ------------------------------------------------------------
        // load
        remapclasses_->reserve(count);
        RemapClass::reset_allocation_count();

        // (1) Setting NULL to all items.
        for (uint32_t i = 0; i < count; ++i) {
          remapclasses_->push_back(NULL);
        }

        // (2) Setting RemapClass* to items.
        for (uint32_t i = 0; i < count; ++i) {
          if (p >= remapclasses_initialize_vector + vector_size) {
            IOLOG_ERROR("%s vector_size mismatch.\n", __FUNCTION__);
            goto error;
          }

          uint32_t size = *p++;
          if (p + size > remapclasses_initialize_vector + vector_size) {
            IOLOG_ERROR("%s vector_size mismatch. (vector_size:%d, size:%d)\n", __FUNCTION__,
                        static_cast<int>(vector_size), size);
            goto error;
          }
          if (size == 0) {
            IOLOG_ERROR("%s size == 0.\n", __FUNCTION__);
            goto error;
          }

          uint32_t configindex = *p++;
          --size;

          RemapClass* newp = new RemapClass(p, size);
          if (! newp) {
            IOLOG_ERROR("%s newp == NULL.\n", __FUNCTION__);
            goto error;
          }
          p += size;

          if (configindex >= remapclasses_->size()) {
            IOLOG_ERROR("%s invalid configindex %d (remapclasses_->size() == %d).\n", __FUNCTION__,
                        configindex, static_cast<int>(remapclasses_->size()));
            goto error;
          }
          (*remapclasses_)[configindex] = newp;
        }

        // (3) Making sure that is not NULL for all items.
        for (uint32_t i = 0; i < remapclasses_->size(); ++i) {
          if (! (*remapclasses_)[i]) {
            IOLOG_ERROR("%s (*remapclasses_)[i] == NULL.\n", __FUNCTION__);
            goto error;
          }
        }
      }

      RemapClass::log_allocation_count();

      return true;

    error:
      clear_remapclasses();
      return false;
    }

    bool
    set_config(const int32_t* const config_vector, mach_vm_size_t config_size)
    {
      // ------------------------------------------------------------
      // check
      if (! remapclasses_) {
        IOLOG_ERROR("%s remapclasses_ == NULL.\n", __FUNCTION__);
        return false;
      }

      if (config_size != (BRIDGE_ESSENTIAL_CONFIG_INDEX__END__ + remapclasses_->size()) * sizeof(int32_t)) {
        IOLOG_ERROR("%s config_size mismatch.\n", __FUNCTION__);
        return false;
      }

      // ------------------------------------------------------------
      // essential config
      const int32_t* p = config_vector;
      Config::set_essential_config(p, BRIDGE_ESSENTIAL_CONFIG_INDEX__END__);
      // remapclasses config
      p += BRIDGE_ESSENTIAL_CONFIG_INDEX__END__;
      for (size_t i = 0; i < remapclasses_->size(); ++i) {
        RemapClass* rc = (*remapclasses_)[i];
        if (! rc) {
          IOLOG_ERROR("%s RemapClass == NULL.\n", __FUNCTION__);
        } else {
          rc->setEnabled(p[i]);
        }
      }

      refresh();

      return true;
    }

    void
    refresh(void)
    {
      // We use timer to prevent deadlock of lock_. (refresh may be called in the remap_key, remap_consumer, *).
      enum {
        DELAY = 1,
      };
      refresh_timer_.setTimeoutMS(DELAY);
    }

    // ----------------------------------------------------------------------
#define CALL_REMAPCLASS_FUNC(FUNC, PARAMS) {                       \
    if (enabled_remapclasses_) {                                   \
      for (size_t i = 0; i < enabled_remapclasses_->size(); ++i) { \
        RemapClass* p = (*enabled_remapclasses_)[i];               \
        if (p) p->FUNC(PARAMS);                                    \
      }                                                            \
    }                                                              \
}

    void
    remap_setkeyboardtype(KeyboardType& keyboardType)
    {
      CALL_REMAPCLASS_FUNC(remap_setkeyboardtype, keyboardType);
    }

    void
    remap_forcenumlockon(ListHookedKeyboard::Item* item)
    {
      CALL_REMAPCLASS_FUNC(remap_forcenumlockon, item);
    }

    void
    remap_key(RemapParams& remapParams)
    {
      CALL_REMAPCLASS_FUNC(remap_key, remapParams);
    }

    void
    remap_consumer(RemapConsumerParams& remapParams)
    {
      CALL_REMAPCLASS_FUNC(remap_consumer, remapParams);
    }

    void
    remap_pointing(RemapPointingParams_relative& remapParams)
    {
      CALL_REMAPCLASS_FUNC(remap_pointing, remapParams);
    }

    void
    remap_pointing_scroll(RemapPointingParams_scroll& remapParams)
    {
      CALL_REMAPCLASS_FUNC(remap_pointing_scroll, remapParams);
    }

#undef CALL_REMAPCLASS_FUNC

    bool
    remap_simultaneouskeypresses(void)
    {
      bool queue_changed = false;

      if (enabled_remapclasses_) {
        for (size_t i = 0; i < enabled_remapclasses_->size(); ++i) {
          RemapClass* p = (*enabled_remapclasses_)[i];
          if (p) {
            if (p->remap_simultaneouskeypresses()) {
              queue_changed = true;
            }
          }
        }
      }

      return queue_changed;
    }

    bool
    remap_dropkeyafterremap(const Params_KeyboardEventCallBack& params)
    {
      bool dropped = false;

      if (enabled_remapclasses_) {
        for (size_t i = 0; i < enabled_remapclasses_->size(); ++i) {
          RemapClass* p = (*enabled_remapclasses_)[i];
          if (p) {
            if (p->remap_dropkeyafterremap(params)) dropped = true;
          }
        }
      }

      return dropped;
    }

    bool
    isEventInputQueueDelayEnabled(void)
    {
      return isEventInputQueueDelayEnabled_;
    }

    bool
    isEnabled(size_t configindex)
    {
      if (! remapclasses_) return false;

      if (configindex >= remapclasses_->size()) {
        IOLOG_ERROR("RemapClass::isEnabled invalid configindex.\n");
        return false;
      }

      RemapClass* p = (*remapclasses_)[configindex];
      if (! p) return false;

      return p->enabled();
    }
  }
示例#8
0
  namespace RemapClassManager {
    IOLock* lock_ = NULL;
    TimerWrapper refresh_timer_;

    char statusmessage_[32];
    char lastmessage_[32];
    bool isEventInputQueueDelayEnabled_ = false;

    Vector_RemapClassPointer* remapclasses_ = NULL;
    Vector_RemapClassPointer* enabled_remapclasses_ = NULL;

    // ======================================================================
    static void
    refresh_core(OSObject* owner, IOTimerEventSource* sender)
    {
      IOLockWrapper::ScopedLock lk(lock_);

      if (! remapclasses_) return;

      // ----------------------------------------
      if (enabled_remapclasses_) {
        delete enabled_remapclasses_;
      }
      enabled_remapclasses_ = new Vector_RemapClassPointer();
      if (! enabled_remapclasses_) return;

      // ----------------------------------------
      KeyboardRepeat::cancel();

      statusmessage_[0] = '\0';

      isEventInputQueueDelayEnabled_ = false;

      for (size_t i = 0; i < remapclasses_->size(); ++i) {
        RemapClass* p = (*remapclasses_)[i];
        if (! p) continue;

        if (p->enabled()) {
          enabled_remapclasses_->push_back(p);

          const char* msg = p->get_statusmessage();
          if (msg) {
            strlcat(statusmessage_, msg, sizeof(statusmessage_));
            strlcat(statusmessage_, " ", sizeof(statusmessage_));
          }

          if (p->is_simultaneouskeypresses()) {
            isEventInputQueueDelayEnabled_ = true;
          }
        }
      }

      if (strcmp(statusmessage_, lastmessage_) != 0) {
        KeyRemap4MacBook_bridge::StatusMessage::Request request(KeyRemap4MacBook_bridge::StatusMessage::MESSAGETYPE_EXTRA, statusmessage_);
        KeyRemap4MacBook_client::sendmsg(KeyRemap4MacBook_bridge::REQUEST_STATUS_MESSAGE, &request, sizeof(request), NULL, 0);
        strlcpy(lastmessage_, statusmessage_, sizeof(lastmessage_));
      }
    }

    // ======================================================================

    void
    initialize(IOWorkLoop& workloop)
    {
      lock_ = IOLockWrapper::alloc();
      statusmessage_[0] = '\0';
      lastmessage_[0] = '\0';
      remapclasses_ = NULL;
      enabled_remapclasses_ = NULL;

      refresh_timer_.initialize(&workloop, NULL, refresh_core);
    }

    void
    clear_xml(void)
    {
      Handle_VK_CONFIG::clear_items();

      if (enabled_remapclasses_) {
        delete enabled_remapclasses_;
        enabled_remapclasses_ = NULL;
      }

      if (remapclasses_) {
        for (size_t i = 0; i < remapclasses_->size(); ++i) {
          RemapClass* p = (*remapclasses_)[i];
          if (p) {
            delete p;
          }
        }
        delete remapclasses_;
        remapclasses_ = NULL;
      }
    }

    void
    terminate(void)
    {
      refresh_timer_.terminate();

      clear_xml();

      IOLockWrapper::free(lock_);
    }

    bool
    reload_xml(void)
    {
      IOLockWrapper::ScopedLock lk(lock_);

      bool retval = false;
      uint32_t count = 0;
      KeyRemap4MacBook_bridge::GetConfigInfo::Reply::Item* configinfo = NULL;

      // ------------------------------------------------------------
      if (Config::do_reload_only_config != 1) {
        clear_xml();
        remapclasses_ = new Vector_RemapClassPointer();
      }

      if (! remapclasses_) {
        IOLOG_ERROR("do_reload_xml remapclasses_ == NULL.\n");
        goto finish;
      }

      // ------------------------------------------------------------
      // get count
      {
        KeyRemap4MacBook_bridge::GetConfigCount::Reply reply;
        time_t timeout_second = 3;
        int error = KeyRemap4MacBook_client::sendmsg(KeyRemap4MacBook_bridge::REQUEST_GET_CONFIG_COUNT, NULL, 0, &reply, sizeof(reply), timeout_second, 0);
        if (error) {
          IOLOG_ERROR("do_reload_xml GetConfigCount sendmsg failed. (%d)\n", error);
          goto finish;
        }
        count = reply.count;
      }

      if (count > RemapClass::MAX_CONFIG_COUNT) {
        IOLOG_ERROR("do_reload_xml too many config count. (%d)\n", count);
        goto finish;
      }

      // ------------------------------------------------------------
      // get configinfo
      configinfo = new KeyRemap4MacBook_bridge::GetConfigInfo::Reply::Item[count];
      if (! configinfo) {
        IOLOG_ERROR("do_reload_xml allocation failed.\n");
        goto finish;
      }

      {
        KeyRemap4MacBook_bridge::GetConfigInfo::Reply* reply = reinterpret_cast<KeyRemap4MacBook_bridge::GetConfigInfo::Reply*>(configinfo);
        time_t timeout_second = 3;
        int error = KeyRemap4MacBook_client::sendmsg(KeyRemap4MacBook_bridge::REQUEST_GET_CONFIG_INFO,
                                                     NULL, 0,
                                                     reply, static_cast<uint32_t>(sizeof(configinfo[0]) * count),
                                                     timeout_second, 0);
        if (error) {
          IOLOG_ERROR("do_reload_xml GetConfigInfo sendmsg failed. (%d)\n", error);
          goto finish;
        }
      }

      // ------------------------------------------------------------
      if (Config::do_reload_only_config == 1) {
        if (count != remapclasses_->size()) {
          IOLOG_ERROR("do_reload_xml count != remapclasses_->size()\n");
          goto finish;
        }

        for (uint32_t i = 0; i < count; ++i) {
          (*remapclasses_)[i]->setEnabled(configinfo[i].enabled);
        }

      } else {
        remapclasses_->reserve(count);
        RemapClass::reset_allocation_count();

        // get initialize_vector
        for (uint32_t i = 0; i < count; ++i) {
          uint32_t size = configinfo[i].initialize_vector_size;
          uint32_t* initialize_vector = NULL;

          if (size > RemapClass::MAX_INITIALIZE_VECTOR_SIZE) {
            IOLOG_ERROR("do_reload_xml too large initialize_vector. (%d)\n", size);
            goto finish;
          }

          initialize_vector = new uint32_t[size];
          {
            KeyRemap4MacBook_bridge::GetConfigInitializeVector::Request request(i);
            KeyRemap4MacBook_bridge::GetConfigInitializeVector::Reply* reply = reinterpret_cast<KeyRemap4MacBook_bridge::GetConfigInitializeVector::Reply*>(initialize_vector);
            time_t timeout_second = 3;
            int error = KeyRemap4MacBook_client::sendmsg(KeyRemap4MacBook_bridge::REQUEST_GET_CONFIG_INITIALIZE_VECTOR,
                                                         &request, sizeof(request),
                                                         reply, static_cast<uint32_t>(sizeof(initialize_vector[0]) * size),
                                                         timeout_second, 0);
            RemapClass* newp = NULL;
            if (! error) {
              newp = new RemapClass(initialize_vector, configinfo[i].enabled);
            }
            remapclasses_->push_back(newp);
          }
          delete[] initialize_vector;
        }

        RemapClass::log_allocation_count();
      }

      refresh();

      retval = true;

    finish:
      if (configinfo) {
        delete[] configinfo;
      }
      return retval;
    }

    void
    refresh(void)
    {
      // We use timer to prevent deadlock of lock_. (refresh may be called in the remap_key, remap_consumer, *).
      enum {
        DELAY = 1,
      };
      refresh_timer_.setTimeoutMS(DELAY);
    }

    // ----------------------------------------------------------------------
#define CALL_REMAPCLASS_FUNC(FUNC, PARAMS) {                       \
    IOLockWrapper::ScopedLock lk(lock_);                           \
    if (enabled_remapclasses_) {                                   \
      for (size_t i = 0; i < enabled_remapclasses_->size(); ++i) { \
        RemapClass* p = (*enabled_remapclasses_)[i];               \
        if (p) p->FUNC(PARAMS);                                    \
      }                                                            \
    }                                                              \
}

    void
    remap_setkeyboardtype(KeyboardType& keyboardType)
    {
      CALL_REMAPCLASS_FUNC(remap_setkeyboardtype, keyboardType);
    }

    void
    remap_key(RemapParams& remapParams)
    {
      CALL_REMAPCLASS_FUNC(remap_key, remapParams);
    }

    void
    remap_consumer(RemapConsumerParams& remapParams)
    {
      CALL_REMAPCLASS_FUNC(remap_consumer, remapParams);
    }

    void
    remap_pointing(RemapPointingParams_relative& remapParams)
    {
      CALL_REMAPCLASS_FUNC(remap_pointing, remapParams);
    }

#undef CALL_REMAPCLASS_FUNC

    bool
    remap_simultaneouskeypresses(void)
    {
      IOLockWrapper::ScopedLock lk(lock_);

      bool queue_changed = false;

      if (enabled_remapclasses_) {
        for (size_t i = 0; i < enabled_remapclasses_->size(); ++i) {
          RemapClass* p = (*enabled_remapclasses_)[i];
          if (p) {
            if (p->remap_simultaneouskeypresses()) {
              queue_changed = true;
            }
          }
        }
      }

      return queue_changed;
    }

    bool
    remap_dropkeyafterremap(const Params_KeyboardEventCallBack& params)
    {
      IOLockWrapper::ScopedLock lk(lock_);

      bool dropped = false;

      if (enabled_remapclasses_) {
        for (size_t i = 0; i < enabled_remapclasses_->size(); ++i) {
          RemapClass* p = (*enabled_remapclasses_)[i];
          if (p) {
            if (p->remap_dropkeyafterremap(params)) dropped = true;
          }
        }
      }

      return dropped;
    }

    bool
    isEventInputQueueDelayEnabled(void)
    {
      return isEventInputQueueDelayEnabled_;
    }

    bool
    isEnabled(size_t configindex)
    {
      // isEnabled called in remap_key, remap_consumer, ...
      // So, don't make ScopedLock(lock_).

      if (! remapclasses_) return false;

      if (configindex >= remapclasses_->size()) {
        IOLOG_ERROR("RemapClass::isEnabled invalid configindex.\n");
        return false;
      }

      RemapClass* p = (*remapclasses_)[configindex];
      if (! p) return false;

      return p->enabled();
    }
  }