FreeRDP
Loading...
Searching...
No Matches
client/ainput_main.c
1
21#include <freerdp/config.h>
22
23#include <stdio.h>
24#include <stdlib.h>
25
26#include <winpr/crt.h>
27#include <winpr/assert.h>
28#include <winpr/stream.h>
29#include <winpr/sysinfo.h>
30
31#include "ainput_main.h"
32#include <freerdp/channels/log.h>
33#include <freerdp/client/channels.h>
34#include <freerdp/client/ainput.h>
35#include <freerdp/channels/ainput.h>
36
37#include "../common/ainput_common.h"
38
39#define TAG CHANNELS_TAG("ainput.client")
40
41typedef struct AINPUT_PLUGIN_ AINPUT_PLUGIN;
42struct AINPUT_PLUGIN_
43{
45 AInputClientContext* context;
46 UINT32 MajorVersion;
47 UINT32 MinorVersion;
48};
49
55static UINT ainput_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* data)
56{
57 UINT16 type = 0;
58 AINPUT_PLUGIN* ainput = NULL;
59 GENERIC_CHANNEL_CALLBACK* callback = (GENERIC_CHANNEL_CALLBACK*)pChannelCallback;
60
61 WINPR_ASSERT(callback);
62 WINPR_ASSERT(data);
63
64 ainput = (AINPUT_PLUGIN*)callback->plugin;
65 WINPR_ASSERT(ainput);
66
67 if (!Stream_CheckAndLogRequiredLength(TAG, data, 2))
68 return ERROR_NO_DATA;
69 Stream_Read_UINT16(data, type);
70 switch (type)
71 {
72 case MSG_AINPUT_VERSION:
73 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
74 return ERROR_NO_DATA;
75 Stream_Read_UINT32(data, ainput->MajorVersion);
76 Stream_Read_UINT32(data, ainput->MinorVersion);
77 break;
78 default:
79 WLog_WARN(TAG, "Received unsupported message type 0x%04" PRIx16, type);
80 break;
81 }
82
83 return CHANNEL_RC_OK;
84}
85
86static UINT ainput_send_input_event(AInputClientContext* context, UINT64 flags, INT32 x, INT32 y)
87{
88 AINPUT_PLUGIN* ainput = NULL;
89 GENERIC_CHANNEL_CALLBACK* callback = NULL;
90 BYTE buffer[32] = { 0 };
91 UINT64 time = 0;
92 wStream sbuffer = { 0 };
93 wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
94
95 WINPR_ASSERT(s);
96 WINPR_ASSERT(context);
97
98 time = GetTickCount64();
99 ainput = (AINPUT_PLUGIN*)context->handle;
100 WINPR_ASSERT(ainput);
101
102 if (ainput->MajorVersion != AINPUT_VERSION_MAJOR)
103 {
104 WLog_WARN(TAG, "Unsupported channel version %" PRIu32 ".%" PRIu32 ", aborting.",
105 ainput->MajorVersion, ainput->MinorVersion);
106 return CHANNEL_RC_UNSUPPORTED_VERSION;
107 }
108 callback = ainput->base.listener_callback->channel_callback;
109 WINPR_ASSERT(callback);
110
111 {
112 char ebuffer[128] = { 0 };
113 WLog_VRB(TAG, "sending timestamp=0x%08" PRIx64 ", flags=%s, %" PRId32 "x%" PRId32, time,
114 ainput_flags_to_string(flags, ebuffer, sizeof(ebuffer)), x, y);
115 }
116
117 /* Message type */
118 Stream_Write_UINT16(s, MSG_AINPUT_MOUSE);
119
120 /* Event data */
121 Stream_Write_UINT64(s, time);
122 Stream_Write_UINT64(s, flags);
123 Stream_Write_INT32(s, x);
124 Stream_Write_INT32(s, y);
125 Stream_SealLength(s);
126
127 /* ainput back what we have received. AINPUT does not have any message IDs. */
128 WINPR_ASSERT(callback->channel);
129 WINPR_ASSERT(callback->channel->Write);
130 return callback->channel->Write(callback->channel, (ULONG)Stream_Length(s), Stream_Buffer(s),
131 NULL);
132}
133
139static UINT ainput_on_close(IWTSVirtualChannelCallback* pChannelCallback)
140{
141 GENERIC_CHANNEL_CALLBACK* callback = (GENERIC_CHANNEL_CALLBACK*)pChannelCallback;
142
143 free(callback);
144
145 return CHANNEL_RC_OK;
146}
147
148static UINT init_plugin_cb(GENERIC_DYNVC_PLUGIN* base, WINPR_ATTR_UNUSED rdpContext* rcontext,
149 WINPR_ATTR_UNUSED rdpSettings* settings)
150{
151 AINPUT_PLUGIN* ainput = (AINPUT_PLUGIN*)base;
152 AInputClientContext* context = (AInputClientContext*)calloc(1, sizeof(AInputClientContext));
153 if (!context)
154 return CHANNEL_RC_NO_MEMORY;
155
156 context->handle = (void*)base;
157 context->AInputSendInputEvent = ainput_send_input_event;
158
159 ainput->context = context;
160 ainput->base.iface.pInterface = context;
161 return CHANNEL_RC_OK;
162}
163
164static void terminate_plugin_cb(GENERIC_DYNVC_PLUGIN* base)
165{
166 AINPUT_PLUGIN* ainput = (AINPUT_PLUGIN*)base;
167 free(ainput->context);
168}
169
170static const IWTSVirtualChannelCallback ainput_functions = { ainput_on_data_received,
171 NULL, /* Open */
172 ainput_on_close, NULL };
173
179FREERDP_ENTRY_POINT(UINT VCAPITYPE ainput_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
180{
181 return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, AINPUT_DVC_CHANNEL_NAME,
182 sizeof(AINPUT_PLUGIN), sizeof(GENERIC_CHANNEL_CALLBACK),
183 &ainput_functions, init_plugin_cb, terminate_plugin_cb);
184}