## Chamelium Chamelium — Library for using the Chamelium into igt tests |

## Functions

struct chamelium * | chamelium_init ()
void | chamelium_deinit ()
void | chamelium_reset ()
struct chamelium_port ** | chamelium_get_ports ()
drmModeConnector * | chamelium_port_get_connector ()
const char * | chamelium_port_get_name ()
void | chamelium_plug ()
void | chamelium_unplug ()
bool | chamelium_is_plugged ()
bool | chamelium_port_wait_video_input_stable ()
void | chamelium_fire_mixed_hpd_pulses ()
void | chamelium_fire_hpd_pulses ()
void | chamelium_schedule_hpd_toggle ()
int | chamelium_new_edid ()
void | chamelium_port_set_edid ()
bool | chamelium_port_get_ddc_state ()
void | chamelium_port_set_ddc_state ()
void | chamelium_port_get_resolution ()
igt_crc_t * | chamelium_get_crc_for_area ()
void | chamelium_start_capture ()
void | chamelium_stop_capture ()
void | chamelium_capture ()
igt_crc_t * | chamelium_read_captured_crcs ()
struct chamelium_frame_dump * | chamelium_read_captured_frame ()
struct chamelium_frame_dump * | chamelium_port_dump_pixels ()
igt_crc_t * | chamelium_calculate_fb_crc ()
struct chamelium_fb_crc_async_data * | chamelium_calculate_fb_crc_async_start ()
igt_crc_t * | chamelium_calculate_fb_crc_async_finish ()
int | chamelium_get_captured_frame_count ()
int | chamelium_get_frame_limit ()
void | chamelium_assert_frame_eq ()
void | chamelium_assert_crc_eq_or_dump ()
void | chamelium_assert_analog_frame_match_or_dump ()
void | chamelium_crop_analog_frame ()
void | chamelium_destroy_frame_dump ()

## Types and Values

struct | chamelium
struct | chamelium_fb_crc_async_data
struct | chamelium_frame_dump
struct | chamelium_port
struct | igt_fb

## Includes

    #include <igt_chamelium.h>

## Description

This library contains helpers for using Chameliums in IGT tests. This allows for tests to simulate more difficult tasks to automate such as display hotplugging, faulty display behaviors, etc.

More information on the Chamelium can be found on the ChromeOS project page.

In order to run tests using the Chamelium, a valid configuration file must be present. It must contain Chamelium-specific keys as shown with the following example:

    [Chamelium]
    URL=http://chameleon:9992 # The URL used for connecting to the Chamelium's RPC server

    # The rest of the sections are used for defining connector mappings.
    # This is required so any tests using the Chamelium know which connector
    # on the test machine should be connected to each Chamelium port.
    #
    # In the event that any of these mappings are specified incorrectly,
    # any hotplugging tests for the incorrect connector mapping will fail.

    [Chamelium:DP-1] # The name of the DRM connector
    ChameliumPortID=1 # The ID of the port on the Chamelium this connector is attached to

    [Chamelium:HDMI-A-1]
    ChameliumPortID=3

## Functions

### chamelium_init ()

    struct chamelium *
    chamelium_init (int drm_fd);

Sets up a connection with a chamelium, using the URL specified in the Chamelium configuration. This must be called first before trying to use the chamelium.

If we fail to establish a connection with the chamelium, fail to find a configured connector, etc. we fail the current test.

#### Parameters

chamelium | The Chamelium instance to use |
drm_fd | a display initialized with igt_display_init |

#### Returns

A newly initialized chamelium struct, or NULL on error

### chamelium_deinit ()

    void
    chamelium_deinit (struct chamelium *chamelium);

Frees the resources used by a connection to the chamelium that was set up with chamelium_init. As well, this function restores the state of the chamelium like it was before calling chamelium_init. This function is also called as an exit handler, so users only need to call manually if they don't want the chamelium interfering with other tests in the same file.

#### Parameters

chamelium | The Chamelium instance to use |

### chamelium_reset ()

    void
    chamelium_reset (struct chamelium *chamelium);

Resets the chamelium's IO board. As well, this also has the effect of causing all of the chamelium ports to get set to unplugged

#### Parameters

chamelium | The Chamelium instance to use |

### chamelium_get_ports ()

    struct chamelium_port **
    chamelium_get_ports (struct chamelium *chamelium,
                         int *count);

