1/*
2 * Copyright © 2003 Philip Blundell
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Philip Blundell not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Philip Blundell makes no
11 * representations about the suitability of this software for any purpose.  It
12 * is provided "as is" without express or implied warranty.
13 *
14 * PHILIP BLUNDELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL PHILIP BLUNDELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_KDRIVE_CONFIG_H
24#include <kdrive-config.h>
25#endif
26
27
28#include <X11/X.h>
29#include <X11/Xproto.h>
30#include "misc.h"
31#include "os.h"
32#include "dixstruct.h"
33#include "extnsionst.h"
34#include "swaprep.h"
35#include "protocol-versions.h"
36
37#include <X11/extensions/xcalibrateproto.h>
38#include <X11/extensions/xcalibratewire.h>
39
40extern void (*tslib_raw_event_hook)(int x, int y, int pressure, void *closure);
41extern void *tslib_raw_event_closure;
42
43static CARD8	XCalibrateReqCode;
44int		XCalibrateEventBase;
45int		XCalibrateReqBase;
46int		XCalibrateErrorBase;
47
48static ClientPtr xcalibrate_client;
49
50static void
51xcalibrate_event_hook (int x, int y, int pressure, void *closure)
52{
53  ClientPtr pClient = (ClientPtr) closure;
54  xXCalibrateRawTouchscreenEvent	ev;
55
56  ev.type = XCalibrateEventBase + X_XCalibrateRawTouchscreen;
57  ev.x = x;
58  ev.y = y;
59  ev.pressure = pressure;
60
61  WriteEventsToClient (pClient, 1, (xEvent *) &ev);
62}
63
64static int
65ProcXCalibrateQueryVersion (ClientPtr client)
66{
67  REQUEST(xXCalibrateQueryVersionReq);
68  xXCalibrateQueryVersionReply rep;
69  CARD16 client_major, client_minor;  /* not used */
70
71  REQUEST_SIZE_MATCH (xXCalibrateQueryVersionReq);
72
73  client_major = stuff->majorVersion;
74  client_minor = stuff->minorVersion;
75
76  fprintf(stderr, "%s(): called\n", __func__);
77
78  rep.type = X_Reply;
79  rep.length = 0;
80  rep.sequenceNumber = client->sequence;
81  rep.majorVersion = SERVER_XCALIBRATE_MAJOR_VERSION;
82  rep.minorVersion = SERVER_XCALIBRATE_MINOR_VERSION;
83  if (client->swapped) {
84    int n;
85    swaps(&rep.sequenceNumber, n);
86    swapl(&rep.length, n);
87    swaps(&rep.majorVersion, n);
88    swaps(&rep.minorVersion, n);
89  }
90  WriteToClient(client, sizeof (xXCalibrateQueryVersionReply), (char *)&rep);
91  return Success;
92}
93
94static int
95SProcXCalibrateQueryVersion (ClientPtr client)
96{
97    REQUEST(xXCalibrateQueryVersionReq);
98    int n;
99
100    REQUEST_SIZE_MATCH (xXCalibrateQueryVersionReq);
101    swaps(&stuff->majorVersion,n);
102    swaps(&stuff->minorVersion,n);
103    return ProcXCalibrateQueryVersion(client);
104}
105
106static int
107ProcXCalibrateSetRawMode (ClientPtr client)
108{
109  REQUEST(xXCalibrateRawModeReq);
110  xXCalibrateRawModeReply rep;
111
112  REQUEST_SIZE_MATCH (xXCalibrateRawModeReq);
113
114  memset (&rep, 0, sizeof (rep));
115  rep.type = X_Reply;
116  rep.sequenceNumber = client->sequence;
117
118  if (stuff->on)
119    {
120      if (xcalibrate_client == NULL)
121	{
122	  /* Start calibrating.  */
123	  xcalibrate_client = client;
124	  tslib_raw_event_hook = xcalibrate_event_hook;
125	  tslib_raw_event_closure = client;
126	  rep.status = GrabSuccess;
127	}
128      else
129	{
130	  rep.status = AlreadyGrabbed;
131	}
132    }
133  else
134    {
135      if (xcalibrate_client == client)
136	{
137	  /* Stop calibrating.  */
138	  xcalibrate_client = NULL;
139	  tslib_raw_event_hook = NULL;
140	  tslib_raw_event_closure = NULL;
141	  rep.status = GrabSuccess;
142
143	  /* Cycle input off and on to reload configuration.  */
144	  KdDisableInput ();
145	  KdEnableInput ();
146	}
147      else
148	{
149	  rep.status = AlreadyGrabbed;
150	}
151    }
152
153  if (client->swapped)
154    {
155      int n;
156
157      swaps (&rep.sequenceNumber, n);
158      swaps (&rep.status, n);
159    }
160  WriteToClient(client, sizeof (rep), (char *) &rep);
161  return Success;
162}
163
164static int
165SProcXCalibrateSetRawMode (ClientPtr client)
166{
167  REQUEST(xXCalibrateRawModeReq);
168  int n;
169
170  REQUEST_SIZE_MATCH (xXCalibrateRawModeReq);
171
172  swaps(&stuff->on, n);
173
174  return ProcXCalibrateSetRawMode(client);
175}
176
177static int
178ProcXCalibrateScreenToCoord (ClientPtr client)
179{
180  REQUEST(xXCalibrateScreenToCoordReq);
181  xXCalibrateScreenToCoordReply rep;
182
183  REQUEST_SIZE_MATCH (xXCalibrateScreenToCoordReq);
184
185  memset (&rep, 0, sizeof (rep));
186  rep.type = X_Reply;
187  rep.sequenceNumber = client->sequence;
188  rep.x = stuff->x;
189  rep.y = stuff->y;
190
191  KdScreenToPointerCoords(&rep.x, &rep.y);
192
193  if (client->swapped)
194    {
195      int n;
196
197      swaps (&rep.x, n);
198      swaps (&rep.y, n);
199    }
200  WriteToClient(client, sizeof (rep), (char *) &rep);
201  return Success;
202}
203
204static int
205SProcXCalibrateScreenToCoord (ClientPtr client)
206{
207  REQUEST(xXCalibrateScreenToCoordReq);
208  int n;
209
210  REQUEST_SIZE_MATCH (xXCalibrateScreenToCoordReq);
211
212  swaps(&stuff->x, n);
213  swaps(&stuff->y, n);
214
215  return ProcXCalibrateScreenToCoord(client);
216}
217
218static int
219ProcXCalibrateDispatch (ClientPtr client)
220{
221    REQUEST(xReq);
222    switch (stuff->data) {
223    case X_XCalibrateQueryVersion:
224        return ProcXCalibrateQueryVersion(client);
225    case X_XCalibrateRawMode:
226        return ProcXCalibrateSetRawMode(client);
227    case X_XCalibrateScreenToCoord:
228        return ProcXCalibrateScreenToCoord(client);
229
230    default: break;
231    }
232
233    return BadRequest;
234}
235
236static int
237SProcXCalibrateDispatch (ClientPtr client)
238{
239    REQUEST(xReq);
240    int n;
241
242    swaps(&stuff->length,n);
243
244    switch (stuff->data) {
245    case X_XCalibrateQueryVersion:
246        return SProcXCalibrateQueryVersion(client);
247    case X_XCalibrateRawMode:
248        return SProcXCalibrateSetRawMode(client);
249    case X_XCalibrateScreenToCoord:
250        return SProcXCalibrateScreenToCoord(client);
251
252    default: break;
253    }
254
255    return BadRequest;
256}
257
258static void
259XCalibrateClientCallback (CallbackListPtr	*list,
260			  pointer		closure,
261			  pointer		data)
262{
263    NewClientInfoRec	*clientinfo = (NewClientInfoRec *) data;
264    ClientPtr		pClient = clientinfo->client;
265
266    if (clientinfo->setup == NULL
267	&& xcalibrate_client != NULL
268	&& xcalibrate_client == pClient)
269      {
270	/* Stop calibrating.  */
271	xcalibrate_client = NULL;
272	tslib_raw_event_hook = NULL;
273	tslib_raw_event_closure = NULL;
274      }
275}
276
277void
278XCalibrateExtensionInit(void)
279{
280  ExtensionEntry *extEntry;
281
282  if (!AddCallback (&ClientStateCallback, XCalibrateClientCallback, 0))
283    return;
284
285  extEntry = AddExtension(XCALIBRATE_NAME, XCalibrateNumberEvents, XCalibrateNumberErrors,
286			  ProcXCalibrateDispatch, SProcXCalibrateDispatch,
287			  NULL, StandardMinorOpcode);
288
289  if (!extEntry)
290    return;
291
292  XCalibrateReqCode = (unsigned char)extEntry->base;
293  XCalibrateEventBase = extEntry->eventBase;
294  XCalibrateErrorBase = extEntry->errorBase;
295
296  xcalibrate_client = 0;
297}
298