Commit c99f8b7a authored by Lyude Paul's avatar Lyude Paul

Add support for hotplug testing with the Chamelium

For the purpose of testing things such as hotplugging and bad monitors,
the ChromeOS team ended up designing a neat little device known as the
Chamelium. More information on this can be found here:

	https://www.chromium.org/chromium-os/testing/chamelium

This adds support for a couple of things to intel-gpu-tools:
 - igt library functions for connecting to udev and monitoring it for
   hotplug events, loosely based off of the unfinished hotplugging
   implementation in testdisplay
 - Library functions for controlling the chamelium in tests using
   xmlrpc. A couple of RPC calls were ommitted here, mainly because they
   didn't seem very useful for our needs (yet)
 - A set of functions for doing CRC checks and frame comparisons in
   tests
 - A set of basic tests using the Chamelium library.

Cc: Tomeu Vizoso <tomeu@tomeuvizoso.net>
Signed-off-by: Lyude Paul's avatarLyude <lyude@redhat.com>

Changes since v1:
- Don't try to guess connector mappings, have the user specify them
  manually using a configuration file
- Open DRM fd using DRIVER_ANY, not DRIVER_INTEL
- Lower the hotplug timeout a little bit, since 30 seconds was leftover
  from debugging these tests anyway
- Don't try to keep track of the original state of the chamelium ports,
  and just leave them plugged in after each run. This makes more sense
  to me, since I'd imagine in automated testing setups using chameliums
  that all of the extra monitors will probably be provided by the
  Chamelium to begin with, so keeping them plugged in would make sure
  tests running afterwards that require >1 monitor don't get skipped.
- Add wait_for_connector() to the chamelium tests. After some more
  testing, I found that depending on the system some tests would throw
  false negatives due to us not waiting long enough for the system to
  detect that we connected something to it. This mainly happened with
  VGA connectors, since their lack of HPD makes them take significantly
  longer for the hardware to notice. wait_for_connector() fixes this by
  continually reprobing the status of the desired connector (without
  relying on a hpd event happening, since that might never come) until
  we get what we want, or we time out and fail.
- Use kmstest_get_property() for retrieving EDIDs instead of doing it by
  hand
- Don't hardcode PIPE_A for bringing up the display, use kmstest to find
  an appropriate CRTC to use.
Changes since v2:
- Fix incorrect usage of the list helpers when recording new EDIDs
- Add missing documentation
- Make sure documentation actually appears
- Since we finally got video capture working, add CRC functions and fix
  the ones we couldn't actually test before
- In the exit handler, reset the xmlrpc env so we can properly reset the
  Chamelium even after an RPC error
- Make sure compiling without Chamelium support still works
Changes since v3:
- Change the config file name from .igt_chamelium_rc to .igtrc
- Remove chamelium global context
- Get rid of define_common_connector_tests()
- Get rid of connector list, expose connectors as opaque objects and
  provide helpers for accessing their attributes
- Get rid of configure.ac option for Chamelium
- Add tests for CRC functions
- Add frame dumping functions + tests
- Add FSM handling to chamelium_rpc()
- Use LIBUDEV_LIBS in automake, not UDEV_LIBS
- Documentation fixes
- Improve debugging output some more
- Remove skip_without_suspend_support, we no longer need to check for
  suspend support before calling things
- Remove unnessecary malloc() checks with igt_assert()
- Don't use igt_require in chamelium_init, leave it up to the caller
  whether or not to abort when failing to initialize the chamelium
