[v2,5/5] drm: Add decoding of DRM and KMS ioctls
diff mbox

Message ID 1434616965-5157-6-git-send-email-patrik.jakobsson@linux.intel.com
State New
Headers show

Commit Message

Patrik Jakobsson June 18, 2015, 8:42 a.m. UTC
This patch adds many of the DRM and KMS ioctls. The rest can be added as
needed.

* drm.c: Decode DRM_IOCTL_VERSION
* drm.c: Decode DRM_IOCTL_GET_UNIQUE
* drm.c: Decode DRM_IOCTL_GET_MAGIC
* drm.c: Decode DRM_IOCTL_WAIT_VBLANK
* drm.c: Decode DRM_IOCTL_MODE_GETRESOURCES
* drm.c: Decode DRM_IOCTL_MODE_GETCRTC
* drm.c: Decode DRM_IOCTL_MODE_SETCRTC
* drm.c: Decode DRM_IOCTL_MODE_CURSOR
* drm.c: Decode DRM_IOCTL_MODE_CURSOR2
* drm.c: Decode DRM_IOCTL_MODE_GETGAMMA
* drm.c: Decode DRM_IOCTL_MODE_SETGAMMA
* drm.c: Decode DRM_IOCTL_MODE_GETENCODER
* drm.c: Decode DRM_IOCTL_MODE_GETCONNECTOR
* drm.c: Decode DRM_IOCTL_MODE_GETPROPERTY
* drm.c: Decode DRM_IOCTL_MODE_SETPROPERTY
* drm.c: Decode DRM_IOCTL_MODE_GETPROPBLOB
* drm.c: Decode DRM_IOCTL_MODE_GETFB
* drm.c: Decode DRM_IOCTL_MODE_ADDFB
* drm.c: Decode DRM_IOCTL_MODE_RMFB
* drm.c: Decode DRM_IOCTL_MODE_PAGE_FLIP
* drm.c: Decode DRM_IOCTL_DIRTYFB
* drm.c: Decode DRM_IOCTL_CREATE_DUMB
* drm.c: Decode DRM_IOCTL_MAP_DUMB
* drm.c: Decode DRM_IOCTL_DESTROY_DUMB
* drm.c: Decode DRM_IOCTL_GEM_CLOSE

Signed-off-by: Patrik Jakobsson <patrik.jakobsson@linux.intel.com>
---
 drm.c | 510 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 510 insertions(+)

Comments

Gabriel Laskar June 29, 2015, 5:35 p.m. UTC | #1
On Thu, 18 Jun 2015 10:42:45 +0200
Patrik Jakobsson <patrik.jakobsson@linux.intel.com> wrote:

