1 #include <stdlib.h>
2 #include <string.h>
3 #include <libretro.h>
4 #include <input.h>
5 #include <util.h>
6
7 struct input_data {
8 struct input_config *config;
9 int16_t *states;
10 };
11
12 struct retro_data {
13 struct list_link *input_states;
14 retro_input_poll_t input_poll_cb;
15 retro_input_state_t input_state_cb;
16 };
17
18 static void ret_load(struct input_frontend *fe, struct input_config *cfg);
19 static void ret_unload(struct input_frontend *fe, struct input_config *cfg);
20 static void ret_update(struct input_frontend *fe);
21
22 static struct retro_data retro_data;
23
retro_set_input_poll(retro_input_poll_t cb)24 void retro_set_input_poll(retro_input_poll_t cb)
25 {
26 retro_data.input_poll_cb = cb;
27 }
28
retro_set_input_state(retro_input_state_t cb)29 void retro_set_input_state(retro_input_state_t cb)
30 {
31 retro_data.input_state_cb = cb;
32 }
33
ret_load(struct input_frontend * fe,struct input_config * cfg)34 void ret_load(struct input_frontend *fe, struct input_config *cfg)
35 {
36 struct input_data *data;
37
38 /* Allocate input data structure and append it to states list */
39 data = calloc(1, sizeof(struct input_data));
40 list_insert(&retro_data.input_states, data);
41
42 /* Initialize input data */
43 data->config = cfg;
44 data->states = calloc(cfg->num_descs, sizeof(int16_t));
45 }
46
ret_unload(struct input_frontend * fe,struct input_config * cfg)47 void ret_unload(struct input_frontend *fe, struct input_config *cfg)
48 {
49 struct list_link *link = retro_data.input_states;
50 struct input_data *data;
51
52 /* Find data associated to config */
53 while ((data = list_get_next(&link)))
54 if (data->config == cfg)
55 break;
56
57 /* Free data and remove it from states list */
58 free(data->states);
59 free(data);
60 list_remove(&retro_data.input_states, data);
61 }
62
ret_update(struct input_frontend * UNUSED (fe))63 void ret_update(struct input_frontend *UNUSED(fe))
64 {
65 struct list_link *link = retro_data.input_states;
66 struct input_data *data;
67 struct input_desc *desc;
68 enum input_type type;
69 unsigned int dev;
70 unsigned int port;
71 unsigned int index;
72 unsigned int id;
73 int16_t s;
74 int i;
75
76 /* Poll input */
77 retro_data.input_poll_cb();
78
79 /* Parse all configs and update states */
80 while ((data = list_get_next(&link)))
81 for (i = 0; i < data->config->num_descs; i++) {
82 /* Get descriptor */
83 desc = &data->config->descs[i];
84
85 /* Extract device, port, index, and ID from config */
86 dev = desc->device;
87 port = (desc->code >> PORT_SHIFT) & PORT_MASK;
88 index = (desc->code >> INDEX_SHIFT) & INDEX_MASK;
89 id = (desc->code >> ID_SHIFT) & ID_MASK;
90
91 /* Get state and continue if unchanged */
92 s = retro_data.input_state_cb(port, dev, index, id);
93 if (s == data->states[i])
94 continue;
95
96 /* Report event directly */
97 type = (s > 0) ? EVENT_BUTTON_DOWN : EVENT_BUTTON_UP;
98 data->config->callback(i, type, data->config->data);
99
100 /* Save new state */
101 data->states[i] = s;
102 }
103 }
104
105 INPUT_START(retro)
106 .load = ret_load,
107 .unload = ret_unload,
108 .update = ret_update
109 INPUT_END
110
111