Retrieves all of the ports currently configured for use with this chamelium

#### Parameters

chamelium | The Chamelium instance to use |
count | Where to store the number of ports |

#### Returns

an array containing a pointer to each configured chamelium port

### chamelium_port_get_connector ()

    drmModeConnector *
    chamelium_port_get_connector (struct chamelium *chamelium,
                                  struct chamelium_port *port,
                                  bool reprobe);

Get a drmModeConnector object for the given Chamelium port, and optionally reprobe the port in the process

#### Parameters

chamelium | The Chamelium instance to use |
port | The chamelium port to retrieve the DRM connector for |
reprobe | Whether or not to reprobe the DRM connector |

#### Returns

a drmModeConnector object corresponding to the given port

### chamelium_port_get_name ()

    const char *
    chamelium_port_get_name (struct chamelium_port *port);

Gets the name of the DRM connector corresponding to the given Chamelium port.

#### Parameters

port | The chamelium port to retrieve the name of |

#### Returns

the name of the DRM connector

### chamelium_plug ()

    void
    chamelium_plug (struct chamelium *chamelium,
                    struct chamelium_port *port);

Simulate a display connector being plugged into the system using the chamelium.

#### Parameters

chamelium | The Chamelium instance to use |
port | The port on the chamelium to plug |

### chamelium_unplug ()

    void
    chamelium_unplug (struct chamelium *chamelium,
                      struct chamelium_port *port);

Simulate a display connector being unplugged from the system using the chamelium.

#### Parameters

chamelium | The Chamelium instance to use |
port | The port on the chamelium to unplug |

### chamelium_is_plugged ()

    bool
    chamelium_is_plugged (struct chamelium *chamelium,
                          struct chamelium_port *port);

Check whether or not the given port has been plugged into the system using chamelium_plug.

#### Parameters

chamelium | The Chamelium instance to use |
port | The port on the Chamelium to check the status of |

#### Returns

`true` if the connector is set to plugged in, `false` otherwise.

### chamelium_port_wait_video_input_stable ()

    bool
    chamelium_port_wait_video_input_stable
                                   (struct chamelium *chamelium,
                                    struct chamelium_port *port,
                                    int timeout_secs);

Waits for a video signal to appear on the given port. This is useful for checking whether or not we've setup a monitor correctly.

#### Parameters

chamelium | The Chamelium instance to use |
port | The port on the Chamelium to check the status of |
timeout_secs | How long to wait for a video signal to appear before timing out |

#### Returns

`true` if a video signal was detected, `false` if we timed out

### chamelium_fire_mixed_hpd_pulses ()

    void
    chamelium_fire_mixed_hpd_pulses (struct chamelium *chamelium,
                                     struct chamelium_port *port,
                                     ...);

Does the same thing as chamelium_fire_hpd_pulses, but allows the caller to specify the length of each individual pulse.

#### Parameters

chamelium | The Chamelium instance to use |
port | The port to fire the HPD pulses on |
... | The length of each pulse in milliseconds, terminated with a `0` |

### chamelium_fire_hpd_pulses ()

    void
    chamelium_fire_hpd_pulses (struct chamelium *chamelium,
                               struct chamelium_port *port,
                               int width_msec,
                               int count);

A convienence function for sending multiple hotplug pulses to the system. The pulses start at low (e.g. connector is disconnected), and then alternate from high (e.g. connector is plugged in) to low. This is the equivalent of repeatedly calling chamelium_plug and chamelium_unplug, waiting `width_msec` between each call.

If `count` is even, the last pulse sent will be high, and if it's odd then it will be low. Resetting the HPD line back to it's previous state, if desired, is the responsibility of the caller.

#### Parameters

chamelium | The Chamelium instance to use |
port | The port to fire the HPD pulses on |
width_msec | How long each pulse should last |
count | The number of pulses to send |

### chamelium_schedule_hpd_toggle ()

    void
    chamelium_schedule_hpd_toggle (struct chamelium *chamelium,
                                   struct chamelium_port *port,
                                   int delay_ms,
                                   bool rising_edge);

Instructs the chamelium to schedule an hpd toggle (either a rising edge or a falling edge, depending on `rising_edg` ) after `delay_ms` have passed. This is useful for testing things such as hpd after a suspend/resume cycle.

