void communicate(int d) { int32_t command = ur[0].value; ri.report_type = HID_REPORT_TYPE_OUTPUT; for (unsigned int u = 0; u <= 63; ++u) { ur[u].report_type = ri.report_type; if (0 != ioctl(d, HIDIOCSUSAGE, &ur[u])) fatal_e(E_RARE, "Can't set usage %u", u); } if (0 != ioctl(d, HIDIOCSREPORT, &ri)) fatal_e(E_COMMON, "Can't send report"); wait(); ri.report_type = HID_REPORT_TYPE_INPUT; if (0 != ioctl(d, HIDIOCGREPORT, &ri)) fatal_e(E_COMMON, "Can't get report"); wait(); for (unsigned int u = 0; u <= 63; ++u) { ur[u].report_type = ri.report_type; if (0 != ioctl(d, HIDIOCGUSAGE, &ur[u])) fatal_e(E_RARE, "Can't get value of usage %u", u); } if (ur[0].value != command) fatal(E_RARE, "Command not echoed (command = 0x%02X, response = 0x%02X)", command, ur[0].value); else if (ur[1].value != 0) fatal(E_COMMON, "Command failed"); }
struct hiddev_usage_ref* init_report(int d, struct hiddev_report_info* new_ri) { ri = *new_ri; ri.report_type = HID_REPORT_TYPE_OUTPUT; { int version; if (0 != ioctl(d, HIDIOCGVERSION, &version)) fatal(E_RARE, "Can't get hiddev version"); /*printf("hiddev is version 0x%x\n", version);*/ } for (unsigned int u = 0; u <= 63; ++u) { ur[u].report_type = HID_REPORT_TYPE_OUTPUT; ur[u].report_id = ri.report_id; ur[u].field_index = 0; ur[u].usage_index = u; if (0 != ioctl(d, HIDIOCGUCODE, &ur[u])) fatal_e(E_RARE, "Can't get usage code %u", u); } wait(); ur[0].value = 0x10; communicate(d); return ur; }
void ossp_slave_init(int argc, char **argv) { int have_uid = 0, have_gid = 0; uid_t uid; gid_t gid; int mmap_fd = -1; off_t mmap_off = 0; size_t mmap_size = 0; int opt; struct passwd *pw, pw_buf; struct sigaction sa; char pw_sbuf[sysconf(_SC_GETPW_R_SIZE_MAX)]; while ((opt = getopt(argc, argv, "u:g:c:n:m:o:s:l:t")) != -1) { switch (opt) { case 'u': have_uid = 1; uid = strtol(optarg, NULL, 0); break; case 'g': have_gid = 1; gid = strtol(optarg, NULL, 0); break; case 'c': ossp_cmd_fd = strtol(optarg, NULL, 0); break; case 'n': ossp_notify_fd = strtol(optarg, NULL, 0); break; case 'm': mmap_fd = strtol(optarg, NULL, 0); break; case 'o': mmap_off = strtoull(optarg, NULL, 0); break; case 's': mmap_size = strtoul(optarg, NULL, 0); break; case 'l': ossp_log_level = strtol(optarg, NULL, 0); break; case 't': ossp_log_timestamp = 1; break; } } if (!have_uid || !have_gid || ossp_cmd_fd < 0 || ossp_notify_fd < 0) { fprintf(stderr, usage); _exit(1); } snprintf(ossp_user_name, sizeof(ossp_user_name), "uid%d", uid); if (getpwuid_r(uid, &pw_buf, pw_sbuf, sizeof(pw_sbuf), &pw) == 0) snprintf(ossp_user_name, sizeof(ossp_user_name), "%s", pw->pw_name); snprintf(ossp_log_name, sizeof(ossp_log_name), "ossp-padsp[%s:%d]", ossp_user_name, getpid()); if (mmap_fd >= 0) { void *p; if (!mmap_off || !mmap_size) { fprintf(stderr, usage); _exit(1); } p = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, mmap_fd, mmap_off); if (p == MAP_FAILED) fatal_e(-errno, "mmap failed"); ossp_mmap_addr[PLAY] = p; ossp_mmap_addr[REC] = p + mmap_size / 2; close(mmap_fd); } /* mmap done, drop privileges */ if (setresgid(gid, gid, gid) || setresuid(uid, uid, uid)) fatal_e(-errno, "failed to drop privileges"); /* block SIGPIPE */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_IGN; if (sigaction(SIGPIPE, &sa, NULL)) fatal_e(-errno, "failed to ignore SIGPIPE"); }