sylware / xalga (public) (License: Unspecified) (since 2019-09-09) (hash sha1)
my old xorg ddx to go with my old gpu driver (has interesting code)
List of commits:
Subject Hash Author Date (UTC)
archive old xalga code (has interesting code) 25d156a68fdb9b34342eaf85ab07362c0a094cfb Sylvain BERTRAND 2018-06-05 14:10:47
Commit 25d156a68fdb9b34342eaf85ab07362c0a094cfb - archive old xalga code (has interesting code)
Author: Sylvain BERTRAND
Author date (UTC): 2018-06-05 14:10
Committer name: Sylvain BERTRAND
Committer date (UTC): 2018-06-05 14:10
Parent(s):
Signing key:
Tree: fa8ce07f0450a0e2d2dadd41dfc5297c215c1f83
File Lines added Lines deleted
README 3 0
hw/xalga/Makefile.am 36 0
hw/xalga/README 9 0
hw/xalga/ddx.c 237 0
hw/xalga/evdev/axis/rel.c 226 0
hw/xalga/evdev/evdev.c 345 0
hw/xalga/evdev/input-event.c 167 0
hw/xalga/evdev/key/key-btn.c 403 0
hw/xalga/evdev/key/key-key.c 197 0
hw/xalga/evdev/key/key.c 55 0
hw/xalga/output.c 931 0
hw/xalga/xalga/evdev/axis/rel.h 25 0
hw/xalga/xalga/evdev/evdev.h 78 0
hw/xalga/xalga/evdev/input-event.h 10 0
hw/xalga/xalga/evdev/key/key-btn.h 11 0
hw/xalga/xalga/evdev/key/key-key.h 10 0
hw/xalga/xalga/evdev/key/key.h 10 0
hw/xalga/xalga/evdev/key/private.h 12 0
hw/xalga/xalga/evdev/private.h 31 0
hw/xalga/xalga/namespace.h 18 0
hw/xalga/xalga/output.h 9 0
include/xalga_glx_extinit.h 9 0
xalgaglx/Makefile.am 10 0
xalgaglx/glxext.c 79 0
File README added (mode: 100644) (index 0000000..1fcb9f7)
1 this is my old xserver ddx for my custom amd gpu si driver.
2
3 Contain easy code to know how to boostrap your own xserver ddx.
File hw/xalga/Makefile.am added (mode: 100644) (index 0000000..b5239d3)
1 bin_PROGRAMS = Xalga
2
3 Xalga_CFLAGS = $(DIX_CFLAGS)
4
5 #miinitext.c is not in mi lib cause it's source based...
6 #idem for Xext/dpmsstubs and Xi/stubs
7 Xalga_SOURCES = \
8 ddx.c \
9 output.c \
10 evdev/evdev.c \
11 evdev/input-event.c \
12 evdev/axis/rel.c \
13 evdev/key/key.c \
14 evdev/key/key-key.c \
15 evdev/key/key-btn.c \
16 $(top_srcdir)/Xext/dpmsstubs.c \
17 $(top_srcdir)/Xi/stubs.c \
18 $(top_srcdir)/mi/miinitext.c
19
20 #XSERVER_SYS_LIBS are out-of-tree libs. For instance pkgconfig based libs. Not
21 #used to track dependencies.
22 #XSERVER_LIBS are xserver in-tree libs, used to track dependencies.
23 Xalga_LDADD = \
24 $(XALGA_LIBS) \
25 $(XSERVER_LIBS) \
26 $(XSERVER_SYS_LIBS)
27
28 Xalga_DEPENDENCIES = \
29 $(XALGA_LIBS) \
30 $(XSERVER_LIBS)
31
32 #we need that to export xserver symbols because they will be used by modules
33 Xalga_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
34
35 relink:
36 $(AM_V_at)rm -f Xalga$(EXEEXT) && $(MAKE) Xalga$(EXEEXT)
File hw/xalga/README added (mode: 100644) (index 0000000..d465e8e)
1 This is an harcoded ddx on my custom linux graphic driver.
2
3 The intent is not to provide a fully dynamically configurable xserver.
4
5 Using this code as a base to bootstrap your own ddx is way easier than
6 what is provided by default by the xserver source code.
7
8 The header files are in the xalga subdirectory in order to avoid name conflicts
9 with the xserver header files.
File hw/xalga/ddx.c added (mode: 100644) (index 0000000..d992b77)
1 /*
2 * XALGA implementation
3 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
4 * Opens source legal protection provided by a GNU Lesser GPLv3 license
5 */
6 #define _POSIX_C_SOURCE 200809L /* scandir */
7 #include <linux/input.h>
8 #include <errno.h>
9 #include <unistd.h>
10 #include <dirent.h>
11
12 #include "dix-config.h"
13 #include "extension.h"
14 #include "screenint.h"
15 #include "scrnintstr.h"
16 #include "servermd.h"
17 #include "mi.h"
18 #include "input.h"
19 #include "list.h"
20
21 #include "xalga_glx_extinit.h"
22
23 #include "xalga/namespace.h"
24 #include "xalga/output.h"
25 #include "xalga/evdev/axis/rel.h"
26 #include "xalga/evdev/evdev.h"
27
28
29 /*----------------------------------------------------------------------------*/
30 /* we do the link with our GLX implementation here */
31 static Bool no_xalga_glx_extension = FALSE;
32 static const ExtensionModule xalga_extensions[] = {
33 {xalga_glx_extension_init, "GLX", &no_xalga_glx_extension}
34 };
35 /*----------------------------------------------------------------------------*/
36
37
38 /*----------------------------------------------------------------------------*/
39 /* hardcoded evdev devices for pointers and keyboards */
40 static struct xorg_list evdevs_head;
41 /*----------------------------------------------------------------------------*/
42
43
44 /*----------------------------------------------------------------------------*/
45 static int event_filter(const struct dirent *dirent);
46 static void event_add(struct dirent *dirent, long fs_name_sz_max);
47 /*----------------------------------------------------------------------------*/
48
49
50 /******************************************************************************/
51 /* in this section, you will have the mandatory entry points for a ddx */
52 void
53 DDXRingBell(int volume, int pitch, int duration)
54 {
55 }
56
57 void
58 ProcessInputEvents(void)
59 {
60 mieqProcessInputEvents();
61 }
62
63 Bool
64 LegalModifier(unsigned int key, DeviceIntPtr pDev)
65 {
66 return TRUE;
67 }
68
69 int
70 ddxProcessArgument(int argc, char *argv[], int i)
71 {
72 return 0;
73 }
74
75 void
76 ddxUseMsg(void)
77 {
78 }
79
80 void
81 ddxGiveUp(enum ExitCode error)
82 {
83 ErrorF("ddxGiveUp\n");
84 }
85
86 void
87 AbortDDX(enum ExitCode error)
88 {
89 ErrorF("AbortDDX\n");
90 ddxGiveUp(error);
91 }
92
93 void
94 OsVendorFatalError(const char *f, va_list args)
95 {
96 }
97
98 void
99 OsVendorInit(void)
100 {
101 }
102
103 static int
104 event_filter(const struct dirent *dirent)
105 {
106 /* yes, this is really basic */
107 if (strstr(dirent->d_name, "event"))
108 return 1;
109 return 0;
110 }
111
112 #define DEV_INPUT "/dev/input"
113 static
114 void event_add(struct dirent *dirent, long fs_name_sz_max)
115 {
116 char *dev_path;
117 Bool r;
118 struct evdev *evdev;
119
120 dev_path = xnfcalloc(1, strlen(DEV_INPUT) + strlen("/") + fs_name_sz_max
121 + strlen("\0"));
122 strcpy(dev_path, DEV_INPUT);
123 strcat(dev_path, "/");
124 strcat(dev_path, dirent->d_name);
125
126 evdev = xnfcalloc(1, sizeof(*evdev));
127 evdev->dev_path = dev_path;
128 evdev->xkb.rules = xnfstrdup("evdev");
129 evdev->xkb.model = xnfstrdup("tm2030USB");
130 evdev->xkb.layout = xnfstrdup("dvorak");
131 evdev->xkb.variant = NULL;
132 evdev->xkb.options = xnfstrdup("compose:ralt");
133
134 ErrorF("adding %s\n", evdev->dev_path);
135 r = evdev_init(evdev);
136 if (!r) {
137 ErrorF("unable to init %s\n", evdev->dev_path);
138 if (evdev->xkb.options)
139 free(evdev->xkb.options);
140 if (evdev->xkb.variant)
141 free(evdev->xkb.variant);
142 if (evdev->xkb.layout)
143 free(evdev->xkb.layout);
144 if (evdev->xkb.model)
145 free(evdev->xkb.model);
146 free(evdev->xkb.rules);
147 free(dev_path);
148 free(evdev);
149 } else
150 xorg_list_add(&evdev->entry, &evdevs_head);
151 free(dirent);
152 }
153
154 #define FS_NAME_SZ_MAX_DEFAULT 256
155 void
156 InitInput(int argc, char *argv[])
157 {
158 struct dirent **dirents;
159 int dirents_cnt;
160 int dirents_idx;
161 long fs_name_sz_max;
162
163 /*
164 * this is Machine Independent event queue for input device **internal**
165 * event processing
166 */
167 mieqInit();
168
169 /* we open all evdev devices */
170 xorg_list_init(&evdevs_head);
171
172 /*------------------------------------------------------------------------*/
173 errno = 0;
174 fs_name_sz_max = pathconf(DEV_INPUT, _PC_NAME_MAX);
175 if (fs_name_sz_max == -1)
176 fs_name_sz_max = FS_NAME_SZ_MAX_DEFAULT;
177 /*------------------------------------------------------------------------*/
178
179 /*------------------------------------------------------------------------*/
180 dirents_cnt = scandir(DEV_INPUT, &dirents, event_filter, NULL);
181
182 if (dirents_cnt == -1) {
183 ErrorF("unable to scan the dir " DEV_INPUT "\n");
184 return;
185 }
186 /*------------------------------------------------------------------------*/
187
188 dirents_idx = dirents_cnt;
189
190 while (dirents_idx--)
191 event_add(dirents[dirents_idx], fs_name_sz_max);
192
193 free(dirents);
194 return;
195 }
196
197 void
198 CloseInput(void)
199 {
200 /* evdev file descriptors cleanup everything properly at process shutdown */
201
202 /* TODO: cleanup input device OS resources */
203 mieqFini();
204 }
205
206 void
207 InitOutput(ScreenInfo *screen_info, int argc, char **argv)
208 {
209 int depths[] = {1, 4, 8, 15, 16, 24, 32};
210 int bpp[] = {1, 8, 8, 16, 16, 32, 32};
211 u8 i;
212 int r;
213
214 (void)argc;
215 (void)argv;
216
217 for (i = 0; i < ARRAY_SIZE(depths); ++i) {
218 screen_info->formats[i].depth = depths[i];
219 screen_info->formats[i].bitsPerPixel = bpp[i];
220 screen_info->formats[i].scanlinePad = BITMAP_SCANLINE_PAD;
221 }
222
223 screen_info->imageByteOrder = IMAGE_BYTE_ORDER;
224 screen_info->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
225 screen_info->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
226 screen_info->bitmapBitOrder = BITMAP_BIT_ORDER;
227 screen_info->numPixmapFormats = ARRAY_SIZE(depths);
228
229 LoadExtensionList(xalga_extensions, ARRAY_SIZE(xalga_extensions), FALSE);
230
231 /* XXX:strange, we add a screen whatever */
232 r = AddScreen(screen_init, argc, argv);
233 if (r == -1)
234 FatalError("couldn't add screen\n");
235 ErrorF("ddx InitOutput successful\n");
236 }
237 /******************************************************************************/
File hw/xalga/evdev/axis/rel.c added (mode: 100644) (index 0000000..ab9adf2)
1 /*
2 * XALGA implementation
3 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
4 * Opens source legal protection provided by a GNU Lesser GPLv3 license
5 */
6 #include <stdint.h>
7 #include <sys/ioctl.h>
8 #include <linux/input.h>
9
10 #include "dix-config.h"
11 #include "inpututils.h"
12 #include "input.h"
13 #include "xserver-properties.h"
14 #include "exevents.h"
15
16 #include "xalga/namespace.h"
17 #define XALGA_EVDEV_AXIS_REL_C
18 #include "xalga/evdev/axis/rel.h"
19 #include "xalga/evdev/evdev.h"
20
21 #include "xalga/evdev/private.h"
22
23 struct rel_axis_desc {
24 long bit_idx;
25 const char *dix_name;
26
27 /* if we want a dix scrolling valuator for this axis */
28 u8 scroll_type;
29 u8 scroll_flags; /* to select a prefered scroll valuator */
30 };
31
32 static struct rel_axis_desc rel_axes_desc[REL_CNT] = {
33 {REL_X, AXIS_LABEL_PROP_REL_X,SCROLL_TYPE_NONE, SCROLL_FLAG_NONE},
34 {REL_Y, AXIS_LABEL_PROP_REL_Y, SCROLL_TYPE_NONE, SCROLL_FLAG_NONE},
35 {REL_Z, AXIS_LABEL_PROP_REL_Z, SCROLL_TYPE_NONE, SCROLL_FLAG_NONE},
36 {REL_RX, AXIS_LABEL_PROP_REL_RX, SCROLL_TYPE_NONE, SCROLL_FLAG_NONE},
37 {REL_RY, AXIS_LABEL_PROP_REL_RY, SCROLL_TYPE_NONE, SCROLL_FLAG_NONE},
38 {REL_RZ, AXIS_LABEL_PROP_REL_RZ, SCROLL_TYPE_NONE, SCROLL_FLAG_NONE},
39 {REL_HWHEEL, AXIS_LABEL_PROP_REL_HWHEEL, SCROLL_TYPE_HORIZONTAL,
40 SCROLL_FLAG_NONE},
41 {REL_DIAL, AXIS_LABEL_PROP_REL_DIAL, SCROLL_TYPE_HORIZONTAL,
42 SCROLL_FLAG_NONE},
43 {REL_WHEEL, AXIS_LABEL_PROP_REL_WHEEL, SCROLL_TYPE_VERTICAL,
44 SCROLL_FLAG_PREFERRED},
45 {REL_MISC, AXIS_LABEL_PROP_REL_MISC, SCROLL_TYPE_NONE, SCROLL_FLAG_NONE},
46 {REL_MAX, "unknown axis label", SCROLL_TYPE_NONE, SCROLL_FLAG_NONE},
47 {REL_MAX, "unknown axis label", SCROLL_TYPE_NONE, SCROLL_FLAG_NONE},
48 {REL_MAX, "unknown axis label", SCROLL_TYPE_NONE, SCROLL_FLAG_NONE},
49 {REL_MAX, "unknown axis label", SCROLL_TYPE_NONE, SCROLL_FLAG_NONE},
50 {REL_MAX, "unknown axis label", SCROLL_TYPE_NONE, SCROLL_FLAG_NONE},
51 {REL_MAX, "unknown axis label", SCROLL_TYPE_NONE, SCROLL_FLAG_NONE}
52 };
53
54 Bool
55 rel_axes_codes_get(struct evdev *evdev)
56 {
57 int r;
58
59 r = ioctl(evdev->fd, EVIOCGBIT(EV_REL, sizeof(evdev->rel_codes)),
60 evdev->rel_codes);
61 if (r == -1) {
62 ErrorF("unable to query the supported evdev rel codes\n");
63 return FALSE;
64 }
65 return TRUE;
66 }
67
68 /* here we stack all the relative axes supported by this evdev device */
69 void
70 rel_axes_get(struct dix_init_data *init_data)
71 {
72 struct evdev *evdev;
73 Atom *labels;
74 u8 *scroll_type;
75 u8 *scroll_flags;
76 u8 dix_rel_axis;
77 u8 rel_axis;
78 u8 supported_rel_axis;
79
80 ErrorF("getting supported evdev rel axes...\n");
81
82 evdev = init_data->dix->public.devicePrivate;
83
84 dix_rel_axis = init_data->dix_axes_cnt; /* first available dix axis index */
85
86 supported_rel_axis = 0;
87 labels = &init_data->rel_axes.labels[0];
88 scroll_type = &init_data->rel_axes.scroll_type[0];
89 scroll_flags = &init_data->rel_axes.scroll_flags[0];
90
91 /* init the evdev -> dix mapping */
92 for (rel_axis = 0; rel_axis < REL_CNT; ++rel_axis)
93 evdev->rel_axes_dix_map[rel_axis] = -1;
94
95 for (rel_axis = 0; rel_axis < REL_CNT; ++rel_axis)
96 if (IS_BIT_SET(evdev->rel_codes, rel_axes_desc[rel_axis].bit_idx)) {
97 ErrorF("%s axis supported\n", rel_axes_desc[rel_axis].dix_name);
98
99 labels[supported_rel_axis] = XIGetKnownProperty(
100 rel_axes_desc[rel_axis].dix_name);
101 scroll_type[supported_rel_axis] =
102 rel_axes_desc[rel_axis].scroll_type;
103 scroll_flags[supported_rel_axis] =
104 rel_axes_desc[rel_axis].scroll_flags;
105
106 evdev->rel_axes_dix_map[rel_axis] = dix_rel_axis;
107 ++supported_rel_axis;
108 ++dix_rel_axis;
109 }
110
111 init_data->rel_axes.cnt = supported_rel_axis;
112 }
113
114 void
115 rel_axis_code_dispatch(DeviceIntPtr dix, struct input_event *e)
116 {
117 struct evdev *evdev;
118 int dix_axis;
119 ValuatorMask mask;
120
121 valuator_mask_zero(&mask);
122
123 evdev = dix->public.devicePrivate;
124 dix_axis = evdev->rel_axes_dix_map[e->code];
125
126 if (dix_axis != -1) {/* only if that evdev axis is mapped */
127 valuator_mask_set(&mask, dix_axis, (int)e->value);
128 QueuePointerEvents(dix, MotionNotify, 0, 0, &mask);
129 }
130 }
131
132 static void
133 feedback_ctl(DeviceIntPtr device, PtrCtrl *ctrl)
134 {
135 /* Nothing to do, dix handles all settings */
136 }
137
138 Bool
139 dix_rel_axes_register(struct dix_init_data *init_data)
140 {
141 Bool r;
142 u8 axis;
143
144 if (!init_data->rel_axes.cnt) {
145 ErrorF("no evdev rel axes to register in dix\n");
146 return TRUE;
147 }
148
149 ErrorF("registering %u relative axes in dix...\n", init_data->rel_axes.cnt);
150
151 /*
152 * XXX: this is really ugly. For an dix input device valuators of all axes
153 * should be allocated with this function, absolute or relative
154 * with/without a proximity class (which get allocated *only* here with
155 * the OutOfProximity mode flag. Since, it's exclusive, a dix input device
156 * should be created for each type of valuator an evdev device has.
157 * You can "overwrite" the relative/absolute mode by re-configuring each
158 * axis with the following InitValuatorAxisStruct.
159 */
160 r = InitValuatorClassDeviceStruct(init_data->dix, init_data->rel_axes.cnt,
161 &init_data->rel_axes.labels[0], GetMotionHistorySize(), Relative);
162 if (!r) {
163 ErrorF("unable to alloc the valuator class device struct for relative axes\n");
164 return FALSE;
165 }
166
167 r = InitPtrFeedbackClassDeviceStruct(init_data->dix, feedback_ctl);
168 if (!r) {
169 ErrorF("unable to init the pointer feedback class device struct for relative axes\n");
170 return FALSE;
171 }
172
173 for (axis = 0; axis < init_data->rel_axes.cnt; ++axis) {
174 double delta;
175 const char *type;
176 const char *flags;
177
178 r = InitValuatorAxisStruct(init_data->dix, axis,
179 init_data->rel_axes.labels[axis], NO_AXIS_LIMITS,
180 NO_AXIS_LIMITS, 1, 0, 1, Relative);
181 if (!r) {
182 ErrorF("unable to configure resolution/min/max for axis %u\n", axis);
183 return FALSE;
184 }
185
186 if (init_data->rel_axes.scroll_type[axis] == SCROLL_TYPE_NONE)
187 continue;
188
189 if (init_data->rel_axes.scroll_type[axis] == SCROLL_TYPE_VERTICAL)
190 delta = -1.0;
191 else
192 delta = 1.0;
193
194 /*--------------------------------------------------------------------*/
195 if (init_data->rel_axes.scroll_type[axis] == SCROLL_TYPE_VERTICAL)
196 type = "vertical";
197 else
198 type = "horizontal";
199
200 if (init_data->rel_axes.scroll_flags[axis] == SCROLL_FLAG_PREFERRED)
201 flags = " prefered";
202 else
203 flags = "";
204
205 ErrorF("registering%s %s scroll valuator on axis %u with a delta of %f\n",
206 flags, type, axis, delta);
207 /*--------------------------------------------------------------------*/
208
209 /*
210 * XXX: carefull, there is only one valuator created per axis. The
211 * "scroll valuator" is actually an extra/extension input class to the
212 * the valuator axis class. Yes, this is actually really awkward.
213 * Hopefully the original writters did not use syntax rich/object
214 * oriented language which would have given us a massive object
215 * orientish kludge.
216 */
217 r = SetScrollValuator(init_data->dix, axis,
218 init_data->rel_axes.scroll_type[axis], delta,
219 init_data->rel_axes.scroll_flags[axis]);
220 if (!r) {
221 ErrorF("unable to register scroll valuator for axis %u\n", axis);
222 return FALSE;
223 }
224 }
225 return TRUE;
226 }
File hw/xalga/evdev/evdev.c added (mode: 100644) (index 0000000..7e773e8)
1 /*
2 * XALGA implementation
3 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
4 * Opens source legal protection provided by a GNU Lesser GPLv3 license
5 */
6 #include <unistd.h>
7 #include <sys/ioctl.h>
8 #include <fcntl.h>
9 #include <libgen.h>
10 #include <linux/input.h>
11
12
13 #include "dix-config.h"
14 #include "input.h"
15 #include "exevents.h"
16 #include "xserver-properties.h"
17 #include "extinit.h"
18
19 #include "xalga/namespace.h"
20 #include "xalga/evdev/axis/rel.h"
21 #define XALGA_EVDEV_EVDEV_C
22 #include "xalga/evdev/evdev.h"
23 #include "xalga/evdev/private.h"
24 #include "xalga/evdev/input-event.h"
25 #include "xalga/evdev/key/key.h"
26 #include "xalga/evdev/key/key-key.h"
27 #include "xalga/evdev/key/key-btn.h"
28
29
30 /*----------------------------------------------------------------------------*/
31 static Bool event_types_get(struct evdev *evdev);
32 static Bool init_data_collect(struct dix_init_data *init_data);
33 /*----------------------------------------------------------------------------*/
34
35
36 /*----------------------------------------------------------------------------*/
37 static Bool dix_register(struct dix_init_data *init_data);
38
39 static int dix_proc(DeviceIntPtr dix, int what);
40 static int dix_init(DeviceIntPtr dix);
41 static int dix_on(DeviceIntPtr dix);
42 static void dix_off(DeviceIntPtr dix);
43 /*----------------------------------------------------------------------------*/
44
45
46 static int
47 dix_proc(DeviceIntPtr dix, int what)
48 {
49 int r;
50 struct evdev *evdev;
51
52 r = BadMatch;
53
54 switch (what) {
55 case DEVICE_INIT:
56 r = dix_init(dix);
57 break;
58 case DEVICE_ON:
59 r = dix_on(dix);
60 break;
61 case DEVICE_OFF:
62 dix_off(dix);
63 r = Success;
64 break;
65 case DEVICE_CLOSE:
66 ErrorF("closing input device...\n");
67 if (dix->public.on) {
68 ErrorF("the input device is closed before being turned off, turning off now\n");
69 dix_off(dix);
70 }
71 /*
72 * XXX: for the moment, only happening at server shutdown then, just
73 * do basic cleanup (even if it's useless)
74 */
75 evdev = dix->public.devicePrivate;
76 if (evdev->xkb.options)
77 free(evdev->xkb.options);
78 if (evdev->xkb.variant)
79 free(evdev->xkb.variant);
80 if (evdev->xkb.layout)
81 free(evdev->xkb.layout);
82 if (evdev->xkb.model)
83 free(evdev->xkb.model);
84 free(evdev->xkb.rules);
85 free(evdev->dev_path);
86 close(evdev->fd);
87 xorg_list_del(&evdev->entry);
88 free(evdev);
89 break;
90 }
91 return r;
92 }
93
94 static Bool
95 event_types_get(struct evdev *evdev)
96 {
97 int r;
98
99 r = ioctl(evdev->fd, EVIOCGBIT(0, sizeof(evdev->event_types)),
100 evdev->event_types);
101 if (r == -1) {
102 ErrorF("unable to query the supported evdev event types\n");
103 return FALSE;
104 }
105 return TRUE;
106 }
107
108 static Bool
109 init_data_collect(struct dix_init_data *init_data)
110 {
111 struct evdev *evdev;
112 Bool r;
113
114 evdev = init_data->dix->public.devicePrivate;
115
116 if (IS_BIT_SET(evdev->event_types, EV_REL)) {
117 ErrorF("evdev rel events supported\n");
118
119 r = rel_axes_codes_get(evdev);
120 if (!r)
121 return FALSE;
122
123 rel_axes_get(init_data);
124 }
125
126 /* XXX: I don't support ABS axes yet */
127
128 if (IS_BIT_SET(evdev->event_types, EV_KEY)) {
129 ErrorF("evdev key events supported\n");
130
131 r = key_codes_get(evdev);
132 if (!r)
133 return FALSE;
134
135 key_btns_get(init_data);
136 key_keys_get(init_data);
137 }
138 return TRUE;
139 }
140
141 static Bool
142 dix_register(struct dix_init_data *init_data)
143 {
144 Bool r;
145
146 r = dix_keys_register(init_data);
147 if (!r)
148 return FALSE;
149
150 r = dix_btns_register(init_data);
151 if (!r)
152 return FALSE;
153
154 r = dix_rel_axes_register(init_data);
155 if (!r)
156 return FALSE;
157 return TRUE;
158 }
159
160 static int
161 dix_init(DeviceIntPtr dix)
162 {
163 struct evdev *evdev;
164 Bool r;
165 struct dix_init_data dix_init_data;
166
167 evdev = dix->public.devicePrivate;
168
169 ErrorF("initing dix device for evdev %s...\n", evdev->dev_path);
170
171 evdev->fd = open(evdev->dev_path, O_RDWR | O_NONBLOCK);
172 if (evdev->fd == -1) {
173 ErrorF("unable to open the evdev file descriptor\n");
174 return BadValue;
175 }
176
177 r = event_types_get(evdev);
178 if (!r)
179 goto err_close_evdev_fd;
180
181 memset(&dix_init_data, 0, sizeof(dix_init_data));
182 dix_init_data.dix = dix;
183
184 r = init_data_collect(&dix_init_data);
185 if (!r)
186 goto err_close_evdev_fd;
187
188 r = dix_register(&dix_init_data);
189 if (!r)
190 goto err_close_evdev_fd;
191
192 return Success;
193
194 err_close_evdev_fd:
195 close(evdev->fd);
196 return BadValue;
197 }
198
199 /*
200 * This is called after the dix waitforsomething select. The err parameter
201 * contain the return value from the select (error or not), or a dix
202 * specific error. The read_mask is the FD_SET of file descriptors available
203 * for reading.
204 */
205 static void
206 wakeup_handler(void *data, int err, void *read_mask)
207 {
208 DeviceIntPtr dix;
209 struct evdev *evdev;
210
211 /* the dix waitforsomething select is in error or the dix */
212 if (err < 0)
213 return;
214
215 dix = data;
216 evdev = dix->public.devicePrivate;
217
218 if (FD_ISSET(evdev->fd, (fd_set*)read_mask))
219 read_buf_processing(dix);
220 }
221
222 static int
223 dix_on(DeviceIntPtr dix)
224 {
225 struct evdev *evdev;
226 Bool r;
227
228 evdev = dix->public.devicePrivate;
229
230 ErrorF("switching on evdev device %s...\n", evdev->dev_path);
231
232 evdev->read_buf = read_buf_alloc();
233 if (!evdev->read_buf)
234 return BadValue;
235
236 /*
237 * The block handler is called before the dix waitforsomething select.
238 * The wakeup handler is called after the dix waitforsomething select
239 * with the result of the select in err parameter.
240 * We don't have a block handler here.
241 */
242 r = RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
243 wakeup_handler, dix);
244 if (!r) {
245 ErrorF("unable to add pointer wakeup handler\n");
246 goto err_free_read_buf;
247 }
248
249 /*
250 * this will add the file descriptor to the dix
251 * dispatch/waitforsomething core loop. Do not mixup that API with the
252 * API from AddInputDevice which is at other level.
253 * Reading from this file destriptor will be done in the "wakeup handler".
254 */
255 AddEnabledDevice(evdev->fd);
256
257 evdev->overrun = FALSE;
258 dix->public.on = TRUE;
259 return Success;
260
261 err_free_read_buf:
262 free(evdev->read_buf);
263 return BadValue;
264 }
265
266 static void
267 dix_off(DeviceIntPtr dix)
268 {
269 struct evdev *evdev;
270
271 evdev = dix->public.devicePrivate;
272
273 ErrorF("switching off evdev device %s...\n", evdev->dev_path);
274
275 RemoveEnabledDevice(evdev->fd);
276
277 RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, wakeup_handler,
278 dix);
279
280 free(evdev->read_buf);
281 dix->public.on = FALSE;
282 }
283
284 /*----------------------------------------------------------------------------*/
285 #define EVDEV_ATOM_TYPE_NAME "evdev"
286 #define FS_NAME_SZ_MAX_DEFAULT 256
287 Bool
288 evdev_init(struct evdev *evdev)
289 {
290 static Atom type_atom = None;
291 int r;
292 long fs_name_sz_max; /* fs stands for filesystem */
293 char *atom_name;
294 ul atom_name_sz;
295 char *dev_path_dup;
296 char *dev_path_basename;
297
298 /* evdev->dev_path is usually something like /dev/input/event16 */
299 fs_name_sz_max = pathconf(evdev->dev_path, _PC_NAME_MAX);
300 if (fs_name_sz_max == -1)
301 fs_name_sz_max = FS_NAME_SZ_MAX_DEFAULT;
302
303 dev_path_dup = xnfstrdup(evdev->dev_path);
304 dev_path_basename = basename(dev_path_dup); /* POSIX and not GNU behavior */
305
306 atom_name_sz = sizeof(EVDEV_ATOM_TYPE_NAME "-") + strlen(dev_path_basename);
307 atom_name = xnfalloc(atom_name_sz);
308 snprintf(atom_name, atom_name_sz, "%s-%s", EVDEV_ATOM_TYPE_NAME,
309 dev_path_basename);
310 free(dev_path_dup);
311
312 /*
313 * XXX: due to the weird and ugly dix api method
314 * "InitValuatorClassDeviceStruct", an evdev device should be split in
315 * several dix input devices for relative, absolute with/without proximity.
316 * axis support.
317 */
318 evdev->dix = AddInputDevice(serverClient, dix_proc, TRUE);
319 if (!evdev->dix) {
320 ErrorF("unable to add the evdev device to dix input subsystem\n");
321 return FALSE;
322 }
323 evdev->dix->public.devicePrivate = evdev;
324
325 /* the type atom is made only once, then static */
326 if (type_atom == None) {
327 type_atom = MakeAtom(EVDEV_ATOM_TYPE_NAME,
328 sizeof(EVDEV_ATOM_TYPE_NAME) - 1, TRUE);
329 if(type_atom == BAD_RESOURCE) {
330 ErrorF("unable to make a type atom for evdev\n");
331 goto err_remove_device;
332 }
333 }
334 AssignTypeAndName(evdev->dix, type_atom, atom_name);
335 evdev->dix->type = SLAVE;
336 evdev->dix->spriteInfo->spriteOwner = FALSE;
337 return TRUE;
338
339 err_remove_device:
340 r = RemoveDevice(evdev->dix, TRUE);
341 if (r != Success)
342 ErrorF("something went wrong while removing the dix device\n");
343 return FALSE;
344 }
345 /*----------------------------------------------------------------------------*/
File hw/xalga/evdev/input-event.c added (mode: 100644) (index 0000000..c32aa1f)
1 /*
2 * XALGA implementation
3 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
4 * Opens source legal protection provided by a GNU Lesser GPLv3 license
5 */
6 #include <fcntl.h>
7 #include <errno.h>
8 #include <unistd.h>
9 #include <linux/input.h>
10
11 #include "dix-config.h"
12 #include "inputstr.h"
13 #include "input.h"
14
15 #include "xalga/namespace.h"
16 #include "xalga/evdev/axis/rel.h"
17 #include "xalga/evdev/key/key.h"
18 #include "xalga/evdev/evdev.h"
19
20 #define LINUX_INPUT_EVENTS_CNT 32
21
22
23 /*----------------------------------------------------------------------------*/
24 static void sync_report(DeviceIntPtr dix_dev, struct input_event *e);
25 static void sync_dropped(DeviceIntPtr dix_dev, struct input_event *e);
26 static void sync_code_dispatch(DeviceIntPtr dix_dev, struct input_event *e);
27 static void type_dispatch(DeviceIntPtr dix_dev, struct input_event *e);
28 static void buf_parse(DeviceIntPtr dix, ssize_t r);
29
30 void read_buf_processing(DeviceIntPtr dix);
31 void* read_buf_alloc(void);
32 /*----------------------------------------------------------------------------*/
33
34
35 static void
36 sync_report(DeviceIntPtr dix, struct input_event *e)
37 {
38 struct evdev *evdev;
39 evdev = dix->public.devicePrivate;
40
41 if (evdev->overrun) {/* input event dropping recovered */
42 evdev->overrun = FALSE;
43 return;
44 }
45 }
46
47 static void
48 sync_dropped(DeviceIntPtr dix, struct input_event *e)
49 {
50 struct evdev *evdev;
51 evdev = dix->public.devicePrivate;
52
53 /* we have to drop all input events till the next SYN_REPORT */
54 evdev->overrun = TRUE;
55 }
56
57 static void
58 sync_code_dispatch(DeviceIntPtr dix, struct input_event *e)
59 {
60 switch (e->code) {
61 case SYN_REPORT:
62 sync_report(dix, e);
63 break;
64 case SYN_DROPPED:
65 sync_dropped(dix, e);
66 break;
67 default:
68 /* ignore */
69 break;
70 };
71 }
72
73 static void
74 type_dispatch(DeviceIntPtr dix, struct input_event *e)
75 {
76 struct evdev *evdev;
77
78 evdev = dix->public.devicePrivate;
79
80 /*
81 * cannot be skipped as a whole if evdev_overrun since it's there where
82 * a evdev_overrun is notified to be fixed
83 */
84 if (e->type == EV_SYN) {
85 sync_code_dispatch(dix, e);
86 return;
87 }
88
89 if (!evdev->overrun)
90 switch (e->type) {
91 case EV_REL:
92 rel_axis_code_dispatch(dix, e);
93 break;
94 case EV_KEY:
95 key_code_dispatch(dix, e);
96 break;
97 default:
98 /* ignore */
99 break;
100 };
101 }
102
103 static void
104 buf_parse(DeviceIntPtr dix, ssize_t r)
105 {
106 struct evdev *evdev;
107 u8 events_cnt;
108 struct input_event *input_event;
109
110 evdev = dix->public.devicePrivate;
111
112 if ((r % sizeof(struct input_event)) != 0) {
113 ErrorF("evdev input events corrupted, discarding\n");
114 return;
115 }
116
117 events_cnt = r / sizeof(struct input_event);
118 input_event = evdev->read_buf;
119
120 while (events_cnt--)
121 type_dispatch(dix, input_event++);
122 }
123
124 void
125 read_buf_processing(DeviceIntPtr dix)
126 {
127 struct evdev *evdev;
128 ssize_t r;
129
130 evdev = dix->public.devicePrivate;
131
132 while (1) {
133 errno = 0;
134 r = read(evdev->fd, evdev->read_buf, (size_t)(LINUX_INPUT_EVENTS_CNT
135 * sizeof(struct input_event)));
136 if (r == -1) {
137 if (errno == EAGAIN || errno == EWOULDBLOCK)
138 break;
139 if (errno == EINTR)
140 continue;
141 ErrorF("error while reading the evdev buffer\n");
142 return;
143 }
144 if (r == 0) {/* should never happen since no end of file for evdev */
145 ErrorF("end of file? Hot removal of device?");
146 return;
147 }
148 buf_parse(dix, r);
149 }
150 }
151
152 void *
153 read_buf_alloc(void)
154 {
155 void *read_buf;
156
157 read_buf = calloc(LINUX_INPUT_EVENTS_CNT, sizeof(struct input_event));
158 if (read_buf) {
159 ErrorF("allocated evdev buffer for %u linux input events of %tu bytes\n",
160 LINUX_INPUT_EVENTS_CNT, sizeof(struct input_event));
161 } else {
162 ErrorF("unable to allocate evdev read buffer, %u linux input events of %tu bytes\n",
163 LINUX_INPUT_EVENTS_CNT, sizeof(struct input_event));
164 }
165 return read_buf;
166 }
167
File hw/xalga/evdev/key/key-btn.c added (mode: 100644) (index 0000000..0d5ae46)
1 /*
2 * XALGA implementation
3 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
4 * Opens source legal protection provided by a GNU Lesser GPLv3 license
5 */
6 #include <linux/input.h>
7
8 #include "dix-config.h"
9 #include "input.h"
10 #include "xserver-properties.h"
11 #include "exevents.h"
12
13 #include "xalga/namespace.h"
14 #include "xalga/evdev/axis/rel.h"
15 #include "xalga/evdev/evdev.h"
16 #include "xalga/evdev/private.h"
17
18 struct btn {
19 long evdev_bit;
20 int dix;
21 const char *name;
22 };
23
24 /*----------------------------------------------------------------------------*/
25 static void btns_section_map(struct dix_init_data *init_data,
26 struct btn *evdev_section, long evdev_section_btns_n,
27 int *dix_map, u16 evdev_mask);
28
29 /* public */
30 void key_btns_get(struct dix_init_data *init_data);
31 Bool dix_btns_register(struct dix_init_data *init_data);
32
33 /* private to evdev/key */
34 void btn_process(DeviceIntPtr dix, struct input_event *e, u16 btn_section_mask);
35 u16 btn_section_mask_get(u16 code);
36 /*----------------------------------------------------------------------------*/
37
38
39 /*----------------------------------------------------------------------------*/
40 /* follow the dix button mapping found in xorg ddx evdev driver */
41 static struct btn btns_section_misc[] = {
42 {BTN_0, 1, BTN_LABEL_PROP_BTN_0},
43 {BTN_1, 2, BTN_LABEL_PROP_BTN_1},
44 {BTN_2, 3, BTN_LABEL_PROP_BTN_2},
45 {BTN_3, 8, BTN_LABEL_PROP_BTN_3},
46 {BTN_4, 9, BTN_LABEL_PROP_BTN_4},
47 {BTN_5, 10, BTN_LABEL_PROP_BTN_5},
48 {BTN_6, 11, BTN_LABEL_PROP_BTN_6},
49 {BTN_7, 12, BTN_LABEL_PROP_BTN_7},
50 {BTN_8, 13, BTN_LABEL_PROP_BTN_8},
51 {BTN_9, 14, BTN_LABEL_PROP_BTN_9}
52 };
53
54 static struct btn btns_section_mouse[] = {
55 {BTN_LEFT, 1, BTN_LABEL_PROP_BTN_LEFT},
56 {BTN_RIGHT, 3, BTN_LABEL_PROP_BTN_RIGHT},
57 {BTN_MIDDLE, 2, BTN_LABEL_PROP_BTN_MIDDLE},
58 {BTN_SIDE, 8, BTN_LABEL_PROP_BTN_SIDE},
59 {BTN_EXTRA, 9, BTN_LABEL_PROP_BTN_EXTRA},
60 {BTN_FORWARD, 10, BTN_LABEL_PROP_BTN_FORWARD},
61 {BTN_BACK, 11, BTN_LABEL_PROP_BTN_BACK},
62 {BTN_TASK, 12, BTN_LABEL_PROP_BTN_TASK}
63 };
64
65 static struct btn btns_section_joystick[] = {
66 {BTN_TRIGGER, 0, BTN_LABEL_PROP_BTN_TRIGGER},
67 {BTN_THUMB, 0, BTN_LABEL_PROP_BTN_THUMB},
68 {BTN_THUMB2, 0, BTN_LABEL_PROP_BTN_THUMB2},
69 {BTN_TOP, 0, BTN_LABEL_PROP_BTN_TOP},
70 {BTN_TOP2, 0, BTN_LABEL_PROP_BTN_TOP2},
71 {BTN_PINKIE, 0, BTN_LABEL_PROP_BTN_PINKIE},
72 {BTN_BASE, 0, BTN_LABEL_PROP_BTN_BASE},
73 {BTN_BASE2, 0, BTN_LABEL_PROP_BTN_BASE2},
74 {BTN_BASE3, 0, BTN_LABEL_PROP_BTN_BASE3},
75 {BTN_BASE4, 0, BTN_LABEL_PROP_BTN_BASE4},
76 {BTN_BASE5, 0, BTN_LABEL_PROP_BTN_BASE5},
77 {BTN_BASE6, 0, BTN_LABEL_PROP_BTN_BASE6},
78 {BTN_DEAD, 0, BTN_LABEL_PROP_BTN_DEAD}
79 };
80
81 static struct btn btns_section_gamepad[] = {
82 {BTN_A, 0, BTN_LABEL_PROP_BTN_A},
83 {BTN_B, 0, BTN_LABEL_PROP_BTN_B},
84 {BTN_C, 0, BTN_LABEL_PROP_BTN_C},
85 {BTN_X, 0, BTN_LABEL_PROP_BTN_X},
86 {BTN_Y, 0, BTN_LABEL_PROP_BTN_Y},
87 {BTN_Z, 0, BTN_LABEL_PROP_BTN_Z},
88 {BTN_TL, 0, BTN_LABEL_PROP_BTN_TL},
89 {BTN_TR, 0, BTN_LABEL_PROP_BTN_TR},
90 {BTN_TL2, 0, BTN_LABEL_PROP_BTN_TL2},
91 {BTN_TR2, 0, BTN_LABEL_PROP_BTN_TR2},
92 {BTN_SELECT, 0, BTN_LABEL_PROP_BTN_SELECT},
93 {BTN_START, 0, BTN_LABEL_PROP_BTN_START},
94 {BTN_MODE, 0, BTN_LABEL_PROP_BTN_MODE},
95 {BTN_THUMBL, 0, BTN_LABEL_PROP_BTN_THUMBL},
96 {BTN_THUMBR, 0, BTN_LABEL_PROP_BTN_THUMBR}
97 };
98
99 static struct btn btns_section_digi[] = {
100 {BTN_TOOL_PEN, 0, BTN_LABEL_PROP_BTN_TOOL_PEN},
101 {BTN_TOOL_RUBBER, 0, BTN_LABEL_PROP_BTN_TOOL_RUBBER},
102 {BTN_TOOL_BRUSH, 0, BTN_LABEL_PROP_BTN_TOOL_BRUSH},
103 {BTN_TOOL_PENCIL, 0, BTN_LABEL_PROP_BTN_TOOL_PENCIL},
104 {BTN_TOOL_AIRBRUSH, 0, BTN_LABEL_PROP_BTN_TOOL_AIRBRUSH},
105 {BTN_TOOL_FINGER, 0, BTN_LABEL_PROP_BTN_TOOL_FINGER},
106 {BTN_TOOL_MOUSE, 0, BTN_LABEL_PROP_BTN_TOOL_MOUSE},
107 {BTN_TOOL_LENS, 0, BTN_LABEL_PROP_BTN_TOOL_LENS},
108 {BTN_TOOL_QUINTTAP, 0, "Button Tool Quinttap"},
109 {BTN_TOUCH, 1, BTN_LABEL_PROP_BTN_TOUCH},
110 {BTN_STYLUS, 2, BTN_LABEL_PROP_BTN_STYLUS},
111 {BTN_STYLUS2, 3, BTN_LABEL_PROP_BTN_STYLUS2},
112 {BTN_TOOL_DOUBLETAP, 0, BTN_LABEL_PROP_BTN_TOOL_DOUBLETAP},
113 {BTN_TOOL_TRIPLETAP, 0, BTN_LABEL_PROP_BTN_TOOL_TRIPLETAP},
114 {BTN_TOOL_QUADTAP, 0, "Button Tool Quadtap"}
115 };
116
117 static struct btn btns_section_wheel[] = {
118 {BTN_GEAR_DOWN, 0, BTN_LABEL_PROP_BTN_GEAR_DOWN},
119 {BTN_GEAR_UP, 0, BTN_LABEL_PROP_BTN_GEAR_UP}
120 };
121
122 static struct btn btns_section_dpad[] = {
123 {BTN_DPAD_UP, 0, "Button Dpad Up"},
124 {BTN_DPAD_DOWN, 0, "Button Dpad Down"},
125 {BTN_DPAD_LEFT, 0, "Button Dpad Left"},
126 {BTN_DPAD_RIGHT, 0, "Button Dpad Right"}
127 };
128
129 static struct btn btns_section_trigger_happy[] = {
130 {BTN_TRIGGER_HAPPY1, 0, "Button Trigger Happy 1"},
131 {BTN_TRIGGER_HAPPY2, 0, "Button Trigger Happy 2"},
132 {BTN_TRIGGER_HAPPY3, 0, "Button Trigger Happy 3"},
133 {BTN_TRIGGER_HAPPY4, 0, "Button Trigger Happy 4"},
134 {BTN_TRIGGER_HAPPY5, 0, "Button Trigger Happy 5"},
135 {BTN_TRIGGER_HAPPY6, 0, "Button Trigger Happy 6"},
136 {BTN_TRIGGER_HAPPY7, 0, "Button Trigger Happy 7"},
137 {BTN_TRIGGER_HAPPY8, 0, "Button Trigger Happy 8"},
138 {BTN_TRIGGER_HAPPY9, 0, "Button Trigger Happy 9"},
139 {BTN_TRIGGER_HAPPY10, 0, "Button Trigger Happy 10"},
140 {BTN_TRIGGER_HAPPY11, 0, "Button Trigger Happy 11"},
141 {BTN_TRIGGER_HAPPY12, 0, "Button Trigger Happy 12"},
142 {BTN_TRIGGER_HAPPY13, 0, "Button Trigger Happy 13"},
143 {BTN_TRIGGER_HAPPY14, 0, "Button Trigger Happy 14"},
144 {BTN_TRIGGER_HAPPY15, 0, "Button Trigger Happy 15"},
145 {BTN_TRIGGER_HAPPY16, 0, "Button Trigger Happy 16"},
146 {BTN_TRIGGER_HAPPY17, 0, "Button Trigger Happy 17"},
147 {BTN_TRIGGER_HAPPY18, 0, "Button Trigger Happy 18"},
148 {BTN_TRIGGER_HAPPY19, 0, "Button Trigger Happy 19"},
149 {BTN_TRIGGER_HAPPY20, 0, "Button Trigger Happy 20"},
150 {BTN_TRIGGER_HAPPY21, 0, "Button Trigger Happy 21"},
151 {BTN_TRIGGER_HAPPY22, 0, "Button Trigger Happy 22"},
152 {BTN_TRIGGER_HAPPY23, 0, "Button Trigger Happy 23"},
153 {BTN_TRIGGER_HAPPY24, 0, "Button Trigger Happy 24"},
154 {BTN_TRIGGER_HAPPY25, 0, "Button Trigger Happy 25"},
155 {BTN_TRIGGER_HAPPY26, 0, "Button Trigger Happy 26"},
156 {BTN_TRIGGER_HAPPY27, 0, "Button Trigger Happy 27"},
157 {BTN_TRIGGER_HAPPY28, 0, "Button Trigger Happy 28"},
158 {BTN_TRIGGER_HAPPY29, 0, "Button Trigger Happy 29"},
159 {BTN_TRIGGER_HAPPY30, 0, "Button Trigger Happy 30"},
160 {BTN_TRIGGER_HAPPY31, 0, "Button Trigger Happy 31"},
161 {BTN_TRIGGER_HAPPY32, 0, "Button Trigger Happy 32"},
162 {BTN_TRIGGER_HAPPY33, 0, "Button Trigger Happy 33"},
163 {BTN_TRIGGER_HAPPY34, 0, "Button Trigger Happy 34"},
164 {BTN_TRIGGER_HAPPY35, 0, "Button Trigger Happy 35"},
165 {BTN_TRIGGER_HAPPY36, 0, "Button Trigger Happy 36"},
166 {BTN_TRIGGER_HAPPY37, 0, "Button Trigger Happy 37"},
167 {BTN_TRIGGER_HAPPY38, 0, "Button Trigger Happy 38"},
168 {BTN_TRIGGER_HAPPY39, 0, "Button Trigger Happy 39"},
169 {BTN_TRIGGER_HAPPY40, 0, "Button Trigger Happy 40"}
170 };
171 /* end of evdev button to dix mapping definitions */
172 /*----------------------------------------------------------------------------*/
173
174 static void
175 btns_section_map(struct dix_init_data *init_data, struct btn *evdev_section,
176 long evdev_section_btns_n, int *dix_map, u16 evdev_mask)
177 {
178 struct evdev *evdev;
179 long section_btn_idx;
180
181 evdev = init_data->dix->public.devicePrivate;
182
183 for (section_btn_idx = 0; section_btn_idx < evdev_section_btns_n;
184 ++section_btn_idx) {
185 struct btn *section_btn;
186
187 section_btn = evdev_section + section_btn_idx;
188
189 if (IS_BIT_SET(evdev->key_codes, section_btn->evdev_bit)) {
190 u16 evdev_map_idx;
191
192 /* we use the xserver strings for evdev, they are the same */
193 if (section_btn->dix) {
194 ErrorF("evdev %s mapped to dix %u\n", section_btn->name,
195 section_btn->dix);
196
197 } else {
198 ErrorF("evdev %s ignored\n", section_btn->name);
199 }
200
201 if (section_btn->dix > init_data->dix_btn_n_max)
202 init_data->dix_btn_n_max = (u16)section_btn->dix;
203
204 evdev_map_idx = section_btn->evdev_bit & ~evdev_mask;
205 dix_map[evdev_map_idx] = section_btn->dix;
206 }
207 }
208 }
209
210 void
211 key_btns_get(struct dix_init_data *init_data)
212 {
213 struct evdev *evdev;
214
215 evdev = init_data->dix->public.devicePrivate;
216
217 ErrorF("getting supported evdev misc section buttons...\n");
218 btns_section_map(init_data, &btns_section_misc[0],
219 ARRAY_SIZE(btns_section_misc),
220 &evdev->btns_misc_dix_map[0], BTN_MISC);
221
222 ErrorF("getting supported evdev mouse section buttons...\n");
223 btns_section_map(init_data, &btns_section_mouse[0],
224 ARRAY_SIZE(btns_section_mouse),
225 &evdev->btns_mouse_dix_map[0], BTN_MOUSE);
226
227 ErrorF("getting supported evdev joystick section buttons...\n");
228 btns_section_map(init_data, &btns_section_joystick[0],
229 ARRAY_SIZE(btns_section_joystick),
230 &evdev->btns_joystick_dix_map[0], BTN_JOYSTICK);
231
232 ErrorF("getting supported evdev gamepad section buttons...\n");
233 btns_section_map(init_data, &btns_section_gamepad[0],
234 ARRAY_SIZE(btns_section_gamepad),
235 &evdev->btns_gamepad_dix_map[0], BTN_GAMEPAD);
236
237 ErrorF("getting supported evdev digi section buttons...\n");
238 btns_section_map(init_data, &btns_section_digi[0],
239 ARRAY_SIZE(btns_section_digi),
240 &evdev->btns_digi_dix_map[0], BTN_DIGI);
241
242 ErrorF("getting supported evdev wheel section buttons...\n");
243 btns_section_map(init_data, &btns_section_wheel[0],
244 ARRAY_SIZE(btns_section_wheel),
245 &evdev->btns_wheel_dix_map[0], BTN_WHEEL);
246
247 ErrorF("getting supported evdev dpad section buttons...\n");
248 btns_section_map(init_data, &btns_section_dpad[0],
249 ARRAY_SIZE(btns_section_dpad),
250 &evdev->btns_dpad_dix_map[0], BTN_DPAD_UP);
251
252 ErrorF("getting supported evdev trigger happy section buttons...\n");
253 btns_section_map(init_data, &btns_section_trigger_happy[0],
254 ARRAY_SIZE(btns_section_trigger_happy),
255 &evdev->btns_trigger_happy_dix_map[0], BTN_TRIGGER_HAPPY);
256 }
257
258 /* we could use Bool arithmetics... */
259 u16
260 btn_section_mask_get(u16 code)
261 {
262 if (BTN_MISC <= code && code <= BTN_9)
263 return BTN_MISC;
264
265 if (BTN_MOUSE <= code && code <= BTN_TASK)
266 return BTN_MOUSE;
267
268 if (BTN_JOYSTICK <= code && code <= BTN_DEAD)
269 return BTN_JOYSTICK;
270
271 if (BTN_GAMEPAD <= code && code <= BTN_THUMBR)
272 return BTN_GAMEPAD;
273
274 if (BTN_DIGI <= code && code <= BTN_TOOL_QUADTAP)
275 return BTN_DIGI;
276
277 if (BTN_WHEEL <= code && code <= BTN_GEAR_UP)
278 return BTN_WHEEL;
279
280 if (BTN_DPAD_UP <= code && code <= BTN_DPAD_RIGHT)
281 return BTN_DPAD_UP;
282
283 if (BTN_TRIGGER_HAPPY <= code && code <= BTN_TRIGGER_HAPPY40)
284 return BTN_TRIGGER_HAPPY;
285 return 0; /* it's a KEY KEY not KEY BTN... */
286 }
287
288 void
289 btn_process(DeviceIntPtr dix, struct input_event *e, u16 btn_section_mask)
290 {
291 int dix_btn_n;
292 struct evdev *evdev;
293 int dix_type;
294
295 evdev = dix->public.devicePrivate;
296 dix_btn_n = 0;
297
298 switch (btn_section_mask) {
299 case BTN_MISC:
300 dix_btn_n = evdev->btns_misc_dix_map[e->code & ~BTN_MISC];
301 break;
302 case BTN_MOUSE:
303 dix_btn_n = evdev->btns_mouse_dix_map[e->code & ~BTN_MOUSE];
304 break;
305 case BTN_JOYSTICK:
306 dix_btn_n = evdev->btns_joystick_dix_map[e->code & ~BTN_JOYSTICK];
307 break;
308 case BTN_GAMEPAD:
309 dix_btn_n = evdev->btns_gamepad_dix_map[e->code & ~BTN_GAMEPAD];
310 break;
311 case BTN_DIGI:
312 dix_btn_n = evdev->btns_digi_dix_map[e->code & ~BTN_DIGI];
313 break;
314 case BTN_WHEEL:
315 dix_btn_n = evdev->btns_wheel_dix_map[e->code & ~BTN_WHEEL];
316 break;
317 case BTN_DPAD_UP:
318 dix_btn_n = evdev->btns_wheel_dix_map[e->code & ~BTN_DPAD_UP];
319 break;
320 case BTN_TRIGGER_HAPPY:
321 dix_btn_n = evdev->btns_trigger_happy_dix_map[e->code
322 & ~BTN_TRIGGER_HAPPY];
323 break;
324 };
325
326 if (!dix_btn_n) /* no dix btn mapped */
327 return;
328
329 /*
330 * XXX: a evdev KEY can have an "autorepeat" value = 2, ignore the button
331 * event
332 */
333 if (e->value == 2)
334 return;
335
336 if (e->value)
337 dix_type = ButtonPress;
338 else
339 dix_type = ButtonRelease;
340
341 QueuePointerEvents(dix, dix_type, dix_btn_n, 0, NULL);
342 }
343
344 #define BTN_ATOM_FMT "Button %02u"
345 #define BTN_ATOM_TMPL "Button XX"
346 #define BTN_ATOM_TMPL_SZ sizeof(BTN_ATOM_TMPL)
347 static Atom*
348 dix_btns_atom_make(u16 btns_cnt)
349 {
350 u16 btn;
351 Atom *labels;
352
353 ErrorF("creating %u atoms for button labels\n", btns_cnt);
354
355 labels = xnfcalloc(1, btns_cnt * sizeof(*labels));
356
357 /* x11 button number for 1, but labels from 0 */
358 for(btn = 1; btn <= btns_cnt; ++btn) {
359 char label[BTN_ATOM_TMPL_SZ];
360
361 snprintf(label, BTN_ATOM_TMPL_SZ, BTN_ATOM_FMT, btn);
362
363 labels[btn - 1] = MakeAtom(label, strlen(label), TRUE);
364 if (labels[btn - 1] == BAD_RESOURCE) {
365 ErrorF("unable to make atom for button label %02u\n", btn);
366 free(labels);
367 return NULL;
368 }
369 }
370 return labels;
371 }
372
373 Bool
374 dix_btns_register(struct dix_init_data *init_data)
375 {
376 Bool r;
377 Atom *labels;
378 BYTE *map;
379 u16 btn;
380
381 if (!init_data->dix_btn_n_max) {
382 ErrorF("no evdev buttons to register in dix\n");
383 return TRUE;
384 }
385
386 labels = dix_btns_atom_make(init_data->dix_btn_n_max);
387 if (!labels)
388 return FALSE;
389
390 /* identity mapping */
391 map = xnfcalloc(1, (init_data->dix_btn_n_max + 1) * sizeof(*map));
392 for (btn = 1; btn <= init_data->dix_btn_n_max; ++btn)
393 map[btn] = (BYTE)btn;
394
395 r = InitButtonClassDeviceStruct(init_data->dix,
396 init_data->dix_btn_n_max, labels, map);
397 if (!r)
398 ErrorF("unable to register evdev buttons in dix\n");
399
400 free(map);
401 free(labels);
402 return r;
403 }
File hw/xalga/evdev/key/key-key.c added (mode: 100644) (index 0000000..ff98fec)
1 /*
2 * XALGA implementation
3 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
4 * Opens source legal protection provided by a GNU Lesser GPLv3 license
5 */
6 #include <errno.h>
7 #include <unistd.h>
8 #include <linux/input.h>
9
10 #include "dix-config.h"
11 #include "inpututils.h"
12 #include "input.h"
13 #include "xserver-properties.h"
14 #include "exevents.h"
15
16 #include "xalga/namespace.h"
17 #include "xalga/evdev/axis/rel.h"
18 #include "xalga/evdev/evdev.h"
19 #include "xalga/evdev/private.h"
20
21
22 /*----------------------------------------------------------------------------*/
23 void key_keys_get(struct dix_init_data *init_data);
24 void key_process(DeviceIntPtr dix, struct input_event *e);
25 Bool dix_keys_register(struct dix_init_data *init_data);
26 /*----------------------------------------------------------------------------*/
27
28
29 void
30 key_keys_get(struct dix_init_data *init_data)
31 {
32 struct evdev *evdev;
33 long key_bit;
34
35 evdev = init_data->dix->public.devicePrivate;
36
37 evdev->have_key = FALSE;
38
39 /* 1st section for keys */
40 for (key_bit = KEY_RESERVED; key_bit <= KEY_KPDOT; ++key_bit)
41 if (IS_BIT_SET(evdev->key_codes, key_bit))
42 goto exit_have_key;
43
44 /* 2nd section */
45 for (key_bit = KEY_ZENKAKUHANKAKU; key_bit <= KEY_F24; ++key_bit)
46 if (IS_BIT_SET(evdev->key_codes, key_bit))
47 goto exit_have_key;
48
49 /* 3rd section */
50 for (key_bit = KEY_PLAYCD; key_bit <= KEY_MICMUTE; ++key_bit)
51 if (IS_BIT_SET(evdev->key_codes, key_bit))
52 goto exit_have_key;
53
54 /* 4th section */
55 for (key_bit = KEY_OK; key_bit <= KEY_IMAGES; ++key_bit)
56 if (IS_BIT_SET(evdev->key_codes, key_bit))
57 goto exit_have_key;
58
59 /* 5th section */
60 for (key_bit = KEY_DEL_EOL; key_bit <= KEY_DEL_LINE; ++key_bit)
61 if (IS_BIT_SET(evdev->key_codes, key_bit))
62 goto exit_have_key;
63
64 /* 6th section */
65 for (key_bit = KEY_FN; key_bit <= KEY_FN_B; ++key_bit)
66 if (IS_BIT_SET(evdev->key_codes, key_bit))
67 goto exit_have_key;
68
69 /* 7th section */
70 for (key_bit = KEY_BRL_DOT1; key_bit <= KEY_BRL_DOT10; ++key_bit)
71 if (IS_BIT_SET(evdev->key_codes, key_bit))
72 goto exit_have_key;
73
74 /* 8th section */
75 for (key_bit = KEY_NUMERIC_0; key_bit <= KEY_NUMERIC_POUND; ++key_bit)
76 if (IS_BIT_SET(evdev->key_codes, key_bit))
77 goto exit_have_key;
78
79 /* 9th section */
80 for (key_bit = KEY_CAMERA_FOCUS; key_bit <= KEY_LIGHTS_TOGGLE; ++key_bit)
81 if (IS_BIT_SET(evdev->key_codes, key_bit))
82 goto exit_have_key;
83
84 /* 10th section */
85 if (IS_BIT_SET(evdev->key_codes, KEY_ALS_TOGGLE))
86 goto exit_have_key;
87 return;
88
89 exit_have_key:
90 ErrorF("device has key\n");
91 evdev->have_key = TRUE;
92 return;
93 }
94
95 void
96 key_process(DeviceIntPtr dix, struct input_event *e)
97 {
98 int type;
99 ValuatorMask mask;
100
101 /*
102 * XXX: a evdev KEY can have an "autorepeat" value = 2, ignore the key
103 * event as repeat is done in dix
104 */
105 if (e->value == 2)
106 return;
107
108 if (e->value)
109 type = KeyPress;
110 else
111 type = KeyRelease;
112
113 /*
114 * XXX: In x11 the keycode must start above 8. The default xserver evdev
115 * mapping uses the trick to translate kernel keycode of 8, which is
116 * probably linked to the fact that x11 has 8 modifiers.
117 */
118 e->code += 8;
119 valuator_mask_zero(&mask);
120 QueueKeyboardEvents(dix, type, e->code, &mask);
121 }
122
123 static void
124 keyboard_ctl(DeviceIntPtr dix, KeybdCtrl *ctl)
125 {
126 static struct { int dix_bit, evdev_led_code; } map[] = {
127 {1, LED_CAPSL},
128 {2, LED_NUML},
129 {4, LED_SCROLLL},
130 {8, LED_KANA},
131 {16, LED_COMPOSE}
132 };
133 struct input_event es[ARRAY_SIZE(map) + 1];
134 u8 led;
135 struct evdev *evdev;
136 ssize_t r;
137 u8 rem_es_to_send;
138 u8 *write_buf;
139
140 memset(es, 0, sizeof(es));
141
142 for (led = 0; led < ARRAY_SIZE(map); ++led) {
143 es[led].type = EV_LED;
144 es[led].code = map[led].evdev_led_code;
145 es[led].value = (ctl->leds & map[led].dix_bit) > 0;
146 }
147
148 /* a syn report to finish the event stream */
149 es[led].type = EV_SYN;
150 es[led].code = SYN_REPORT;
151 es[led].value = 0;
152
153 evdev = dix->public.devicePrivate;
154 write_buf = (u8*)&es[0];
155 rem_es_to_send = led + 1;
156 while (1) {
157 /* write must send blocks of whole input events */
158 errno = 0;
159 r = write(evdev->fd, write_buf, rem_es_to_send * sizeof(es[0]));
160 if (r == -1) {
161 if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
162 continue;
163 ErrorF("unable to send the led states to linux\n");
164 return;
165 }
166 if (r < (rem_es_to_send * sizeof(es[0]))) {
167 if (r % sizeof(es[0])) {
168 ErrorF("unable to send to linux whole evdev input events for led states\n");
169 return;
170 }
171 write_buf += r;
172 rem_es_to_send -= r / sizeof(es[0]);
173 continue;
174 }
175 /* r == (rem_es_to_send * sizeof(es[0]) */
176 break;
177 }
178 }
179 Bool
180 dix_keys_register(struct dix_init_data *init_data)
181 {
182 Bool r;
183 struct evdev *evdev;
184
185 evdev = init_data->dix->public.devicePrivate;
186
187 if (!evdev->have_key)
188 return TRUE;
189
190 r = InitKeyboardDeviceStruct(init_data->dix, &evdev->xkb, NULL,
191 keyboard_ctl);
192 if (!r) {
193 ErrorF("unable to init the keyboard device\n");
194 return FALSE;
195 }
196 return TRUE;
197 }
File hw/xalga/evdev/key/key.c added (mode: 100644) (index 0000000..6b4449d)
1 /*
2 * XALGA implementation
3 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
4 * Opens source legal protection provided by a GNU Lesser GPLv3 license
5 */
6 #include <stdint.h>
7 #include <sys/ioctl.h>
8 #include <linux/input.h>
9
10 #include "dix-config.h"
11 #include "input.h"
12 #include "xserver-properties.h"
13 #include "exevents.h"
14
15 #include "xalga/namespace.h"
16 #include "xalga/evdev/axis/rel.h"
17 #include "xalga/evdev/evdev.h"
18 #include "xalga/evdev/key/private.h"
19
20
21 /*----------------------------------------------------------------------------*/
22 Bool key_codes_get(struct evdev *evdev);
23 void key_code_dispatch(DeviceIntPtr dix, struct input_event *e);
24 /*----------------------------------------------------------------------------*/
25
26
27 Bool
28 key_codes_get(struct evdev *evdev)
29 {
30 int r;
31
32 r = ioctl(evdev->fd, EVIOCGBIT(EV_KEY, sizeof(evdev->key_codes)),
33 evdev->key_codes);
34 if (r == -1) {
35 ErrorF("unable to query the supported evdev key codes\n");
36 return FALSE;
37 }
38 return TRUE;
39 }
40
41 /* an evdev key can be a key key or key btn... */
42 void
43 key_code_dispatch(DeviceIntPtr dix, struct input_event *e)
44 {
45 struct evdev *evdev;
46 u16 btn_section_mask;
47
48 evdev = dix->public.devicePrivate;
49 btn_section_mask = btn_section_mask_get(e->code);
50
51 if (btn_section_mask)
52 btn_process(dix, e, btn_section_mask);
53 else if (evdev->have_key)
54 key_process(dix, e);
55 }
File hw/xalga/output.c added (mode: 100644) (index 0000000..2273ead)
1 /*
2 * XALGA implementation
3 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
4 * Opens source legal protection provided by a GNU Lesser GPLv3 license
5 */
6 #include <stdint.h>
7 /*============================================================================*/
8 #include <time.h>
9 #include <sys/epoll.h>
10 #include <sys/ioctl.h>
11 #include <sys/mman.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <fcntl.h>
15 #include <errno.h>
16 #include <alga/pixel_fmts.h>
17 #include <alga/amd/dce6/dce6.h>
18 #include <alga/amd/si/ioctl.h>
19 /*============================================================================*/
20
21 #include "dix-config.h"
22 #include "randrstr.h"
23 #include "micmap.h"
24 #include "fb.h"
25 #include "mipointer.h"
26
27 #include "xalga/namespace.h"
28
29 #define DISPLAYPORT_DEFAULT_WIDTH 640
30 #define DISPLAYPORT_DEFAULT_HEIGHT 480
31 #define DISPLAYPORT_DEFAULT_REFRESH 60
32 #define X_DPI_DEFAULT 96
33 #define Y_DPI_DEFAULT 96
34 #define DCE6_WIDTH_MAX 16384
35 #define DCE6_HEIGHT_MAX 16384
36
37 #define CREATE_PIXMAP_USAGE_DMA 5
38
39 /*----------------------------------------------------------------------------*/
40 struct alga_pixmap {
41 void *data;
42 u64 data_sz;
43 };
44 static DevPrivateKeyRec alga_pixmap_private_key;
45
46 static void alga_pixmap_set_private(PixmapPtr pixmap,
47 struct alga_pixmap *alga_pixmap);
48 static PixmapPtr pixmap_create(ScreenPtr screen, int w, int h, int d,
49 unsigned int hint);
50 static Bool pixmap_destroy(PixmapPtr pixmap);
51 /*----------------------------------------------------------------------------*/
52
53
54 /*----------------------------------------------------------------------------*/
55 #define MODE_NAME_MAX_TMPL "wwwwxhhhhh@rrr"
56 struct alga_screen {
57 /* this is used to chain our work with the work of other subsystems */
58 CreateScreenResourcesProcPtr CreateScreenResources;
59 CloseScreenProcPtr CloseScreen;
60
61 RealizeWindowProcPtr RealizeWindow;
62
63 /*============================================================================*/
64 int f;
65 u16 w;
66 u16 h;
67 u8 r;
68 u8 pixel_fmt;
69 u64 stride;
70 /* because af randr mode info, it must have a terminal 0 */
71 char mode_name[sizeof(MODE_NAME_MAX_TMPL)];
72
73 u8 idx; /* the index of the display block */
74 u64 fb_gpu_addr_front;
75 u64 fb_gpu_addr_back;
76 u64 fb_gpu_addr_visible;
77 u64 fb_gpu_addr_hidden;
78 u64 fb_sz;
79 RROutputPtr randr_output;
80 RRCrtcPtr randr_crtc;
81
82 /*----------------*/
83 /* state */
84 Bool dpm_on;
85 Bool flip_evts_expected;
86 Bool fb_dma_do;
87 /*----------------*/
88 ScreenBlockHandlerProcPtr BlockHandler;
89 ScreenWakeupHandlerProcPtr WakeupHandler;
90 /*============================================================================*/
91 };
92 static DevPrivateKeyRec alga_screen_private_key;
93
94 static void alga_screen_set_private(ScreenPtr screen,
95 struct alga_screen *alga_screen);
96 static struct alga_screen * alga_screen_get(ScreenPtr screen);
97 static Bool screen_save(ScreenPtr pScreen, int on);
98 static Bool alga_CreateScreenResources(ScreenPtr screen);
99 static Bool alga_CloseScreen(ScreenPtr screen);
100 static Bool alga_rrGetInfo(ScreenPtr pScreen, Rotation * rotations);
101 static Bool alga_rrSetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
102 RRScreenSizePtr pSize);
103 /*============================================================================*/
104 static void alga_fb_alloc(struct alga_screen *alga_screen);
105 static void alga_fb_free(struct alga_screen *alga_screen);
106 static void alga_mode_set(struct alga_screen *alga_screen);
107 /*============================================================================*/
108 /*----------------------------------------------------------------------------*/
109
110
111 /*----------------------------------------------------------------------------*/
112 struct alga_window {
113 WindowPtr window;
114 DamagePtr damage;
115 };
116
117 static Bool alga_RealizeWindow(WindowPtr window);
118 /*----------------------------------------------------------------------------*/
119
120
121 /*----------------------------------------------------------------------------*/
122 static Bool alga_CursorOffScreen(ScreenPtr *screen, int *x, int *y);
123 static void alga_CrossScreen(ScreenPtr screen, int entering);
124 static void alga_WarpCursor(DeviceIntPtr dev, ScreenPtr screen, int x, int y);
125
126 miPointerScreenFuncRec alga_pointer_screen_funcs = {
127 alga_CursorOffScreen,
128 alga_CrossScreen,
129 alga_WarpCursor
130 };
131 /*----------------------------------------------------------------------------*/
132
133
134 /*----------------------------------------------------------------------------*/
135 static void alga_BlockHandler(ScreenPtr pScreen, void *pTimeout,
136 void *pReadmask);
137 static void alga_WakeupHandler(ScreenPtr pScreen, unsigned long result,
138 void *pReadMask);
139 /*----------------------------------------------------------------------------*/
140
141
142 /*----------------------------------------------------------------------------*/
143 Bool screen_init(ScreenPtr screen, int argc, char **argv);
144 /*----------------------------------------------------------------------------*/
145
146
147 /*----------------------------------------------------------------------------*/
148 static void dpm_on(ScreenPtr pScreen);
149 static void fb_flip_schedule(ScreenPtr screen, Bool retry_on_pending);
150 static void si_evts_process(ScreenPtr screen, Bool flip_fbs);
151 static void fb_dma_to_device(ScreenPtr screen, Bool visible);
152 /*----------------------------------------------------------------------------*/
153
154
155 static Bool
156 alga_CursorOffScreen(ScreenPtr *screen, int *x, int *y)
157 {
158 /*
159 * XXX: if there are more than 1 screen, and if the cursor leaving its
160 * current screen reaches another screen, then update the screen pointer
161 * and return TRUE. Else return FALSE;
162 */
163 return FALSE;
164 }
165
166 static void
167 alga_CrossScreen(ScreenPtr screen, int entering)
168 {
169 /*
170 * XXX: probably called when entering a new screen decided by
171 * alga_CursorOffScreen above.
172 */
173 }
174
175 static void
176 alga_WarpCursor(DeviceIntPtr dev, ScreenPtr screen, int x, int y)
177 {
178 OsBlockSIGIO();
179 miPointerWarpCursor(dev, screen, x, y);
180 OsReleaseSIGIO();
181 }
182
183 static void
184 alga_pixmap_set_private(PixmapPtr pixmap, struct alga_pixmap *alga_pixmap)
185 {
186 dixSetPrivate(&pixmap->devPrivates, &alga_pixmap_private_key, alga_pixmap);
187 }
188
189 static struct alga_pixmap *
190 alga_pixmap_get(PixmapPtr pixmap)
191 {
192 return dixLookupPrivate(&pixmap->devPrivates, &alga_screen_private_key);
193 }
194
195 static void
196 alga_screen_set_private(ScreenPtr screen, struct alga_screen *alga_screen)
197 {
198 dixSetPrivate(&screen->devPrivates, &alga_screen_private_key, alga_screen);
199 }
200
201 static struct alga_screen *
202 alga_screen_get(ScreenPtr screen)
203 {
204 return dixLookupPrivate(&screen->devPrivates, &alga_screen_private_key);
205 }
206
207 static Bool
208 pixmap_destroy(PixmapPtr pixmap)
209 {
210 struct alga_pixmap *alga_pixmap;
211
212 alga_pixmap = alga_pixmap_get(pixmap);
213
214 if (alga_pixmap && pixmap->refcnt == 1) {
215 if (alga_pixmap->data)
216 munmap(alga_pixmap->data, alga_pixmap->data_sz);
217 free(alga_pixmap);
218 }
219 return fbDestroyPixmap(pixmap);
220 }
221
222 static PixmapPtr
223 pixmap_create(ScreenPtr screen, int w, int h, int d, unsigned int hint)
224 {
225 PixmapPtr pixmap;
226 struct alga_pixmap *alga_pixmap;
227 u64 stride;
228 Bool r;
229 struct alga_screen *alga_screen;
230
231 /* we have our own hint */
232 if (hint != CREATE_PIXMAP_USAGE_DMA)
233 return fbCreatePixmap(screen, w, h, d, hint);
234
235 /*
236 * XXX: here we let the fb helper create a pixmap of WxH 0x0 which we will
237 * update below with the right sizes. This is a nasty hack in order
238 * to forbid the fb helper to allocate memory.
239 */
240 pixmap = fbCreatePixmap(screen, 0, 0, d, hint);
241 if (!pixmap) {
242 ErrorF("%s:unable to allocate frame buffer helper pixmap\n", __func__);
243 return NULL;
244 }
245
246 alga_pixmap = malloc(sizeof(*alga_pixmap));
247 if (alga_pixmap == NULL) {
248 ErrorF("%s:unable to allocate alga pixmap\n", __func__);
249 goto err_destroy_pixmap;
250 }
251
252 /* the actual number of byte for a line */
253 stride = (u64)PixmapBytePad(w, d);
254 alga_pixmap->data_sz = stride * h;
255
256 alga_screen = alga_screen_get(screen);
257 alga_pixmap->data = mmap(NULL, alga_pixmap->data_sz, PROT_READ
258 | PROT_WRITE, MAP_SHARED, alga_screen->f, 0);
259 if (alga_pixmap->data == MAP_FAILED) {
260 ErrorF("%s:unable to mmap alga pixmap buffer\n", __func__);
261 alga_pixmap->data = NULL;
262 goto err_free_alga_pixmap;
263 }
264
265 r = (*screen->ModifyPixmapHeader)(pixmap, w, h, d, BitsPerPixel(d), stride,
266 alga_pixmap->data);
267 if (!r) {
268 ErrorF("%s:unable to modify pixmap header\n", __func__);
269 goto err_munmap_alga_pixmap_data;
270 }
271
272 alga_pixmap_set_private(pixmap, alga_pixmap);
273 return pixmap;
274
275 err_munmap_alga_pixmap_data:
276 munmap(alga_pixmap->data, alga_pixmap->data_sz);
277
278 err_free_alga_pixmap:
279 free(alga_pixmap);
280
281 err_destroy_pixmap:
282 fbDestroyPixmap(pixmap);
283 return NULL;
284 }
285
286 static Bool
287 alga_RealizeWindow(WindowPtr window)
288 {
289 ScreenPtr screen;
290 struct alga_screen *alga_screen;
291 Bool r;
292
293 screen = window->drawable.pScreen;
294 alga_screen = alga_screen_get(screen);
295
296 screen->RealizeWindow = alga_screen->RealizeWindow;
297 r = screen->RealizeWindow(window);
298
299 /*
300 * XXX: in xalga we want the cursor on the root window to be displayed right
301 * away and not wait for the first application to call XDefineCursor
302 */
303 if (window == screen->root)
304 CursorVisible = EnableCursor;
305
306 if (!r)
307 goto err;
308
309
310 alga_screen->RealizeWindow = screen->RealizeWindow;
311 screen->RealizeWindow = alga_RealizeWindow;
312 return TRUE;
313
314 err:
315 alga_screen->RealizeWindow = screen->RealizeWindow;
316 screen->RealizeWindow = alga_RealizeWindow;
317 return FALSE;
318 }
319
320 static void
321 fb_flip_evt_wait(ScreenPtr pScreen)
322 {
323 struct alga_screen *alga_screen;
324 fd_set flip_set;
325 int r;
326
327 alga_screen = alga_screen_get(pScreen);
328
329 FD_ZERO(&flip_set);
330 FD_SET(alga_screen->f, &flip_set);
331 while (1) {
332 errno = 0;
333 r = select(alga_screen->f + 1, &flip_set, NULL, NULL, NULL);
334 if (r == -1 && errno != EINTR)
335 FatalError("%s:unable to synchronously wait for the flip event\n",
336 __func__);
337 if (r == 1)
338 break;
339 }
340 }
341
342 static void
343 dpm_on(ScreenPtr pScreen)
344 {
345 struct alga_screen *alga_screen;
346 int r;
347 ul req;
348
349 alga_screen = alga_screen_get(pScreen);
350
351 req = _IOW('d', SI_DCE_DP_DPM, alga_screen->idx);
352 r = ioctl(alga_screen->f, req, &alga_screen->idx);
353 if (r == -1)
354 FatalError("%s:an error occured while switching dpm on\n", __func__);
355 }
356
357 static Bool
358 screen_save(ScreenPtr pScreen, int on)
359 {
360 struct alga_screen *alga_screen;
361 alga_screen = alga_screen_get(pScreen);
362
363 switch (on) {
364 case SCREEN_SAVER_ON:
365 /*
366 * we allow to stall and wait for the outstanding page flip event
367 * since we are not in a hurry. In the opposite case, we would have
368 * needed a cancel flip driver command
369 */
370 if (alga_screen->flip_evts_expected) {
371 fb_flip_evt_wait(pScreen);
372 si_evts_process(pScreen, FALSE);
373 alga_screen->flip_evts_expected = FALSE;
374 }
375 dpm_on(pScreen);
376 alga_screen->dpm_on = TRUE;
377 break;
378 case SCREEN_SAVER_OFF:
379 alga_mode_set(alga_screen);
380 alga_screen->fb_dma_do = TRUE;
381 alga_screen->dpm_on = FALSE;
382 break;
383 case SCREEN_SAVER_FORCER:
384 case SCREEN_SAVER_CYCLE:
385 default:
386 break;
387 };
388 return TRUE;
389 }
390
391 static Bool
392 alga_CloseScreen(ScreenPtr screen)
393 {
394 struct alga_screen *alga_screen;
395
396 alga_screen = alga_screen_get(screen);
397
398 /*========================================================================*/
399 dpm_on(screen);
400 RROutputDestroy(alga_screen->randr_output);
401 RRCrtcDestroy(alga_screen->randr_crtc);
402 alga_fb_free(alga_screen);
403 pixmap_destroy((PixmapPtr)screen->devPrivate);
404 /*
405 * XXX: the fb helper screen close expect a pixmap here if not null and
406 * will free the pixmap without destroying it...
407 */
408 screen->devPrivate = NULL;
409 RemoveGeneralSocket(alga_screen->f);
410 close(alga_screen->f);
411 /*========================================================================*/
412
413 /* unwrap/restore screen methods */
414 screen->CreateScreenResources = alga_screen->CreateScreenResources;
415 screen->CloseScreen = alga_screen->CloseScreen;
416 screen->RealizeWindow= alga_screen->RealizeWindow;
417 screen->BlockHandler = alga_screen->BlockHandler;
418 screen->WakeupHandler = alga_screen->WakeupHandler;
419
420 free(alga_screen);
421 return screen->CloseScreen(screen);
422 }
423
424 static Bool
425 alga_CreateScreenResources(ScreenPtr screen)
426 {
427 struct alga_screen *alga_screen;
428 Bool r;
429
430 alga_screen = alga_screen_get(screen);
431
432 screen->CreateScreenResources = alga_screen->CreateScreenResources;
433 r = (*screen->CreateScreenResources)(screen);
434 alga_screen->CreateScreenResources = screen->CreateScreenResources;
435 screen->CreateScreenResources = alga_CreateScreenResources;
436
437 if (!r)
438 return FALSE;
439
440 /*
441 * XXX: we use the fb helper for the screen, it wants the framebuffer
442 * pixmap here. Carefull, it's not "destroyed" between server generations,
443 * just freed by the fb helper close screen.
444 */
445 screen->devPrivate = pixmap_create(screen, screen->width, screen->height,
446 screen->rootDepth, CREATE_PIXMAP_USAGE_DMA);
447 if (!screen->devPrivate)
448 return FALSE;
449 return TRUE;
450 }
451
452 static Bool
453 alga_rrGetInfo(ScreenPtr pScreen, Rotation * rotations)
454 {
455 *rotations = 0;
456
457 return TRUE;
458 }
459
460 static Bool
461 alga_rrSetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
462 RRScreenSizePtr pSize)
463 {
464 return FALSE;
465 }
466
467 /*============================================================================*/
468 static void
469 alga_fb_alloc(struct alga_screen *alga_screen)
470 {
471 struct si_mem mem;
472 u64 sz;
473 ul req;
474 int r;
475
476 memset(&mem,0,sizeof(mem));
477
478 mem.align = 4096; /* FIXME: 256 should be enough */
479 alga_screen->fb_sz = alga_screen->stride * alga_screen->h;
480 sz = 2 * alga_screen->fb_sz;
481 mem.sz = sz;
482 ErrorF("db_fb alloc sz=%016llx\n",(ull)mem.sz);
483 req = _IOWR('d',SI_MEM_ALLOC,mem);
484 r = ioctl(alga_screen->f, req, &mem);
485 if (r == -1)
486 FatalError("%s:alloc db_fb failed\n", __func__);
487
488 ErrorF("front_fb=0x%016llx back_fb=0x%016llx\n",(ull)mem.gpu_addr,
489 (ull)mem.gpu_addr + alga_screen->fb_sz);
490 alga_screen->fb_gpu_addr_front = mem.gpu_addr;
491 alga_screen->fb_gpu_addr_back = mem.gpu_addr + alga_screen->fb_sz;
492 alga_screen->fb_gpu_addr_visible = alga_screen->fb_gpu_addr_front;
493 alga_screen->fb_gpu_addr_hidden = alga_screen->fb_gpu_addr_back;
494 }
495
496 static void
497 alga_fb_free(struct alga_screen *alga_screen)
498 {
499 ul req;
500 int r;
501
502 ErrorF("freeing fb_gpu_addr_front=%016llx\n",
503 (ull)alga_screen->fb_gpu_addr_front);
504 req = _IOW('d', SI_MEM_FREE, alga_screen->fb_gpu_addr_front);
505 r = ioctl(alga_screen->f, req, &alga_screen->fb_gpu_addr_front);
506 if (r == -1)
507 ErrorF("%s:free vram fb failed (LEAK till garbage collection is implemented!)\n",
508 __func__);
509 }
510
511 static void
512 alga_mode_set(struct alga_screen *alga_screen)
513 {
514 struct si_dce_dp_set dp_set;
515 ul req;
516 int r;
517
518 memset(&dp_set,0,sizeof(dp_set));
519
520 dp_set.idx = alga_screen->idx;
521 dp_set.primary = alga_screen->fb_gpu_addr_front;
522 dp_set.secondary = alga_screen->fb_gpu_addr_back;
523 strncpy(&dp_set.mode[0], &alga_screen->mode_name[0], sizeof(dp_set.mode));
524 strncpy(&dp_set.pixel_fmt[0], alga_pixel_fmts_str[alga_screen->pixel_fmt],
525 sizeof(dp_set.pixel_fmt));
526 req = _IOR('d', SI_DCE_DP_SET, dp_set);
527 r = ioctl(alga_screen->f, req, &dp_set);
528 if (r == -1)
529 FatalError("%s:dp set failed", __func__);
530
531 alga_screen->fb_gpu_addr_visible = alga_screen->fb_gpu_addr_front;
532 alga_screen->fb_gpu_addr_hidden = alga_screen->fb_gpu_addr_back;
533 }
534 /*============================================================================*/
535
536 Bool
537 screen_init(ScreenPtr screen, int argc, char **argv)
538 {
539 Bool r;
540 struct alga_screen *alga_screen;
541 /*========================================================================*/
542 rrScrPrivPtr rr;
543 xRRModeInfo mode_info;
544 RRModePtr randr_mode;
545 /*========================================================================*/
546
547 ErrorF("initing screen...\n");
548
549 /* a private key is the way to allocate private data into a public struct */
550 r = dixRegisterPrivateKey(&alga_pixmap_private_key, PRIVATE_PIXMAP, 0);
551 if (!r) {
552 ErrorF("unable to register a dix private key for pixmap structure\n");
553 goto err;
554 }
555
556 r = dixRegisterPrivateKey(&alga_screen_private_key, PRIVATE_SCREEN, 0);
557 if (!r) {
558 ErrorF("unable to register a dix private key for screen structure\n");
559 goto err;
560 }
561
562 alga_screen = calloc(1, sizeof(*alga_screen));
563 if (!alga_screen) {
564 ErrorF("unable to allocate an alga private screen structure\n");
565 goto err;
566 }
567
568 /*========================================================================*/
569 alga_screen->f = open("/dev/si0", O_RDWR | O_NONBLOCK);
570 if (alga_screen->f == -1) {
571 ErrorF("unable to open /dev/si0\n");
572 goto err_free_alga_screen;
573 }
574 AddGeneralSocket(alga_screen->f);
575
576 r = RRScreenInit(screen);
577 if (!r) {
578 ErrorF("unable to perform randr screen init\n");
579 goto err_remove_general_socket;
580 }
581
582 RRScreenSetSizeRange(screen, DISPLAYPORT_DEFAULT_WIDTH,
583 DISPLAYPORT_DEFAULT_HEIGHT, DCE6_WIDTH_MAX, DCE6_HEIGHT_MAX);
584
585 rr = rrGetScrPriv(screen);
586 rr->rrGetInfo = alga_rrGetInfo;
587 rr->rrSetConfig = alga_rrSetConfig;
588
589 alga_screen->idx = 5;
590 alga_screen->w = 1920;
591 alga_screen->h = 1080;
592 alga_screen->r = 60;
593 alga_screen->pixel_fmt = ALGA_ARGB8888;
594 alga_screen->stride = alga_screen->w
595 * alga_pixel_fmts_sz[alga_screen->pixel_fmt];
596 snprintf(&alga_screen->mode_name[0], CSTRLEN(MODE_NAME_MAX_TMPL),
597 "%ux%u@%u", alga_screen->w, alga_screen->h, alga_screen->r);
598
599 alga_fb_alloc(alga_screen);
600 alga_mode_set(alga_screen);
601
602 alga_screen->randr_crtc = RRCrtcCreate(screen, alga_screen);
603 if (!alga_screen->randr_crtc) {
604 ErrorF("unable to create randr crtc\n");
605 goto err_free_fb;
606 }
607
608 #define OUTPUT_NAME "hardcoded_output0"
609 alga_screen->randr_output = RROutputCreate(screen, OUTPUT_NAME,
610 sizeof(OUTPUT_NAME), alga_screen);
611 if (!alga_screen->randr_output) {
612 ErrorF("unable to create randr output\n");
613 goto err_destroy_randr_crtc;
614 }
615
616 r = RRCrtcGammaSetSize(alga_screen->randr_crtc, 256);
617 if (!r) {
618 ErrorF("unable to setup randr crtc gamma size\n");
619 goto err_destroy_randr_output;
620 }
621
622 r = RROutputSetCrtcs(alga_screen->randr_output, &alga_screen->randr_crtc,
623 1);
624 if (!r) {
625 ErrorF("unable to setup randr crtc for the output\n");
626 goto err_destroy_randr_output;
627 }
628
629 r = RROutputSetConnection(alga_screen->randr_output, RR_Connected);
630 if (!r) {
631 ErrorF("unable to set randr connected state of the output\n");
632 goto err_destroy_randr_output;
633 }
634
635 memset(&mode_info, 0, sizeof(mode_info));
636 mode_info.width = alga_screen->w;
637 mode_info.height = alga_screen->h;
638 /* we presume Hz here */
639 mode_info.dotClock = alga_screen->w * alga_screen->h * alga_screen->r;
640 mode_info.hSyncStart = alga_screen->w;
641 mode_info.hSyncEnd = alga_screen->w;
642 mode_info.hTotal = alga_screen->w;
643 mode_info.hSkew = 0;
644 mode_info.vSyncStart = alga_screen->h;
645 mode_info.vSyncEnd = alga_screen->h;
646 mode_info.vTotal = alga_screen->h;
647
648 mode_info.nameLength = strlen(&alga_screen->mode_name[0]) + 1;
649 randr_mode = RRModeGet(&mode_info, &alga_screen->mode_name[0]);
650
651 r = RROutputSetModes(alga_screen->randr_output, &randr_mode, 1, 1);
652 if (!r) {
653 ErrorF("unable to setup the randr modes of the output\n");
654 goto err_destroy_randr_output;
655 }
656
657 r = RRCrtcNotify(alga_screen->randr_crtc, randr_mode, 0, 0, RR_Rotate_0,
658 NULL, 1, &alga_screen->randr_output);
659 if (!r) {
660 ErrorF("unable to setup the randr crtc for the output mode\n");
661 goto err_destroy_randr_output;
662 }
663
664 screen->width = alga_screen->w;
665 screen->height = alga_screen->h;
666 /* FIXME: no root window yet for RRScreenSizeNotify(screen) */
667 /*========================================================================*/
668
669 /* target ARGB8888 as default */
670 if (alga_screen->pixel_fmt != ALGA_ARGB8888) {
671 ErrorF("don't handle pixel format other than ALGA_ARGB8888\n");
672 goto err_destroy_randr_output;
673 }
674
675 r = miSetVisualTypesAndMasks(24, 1 << TrueColor, 8, TrueColor, 0x00ff0000,
676 0x0000ff00, 0x000000ff);
677 if (!r) {
678 ErrorF("unable to perform mi visual init\n");
679 goto err_destroy_randr_output;
680 }
681
682 r = miSetPixmapDepths();
683 if (!r) {
684 ErrorF("unable to perform mi pixmap depth init\n");
685 goto err_destroy_randr_output;
686 }
687
688 /*
689 * XXX: we force the fbScreenInit code path *not* to put a pixmap
690 * in screen->devPrivate, since we will use it for our framebuffer
691 */
692 r = fbScreenInit(screen, NULL, screen->width, screen->height, X_DPI_DEFAULT,
693 Y_DPI_DEFAULT,
694 0, /* no pixmap provided */
695 32);
696 if (!r) {
697 ErrorF("unable to perform frame buffer helper init\n");
698 goto err_destroy_randr_output;
699 }
700
701 r = fbPictureInit(screen, 0, 0);
702 if (!r) {
703 ErrorF("unable to perform frame buffer helper picture init\n");
704 goto err_destroy_randr_output;
705 }
706
707 screen->CreatePixmap = pixmap_create;
708 screen->DestroyPixmap = pixmap_destroy;
709
710 screen->SaveScreen = screen_save;
711
712 screen->blackPixel = 0;
713 screen->whitePixel = 1;
714
715 /* XXX: must be setup *before* the color map */
716 r = miDCInitialize(screen, &alga_pointer_screen_funcs);
717 if (!r) {
718 ErrorF("unable to init pointer support\n");
719 goto err_destroy_randr_output;
720 }
721
722 r = fbCreateDefColormap(screen);
723 if (!r) {
724 ErrorF("unable to perform the frame buffer helper color map init\n");
725 goto err_destroy_randr_output;
726 }
727
728 /*------------------------------------------------------------------------*/
729 /* chain our funcs with the other subsystems */
730 alga_screen->CreateScreenResources = screen->CreateScreenResources;
731 screen->CreateScreenResources = alga_CreateScreenResources;
732
733 alga_screen->CloseScreen = screen->CloseScreen;
734 screen->CloseScreen = alga_CloseScreen;
735
736 alga_screen->BlockHandler = screen->BlockHandler;
737 screen->BlockHandler = alga_BlockHandler;
738
739 alga_screen->WakeupHandler = screen->WakeupHandler;
740 screen->WakeupHandler = alga_WakeupHandler;
741
742 alga_screen->RealizeWindow = screen->RealizeWindow;
743 screen->RealizeWindow = alga_RealizeWindow;
744 /*------------------------------------------------------------------------*/
745
746 alga_screen_set_private(screen, alga_screen);
747 fb_flip_schedule(screen, FALSE);
748 return TRUE;
749
750 /*========================================================================*/
751 err_destroy_randr_output:
752 RROutputDestroy(alga_screen->randr_output);
753
754 err_destroy_randr_crtc:
755 RRCrtcDestroy(alga_screen->randr_crtc);
756
757 err_free_fb:
758 alga_fb_free(alga_screen);
759
760 err_remove_general_socket:
761 RemoveGeneralSocket(alga_screen->f);
762 close(alga_screen->f);
763 /*========================================================================*/
764
765 err_free_alga_screen:
766 free(alga_screen);
767
768 err:
769 ErrorF("failed to init default screen\n");
770 return FALSE;
771 }
772
773 static void
774 fb_dma_to_device(ScreenPtr screen, Bool visible)
775 {
776 struct alga_screen *alga_screen;
777 PixmapPtr screen_pixmap;
778 struct alga_pixmap *alga_screen_pixmap;
779 /*----*/
780 struct si_dma dma;
781 struct si_dma_l2l *l2l;
782 struct si_timeouts_info *t_info;
783 ul req;
784 si r;
785
786 alga_screen = alga_screen_get(screen);
787 screen_pixmap = (PixmapPtr)screen->devPrivate;
788 alga_screen_pixmap = alga_pixmap_get(screen_pixmap);
789
790 l2l = &dma.params.l2l;
791 t_info = &dma.t_info;
792
793 dma.type = SI_DMA_TYPE_L2L;
794 dma.dir=SI_DMA_TO_DEVICE;
795
796 /* we don't really care here lets put one seconde! */
797 t_info->ring.n_max = 1;
798 t_info->ring.us = 1000000;
799 t_info->fence.n_max = 1;
800 t_info->fence.us = 1000000;
801
802 l2l->src_addr = (u64)alga_screen_pixmap->data;
803 if (visible)
804 l2l->dst_addr = alga_screen->fb_gpu_addr_visible;
805 else
806 l2l->dst_addr = alga_screen->fb_gpu_addr_hidden;
807 l2l->sz = alga_screen_pixmap->data_sz;
808
809 req = _IOW('d', SI_DMA, dma);
810
811 errno = 0;
812 r = ioctl(alga_screen->f, req, &dma);
813 switch (r) {
814 case -1:
815 FatalError("%s:dma l2l failed:%s\n", __func__, strerror(errno));
816 case SI_RING_TIMEOUT:
817 FatalError("%s:dma l2l failed:ring timeout\n", __func__);
818 case SI_FENCE_TIMEOUT:
819 FatalError("%s:dma l2l failed:fence timeout\n", __func__);
820 }
821 }
822
823 static void
824 si_evts_process(ScreenPtr screen, Bool flip_fbs)
825 {
826 struct alga_screen *alga_screen;
827 struct si_evt si_evt;
828 ssize_t rd;
829
830 alga_screen = alga_screen_get(screen);
831
832 while (1) {
833 errno = 0;
834 /* the driver sends whole events in order */
835 rd = read(alga_screen->f, &si_evt, sizeof(si_evt));
836
837 if (rd == -1) {
838 if (errno == EINTR)
839 continue;
840
841 if (errno == EAGAIN || errno == EWOULDBLOCK) {
842 return; /* no more events with a non blocking fd */
843 }
844
845 FatalError("an error occured while reading the page flip event\n");
846 }
847
848 if (!flip_fbs)
849 continue;
850
851 if (alga_screen->fb_gpu_addr_visible == alga_screen->fb_gpu_addr_front) {
852 alga_screen->fb_gpu_addr_visible = alga_screen->fb_gpu_addr_back;
853 alga_screen->fb_gpu_addr_hidden = alga_screen->fb_gpu_addr_front;
854 } else {
855 alga_screen->fb_gpu_addr_visible = alga_screen->fb_gpu_addr_front;
856 alga_screen->fb_gpu_addr_hidden = alga_screen->fb_gpu_addr_back;
857 }
858 }
859 }
860
861 static void
862 fb_flip_schedule(ScreenPtr screen, Bool retry_on_pending)
863 {
864 struct alga_screen *alga_screen;
865 u8 idx;
866
867 alga_screen = alga_screen_get(screen);
868 idx = alga_screen->idx;
869
870 while (1) {
871 ul req;
872 int r;
873
874 req = _IOW('d', SI_DCE_PF, idx);
875 errno = 0;
876 r = ioctl(alga_screen->f, req, &idx);
877
878 switch (r) {
879 case SI_DCE_PF_PENDING:
880 if (retry_on_pending)
881 continue;
882 else
883 FatalError("%s:a page flip is already pending\n", __func__);
884 case 0:
885 return;
886 case -1:
887 default:
888 FatalError("%s:error while scheduling a flip\n", __func__);
889 }
890 }
891 }
892
893 /*
894 * XXX: properly handling errors to make the code path robust is a **huge**
895 * task. Several displays per screen with a "not abort all on error" policy is
896 * really a daunting task. It is very likely that the code paths would become
897 * quite complex.
898 */
899 static void
900 alga_BlockHandler(ScreenPtr pScreen, void *pTimeout, void *pReadmask)
901 {
902 struct alga_screen *alga_screen;
903 alga_screen = alga_screen_get(pScreen);
904
905 if (alga_screen->fb_dma_do) {
906 alga_screen->fb_dma_do = FALSE;
907
908 if (!alga_screen->dpm_on) {
909 fb_dma_to_device(pScreen, FALSE);
910
911 fb_flip_schedule(pScreen, TRUE);
912 alga_screen->flip_evts_expected = TRUE;
913 }
914 }
915 }
916
917 static void
918 alga_WakeupHandler(ScreenPtr pScreen, unsigned long result, void *pReadMask)
919 {
920 struct alga_screen *alga_screen;
921 fd_set *general_sockets_rd;
922
923 alga_screen = alga_screen_get(pScreen);
924 general_sockets_rd = (fd_set *)pReadMask;
925
926 if (FD_ISSET(alga_screen->f, general_sockets_rd)) {
927 si_evts_process(pScreen, TRUE);
928 alga_screen->flip_evts_expected = FALSE;
929 alga_screen->fb_dma_do = TRUE;
930 }
931 }
File hw/xalga/xalga/evdev/axis/rel.h added (mode: 100644) (index 0000000..fbb078c)
1 #ifndef XALGA_EVDEV_AXIS_REL_H
2 #define XALGA_EVDEV_AXIS_REL_H
3 /*
4 * XALGA implementation
5 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
6 * Opens source legal protection provided by a GNU Lesser GPLv3 license
7 */
8
9 struct evdev;
10 struct dix_init_data;
11
12 #define EVDEV_REL_AXES_CNT REL_CNT
13
14 #ifdef XALGA_EVDEV_AXIS_REL_C
15 #define EXTERN
16 #else
17 #define EXTERN extern
18 #endif
19
20 EXTERN Bool rel_axes_codes_get(struct evdev *evdev);
21 EXTERN void rel_axes_get(struct dix_init_data *init_data);
22 EXTERN void rel_axis_code_dispatch(DeviceIntPtr dix, struct input_event *e);
23 EXTERN Bool dix_rel_axes_register(struct dix_init_data *init_data);
24 #undef EXTERN
25 #endif
File hw/xalga/xalga/evdev/evdev.h added (mode: 100644) (index 0000000..1a79d53)
1 #ifndef XALGA_EVDEV_EVDEV_H
2 #define XALGA_EVDEV_EVDEV_H
3 /*
4 * XALGA implementation
5 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
6 * Opens source legal protection provided by a GNU Lesser GPLv3 license
7 */
8
9
10 /*----------------------------------------------------------------------------*/
11 /* evdev bits helpers */
12 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
13 #define BITS_PER_BYTE 8
14 #define BITS_PER_LONG (sizeof(long) * BITS_PER_BYTE)
15 #define BITS_TO_LONGS(n) DIV_ROUND_UP(n, BITS_PER_BYTE * sizeof(long))
16
17 static inline Bool
18 is_bit_set(long *array, long bit_idx)
19 {
20 long long_idx;
21
22 long_idx = BITS_TO_LONGS(bit_idx + 1) - 1;
23
24 bit_idx = bit_idx - BITS_PER_LONG * long_idx;
25
26 return (1 << bit_idx) & array[long_idx];
27 }
28 #define IS_BIT_SET(a,i) is_bit_set(&(a)[0], i)
29 /*----------------------------------------------------------------------------*/
30
31
32 struct evdev {
33 struct xorg_list entry;
34
35 DeviceIntPtr dix;
36
37 char *dev_path; /* to init before calling evdev_init */
38 int fd;
39 void *read_buf;
40 Bool overrun;
41
42 long event_types[BITS_TO_LONGS(EV_CNT)];
43 long rel_codes[BITS_TO_LONGS(REL_CNT)];
44 long key_codes[BITS_TO_LONGS(KEY_CNT)];
45
46 /*
47 * lookup table to map evdev axes index to dix axes index, which will be
48 * used to create valutator masks for dix input event reporting
49 */
50 int rel_axes_dix_map[EVDEV_REL_AXES_CNT];
51
52 /*
53 * lookup tables for evdev code to dix button number, which size is
54 * **NOT** the number of evdev defined button since some "slots" are
55 * empty
56 */
57 int btns_misc_dix_map[BTN_9 - BTN_MISC + 1];
58 int btns_mouse_dix_map[BTN_TASK - BTN_MOUSE + 1];
59 int btns_joystick_dix_map[BTN_DEAD - BTN_JOYSTICK + 1];
60 int btns_gamepad_dix_map[BTN_THUMBR - BTN_GAMEPAD + 1];
61 int btns_digi_dix_map[BTN_TOOL_QUADTAP - BTN_DIGI + 1];
62 int btns_wheel_dix_map[BTN_GEAR_UP - BTN_WHEEL + 1];
63 int btns_dpad_dix_map[BTN_DPAD_RIGHT - BTN_DPAD_UP + 1];
64 int btns_trigger_happy_dix_map[BTN_TRIGGER_HAPPY40 - BTN_TRIGGER_HAPPY + 1];
65
66 Bool have_key;
67 XkbRMLVOSet xkb; /* to inin before calling evdev_init */
68 };
69
70 #ifdef XALGA_EVDEV_EVDEV_C
71 #define EXTERN
72 #else
73 #define EXTERN extern
74 #endif
75
76 EXTERN Bool evdev_init(struct evdev *evdev);
77 #undef EXTERN
78 #endif
File hw/xalga/xalga/evdev/input-event.h added (mode: 100644) (index 0000000..862e33f)
1 #ifndef XALGA_EVDEV_INPUT_EVENT_H
2 #define XALGA_EVDEV_INPUT_EVENT_H
3 /*
4 * XALGA implementation
5 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
6 * Opens source legal protection provided by a GNU Lesser GPLv3 license
7 */
8 extern void read_buf_processing(DeviceIntPtr dix);
9 extern void* read_buf_alloc(void);
10 #endif
File hw/xalga/xalga/evdev/key/key-btn.h added (mode: 100644) (index 0000000..15e4f0b)
1 #ifndef XALGA_EVDEV_KEY_KEY_BTN_H
2 #define XALGA_EVDEV_KEY_KEY_BTN_H
3 /*
4 * XALGA implementation
5 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
6 * Opens source legal protection provided by a GNU Lesser GPLv3 license
7 */
8 extern void key_btns_get(struct dix_init_data *init_data);
9 extern Bool dix_btns_register(struct dix_init_data *init_data);
10 #endif
11
File hw/xalga/xalga/evdev/key/key-key.h added (mode: 100644) (index 0000000..b920028)
1 #ifndef XALGA_EVDEV_KEY_KEY_KEY_H
2 #define XALGA_EVDEV_KEY_KEY_KEY_H
3 /*
4 * XALGA implementation
5 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
6 * Opens source legal protection provided by a GNU Lesser GPLv3 license
7 */
8 extern void key_keys_get(struct dix_init_data *init_data);
9 extern Bool dix_keys_register(struct dix_init_data *init_data);
10 #endif
File hw/xalga/xalga/evdev/key/key.h added (mode: 100644) (index 0000000..8943141)
1 #ifndef XALGA_EVDEV_KEY_KEY_H
2 #define XALGA_EVDEV_KEY_KEY_H
3 /*
4 * XALGA implementation
5 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
6 * Opens source legal protection provided by a GNU Lesser GPLv3 license
7 */
8 extern Bool key_codes_get(struct evdev *evdev);
9 extern void key_code_dispatch(DeviceIntPtr dix, struct input_event *e);
10 #endif
File hw/xalga/xalga/evdev/key/private.h added (mode: 100644) (index 0000000..3d55ff1)
1 #ifndef XALGA_EVDEV_KEY_PRIVATE_H
2 #define XALGA_EVDEV_KEY_PRIVATE_H
3 /*
4 * XALGA implementation
5 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
6 * Opens source legal protection provided by a GNU Lesser GPLv3 license
7 */
8 extern void btn_process(DeviceIntPtr dix, struct input_event *e,
9 u16 btn_section_mask);
10 extern u16 btn_section_mask_get(u16 code);
11 extern void key_process(DeviceIntPtr dix_dev, struct input_event *e);
12 #endif
File hw/xalga/xalga/evdev/private.h added (mode: 100644) (index 0000000..5516802)
1 #ifndef XALGA_EVDEV_PRIVATE_H
2 #define XALGA_EVDEV_PRIVATE_H
3 /*
4 * XALGA implementation
5 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
6 * Opens source legal protection provided by a GNU Lesser GPLv3 license
7 */
8
9 /*----------------------------------------------------------------------------*/
10 /*
11 * this struct collects all the data required from evdev *before* configuring
12 * the device properly from a dix perspective
13 */
14 struct rel_axes_init_data {
15 u8 cnt;
16 Atom labels[EVDEV_REL_AXES_CNT];
17 /* for scroll valuators */
18 u8 scroll_type[EVDEV_REL_AXES_CNT];
19 u8 scroll_flags[EVDEV_REL_AXES_CNT];
20 };
21
22 struct dix_init_data {
23 DeviceIntPtr dix;
24
25 u8 dix_axes_cnt;
26 struct rel_axes_init_data rel_axes;
27
28 u16 dix_btn_n_max;
29 };
30 /*----------------------------------------------------------------------------*/
31 #endif
File hw/xalga/xalga/namespace.h added (mode: 100644) (index 0000000..bb0133a)
1 #ifndef XALGA_NAMESPACE_H
2 #define XALGA_NAMESPACE_H
3 /*
4 * XALGA implementation
5 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
6 * Opens source legal protection provided by a GNU Lesser GPLv3 license
7 */
8
9 #define u8 uint8_t
10 #define u16 uint16_t
11 #define u32 uint32_t
12 #define u64 uint64_t
13 #define ull unsigned long long
14 #define ul unsigned long
15 #define si int
16
17 #define CSTRLEN(x) (sizeof(x) - 1)
18 #endif
File hw/xalga/xalga/output.h added (mode: 100644) (index 0000000..f2b82e9)
1 #ifndef XALGA_OUTPUT_H
2 #define XALGA_OUTPUT_H
3 /*
4 * XALGA implementation
5 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
6 * Opens source legal protection provided by a GNU Lesser GPLv3 license
7 */
8 extern Bool screen_init(ScreenPtr screen, int argc, char **argv);
9 #endif
File include/xalga_glx_extinit.h added (mode: 100644) (index 0000000..4e434b1)
1 #ifndef XALGA_GLX_EXT_INIT_H
2 #define XALGA_GLX_EXT_INIT_H
3 /*
4 * XALGA implementation
5 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
6 * Opens source legal protection provided by a GNU Lesser GPLv3 license
7 */
8 extern void xalga_glx_extension_init(void);
9 #endif
File xalgaglx/Makefile.am added (mode: 100644) (index 0000000..b1095e5)
1 noinst_LTLIBRARIES = libglx.la
2
3 AM_CFLAGS = \
4 @DIX_CFLAGS@ \
5 @XLIB_CFLAGS@
6
7 libglx_la_SOURCES = \
8 glxext.c
9
10 libglx_la_LIBADD = $(DLOPEN_LIBS)
File xalgaglx/glxext.c added (mode: 100644) (index 0000000..8d2f1cc)
1 /*
2 * XALGA-GLX implementation
3 * Copyright (C) 2014 Sylvain BERTRAND All Rights Reserved
4 * Opens source legal protection provided by a GNU Lesser GPLv3 license
5 * Original code was sublicenced, see below.
6 */
7
8 /*
9 *
10 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
11 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a
14 * copy of this software and associated documentation files (the "Software"),
15 * to deal in the Software without restriction, including without limitation
16 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 * and/or sell copies of the Software, and to permit persons to whom the
18 * Software is furnished to do so, subject to the following conditions:
19 *
20 * The above copyright notice including the dates of first publication and
21 * either this permission notice or a reference to
22 * http://oss.sgi.com/projects/FreeB/
23 * shall be included in all copies or substantial portions of the Software.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
26 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
29 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
30 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
32 *
33 * Except as contained in this notice, the name of Silicon Graphics, Inc.
34 * shall not be used in advertising or otherwise to promote the sale, use or
35 * other dealings in this Software without prior written authorization from
36 * Silicon Graphics, Inc.
37 */
38
39 #ifdef HAVE_DIX_CONFIG_H
40 #include <dix-config.h>
41 #endif
42
43 #include "extnsionst.h"
44
45 void xalga_glx_extension_init(void);
46 static int glx_dispatch(ClientPtr client);
47 static int glx_error_base;
48 int glx_event_base;
49
50 void
51 xalga_glx_extension_init(void)
52 {
53 ExtensionEntry *extension_entry;
54 Bool r;
55
56 /* add extension to server extensions */
57 extension_entry= AddExtension("GLX", 0, 0, glx_dispatch, glx_dispatch, NULL,
58 StandardMinorOpcode);
59 if (!extension_entry) {
60 FatalError("%s: AddExtensions failed\n", __func__);
61 return;
62 }
63
64 r = AddExtensionAlias("GLX", extension_entry);
65 if (!r) {
66 ErrorF("%s: AddExtensionAlias failed\n", __func__);
67 return;
68 }
69
70 glx_error_base = extension_entry->errorBase;
71 glx_event_base = extension_entry->eventBase;
72 }
73
74 static int
75 glx_dispatch(ClientPtr client)
76 {
77 LogMessage(X_INFO, "GLX request received-->NOP\n");
78 return Success;
79 }
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/sylware/xalga

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/sylware/xalga

Clone this repository using git:
git clone git://git.rocketgit.com/user/sylware/xalga

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main