Beispiel #1
0
s32 cellSysmoduleUnloadModule(u16 id)
{
	cellSysmodule.warning("cellSysmoduleUnloadModule(id=%s)", get_module_id(id));

	const auto name = get_module_name(id);

	if (!name)
	{
		cellSysmodule.error("cellSysmoduleUnloadModule() failed: unknown module 0x%04X", id);
		return CELL_SYSMODULE_ERROR_UNKNOWN;
	}

	//if (Module<>* m = Emu.GetModuleManager().GetModuleById(id))
	//{
	//	if (!m->IsLoaded())
	//	{
	//		cellSysmodule.error("cellSysmoduleUnloadModule() failed: module not loaded (id=0x%04x)", id);
	//		return CELL_SYSMODULE_ERROR_FATAL;
	//	}

	//	m->Unload();
	//}
	
	return CELL_OK;
}
Beispiel #2
0
std::string map_file(const std::string& passed_fname)
{
	if(sys::is_path_absolute(passed_fname)) {
		return passed_fname;
	}

	std::string fname = passed_fname;
	std::string module_id;
	if(std::find(fname.begin(), fname.end(), ':') != fname.end()) {
		module_id = get_module_id(fname);
		fname = get_id(fname);
	}

	foreach(const modules& p, loaded_paths()) {
		if(module_id.empty() == false && module_id != p.name_) {
			continue;
		}

		foreach(const std::string& base_path, p.base_path_) {
			const std::string path = sys::find_file(base_path + fname);
			if(sys::file_exists(path)) {
				return path;
			}
		}
	}
	return fname;
}
Beispiel #3
0
void AddinsTreeModel::name_pixbuf_cell_data_func(Gtk::CellRenderer * renderer,
        const Gtk::TreeIter & iter)
{
    Gtk::CellRendererPixbuf *icon_renderer = dynamic_cast<Gtk::CellRendererPixbuf*>(renderer);
    Glib::RefPtr<Gdk::Pixbuf> icon;
    if(get_module_id(iter) != "") {
        icon = gnote::IconManager::obj().get_icon(gnote::IconManager::EMBLEM_PACKAGE, 22);
    }
    icon_renderer->property_pixbuf() = icon;
}
/*
 * Copy argument
 */