#### Parameters

chamelium | The Chamelium instance to use |
port | The port to fire the HPD pulses on |
delay_ms | Delay in milli-second before the toggle takes place |
rising_edge | Whether the toggle should be a rising edge or a falling edge |

### chamelium_new_edid ()

    int
    chamelium_new_edid (struct chamelium *chamelium,
                        const unsigned char *edid);

Uploads and registers a new EDID with the chamelium. The EDID will be destroyed automatically when chamelium_deinit is called.

#### Parameters

chamelium | The Chamelium instance to use |
edid | The edid blob to upload to the chamelium |

#### Returns

The ID of the EDID uploaded to the chamelium.

### chamelium_port_set_edid ()

    void
    chamelium_port_set_edid (struct chamelium *chamelium,
                             struct chamelium_port *port,
                             int edid_id);

Sets a port on the chamelium to use the specified EDID. This does not fire a hotplug pulse on it's own, and merely changes what EDID the chamelium port will report to us the next time we probe it. Users will need to reprobe the connectors themselves if they want to see the EDID reported by the port change.

#### Parameters

chamelium | The Chamelium instance to use |
port | The port on the Chamelium to set the EDID on |
edid_id | The ID of an EDID on the chamelium created with chamelium_new_edid, or 0 to disable the EDID on the port |

### chamelium_port_get_ddc_state ()

    bool
    chamelium_port_get_ddc_state (struct chamelium *chamelium,
                                  struct chamelium_port *port);

Check whether or not the DDC bus on the specified chamelium port is enabled or not.

#### Parameters

chamelium | The Chamelium instance to use |
port | The port on the Chamelium to check the status of |

#### Returns

`true` if the DDC bus is enabled, `false` otherwise.

### chamelium_port_set_ddc_state ()

    void
    chamelium_port_set_ddc_state (struct chamelium *chamelium,
                                  struct chamelium_port *port,
                                  bool enabled);

This disables the DDC bus (e.g. the i2c line on the connector that gives us an EDID) of the specified port on the chamelium. This is useful for testing behavior on legacy connectors such as VGA, where the presence of a DDC bus is not always guaranteed.

#### Parameters

chamelium | The Chamelium instance to use |
port | The port to change the DDC state on |
enabled | Whether or not to enable the DDC bus |

### chamelium_port_get_resolution ()

    void
    chamelium_port_get_resolution (struct chamelium *chamelium,
                                   struct chamelium_port *port,
                                   int *x,
                                   int *y);

Check the current reported display resolution of the specified port on the chamelium. This information is provided by the chamelium itself, not DRM. Useful for verifying that we really are scanning out at the resolution we think we are.

#### Parameters

chamelium | The Chamelium instance to use |
port | The port on the Chamelium to check |
x | Where to store the horizontal resolution of the port |
y | Where to store the verical resolution of the port |

### chamelium_get_crc_for_area ()

    igt_crc_t *
    chamelium_get_crc_for_area (struct chamelium *chamelium,
                                struct chamelium_port *port,
                                int x,
                                int y,
                                int w,
                                int h);

Reads back the pixel CRC for an area on the specified chamelium port. This is the same as using the CRC readback from a GPU, the main difference being the data is provided by the chamelium and also allows us to specify a region of the screen to use as opposed to the entire thing.

