On Tue, 22 Nov 2016, Manasi Navare <manasi.d.navare@xxxxxxxxx> wrote: > + > +static void get_test_videopattern_data(void) > +{ > + int count = 0; > + uint16_t video_pattern_value[3]; > + char video_pattern_attribute[15]; > + > + if (!test_data_fp) > + fprintf(stderr, "Invalid Test data File pointer\r\n"); > + > + rewind(test_data_fp); > + while (!feof(test_data_fp) && count < 3) > + fscanf(test_data_fp, "%s %u\n", video_pattern_attribute, > + (unsigned int *)&video_pattern_value[count++]); > + > + hdisplay = video_pattern_value[0]; > + vdisplay = video_pattern_value[1]; > + bitdepth = video_pattern_value[2]; > + igt_info("Hdisplay = %d\r\n", hdisplay); > + igt_info("Vdisplay = %d\r\n", vdisplay); > + igt_info("BitDepth = %u\r\n", bitdepth); > + > +} If you have this working now, I guess we can go with what's in [1] since that's fairly isolated for now. It's debugfs, so we can remove it later. In the long run, I do want this using DPCD directly though. BR, Jani. [1] http://patchwork.freedesktop.org/patch/msgid/1479850766-32748-6-git-send-email-manasi.d.navare@xxxxxxxxx > + > +static int process_test_request(int test_type) > +{ > + int mode; > + unsigned long test_data_edid; > + int status = 0; > + > + switch (test_type) { > + case DP_TEST_LINK_VIDEO_PATTERN: > + video_pattern_flag = true; > + get_test_videopattern_data(); > + mode = INTEL_MODE_VIDEO_PATTERN_TEST; > + break; > + case DP_TEST_LINK_EDID_READ: > + test_data_edid = get_test_edid_data(); > + mode = (test_data_edid & DP_COMPLIANCE_VIDEO_MODE_MASK) >> > + INTEL_DP_RESOLUTION_SHIFT_MASK; > + break; > + default: > + /* Unknown test type */ > + fprintf(stderr, "Invalid test request. Ignored.\r\n"); > + break; > + } > + status = update_display(mode, true); > + > + /* Return 0 on success and -1 on failure */ > + return status; > +} > + > +static void dump_connectors_fd(int drmfd) > +{ > + int i, j; > + > + drmModeRes *mode_resources = drmModeGetResources(drmfd); > + > + if (!mode_resources) { > + igt_warn("drmModeGetResources failed: %s\n", strerror(errno)); > + return; > + } > + > + igt_info("Connectors:\n"); > + igt_info("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\n"); > + for (i = 0; i < mode_resources->count_connectors; i++) { > + drmModeConnector *connector; > + > + connector = drmModeGetConnectorCurrent(drmfd, > + mode_resources->connectors[i]); > + if (!connector) { > + igt_warn("could not get connector %i: %s\n", mode_resources->connectors[i], strerror(errno)); > + continue; > + } > + > + igt_info("%d\t%d\t%s\t%s\t%dx%d\t\t%d\n", connector->connector_id, connector->encoder_id, kmstest_connector_status_str(connector->connection), kmstest_connector_type_str(connector->connector_type), connector->mmWidth, connector->mmHeight, connector->count_modes); > + > + if (!connector->count_modes) > + continue; > + > + igt_info(" modes:\n"); > + igt_info(" name refresh (Hz) hdisp hss hse htot vdisp ""vss vse vtot flags type clock\n"); > + for (j = 0; j < connector->count_modes; j++) { > + igt_info("[%d]", j); > + kmstest_dump_mode(&connector->modes[j]); > + } > + > + drmModeFreeConnector(connector); > + } > + igt_info("\n"); > + > + drmModeFreeResources(mode_resources); > +} > + > +static void dump_crtcs_fd(int drmfd) > +{ > + int i; > + drmModeRes *mode_resources = drmModeGetResources(drmfd); > + > + igt_info("CRTCs:\n"); > + igt_info("id\tfb\tpos\tsize\n"); > + for (i = 0; i < mode_resources->count_crtcs; i++) { > + drmModeCrtc *crtc; > + > + crtc = drmModeGetCrtc(drmfd, mode_resources->crtcs[i]); > + if (!crtc) { > + igt_warn("could not get crtc %i: %s\n", mode_resources->crtcs[i], strerror(errno)); > + continue; > + } > + igt_info("%d\t%d\t(%d,%d)\t(%dx%d)\n", crtc->crtc_id, crtc->buffer_id, crtc->x, crtc->y, crtc->width, crtc->height); > + kmstest_dump_mode(&crtc->mode); > + > + drmModeFreeCrtc(crtc); > + } > + igt_info("\n"); > + > + drmModeFreeResources(mode_resources); > +} > + > +static void dump_info(void) > +{ > + dump_connectors_fd(drm_fd); > + dump_crtcs_fd(drm_fd); > +} > + > +static void connector_find_preferred_mode(uint32_t connector_id, > + unsigned long crtc_idx_mask, > + struct connector *c) > +{ > + struct kmstest_connector_config config; > + bool ret; > + > + ret = kmstest_probe_connector_config(drm_fd, connector_id, > + crtc_idx_mask, &config); > + if (!ret) { > + c->mode_valid = 0; > + return; > + } > + > + c->connector = config.connector; > + c->encoder = config.encoder; > + c->crtc = config.crtc->crtc_id; > + c->pipe = config.pipe; > + > + if (c->connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort || > + c->connector->connection != DRM_MODE_CONNECTED) { > + c->mode_valid = 0; > + return; > + } > + > + c->mode = config.default_mode; > + c->mode_valid = 1; > +} > + > +static int setup_framebuffers(struct connector *dp_conn) > +{ > + > + dp_conn->fb = igt_create_fb(drm_fd, > + dp_conn->fb_width, dp_conn->fb_height, > + DRM_FORMAT_XRGB8888, > + LOCAL_DRM_FORMAT_MOD_NONE, > + &dp_conn->fb_video_pattern); > + igt_assert(dp_conn->fb); > + > + /* Map the mapping of GEM object into the virtual address space */ > + dp_conn->pixmap = gem_mmap__gtt(drm_fd, > + dp_conn->fb_video_pattern.gem_handle, > + dp_conn->fb_video_pattern.size, > + PROT_READ | PROT_WRITE); > + gem_set_domain(drm_fd, dp_conn->fb_video_pattern.gem_handle, > + I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); > + dp_conn->fb_size = dp_conn->fb_video_pattern.size; > + > + /* After filling the device memory with 0s it needs to be unmapped */ > + memset(dp_conn->pixmap, 0, dp_conn->fb_size); > + munmap(dp_conn->pixmap, dp_conn->fb_size); > + > + return 0; > +} > + > +static int setup_failsafe_framebuffer(struct connector *dp_conn) > +{ > + > + dp_conn->failsafe_fb = igt_create_fb(drm_fd, > + dp_conn->failsafe_width, > + dp_conn->failsafe_height, > + DRM_FORMAT_XRGB8888, > + LOCAL_DRM_FORMAT_MOD_NONE, > + &dp_conn->fb_failsafe_pattern); > + igt_assert(dp_conn->failsafe_fb); > + > + /* Map the mapping of GEM object into the virtual address space */ > + dp_conn->failsafe_pixmap = gem_mmap__gtt(drm_fd, > + dp_conn->fb_failsafe_pattern.gem_handle, > + dp_conn->fb_failsafe_pattern.size, > + PROT_READ | PROT_WRITE); > + gem_set_domain(drm_fd, dp_conn->fb_failsafe_pattern.gem_handle, > + I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); > + dp_conn->failsafe_size = dp_conn->fb_failsafe_pattern.size; > + > + /* After filling the device framebuffer the mapped memory needs to be freed */ > + memset(dp_conn->failsafe_pixmap, 0, dp_conn->failsafe_size); > + munmap(dp_conn->failsafe_pixmap, dp_conn->failsafe_size); > + > + return 0; > + > +} > + > +static int setup_video_pattern_framebuffer(struct connector *dp_conn) > +{ > + uint32_t video_width, video_height; > + > + video_width = dp_conn->test_pattern.hdisplay; > + video_height = dp_conn->test_pattern.vdisplay; > + dp_conn->test_pattern.fb = igt_create_fb(drm_fd, > + video_width, video_height, > + DRM_FORMAT_XRGB8888, > + LOCAL_DRM_FORMAT_MOD_NONE, > + &dp_conn->test_pattern.fb_pattern); > + igt_assert(dp_conn->test_pattern.fb); > + > + /* Map the mapping of GEM object into the virtual address space */ > + dp_conn->test_pattern.pixmap = gem_mmap__gtt(drm_fd, > + dp_conn->test_pattern.fb_pattern.gem_handle, > + dp_conn->test_pattern.fb_pattern.size, > + PROT_READ | PROT_WRITE); > + gem_set_domain(drm_fd, dp_conn->test_pattern.fb_pattern.gem_handle, > + I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); > + > + dp_conn->test_pattern.size = dp_conn->test_pattern.fb_pattern.size; > + > + memset(dp_conn->test_pattern.pixmap, 0, dp_conn->test_pattern.size); > + return 0; > + > +} > + > +static int fill_framebuffer(struct connector *dp_conn) > +{ > + uint32_t tile_height, tile_width, video_width, video_height; > + uint32_t *red_ptr, *green_ptr, *blue_ptr, *white_ptr, *src_ptr, *dst_ptr; > + int x, y; > + int32_t pixel_val; > + > + video_width = dp_conn->test_pattern.hdisplay; > + video_height = dp_conn->test_pattern.vdisplay; > + > + tile_height = 64; > + tile_width = 1 << (dp_conn->test_pattern.bitdepth); > + > + red_ptr = dp_conn->test_pattern.pixmap; > + green_ptr = red_ptr + (video_width * tile_height); > + blue_ptr = green_ptr + (video_width * tile_height); > + white_ptr = blue_ptr + (video_width * tile_height); > + x = 0; > + > + /* Fill the frame buffer with video pattern from CTS 3.1.5 */ > + while (x < video_width) { > + for (pixel_val = 0; pixel_val < 256; > + pixel_val = pixel_val + (256 / tile_width)) { > + red_ptr[x] = pixel_val << 16; > + green_ptr[x] = pixel_val << 8; > + blue_ptr[x] = pixel_val << 0; > + white_ptr[x] = red_ptr[x] | green_ptr[x] | blue_ptr[x]; > + if (++x >= video_width) > + break; > + } > + } > + for (y = 0; y < video_height; y++) { > + if (y == 0 || y == 64 || y == 128 || y == 192) > + continue; > + switch ((y / tile_height) % 4) { > + case 0: > + src_ptr = red_ptr; > + break; > + case 1: > + src_ptr = green_ptr; > + break; > + case 2: > + src_ptr = blue_ptr; > + break; > + case 3: > + src_ptr = white_ptr; > + break; > + } > + dst_ptr = dp_conn->test_pattern.pixmap + (y * video_width); > + memcpy(dst_ptr, src_ptr, (video_width * 4)); > + } > + munmap(dp_conn->test_pattern.pixmap, > + dp_conn->test_pattern.size); > + return 0; > +} > + > +static int set_test_mode(struct connector *dp_conn) > +{ > + int ret = 0; > + int i; > + bool found_std = false, found_fs = false; > + drmModeConnector *c = dp_conn->connector; > + > + /* Ignore any disconnected devices */ > + if (c->connection != DRM_MODE_CONNECTED) { > + igt_warn("Connector %u disconnected\r\n", c->connector_id); > + return -ENOENT; > + } > + igt_info("Connector Setup:\r\n"); > + /* Setup preferred mode - should be mode[0] in the list */ > + dp_conn->mode_preferred = c->modes[0]; > + dp_conn->fb_width = c->modes[0].hdisplay; > + dp_conn->fb_height = c->modes[0].vdisplay; > + > + dp_conn->test_pattern.mode = c->modes[0]; > + dp_conn->test_pattern.mode.hdisplay = c->modes[0].hdisplay; > + dp_conn->test_pattern.mode.vdisplay = c->modes[0].vdisplay; > + > + igt_info("Preferred mode (mode 0) for connector %u is %ux%u\r\n", > + dp_conn->id, c->modes[0].hdisplay, c->modes[0].vdisplay); > + fflush(stdin); > + > + for (i = 1; i < c->count_modes; i++) { > + /* Standard mode is 800x600@60 */ > + if (c->modes[i].hdisplay == 800 && > + c->modes[i].vdisplay == 600 && > + c->modes[i].vrefresh == 60 && > + found_std == false) { > + dp_conn->mode_standard = c->modes[i]; > + igt_info("Standard mode (%d) for connector %u is %ux%u\r\n", > + i, > + c->connector_id, > + c->modes[i].hdisplay, > + c->modes[i].vdisplay); > + found_std = true; > + } > + /* Failsafe mode is 640x480@60 */ > + if (c->modes[i].hdisplay == 640 && > + c->modes[i].vdisplay == 480 && > + c->modes[i].vrefresh == 60 && > + found_fs == false) { > + dp_conn->mode_failsafe = c->modes[i]; > + dp_conn->failsafe_width = c->modes[i].hdisplay; > + dp_conn->failsafe_height = c->modes[i].vdisplay; > + igt_info("Failsafe mode (%d) for connector %u is %ux%u\r\n", > + i, > + c->connector_id, > + c->modes[i].hdisplay, > + c->modes[i].vdisplay); > + found_fs = true; > + } > + } > + > + ret = setup_framebuffers(dp_conn); > + if (ret) { > + igt_warn("Create framebuffer for connector %u failed (%d)\r\n", > + c->connector_id, ret); > + return ret; > + } > + > + if (found_fs) { > + ret = setup_failsafe_framebuffer(dp_conn); > + if (ret) { > + igt_warn("Create failsafe framebuffer for connector %u" > + "failed (%d)\r\n", > + c->connector_id, ret); > + return ret; > + } > + } > + > + if (video_pattern_flag) { > + dp_conn->test_pattern.hdisplay = hdisplay; > + dp_conn->test_pattern.vdisplay = vdisplay; > + dp_conn->test_pattern.bitdepth = bitdepth; > + ret = setup_video_pattern_framebuffer(dp_conn); > + if (ret) { > + igt_warn("Create framebuffer for connector %u failed (%d)\r\n", > + c->connector_id, ret); > + return ret; > + } > + ret = fill_framebuffer(dp_conn); > + if (ret) { > + igt_warn("Fill framebuffer for connector %u failed (%d)\r\n", > + c->connector_id, ret); > + return ret; > + } > + } > + > + return ret; > +} > + > +static int set_video(int mode, struct connector *test_connector) > +{ > + drmModeModeInfo *requested_mode; > + uint32_t required_fb_id; > + struct igt_fb required_fb; > + int ret = 0; > + > + switch (mode) { > + case INTEL_MODE_NONE: > + igt_info("NONE\r\n"); > + ret = drmModeSetCrtc(drm_fd, test_connector->crtc, > + -1, 0, 0, NULL, 0, NULL); > + goto out; > + case INTEL_MODE_PREFERRED: > + igt_info("PREFERRED\r\n"); > + requested_mode = &test_connector->mode_preferred; > + required_fb_id = test_connector->fb; > + required_fb = test_connector->fb_video_pattern; > + break; > + case INTEL_MODE_STANDARD: > + igt_info("STANDARD\r\n"); > + requested_mode = &test_connector->mode_standard; > + required_fb_id = test_connector->fb; > + required_fb = test_connector->fb_video_pattern; > + break; > + case INTEL_MODE_FAILSAFE: > + igt_info("FAILSAFE\r\n"); > + requested_mode = &test_connector->mode_failsafe; > + required_fb_id = test_connector->failsafe_fb; > + required_fb = test_connector->fb_failsafe_pattern; > + break; > + case INTEL_MODE_VIDEO_PATTERN_TEST: > + igt_info("VIDEO PATTERN TEST\r\n"); > + requested_mode = &test_connector->test_pattern.mode; > + required_fb_id = test_connector->test_pattern.fb; > + required_fb = test_connector->test_pattern.fb_pattern; > + break; > + case INTEL_MODE_INVALID: > + default: > + igt_warn("INVALID! (%08x) Mode set aborted!\r\n", mode); > + return -1; > + } > + > + igt_info("CRTC(%u):", test_connector->crtc); > + kmstest_dump_mode(requested_mode); > + ret = drmModeSetCrtc(drm_fd, test_connector->crtc, required_fb_id, 0, 0, > + &test_connector->id, 1, requested_mode); > + if (ret) { > + igt_warn("failed to set mode (%dx%d@%dHz): %s\n", > + requested_mode->hdisplay, requested_mode->vdisplay, > + requested_mode->vrefresh, strerror(errno)); > + igt_remove_fb(drm_fd, &required_fb); > + > + } > + /* Keep the pattern on output lines for atleast 0.5 secs for > + * DPR-120 to detect it. > + */ > + usleep(1000000); > + > +out: > + if (ret) { > + igt_warn("Failed to set CRTC for connector %u\r\n", > + test_connector->id); > + } > + > + return ret; > +} > + > +static int > +set_default_mode(struct connector *c) > +{ > + unsigned int fb_id = 0; > + struct igt_fb fb_info; > + int ret = 0; > + > + c->mode = c->connector->modes[0]; > + > + if (!c->mode_valid) > + return -1; > + > + width = c->mode.hdisplay; > + height = c->mode.vdisplay; > + > + fb_id = igt_create_pattern_fb(drm_fd, width, height, > + DRM_FORMAT_XRGB8888, > + tiling, &fb_info); > + > + igt_info("CRTC(%u):[%d]", c->crtc, 0); > + kmstest_dump_mode(&c->mode); > + drmModeSetCrtc(drm_fd, c->crtc, -1, 0, 0, NULL, 0, NULL); > + ret = drmModeSetCrtc(drm_fd, c->crtc, fb_id, 0, 0, > + &c->id, 1, &c->mode); > + if (ret) { > + igt_warn("failed to set mode (%dx%d@%dHz): %s\n", width, height, c->mode.vrefresh, strerror(errno)); > + igt_remove_fb(drm_fd, &fb_info); > + > + } > + > + return ret; > +} > + > +/* > + * Re-probe connectors and do a modeset based on test request or > + * in case of a hotplug uevent. > + * > + * @mode: Video mode requested by the test > + * @is_compliance_test: 1: If it is a compliance test > + * 0: If it is a hotplug event > + * > + * Returns: > + * 0: On Success > + * -1: On failure > + */ > +int update_display(int mode, bool is_compliance_test) > +{ > + struct connector *connectors; > + int c, ret = 0; > + unsigned long crtc_idx_mask = -1UL; > + > + resources = drmModeGetResources(drm_fd); > + if (!resources) { > + igt_warn("drmModeGetResources failed: %s\n", strerror(errno)); > + return -1; > + } > + > + connectors = calloc(resources->count_connectors, > + sizeof(struct connector)); > + if (!connectors) > + return -1; > + > + /* Find any connected displays */ > + for (c = 0; c < resources->count_connectors; c++) { > + > + struct connector *connector = &connectors[c]; > + > + connector->id = resources->connectors[c]; > + connector_find_preferred_mode(connector->id, > + crtc_idx_mask, > + connector); > + if (!connector->mode_valid) > + continue; > + if (is_compliance_test) { > + set_test_mode(connector); > + ret = set_video(INTEL_MODE_NONE, connector); > + ret = set_video(mode, connector); > + > + } else > + ret = set_default_mode(connector); > + > + crtc_idx_mask &= ~(1 << connector->pipe); > + > + drmModeFreeEncoder(connector->encoder); > + drmModeFreeConnector(connector->connector); > + > + } > + > + /* Error condition if no connected displays */ > + > + free(connectors); > + drmModeFreeResources(resources); > + return ret; > +} > + > +static const char optstr[] = "hi"; > + > +static void __attribute__((noreturn)) usage(char *name, char opt) > +{ > + igt_info("usage: %s [-hi]\n", name); > + igt_info("\t-i\tdump info\n"); > + igt_info("\tDefault is to respond to DPR-120 tests.\n"); > + exit((opt != 'h') ? -1 : 0); > +} > + > +static void cleanup_debugfs(void) > +{ > + fclose(test_active_fp); > + fclose(test_data_fp); > + fclose(test_type_fp); > +} > + > +static void __attribute__((noreturn)) cleanup_and_exit(int ret) > +{ > + cleanup_debugfs(); > + close(drm_fd); > + igt_info("Compliance testing Application Exiting\n"); > + exit(ret); > +} > + > +static void cleanup_test(void) > +{ > + video_pattern_flag = false; > + hdisplay = 0; > + vdisplay = 0; > + bitdepth = 0; > +} > + > +static void read_test_request(void) > +{ > + unsigned long test_type; > + > + test_type = get_test_type(); > + process_test_request(test_type); > + cleanup_test(); > + clear_test_active(); > +} > + > +static gboolean test_handler(GIOChannel *source, GIOCondition condition, > + gpointer data) > +{ > + unsigned long test_active; > + > + rewind(test_active_fp); > + fscanf(test_active_fp, "%lx", &test_active); > + if (test_active) > + read_test_request(); > + return TRUE; > +} > + > +static gboolean input_event(GIOChannel *source, GIOCondition condition, > + gpointer data) > +{ > + gchar buf[2]; > + gsize count; > + > + count = read(g_io_channel_unix_get_fd(source), buf, sizeof(buf)); > + if (buf[0] == 'q' && (count == 1 || buf[1] == '\n')) { > + cleanup_and_exit(0); > + } > + > + return TRUE; > +} > + > +static void enter_exec_path(char **argv) > +{ > + char *exec_path = NULL; > + char *pos = NULL; > + short len_path = 0; > + int ret; > + > + len_path = strlen(argv[0]); > + exec_path = (char *) malloc(len_path); > + > + memcpy(exec_path, argv[0], len_path); > + pos = strrchr(exec_path, '/'); > + if (pos != NULL) > + *(pos+1) = '\0'; > + > + ret = chdir(exec_path); > + igt_assert_eq(ret, 0); > + free(exec_path); > +} > + > +static void restore_termio_mode(int sig) > +{ > + tcsetattr(tio_fd, TCSANOW, &saved_tio); > + close(tio_fd); > +} > + > +static void set_termio_mode(void) > +{ > + struct termios tio; > + > + /* don't attempt to set terminal attributes if not in the foreground > + * process group > + */ > + if (getpgrp() != tcgetpgrp(STDOUT_FILENO)) > + return; > + > + tio_fd = dup(STDIN_FILENO); > + tcgetattr(tio_fd, &saved_tio); > + igt_install_exit_handler(restore_termio_mode); > + tio = saved_tio; > + tio.c_lflag &= ~(ICANON | ECHO); > + tcsetattr(tio_fd, TCSANOW, &tio); > +} > + > +int main(int argc, char **argv) > +{ > + int c; > + int ret = 0; > + GIOChannel *stdinchannel, *testactive_channel; > + GMainLoop *mainloop; > + bool opt_dump_info = false; > + struct option long_opts[] = { > + {"help-description", 0, 0, HELP_DESCRIPTION}, > + {"help", 0, 0, 'h'}, > + }; > + > + igt_skip_on_simulation(); > + > + enter_exec_path(argv); > + > + while ((c = getopt_long(argc, argv, optstr, long_opts, NULL)) != -1) { > + switch (c) { > + case 'i': > + opt_dump_info = true; > + break; > + case HELP_DESCRIPTION: > + igt_info("DP Compliance Test Suite using DPR-120\n"); > + igt_info("EDID Tests\n"); > + igt_info("Video Pattern Generation Tests\n"); > + exit(0); > + break; > + default: > + /* fall through */ > + case 'h': > + usage(argv[0], c); > + break; > + } > + } > + > + set_termio_mode(); > + > + igt_info("*************DP Compliance Testing using DPR-120*************\n"); > + igt_info("Waiting for Test Request Input......\n"); > + drm_fd = drm_open_driver(DRIVER_ANY); > + > + if (opt_dump_info) { > + dump_info(); > + goto out_close; > + } > + > + kmstest_set_vt_graphics_mode(); > + setup_debugfs_files(); > + cleanup_test(); > + > + mainloop = g_main_loop_new(NULL, FALSE); > + if (!mainloop) { > + igt_warn("failed to create glib mainloop\n"); > + ret = -1; > + goto out_close; > + } > + > + if (!intel_dp_compliance_setup_hotplug()) { > + igt_warn("failed to initialize hotplug support\n"); > + goto out_mainloop; > + } > + > + testactive_channel = g_io_channel_unix_new(fileno(test_active_fp)); > + if (!testactive_channel) { > + igt_warn("failed to create Test Active GIO channel\n"); > + goto out_close; > + } > + > + ret = g_io_add_watch(testactive_channel, G_IO_IN | G_IO_ERR, test_handler, > + NULL); > + if (ret < 0) { > + igt_warn("failed to add watch on udev GIO channel\n"); > + goto out_close; > + } > + > + stdinchannel = g_io_channel_unix_new(0); > + if (!stdinchannel) { > + igt_warn("failed to create stdin GIO channel\n"); > + goto out_hotplug; > + } > + > + ret = g_io_add_watch(stdinchannel, G_IO_IN | G_IO_ERR, input_event, > + NULL); > + if (ret < 0) { > + igt_warn("failed to add watch on stdin GIO channel\n"); > + goto out_stdio; > + } > + > + ret = 0; > + > + g_main_loop_run(mainloop); > + > +out_stdio: > + g_io_channel_shutdown(stdinchannel, TRUE, NULL); > +out_hotplug: > + intel_dp_compliance_cleanup_hotplug(); > +out_mainloop: > + g_main_loop_unref(mainloop); > +out_close: > + cleanup_debugfs(); > + close(drm_fd); > + > + igt_assert_eq(ret, 0); > + > + igt_info("Compliance testing application exiting.\n"); > + igt_exit(); > +} > diff --git a/tools/intel_dp_compliance.h b/tools/intel_dp_compliance.h > new file mode 100644 > index 0000000..ade1e2f > --- /dev/null > +++ b/tools/intel_dp_compliance.h > @@ -0,0 +1,35 @@ > +/* > + * Copyright 2010 Intel Corporation > + * Manasi Navare <manasi.d.navare@xxxxxxxxx> > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice shall be included in > + * all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE > + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS > + * IN THE SOFTWARE. > + */ > + > +#include <stdio.h> > +#include <string.h> > +#include <stdlib.h> > +#include <glib.h> > + > +extern int drm_fd; > + > +gboolean intel_dp_compliance_setup_hotplug(void); > +void intel_dp_compliance_cleanup_hotplug(void); > + > +/* called by the hotplug code */ > +int update_display(int mode, bool is_compliance_test); > diff --git a/tools/intel_dp_compliance_hotplug.c b/tools/intel_dp_compliance_hotplug.c > new file mode 100644 > index 0000000..d489026 > --- /dev/null > +++ b/tools/intel_dp_compliance_hotplug.c > @@ -0,0 +1,123 @@ > +/* > + * Copyright 2010 Intel Corporation > + * Jesse Barnes <jesse.barnes@xxxxxxxxx> > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice shall be included in > + * all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE > + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS > + * IN THE SOFTWARE. > + */ > + > +#include "igt.h" > +#include <stdio.h> > +#include <string.h> > +#include <stdlib.h> > + > +#include <sys/stat.h> > + > +#include "intel_dp_compliance.h" > +#include <libudev.h> > +static struct udev_monitor *uevent_monitor; > +static struct udev *udev; > +static GIOChannel *udevchannel; > + > +static gboolean hotplug_event(GIOChannel *source, GIOCondition condition, > + gpointer data) > +{ > + struct udev_device *dev; > + dev_t udev_devnum; > + struct stat s; > + const char *hotplug; > + > + dev = udev_monitor_receive_device(uevent_monitor); > + if (!dev) > + goto out; > + > + udev_devnum = udev_device_get_devnum(dev); > + fstat(drm_fd, &s); > + > + hotplug = udev_device_get_property_value(dev, "HOTPLUG"); > + > + if (memcmp(&s.st_rdev, &udev_devnum, sizeof(dev_t)) == 0 && > + hotplug && atoi(hotplug) == 1) > + update_display(0, false); > + > + udev_device_unref(dev); > +out: > + return TRUE; > +} > + > + > +gboolean intel_dp_compliance_setup_hotplug(void) > +{ > + int ret; > + > + udev = udev_new(); > + if (!udev) { > + igt_warn("failed to create udev object\n"); > + goto out; > + } > + > + uevent_monitor = udev_monitor_new_from_netlink(udev, "udev"); > + if (!uevent_monitor) { > + igt_warn("failed to create udev event monitor\n"); > + goto out; > + } > + > + ret = udev_monitor_filter_add_match_subsystem_devtype(uevent_monitor, > + "drm", > + "drm_minor"); > + if (ret < 0) { > + igt_warn("failed to filter for drm events\n"); > + goto out; > + } > + > + ret = udev_monitor_enable_receiving(uevent_monitor); > + if (ret < 0) { > + igt_warn("failed to enable udev event reception\n"); > + goto out; > + } > + > + udevchannel = > + g_io_channel_unix_new(udev_monitor_get_fd(uevent_monitor)); > + if (!udevchannel) { > + igt_warn("failed to create udev GIO channel\n"); > + goto out; > + } > + > + ret = g_io_add_watch(udevchannel, G_IO_IN | G_IO_ERR, hotplug_event, > + udev); > + if (ret < 0) { > + igt_warn("failed to add watch on udev GIO channel\n"); > + goto out; > + } > + > + return TRUE; > + > +out: > + intel_dp_compliance_cleanup_hotplug(); > + return FALSE; > +} > + > +void intel_dp_compliance_cleanup_hotplug(void) > +{ > + if (udevchannel) > + g_io_channel_shutdown(udevchannel, TRUE, NULL); > + if (uevent_monitor) > + udev_monitor_unref(uevent_monitor); > + if (udev) > + udev_unref(udev); > +} -- Jani Nikula, Intel Open Source Technology Center _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx