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_lo_cur2d_handle(const char *path
,
69 _object_get(ObjectList list
, int id
);
72 _object_insert(ObjectList list
);
75 _object_remove(ObjectList list
, ObjectPtr obj
);
78 _tuio_init_buttons(DeviceIntPtr device
);
81 _tuio_init_axes(DeviceIntPtr device
);
89 static XF86ModuleVersionInfo TuioVersionRec
=
96 PACKAGE_VERSION_MAJOR
, PACKAGE_VERSION_MINOR
, PACKAGE_VERSION_PATCHLEVEL
,
103 _X_EXPORT InputDriverRec TUIO
=
114 _X_EXPORT XF86ModuleData tuioModuleData
=
122 TuioPlug(pointer module
,
127 xf86AddInputDriver(&TUIO
, module
, 0);
132 TuioUnplug(pointer p
)
137 * Pre-initialization of new device
140 * - Parse configuration options
141 * - Setup internal data
144 TuioPreInit(InputDriverPtr drv
,
152 if (!(pInfo
= xf86AllocateInput(drv
, 0)))
155 pTuio
= xcalloc(1, sizeof(TuioDeviceRec
));
157 pInfo
->private = NULL
;
158 xf86DeleteInput(pInfo
, 0);
162 pInfo
->private = pTuio
;
164 pInfo
->name
= xstrdup(dev
->identifier
);
166 pInfo
->type_name
= XI_TOUCHSCREEN
; /* FIXME: Correct type? */
167 pInfo
->conf_idev
= dev
;
168 pInfo
->read_input
= TuioReadInput
; /* Set callback */
169 pInfo
->switch_mode
= NULL
;
170 pInfo
->device_control
= TuioControl
; /* Set callback */
172 /* Process common device options */
173 xf86CollectInputOptions(pInfo
, NULL
, NULL
);
174 xf86ProcessCommonOptions(pInfo
, pInfo
->options
);
176 pInfo
->flags
|= XI86_OPEN_ON_INIT
;
177 pInfo
->flags
|= XI86_CONFIGURED
;
183 TuioUnInit(InputDriverPtr drv
,
187 TuioDevicePtr pTuio
= pInfo
->private;
190 xf86DeleteInput(pInfo
, 0);
194 * Handle new data on the socket
197 TuioReadInput(InputInfoPtr pInfo
)
199 TuioDevicePtr pTuio
= pInfo
->private;
202 while(xf86WaitForInput(pInfo
->fd
, 0) > 0)
204 lo_server_recv_noblock(pTuio
->server
, 0);
209 * Handle device state changes
212 TuioControl(DeviceIntPtr device
,
215 InputInfoPtr pInfo
= device
->public.devicePrivate
;
216 TuioDevicePtr pTuio
= pInfo
->private;
221 xf86Msg(X_INFO
, "%s: Init\n", pInfo
->name
);
222 _tuio_init_buttons(device
);
223 _tuio_init_axes(device
);
226 case DEVICE_ON
: /* Open device socket and start listening! */
227 xf86Msg(X_INFO
, "%s: On.\n", pInfo
->name
);
228 if (device
->public.on
) /* already on! */
231 pTuio
->server
= lo_server_new_with_proto("3333", LO_UDP
, lo_error
);
232 if (pTuio
->server
== NULL
) {
233 xf86Msg(X_ERROR
, "%s: Error allocating new lo_server\n",
237 pTuio
->list
= xcalloc(1, sizeof(ObjectPtr
));
240 /* Register to receive all /tuio/2Dcur messages */
241 lo_server_add_method(pTuio
->server
, "/tuio/2Dcur", NULL
,
242 _tuio_lo_cur2d_handle
, pInfo
);
244 pInfo
->fd
= lo_server_get_socket_fd(pTuio
->server
);
245 xf86Msg(X_INFO
, "%s: Socket = %i\n", pInfo
->name
, pInfo
->fd
);
247 //xf86FlushInput(pInfo->fd);
248 xf86AddEnabledDevice(pInfo
);
249 device
->public.on
= TRUE
;
253 xf86Msg(X_INFO
, "%s: Off\n", pInfo
->name
);
254 if (!device
->public.on
)
257 xf86RemoveEnabledDevice(pInfo
);
259 lo_server_free(pTuio
->server
);
262 device
->public.on
= FALSE
;
266 xf86Msg(X_INFO
, "%s: Close\n", pInfo
->name
);
268 lo_server_free(pTuio
->server
);
270 device
->public.on
= FALSE
;
278 _tuio_create_master() {
279 //XICreateMasterInfo ci;
280 //unsigned int blobid;
281 //char cur_name[21]; /* Max len: 20 char + \0 */
283 //sprintf(cur_name, "tuio_blob_%u", blobid);
285 //c.type = XICreateMaster;
290 * Handles OSC messages in the /tuio/2Dcur address space
293 _tuio_lo_cur2d_handle(const char *path
,
300 InputInfoPtr pInfo
= user_data
;
301 TuioDevicePtr pTuio
= pInfo
->private;
302 ObjectList list
= pTuio
->list
;
303 ObjectPtr obj
, objtemp
;
308 xf86Msg(X_ERROR
, "%s: \n", pInfo
->name
);
312 /* Parse message type */
313 if (!strcmp(argv
[0], "set")) {
314 obj
= _object_get(list
, argv
[1]->i
);
316 obj
= _object_insert(list
);
317 obj
->id
= argv
[1]->i
;
321 valuators
[0] = obj
->x
* 1400;
322 valuators
[1] = obj
->y
* 1050;
323 xf86PostMotionEventP(pInfo
->dev
,
324 TRUE
, /* is_absolute */
325 0, /* first_valuator */
326 2, /* num_valuators */
329 } else if (!strcmp(argv
[0], "alive")) {
331 while (obj
!= NULL
) {
333 for (i
=1; i
<argc
; i
++) {
334 if (argv
[i
]->i
== obj
->id
) {
341 _object_remove(list
, obj
);
349 } else if (!strcmp(argv
[0], "fseq")) {
356 * liblo error handler
363 xf86Msg(X_ERROR
, "liblo: %s\n", msg
);
367 _object_get(ObjectList list
, int id
) {
368 ObjectPtr obj
= *list
;
370 while (obj
!= NULL
&& obj
->id
!= id
) {
378 _object_insert(ObjectList list
) {
379 ObjectPtr obj
= xcalloc(1, sizeof(ObjectRec
));
380 obj
->previous
= NULL
;
383 (*list
)->previous
= obj
;
389 _object_remove(ObjectList list
, ObjectPtr obj
) {
390 if (obj
->next
!= NULL
)
391 obj
->next
->previous
= obj
->previous
;
393 if (obj
->previous
!= NULL
)
394 obj
->previous
->next
= obj
->next
;
401 * Init the button map for the random device.
402 * @return Success or X error code on failure.
405 _tuio_init_buttons(DeviceIntPtr device
)
407 InputInfoPtr pInfo
= device
->public.devicePrivate
;
411 const int num_buttons
= 2;
414 map
= xcalloc(num_buttons
, sizeof(CARD8
));
415 labels
= xalloc(num_buttons
* sizeof(Atom
));
417 for (i
= 0; i
< num_buttons
; i
++)
420 if (!InitButtonClassDeviceStruct(device
, num_buttons
,
421 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
425 xf86Msg(X_ERROR
, "%s: Failed to register buttons.\n", pInfo
->name
);
435 * Init the valuators for the random device.
436 * Only absolute mode is supported.
437 * @return Success or X error code on failure.
440 _tuio_init_axes(DeviceIntPtr device
)
442 InputInfoPtr pInfo
= device
->public.devicePrivate
;
444 const int num_axes
= 2;
447 atoms
= xalloc(2 * sizeof(Atom
));
449 if (!InitValuatorClassDeviceStruct(device
,
451 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
454 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
457 GetMotionHistorySize(),
461 pInfo
->dev
->valuator
->mode
= Absolute
;
462 if (!InitAbsoluteClassDeviceStruct(device
))
465 for (i
= 0; i
< num_axes
; i
++)
467 xf86InitValuatorAxisStruct(device
, i
,
468 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
472 xf86InitValuatorDefaults(device
, i
);