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