hgsmi_base.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // SPDX-License-Identifier: MIT
  2. /* Copyright (C) 2006-2017 Oracle Corporation */
  3. #include <linux/vbox_err.h>
  4. #include "vbox_drv.h"
  5. #include "vboxvideo_guest.h"
  6. #include "vboxvideo_vbe.h"
  7. #include "hgsmi_channels.h"
  8. #include "hgsmi_ch_setup.h"
  9. /**
  10. * hgsmi_report_flags_location - Inform the host of the location of
  11. * the host flags in VRAM via an HGSMI cmd.
  12. * Return: 0 or negative errno value.
  13. * @ctx: The context of the guest heap to use.
  14. * @location: The offset chosen for the flags within guest VRAM.
  15. */
  16. int hgsmi_report_flags_location(struct gen_pool *ctx, u32 location)
  17. {
  18. struct hgsmi_buffer_location *p;
  19. p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_HGSMI,
  20. HGSMI_CC_HOST_FLAGS_LOCATION);
  21. if (!p)
  22. return -ENOMEM;
  23. p->buf_location = location;
  24. p->buf_len = sizeof(struct hgsmi_host_flags);
  25. hgsmi_buffer_submit(ctx, p);
  26. hgsmi_buffer_free(ctx, p);
  27. return 0;
  28. }
  29. /**
  30. * hgsmi_send_caps_info - Notify the host of HGSMI-related guest capabilities
  31. * via an HGSMI command.
  32. * Return: 0 or negative errno value.
  33. * @ctx: The context of the guest heap to use.
  34. * @caps: The capabilities to report, see vbva_caps.
  35. */
  36. int hgsmi_send_caps_info(struct gen_pool *ctx, u32 caps)
  37. {
  38. struct vbva_caps *p;
  39. p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA, VBVA_INFO_CAPS);
  40. if (!p)
  41. return -ENOMEM;
  42. p->rc = VERR_NOT_IMPLEMENTED;
  43. p->caps = caps;
  44. hgsmi_buffer_submit(ctx, p);
  45. WARN_ON_ONCE(p->rc < 0);
  46. hgsmi_buffer_free(ctx, p);
  47. return 0;
  48. }
  49. int hgsmi_test_query_conf(struct gen_pool *ctx)
  50. {
  51. u32 value = 0;
  52. int ret;
  53. ret = hgsmi_query_conf(ctx, U32_MAX, &value);
  54. if (ret)
  55. return ret;
  56. return value == U32_MAX ? 0 : -EIO;
  57. }
  58. /**
  59. * hgsmi_query_conf - Query the host for an HGSMI configuration
  60. * parameter via an HGSMI command.
  61. * Return: 0 or negative errno value.
  62. * @ctx: The context containing the heap used.
  63. * @index: The index of the parameter to query.
  64. * @value_ret: Where to store the value of the parameter on success.
  65. */
  66. int hgsmi_query_conf(struct gen_pool *ctx, u32 index, u32 *value_ret)
  67. {
  68. struct vbva_conf32 *p;
  69. p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA,
  70. VBVA_QUERY_CONF32);
  71. if (!p)
  72. return -ENOMEM;
  73. p->index = index;
  74. p->value = U32_MAX;
  75. hgsmi_buffer_submit(ctx, p);
  76. *value_ret = p->value;
  77. hgsmi_buffer_free(ctx, p);
  78. return 0;
  79. }
  80. /**
  81. * hgsmi_update_pointer_shape - Pass the host a new mouse pointer shape
  82. * via an HGSMI command.
  83. * Return: 0 or negative errno value.
  84. * @ctx: The context containing the heap to be used.
  85. * @flags: Cursor flags.
  86. * @hot_x: Horizontal position of the hot spot.
  87. * @hot_y: Vertical position of the hot spot.
  88. * @width: Width in pixels of the cursor.
  89. * @height: Height in pixels of the cursor.
  90. * @pixels: Pixel data, @see VMMDevReqMousePointer for the format.
  91. * @len: Size in bytes of the pixel data.
  92. */
  93. int hgsmi_update_pointer_shape(struct gen_pool *ctx, u32 flags,
  94. u32 hot_x, u32 hot_y, u32 width, u32 height,
  95. u8 *pixels, u32 len)
  96. {
  97. struct vbva_mouse_pointer_shape *p;
  98. u32 pixel_len = 0;
  99. int rc;
  100. if (flags & VBOX_MOUSE_POINTER_SHAPE) {
  101. /*
  102. * Size of the pointer data:
  103. * sizeof (AND mask) + sizeof (XOR_MASK)
  104. */
  105. pixel_len = ((((width + 7) / 8) * height + 3) & ~3) +
  106. width * 4 * height;
  107. if (pixel_len > len)
  108. return -EINVAL;
  109. /*
  110. * If shape is supplied, then always create the pointer visible.
  111. * See comments in 'vboxUpdatePointerShape'
  112. */
  113. flags |= VBOX_MOUSE_POINTER_VISIBLE;
  114. }
  115. p = hgsmi_buffer_alloc(ctx, sizeof(*p) + pixel_len, HGSMI_CH_VBVA,
  116. VBVA_MOUSE_POINTER_SHAPE);
  117. if (!p)
  118. return -ENOMEM;
  119. p->result = VINF_SUCCESS;
  120. p->flags = flags;
  121. p->hot_X = hot_x;
  122. p->hot_y = hot_y;
  123. p->width = width;
  124. p->height = height;
  125. if (pixel_len)
  126. memcpy(p->data, pixels, pixel_len);
  127. hgsmi_buffer_submit(ctx, p);
  128. switch (p->result) {
  129. case VINF_SUCCESS:
  130. rc = 0;
  131. break;
  132. case VERR_NO_MEMORY:
  133. rc = -ENOMEM;
  134. break;
  135. case VERR_NOT_SUPPORTED:
  136. rc = -EBUSY;
  137. break;
  138. default:
  139. rc = -EINVAL;
  140. }
  141. hgsmi_buffer_free(ctx, p);
  142. return rc;
  143. }
  144. /**
  145. * hgsmi_cursor_position - Report the guest cursor position. The host may
  146. * wish to use this information to re-position its
  147. * own cursor (though this is currently unlikely).
  148. * The current host cursor position is returned.
  149. * Return: 0 or negative errno value.
  150. * @ctx: The context containing the heap used.
  151. * @report_position: Are we reporting a position?
  152. * @x: Guest cursor X position.
  153. * @y: Guest cursor Y position.
  154. * @x_host: Host cursor X position is stored here. Optional.
  155. * @y_host: Host cursor Y position is stored here. Optional.
  156. */
  157. int hgsmi_cursor_position(struct gen_pool *ctx, bool report_position,
  158. u32 x, u32 y, u32 *x_host, u32 *y_host)
  159. {
  160. struct vbva_cursor_position *p;
  161. p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA,
  162. VBVA_CURSOR_POSITION);
  163. if (!p)
  164. return -ENOMEM;
  165. p->report_position = report_position;
  166. p->x = x;
  167. p->y = y;
  168. hgsmi_buffer_submit(ctx, p);
  169. *x_host = p->x;
  170. *y_host = p->y;
  171. hgsmi_buffer_free(ctx, p);
  172. return 0;
  173. }