static int
md_command_cparg(AXP *axp, uint32_t pm_type, int tag,
		 const char *buf, size_t len, tr_ctx_t *tr_ctx)
{
	struct md_command_args *arg = tr_ctx->arg;
	uint32_t mod_id;

	if (arg->already_running) {
		tr_ctx->result = 302;
		return 0;
	}

	switch (tag) {
		case ARMS_TAG_START_CPARG:
			break;
		case ARMS_TAG_END_CPARG:
			if (arg->mod_count < 1) {
				tr_ctx->result = 203;/*Parameter Problem*/
			}
			break;
		case ARMS_TAG_MDCOMMAND:
			if (tr_ctx->read_done)
				break;
			arg->mod_count++;
			if (arg->mod_count > 1) {
				tr_ctx->result = 422;/*Multiple Request*/
				return -1;
			}
			mod_id = get_module_id(axp, tag);
			arg->mod_id = mod_id;
			if (sizeof(arg->request) < len) {
				tr_ctx->result = 402;/*SA Failure*/
				return -1;
			}
			if (arms_get_encoding(axp, tag) == ARMS_DATA_BINARY) {
				/* decode base64 */
				len = arms_base64_decode_stream(&arg->base64,
							 arg->request,
							 sizeof(arg->request),
							 buf, len);
			} else {
				memcpy(arg->request, buf, len);
			}
			arg->req_len = len;
			break;
		default:
			break;
	}

	return 0;
}
Beispiel #5
0
void AddinsTreeModel::name_cell_data_func(Gtk::CellRenderer * renderer,
        const Gtk::TreeIter & iter)
{
    Gtk::CellRendererText *text_renderer = dynamic_cast<Gtk::CellRendererText*>(renderer);
    std::string value;
    iter->get_value(0, value);
    text_renderer->property_text() = value;
    const sharp::DynamicModule *module = get_module(iter);
    if(get_module_id(iter) == "" || (module && module->is_enabled())) {
        text_renderer->property_foreground() = "black";
    }
    else {
        text_renderer->property_foreground() = "grey";
    }
}
Beispiel #6
0
s32 cellSysmoduleLoadModule(u16 id)
{
	cellSysmodule.Warning("cellSysmoduleLoadModule(id=0x%04x: %s)", id, get_module_id(id));

	if (!Emu.GetModuleManager().CheckModuleId(id))
	{
		return CELL_SYSMODULE_ERROR_UNKNOWN;
	}

	if (Module<>* m = Emu.GetModuleManager().GetModuleById(id))
	{
		// CELL_SYSMODULE_ERROR_DUPLICATED shouldn't be returned
		m->Load();
	}

	return CELL_OK;
}
Beispiel #7
0
s32 cellSysmoduleLoadModule(u16 id)
{
	cellSysmodule.warning("cellSysmoduleLoadModule(id=%s)", get_module_id(id));

	const auto name = get_module_name(id);

	if (!name)
	{
		cellSysmodule.error("cellSysmoduleLoadModule() failed: unknown module 0x%04X", id);
		return CELL_SYSMODULE_ERROR_UNKNOWN;
	}

	//if (Module<>* m = Emu.GetModuleManager().GetModuleById(id))
	//{
	//	// CELL_SYSMODULE_ERROR_DUPLICATED shouldn't be returned
	//	m->Load();
	//}

	return CELL_OK;
}
Beispiel #8
0
s32 cellSysmoduleIsLoaded(u16 id)
{
	cellSysmodule.Warning("cellSysmoduleIsLoaded(id=0x%04x: %s)", id, get_module_id(id));

	if (!Emu.GetModuleManager().CheckModuleId(id))
	{
		cellSysmodule.Error("cellSysmoduleIsLoaded(): unknown module (id=0x%04x)", id);
		return CELL_SYSMODULE_ERROR_UNKNOWN;
	}

	if (Module<>* m = Emu.GetModuleManager().GetModuleById(id))
	{
		if (!m->IsLoaded())
		{
			cellSysmodule.Warning("cellSysmoduleIsLoaded(): module not loaded (id=0x%04x)", id);
			return CELL_SYSMODULE_ERROR_UNLOADED;
		}
	}

	return CELL_SYSMODULE_LOADED;
}
Beispiel #9
0
s32 cellSysmoduleUnloadModule(u16 id)
{
	cellSysmodule.Warning("cellSysmoduleUnloadModule(id=0x%04x: %s)", id, get_module_id(id));

	if (!Emu.GetModuleManager().CheckModuleId(id))
	{
		return CELL_SYSMODULE_ERROR_UNKNOWN;
	}

	if (Module<>* m = Emu.GetModuleManager().GetModuleById(id))
	{
		if (!m->IsLoaded())
		{
			cellSysmodule.Error("cellSysmoduleUnloadModule() failed: module not loaded (id=0x%04x)", id);
			return CELL_SYSMODULE_ERROR_FATAL;
		}

		m->Unload();
	}
	
	return CELL_OK;
}
Beispiel #10
0
ContextAddress get_tls_address(Context * ctx, ELF_File * file) {
    ContextAddress mod_tls_addr = 0;
    RegisterIdScope reg_id_scope;

    memset(&reg_id_scope, 0, sizeof(reg_id_scope));
    reg_id_scope.machine = file->machine;
    reg_id_scope.os_abi = file->os_abi;
    reg_id_scope.elf64 = file->elf64;
    reg_id_scope.big_endian = file->big_endian;
    reg_id_scope.id_type = REGNUM_DWARF;

    switch (file->machine) {
    case EM_X86_64:
    {
        uint8_t buf[8];
        ContextAddress tcb_addr = 0;
        ContextAddress vdt_addr = 0;
        ContextAddress mod_id = 0;
        RegisterDefinition * reg_def = get_reg_by_id(ctx, 58, &reg_id_scope);
        if (reg_def == NULL) exception(errno);
        if (context_read_reg(ctx, reg_def, 0, reg_def->size, buf) < 0)
            str_exception(errno, "Cannot read TCB base register");
        tcb_addr = to_address(buf, reg_def->size, reg_def->big_endian);
        if (elf_read_memory_word(ctx, file, tcb_addr + 8, &vdt_addr) < 0)
            str_exception(errno, "Cannot read TCB");
        mod_id = get_module_id(ctx, file);
        if (elf_read_memory_word(ctx, file, vdt_addr + mod_id * 16, &mod_tls_addr) < 0)
            str_exception(errno, "Cannot read VDT");
        if (mod_tls_addr == 0 || mod_tls_addr == ~(ContextAddress)0)
            str_exception(errno, "Thread local storage is not allocated yet");
    }
    break;
    default:
        str_fmt_exception(ERR_INV_CONTEXT,
                          "Thread local storage access is not supported yet for machine type %d",
                          file->machine);
    }
    return mod_tls_addr;
}
Beispiel #11
0
/*
 * Copy argument
 */