As an important note: some of the EDIDs provided by the Chamelium cause certain GPU drivers to default to using limited color ranges. This can cause video captures from the Chamelium to provide different images then expected due to the difference in color ranges (framebuffer uses full color range, but the video output doesn't), and as a result lead to CRC mismatches. To workaround this, the caller should force the connector to use full color ranges by using kmstest_set_connector_broadcast_rgb before setting up the display.

After the caller is finished with the EDID returned by this function, the caller should manually free the resources associated with it.

#### Parameters

chamelium | The Chamelium instance to use |
port | The port to perform the CRC checking on |
x | The X coordinate on the emulated display to start calculating the CRC from |
y | The Y coordinate on the emulated display to start calculating the CRC from |
w | The width of the area to fetch the CRC from, or `0` for the whole display |
h | The height of the area to fetch the CRC from, or `0` for the whole display |

#### Returns

The CRC read back from the chamelium

### chamelium_start_capture ()

    void
    chamelium_start_capture (struct chamelium *chamelium,
                             struct chamelium_port *port,
                             int x,
                             int y,
                             int w,
                             int h);

Starts capturing video frames on the given Chamelium port. Once the user is finished capturing frames, they should call chamelium_stop_capture.

A blocking, one-shot version of this function is available: see chamelium_capture

As an important note: some of the EDIDs provided by the Chamelium cause certain GPU drivers to default to using limited color ranges. This can cause video captures from the Chamelium to provide different images then expected due to the difference in color ranges (framebuffer uses full color range, but the video output doesn't), and as a result lead to CRC and frame dump comparison mismatches. To workaround this, the caller should force the connector to use full color ranges by using kmstest_set_connector_broadcast_rgb before setting up the display.

#### Parameters

chamelium | The Chamelium instance to use |
port | The port to perform the video capture on |
x | The X coordinate to crop the video to |
y | The Y coordinate to crop the video to |
w | The width of the cropped video, or `0` for the whole display |
h | The height of the cropped video, or `0` for the whole display |

### chamelium_stop_capture ()

    void
    chamelium_stop_capture (struct chamelium *chamelium,
                            int frame_count);

Finishes capturing video frames on the given Chamelium port. If `frame_count` is specified, this call will block until the given number of frames have been captured.

#### Parameters

chamelium | The Chamelium instance to use |
frame_count | The number of frames to wait to capture, or `0` to stop immediately |

### chamelium_capture ()

    void
    chamelium_capture (struct chamelium *chamelium,
                       struct chamelium_port *port,
                       int x,
                       int y,
                       int w,
                       int h,
                       int frame_count);

Captures the given number of frames on the chamelium. This is equivalent to calling chamelium_start_capture immediately followed by chamelium_stop_capture. The caller is blocked until all of the frames have been captured.

As an important note: some of the EDIDs provided by the Chamelium cause certain GPU drivers to default to using limited color ranges. This can cause video captures from the Chamelium to provide different images then expected due to the difference in color ranges (framebuffer uses full color range, but the video output doesn't), and as a result lead to CRC and frame dump comparison mismatches. To workaround this, the caller should force the connector to use full color ranges by using kmstest_set_connector_broadcast_rgb before setting up the display.

#### Parameters

chamelium | The Chamelium instance to use |
port | The port to perform the video capture on |
x | The X coordinate to crop the video to |
y | The Y coordinate to crop the video to |
w | The width of the cropped video, or `0` for the whole display |
h | The height of the cropped video, or `0` for the whole display |
frame_count | The number of frames to capture |

### chamelium_read_captured_crcs ()

    igt_crc_t *
    chamelium_read_captured_crcs (struct chamelium *chamelium,
                                  int *frame_count);

Reads all of the CRCs that have been captured thus far from the Chamelium.

#### Parameters

chamelium | The Chamelium instance to use |
frame_count | Where to store the number of CRCs we read in |

#### Returns

An array of `frame_count` length containing all of the CRCs we read

### chamelium_read_captured_frame ()

    struct chamelium_frame_dump *
    chamelium_read_captured_frame (struct chamelium *chamelium,
                                   unsigned int index);

### chamelium_port_dump_pixels ()

    struct chamelium_frame_dump *
    chamelium_port_dump_pixels (struct chamelium *chamelium,
                                struct chamelium_port *port,
                                int x,
                                int y,
                                int w,
                                int h);

Captures the currently displayed image on the given chamelium port, optionally cropped to a given region. In situations where pre-calculating CRCs may not be reliable, this can be used as an alternative for figuring out whether or not the correct images are being displayed on the screen.

The frame dump data returned by this function should be freed when the caller is done with it using chamelium_destroy_frame_dump.

As an important note: some of the EDIDs provided by the Chamelium cause certain GPU drivers to default to using limited color ranges. This can cause video captures from the Chamelium to provide different images then expected due to the difference in color ranges (framebuffer uses full color range, but the video output doesn't), and as a result lead to CRC mismatches. To workaround this, the caller should force the connector to use full color ranges by using kmstest_set_connector_broadcast_rgb before setting up the display.

#### Parameters

chamelium | The Chamelium instance to use |
port | The port to perform the video capture on |
x | The X coordinate to crop the screen capture to |
y | The Y coordinate to crop the screen capture to |
w | The width of the area to crop the screen capture to, or 0 for the whole screen |
h | The height of the area to crop the screen capture to, or 0 for the whole screen |

#### Returns

a chamelium_frame_dump struct

### chamelium_calculate_fb_crc ()

    igt_crc_t *
    chamelium_calculate_fb_crc (int fd,
                                struct igt_fb *fb);

Calculates the CRC for the provided framebuffer, using the Chamelium's CRC algorithm. This calculates the CRC in a synchronous fashion.

#### Parameters

fd | The drm file descriptor |
fb | The framebuffer to calculate the CRC for |

#### Returns

The calculated CRC

### chamelium_calculate_fb_crc_async_start ()

    struct chamelium_fb_crc_async_data *
    chamelium_calculate_fb_crc_async_start
                                   (int fd,
                                    struct igt_fb *fb);

### chamelium_calculate_fb_crc_async_finish ()

    igt_crc_t *
    chamelium_calculate_fb_crc_async_finish
                                   (struct chamelium_fb_crc_async_data *fb_crc);

### chamelium_get_captured_frame_count ()

    int
    chamelium_get_captured_frame_count (struct chamelium *chamelium);

Gets the number of frames that were captured during the last video capture.

#### Parameters

chamelium | The Chamelium instance to use |

#### Returns

the number of frames the Chamelium captured during the last video capture.

### chamelium_get_frame_limit ()

    int
    chamelium_get_frame_limit (struct chamelium *chamelium,
                               struct chamelium_port *port,
                               int w,
                               int h);

Gets the max number of frames we can capture with the Chamelium for the given resolution.

#### Parameters

chamelium | The Chamelium instance to use |
port | The port to check the frame limit on |
w | The width of the area to get the capture frame limit for, or `0` for the whole display |
h | The height of the area to get the capture frame limit for, or `0` for the whole display |

#### Returns

The number of the max number of frames we can capture

### chamelium_assert_frame_eq ()

    void
    chamelium_assert_frame_eq (const struct chamelium *chamelium,
                               const struct chamelium_frame_dump *dump,
                               struct igt_fb *fb);

Asserts that the image contained in the chamelium frame dump is identical to the given framebuffer. Useful for scenarios where pre-calculating CRCs might not be ideal.

#### Parameters

chamelium | The chamelium instance the frame dump belongs to |
dump | The chamelium frame dump to check |
fb | The framebuffer to check against |

### chamelium_assert_crc_eq_or_dump ()

    void
    chamelium_assert_crc_eq_or_dump (struct chamelium *chamelium,
                                     igt_crc_t *reference_crc,
                                     igt_crc_t *capture_crc,
                                     struct igt_fb *fb,
                                     int index);

Asserts that the CRC provided for both the reference and the captured frame are identical. If they are not, this grabs the captured frame and saves it along with the reference to a png file.

#### Parameters

chamelium | The chamelium instance the frame dump belongs to |
reference_crc | The CRC for the reference frame |
capture_crc | The CRC for the captured frame |
fb | pointer to an igt_fb structure |

### chamelium_assert_analog_frame_match_or_dump ()

    void
    chamelium_assert_analog_frame_match_or_dump
                                   (struct chamelium *chamelium,
                                    struct chamelium_port *port,
                                    const struct chamelium_frame_dump *frame,
                                    struct igt_fb *fb);

Asserts that the provided captured frame matches the reference frame from the framebuffer. If they do not, this saves the reference and captured frames to a png file.

#### Parameters

chamelium | The chamelium instance the frame dump belongs to |
frame | The chamelium frame dump to match |
fb | pointer to an igt_fb structure |

### chamelium_crop_analog_frame ()

    void
    chamelium_crop_analog_frame (struct chamelium_frame_dump *dump,
                                 int width,
                                 int height);

### chamelium_destroy_frame_dump ()

    void
    chamelium_destroy_frame_dump (struct chamelium_frame_dump *dump);

Destroys the given frame dump and frees all of the resources associated with it.

#### Parameters

dump | The frame dump to destroy |

## Types and Values

### struct chamelium

    struct chamelium;

### struct chamelium_fb_crc_async_data

    struct chamelium_fb_crc_async_data;

### struct chamelium_frame_dump

    struct chamelium_frame_dump;

### struct chamelium_port

    struct chamelium_port;

### struct igt_fb

    struct igt_fb;