static int hidpp20drv_20_probe(struct ratbag_device *device) { struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device); struct hidpp20_device *dev = drv_data->dev; struct hidpp20_feature *feature_list = dev->feature_list; unsigned int i; int rc; log_raw(device->ratbag, "'%s' has %d features\n", ratbag_device_get_name(device), dev->feature_count); for (i = 0; i < dev->feature_count; i++) { log_raw(device->ratbag, "Init feature %s (0x%04x) \n", hidpp20_feature_get_name(feature_list[i].feature), feature_list[i].feature); rc = hidpp20drv_init_feature(device, feature_list[i].feature); if (rc < 0) return rc; } return 0; }
static int print_socket_options(void) { int fd, len; SOCK_OPT *ptr; OPT_UNION val; char line[STRLEN]; fd=socket(AF_INET, SOCK_STREAM, 0); log_raw("Socket option defaults:"); log_raw(" %-16s%-10s%-10s%-10s%-10s", "Option", "Accept", "Local", "Remote", "OS default"); for(ptr=sock_opts; ptr->opt_str; ptr++) { /* display option name */ sprintf(line, " %-16s", ptr->opt_str); /* display stunnel default values */ print_option(line, ptr->opt_type, ptr->opt_val[0]); print_option(line, ptr->opt_type, ptr->opt_val[1]); print_option(line, ptr->opt_type, ptr->opt_val[2]); /* display OS default value */ len = sizeof(val); if(getsockopt(fd, ptr->opt_level, ptr->opt_name, (void *)&val, &len)) { if(get_last_socket_error()!=ENOPROTOOPT) { log_raw("%s", line); /* dump the name and assigned values */ sockerror("getsockopt"); return 0; /* FAILED */ } safeconcat(line, " -- "); /* write-only value */ } else print_option(line, ptr->opt_type, &val); log_raw("%s", line); } return 1; /* OK */ }
int hidpp10_get_firmare_information(struct hidpp10_device *dev, uint8_t *major_out, uint8_t *minor_out, uint8_t *build_out) { unsigned idx = dev->index; union hidpp10_message firmware_information = CMD_DEVICE_FIRMWARE_INFORMATION(idx, FIRMWARE_INFO_ITEM_FW_NAME_AND_VERSION(1)); union hidpp10_message build_information = CMD_DEVICE_FIRMWARE_INFORMATION(idx, FIRMWARE_INFO_ITEM_FW_BUILD_NUMBER(1)); int res; uint8_t maj, min, build; log_raw(dev->ratbag_device->ratbag, "Fetching firmware information\n"); /* * This may fail on some devices * => we can not retrieve their FW version through HID++ 1.0. */ res = hidpp10_request_command(dev, &firmware_information); if (res) return res; maj = firmware_information.msg.string[1]; min = firmware_information.msg.string[2]; res = hidpp10_request_command(dev, &build_information); if (res) return res; build = hidpp10_get_unaligned_u16(&build_information.msg.string[1]); *major_out = maj; *minor_out = min; *build_out = build; return 0; }
static void hidpp20drv_read_button_1b04(struct ratbag_button *button) { struct ratbag_device *device = button->profile->device; struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device); struct hidpp20_control_id *control; const struct ratbag_button_action *action; uint16_t mapping; if (!(drv_data->capabilities & HIDPP_CAP_BUTTON_KEY_1b04)) return; control = &drv_data->controls[button->index]; mapping = control->control_id; if (control->reporting.divert || control->reporting.persist) mapping = control->reporting.remapped; log_raw(device->ratbag, " - button%d: %s (%02x) %s%s:%d\n", button->index, hidpp20_1b04_get_logical_mapping_name(mapping), mapping, control->reporting.divert || control->reporting.persist ? "(redirected) " : "", __FILE__, __LINE__); button->type = hidpp20_1b04_get_physical_mapping(control->task_id); action = hidpp20_1b04_get_logical_mapping(mapping); if (action) button->action = *action; ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_BUTTON); ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_KEY); ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_SPECIAL); }
/* s_log is not initialized here, but we can use log_raw */ void sthreads_init(void) { /* create the first (listening) context and put it in the running queue */ if(!new_context()) { log_raw("Unable create the listening context"); exit(1); } }
static void log_buffer_notrunc(const uint8_t *buf, uintptr_t length) { if(buf == NULL || length == 0) { return; } bson b; bson_init(&b); bson_append_string(&b, "type", "buffer"); if(range_is_readable(buf, length) != 0) { bson_append_binary(&b, "buffer", BSON_BIN_BINARY, (const char *) buf, length); char checksum[64]; sha1(buf, length, checksum); bson_append_string(&b, "checksum", checksum); } else { bson_append_string(&b, "buffer", "<INVALID POINTER>"); bson_append_string(&b, "checksum", "???"); } bson_finish(&b); log_raw(bson_data(&b), bson_size(&b)); bson_destroy(&b); }
static char *stralloc(char *str) { /* Allocate static string */ char *retval; retval=calloc(strlen(str)+1, 1); if(!retval) { log_raw("Fatal memory allocation error"); exit(2); } strcpy(retval, str); return retval; }
int hidpp10_get_usb_refresh_rate(struct hidpp10_device *dev, uint16_t *rate) { unsigned idx = dev->index; union hidpp10_message refresh = CMD_USB_REFRESH_RATE(idx, GET_REGISTER_REQ); int res; log_raw(dev->ratbag_device->ratbag, "Fetching USB refresh rate\n"); res = hidpp10_request_command(dev, &refresh); if (res) return res; *rate = 1000/refresh.msg.parameters[0]; return 0; }
int hidpp10_set_hidpp_notifications(struct hidpp10_device *dev, uint8_t reporting_flags_r0, uint8_t reporting_flags_r2) { unsigned idx = dev->index; union hidpp10_message notifications = CMD_HIDPP_NOTIFICATIONS(idx, SET_REGISTER_REQ); int res; log_raw(dev->ratbag_device->ratbag, "Setting HID++ notifications\n"); notifications.msg.parameters[0] = reporting_flags_r0; notifications.msg.parameters[2] = reporting_flags_r2; res = hidpp10_request_command(dev, ¬ifications); return res; }
int hidpp10_get_pairing_information_device_name(struct hidpp10_device *dev, char *name, size_t *name_size) { unsigned int idx = dev->index; union hidpp10_message device_name = CMD_PAIRING_INFORMATION(idx, DEVICE_NAME); int res; log_raw(dev->ratbag_device->ratbag, "Fetching device name\n"); res = hidpp10_request_command(dev, &device_name); if (res) return -1; *name_size = min(*name_size, device_name.msg.string[1]); strncpy_safe(name, (char*)&device_name.msg.string[2], *name_size); return 0; }
int hidpp10_set_led_status(struct hidpp10_device *dev, const bool led[4]) { unsigned idx = dev->index; union hidpp10_message led_status = CMD_LED_STATUS(idx, SET_REGISTER_REQ); int res; log_raw(dev->ratbag_device->ratbag, "Setting LED status\n"); /* each led is 4-bits, 0x1 == off, 0x2 == on */ led_status.msg.parameters[0] |= led[0] ? 0x02 : 0x01; /* running man logo */ led_status.msg.parameters[0] |= led[1] ? 0x20 : 0x10; /* lowest */ led_status.msg.parameters[1] |= led[2] ? 0x02 : 0x01; /* middle */ led_status.msg.parameters[1] |= led[3] ? 0x20 : 0x10; /* highest */ res = hidpp10_request_command(dev, &led_status); return res; }
int hidpp10_get_individual_features(struct hidpp10_device *dev, uint8_t *feature_bit_r0, uint8_t *feature_bit_r2) { unsigned idx = dev->index; union hidpp10_message features = CMD_ENABLE_INDIVIDUAL_FEATURES(idx, GET_REGISTER_REQ); int res; log_raw(dev->ratbag_device->ratbag, "Fetching individual features\n"); res = hidpp10_request_command(dev, &features); if (res) return res; *feature_bit_r0 = features.msg.parameters[0]; *feature_bit_r2 = features.msg.parameters[2]; return 0; }
int hidpp10_get_optical_sensor_settings(struct hidpp10_device *dev, uint8_t *surface_reflectivity) { unsigned idx = dev->index; union hidpp10_message sensor = CMD_OPTICAL_SENSOR_SETTINGS(idx, GET_REGISTER_REQ); int res; log_raw(dev->ratbag_device->ratbag, "Fetching optical sensor settings\n"); res = hidpp10_request_command(dev, &sensor); if (res) return res; *surface_reflectivity = sensor.msg.parameters[0]; /* Don't know what the other values are */ return 0; }
static int hidpp10_read_memory(struct hidpp10_device *dev, uint8_t page, uint16_t offset, uint8_t bytes[16]) { unsigned idx = dev->index; union hidpp10_message readmem = CMD_READ_MEMORY(idx, page, offset/2); int res; log_raw(dev->ratbag_device->ratbag, "Reading memory page %d, offset %#x\n", page, offset); res = hidpp10_request_command(dev, &readmem); if (res) return res; memcpy(bytes, readmem.msg.string, sizeof(readmem.msg.string)); return 0; }
int hidpp10_set_individual_feature(struct hidpp10_device *dev, uint8_t feature_bit_r0, uint8_t feature_bit_r2) { unsigned idx = RECEIVER_IDX; union hidpp10_message mode = CMD_ENABLE_INDIVIDUAL_FEATURES(idx, SET_REGISTER_REQ); int res; log_raw(dev->ratbag_device->ratbag, "Setting individual features\n"); if (dev) mode.msg.device_idx = dev->index; mode.msg.parameters[0] = feature_bit_r0; mode.msg.parameters[1] = feature_bit_r2; res = hidpp10_request_command(dev, &mode); return res; }
int hidpp10_get_current_resolution(struct hidpp10_device *dev, uint16_t *xres, uint16_t *yres) { unsigned idx = dev->index; union hidpp10_message resolution = CMD_CURRENT_RESOLUTION(idx, GET_LONG_REGISTER_REQ); int res; log_raw(dev->ratbag_device->ratbag, "Fetching current resolution\n"); res = hidpp10_request_command(dev, &resolution); if (res) return res; /* resolution is in 50dpi multiples */ *xres = hidpp10_get_unaligned_u16le(&resolution.data[4]) * 50; *yres = hidpp10_get_unaligned_u16le(&resolution.data[6]) * 50; return 0; }
static int open_handles() { do { // TODO Use NtCreateFile instead of CreateFileW. g_log_handle = CreateFileW(g_log_pipename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL); sleep(50); } while (g_log_handle == INVALID_HANDLE_VALUE); // The process identifier. uint32_t process_identifier = get_current_process_id(); log_raw((const char *) &process_identifier, sizeof(process_identifier)); #if DEBUG g_debug_handle = CreateFileW(g_debug_filepath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); #endif return 0; }
int hidpp10_get_pairing_information(struct hidpp10_device *dev, uint8_t *report_interval, uint16_t *wpid, uint8_t *device_type) { unsigned int idx = dev->index; union hidpp10_message pairing_information = CMD_PAIRING_INFORMATION(idx, DEVICE_PAIRING_INFORMATION); int res; log_raw(dev->ratbag_device->ratbag, "Fetching pairing information\n"); res = hidpp10_request_command(dev, &pairing_information); if (res) return -1; *report_interval = pairing_information.msg.string[2]; *wpid = hidpp10_get_unaligned_u16(&pairing_information.msg.string[3]); *device_type = pairing_information.msg.string[7]; return 0; }
int hidpp10_get_led_status(struct hidpp10_device *dev, bool led[4]) { unsigned idx = dev->index; union hidpp10_message led_status = CMD_LED_STATUS(idx, GET_REGISTER_REQ); int res; log_raw(dev->ratbag_device->ratbag, "Fetching LED status\n"); res = hidpp10_request_command(dev, &led_status); if (res) return res; /* each led is 4-bits, 0x1 == off, 0x2 == on */ led[0] = !!(led_status.msg.parameters[0] & 0x02); /* running man logo */ led[1] = !!(led_status.msg.parameters[0] & 0x20); /* lowest */ led[2] = !!(led_status.msg.parameters[1] & 0x02); /* middle */ led[3] = !!(led_status.msg.parameters[1] & 0x20); /* highest */ return 0; }
void log_flush(LOG_MODE new_mode) { struct LIST *tmp; CRYPTO_THREAD_write_lock(stunnel_locks[LOCK_LOG_MODE]); /* prevent changing LOG_MODE_CONFIGURED to LOG_MODE_ERROR * once stderr file descriptor is closed */ if(log_mode!=LOG_MODE_CONFIGURED) log_mode=new_mode; /* log_raw() will use the new value of log_mode */ CRYPTO_THREAD_write_lock(stunnel_locks[LOCK_LOG_BUFFER]); while(head) { log_raw(head->opt, head->level, head->stamp, head->id, head->text); str_free(head->stamp); str_free(head->id); str_free(head->text); tmp=head; head=head->next; str_free(tmp); } head=tail=NULL; CRYPTO_THREAD_write_unlock(stunnel_locks[LOCK_LOG_BUFFER]); CRYPTO_THREAD_write_unlock(stunnel_locks[LOCK_LOG_MODE]); }
int hidpp10_get_current_profile(struct hidpp10_device *dev, int8_t *current_profile) { unsigned idx = dev->index; union hidpp10_message profile = CMD_PROFILE(idx, GET_REGISTER_REQ); int res; int8_t page; log_raw(dev->ratbag_device->ratbag, "Fetching current profile\n"); res = hidpp10_request_command(dev, &profile); if (res) return res; page = profile.msg.parameters[0]; /* FIXME: my mouse is always 0 */ *current_profile = page; /* FIXME: my mouse appears to be on page 5, but with the offset of * 3, it's actually profile 2. not sure how to change this */ *current_profile = 2; return 0; }
void parse_config(char *name, char *parameter) { #ifdef CONFDIR char *default_config_file=CONFDIR "/stunnel.conf"; #else char *default_config_file="stunnel.conf"; #endif FILE *fp; char line[STRLEN], *arg, *opt, *errstr, *filename; int line_number, i; LOCAL_OPTIONS *section, *new_section; memset(&options, 0, sizeof(GLOBAL_OPTIONS)); /* reset global options */ memset(&local_options, 0, sizeof(LOCAL_OPTIONS)); /* reset local options */ local_options.next=NULL; section=&local_options; global_options(CMD_INIT, NULL, NULL); service_options(CMD_INIT, section, NULL, NULL); if(!name) name=default_config_file; if(!strcasecmp(name, "-help")) { global_options(CMD_HELP, NULL, NULL); service_options(CMD_HELP, section, NULL, NULL); exit(1); } if(!strcasecmp(name, "-version")) { log_raw("%s", stunnel_info()); log_raw(" "); global_options(CMD_DEFAULT, NULL, NULL); service_options(CMD_DEFAULT, section, NULL, NULL); exit(1); } if(!strcasecmp(name, "-sockets")) { print_socket_options(); exit(1); } #ifndef USE_WIN32 if(!strcasecmp(name, "-fd")) { if(!parameter) { log_raw("No file descriptor specified"); syntax(default_config_file); } for(arg=parameter, i=0; *arg; arg++) { if(*arg<'0' || *arg>'9') { log_raw("Invalid file descriptor %s", parameter); syntax(default_config_file); } i=10*i+*arg-'0'; } fp=fdopen(i, "r"); if(!fp) { log_raw("Invalid file descriptor %s", parameter); syntax(default_config_file); } filename="descriptor"; } else #endif { fp=fopen(name, "r"); if(!fp) { #ifdef USE_WIN32 /* Win32 doesn't seem to set errno in fopen() */ log_raw("Failed to open configuration file %s", name); #else ioerror(name); #endif syntax(default_config_file); } filename=name; } line_number=0; while(fgets(line, STRLEN, fp)) { line_number++; opt=line; while(isspace(*opt)) opt++; /* remove initial whitespaces */ for(i=strlen(opt)-1; i>=0 && isspace(opt[i]); i--) opt[i]='\0'; /* remove trailing whitespaces */ if(opt[0]=='\0' || opt[0]=='#') /* empty line or comment */ continue; if(opt[0]=='[' && opt[strlen(opt)-1]==']') { /* new section */ errstr=section_validate(section); if(errstr) { log_raw("file %s line %d: %s", filename, line_number, errstr); exit(1); } opt++; opt[strlen(opt)-1]='\0'; new_section=calloc(1, sizeof(LOCAL_OPTIONS)); if(!new_section) { log_raw("Fatal memory allocation error"); exit(2); } memcpy(new_section, &local_options, sizeof(LOCAL_OPTIONS)); new_section->servname=stralloc(opt); new_section->next=NULL; section->next=new_section; section=new_section; continue; } arg=strchr(line, '='); if(!arg) { log_raw("file %s line %d: No '=' found", filename, line_number); exit(1); } *arg++='\0'; /* split into option name and argument value */ for(i=strlen(opt)-1; i>=0 && isspace(opt[i]); i--) opt[i]='\0'; /* remove trailing whitespaces */ while(isspace(*arg)) arg++; /* remove initial whitespaces */ errstr=service_options(CMD_EXEC, section, opt, arg); if(section==&local_options && errstr==option_not_found) errstr=global_options(CMD_EXEC, opt, arg); if(errstr) { log_raw("file %s line %d: %s", filename, line_number, errstr); exit(1); } } errstr=section_validate(section); if(errstr) { log_raw("file %s line %d: %s", filename, line_number, errstr); exit(1); } fclose(fp); if(!local_options.next && section->option.accept) { log_raw("accept option is not allowed in inetd mode"); log_raw("remove accept option or define a [section]"); exit(1); } if(!options.option.client) options.option.cert=1; /* Server always needs a certificate */ if(!options.option.foreground) options.option.syslog=1; }
void log_explain(uint32_t index) { bson b; char argidx[4]; bson_init_size(&b, mem_suggested_size(1024)); bson_append_int(&b, "I", index); bson_append_string(&b, "name", sig_apiname(index)); bson_append_string(&b, "type", "info"); bson_append_string(&b, "category", sig_category(index)); bson_append_start_array(&b, "args"); bson_append_string(&b, "0", "is_success"); bson_append_string(&b, "1", "retval"); const char *fmt = sig_paramtypes(index); for (uint32_t argnum = 2; *fmt != 0; argnum++, fmt++) { ultostr(argnum, argidx, 10); // Ignore buffers, they are sent over separately. if(*fmt == '!') { argnum--; fmt++; continue; } const char *argname = sig_param_name(index, argnum-2); // On certain formats, we need to tell cuckoo about them for // nicer display / matching. if(*fmt == 'p' || *fmt == 'P') { bson_append_start_array(&b, argidx); bson_append_string(&b, "0", argname); bson_append_string(&b, "1", "p"); bson_append_finish_array(&b); } else { bson_append_string(&b, argidx, argname); } } bson_append_finish_array(&b); bson_append_start_object(&b, "flags_value"); for (uint32_t idx = 0; sig_flag_name(index, idx) != NULL; idx++) { const flag_repr_t *f = flag_value(sig_flag_value(index, idx)); bson_append_start_array(&b, sig_flag_name(index, idx)); for (uint32_t idx2 = 0; f->repr != NULL; idx2++, f++) { ultostr(idx, argidx, 10); bson_append_start_array(&b, argidx); bson_append_int(&b, "0", f->value); bson_append_string(&b, "1", f->repr); bson_append_finish_array(&b); } bson_append_finish_array(&b); } bson_append_finish_object(&b); bson_append_start_object(&b, "flags_bitmask"); for (uint32_t idx = 0; sig_flag_name(index, idx) != NULL; idx++) { const flag_repr_t *f = flag_bitmask(sig_flag_value(index, idx)); bson_append_start_array(&b, sig_flag_name(index, idx)); for (uint32_t idx2 = 0; f->repr != NULL; idx2++, f++) { ultostr(idx, argidx, 10); bson_append_start_array(&b, argidx); bson_append_int(&b, "0", f->value); bson_append_string(&b, "1", f->repr); bson_append_finish_array(&b); } bson_append_finish_array(&b); } bson_append_finish_object(&b); bson_finish(&b); log_raw(bson_data(&b), bson_size(&b)); bson_destroy(&b); }
static char *global_options(CMD cmd, char *opt, char *arg) { if(cmd==CMD_DEFAULT || cmd==CMD_HELP) { log_raw("Global options"); } /* CApath */ switch(cmd) { case CMD_INIT: #if 0 options.ca_dir=(char *)X509_get_default_cert_dir(); #endif options.ca_dir=NULL; break; case CMD_EXEC: if(strcasecmp(opt, "CApath")) break; if(arg[0]) /* not empty */ options.ca_dir=stralloc(arg); else options.ca_dir=NULL; return NULL; /* OK */ case CMD_DEFAULT: #if 0 log_raw("%-15s = %s", "CApath", options.ca_dir ? options.ca_dir : "(none)"); #endif break; case CMD_HELP: log_raw("%-15s = CA certificate directory for 'verify' option", "CApath"); break; } /* CAfile */ switch(cmd) { case CMD_INIT: #if 0 options.ca_file=(char *)X509_get_default_certfile(); #endif options.ca_file=NULL; break; case CMD_EXEC: if(strcasecmp(opt, "CAfile")) break; if(arg[0]) /* not empty */ options.ca_file=stralloc(arg); else options.ca_file=NULL; return NULL; /* OK */ case CMD_DEFAULT: #if 0 log_raw("%-15s = %s", "CAfile", options.ca_file ? options.ca_file : "(none)"); #endif break; case CMD_HELP: log_raw("%-15s = CA certificate file for 'verify' option", "CAfile"); break; } /* cert */ switch(cmd) { case CMD_INIT: #ifdef CONFDIR options.cert=CONFDIR "/stunnel.pem"; #else options.cert="stunnel.pem"; #endif break; case CMD_EXEC: if(strcasecmp(opt, "cert")) break; options.cert=stralloc(arg); options.option.cert=1; return NULL; /* OK */ case CMD_DEFAULT: log_raw("%-15s = %s", "cert", options.cert); break; case CMD_HELP: log_raw("%-15s = certificate chain", "cert"); break; } /* chroot */ #ifdef HAVE_CHROOT switch(cmd) { case CMD_INIT: options.chroot_dir=NULL; break; case CMD_EXEC: if(strcasecmp(opt, "chroot")) break; options.chroot_dir=stralloc(arg); return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = directory to chroot stunnel process", "chroot"); break; } #endif /* HAVE_CHROOT */ /* ciphers */ switch(cmd) { case CMD_INIT: options.cipher_list=SSL_DEFAULT_CIPHER_LIST; break; case CMD_EXEC: if(strcasecmp(opt, "ciphers")) break; options.cipher_list=stralloc(arg); return NULL; /* OK */ case CMD_DEFAULT: log_raw("%-15s = %s", "ciphers", SSL_DEFAULT_CIPHER_LIST); break; case CMD_HELP: log_raw("%-15s = list of permitted SSL ciphers", "ciphers"); break; } /* client */ switch(cmd) { case CMD_INIT: options.option.client=0; break; case CMD_EXEC: if(strcasecmp(opt, "client")) break; if(!strcasecmp(arg, "yes")) options.option.client=1; else if(!strcasecmp(arg, "no")) options.option.client=0; else return "argument should be either 'yes' or 'no'"; return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = yes|no client mode (remote service uses SSL)", "client"); break; } /* CRLpath */ switch(cmd) { case CMD_INIT: options.crl_dir=NULL; break; case CMD_EXEC: if(strcasecmp(opt, "CRLpath")) break; if(arg[0]) /* not empty */ options.crl_dir=stralloc(arg); else options.crl_dir=NULL; return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = CRL directory", "CRLpath"); break; } /* CRLfile */ switch(cmd) { case CMD_INIT: options.crl_file=NULL; break; case CMD_EXEC: if(strcasecmp(opt, "CRLfile")) break; if(arg[0]) /* not empty */ options.crl_file=stralloc(arg); else options.crl_file=NULL; return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = CRL file", "CRLfile"); break; } /* debug */ switch(cmd) { case CMD_INIT: options.debug_level=5; #if !defined (USE_WIN32) && !defined (__vms) options.facility=LOG_DAEMON; #endif break; case CMD_EXEC: if(strcasecmp(opt, "debug")) break; if(!parse_debug_level(arg)) return "Illegal debug argument"; return NULL; /* OK */ case CMD_DEFAULT: log_raw("%-15s = %d", "debug", options.debug_level); break; case CMD_HELP: log_raw("%-15s = [facility].level (e.g. daemon.info)", "debug"); break; } /* EGD is only supported when compiled with OpenSSL 0.9.5a or later */ #if SSLEAY_VERSION_NUMBER >= 0x0090581fL switch(cmd) { case CMD_INIT: options.egd_sock=NULL; break; case CMD_EXEC: if(strcasecmp(opt, "EGD")) break; options.egd_sock=stralloc(arg); return NULL; /* OK */ case CMD_DEFAULT: #ifdef EGD_SOCKET log_raw("%-15s = %s", "EGD", EGD_SOCKET); #endif break; case CMD_HELP: log_raw("%-15s = path to Entropy Gathering Daemon socket", "EGD"); break; } #endif /* OpenSSL 0.9.5a */ /* foreground */ #ifndef USE_WIN32 switch(cmd) { case CMD_INIT: options.option.syslog=0; options.option.foreground=0; break; case CMD_EXEC: if(strcasecmp(opt, "foreground")) break; if(!strcasecmp(arg, "yes")) options.option.foreground=1; else if(!strcasecmp(arg, "no")) options.option.foreground=0; else return "argument should be either 'yes' or 'no'"; return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = yes|no foreground mode (don't fork, log to stderr)", "foreground"); break; } #endif /* key */ switch(cmd) { case CMD_INIT: options.key=NULL; break; case CMD_EXEC: if(strcasecmp(opt, "key")) break; options.key=stralloc(arg); return NULL; /* OK */ case CMD_DEFAULT: log_raw("%-15s = %s", "key", options.cert); /* set in stunnel.c */ break; case CMD_HELP: log_raw("%-15s = certificate private key", "key"); break; } /* options */ switch(cmd) { case CMD_INIT: options.ssl_options=0; break; case CMD_EXEC: if(strcasecmp(opt, "options")) break; if(!parse_ssl_option(arg)) return "Illegal SSL option"; return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = SSL option", "options"); log_raw("%18sset an SSL option", ""); break; } /* output */ switch(cmd) { case CMD_INIT: options.output_file=NULL; break; case CMD_EXEC: if(strcasecmp(opt, "output")) break; options.output_file=stralloc(arg); return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = file to append log messages", "output"); break; } /* pid */ #ifndef USE_WIN32 switch(cmd) { case CMD_INIT: options.pidfile=PIDFILE; break; case CMD_EXEC: if(strcasecmp(opt, "pid")) break; if(arg[0]) /* is argument not empty? */ options.pidfile=stralloc(arg); else options.pidfile=NULL; /* empty -> do not create a pid file */ return NULL; /* OK */ case CMD_DEFAULT: log_raw("%-15s = %s", "pid", PIDFILE); break; case CMD_HELP: log_raw("%-15s = pid file (empty to disable creating)", "pid"); break; } #endif /* RNDbytes */ switch(cmd) { case CMD_INIT: options.random_bytes=RANDOM_BYTES; break; case CMD_EXEC: if(strcasecmp(opt, "RNDbytes")) break; options.random_bytes=atoi(arg); return NULL; /* OK */ case CMD_DEFAULT: log_raw("%-15s = %d", "RNDbytes", RANDOM_BYTES); break; case CMD_HELP: log_raw("%-15s = bytes to read from random seed files", "RNDbytes"); break; } /* RNDfile */ switch(cmd) { case CMD_INIT: options.rand_file=NULL; break; case CMD_EXEC: if(strcasecmp(opt, "RNDfile")) break; options.rand_file=stralloc(arg); return NULL; /* OK */ case CMD_DEFAULT: #ifdef RANDOM_FILE log_raw("%-15s = %s", "RNDfile", RANDOM_FILE); #endif break; case CMD_HELP: log_raw("%-15s = path to file with random seed data", "RNDfile"); break; } /* RNDoverwrite */ switch(cmd) { case CMD_INIT: options.option.rand_write=1; break; case CMD_EXEC: if(strcasecmp(opt, "RNDoverwrite")) break; if(!strcasecmp(arg, "yes")) options.option.rand_write=1; else if(!strcasecmp(arg, "no")) options.option.rand_write=0; else return "argument should be either 'yes' or 'no'"; return NULL; /* OK */ case CMD_DEFAULT: log_raw("%-15s = yes", "RNDoverwrite"); break; case CMD_HELP: log_raw("%-15s = yes|no overwrite seed datafiles with new random data", "RNDoverwrite"); break; } /* service */ switch(cmd) { case CMD_INIT: local_options.servname=stralloc("stunnel"); #ifdef USE_WIN32 options.win32_service="stunnel"; options.win32_name="stunnel " VERSION " on Win32"; #endif break; case CMD_EXEC: if(strcasecmp(opt, "service")) break; local_options.servname=stralloc(arg); #ifdef USE_WIN32 options.win32_service=stralloc(arg); { char tmpstr[STRLEN]; safecopy(tmpstr, "stunnel " VERSION " on Win32 ("); safeconcat(tmpstr, arg); safeconcat(tmpstr, ")"); options.win32_name=stralloc(tmpstr); } #endif return NULL; /* OK */ case CMD_DEFAULT: #ifdef USE_WIN32 log_raw("%-15s = %s", "service", options.win32_service); #endif break; case CMD_HELP: log_raw("%-15s = service name", "service"); break; } /* session */ switch(cmd) { case CMD_INIT: options.session_timeout=300; break; case CMD_EXEC: if(strcasecmp(opt, "session")) break; if(atoi(arg)>0) options.session_timeout=atoi(arg); else return "Illegal session timeout"; return NULL; /* OK */ case CMD_DEFAULT: log_raw("%-15s = %ld seconds", "session", options.session_timeout); break; case CMD_HELP: log_raw("%-15s = session cache timeout (in seconds)", "session"); break; } #ifndef USE_WIN32 /* setgid */ switch(cmd) { case CMD_INIT: options.setgid_group=NULL; break; case CMD_EXEC: if(strcasecmp(opt, "setgid")) break; options.setgid_group=stralloc(arg); return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = groupname for setgid()", "setgid"); break; } #endif #ifndef USE_WIN32 /* setuid */ switch(cmd) { case CMD_INIT: options.setuid_user=NULL; break; case CMD_EXEC: if(strcasecmp(opt, "setuid")) break; options.setuid_user=stralloc(arg); return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = username for setuid()", "setuid"); break; } #endif /* socket */ switch(cmd) { case CMD_INIT: break; case CMD_EXEC: if(strcasecmp(opt, "socket")) break; if(!parse_socket_option(arg)) return "Illegal socket option"; return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = a|l|r:option=value[:value]", "socket"); log_raw("%18sset an option on accept/local/remote socket", ""); break; } /* taskbar */ #ifdef USE_WIN32 switch(cmd) { case CMD_INIT: options.option.taskbar=1; break; case CMD_EXEC: if(strcasecmp(opt, "taskbar")) break; if(!strcasecmp(arg, "yes")) options.option.taskbar=1; else if(!strcasecmp(arg, "no")) options.option.taskbar=0; else return "argument should be either 'yes' or 'no'"; return NULL; /* OK */ case CMD_DEFAULT: log_raw("%-15s = yes", "taskbar"); break; case CMD_HELP: log_raw("%-15s = yes|no enable the taskbar icon", "taskbar"); break; } #endif /* verify */ switch(cmd) { case CMD_INIT: options.verify_level=-1; options.verify_use_only_my=0; break; case CMD_EXEC: if(strcasecmp(opt, "verify")) break; options.verify_level=SSL_VERIFY_NONE; switch(atoi(arg)) { case 3: options.verify_use_only_my=1; case 2: options.verify_level|=SSL_VERIFY_FAIL_IF_NO_PEER_CERT; case 1: options.verify_level|=SSL_VERIFY_PEER; case 0: return NULL; /* OK */ default: return "Bad verify level"; } case CMD_DEFAULT: log_raw("%-15s = none", "verify"); break; case CMD_HELP: log_raw("%-15s = level of peer certificate verification", "verify"); log_raw("%18slevel 1 - verify peer certificate if present", ""); log_raw("%18slevel 2 - require valid peer certificate always", ""); log_raw("%18slevel 3 - verify peer with locally installed certificate", ""); break; } if(cmd==CMD_EXEC) return option_not_found; return NULL; /* OK */ }
static int hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature) { struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device); struct ratbag *ratbag = device->ratbag; int rc; uint8_t feature_index, feature_type, feature_version; rc = hidpp_root_get_feature(drv_data->dev, feature, &feature_index, &feature_type, &feature_version); switch (feature) { case HIDPP_PAGE_ROOT: case HIDPP_PAGE_FEATURE_SET: /* these features are mandatory and already handled */ break; case HIDPP_PAGE_MOUSE_POINTER_BASIC: { drv_data->capabilities |= HIDPP_CAP_RESOLUTION_2200; break; } case HIDPP_PAGE_ADJUSTABLE_DPI: { log_debug(ratbag, "device has adjustable dpi\n"); /* we read the profile once to get the correct number of * supported resolutions. */ rc = hidpp20drv_read_resolution_dpi_2201(device); if (rc < 0) return 0; /* this is not a hard failure */ ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_SWITCHABLE_RESOLUTION); drv_data->capabilities |= HIDPP_CAP_SWITCHABLE_RESOLUTION_2201; break; } case HIDPP_PAGE_SPECIAL_KEYS_BUTTONS: { log_debug(ratbag, "device has programmable keys/buttons\n"); drv_data->capabilities |= HIDPP_CAP_BUTTON_KEY_1b04; ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_KEY); /* we read the profile once to get the correct number of * supported buttons. */ if (!hidpp20drv_read_special_key_mouse(device)) device->num_buttons = drv_data->num_controls; break; } case HIDPP_PAGE_BATTERY_LEVEL_STATUS: { uint16_t level, next_level; enum hidpp20_battery_status status; rc = hidpp20_batterylevel_get_battery_level(drv_data->dev, &level, &next_level); if (rc < 0) return rc; status = rc; log_debug(ratbag, "device battery level is %d%% (next %d%%), status %d \n", level, next_level, status); drv_data->capabilities |= HIDPP_CAP_BATTERY_LEVEL_1000; break; } case HIDPP_PAGE_KBD_REPROGRAMMABLE_KEYS: { log_debug(ratbag, "device has programmable keys/buttons\n"); drv_data->capabilities |= HIDPP_CAP_KBD_REPROGRAMMABLE_KEYS_1b00; /* we read the profile once to get the correct number of * supported buttons. */ if (!hidpp20drv_read_kbd_reprogrammable_key(device)) device->num_buttons = drv_data->num_controls; break; } case HIDPP_PAGE_ADJUSTABLE_REPORT_RATE: { log_debug(ratbag, "device has adjustable report rate\n"); break; } case HIDPP_PAGE_COLOR_LED_EFFECTS: { log_debug(ratbag, "device has color effects\n"); break; } case HIDPP_PAGE_ONBOARD_PROFILES: { log_debug(ratbag, "device has onboard profiles\n"); drv_data->capabilities |= HIDPP_CAP_ONBOARD_PROFILES_8100; rc = hidpp20_onboard_profiles_allocate(drv_data->dev, &drv_data->profiles); if (rc < 0) return rc; drv_data->num_profiles = drv_data->profiles->num_profiles; drv_data->num_resolutions = drv_data->profiles->num_modes; drv_data->num_buttons = drv_data->profiles->num_buttons; break; } case HIDPP_PAGE_MOUSE_BUTTON_SPY: { log_debug(ratbag, "device has configurable mouse button spy\n"); break; } default: log_raw(device->ratbag, "unknown feature 0x%04x\n", feature); } return 0; }
int hidpp20_special_key_mouse_set_control(struct ratbag_device *device, struct hidpp20_control_id *control) { uint8_t feature_index, feature_type, feature_version; union hidpp20_message msg = { .msg.report_id = REPORT_ID_LONG, .msg.device_idx = 0xff, .msg.address = CMD_SPECIAL_KEYS_BUTTONS_SET_REPORTING, .msg.parameters[0] = control->control_id >> 8, .msg.parameters[1] = control->control_id & 0xff, .msg.parameters[2] = 0x00, .msg.parameters[3] = control->reporting.remapped >> 8, .msg.parameters[4] = control->reporting.remapped & 0xff, }; int rc; rc = hidpp_root_get_feature(device, HIDPP_PAGE_SPECIAL_KEYS_BUTTONS, &feature_index, &feature_type, &feature_version); if (rc) return rc; msg.msg.sub_id = feature_index; if (control->reporting.divert) msg.msg.parameters[2] |= 0x03; if (control->reporting.persist) msg.msg.parameters[2] |= 0x0c; if (control->reporting.raw_XY) msg.msg.parameters[2] |= 0x20; return hidpp20_request_command(device, &msg); } /* -------------------------------------------------------------------------- */ /* 0x2200: Mouse Pointer Basic Optical Sensors */ /* -------------------------------------------------------------------------- */ #define CMD_MOUSE_POINTER_BASIC_GET_INFO 0x00 int hidpp20_mousepointer_get_mousepointer_info(struct ratbag_device *device, uint16_t *resolution, uint8_t *flags) { uint8_t feature_index, feature_type, feature_version; union hidpp20_message msg = { .msg.report_id = REPORT_ID_LONG, .msg.device_idx = 0xff, .msg.address = CMD_MOUSE_POINTER_BASIC_GET_INFO, .msg.parameters[0] = feature_index, }; int rc; rc = hidpp_root_get_feature(device, HIDPP_PAGE_MOUSE_POINTER_BASIC, &feature_index, &feature_type, &feature_version); if (rc) return rc; msg.msg.sub_id = feature_index; rc = hidpp20_request_command(device, &msg); if (rc) return rc; *resolution = hidpp20_get_unaligned_u16(msg.msg.parameters); *flags = msg.msg.parameters[2]; return 0; } /* -------------------------------------------------------------------------- */ /* 0x2201: Adjustable DPI */ /* -------------------------------------------------------------------------- */ #define CMD_ADJUSTABLE_DPI_GET_SENSOR_COUNT 0x00 #define CMD_ADJUSTABLE_DPI_GET_SENSOR_DPI_LIST 0x10 #define CMD_ADJUSTABLE_DPI_GET_SENSOR_DPI 0x20 #define CMD_ADJUSTABLE_DPI_SET_SENSOR_DPI 0x30 static int hidpp20_adjustable_dpi_get_count(struct ratbag_device *device, uint8_t reg) { int rc; union hidpp20_message msg = { .msg.report_id = REPORT_ID_LONG, .msg.device_idx = 0xff, .msg.sub_id = reg, .msg.address = CMD_ADJUSTABLE_DPI_GET_SENSOR_COUNT, }; rc = hidpp20_request_command(device, &msg); if (rc) return rc; return msg.msg.parameters[0]; } static int hidpp20_adjustable_dpi_get_dpi_list(struct ratbag_device *device, uint8_t reg, struct hidpp20_sensor *sensor) { int rc; unsigned i = 1, dpi_index = 0; union hidpp20_message msg = { .msg.report_id = REPORT_ID_LONG, .msg.device_idx = 0xff, .msg.sub_id = reg, .msg.address = CMD_ADJUSTABLE_DPI_GET_SENSOR_DPI_LIST, .msg.parameters[0] = sensor->index, }; rc = hidpp20_request_command(device, &msg); if (rc) return rc; sensor->dpi_min = 0xffff; sensor->index = msg.msg.parameters[0]; while (i < LONG_MESSAGE_LENGTH - 4U && hidpp20_get_unaligned_u16(&msg.msg.parameters[i]) != 0) { uint16_t value = hidpp20_get_unaligned_u16(&msg.msg.parameters[i]); if (value > 0xe000) { sensor->dpi_steps = value - 0xe000; } else { sensor->dpi_min = value < sensor->dpi_min ? value : sensor->dpi_min; sensor->dpi_max = value > sensor->dpi_max ? value : sensor->dpi_max; sensor->dpi_list[dpi_index++] = value; } assert(sensor->dpi_list[dpi_index] == 0x0000); i += 2; } return 0; } static int hidpp20_adjustable_dpi_get_dpi(struct ratbag_device *device, uint8_t reg, struct hidpp20_sensor *sensor) { int rc; union hidpp20_message msg = { .msg.report_id = REPORT_ID_LONG, .msg.device_idx = 0xff, .msg.sub_id = reg, .msg.address = CMD_ADJUSTABLE_DPI_GET_SENSOR_DPI, .msg.parameters[0] = sensor->index, }; rc = hidpp20_request_command(device, &msg); if (rc) return rc; sensor->dpi = hidpp20_get_unaligned_u16(&msg.msg.parameters[1]); sensor->default_dpi = hidpp20_get_unaligned_u16(&msg.msg.parameters[3]); return 0; } int hidpp20_adjustable_dpi_get_sensors(struct ratbag_device *device, struct hidpp20_sensor **sensors_list) { uint8_t feature_index, feature_type, feature_version; struct hidpp20_sensor *s_list, *sensor; uint8_t num_sensors; unsigned i; int rc; rc = hidpp_root_get_feature(device, HIDPP_PAGE_ADJUSTABLE_DPI, &feature_index, &feature_type, &feature_version); if (rc) return rc; rc = hidpp20_adjustable_dpi_get_count(device, feature_index); if (rc < 0) return rc; num_sensors = rc; if (num_sensors == 0) { *sensors_list = NULL; return 0; } s_list = zalloc(num_sensors * sizeof(struct hidpp20_sensor)); for (i = 0; i < num_sensors; i++) { sensor = &s_list[i]; sensor->index = i; rc = hidpp20_adjustable_dpi_get_dpi_list(device, feature_index, sensor); if (rc) goto err; rc = hidpp20_adjustable_dpi_get_dpi(device, feature_index, sensor); if (rc) goto err; log_raw(device->ratbag, "sensor %d: current dpi: %d (default: %d) min: %d max: %d steps: %d\n", sensor->index, sensor->dpi, sensor->default_dpi, sensor->dpi_min, sensor->dpi_max, sensor->dpi_steps); } *sensors_list = s_list; return num_sensors; err: free(s_list); return rc; }
int hidpp20_batterylevel_get_battery_level(struct ratbag_device *device, uint16_t *level, uint16_t *next_level) { uint8_t feature_index, feature_type, feature_version; union hidpp20_message msg = { .msg.report_id = REPORT_ID_LONG, .msg.device_idx = 0xff, .msg.address = CMD_BATTERY_LEVEL_STATUS_GET_BATTERY_LEVEL_STATUS, }; int rc; rc = hidpp_root_get_feature(device, HIDPP_PAGE_BATTERY_LEVEL_STATUS, &feature_index, &feature_type, &feature_version); if (rc) return rc; msg.msg.sub_id = feature_index; rc = hidpp20_request_command(device, &msg); if (rc) return rc; *level = msg.msg.parameters[0]; *next_level = msg.msg.parameters[1]; return msg.msg.parameters[2]; } /* -------------------------------------------------------------------------- */ /* 0x1b00: KBD reprogrammable keys and mouse buttons */ /* -------------------------------------------------------------------------- */ #define CMD_KBD_REPROGRAMMABLE_KEYS_GET_COUNT 0x00 #define CMD_KBD_REPROGRAMMABLE_KEYS_GET_CTRL_ID_INFO 0x10 static int hidpp20_kbd_reprogrammable_keys_get_count(struct ratbag_device *device, uint8_t reg) { union hidpp20_message msg = { .msg.report_id = REPORT_ID_LONG, .msg.device_idx = 0xff, .msg.sub_id = reg, .msg.address = CMD_KBD_REPROGRAMMABLE_KEYS_GET_COUNT, }; int rc; rc = hidpp20_request_command(device, &msg); if (rc) return rc; return msg.msg.parameters[0]; } static int hidpp20_kbd_reprogrammable_keys_get_info(struct ratbag_device *device, uint8_t reg, struct hidpp20_control_id *control) { int rc; union hidpp20_message msg = { .msg.report_id = REPORT_ID_LONG, .msg.device_idx = 0xff, .msg.sub_id = reg, .msg.address = CMD_KBD_REPROGRAMMABLE_KEYS_GET_CTRL_ID_INFO, .msg.parameters[0] = control->index, }; rc = hidpp20_request_command(device, &msg); if (rc) return rc; control->control_id = hidpp20_get_unaligned_u16(&msg.msg.parameters[0]); control->task_id = hidpp20_get_unaligned_u16(&msg.msg.parameters[2]); control->flags = msg.msg.parameters[4]; return 0; } int hidpp20_kbd_reprogrammable_keys_get_controls(struct ratbag_device *device, struct hidpp20_control_id **controls_list) { uint8_t feature_index, feature_type, feature_version; struct hidpp20_control_id *c_list, *control; uint8_t num_controls; unsigned i; int rc; rc = hidpp_root_get_feature(device, HIDPP_PAGE_KBD_REPROGRAMMABLE_KEYS, &feature_index, &feature_type, &feature_version); if (rc) return rc; rc = hidpp20_kbd_reprogrammable_keys_get_count(device, feature_index); if (rc < 0) return rc; num_controls = rc; if (num_controls == 0) { *controls_list = NULL; return 0; } c_list = zalloc(num_controls * sizeof(struct hidpp20_control_id)); for (i = 0; i < num_controls; i++) { control = &c_list[i]; control->index = i; rc = hidpp20_kbd_reprogrammable_keys_get_info(device, feature_index, control); if (rc) goto err; /* 0x1b00 and 0x1b04 have the same control/task id mappings. * I hope */ log_raw(device->ratbag, "control %d: cid: '%s' (%d) tid: '%s' (%d) flags: 0x%02x\n", control->index, hidpp20_1b04_get_logical_mapping_name(control->control_id), control->control_id, hidpp20_1b04_get_physical_mapping_name(control->task_id), control->task_id, control->flags); } *controls_list = c_list; return num_controls; err: free(c_list); return rc; } /* -------------------------------------------------------------------------- */ /* 0x1b04: Special keys and mouse buttons */ /* -------------------------------------------------------------------------- */ #define CMD_SPECIAL_KEYS_BUTTONS_GET_COUNT 0x00 #define CMD_SPECIAL_KEYS_BUTTONS_GET_INFO 0x10 #define CMD_SPECIAL_KEYS_BUTTONS_GET_REPORTING 0x20 #define CMD_SPECIAL_KEYS_BUTTONS_SET_REPORTING 0x30 static int hidpp20_special_keys_buttons_get_count(struct ratbag_device *device, uint8_t reg) { int rc; union hidpp20_message msg = { .msg.report_id = REPORT_ID_LONG, .msg.device_idx = 0xff, .msg.sub_id = reg, .msg.address = CMD_SPECIAL_KEYS_BUTTONS_GET_COUNT, }; rc = hidpp20_request_command(device, &msg); if (rc) return rc; return msg.msg.parameters[0]; } static int hidpp20_special_keys_buttons_get_info(struct ratbag_device *device, uint8_t reg, struct hidpp20_control_id *control) { int rc; union hidpp20_message msg = { .msg.report_id = REPORT_ID_LONG, .msg.device_idx = 0xff, .msg.sub_id = reg, .msg.address = CMD_SPECIAL_KEYS_BUTTONS_GET_INFO, .msg.parameters[0] = control->index, }; rc = hidpp20_request_command(device, &msg); if (rc) return rc; control->control_id = hidpp20_get_unaligned_u16(&msg.msg.parameters[0]); control->task_id = hidpp20_get_unaligned_u16(&msg.msg.parameters[2]); control->flags = msg.msg.parameters[4]; control->position = msg.msg.parameters[5]; control->group = msg.msg.parameters[6]; control->group_mask = msg.msg.parameters[7]; control->raw_XY = msg.msg.parameters[8] & 0x01; return 0; } static int hidpp20_special_keys_buttons_get_reporting(struct ratbag_device *device, uint8_t reg, struct hidpp20_control_id *control) { int rc; union hidpp20_message msg = { .msg.report_id = REPORT_ID_LONG, .msg.device_idx = 0xff, .msg.sub_id = reg, .msg.address = CMD_SPECIAL_KEYS_BUTTONS_GET_REPORTING, .msg.parameters[0] = control->control_id >> 8, .msg.parameters[1] = control->control_id & 0xff, }; rc = hidpp20_request_command(device, &msg); if (rc) return rc; control->reporting.remapped = hidpp20_get_unaligned_u16(&msg.msg.parameters[3]); control->reporting.raw_XY = !!(msg.msg.parameters[2] & 0x10); control->reporting.persist = !!(msg.msg.parameters[2] & 0x04); control->reporting.divert = !!(msg.msg.parameters[2] & 0x01); return 0; } int hidpp20_special_key_mouse_get_controls(struct ratbag_device *device, struct hidpp20_control_id **controls_list) { uint8_t feature_index, feature_type, feature_version; struct hidpp20_control_id *c_list, *control; uint8_t num_controls; unsigned i; int rc; rc = hidpp_root_get_feature(device, HIDPP_PAGE_SPECIAL_KEYS_BUTTONS, &feature_index, &feature_type, &feature_version); if (rc) return rc; rc = hidpp20_special_keys_buttons_get_count(device, feature_index); if (rc < 0) return rc; num_controls = rc; if (num_controls == 0) { *controls_list = NULL; return 0; } c_list = zalloc(num_controls * sizeof(struct hidpp20_control_id)); for (i = 0; i < num_controls; i++) { control = &c_list[i]; control->index = i; rc = hidpp20_special_keys_buttons_get_info(device, feature_index, control); if (rc) goto err; rc = hidpp20_special_keys_buttons_get_reporting(device, feature_index, control); if (rc) goto err; log_raw(device->ratbag, "control %d: cid: '%s' (%d) tid: '%s' (%d) flags: 0x%02x pos: %d group: %d gmask: 0x%02x raw_XY: %s\n" " reporting: raw_xy: %s persist: %s divert: %s remapped: '%s' (%d)\n", control->index, hidpp20_1b04_get_logical_mapping_name(control->control_id), control->control_id, hidpp20_1b04_get_physical_mapping_name(control->task_id), control->task_id, control->flags, control->position, control->group, control->group_mask, control->raw_XY ? "yes" : "no", control->reporting.raw_XY ? "yes" : "no", control->reporting.persist ? "yes" : "no", control->reporting.divert ? "yes" : "no", hidpp20_1b04_get_logical_mapping_name(control->reporting.remapped), control->reporting.remapped); } *controls_list = c_list; return num_controls; err: free(c_list); return rc; }
int hidpp_root_get_feature(struct ratbag_device *device, uint16_t feature, uint8_t *feature_index, uint8_t *feature_type, uint8_t *feature_version) { int rc; union hidpp20_message msg = { .msg.report_id = REPORT_ID_LONG, .msg.device_idx = 0xff, .msg.sub_id = HIDPP_PAGE_ROOT_IDX, .msg.address = CMD_ROOT_GET_FEATURE, .msg.parameters[0] = feature >> 8, .msg.parameters[1] = feature & 0xff, }; rc = hidpp20_request_command(device, &msg); if (rc) return rc; *feature_index = msg.msg.parameters[0]; *feature_type = msg.msg.parameters[1]; *feature_version = msg.msg.parameters[2]; log_raw(device->ratbag, "feature 0x%04x is at 0x%02x\n", feature, *feature_index); return 0; } int hidpp20_root_get_protocol_version(struct ratbag_device *device, unsigned *major, unsigned *minor) { int rc; union hidpp20_message msg = { .msg.report_id = REPORT_ID_LONG, .msg.device_idx = 0xff, .msg.sub_id = HIDPP_PAGE_ROOT_IDX, .msg.address = CMD_ROOT_GET_PROTOCOL_VERSION, }; rc = hidpp20_request_command_allow_error(device, &msg, true); if (rc == ERR_INVALID_SUBID) { *major = 1; *minor = 0; return 0; } if (rc == 0) { *major = msg.msg.parameters[0]; *minor = msg.msg.parameters[1]; } return rc; } /* -------------------------------------------------------------------------- */ /* 0x0001: Feature Set */ /* -------------------------------------------------------------------------- */ #define CMD_FEATURE_SET_GET_COUNT 0x00 #define CMD_FEATURE_SET_GET_FEATURE_ID 0x10 static int hidpp20_feature_set_get_count(struct ratbag_device *device, uint8_t reg) { int rc; union hidpp20_message msg = { .msg.report_id = REPORT_ID_LONG, .msg.device_idx = 0xff, .msg.sub_id = reg, .msg.address = CMD_FEATURE_SET_GET_COUNT, }; rc = hidpp20_request_command(device, &msg); if (rc) return rc; return msg.msg.parameters[0]; } static int hidpp20_feature_set_get_feature_id(struct ratbag_device *device, uint8_t reg, uint8_t feature_index, uint16_t *feature, uint8_t *type) { int rc; union hidpp20_message msg = { .msg.report_id = REPORT_ID_LONG, .msg.device_idx = 0xff, .msg.sub_id = reg, .msg.address = CMD_FEATURE_SET_GET_FEATURE_ID, .msg.parameters[0] = feature_index, }; rc = hidpp20_request_command(device, &msg); if (rc) return rc; *feature = hidpp20_get_unaligned_u16(msg.msg.parameters); *type = msg.msg.parameters[2]; return 0; } int hidpp20_feature_set_get(struct ratbag_device *device, struct hidpp20_feature **feature_list) { uint8_t feature_index, feature_type, feature_version; struct hidpp20_feature *flist; int rc; uint8_t feature_count; unsigned int i; rc = hidpp_root_get_feature(device, HIDPP_PAGE_FEATURE_SET, &feature_index, &feature_type, &feature_version); if (rc) return rc; rc = hidpp20_feature_set_get_count(device, feature_index); if (rc < 0) return rc; feature_count = (uint8_t)rc; if (!feature_count) { *feature_list = NULL; return 0; } flist = zalloc(feature_count * sizeof(struct hidpp20_feature)); for (i = 0; i < feature_count; i++) { rc = hidpp20_feature_set_get_feature_id(device, feature_index, i, &flist[i].feature, &flist[i].type); if (rc) goto err; } *feature_list = flist; return feature_count; err: free(flist); return rc; }
static void syntax(char *confname) { log_raw(" "); log_raw("Syntax:"); #ifdef USE_WIN32 log_raw("stunnel [filename] | -help | -version | -sockets" " | -install | -uninstall"); #else log_raw("stunnel [filename] | -fd [n] | -help | -version | -sockets"); #endif log_raw(" filename - use specified config file instead of %s", confname); log_raw(" -fd n - read the config file from specified file descriptor"); log_raw(" -help - get config file help"); log_raw(" -version - display version and defaults"); log_raw(" -sockets - display default socket options"); #ifdef USE_WIN32 log_raw(" -install - install NT service"); log_raw(" -uninstall - uninstall NT service"); #endif exit(1); }
static char *service_options(CMD cmd, LOCAL_OPTIONS *section, char *opt, char *arg) { if(cmd==CMD_DEFAULT || cmd==CMD_HELP) { log_raw(" "); log_raw("Service-level options"); } /* accept */ switch(cmd) { case CMD_INIT: section->option.accept=0; break; case CMD_EXEC: if(strcasecmp(opt, "accept")) break; section->option.accept=1; if(!name2nums(arg, "0.0.0.0", §ion->localnames, §ion->localport)) exit(2); return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = [host:]port accept connections on specified host:port", "accept"); break; } /* connect */ switch(cmd) { case CMD_INIT: section->option.remote=0; section->remote_address=NULL; section->remotenames=NULL; section->remoteport=0; break; case CMD_EXEC: if(strcasecmp(opt, "connect")) break; section->option.remote=1; section->remote_address=stralloc(arg); if(!section->option.delayed_lookup && !name2nums(arg, "127.0.0.1", §ion->remotenames, §ion->remoteport)) { log_raw("Cannot resolve '%s' - delaying DNS lookup", arg); section->option.delayed_lookup=1; } return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = [host:]port connect remote host:port", "connect"); break; } /* delay */ switch(cmd) { case CMD_INIT: section->option.delayed_lookup=0; break; case CMD_EXEC: if(strcasecmp(opt, "delay")) break; if(!strcasecmp(arg, "yes")) section->option.delayed_lookup=1; else if(!strcasecmp(arg, "no")) section->option.delayed_lookup=0; else return "argument should be either 'yes' or 'no'"; return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = yes|no delay DNS lookup for 'connect' option", "delay"); break; } /* exec */ #ifndef USE_WIN32 switch(cmd) { case CMD_INIT: section->option.program=0; section->execname=NULL; break; case CMD_EXEC: if(strcasecmp(opt, "exec")) break; section->option.program=1; section->execname=stralloc(arg); return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = file execute local inetd-type program", "exec"); break; } #endif /* execargs */ #ifndef USE_WIN32 switch(cmd) { case CMD_INIT: section->execargs=NULL; break; case CMD_EXEC: if(strcasecmp(opt, "execargs")) break; section->execargs=argalloc(arg); return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = arguments for 'exec' (including $0)", "execargs"); break; } #endif /* ident */ switch(cmd) { case CMD_INIT: section->username=NULL; break; case CMD_EXEC: if(strcasecmp(opt, "ident")) break; section->username=stralloc(arg); return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = username for IDENT (RFC 1413) checking", "ident"); break; } /* local */ switch(cmd) { case CMD_INIT: section->local_ip=NULL; break; case CMD_EXEC: if(strcasecmp(opt, "local")) break; if(!host2nums(arg, &(section->local_ip))) exit(2); return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = IP address to be used as source for remote" " connections", "local"); break; } /* protocol */ switch(cmd) { case CMD_INIT: section->protocol=NULL; break; case CMD_EXEC: if(strcasecmp(opt, "protocol")) break; section->protocol=stralloc(arg); return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = protocol to negotiate before SSL initialization", "protocol"); log_raw("%18scurrently supported: cifs, nntp, pop3, smtp", ""); break; } /* pty */ #ifndef USE_WIN32 switch(cmd) { case CMD_INIT: section->option.pty=0; break; case CMD_EXEC: if(strcasecmp(opt, "pty")) break; if(!strcasecmp(arg, "yes")) section->option.pty=1; else if(!strcasecmp(arg, "no")) section->option.pty=0; else return "argument should be either 'yes' or 'no'"; return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = yes|no allocate pseudo terminal for 'exec' option", "pty"); break; } #endif /* TIMEOUTbusy */ switch(cmd) { case CMD_INIT: section->timeout_busy=300; /* 5 minutes */ break; case CMD_EXEC: if(strcasecmp(opt, "TIMEOUTbusy")) break; if(atoi(arg)>0) section->timeout_busy=atoi(arg); else return "Illegal busy timeout"; return NULL; /* OK */ case CMD_DEFAULT: log_raw("%-15s = %d seconds", "TIMEOUTbusy", section->timeout_busy); break; case CMD_HELP: log_raw("%-15s = seconds to wait for expected data", "TIMEOUTbusy"); break; } /* TIMEOUTclose */ switch(cmd) { case CMD_INIT: section->timeout_close=60; /* 1 minute */ break; case CMD_EXEC: if(strcasecmp(opt, "TIMEOUTclose")) break; if(atoi(arg)>0 || !strcmp(arg, "0")) section->timeout_close=atoi(arg); else return "Illegal close timeout"; return NULL; /* OK */ case CMD_DEFAULT: log_raw("%-15s = %d seconds", "TIMEOUTclose", section->timeout_close); break; case CMD_HELP: log_raw("%-15s = seconds to wait for close_notify" " (set to 0 for buggy MSIE)", "TIMEOUTclose"); break; } /* TIMEOUTidle */ switch(cmd) { case CMD_INIT: section->timeout_idle=43200; /* 12 hours */ break; case CMD_EXEC: if(strcasecmp(opt, "TIMEOUTidle")) break; if(atoi(arg)>0) section->timeout_idle=atoi(arg); else return "Illegal idle timeout"; return NULL; /* OK */ case CMD_DEFAULT: log_raw("%-15s = %d seconds", "TIMEOUTidle", section->timeout_idle); break; case CMD_HELP: log_raw("%-15s = seconds to keep idle connection", "TIMEOUTidle"); break; } /* transparent */ #ifndef USE_WIN32 switch(cmd) { case CMD_INIT: section->option.transparent=0; break; case CMD_EXEC: if(strcasecmp(opt, "transparent")) break; if(!strcasecmp(arg, "yes")) section->option.transparent=1; else if(!strcasecmp(arg, "no")) section->option.transparent=0; else return "argument should be either 'yes' or 'no'"; return NULL; /* OK */ case CMD_DEFAULT: break; case CMD_HELP: log_raw("%-15s = yes|no transparent proxy mode", "transparent"); break; } #endif if(cmd==CMD_EXEC) return option_not_found; return NULL; /* OK */ }