static int
configure_cparg(AXP *axp, uint32_t pm_type, int tag,
		const char *buf, size_t len, tr_ctx_t *tr_ctx)
{
	struct configure_args *arg = tr_ctx->arg;
	arms_context_t *res = arms_get_context();
	uint32_t mod_id;
	const char *mod_ver = NULL;
	const char *mod_loc = NULL;
	arms_config_cb_t config_cb;
	int flag, err;
	static int module_added = 0;

	if (tr_ctx->result == 302)
		return 0;

	if (arg->already_running) {
		tr_ctx->result = 302;
		return 0;
	}

	config_cb = res->callbacks.config_cb;

	switch (tag) {
	case ARMS_TAG_START_CPARG:
		module_added = 1;
		arg->first = 1;
		break;
	case ARMS_TAG_END_CPARG:
		/* call sync_module if <md-config> is not included. */
		if (module_added) {
			configure_module_cb.udata = res;
			init_module_cb(&configure_module_cb);
			err = sync_module();
			if (err < 0) {
				tr_ctx->result = 411;/*Commit failure*/
				return -1;
			}
			module_added = 0;
		}
		break;
	case ARMS_TAG_MODULE:
		mod_id = get_module_id(axp, tag);
		mod_ver = get_module_ver(axp, tag);
		/* add module id to 'new' */
		err = add_module(mod_id, mod_ver, buf);
		if (err < 0) {
			tr_ctx->result = 411;/*Commit failure*/
			return -1;
		}
		break;
	case ARMS_TAG_MDCONF:
		if (module_added) {
			/*
			 * move module id from 'new' to 'current'
			 */
			configure_module_cb.udata = res;
			init_module_cb(&configure_module_cb);
			err = sync_module();
			if (err < 0) {
				tr_ctx->result = 411;/*Commit failure*/
				return -1;
			}
			module_added = 0;
		}
		mod_id = get_module_id(axp, tag);
		if (!arms_module_is_exist(mod_id)) {
			/*
			 * <md-config> found, but <module> not found.
			 */
			tr_ctx->result = 415;/*System Error*/
			return -1;
		}
		mod_ver = lookup_module_ver(mod_id);
		mod_loc = lookup_module_location(mod_id);
		if (mod_loc == NULL)
			mod_loc = "";
		if (config_cb == NULL)
			break;
		if (arms_get_encoding(axp, tag) == ARMS_DATA_BINARY) {
			/* decode base64 */
			len = arms_base64_decode_stream(&arg->base64,
			    arg->request, sizeof(arg->request) - 1,
			    buf, len);
			arg->request[len] = '\0';
			buf = arg->request;
		}
		/*
		 * buf, len is prepared.
		 * if res->fragment == 0 and AXP_PARSE_CONTENT,
		 * buffered part of config.
		 */
		if (res->fragment == 0) {
			arg->catbuf = REALLOC(arg->catbuf, arg->catlen + len);
			if (arg->catbuf == NULL) {
				/*Resource Exhausted*/
				tr_ctx->result = 413;
				return -1;
			}
			memcpy(arg->catbuf + arg->catlen, buf, len);
			arg->catlen += len;
			if (tr_ctx->parse_state == AXP_PARSE_CONTENT) {
				/* wait for next data */
				return 0;
			}
			/* AXP_PARSE_END */
			buf = arg->catbuf;
			len = arg->catlen;
		}
		/* set fragment flag */
		flag = 0;
		if (arg->first) {
			flag |= ARMS_FRAG_FIRST;
			arg->first = 0;
		}
		/* continued' config */
		if (tr_ctx->parse_state == AXP_PARSE_CONTENT) {
			flag |= ARMS_FRAG_CONTINUE;
		}

		/* callback it */
		do {
			int slen;
			/* call config callback */
			if (res->fragment != 0 && len > res->fragment) {
				slen = res->fragment;
			} else {
				slen = len;
				/* if last fragment */
				if (tr_ctx->parse_state == AXP_PARSE_END) {
					flag |= ARMS_FRAG_FINISHED;
					/* prepare for next md-config */
					arg->first = 1;
				}
			}
			err = (*config_cb) (mod_id, mod_ver,
					    mod_loc,
					    ARMS_PUSH_STORE_CONFIG,
					    buf, slen, flag,
					    res->udata);
			if (err) {
				arg->errs++;
				tr_ctx->result = 410;
				return -1;
			}
			buf += slen;
			len -= slen;
			flag &= ~ARMS_FRAG_FIRST;
			flag |= ARMS_FRAG_CONTINUE;
		} while(len > 0);
		if (arg->catbuf != NULL) {
			/* reset for next module id */
			FREE(arg->catbuf);
			arg->catbuf = NULL;
			arg->catlen = 0;
		}
		break;
	default:
		break;
	}

	return 0;
}
Beispiel #12
0
/* AXP Extention handler */
static int
store_tag(AXP *axp, int when, int type, int tag,
		const char *buf, size_t len, void *u)
{
	/*
	 * note: max size of encoded text via expat is 64kirobyte.
	 * decoded binary size is 3/4 of encoded text.
	 * + 2: module bytes
	 */
	static char decbuf[AXP_BUFSIZE * 3 / 4 + 2 + 1];

	tr_ctx_t *tr_ctx = u;
	rspull_context_t *ctx = tr_ctx->arg;
	arms_context_t *res = arms_get_context();
	uint32_t mod_id = 0;
	const char *mod_ver = NULL;
	const char *mod_loc = NULL;
	static int module_added = 0;
	arms_config_cb_t func;
	int flag, err = 0;

	/* Emergency stop requested */
	if (tr_ctx->read_done) {
		return 0;
	}

	if ((func = res->callbacks.config_cb) == NULL) {
		return -1;
	}

	switch (tag) {
	case ARMS_TAG_MODULE:
		if (when != AXP_PARSE_END)
			return 0;
		/* chained to new module storage */
		mod_id = get_module_id(axp, ARMS_TAG_MODULE);
		mod_ver = get_module_ver(axp, ARMS_TAG_MODULE);
		err = add_module(mod_id, mod_ver, (const char *)buf);
		if (err < 0) {
			tr_ctx->res_result = 415;/*System Error*/
			tr_ctx->read_done = 1;
			err = 0; /* not parser err */
			break;
		}
		module_added = 1;
		break;
	case ARMS_TAG_MDCONF:
		if (module_added) {
			/* module db: new -> current */
			configure_module_cb.udata = res;
			init_module_cb(&configure_module_cb);
			err = sync_module();
			if (err < 0) {
				tr_ctx->res_result = 415;/*System Error*/
				tr_ctx->read_done = 1;
				break;
			}
			module_added = 0;
		}
		if (when == AXP_PARSE_START) {
			ctx->data.first_fragment = 1;
			return 0;
		}

		/* chained to md-config storage */
		mod_id = get_module_id(axp, ARMS_TAG_MDCONF);
		if (!arms_module_is_exist(mod_id)) {
			/*
			 * <md-config> found, but <module> not found.
			 */
			tr_ctx->res_result = 415;/*System Error*/
			tr_ctx->read_done = 1;
			break;
		}
		mod_ver = lookup_module_ver(mod_id);
		mod_loc = lookup_module_location(mod_id);

		if (arms_get_encoding(axp, tag) == ARMS_DATA_BINARY) {
			int newlen;
			newlen = arms_base64_decode_stream(&ctx->base64,
			    decbuf, sizeof(decbuf) - 1, buf, len);
			if (newlen < 0) {
				libarms_log(ARMS_LOG_EBASE64_DECODE,
					    "base64 decode error "
					    "srclen %d, dstlen %d",
					    len, sizeof(decbuf) - 1);
				tr_ctx->res_result = 402;/*SA Failure*/
				tr_ctx->read_done = 1;
				break;
			}
			len = newlen;
			decbuf[len] = '\0';
			buf = decbuf;
		}
		/*
		 * buf, len is prepared.
		 * if res->fragment == 0 and AXP_PARSE_CONTENT,
		 * buffered part of config.
		 */
		if (res->fragment == 0) {
			ctx->catbuf = REALLOC(ctx->catbuf, ctx->catlen + len);
			if (ctx->catbuf == NULL) {
				/*Resource Exhausted*/
				tr_ctx->result = 413;
				return -1;
			}
			memcpy(ctx->catbuf + ctx->catlen, buf, len);
			ctx->catlen += len;
			if (when == AXP_PARSE_CONTENT) {
				/* wait for next data */
				return 0;
			}
			/* AXP_PARSE_END */
			buf = ctx->catbuf;
			len = ctx->catlen;
		}
		/* CONTENT or END */
		flag = 0;
		if (ctx->data.first_fragment == 1) {
			flag |= ARMS_FRAG_FIRST;
			ctx->data.first_fragment = 0;
		}
		/* continued' config */
		if (when == AXP_PARSE_CONTENT) {
			flag |= ARMS_FRAG_CONTINUE;
		}
		/* callback it */
		do {
			int slen;
			/* call config callback */
			if (res->fragment != 0 && len > res->fragment) {
				slen = res->fragment;
			} else {
				slen = len;
				/* if last fragment */
				if (when == AXP_PARSE_END)
					flag |= ARMS_FRAG_FINISHED;
			}
			err = (*func)(mod_id,
				      mod_ver,		/* version */
				      mod_loc,		/* infostring */
				      ARMS_PULL_STORE_CONFIG,
				      buf, slen, flag, res->udata);
			if (err < 0) {
				res->trigger = "invalid config";
				tr_ctx->res_result = 415;/*System Error*/
				tr_ctx->read_done = 1;
				err = 0; /* not parser err */
				break;
			}
			buf += slen;
			len -= slen;
			flag &= ~ARMS_FRAG_FIRST;
			flag |= ARMS_FRAG_CONTINUE;
		} while(len > 0);
		if (ctx->catbuf != NULL) {
			/* reset for next module id */
			FREE(ctx->catbuf);
			ctx->catbuf = NULL;
			ctx->catlen = 0;
		}
		break;
	case ARMS_TAG_PUSH_ADDRESS:
		if (when != AXP_PARSE_END)
			return 0;
		if (ctx->pa_index < MAX_RS_INFO) {
			res->rs_push_address[ctx->pa_index++] = STRDUP(buf);
		}
		break;
	case ARMS_TAG_PULL_SERVER_URL:
		if (when != AXP_PARSE_END)
			return 0;
		if (ctx->pu_index < MAX_RS_INFO) {
			res->rs_pull_url[ctx->pu_index++] = STRDUP(buf);
		}
		break;
	case ARMS_TAG_MSG:
		if (when != AXP_PARSE_END)
			return 0;

		if (module_added) {
			/* care no <md-config> case. */
			configure_module_cb.udata = res;
			init_module_cb(&configure_module_cb);
			err = sync_module();
			if (err < 0) {
				tr_ctx->res_result = 415;/*System Error*/
				tr_ctx->read_done = 1;
				break;
			}
			module_added = 0;
		}
		if (acmi_get_num_server(res->acmi, ACMI_CONFIG_CONFSOL) == ctx->pu_index) {
			res->rs_pull_1st = acmi_get_current_server(res->acmi,
								   ACMI_CONFIG_CONFSOL);
		} else {
			res->rs_pull_1st = -1;
		}
		tr_ctx->read_done = 1;
		break;
	default:
		break;
	}

	return err;
}
uint8_t execute_pdu(pdu_type *pdu) {
	switch (pdu->opcode) {
		case OPCODE_GET_TYPE: {
			pdu->number_of_arguments = 1;
			pdu->arguments[0] = MODULE_TYPE;
			break;
		}

		case OPCODE_GET_ID: {
			pdu->number_of_arguments = 1;
			pdu->arguments[0] = get_module_id();
			break;
		}

		case OPCODE_GET_FW_VERSION: {
			pdu->number_of_arguments = 3;
			pdu->arguments[0] = FIRMWARE_MAJOR;
			pdu->arguments[1] = FIRMWARE_MINOR;
			pdu->arguments[2] = FIRMWARE_PATCHLEVEL;

			break;
		}

		case OPCODE_GET_NR_CHANNELS: {
			pdu->number_of_arguments = 1;
			pdu->arguments[0] = NUM_CHANNELS;

			break;
		}

		case OPCODE_GET_FEATURES: {
			pdu->number_of_arguments = 1;
			pdu->arguments[0] = 0;

			break;
		}

		case OPCODE_GET_SW_THRESHOLD: {
			pdu->number_of_arguments = 1;
			pdu->arguments[0] = get_switch_threshold();

			break;
		}

		case OPCODE_GET_DIMMER_THRESHOLD: {
			pdu->number_of_arguments = 1;
			pdu->arguments[0] = get_long_press_threshold();

			break;
		}


		case OPCODE_GET_DIMMER_DELAY: {
			pdu->number_of_arguments = 1;
			pdu->arguments[0] = get_dimmer_delay();

			break;
		}

		case OPCODE_GET_SW_TIMER: {
			if (pdu->number_of_arguments == 1) {
				uint8_t channel_number = pdu->arguments[0];

				if (is_valid_channel(channel_number)) {
					uint16_t channel_timer = get_switch_timer(channel_number);

					pdu->number_of_arguments = 1;
					pdu->arguments[0] = channel_timer;
				} else {
					return ERROR_INVALID_CHANNEL_NUMBER;
				}
			} else {
				return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
			}

			break;
		}

		case OPCODE_GET_CHANNEL_MAPPING: {
			if (pdu->number_of_arguments == 1) {
				uint8_t channel_number = pdu->arguments[0];

				if (is_valid_channel(channel_number)) {
					uint8_t channel_mapping = get_switch_mapping(channel_number);

					pdu->number_of_arguments = 1;
					pdu->arguments[0] = channel_mapping;
				} else {
					return ERROR_INVALID_CHANNEL_NUMBER;
				}
			} else {
				return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
			}

			break;
		}

		case OPCODE_GET_DEFAULT_STATE: {
			if (pdu->number_of_arguments == 1) {
				uint8_t channel_number = pdu->arguments[0];

				if (is_valid_channel(channel_number)) {
					uint8_t channel_state = get_default_channel_state(channel_number);

					pdu->number_of_arguments = 1;
					pdu->arguments[0] = channel_state;
				} else {
					return ERROR_INVALID_CHANNEL_NUMBER;
				}
			} else {
				return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
			}

			break;
		}

		case OPCODE_GET_DEFAULT_PERCENTAGE: {
			if (pdu->number_of_arguments == 1) {
				uint8_t channel_number = pdu->arguments[0];

				if (is_valid_channel(channel_number)) {
					uint8_t percentage = get_default_dimmer_percentage(channel_number);

					pdu->number_of_arguments = 1;
					pdu->arguments[0] = percentage;
				} else {
					return ERROR_INVALID_CHANNEL_NUMBER;
				}
			} else {
				return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
			}

			break;
		}

		case OPCODE_GET_DEFAULT_DIMMER_DIRECTION: {
			if (pdu->number_of_arguments == 1) {
				uint8_t channel_number = pdu->arguments[0];

				if (is_valid_channel(channel_number)) {
					uint8_t direction = get_default_dimmer_direction(channel_number);

					pdu->number_of_arguments = 1;
					pdu->arguments[0] = direction;
				} else {
					return ERROR_INVALID_CHANNEL_NUMBER;
				}
			} else {
				return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
			}

			break;
		}

		case OPCODE_SET_SW_THRESHOLD: {
			if (pdu->number_of_arguments == 1) {
				uint16_t threshold = pdu->arguments[0];
				set_switch_threshold(threshold);
				pdu->number_of_arguments = 0;
			} else {
				return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
			}

			break;
		}

		case OPCODE_SET_DIMMER_DELAY: {
			if (pdu->number_of_arguments == 1) {
				uint8_t delay = pdu->arguments[0];
				set_dimmer_delay(delay);
				pdu->number_of_arguments = 0;
			} else {
				return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
			}

			break;
		}

		case OPCODE_SET_DIMMER_THRESHOLD: {
			if (pdu->number_of_arguments == 1) {
				uint16_t threshold = pdu->arguments[0];
				set_long_press_threshold(threshold);
				pdu->number_of_arguments = 0;
			} else {
				return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
			}

			break;
		}

		case OPCODE_SET_SW_TIMER: {
			if (pdu->number_of_arguments == 2) {
				uint8_t channel_number = pdu->arguments[0];
				uint16_t timer = pdu->arguments[1];

				if (is_valid_channel(channel_number)) {
					set_switch_timer(channel_number, timer);
					pdu->number_of_arguments = 0;
				} else {
					return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
				}
			} else {
				return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
			}

			break;
		}

		case OPCODE_SET_CHANNEL_MAPPING: {
			if (pdu->number_of_arguments == 2) {
				uint8_t channel_number = pdu->arguments[0];
				uint8_t mapping = pdu->arguments[1];

				if (is_valid_channel(channel_number) && is_valid_channel(mapping)) {
					set_switch_mapping(channel_number, mapping);
					pdu->number_of_arguments = 0;
				} else {
					return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
				}
			} else {
				return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
			}

			break;
		}

		case OPCODE_SET_DEFAULT_STATE: {
			if (pdu->number_of_arguments == 2) {
				uint8_t channel_number = pdu->arguments[0];
				uint8_t default_state = pdu->arguments[1];

				if (is_valid_channel(channel_number)) {
					if (default_state == 0 || default_state == 1) {
						set_default_channel_state(channel_number, default_state);
						pdu->number_of_arguments = 0;
					} else {
						return ERROR_INVALID_STATE;
					}
				} else {
					return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
				}
			} else {
				return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
			}

			break;
		}

		case OPCODE_SET_DEFAULT_PERCENTAGE: {
			if (pdu->number_of_arguments == 2) {
				uint8_t channel_number = pdu->arguments[0];
				uint8_t default_percentage = pdu->arguments[1];

				if (is_valid_channel(channel_number)) {
					if (default_percentage >= 0 || default_percentage <= 100) {
						set_default_dimmer_percentage(channel_number, default_percentage);
						pdu->number_of_arguments = 0;
					} else {
						return ERROR_INVALID_PERCENTAGE;
					}
				} else {
					return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
				}
			} else {
				return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
			}

			break;
		}

		case OPCODE_SET_DEFAULT_DIMMER_DIRECTION: {
			if (pdu->number_of_arguments == 2) {
				uint8_t channel_number = pdu->arguments[0];
				uint8_t default_direction = pdu->arguments[1];

				if (is_valid_channel(channel_number)) {
					if (default_direction == 0 || default_direction == 1) {
						set_default_dimmer_direction(channel_number, default_direction);
						pdu->number_of_arguments = 0;
					} else {
						return ERROR_INVALID_STATE;
					}
				} else {
					return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
				}
			} else {
				return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
			}

			break;
		}

		case OPCODE_RELOAD_CONFIGURATION: {
			configuration_load();
			pdu->number_of_arguments = 0;

			break;
		}

		case OPCODE_SAVE_CONFIGURATION: {
			configuration_save();
			pdu->number_of_arguments = 0;

			break;
		}

		case OPCODE_GET_OUTPUT_STATE: {
			if (pdu->number_of_arguments == 1) {
				uint8_t channel_number = pdu->arguments[0];

				if (is_valid_channel(channel_number)) {
					uint8_t output_state = get_output_state(channel_number);

					pdu->number_of_arguments = 2;
					pdu->arguments[0] = output_state;
					pdu->arguments[1] = get_percentage(channel_number);
				} else {
					return ERROR_INVALID_CHANNEL_NUMBER;
				}
			} else {
				return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
			}

			break;
		}

		case OPCODE_GET_INPUT_STATE: {
			if (pdu->number_of_arguments == 1) {
				uint8_t channel_number = pdu->arguments[0];

				if (is_valid_channel(channel_number)) {
					uint8_t switch_state = get_switch_state(channel_number);

					pdu->number_of_arguments = 1;
					pdu->arguments[0] = switch_state;
				} else {
					return ERROR_INVALID_CHANNEL_NUMBER;
				}
			} else {
				return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
			}

			break;
		}

		case OPCODE_SWITCH_OUTPUT: {
			if (pdu->number_of_arguments == 2) {
				uint8_t channel_number = pdu->arguments[0];

				if (is_valid_channel(channel_number)) {
					uint8_t new_state = pdu->arguments[1];

					if (new_state == STATE_OFF || new_state == STATE_ON) {
						switch_output(channel_number, new_state);

						pdu->number_of_arguments = 0;
					} else {
						return ERROR_INVALID_STATE;
					}
				} else {
					return ERROR_INVALID_CHANNEL_NUMBER;
				}
			} else {
				return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
			}

			break;
		}

		case OPCODE_DIM: {
			if (pdu->number_of_arguments == 2) {
				uint8_t channel_number = pdu->arguments[0];

				if (is_valid_channel(channel_number)) {
					uint8_t percentage = pdu->arguments[1];

					if (percentage >= 0 || percentage <= 100) {
						dim(channel_number, percentage);

						pdu->number_of_arguments = 0;
					} else {
						return ERROR_INVALID_PERCENTAGE;
					}
				} else {
					return ERROR_INVALID_CHANNEL_NUMBER;
				}
			} else {
				return ERROR_WRONG_NUMBER_OF_ARGUMENTS;
			}

			break;
		}

		default: {
			return ERROR_INVALID_OPCODE;
		}
	}

	return 0;
}