2 * Copyright (c) 2009 Ryan Huffman
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * Ryan Huffman (ryanhuffman@gmail.com)
28 #include <xf86Xinput.h>
29 #include <X11/extensions/XIproto.h>
30 #include <X11/extensions/XInput2.h>
31 #include <xf86_OSlib.h>
39 /* Module Functions */
41 TuioPlug(pointer
, pointer
, int *, int *);
46 /* Driver Functions */
48 TuioPreInit(InputDriverPtr
, IDevPtr
, int);
51 TuioUnInit(InputDriverPtr
, InputInfoPtr
, int);
54 TuioReadInput(InputInfoPtr
);
57 TuioControl(DeviceIntPtr
, int);
59 /* Internal Functions */
61 _tuio_init_buttons(DeviceIntPtr device
);
64 _tuio_init_axes(DeviceIntPtr device
);
67 _tuio_lo_cur2d_handle(const char *path
,
79 /* Object list manipulation functions */
81 _object_get(ObjectList list
, int id
);
84 _object_insert(ObjectList list
);
87 _object_remove(ObjectList list
, ObjectPtr obj
);
89 /* Driver information */
90 static XF86ModuleVersionInfo TuioVersionRec
=
97 PACKAGE_VERSION_MAJOR
, PACKAGE_VERSION_MINOR
, PACKAGE_VERSION_PATCHLEVEL
,
104 _X_EXPORT InputDriverRec TUIO
=
115 _X_EXPORT XF86ModuleData tuioModuleData
=
123 TuioPlug(pointer module
,
128 xf86AddInputDriver(&TUIO
, module
, 0);
134 TuioUnplug(pointer p
)
139 * Pre-initialization of new device
142 * - Parse configuration options
145 TuioPreInit(InputDriverPtr drv
,
152 if (!(pInfo
= xf86AllocateInput(drv
, 0)))
155 /* The TuioDevicePtr will hold our blobs */
156 pTuio
= xcalloc(1, sizeof(TuioDeviceRec
));
158 pInfo
->private = NULL
;
159 xf86DeleteInput(pInfo
, 0);
163 pInfo
->private = pTuio
;
165 /* Set up InputInfoPtr */
166 pInfo
->name
= xstrdup(dev
->identifier
);
168 pInfo
->type_name
= XI_TOUCHSCREEN
; /* FIXME: Correct type? */
169 pInfo
->conf_idev
= dev
;
170 pInfo
->read_input
= TuioReadInput
; /* Set callback */
171 pInfo
->device_control
= TuioControl
; /* Set callback */
172 pInfo
->switch_mode
= NULL
;
174 /* Process common device options */
175 xf86CollectInputOptions(pInfo
, NULL
, NULL
);
176 xf86ProcessCommonOptions(pInfo
, pInfo
->options
);
178 pInfo
->flags
|= XI86_OPEN_ON_INIT
;
179 pInfo
->flags
|= XI86_CONFIGURED
;
188 TuioUnInit(InputDriverPtr drv
,
192 TuioDevicePtr pTuio
= pInfo
->private;
195 xf86DeleteInput(pInfo
, 0);
199 * Handle new data on the socket
202 TuioReadInput(InputInfoPtr pInfo
)
204 TuioDevicePtr pTuio
= pInfo
->private;
205 ObjectList list
= pTuio
->list
;
206 ObjectPtr obj
= *list
;
209 while(xf86WaitForInput(pInfo
->fd
, 0) > 0)
211 /* liblo will receive a message and call the appropriate
212 * handlers (i.e. _tuio_lo_cur2d_hande())
213 * If nothing is found (this SHOULDN'T happen, but if it did,
214 * all the objects would be deleted), just return */
215 if(!lo_server_recv_noblock(pTuio
->server
, 0))
218 /* During the processing of the previous message/bundle,
219 * any "active" messages will be handled by flagging
220 * the listed object ids. Now that processing is done,
221 * remove any dead object ids. */
225 _object_remove(list
, obj
);
228 obj
->alive
= 0; /* Reset for next message */
236 * Handle device state changes
239 TuioControl(DeviceIntPtr device
,
242 InputInfoPtr pInfo
= device
->public.devicePrivate
;
243 TuioDevicePtr pTuio
= pInfo
->private;
248 xf86Msg(X_INFO
, "%s: Init\n", pInfo
->name
);
249 _tuio_init_buttons(device
);
250 _tuio_init_axes(device
);
253 case DEVICE_ON
: /* Open device socket and start listening! */
254 xf86Msg(X_INFO
, "%s: On.\n", pInfo
->name
);
255 if (device
->public.on
) /* already on! */
259 pTuio
->server
= lo_server_new_with_proto("3333", LO_UDP
, lo_error
);
260 if (pTuio
->server
== NULL
) {
261 xf86Msg(X_ERROR
, "%s: Error allocating new lo_server\n",
265 pTuio
->list
= xcalloc(1, sizeof(ObjectPtr
));
267 /* Register to receive all /tuio/2Dcur messages */
268 lo_server_add_method(pTuio
->server
, "/tuio/2Dcur", NULL
,
269 _tuio_lo_cur2d_handle
, pInfo
);
271 pInfo
->fd
= lo_server_get_socket_fd(pTuio
->server
);
272 xf86Msg(X_INFO
, "%s: Socket = %i\n", pInfo
->name
, pInfo
->fd
);
274 xf86AddEnabledDevice(pInfo
);
275 device
->public.on
= TRUE
;
279 xf86Msg(X_INFO
, "%s: Off\n", pInfo
->name
);
280 if (!device
->public.on
)
283 xf86RemoveEnabledDevice(pInfo
);
285 lo_server_free(pTuio
->server
);
287 device
->public.on
= FALSE
;
291 xf86Msg(X_INFO
, "%s: Close\n", pInfo
->name
);
293 lo_server_free(pTuio
->server
);
295 device
->public.on
= FALSE
;
303 _tuio_create_master() {
304 //XICreateMasterInfo ci;
305 //unsigned int blobid;
306 //char cur_name[21]; /* Max len: 20 char + \0 */
308 //sprintf(cur_name, "tuio_blob_%u", blobid);
310 //c.type = XICreateMaster;
315 * Handles OSC messages in the /tuio/2Dcur address space
318 _tuio_lo_cur2d_handle(const char *path
,
325 InputInfoPtr pInfo
= user_data
;
326 TuioDevicePtr pTuio
= pInfo
->private;
327 ObjectList list
= pTuio
->list
;
328 ObjectPtr obj
, objtemp
;
333 xf86Msg(X_ERROR
, "%s: \n", pInfo
->name
);
337 /* Parse message type */
339 /* Set message type: */
340 if (strcmp(argv
[0], "set") == 0) {
341 obj
= _object_get(list
, argv
[1]->i
);
343 obj
= _object_insert(list
);
344 obj
->id
= argv
[1]->i
;
350 /* THIS NEEDS TO BE FIXED!! */
351 valuators
[0] = obj
->x
* 0xFFFFFFFF;
352 valuators
[1] = obj
->y
* 0xFFFFFFFF;
354 xf86PostMotionEventP(pInfo
->dev
,
355 TRUE
, /* is_absolute */
356 0, /* first_valuator */
357 2, /* num_valuators */
360 } else if (strcmp(argv
[0], "alive") == 0) {
362 while (obj
!= NULL
) {
364 for (i
=1; i
<argc
; i
++) {
365 if (argv
[i
]->i
== obj
->id
) {
373 } else if (strcmp(argv
[0], "fseq") == 0) {
380 * liblo error handler
387 xf86Msg(X_ERROR
, "liblo: %s\n", msg
);
391 * Retrieves an object from a list based on its id. Returns NULL if
395 _object_get(ObjectList list
, int id
) {
396 ObjectPtr obj
= *list
;
398 while (obj
!= NULL
&& obj
->id
!= id
) {
406 * Allocates and inserts a new object at the beginning of a list.
407 * Pointer to the new object is returned.
410 _object_insert(ObjectList list
) {
411 ObjectPtr obj
= xcalloc(1, sizeof(ObjectRec
));
412 obj
->previous
= NULL
;
415 (*list
)->previous
= obj
;
421 * Removes an object from a list. It is assumed that the object
425 _object_remove(ObjectList list
, ObjectPtr obj
) {
426 if (obj
->next
!= NULL
)
427 obj
->next
->previous
= obj
->previous
;
429 if (obj
->previous
!= NULL
)
430 obj
->previous
->next
= obj
->next
;
437 * Init the button map device. We only use one button.
440 _tuio_init_buttons(DeviceIntPtr device
)
442 InputInfoPtr pInfo
= device
->public.devicePrivate
;
445 const int num_buttons
= 1; /* left-click */
449 map
= xcalloc(num_buttons
, sizeof(CARD8
));
450 labels
= xcalloc(num_buttons
, sizeof(Atom
));
452 for (i
= 0; i
< num_buttons
; i
++)
455 if (!InitButtonClassDeviceStruct(device
, num_buttons
,
456 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
460 xf86Msg(X_ERROR
, "%s: Failed to register buttons.\n", pInfo
->name
);
470 * Init valuators for device, use x/y coordinates.
473 _tuio_init_axes(DeviceIntPtr device
)
475 InputInfoPtr pInfo
= device
->public.devicePrivate
;
477 const int num_axes
= 2;
480 atoms
= xcalloc(2, sizeof(Atom
));
482 if (!InitValuatorClassDeviceStruct(device
,
484 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
487 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
490 GetMotionHistorySize(),
494 /* Use absolute mode. Currently, TUIO coords are mapped to the
495 * full screen area */
496 pInfo
->dev
->valuator
->mode
= Absolute
;
497 if (!InitAbsoluteClassDeviceStruct(device
))
500 for (i
= 0; i
< num_axes
; i
++)
502 xf86InitValuatorAxisStruct(device
, i
,
503 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
506 0, 0xFFFFFFFF, 1, 1, 1);
507 xf86InitValuatorDefaults(device
, i
);