- Use igt_assert_eq for making assertions about connector's statuses
- Define suspend/resume delay for tests as constant
parent 3bd89da2
......@@ -170,6 +170,10 @@ if test x"$udev" = xyes; then
fi
PKG_CHECK_MODULES(GLIB, glib-2.0)
# for chamelium
PKG_CHECK_MODULES(XMLRPC, xmlrpc_client)
PKG_CHECK_MODULES(PIXMAN, pixman-1)
# -----------------------------------------------------------------------------
# Configuration options
# -----------------------------------------------------------------------------
......
......@@ -34,6 +34,7 @@
<xi:include href="xml/igt_vc4.xml"/>
<xi:include href="xml/igt_vgem.xml"/>
<xi:include href="xml/igt_dummyload.xml"/>
<xi:include href="xml/igt_chamelium.xml"/>
</chapter>
<xi:include href="xml/igt_test_programs.xml"/>
......
......@@ -31,6 +31,9 @@ AM_CFLAGS = \
$(KMOD_CFLAGS) \
$(PROCPS_CFLAGS) \
$(DEBUG_CFLAGS) \
$(XMLRPC_CFLAGS) \
$(LIBUDEV_CFLAGS) \
$(PIXMAN_CFLAGS) \
-DIGT_SRCDIR=\""$(abs_top_srcdir)/tests"\" \
-DIGT_DATADIR=\""$(pkgdatadir)"\" \
-DIGT_LOG_DOMAIN=\""$(subst _,-,$*)"\" \
......@@ -47,5 +50,8 @@ libintel_tools_la_LIBADD = \
$(LIBUDEV_LIBS) \
$(LIBUNWIND_LIBS) \
$(TIMER_LIBS) \
$(XMLRPC_LIBS) \
$(LIBUDEV_LIBS) \
$(PIXMAN_LIBS) \
-lm
......@@ -83,6 +83,8 @@ lib_source_list = \
uwildmat/uwildmat.c \
igt_kmod.c \
igt_kmod.h \
igt_chamelium.h \
igt_chamelium.c \
$(NULL)
.PHONY: version.h.tmp
......
......@@ -38,6 +38,7 @@
#include "igt_kms.h"
#include "igt_pm.h"
#include "igt_stats.h"
#include "igt_chamelium.h"
#include "instdone.h"
#include "intel_batchbuffer.h"
#include "intel_chipset.h"
......
This diff is collapsed.
/*
* Copyright © 2016 Red Hat Inc.
*
* 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 (including the next
* paragraph) 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.
*
* Authors: Lyude Paul <lyude@redhat.com>
*/
#ifndef IGT_CHAMELIUM_H
#define IGT_CHAMELIUM_H
#include "config.h"
#include "igt.h"
#include <stdbool.h>
struct chamelium;
struct chamelium_port;
struct chamelium_frame_dump;
struct chamelium *chamelium_init(int drm_fd);
void chamelium_deinit(struct chamelium *chamelium);
void chamelium_reset(struct chamelium *chamelium);
struct chamelium_port **chamelium_get_ports(struct chamelium *chamelium,
int *count);
unsigned int chamelium_port_get_type(const struct chamelium_port *port);
drmModeConnector *chamelium_port_get_connector(struct chamelium *chamelium,
struct chamelium_port *port,
bool reprobe);
const char *chamelium_port_get_name(struct chamelium_port *port);
void chamelium_plug(struct chamelium *chamelium, struct chamelium_port *port);
void chamelium_unplug(struct chamelium *chamelium, struct chamelium_port *port);
bool chamelium_is_plugged(struct chamelium *chamelium,
struct chamelium_port *port);
bool chamelium_port_wait_video_input_stable(struct chamelium *chamelium,
struct chamelium_port *port,
int timeout_secs);
void chamelium_fire_mixed_hpd_pulses(struct chamelium *chamelium,
struct chamelium_port *port, ...);
void chamelium_fire_hpd_pulses(struct chamelium *chamelium,
struct chamelium_port *port,
int width_msec, int count);
void chamelium_async_hpd_pulse_start(struct chamelium *chamelium,
struct chamelium_port *port,
bool high, int delay_secs);
void chamelium_async_hpd_pulse_finish(struct chamelium *chamelium);
int chamelium_new_edid(struct chamelium *chamelium, const unsigned char *edid);
void chamelium_port_set_edid(struct chamelium *chamelium,
struct chamelium_port *port, int edid_id);
bool chamelium_port_get_ddc_state(struct chamelium *chamelium,
struct chamelium_port *port);
void chamelium_port_set_ddc_state(struct chamelium *chamelium,
struct chamelium_port *port,
bool enabled);
void chamelium_port_get_resolution(struct chamelium *chamelium,
struct chamelium_port *port,
int *x, int *y);
igt_crc_t *chamelium_get_crc_for_area(struct chamelium *chamelium,
struct chamelium_port *port,
int x, int y, int w, int h);
void chamelium_start_capture(struct chamelium *chamelium,
struct chamelium_port *port,
int x, int y, int w, int h);
void chamelium_stop_capture(struct chamelium *chamelium, int frame_count);
void chamelium_capture(struct chamelium *chamelium, struct chamelium_port *port,
int x, int y, int w, int h, int frame_count);
igt_crc_t *chamelium_read_captured_crcs(struct chamelium *chamelium,
int *frame_count);
struct chamelium_frame_dump *chamelium_read_captured_frame(struct chamelium *chamelium,
unsigned int index);
struct chamelium_frame_dump *chamelium_port_dump_pixels(struct chamelium *chamelium,
struct chamelium_port *port,
int x, int y,
int w, int h);
int chamelium_get_captured_frame_count(struct chamelium *chamelium);
int chamelium_get_frame_limit(struct chamelium *chamelium,
struct chamelium_port *port,
int w, int h);
void chamelium_assert_frame_eq(const struct chamelium *chamelium,
const struct chamelium_frame_dump *dump,
struct igt_fb *fb);
void chamelium_destroy_frame_dump(struct chamelium_frame_dump *dump);
#endif /* IGT_CHAMELIUM_H */
......@@ -62,7 +62,7 @@ AM_CFLAGS = $(DRM_CFLAGS) $(CWARNFLAGS) -Wno-unused-result $(DEBUG_CFLAGS)\
$(LIBUNWIND_CFLAGS) $(WERROR_CFLAGS) \
$(NULL)
LDADD = ../lib/libintel_tools.la $(GLIB_LIBS)
LDADD = ../lib/libintel_tools.la $(GLIB_LIBS) $(XMLRPC_LIBS)
AM_CFLAGS += $(CAIRO_CFLAGS) $(LIBUDEV_CFLAGS) $(GLIB_CFLAGS)
AM_LDFLAGS = -Wl,--as-needed
......@@ -118,5 +118,8 @@ vc4_wait_bo_CFLAGS = $(AM_CFLAGS) $(DRM_VC4_CFLAGS)
vc4_wait_bo_LDADD = $(LDADD) $(DRM_VC4_LIBS)
vc4_wait_seqno_CFLAGS = $(AM_CFLAGS) $(DRM_VC4_CFLAGS)
vc4_wait_seqno_LDADD = $(LDADD) $(DRM_VC4_LIBS)
chamelium_CFLAGS = $(AM_CFLAGS) $(XMLRPC_CFLAGS) $(LIBUDEV_CFLAGS)
chamelium_LDADD = $(LDADD) $(XMLRPC_LIBS) $(LIBUDEV_LIBS)
endif
......@@ -142,6 +142,7 @@ TESTS_progs_M = \
template \
vgem_basic \
vgem_slow \
chamelium \
$(NULL)
TESTS_progs_XM = \
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment