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; }
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; }
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; }
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"; } }
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; }
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; }
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; }
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; }
ContextAddress get_tls_address(Context * ctx, ELF_File * file) { ContextAddress mod_tls_addr = 0; RegisterIdScope reg_id_scope; memset(®_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, ®_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; }
/* * 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; }
/* 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; }