> This patch adds many of the DRM and KMS ioctls. The rest can be added as
> needed.
> 
> * drm.c: Decode DRM_IOCTL_VERSION
> * drm.c: Decode DRM_IOCTL_GET_UNIQUE
> * drm.c: Decode DRM_IOCTL_GET_MAGIC
> * drm.c: Decode DRM_IOCTL_WAIT_VBLANK
> * drm.c: Decode DRM_IOCTL_MODE_GETRESOURCES
> * drm.c: Decode DRM_IOCTL_MODE_GETCRTC
> * drm.c: Decode DRM_IOCTL_MODE_SETCRTC
> * drm.c: Decode DRM_IOCTL_MODE_CURSOR
> * drm.c: Decode DRM_IOCTL_MODE_CURSOR2
> * drm.c: Decode DRM_IOCTL_MODE_GETGAMMA
> * drm.c: Decode DRM_IOCTL_MODE_SETGAMMA
> * drm.c: Decode DRM_IOCTL_MODE_GETENCODER
> * drm.c: Decode DRM_IOCTL_MODE_GETCONNECTOR
> * drm.c: Decode DRM_IOCTL_MODE_GETPROPERTY
> * drm.c: Decode DRM_IOCTL_MODE_SETPROPERTY
> * drm.c: Decode DRM_IOCTL_MODE_GETPROPBLOB
> * drm.c: Decode DRM_IOCTL_MODE_GETFB
> * drm.c: Decode DRM_IOCTL_MODE_ADDFB
> * drm.c: Decode DRM_IOCTL_MODE_RMFB
> * drm.c: Decode DRM_IOCTL_MODE_PAGE_FLIP
> * drm.c: Decode DRM_IOCTL_DIRTYFB
> * drm.c: Decode DRM_IOCTL_CREATE_DUMB
> * drm.c: Decode DRM_IOCTL_MAP_DUMB
> * drm.c: Decode DRM_IOCTL_DESTROY_DUMB
> * drm.c: Decode DRM_IOCTL_GEM_CLOSE
> 
> Signed-off-by: Patrik Jakobsson <patrik.jakobsson@linux.intel.com>
> ---
>  drm.c | 510 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 510 insertions(+)
> 
> diff --git a/drm.c b/drm.c
> index 8e3f7d1..2e6d763 100644
> --- a/drm.c
> +++ b/drm.c
> @@ -104,6 +104,463 @@ int drm_decode_number(struct tcb *tcp, unsigned int arg)
>  	return 0;
>  }
>  
> +static int drm_version(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_version ver;
> +
> +	if (umove(tcp, arg, &ver))
> +		return 0;
> +

The umove() should be done only on exiting and if the ioctl succeded ?

Same thing for most of the read only ioctl.

> +	if (exiting(tcp)) {
> +		tprintf(", {version_major=%d, version_minor=%d, version_patchlevel=%d, "
> +			"name_len=%lu, name=", ver.version_major,
> +			ver.version_minor, ver.version_patchlevel,
> +			ver.name_len);
> +		printstr(tcp, (long)ver.name, ver.name_len);
> +		tprintf(", date_len=%lu, date=", ver.date_len);
> +		printstr(tcp, (long)ver.date, ver.date_len);
> +		tprintf(", desc_len=%lu, desc=", ver.desc_len);
> +		printstr(tcp, (long)ver.desc, ver.desc_len);
> +		tprints("}");
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_get_unique(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_unique unique;
> +
> +	if (umove(tcp, arg, &unique))
> +		return 0;
> +
> +	if (exiting(tcp)) {
> +		tprintf(", {unique_len=%lu, unique=}", unique.unique_len);

There is an extra '}'

> +		printstr(tcp, (long)unique.unique, unique.unique_len);
> +		tprints("}");
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_get_magic(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_auth auth;
> +
> +	if (umove(tcp, arg, &auth))
> +		return 0;
> +
> +	if (exiting(tcp))
> +		tprintf(", {magic=%u}", auth.magic);
> +
> +	return 1;
> +}
> +
> +static int drm_wait_vblank(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	union drm_wait_vblank vblank;
> +
> +	if (umove(tcp, arg, &vblank))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {request={type=%u, sequence=%u, signal=%lu}",
> +			vblank.request.type, vblank.request.sequence,
> +			vblank.request.signal);
> +	} else if (exiting(tcp)) {
> +		tprintf(", reply={type=%u, sequence=%u, tval_sec=%ld, tval_usec=%ld}}",
> +			vblank.reply.type, vblank.reply.sequence,
> +			vblank.reply.tval_sec, vblank.reply.tval_usec);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_resources(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_card_res res;
> +
> +	if (umove(tcp, arg, &res))
> +		return 0;
> +
> +	if (exiting(tcp)) {
> +		tprintf(", {fb_id_ptr=%p, crtc_id_ptr=%p, connector_id_ptr=%p, "
> +			"encoder_id_ptr=%p, count_fbs=%u, count_crtcs=%u, "
> +			"count_connectors=%u, count_encoders=%u, min_width=%u, "
> +			"max_width=%u, min_height=%u, max_height=%u}",
> +			(void *)res.fb_id_ptr, (void *)res.crtc_id_ptr,
> +			(void *)res.connector_id_ptr, (void *)res.encoder_id_ptr,
> +			res.count_fbs, res.count_crtcs, res.count_connectors,
> +			res.count_encoders, res.min_width, res.max_width,
> +			res.min_height, res.max_height);
> +	}
> +
> +	return 1;
> +}
> +
> +static void drm_mode_print_modeinfo(struct drm_mode_modeinfo *info)
> +{
> +	tprintf("clock=%u, hdisplay=%hu, hsync_start=%hu, hsync_end=%hu, "
> +		"htotal=%hu, hskew=%hu, vdisplay=%hu, vsync_start=%hu, "
> +		"vsync_end=%hu, vtotal=%hu, vscan=%hu, vrefresh=%u, "
> +		"flags=0x%x, type=%u, name=%s", info->clock, info->hdisplay,
> +		info->hsync_start, info->hsync_end, info->htotal, info->hskew,
> +		info->vdisplay, info->vsync_start, info->vsync_end,
> +		info->vtotal, info->vscan, info->vrefresh, info->flags,
> +		info->type, info->name);
> +}
> +
> +static int drm_mode_get_crtc(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_crtc crtc;
> +
> +	if (umove(tcp, arg, &crtc))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {crtc_id=%u", crtc.crtc_id);
> +	} else if (exiting(tcp)) {
> +		tprintf(", set_connectors_ptr=%p, count_connectors=%u, "
> +			"fb_id=%u, x=%u, y=%u, gamma_size=%u, mode_valid=%u, "
> +			"mode={", (void *)crtc.set_connectors_ptr,
> +			crtc.count_connectors, crtc.fb_id, crtc.x, crtc.y,
> +			crtc.gamma_size, crtc.mode_valid);
> +
> +		drm_mode_print_modeinfo(&crtc.mode);
> +		tprintf("}}");
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_set_crtc(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_crtc crtc;
> +
> +	if (umove(tcp, arg, &crtc))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {set_connectors_ptr=%p, count_connectors=%u, "
> +			"crtc_id=%u, fb_id=%u, x=%u, y=%u, gamma_size=%u, "
> +			"mode_valid=%u, mode={", (void *)crtc.set_connectors_ptr,
> +			crtc.count_connectors, crtc.crtc_id, crtc.fb_id, crtc.x,
> +			crtc.y, crtc.gamma_size, crtc.mode_valid);
> +
> +		drm_mode_print_modeinfo(&crtc.mode);
> +		tprintf("}}");
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_cursor(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_cursor cursor;
> +
> +	if (umove(tcp, arg, &cursor))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {flags=0x%x, crtc_id=%u, x=%d, y=%d, width=%u, "
> +			"height=%u, handle=%u}", cursor.flags, cursor.crtc_id,
> +			cursor.x, cursor.y, cursor.width, cursor.height,
> +			cursor.handle);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_cursor2(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_cursor2 cursor;
> +
> +	if (umove(tcp, arg, &cursor))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {flags=0x%x, crtc_id=%u, x=%d, y=%d, width=%u, "
> +			"height=%u, handle=%u, hot_x=%d, hot_y=%d}",
> +			cursor.flags, cursor.crtc_id, cursor.x, cursor.y,
> +			cursor.width, cursor.height, cursor.handle,
> +			cursor.hot_x, cursor.hot_y);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_gamma(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_crtc_lut lut;
> +
> +	if (umove(tcp, arg, &lut))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		/* We don't print the entire table, just the pointers */
> +		tprintf(", {crtc_id=%u, gamma_size=%u, red=%p, green=%p, "
> +			"blue=%p}", lut.crtc_id, lut.gamma_size,
> +			(void *)lut.red, (void *)lut.green, (void *)lut.blue);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_set_gamma(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_crtc_lut lut;
> +
> +	if (umove(tcp, arg, &lut))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		/* We don't print the entire table, just the rgb pointers */
> +		tprintf(", {crtc_id=%u, gamma_size=%u, red=%p, green=%p, "
> +			"blue=%p}", lut.crtc_id, lut.gamma_size,
> +			(void *)lut.red, (void *)lut.green, (void *)lut.blue);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_encoder(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_get_encoder enc;
> +
> +	if (umove(tcp, arg, &enc))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {encoder_id=%u", enc.encoder_id);
> +	} else if (exiting(tcp)) {
> +		/* TODO: Print name of encoder type */
> +		tprintf(", encoder_type=%u, crtc_id=%u, possible_crtcs=0x%x, "
> +			"possible_clones=0x%x}", enc.encoder_type,
> +			enc.crtc_id, enc.possible_crtcs, enc.possible_clones);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_connector(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_get_connector con;
> +
> +	if (umove(tcp, arg, &con))
> +		return 0;
> +
> +	/* We could be very verbose here but keep is simple for now */
> +	if (entering(tcp)) {
> +		tprintf(", {connector_id=%u", con.connector_id);
> +	} else if (exiting(tcp)) {
> +		tprintf(", encoders_ptr=%p, modes_ptr=%p, props_ptr=%p, "
> +			"prop_values_ptr=%p, count_modes=%u, count_props=%u, "
> +			"count_encoders=%u, encoder_id=%u, connector_type=%u, "
> +			"connector_type_id=%u, connection=%u, mm_width=%u, "
> +			"mm_height=%u, subpixel=%u}", (void *)con.encoders_ptr,
> +			(void *)con.modes_ptr, (void *)con.props_ptr,
> +			(void *)con.prop_values_ptr, con.count_modes,
> +			con.count_props, con.count_encoders, con.encoder_id,
> +			con.connector_type, con.connector_type_id,
> +			con.connection, con.mm_width, con.mm_height,
> +			con.subpixel);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_property(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_get_property prop;
> +
> +	if (umove(tcp, arg, &prop))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {prop_id=%u", prop.prop_id);
> +	} else if (exiting(tcp)) {
> +		tprintf(", values_ptr=%p, enum_blob_ptr=%p, flags=0x%x, "
> +			"name=%s, count_values=%u, count_enum_blobs=%u}",
> +			(void *)prop.values_ptr, (void *)prop.enum_blob_ptr,
> +			prop.flags, prop.name, prop.count_values,
> +			prop.count_enum_blobs);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_set_property(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_connector_set_property prop;
> +
> +	if (umove(tcp, arg, &prop))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {value=%Lu, prop_id=%u, connector_id=%u}",
> +			prop.value, prop.prop_id, prop.connector_id);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_prop_blob(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_get_blob blob;
> +
> +	if (umove(tcp, arg, &blob))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {blob_id=%u", blob.blob_id);
> +	} else if (exiting(tcp)) {
> +		tprintf(", length=%u, data=%p}", blob.length,
> +			(void *)blob.data);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_add_fb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_fb_cmd cmd;
> +
> +	if (umove(tcp, arg, &cmd))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {width=%u, height=%u, pitch=%u, bpp=%u, depth=%u, "
> +			"handle=%u", cmd.width, cmd.height, cmd.pitch,
> +			cmd.bpp, cmd.depth, cmd.handle);
> +	} else if (exiting(tcp)) {
> +		tprintf(", fb_id=%u}", cmd.fb_id);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_fb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_fb_cmd cmd;
> +
> +	if (umove(tcp, arg, &cmd))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {fb_id=%u", cmd.fb_id);
> +	} else {
> +		tprintf(", width=%u, height=%u, pitch=%u, bpp=%u, depth=%u, "
> +		"handle=%u}", cmd.width, cmd.height, cmd.pitch,
> +		cmd.bpp, cmd.depth, cmd.handle);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_rm_fb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	unsigned int handle;
> +
> +	if (umove(tcp, arg, &handle))
> +		return 0;
> +
> +	if (entering(tcp))
> +		tprintf(", %u", handle);
> +
> +	return 1;
> +}
> +
> +static int drm_mode_page_flip(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_crtc_page_flip flip;
> +
> +	if (umove(tcp, arg, &flip))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {crtc_id=%u, fb_id=%u, flags=0x%x, user_data=0x%Lx}",
> +			flip.crtc_id, flip.fb_id, flip.flags, flip.user_data);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_dirty_fb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_fb_dirty_cmd cmd;
> +
> +	if (umove(tcp, arg, &cmd))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {fb_id=%u, flags=0x%x, color=0x%x, num_clips=%u, "
> +			"clips_ptr=%p}", cmd.fb_id, cmd.flags, cmd.color,
> +			cmd.num_clips, (void *)cmd.clips_ptr);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_create_dumb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_create_dumb dumb;
> +
> +	if (umove(tcp, arg, &dumb))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {width=%u, height=%u, bpp=%u, flags=0x%x",
> +			dumb.width, dumb.height, dumb.bpp, dumb.flags);
> +	} else if (exiting(tcp)) {
> +		tprintf(", handle=%u, pitch=%u, size=%Lu}", dumb.handle,
> +			dumb.pitch, dumb.size);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_map_dumb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_map_dumb dumb;
> +
> +	if (umove(tcp, arg, &dumb))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {handle=%u", dumb.handle);
> +	} else if (exiting(tcp)) {
> +		tprintf(", offset=%Lu}", dumb.offset);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_destroy_dumb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_destroy_dumb dumb;
> +
> +	if (umove(tcp, arg, &dumb))
> +		return 0;
> +
> +	if (entering(tcp))
> +		tprintf(", {handle=%u}", dumb.handle);
> +
> +	return 1;
> +}
> +
> +static int drm_gem_close(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_gem_close close;
> +
> +	if (umove(tcp, arg, &close))
> +		return 0;
> +
> +	if (entering(tcp))
> +		tprintf(", {handle=%u}", close.handle);
> +
> +	return 1;
> +}
> +
>  int drm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
>  {
>  	/* Check for device specific ioctls */
> @@ -112,6 +569,59 @@ int drm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
>  			return drm_i915_ioctl(tcp, code, arg);
>  	}
>  
> +	switch (code) {
> +	case DRM_IOCTL_VERSION:
> +		return drm_version(tcp, code, arg);
> +	case DRM_IOCTL_GET_UNIQUE:
> +		return drm_get_unique(tcp, code, arg);
> +	case DRM_IOCTL_GET_MAGIC:
> +		return drm_get_magic(tcp, code, arg);
> +	case DRM_IOCTL_WAIT_VBLANK:
> +		return drm_wait_vblank(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETRESOURCES:
> +		return drm_mode_get_resources(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETCRTC:
> +		return drm_mode_get_crtc(tcp, code, arg);
> +	case DRM_IOCTL_MODE_SETCRTC:
> +		return drm_mode_set_crtc(tcp, code, arg);
> +	case DRM_IOCTL_MODE_CURSOR:
> +		return drm_mode_cursor(tcp, code, arg);
> +	case DRM_IOCTL_MODE_CURSOR2:
> +		return drm_mode_cursor2(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETGAMMA:
> +		return drm_mode_get_gamma(tcp, code, arg);
> +	case DRM_IOCTL_MODE_SETGAMMA:
> +		return drm_mode_set_gamma(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETENCODER:
> +		return drm_mode_get_encoder(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETCONNECTOR:
> +		return drm_mode_get_connector(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETPROPERTY:
> +		return drm_mode_get_property(tcp, code, arg);
> +	case DRM_IOCTL_MODE_SETPROPERTY:
> +		return drm_mode_set_property(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETPROPBLOB:
> +		return drm_mode_get_prop_blob(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETFB:
> +		return drm_mode_get_fb(tcp, code, arg);
> +	case DRM_IOCTL_MODE_ADDFB:
> +		return drm_mode_add_fb(tcp, code, arg);
> +	case DRM_IOCTL_MODE_RMFB:
> +		return drm_mode_rm_fb(tcp, code, arg);
> +	case DRM_IOCTL_MODE_PAGE_FLIP:
> +		return drm_mode_page_flip(tcp, code, arg);
> +	case DRM_IOCTL_MODE_DIRTYFB:
> +		return drm_mode_dirty_fb(tcp, code, arg);
> +	case DRM_IOCTL_MODE_CREATE_DUMB:
> +		return drm_mode_create_dumb(tcp, code, arg);
> +	case DRM_IOCTL_MODE_MAP_DUMB:
> +		return drm_mode_map_dumb(tcp, code, arg);
> +	case DRM_IOCTL_MODE_DESTROY_DUMB:
> +		return drm_mode_destroy_dumb(tcp, code, arg);
> +	case DRM_IOCTL_GEM_CLOSE:
> +		return drm_gem_close(tcp, code, arg);
> +	}
> +
>  	/* Free any allocated private data */
>  	if (exiting(tcp) && tcp->priv_data != NULL) {
>  		free(tcp->priv_data);
Patrik Jakobsson June 30, 2015, 7:47 a.m. UTC | #2
On Mon, Jun 29, 2015 at 07:35:00PM +0200, Gabriel Laskar wrote:
> On Thu, 18 Jun 2015 10:42:45 +0200
> Patrik Jakobsson <patrik.jakobsson@linux.intel.com> wrote:
> 
> > This patch adds many of the DRM and KMS ioctls. The rest can be added as
> > needed.
> > 
> > * drm.c: Decode DRM_IOCTL_VERSION
> > * drm.c: Decode DRM_IOCTL_GET_UNIQUE
> > * drm.c: Decode DRM_IOCTL_GET_MAGIC
> > * drm.c: Decode DRM_IOCTL_WAIT_VBLANK
> > * drm.c: Decode DRM_IOCTL_MODE_GETRESOURCES
> > * drm.c: Decode DRM_IOCTL_MODE_GETCRTC
> > * drm.c: Decode DRM_IOCTL_MODE_SETCRTC
> > * drm.c: Decode DRM_IOCTL_MODE_CURSOR
> > * drm.c: Decode DRM_IOCTL_MODE_CURSOR2
> > * drm.c: Decode DRM_IOCTL_MODE_GETGAMMA
> > * drm.c: Decode DRM_IOCTL_MODE_SETGAMMA
> > * drm.c: Decode DRM_IOCTL_MODE_GETENCODER
> > * drm.c: Decode DRM_IOCTL_MODE_GETCONNECTOR
> > * drm.c: Decode DRM_IOCTL_MODE_GETPROPERTY
> > * drm.c: Decode DRM_IOCTL_MODE_SETPROPERTY
> > * drm.c: Decode DRM_IOCTL_MODE_GETPROPBLOB
> > * drm.c: Decode DRM_IOCTL_MODE_GETFB
> > * drm.c: Decode DRM_IOCTL_MODE_ADDFB
> > * drm.c: Decode DRM_IOCTL_MODE_RMFB
> > * drm.c: Decode DRM_IOCTL_MODE_PAGE_FLIP
> > * drm.c: Decode DRM_IOCTL_DIRTYFB
> > * drm.c: Decode DRM_IOCTL_CREATE_DUMB
> > * drm.c: Decode DRM_IOCTL_MAP_DUMB
> > * drm.c: Decode DRM_IOCTL_DESTROY_DUMB
> > * drm.c: Decode DRM_IOCTL_GEM_CLOSE
> > 
> > Signed-off-by: Patrik Jakobsson <patrik.jakobsson@linux.intel.com>
> > ---
> >  drm.c | 510 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 510 insertions(+)
> > 
> > diff --git a/drm.c b/drm.c
> > index 8e3f7d1..2e6d763 100644
> > --- a/drm.c
> > +++ b/drm.c
> > @@ -104,6 +104,463 @@ int drm_decode_number(struct tcb *tcp, unsigned int arg)
> >  	return 0;
> >  }
> >  
> > +static int drm_version(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_version ver;
> > +
> > +	if (umove(tcp, arg, &ver))
> > +		return 0;
> > +
> 
> The umove() should be done only on exiting and if the ioctl succeded ?
> 
> Same thing for most of the read only ioctl.
> 
Yes, that could be moved into exiting. Will fix for all "single phase" ioctls.

> > +	if (exiting(tcp)) {
> > +		tprintf(", {version_major=%d, version_minor=%d, version_patchlevel=%d, "
> > +			"name_len=%lu, name=", ver.version_major,
> > +			ver.version_minor, ver.version_patchlevel,
> > +			ver.name_len);
> > +		printstr(tcp, (long)ver.name, ver.name_len);
> > +		tprintf(", date_len=%lu, date=", ver.date_len);
> > +		printstr(tcp, (long)ver.date, ver.date_len);
> > +		tprintf(", desc_len=%lu, desc=", ver.desc_len);
> > +		printstr(tcp, (long)ver.desc, ver.desc_len);
> > +		tprints("}");
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_get_unique(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_unique unique;
> > +
> > +	if (umove(tcp, arg, &unique))
> > +		return 0;
> > +
> > +	if (exiting(tcp)) {
> > +		tprintf(", {unique_len=%lu, unique=}", unique.unique_len);
> 
> There is an extra '}'
> 

Oops

> > +		printstr(tcp, (long)unique.unique, unique.unique_len);
> > +		tprints("}");
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_get_magic(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_auth auth;
> > +
> > +	if (umove(tcp, arg, &auth))
> > +		return 0;
> > +
> > +	if (exiting(tcp))
> > +		tprintf(", {magic=%u}", auth.magic);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_wait_vblank(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	union drm_wait_vblank vblank;
> > +
> > +	if (umove(tcp, arg, &vblank))
> > +		return 0;
> > +
> > +	if (entering(tcp)) {
> > +		tprintf(", {request={type=%u, sequence=%u, signal=%lu}",
> > +			vblank.request.type, vblank.request.sequence,
> > +			vblank.request.signal);
> > +	} else if (exiting(tcp)) {
> > +		tprintf(", reply={type=%u, sequence=%u, tval_sec=%ld, tval_usec=%ld}}",
> > +			vblank.reply.type, vblank.reply.sequence,
> > +			vblank.reply.tval_sec, vblank.reply.tval_usec);
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_get_resources(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_card_res res;
> > +
> > +	if (umove(tcp, arg, &res))
> > +		return 0;
> > +
> > +	if (exiting(tcp)) {
> > +		tprintf(", {fb_id_ptr=%p, crtc_id_ptr=%p, connector_id_ptr=%p, "
> > +			"encoder_id_ptr=%p, count_fbs=%u, count_crtcs=%u, "
> > +			"count_connectors=%u, count_encoders=%u, min_width=%u, "
> > +			"max_width=%u, min_height=%u, max_height=%u}",
> > +			(void *)res.fb_id_ptr, (void *)res.crtc_id_ptr,
> > +			(void *)res.connector_id_ptr, (void *)res.encoder_id_ptr,
> > +			res.count_fbs, res.count_crtcs, res.count_connectors,
> > +			res.count_encoders, res.min_width, res.max_width,
> > +			res.min_height, res.max_height);
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static void drm_mode_print_modeinfo(struct drm_mode_modeinfo *info)
> > +{
> > +	tprintf("clock=%u, hdisplay=%hu, hsync_start=%hu, hsync_end=%hu, "
> > +		"htotal=%hu, hskew=%hu, vdisplay=%hu, vsync_start=%hu, "
> > +		"vsync_end=%hu, vtotal=%hu, vscan=%hu, vrefresh=%u, "
> > +		"flags=0x%x, type=%u, name=%s", info->clock, info->hdisplay,
> > +		info->hsync_start, info->hsync_end, info->htotal, info->hskew,
> > +		info->vdisplay, info->vsync_start, info->vsync_end,
> > +		info->vtotal, info->vscan, info->vrefresh, info->flags,
> > +		info->type, info->name);
> > +}
> > +
> > +static int drm_mode_get_crtc(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_crtc crtc;
> > +
> > +	if (umove(tcp, arg, &crtc))
> > +		return 0;
> > +
> > +	if (entering(tcp)) {
> > +		tprintf(", {crtc_id=%u", crtc.crtc_id);
> > +	} else if (exiting(tcp)) {
> > +		tprintf(", set_connectors_ptr=%p, count_connectors=%u, "
> > +			"fb_id=%u, x=%u, y=%u, gamma_size=%u, mode_valid=%u, "
> > +			"mode={", (void *)crtc.set_connectors_ptr,
> > +			crtc.count_connectors, crtc.fb_id, crtc.x, crtc.y,
> > +			crtc.gamma_size, crtc.mode_valid);
> > +
> > +		drm_mode_print_modeinfo(&crtc.mode);
> > +		tprintf("}}");
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_set_crtc(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_crtc crtc;
> > +
> > +	if (umove(tcp, arg, &crtc))
> > +		return 0;
> > +
> > +	if (entering(tcp)) {
> > +		tprintf(", {set_connectors_ptr=%p, count_connectors=%u, "
> > +			"crtc_id=%u, fb_id=%u, x=%u, y=%u, gamma_size=%u, "
> > +			"mode_valid=%u, mode={", (void *)crtc.set_connectors_ptr,
> > +			crtc.count_connectors, crtc.crtc_id, crtc.fb_id, crtc.x,
> > +			crtc.y, crtc.gamma_size, crtc.mode_valid);
> > +
> > +		drm_mode_print_modeinfo(&crtc.mode);
> > +		tprintf("}}");
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_cursor(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_cursor cursor;
> > +
> > +	if (umove(tcp, arg, &cursor))
> > +		return 0;
> > +
> > +	if (entering(tcp)) {
> > +		tprintf(", {flags=0x%x, crtc_id=%u, x=%d, y=%d, width=%u, "
> > +			"height=%u, handle=%u}", cursor.flags, cursor.crtc_id,
> > +			cursor.x, cursor.y, cursor.width, cursor.height,
> > +			cursor.handle);
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_cursor2(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_cursor2 cursor;
> > +
> > +	if (umove(tcp, arg, &cursor))
> > +		return 0;
> > +
> > +	if (entering(tcp)) {
> > +		tprintf(", {flags=0x%x, crtc_id=%u, x=%d, y=%d, width=%u, "
> > +			"height=%u, handle=%u, hot_x=%d, hot_y=%d}",
> > +			cursor.flags, cursor.crtc_id, cursor.x, cursor.y,
> > +			cursor.width, cursor.height, cursor.handle,
> > +			cursor.hot_x, cursor.hot_y);
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_get_gamma(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_crtc_lut lut;
> > +
> > +	if (umove(tcp, arg, &lut))
> > +		return 0;
> > +
> > +	if (entering(tcp)) {
> > +		/* We don't print the entire table, just the pointers */
> > +		tprintf(", {crtc_id=%u, gamma_size=%u, red=%p, green=%p, "
> > +			"blue=%p}", lut.crtc_id, lut.gamma_size,
> > +			(void *)lut.red, (void *)lut.green, (void *)lut.blue);
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_set_gamma(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_crtc_lut lut;
> > +
> > +	if (umove(tcp, arg, &lut))
> > +		return 0;
> > +
> > +	if (entering(tcp)) {
> > +		/* We don't print the entire table, just the rgb pointers */
> > +		tprintf(", {crtc_id=%u, gamma_size=%u, red=%p, green=%p, "
> > +			"blue=%p}", lut.crtc_id, lut.gamma_size,
> > +			(void *)lut.red, (void *)lut.green, (void *)lut.blue);
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_get_encoder(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_get_encoder enc;
> > +
> > +	if (umove(tcp, arg, &enc))
> > +		return 0;
> > +
> > +	if (entering(tcp)) {
> > +		tprintf(", {encoder_id=%u", enc.encoder_id);
> > +	} else if (exiting(tcp)) {
> > +		/* TODO: Print name of encoder type */
> > +		tprintf(", encoder_type=%u, crtc_id=%u, possible_crtcs=0x%x, "
> > +			"possible_clones=0x%x}", enc.encoder_type,
> > +			enc.crtc_id, enc.possible_crtcs, enc.possible_clones);
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_get_connector(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_get_connector con;
> > +
> > +	if (umove(tcp, arg, &con))
> > +		return 0;
> > +
> > +	/* We could be very verbose here but keep is simple for now */
> > +	if (entering(tcp)) {
> > +		tprintf(", {connector_id=%u", con.connector_id);
> > +	} else if (exiting(tcp)) {
> > +		tprintf(", encoders_ptr=%p, modes_ptr=%p, props_ptr=%p, "
> > +			"prop_values_ptr=%p, count_modes=%u, count_props=%u, "
> > +			"count_encoders=%u, encoder_id=%u, connector_type=%u, "
> > +			"connector_type_id=%u, connection=%u, mm_width=%u, "
> > +			"mm_height=%u, subpixel=%u}", (void *)con.encoders_ptr,
> > +			(void *)con.modes_ptr, (void *)con.props_ptr,
> > +			(void *)con.prop_values_ptr, con.count_modes,
> > +			con.count_props, con.count_encoders, con.encoder_id,
> > +			con.connector_type, con.connector_type_id,
> > +			con.connection, con.mm_width, con.mm_height,
> > +			con.subpixel);
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_get_property(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_get_property prop;
> > +
> > +	if (umove(tcp, arg, &prop))
> > +		return 0;
> > +
> > +	if (entering(tcp)) {
> > +		tprintf(", {prop_id=%u", prop.prop_id);
> > +	} else if (exiting(tcp)) {
> > +		tprintf(", values_ptr=%p, enum_blob_ptr=%p, flags=0x%x, "
> > +			"name=%s, count_values=%u, count_enum_blobs=%u}",
> > +			(void *)prop.values_ptr, (void *)prop.enum_blob_ptr,
> > +			prop.flags, prop.name, prop.count_values,
> > +			prop.count_enum_blobs);
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_set_property(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_connector_set_property prop;
> > +
> > +	if (umove(tcp, arg, &prop))
> > +		return 0;
> > +
> > +	if (entering(tcp)) {
> > +		tprintf(", {value=%Lu, prop_id=%u, connector_id=%u}",
> > +			prop.value, prop.prop_id, prop.connector_id);
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_get_prop_blob(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_get_blob blob;
> > +
> > +	if (umove(tcp, arg, &blob))
> > +		return 0;
> > +
> > +	if (entering(tcp)) {
> > +		tprintf(", {blob_id=%u", blob.blob_id);
> > +	} else if (exiting(tcp)) {
> > +		tprintf(", length=%u, data=%p}", blob.length,
> > +			(void *)blob.data);
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_add_fb(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_fb_cmd cmd;
> > +
> > +	if (umove(tcp, arg, &cmd))
> > +		return 0;
> > +
> > +	if (entering(tcp)) {
> > +		tprintf(", {width=%u, height=%u, pitch=%u, bpp=%u, depth=%u, "
> > +			"handle=%u", cmd.width, cmd.height, cmd.pitch,
> > +			cmd.bpp, cmd.depth, cmd.handle);
> > +	} else if (exiting(tcp)) {
> > +		tprintf(", fb_id=%u}", cmd.fb_id);
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_get_fb(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_fb_cmd cmd;
> > +
> > +	if (umove(tcp, arg, &cmd))
> > +		return 0;
> > +
> > +	if (entering(tcp)) {
> > +		tprintf(", {fb_id=%u", cmd.fb_id);
> > +	} else {
> > +		tprintf(", width=%u, height=%u, pitch=%u, bpp=%u, depth=%u, "
> > +		"handle=%u}", cmd.width, cmd.height, cmd.pitch,
> > +		cmd.bpp, cmd.depth, cmd.handle);
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_rm_fb(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	unsigned int handle;
> > +
> > +	if (umove(tcp, arg, &handle))
> > +		return 0;
> > +
> > +	if (entering(tcp))
> > +		tprintf(", %u", handle);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_page_flip(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_crtc_page_flip flip;
> > +
> > +	if (umove(tcp, arg, &flip))
> > +		return 0;
> > +
> > +	if (entering(tcp)) {
> > +		tprintf(", {crtc_id=%u, fb_id=%u, flags=0x%x, user_data=0x%Lx}",
> > +			flip.crtc_id, flip.fb_id, flip.flags, flip.user_data);
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_dirty_fb(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_fb_dirty_cmd cmd;
> > +
> > +	if (umove(tcp, arg, &cmd))
> > +		return 0;
> > +
> > +	if (entering(tcp)) {
> > +		tprintf(", {fb_id=%u, flags=0x%x, color=0x%x, num_clips=%u, "
> > +			"clips_ptr=%p}", cmd.fb_id, cmd.flags, cmd.color,
> > +			cmd.num_clips, (void *)cmd.clips_ptr);
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_create_dumb(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_create_dumb dumb;
> > +
> > +	if (umove(tcp, arg, &dumb))
> > +		return 0;
> > +
> > +	if (entering(tcp)) {
> > +		tprintf(", {width=%u, height=%u, bpp=%u, flags=0x%x",
> > +			dumb.width, dumb.height, dumb.bpp, dumb.flags);
> > +	} else if (exiting(tcp)) {
> > +		tprintf(", handle=%u, pitch=%u, size=%Lu}", dumb.handle,
> > +			dumb.pitch, dumb.size);
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_map_dumb(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_map_dumb dumb;
> > +
> > +	if (umove(tcp, arg, &dumb))
> > +		return 0;
> > +
> > +	if (entering(tcp)) {
> > +		tprintf(", {handle=%u", dumb.handle);
> > +	} else if (exiting(tcp)) {
> > +		tprintf(", offset=%Lu}", dumb.offset);
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_destroy_dumb(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_destroy_dumb dumb;
> > +
> > +	if (umove(tcp, arg, &dumb))
> > +		return 0;
> > +
> > +	if (entering(tcp))
> > +		tprintf(", {handle=%u}", dumb.handle);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_gem_close(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_gem_close close;
> > +
> > +	if (umove(tcp, arg, &close))
> > +		return 0;
> > +
> > +	if (entering(tcp))
> > +		tprintf(", {handle=%u}", close.handle);
> > +
> > +	return 1;
> > +}
> > +
> >  int drm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
> >  {
> >  	/* Check for device specific ioctls */
> > @@ -112,6 +569,59 @@ int drm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
> >  			return drm_i915_ioctl(tcp, code, arg);
> >  	}
> >  
> > +	switch (code) {
> > +	case DRM_IOCTL_VERSION:
> > +		return drm_version(tcp, code, arg);
> > +	case DRM_IOCTL_GET_UNIQUE:
> > +		return drm_get_unique(tcp, code, arg);
> > +	case DRM_IOCTL_GET_MAGIC:
> > +		return drm_get_magic(tcp, code, arg);
> > +	case DRM_IOCTL_WAIT_VBLANK:
> > +		return drm_wait_vblank(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_GETRESOURCES:
> > +		return drm_mode_get_resources(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_GETCRTC:
> > +		return drm_mode_get_crtc(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_SETCRTC:
> > +		return drm_mode_set_crtc(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_CURSOR:
> > +		return drm_mode_cursor(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_CURSOR2:
> > +		return drm_mode_cursor2(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_GETGAMMA:
> > +		return drm_mode_get_gamma(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_SETGAMMA:
> > +		return drm_mode_set_gamma(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_GETENCODER:
> > +		return drm_mode_get_encoder(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_GETCONNECTOR:
> > +		return drm_mode_get_connector(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_GETPROPERTY:
> > +		return drm_mode_get_property(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_SETPROPERTY:
> > +		return drm_mode_set_property(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_GETPROPBLOB:
> > +		return drm_mode_get_prop_blob(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_GETFB:
> > +		return drm_mode_get_fb(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_ADDFB:
> > +		return drm_mode_add_fb(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_RMFB:
> > +		return drm_mode_rm_fb(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_PAGE_FLIP:
> > +		return drm_mode_page_flip(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_DIRTYFB:
> > +		return drm_mode_dirty_fb(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_CREATE_DUMB:
> > +		return drm_mode_create_dumb(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_MAP_DUMB:
> > +		return drm_mode_map_dumb(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_DESTROY_DUMB:
> > +		return drm_mode_destroy_dumb(tcp, code, arg);
> > +	case DRM_IOCTL_GEM_CLOSE:
> > +		return drm_gem_close(tcp, code, arg);
> > +	}
> > +
> >  	/* Free any allocated private data */
> >  	if (exiting(tcp) && tcp->priv_data != NULL) {
> >  		free(tcp->priv_data);
> 
> 
> 
> -- 
> Gabriel Laskar
Patrik Jakobsson June 30, 2015, 8:51 a.m. UTC | #3
On Thu, Jun 18, 2015 at 10:42:45AM +0200, Patrik Jakobsson wrote:
> This patch adds many of the DRM and KMS ioctls. The rest can be added as
> needed.
> 
> * drm.c: Decode DRM_IOCTL_VERSION
> * drm.c: Decode DRM_IOCTL_GET_UNIQUE
> * drm.c: Decode DRM_IOCTL_GET_MAGIC
> * drm.c: Decode DRM_IOCTL_WAIT_VBLANK
> * drm.c: Decode DRM_IOCTL_MODE_GETRESOURCES
> * drm.c: Decode DRM_IOCTL_MODE_GETCRTC
> * drm.c: Decode DRM_IOCTL_MODE_SETCRTC
> * drm.c: Decode DRM_IOCTL_MODE_CURSOR
> * drm.c: Decode DRM_IOCTL_MODE_CURSOR2
> * drm.c: Decode DRM_IOCTL_MODE_GETGAMMA
> * drm.c: Decode DRM_IOCTL_MODE_SETGAMMA
> * drm.c: Decode DRM_IOCTL_MODE_GETENCODER
> * drm.c: Decode DRM_IOCTL_MODE_GETCONNECTOR
> * drm.c: Decode DRM_IOCTL_MODE_GETPROPERTY
> * drm.c: Decode DRM_IOCTL_MODE_SETPROPERTY
> * drm.c: Decode DRM_IOCTL_MODE_GETPROPBLOB
> * drm.c: Decode DRM_IOCTL_MODE_GETFB
> * drm.c: Decode DRM_IOCTL_MODE_ADDFB
> * drm.c: Decode DRM_IOCTL_MODE_RMFB
> * drm.c: Decode DRM_IOCTL_MODE_PAGE_FLIP
> * drm.c: Decode DRM_IOCTL_DIRTYFB
> * drm.c: Decode DRM_IOCTL_CREATE_DUMB
> * drm.c: Decode DRM_IOCTL_MAP_DUMB
> * drm.c: Decode DRM_IOCTL_DESTROY_DUMB
> * drm.c: Decode DRM_IOCTL_GEM_CLOSE
> 
> Signed-off-by: Patrik Jakobsson <patrik.jakobsson@linux.intel.com>
> ---
>  drm.c | 510 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 510 insertions(+)
> 
> diff --git a/drm.c b/drm.c
> index 8e3f7d1..2e6d763 100644
> --- a/drm.c
> +++ b/drm.c
> @@ -104,6 +104,463 @@ int drm_decode_number(struct tcb *tcp, unsigned int arg)
>  	return 0;
>  }
>  
> +static int drm_version(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_version ver;
> +
> +	if (umove(tcp, arg, &ver))
> +		return 0;
> +
> +	if (exiting(tcp)) {
> +		tprintf(", {version_major=%d, version_minor=%d, version_patchlevel=%d, "
> +			"name_len=%lu, name=", ver.version_major,
> +			ver.version_minor, ver.version_patchlevel,
> +			ver.name_len);
> +		printstr(tcp, (long)ver.name, ver.name_len);
> +		tprintf(", date_len=%lu, date=", ver.date_len);
> +		printstr(tcp, (long)ver.date, ver.date_len);
> +		tprintf(", desc_len=%lu, desc=", ver.desc_len);
> +		printstr(tcp, (long)ver.desc, ver.desc_len);
> +		tprints("}");
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_get_unique(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_unique unique;
> +
> +	if (umove(tcp, arg, &unique))
> +		return 0;
> +
> +	if (exiting(tcp)) {
> +		tprintf(", {unique_len=%lu, unique=}", unique.unique_len);
> +		printstr(tcp, (long)unique.unique, unique.unique_len);
> +		tprints("}");
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_get_magic(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_auth auth;
> +
> +	if (umove(tcp, arg, &auth))
> +		return 0;
> +
> +	if (exiting(tcp))
> +		tprintf(", {magic=%u}", auth.magic);
> +
> +	return 1;
> +}
> +
> +static int drm_wait_vblank(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	union drm_wait_vblank vblank;
> +
> +	if (umove(tcp, arg, &vblank))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {request={type=%u, sequence=%u, signal=%lu}",
> +			vblank.request.type, vblank.request.sequence,
> +			vblank.request.signal);
> +	} else if (exiting(tcp)) {
> +		tprintf(", reply={type=%u, sequence=%u, tval_sec=%ld, tval_usec=%ld}}",
> +			vblank.reply.type, vblank.reply.sequence,
> +			vblank.reply.tval_sec, vblank.reply.tval_usec);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_resources(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_card_res res;
> +
> +	if (umove(tcp, arg, &res))
> +		return 0;
> +
> +	if (exiting(tcp)) {
> +		tprintf(", {fb_id_ptr=%p, crtc_id_ptr=%p, connector_id_ptr=%p, "
> +			"encoder_id_ptr=%p, count_fbs=%u, count_crtcs=%u, "
> +			"count_connectors=%u, count_encoders=%u, min_width=%u, "
> +			"max_width=%u, min_height=%u, max_height=%u}",
> +			(void *)res.fb_id_ptr, (void *)res.crtc_id_ptr,
> +			(void *)res.connector_id_ptr, (void *)res.encoder_id_ptr,
> +			res.count_fbs, res.count_crtcs, res.count_connectors,
> +			res.count_encoders, res.min_width, res.max_width,
> +			res.min_height, res.max_height);
> +	}
> +
> +	return 1;
> +}
> +
> +static void drm_mode_print_modeinfo(struct drm_mode_modeinfo *info)
> +{
> +	tprintf("clock=%u, hdisplay=%hu, hsync_start=%hu, hsync_end=%hu, "
> +		"htotal=%hu, hskew=%hu, vdisplay=%hu, vsync_start=%hu, "
> +		"vsync_end=%hu, vtotal=%hu, vscan=%hu, vrefresh=%u, "
> +		"flags=0x%x, type=%u, name=%s", info->clock, info->hdisplay,
> +		info->hsync_start, info->hsync_end, info->htotal, info->hskew,
> +		info->vdisplay, info->vsync_start, info->vsync_end,
> +		info->vtotal, info->vscan, info->vrefresh, info->flags,
> +		info->type, info->name);
> +}
> +
> +static int drm_mode_get_crtc(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_crtc crtc;
> +
> +	if (umove(tcp, arg, &crtc))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {crtc_id=%u", crtc.crtc_id);
> +	} else if (exiting(tcp)) {
> +		tprintf(", set_connectors_ptr=%p, count_connectors=%u, "
> +			"fb_id=%u, x=%u, y=%u, gamma_size=%u, mode_valid=%u, "
> +			"mode={", (void *)crtc.set_connectors_ptr,
> +			crtc.count_connectors, crtc.fb_id, crtc.x, crtc.y,
> +			crtc.gamma_size, crtc.mode_valid);
> +
> +		drm_mode_print_modeinfo(&crtc.mode);
> +		tprintf("}}");
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_set_crtc(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_crtc crtc;
> +
> +	if (umove(tcp, arg, &crtc))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {set_connectors_ptr=%p, count_connectors=%u, "
> +			"crtc_id=%u, fb_id=%u, x=%u, y=%u, gamma_size=%u, "
> +			"mode_valid=%u, mode={", (void *)crtc.set_connectors_ptr,
> +			crtc.count_connectors, crtc.crtc_id, crtc.fb_id, crtc.x,
> +			crtc.y, crtc.gamma_size, crtc.mode_valid);
> +
> +		drm_mode_print_modeinfo(&crtc.mode);
> +		tprintf("}}");
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_cursor(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_cursor cursor;
> +
> +	if (umove(tcp, arg, &cursor))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {flags=0x%x, crtc_id=%u, x=%d, y=%d, width=%u, "
> +			"height=%u, handle=%u}", cursor.flags, cursor.crtc_id,
> +			cursor.x, cursor.y, cursor.width, cursor.height,
> +			cursor.handle);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_cursor2(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_cursor2 cursor;
> +
> +	if (umove(tcp, arg, &cursor))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {flags=0x%x, crtc_id=%u, x=%d, y=%d, width=%u, "
> +			"height=%u, handle=%u, hot_x=%d, hot_y=%d}",
> +			cursor.flags, cursor.crtc_id, cursor.x, cursor.y,
> +			cursor.width, cursor.height, cursor.handle,
> +			cursor.hot_x, cursor.hot_y);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_gamma(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_crtc_lut lut;
> +
> +	if (umove(tcp, arg, &lut))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		/* We don't print the entire table, just the pointers */
> +		tprintf(", {crtc_id=%u, gamma_size=%u, red=%p, green=%p, "
> +			"blue=%p}", lut.crtc_id, lut.gamma_size,
> +			(void *)lut.red, (void *)lut.green, (void *)lut.blue);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_set_gamma(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_crtc_lut lut;
> +
> +	if (umove(tcp, arg, &lut))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		/* We don't print the entire table, just the rgb pointers */
> +		tprintf(", {crtc_id=%u, gamma_size=%u, red=%p, green=%p, "
> +			"blue=%p}", lut.crtc_id, lut.gamma_size,
> +			(void *)lut.red, (void *)lut.green, (void *)lut.blue);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_encoder(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_get_encoder enc;
> +
> +	if (umove(tcp, arg, &enc))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {encoder_id=%u", enc.encoder_id);
> +	} else if (exiting(tcp)) {
> +		/* TODO: Print name of encoder type */
> +		tprintf(", encoder_type=%u, crtc_id=%u, possible_crtcs=0x%x, "
> +			"possible_clones=0x%x}", enc.encoder_type,
> +			enc.crtc_id, enc.possible_crtcs, enc.possible_clones);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_connector(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_get_connector con;
> +
> +	if (umove(tcp, arg, &con))
> +		return 0;
> +
> +	/* We could be very verbose here but keep is simple for now */
> +	if (entering(tcp)) {
> +		tprintf(", {connector_id=%u", con.connector_id);
> +	} else if (exiting(tcp)) {
> +		tprintf(", encoders_ptr=%p, modes_ptr=%p, props_ptr=%p, "
> +			"prop_values_ptr=%p, count_modes=%u, count_props=%u, "
> +			"count_encoders=%u, encoder_id=%u, connector_type=%u, "
> +			"connector_type_id=%u, connection=%u, mm_width=%u, "
> +			"mm_height=%u, subpixel=%u}", (void *)con.encoders_ptr,
> +			(void *)con.modes_ptr, (void *)con.props_ptr,
> +			(void *)con.prop_values_ptr, con.count_modes,
> +			con.count_props, con.count_encoders, con.encoder_id,
> +			con.connector_type, con.connector_type_id,
> +			con.connection, con.mm_width, con.mm_height,
> +			con.subpixel);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_property(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_get_property prop;
> +
> +	if (umove(tcp, arg, &prop))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {prop_id=%u", prop.prop_id);
> +	} else if (exiting(tcp)) {
> +		tprintf(", values_ptr=%p, enum_blob_ptr=%p, flags=0x%x, "
> +			"name=%s, count_values=%u, count_enum_blobs=%u}",
> +			(void *)prop.values_ptr, (void *)prop.enum_blob_ptr,
> +			prop.flags, prop.name, prop.count_values,
> +			prop.count_enum_blobs);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_set_property(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_connector_set_property prop;
> +
> +	if (umove(tcp, arg, &prop))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {value=%Lu, prop_id=%u, connector_id=%u}",
> +			prop.value, prop.prop_id, prop.connector_id);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_prop_blob(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_get_blob blob;
> +
> +	if (umove(tcp, arg, &blob))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {blob_id=%u", blob.blob_id);
> +	} else if (exiting(tcp)) {
> +		tprintf(", length=%u, data=%p}", blob.length,
> +			(void *)blob.data);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_add_fb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_fb_cmd cmd;
> +
> +	if (umove(tcp, arg, &cmd))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {width=%u, height=%u, pitch=%u, bpp=%u, depth=%u, "
> +			"handle=%u", cmd.width, cmd.height, cmd.pitch,
> +			cmd.bpp, cmd.depth, cmd.handle);
> +	} else if (exiting(tcp)) {
> +		tprintf(", fb_id=%u}", cmd.fb_id);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_fb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_fb_cmd cmd;
> +
> +	if (umove(tcp, arg, &cmd))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {fb_id=%u", cmd.fb_id);
> +	} else {
> +		tprintf(", width=%u, height=%u, pitch=%u, bpp=%u, depth=%u, "
> +		"handle=%u}", cmd.width, cmd.height, cmd.pitch,
> +		cmd.bpp, cmd.depth, cmd.handle);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_rm_fb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	unsigned int handle;
> +
> +	if (umove(tcp, arg, &handle))
> +		return 0;
> +
> +	if (entering(tcp))
> +		tprintf(", %u", handle);
> +
> +	return 1;
> +}
> +
> +static int drm_mode_page_flip(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_crtc_page_flip flip;
> +
> +	if (umove(tcp, arg, &flip))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {crtc_id=%u, fb_id=%u, flags=0x%x, user_data=0x%Lx}",
> +			flip.crtc_id, flip.fb_id, flip.flags, flip.user_data);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_dirty_fb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_fb_dirty_cmd cmd;
> +
> +	if (umove(tcp, arg, &cmd))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {fb_id=%u, flags=0x%x, color=0x%x, num_clips=%u, "
> +			"clips_ptr=%p}", cmd.fb_id, cmd.flags, cmd.color,
> +			cmd.num_clips, (void *)cmd.clips_ptr);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_create_dumb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_create_dumb dumb;
> +
> +	if (umove(tcp, arg, &dumb))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {width=%u, height=%u, bpp=%u, flags=0x%x",
> +			dumb.width, dumb.height, dumb.bpp, dumb.flags);
> +	} else if (exiting(tcp)) {
> +		tprintf(", handle=%u, pitch=%u, size=%Lu}", dumb.handle,
> +			dumb.pitch, dumb.size);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_map_dumb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_map_dumb dumb;
> +
> +	if (umove(tcp, arg, &dumb))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {handle=%u", dumb.handle);
> +	} else if (exiting(tcp)) {
> +		tprintf(", offset=%Lu}", dumb.offset);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_destroy_dumb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_destroy_dumb dumb;
> +
> +	if (umove(tcp, arg, &dumb))
> +		return 0;
> +
> +	if (entering(tcp))
> +		tprintf(", {handle=%u}", dumb.handle);
> +
> +	return 1;
> +}
> +
> +static int drm_gem_close(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_gem_close close;
> +
> +	if (umove(tcp, arg, &close))
> +		return 0;
> +
> +	if (entering(tcp))
> +		tprintf(", {handle=%u}", close.handle);
> +
> +	return 1;
> +}
> +
>  int drm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
>  {
>  	/* Check for device specific ioctls */
> @@ -112,6 +569,59 @@ int drm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
>  			return drm_i915_ioctl(tcp, code, arg);
>  	}
>  
> +	switch (code) {
> +	case DRM_IOCTL_VERSION:
> +		return drm_version(tcp, code, arg);
> +	case DRM_IOCTL_GET_UNIQUE:
> +		return drm_get_unique(tcp, code, arg);
> +	case DRM_IOCTL_GET_MAGIC:
> +		return drm_get_magic(tcp, code, arg);
> +	case DRM_IOCTL_WAIT_VBLANK:
> +		return drm_wait_vblank(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETRESOURCES:
> +		return drm_mode_get_resources(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETCRTC:
> +		return drm_mode_get_crtc(tcp, code, arg);
> +	case DRM_IOCTL_MODE_SETCRTC:
> +		return drm_mode_set_crtc(tcp, code, arg);
> +	case DRM_IOCTL_MODE_CURSOR:
> +		return drm_mode_cursor(tcp, code, arg);
> +	case DRM_IOCTL_MODE_CURSOR2:
> +		return drm_mode_cursor2(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETGAMMA:
> +		return drm_mode_get_gamma(tcp, code, arg);
> +	case DRM_IOCTL_MODE_SETGAMMA:
> +		return drm_mode_set_gamma(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETENCODER:
> +		return drm_mode_get_encoder(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETCONNECTOR:
> +		return drm_mode_get_connector(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETPROPERTY:
> +		return drm_mode_get_property(tcp, code, arg);
> +	case DRM_IOCTL_MODE_SETPROPERTY:
> +		return drm_mode_set_property(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETPROPBLOB:
> +		return drm_mode_get_prop_blob(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETFB:
> +		return drm_mode_get_fb(tcp, code, arg);
> +	case DRM_IOCTL_MODE_ADDFB:
> +		return drm_mode_add_fb(tcp, code, arg);
> +	case DRM_IOCTL_MODE_RMFB:
> +		return drm_mode_rm_fb(tcp, code, arg);
> +	case DRM_IOCTL_MODE_PAGE_FLIP:
> +		return drm_mode_page_flip(tcp, code, arg);
> +	case DRM_IOCTL_MODE_DIRTYFB:
> +		return drm_mode_dirty_fb(tcp, code, arg);
> +	case DRM_IOCTL_MODE_CREATE_DUMB:
> +		return drm_mode_create_dumb(tcp, code, arg);
> +	case DRM_IOCTL_MODE_MAP_DUMB:
> +		return drm_mode_map_dumb(tcp, code, arg);
> +	case DRM_IOCTL_MODE_DESTROY_DUMB:
> +		return drm_mode_destroy_dumb(tcp, code, arg);
> +	case DRM_IOCTL_GEM_CLOSE:
> +		return drm_gem_close(tcp, code, arg);
> +	}
> +

Just realized I'm leaking memory here because of those returns. Will take care
of that.

>  	/* Free any allocated private data */
>  	if (exiting(tcp) && tcp->priv_data != NULL) {
>  		free(tcp->priv_data);
> -- 
> 2.1.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Patch
diff mbox

diff --git a/drm.c b/drm.c
index 8e3f7d1..2e6d763 100644
--- a/drm.c
+++ b/drm.c
@@ -104,6 +104,463 @@  int drm_decode_number(struct tcb *tcp, unsigned int arg)
 	return 0;
 }
 
+static int drm_version(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_version ver;
+
+	if (umove(tcp, arg, &ver))
+		return 0;
+
+	if (exiting(tcp)) {
+		tprintf(", {version_major=%d, version_minor=%d, version_patchlevel=%d, "
+			"name_len=%lu, name=", ver.version_major,
+			ver.version_minor, ver.version_patchlevel,
+			ver.name_len);
+		printstr(tcp, (long)ver.name, ver.name_len);
+		tprintf(", date_len=%lu, date=", ver.date_len);
+		printstr(tcp, (long)ver.date, ver.date_len);
+		tprintf(", desc_len=%lu, desc=", ver.desc_len);
+		printstr(tcp, (long)ver.desc, ver.desc_len);
+		tprints("}");
+	}
+
+	return 1;
+}
+
+static int drm_get_unique(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_unique unique;
+
+	if (umove(tcp, arg, &unique))
+		return 0;
+
+	if (exiting(tcp)) {
+		tprintf(", {unique_len=%lu, unique=}", unique.unique_len);
+		printstr(tcp, (long)unique.unique, unique.unique_len);
+		tprints("}");
+	}
+
+	return 1;
+}
+
+static int drm_get_magic(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_auth auth;
+
+	if (umove(tcp, arg, &auth))
+		return 0;
+
+	if (exiting(tcp))
+		tprintf(", {magic=%u}", auth.magic);
+
+	return 1;
+}
+
+static int drm_wait_vblank(struct tcb *tcp, const unsigned int code, long arg)
+{
+	union drm_wait_vblank vblank;
+
+	if (umove(tcp, arg, &vblank))
+		return 0;
+
+	if (entering(tcp)) {
+		tprintf(", {request={type=%u, sequence=%u, signal=%lu}",
+			vblank.request.type, vblank.request.sequence,
+			vblank.request.signal);
+	} else if (exiting(tcp)) {
+		tprintf(", reply={type=%u, sequence=%u, tval_sec=%ld, tval_usec=%ld}}",
+			vblank.reply.type, vblank.reply.sequence,
+			vblank.reply.tval_sec, vblank.reply.tval_usec);
+	}
+
+	return 1;
+}
+
+static int drm_mode_get_resources(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_card_res res;
+
+	if (umove(tcp, arg, &res))
+		return 0;
+
+	if (exiting(tcp)) {
+		tprintf(", {fb_id_ptr=%p, crtc_id_ptr=%p, connector_id_ptr=%p, "
+			"encoder_id_ptr=%p, count_fbs=%u, count_crtcs=%u, "
+			"count_connectors=%u, count_encoders=%u, min_width=%u, "
+			"max_width=%u, min_height=%u, max_height=%u}",
+			(void *)res.fb_id_ptr, (void *)res.crtc_id_ptr,
+			(void *)res.connector_id_ptr, (void *)res.encoder_id_ptr,
+			res.count_fbs, res.count_crtcs, res.count_connectors,
+			res.count_encoders, res.min_width, res.max_width,
+			res.min_height, res.max_height);
+	}
+
+	return 1;
+}
+
+static void drm_mode_print_modeinfo(struct drm_mode_modeinfo *info)
+{
+	tprintf("clock=%u, hdisplay=%hu, hsync_start=%hu, hsync_end=%hu, "
+		"htotal=%hu, hskew=%hu, vdisplay=%hu, vsync_start=%hu, "
+		"vsync_end=%hu, vtotal=%hu, vscan=%hu, vrefresh=%u, "
+		"flags=0x%x, type=%u, name=%s", info->clock, info->hdisplay,
+		info->hsync_start, info->hsync_end, info->htotal, info->hskew,
+		info->vdisplay, info->vsync_start, info->vsync_end,
+		info->vtotal, info->vscan, info->vrefresh, info->flags,
+		info->type, info->name);
+}
+
+static int drm_mode_get_crtc(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_crtc crtc;
+
+	if (umove(tcp, arg, &crtc))
+		return 0;
+
+	if (entering(tcp)) {
+		tprintf(", {crtc_id=%u", crtc.crtc_id);
+	} else if (exiting(tcp)) {
+		tprintf(", set_connectors_ptr=%p, count_connectors=%u, "
+			"fb_id=%u, x=%u, y=%u, gamma_size=%u, mode_valid=%u, "
+			"mode={", (void *)crtc.set_connectors_ptr,
+			crtc.count_connectors, crtc.fb_id, crtc.x, crtc.y,
+			crtc.gamma_size, crtc.mode_valid);
+
+		drm_mode_print_modeinfo(&crtc.mode);
+		tprintf("}}");
+	}
+
+	return 1;
+}
+
+static int drm_mode_set_crtc(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_crtc crtc;
+
+	if (umove(tcp, arg, &crtc))
+		return 0;
+
+	if (entering(tcp)) {
+		tprintf(", {set_connectors_ptr=%p, count_connectors=%u, "
+			"crtc_id=%u, fb_id=%u, x=%u, y=%u, gamma_size=%u, "
+			"mode_valid=%u, mode={", (void *)crtc.set_connectors_ptr,
+			crtc.count_connectors, crtc.crtc_id, crtc.fb_id, crtc.x,
+			crtc.y, crtc.gamma_size, crtc.mode_valid);
+
+		drm_mode_print_modeinfo(&crtc.mode);
+		tprintf("}}");
+	}
+
+	return 1;
+}
+
+static int drm_mode_cursor(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_cursor cursor;
+
+	if (umove(tcp, arg, &cursor))
+		return 0;
+
+	if (entering(tcp)) {
+		tprintf(", {flags=0x%x, crtc_id=%u, x=%d, y=%d, width=%u, "
+			"height=%u, handle=%u}", cursor.flags, cursor.crtc_id,
+			cursor.x, cursor.y, cursor.width, cursor.height,
+			cursor.handle);
+	}
+
+	return 1;
+}
+
+static int drm_mode_cursor2(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_cursor2 cursor;
+
+	if (umove(tcp, arg, &cursor))
+		return 0;
+
+	if (entering(tcp)) {
+		tprintf(", {flags=0x%x, crtc_id=%u, x=%d, y=%d, width=%u, "
+			"height=%u, handle=%u, hot_x=%d, hot_y=%d}",
+			cursor.flags, cursor.crtc_id, cursor.x, cursor.y,
+			cursor.width, cursor.height, cursor.handle,
+			cursor.hot_x, cursor.hot_y);
+	}
+
+	return 1;
+}
+
+static int drm_mode_get_gamma(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_crtc_lut lut;
+
+	if (umove(tcp, arg, &lut))
+		return 0;
+
+	if (entering(tcp)) {
+		/* We don't print the entire table, just the pointers */
+		tprintf(", {crtc_id=%u, gamma_size=%u, red=%p, green=%p, "
+			"blue=%p}", lut.crtc_id, lut.gamma_size,
+			(void *)lut.red, (void *)lut.green, (void *)lut.blue);
+	}
+
+	return 1;
+}
+
+static int drm_mode_set_gamma(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_crtc_lut lut;
+
+	if (umove(tcp, arg, &lut))
+		return 0;
+
+	if (entering(tcp)) {
+		/* We don't print the entire table, just the rgb pointers */
+		tprintf(", {crtc_id=%u, gamma_size=%u, red=%p, green=%p, "
+			"blue=%p}", lut.crtc_id, lut.gamma_size,
+			(void *)lut.red, (void *)lut.green, (void *)lut.blue);
+	}
+
+	return 1;
+}
+
+static int drm_mode_get_encoder(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_get_encoder enc;
+
+	if (umove(tcp, arg, &enc))
+		return 0;
+
+	if (entering(tcp)) {
+		tprintf(", {encoder_id=%u", enc.encoder_id);
+	} else if (exiting(tcp)) {
+		/* TODO: Print name of encoder type */
+		tprintf(", encoder_type=%u, crtc_id=%u, possible_crtcs=0x%x, "
+			"possible_clones=0x%x}", enc.encoder_type,
+			enc.crtc_id, enc.possible_crtcs, enc.possible_clones);
+	}
+
+	return 1;
+}
+
+static int drm_mode_get_connector(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_get_connector con;
+
+	if (umove(tcp, arg, &con))
+		return 0;
+
+	/* We could be very verbose here but keep is simple for now */
+	if (entering(tcp)) {
+		tprintf(", {connector_id=%u", con.connector_id);
+	} else if (exiting(tcp)) {
+		tprintf(", encoders_ptr=%p, modes_ptr=%p, props_ptr=%p, "
+			"prop_values_ptr=%p, count_modes=%u, count_props=%u, "
+			"count_encoders=%u, encoder_id=%u, connector_type=%u, "
+			"connector_type_id=%u, connection=%u, mm_width=%u, "
+			"mm_height=%u, subpixel=%u}", (void *)con.encoders_ptr,
+			(void *)con.modes_ptr, (void *)con.props_ptr,
+			(void *)con.prop_values_ptr, con.count_modes,
+			con.count_props, con.count_encoders, con.encoder_id,
+			con.connector_type, con.connector_type_id,
+			con.connection, con.mm_width, con.mm_height,
+			con.subpixel);
+	}
+
+	return 1;
+}
+
+static int drm_mode_get_property(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_get_property prop;
+
+	if (umove(tcp, arg, &prop))
+		return 0;
+
+	if (entering(tcp)) {
+		tprintf(", {prop_id=%u", prop.prop_id);
+	} else if (exiting(tcp)) {
+		tprintf(", values_ptr=%p, enum_blob_ptr=%p, flags=0x%x, "
+			"name=%s, count_values=%u, count_enum_blobs=%u}",
+			(void *)prop.values_ptr, (void *)prop.enum_blob_ptr,
+			prop.flags, prop.name, prop.count_values,
+			prop.count_enum_blobs);
+	}
+
+	return 1;
+}
+
+static int drm_mode_set_property(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_connector_set_property prop;
+
+	if (umove(tcp, arg, &prop))
+		return 0;
+
+	if (entering(tcp)) {
+		tprintf(", {value=%Lu, prop_id=%u, connector_id=%u}",
+			prop.value, prop.prop_id, prop.connector_id);
+	}
+
+	return 1;
+}
+
+static int drm_mode_get_prop_blob(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_get_blob blob;
+
+	if (umove(tcp, arg, &blob))
+		return 0;
+
+	if (entering(tcp)) {
+		tprintf(", {blob_id=%u", blob.blob_id);
+	} else if (exiting(tcp)) {
+		tprintf(", length=%u, data=%p}", blob.length,
+			(void *)blob.data);
+	}
+
+	return 1;
+}
+
+static int drm_mode_add_fb(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_fb_cmd cmd;
+
+	if (umove(tcp, arg, &cmd))
+		return 0;
+
+	if (entering(tcp)) {
+		tprintf(", {width=%u, height=%u, pitch=%u, bpp=%u, depth=%u, "
+			"handle=%u", cmd.width, cmd.height, cmd.pitch,
+			cmd.bpp, cmd.depth, cmd.handle);
+	} else if (exiting(tcp)) {
+		tprintf(", fb_id=%u}", cmd.fb_id);
+	}
+
+	return 1;
+}
+
+static int drm_mode_get_fb(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_fb_cmd cmd;
+
+	if (umove(tcp, arg, &cmd))
+		return 0;
+
+	if (entering(tcp)) {
+		tprintf(", {fb_id=%u", cmd.fb_id);
+	} else {
+		tprintf(", width=%u, height=%u, pitch=%u, bpp=%u, depth=%u, "
+		"handle=%u}", cmd.width, cmd.height, cmd.pitch,
+		cmd.bpp, cmd.depth, cmd.handle);
+	}
+
+	return 1;
+}
+
+static int drm_mode_rm_fb(struct tcb *tcp, const unsigned int code, long arg)
+{
+	unsigned int handle;
+
+	if (umove(tcp, arg, &handle))
+		return 0;
+
+	if (entering(tcp))
+		tprintf(", %u", handle);
+
+	return 1;
+}
+
+static int drm_mode_page_flip(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_crtc_page_flip flip;
+
+	if (umove(tcp, arg, &flip))
+		return 0;
+
+	if (entering(tcp)) {
+		tprintf(", {crtc_id=%u, fb_id=%u, flags=0x%x, user_data=0x%Lx}",
+			flip.crtc_id, flip.fb_id, flip.flags, flip.user_data);
+	}
+
+	return 1;
+}
+
+static int drm_mode_dirty_fb(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_fb_dirty_cmd cmd;
+
+	if (umove(tcp, arg, &cmd))
+		return 0;
+
+	if (entering(tcp)) {
+		tprintf(", {fb_id=%u, flags=0x%x, color=0x%x, num_clips=%u, "
+			"clips_ptr=%p}", cmd.fb_id, cmd.flags, cmd.color,
+			cmd.num_clips, (void *)cmd.clips_ptr);
+	}
+
+	return 1;
+}
+
+static int drm_mode_create_dumb(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_create_dumb dumb;
+
+	if (umove(tcp, arg, &dumb))
+		return 0;
+
+	if (entering(tcp)) {
+		tprintf(", {width=%u, height=%u, bpp=%u, flags=0x%x",
+			dumb.width, dumb.height, dumb.bpp, dumb.flags);
+	} else if (exiting(tcp)) {
+		tprintf(", handle=%u, pitch=%u, size=%Lu}", dumb.handle,
+			dumb.pitch, dumb.size);
+	}
+
+	return 1;
+}
+
+static int drm_mode_map_dumb(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_map_dumb dumb;
+
+	if (umove(tcp, arg, &dumb))
+		return 0;
+
+	if (entering(tcp)) {
+		tprintf(", {handle=%u", dumb.handle);
+	} else if (exiting(tcp)) {
+		tprintf(", offset=%Lu}", dumb.offset);
+	}
+
+	return 1;
+}
+
+static int drm_mode_destroy_dumb(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_destroy_dumb dumb;
+
+	if (umove(tcp, arg, &dumb))
+		return 0;
+
+	if (entering(tcp))
+		tprintf(", {handle=%u}", dumb.handle);
+
+	return 1;
+}
+
+static int drm_gem_close(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_gem_close close;
+
+	if (umove(tcp, arg, &close))
+		return 0;
+
+	if (entering(tcp))
+		tprintf(", {handle=%u}", close.handle);
+
+	return 1;
+}
+
 int drm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 {
 	/* Check for device specific ioctls */
@@ -112,6 +569,59 @@  int drm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 			return drm_i915_ioctl(tcp, code, arg);
 	}
 
+	switch (code) {
+	case DRM_IOCTL_VERSION:
+		return drm_version(tcp, code, arg);
+	case DRM_IOCTL_GET_UNIQUE:
+		return drm_get_unique(tcp, code, arg);
+	case DRM_IOCTL_GET_MAGIC:
+		return drm_get_magic(tcp, code, arg);
+	case DRM_IOCTL_WAIT_VBLANK:
+		return drm_wait_vblank(tcp, code, arg);
+	case DRM_IOCTL_MODE_GETRESOURCES:
+		return drm_mode_get_resources(tcp, code, arg);
+	case DRM_IOCTL_MODE_GETCRTC:
+		return drm_mode_get_crtc(tcp, code, arg);
+	case DRM_IOCTL_MODE_SETCRTC:
+		return drm_mode_set_crtc(tcp, code, arg);
+	case DRM_IOCTL_MODE_CURSOR:
+		return drm_mode_cursor(tcp, code, arg);
+	case DRM_IOCTL_MODE_CURSOR2:
+		return drm_mode_cursor2(tcp, code, arg);
+	case DRM_IOCTL_MODE_GETGAMMA:
+		return drm_mode_get_gamma(tcp, code, arg);
+	case DRM_IOCTL_MODE_SETGAMMA:
+		return drm_mode_set_gamma(tcp, code, arg);
+	case DRM_IOCTL_MODE_GETENCODER:
+		return drm_mode_get_encoder(tcp, code, arg);
+	case DRM_IOCTL_MODE_GETCONNECTOR:
+		return drm_mode_get_connector(tcp, code, arg);
+	case DRM_IOCTL_MODE_GETPROPERTY:
+		return drm_mode_get_property(tcp, code, arg);
+	case DRM_IOCTL_MODE_SETPROPERTY:
+		return drm_mode_set_property(tcp, code, arg);
+	case DRM_IOCTL_MODE_GETPROPBLOB:
+		return drm_mode_get_prop_blob(tcp, code, arg);
+	case DRM_IOCTL_MODE_GETFB:
+		return drm_mode_get_fb(tcp, code, arg);
+	case DRM_IOCTL_MODE_ADDFB:
+		return drm_mode_add_fb(tcp, code, arg);
+	case DRM_IOCTL_MODE_RMFB:
+		return drm_mode_rm_fb(tcp, code, arg);
+	case DRM_IOCTL_MODE_PAGE_FLIP:
+		return drm_mode_page_flip(tcp, code, arg);
+	case DRM_IOCTL_MODE_DIRTYFB:
+		return drm_mode_dirty_fb(tcp, code, arg);
+	case DRM_IOCTL_MODE_CREATE_DUMB:
+		return drm_mode_create_dumb(tcp, code, arg);
+	case DRM_IOCTL_MODE_MAP_DUMB:
+		return drm_mode_map_dumb(tcp, code, arg);
+	case DRM_IOCTL_MODE_DESTROY_DUMB:
+		return drm_mode_destroy_dumb(tcp, code, arg);
+	case DRM_IOCTL_GEM_CLOSE:
+		return drm_gem_close(tcp, code, arg);
+	}
+
 	/* Free any allocated private data */
 	if (exiting(tcp) && tcp->priv_data != NULL) {
 		free(tcp->priv_data);