~ubuntu-branches/ubuntu/wily/bluez/wily

« back to all changes in this revision

Viewing changes to input/sixpair.c

ImportĀ upstreamĀ versionĀ 4.81

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* To compile
2
 
 * gcc -g -Wall -I../src -I../lib/ -I../include -DSTORAGEDIR=\"/var/lib/bluetooth\" -o sixpair sixpair.c ../src/storage.c ../common/libhelper.a -I../common `pkg-config --libs --cflags glib-2.0 libusb-1.0` -lbluetooth
3
 
 */
4
 
 
5
 
#include <unistd.h>
6
 
#include <stdio.h>
7
 
#include <inttypes.h>
8
 
 
9
 
#include <sdp.h>
10
 
#include <bluetooth/bluetooth.h>
11
 
#include <bluetooth/sdp_lib.h>
12
 
#include <glib.h>
13
 
#include <libusb.h>
14
 
 
15
 
#include "storage.h"
16
 
 
17
 
/* Vendor and product ID for the Sixaxis PS3 controller */
18
 
#define VENDOR 0x054c
19
 
#define PRODUCT 0x0268
20
 
 
21
 
#define PS3_PNP_RECORD "3601920900000A000100000900013503191124090004350D35061901000900113503190011090006350909656E09006A0901000900093508350619112409010009000D350F350D350619010009001335031900110901002513576972656C65737320436F6E74726F6C6C65720901012513576972656C65737320436F6E74726F6C6C6572090102251B536F6E7920436F6D707574657220456E7465727461696E6D656E740902000901000902010901000902020800090203082109020428010902052801090206359A35980822259405010904A101A102850175089501150026FF00810375019513150025013500450105091901291381027501950D0600FF8103150026FF0005010901A10075089504350046FF0009300931093209358102C0050175089527090181027508953009019102750895300901B102C0A1028502750895300901B102C0A10285EE750895300901B102C0A10285EF750895300901B102C0C0090207350835060904090901000902082800090209280109020A280109020B09010009020C093E8009020D280009020E2800"
22
 
 
23
 
gboolean option_get_master = TRUE;
24
 
char *option_master= NULL;
25
 
gboolean option_store_info = TRUE;
26
 
const char *option_device = NULL;
27
 
gboolean option_quiet = FALSE;
28
 
 
29
 
const GOptionEntry options[] = {
30
 
        { "get-master", '\0', 0, G_OPTION_ARG_NONE, &option_get_master, "Get currently set master address", NULL },
31
 
        { "set-master", '\0', 0, G_OPTION_ARG_STRING, &option_master, "Set master address (\"auto\" for automatic)", NULL },
32
 
        { "store-info", '\0', 0, G_OPTION_ARG_NONE, &option_store_info, "Store the HID info into the input database", NULL },
33
 
        { "device", '\0', 0, G_OPTION_ARG_STRING, &option_device, "Only handle one device (default, all supported", NULL },
34
 
        { "quiet", 'q', 0, G_OPTION_ARG_NONE, &option_quiet, "Quieten the output", NULL },
35
 
        { NULL }
36
 
};
37
 
 
38
 
static gboolean
39
 
show_master (libusb_device_handle *devh, int itfnum)
40
 
{
41
 
        unsigned char msg[8];
42
 
        int res;
43
 
 
44
 
        res = libusb_control_transfer (devh,
45
 
                                       LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
46
 
                                       0x01, 0x03f5, itfnum,
47
 
                                       (void*) msg, sizeof(msg),
48
 
                                       5000);
49
 
 
50
 
        if (res < 0) {
51
 
                g_warning ("Getting the master Bluetooth address failed");
52
 
                return FALSE;
53
 
        }
54
 
        g_print ("Current Bluetooth master: %02X:%02X:%02X:%02X:%02X:%02X\n",
55
 
                 msg[2], msg[3], msg[4], msg[5], msg[6], msg[7]);
56
 
 
57
 
        return TRUE;
58
 
}
59
 
 
60
 
static char *
61
 
get_bdaddr (libusb_device_handle *devh, int itfnum)
62
 
{
63
 
        unsigned char msg[17];
64
 
        char *address;
65
 
        int res;
66
 
 
67
 
        res = libusb_control_transfer (devh,
68
 
                                       LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
69
 
                                       0x01, 0x03f2, itfnum,
70
 
                                       (void*) msg, sizeof(msg),
71
 
                                       5000);
72
 
 
73
 
        if (res < 0) {
74
 
                g_warning ("Getting the device Bluetooth address failed");
75
 
                return NULL;
76
 
        }
77
 
 
78
 
        address = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
79
 
                                   msg[4], msg[5], msg[6], msg[7], msg[8], msg[9]);
80
 
 
81
 
        if (option_quiet == FALSE) {
82
 
                g_print ("Device Bluetooth address: %s\n", address);
83
 
        }
84
 
 
85
 
        return address;
86
 
}
87
 
 
88
 
static gboolean
89
 
set_master_bdaddr (libusb_device_handle *devh, int itfnum, char *host)
90
 
{
91
 
        unsigned char msg[8];
92
 
        int mac[6];
93
 
        int res;
94
 
 
95
 
        if (sscanf(host, "%X:%X:%X:%X:%X:%X",
96
 
                   &mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]) != 6) {
97
 
                return FALSE;
98
 
        }
99
 
 
100
 
        msg[0] = 0x01;
101
 
        msg[1] = 0x00;
102
 
        msg[2] = mac[0];
103
 
        msg[3] = mac[1];
104
 
        msg[4] = mac[2];
105
 
        msg[5] = mac[3];
106
 
        msg[6] = mac[4];
107
 
        msg[7] = mac[5];
108
 
 
109
 
        res = libusb_control_transfer (devh,
110
 
                                       LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
111
 
                                       0x09, 0x03f5, itfnum,
112
 
                                       (void*) msg, sizeof(msg),
113
 
                                       5000);
114
 
 
115
 
        if (res < 0) {
116
 
                g_warning ("Setting the master Bluetooth address failed");
117
 
                return FALSE;
118
 
        }
119
 
 
120
 
        return TRUE;
121
 
}
122
 
 
123
 
static char *
124
 
get_host_bdaddr (void)
125
 
{
126
 
        FILE *f;
127
 
        int mac[6];
128
 
 
129
 
        //FIXME use dbus to get the default adapter
130
 
 
131
 
        f = popen("hcitool dev", "r");
132
 
 
133
 
        if (f == NULL) {
134
 
                //FIXME
135
 
                return NULL;
136
 
        }
137
 
        if (fscanf(f, "%*s\n%*s %X:%X:%X:%X:%X:%X",
138
 
                   &mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]) != 6) {
139
 
                //FIXME
140
 
                return NULL;
141
 
        }
142
 
 
143
 
        return g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
144
 
}
145
 
 
146
 
static int
147
 
handle_device (libusb_device *dev, struct libusb_config_descriptor *cfg, int itfnum, const struct libusb_interface_descriptor *alt)
148
 
{
149
 
        libusb_device_handle *devh;
150
 
        int res, retval;
151
 
 
152
 
        retval = -1;
153
 
 
154
 
        if (libusb_open (dev, &devh) < 0) {
155
 
                g_warning ("Can't open device");
156
 
                goto bail;
157
 
        }
158
 
        libusb_detach_kernel_driver (devh, itfnum);
159
 
 
160
 
        res = libusb_claim_interface (devh, itfnum);
161
 
        if (res < 0) {
162
 
                g_warning ("Can't claim interface %d", itfnum);
163
 
                goto bail;
164
 
        }
165
 
 
166
 
        if (option_get_master != FALSE) {
167
 
                if (show_master (devh, itfnum) == FALSE)
168
 
                        goto bail;
169
 
                retval = 0;
170
 
        }
171
 
 
172
 
        if (option_master != NULL) {
173
 
                if (strcmp (option_master, "auto") == 0) {
174
 
                        g_free (option_master);
175
 
                        option_master = get_host_bdaddr ();
176
 
                        if (option_master == NULL) {
177
 
                                g_warning ("Can't get bdaddr from default device");
178
 
                                retval = -1;
179
 
                                goto bail;
180
 
                        }
181
 
                }
182
 
        } else {
183
 
                option_master = get_host_bdaddr ();
184
 
                if (option_master == NULL) {
185
 
                        g_warning ("Can't get bdaddr from default device");
186
 
                        retval = -1;
187
 
                        goto bail;
188
 
                }
189
 
        }
190
 
 
191
 
        if (option_store_info != FALSE) {
192
 
                sdp_record_t *rec;
193
 
                char *device;
194
 
                bdaddr_t dst, src;
195
 
 
196
 
                device = get_bdaddr (devh, itfnum);
197
 
                if (device == NULL) {
198
 
                        retval = -1;
199
 
                        goto bail;
200
 
                }
201
 
 
202
 
                rec = record_from_string (PS3_PNP_RECORD);
203
 
                store_record(option_master, device, rec);
204
 
                write_trust(option_master, device, "[all]", TRUE);
205
 
                store_device_id(option_master, device, 0xffff, 0x054c, 0x0268, 0);
206
 
                str2ba(option_master, &src);
207
 
                str2ba(device, &dst);
208
 
                write_device_profiles(&src, &dst, "");
209
 
                write_device_name(&src, &dst, "PLAYSTATION(R)3 Controller");
210
 
                sdp_record_free(rec);
211
 
 
212
 
                if (set_master_bdaddr (devh, itfnum, option_master) == FALSE) {
213
 
                        retval = -1;
214
 
                        goto bail;
215
 
                }
216
 
        }
217
 
 
218
 
bail:
219
 
        libusb_release_interface (devh, itfnum);
220
 
        res = libusb_attach_kernel_driver(devh, itfnum);
221
 
        if (res < 0) {
222
 
                //FIXME sometimes the kernel tells us ENOENT, but succeeds anyway...
223
 
                g_warning ("Reattaching the driver failed: %d", res);
224
 
        }
225
 
        if (devh != NULL)
226
 
                libusb_close (devh);
227
 
 
228
 
        return retval;
229
 
}
230
 
 
231
 
int main (int argc, char **argv)
232
 
{
233
 
        GOptionContext *context;
234
 
        GError *error = NULL;
235
 
        libusb_device **list;
236
 
        ssize_t num_devices, i;
237
 
 
238
 
        context = g_option_context_new ("- Manage Sixaxis PS3 controllers");
239
 
        g_option_context_add_main_entries (context, options, NULL);
240
 
        if (g_option_context_parse (context, &argc, &argv, &error) == FALSE) {
241
 
                g_warning ("Couldn't parse command-line options: %s", error->message);
242
 
                return 1;
243
 
        }
244
 
 
245
 
        /* Check that the passed bdaddr is correct */
246
 
        if (option_master != NULL && strcmp (option_master, "auto") != 0) {
247
 
                //FIXME check bdaddr
248
 
        }
249
 
 
250
 
        libusb_init (NULL);
251
 
 
252
 
        /* Find device(s) */
253
 
        num_devices = libusb_get_device_list (NULL, &list);
254
 
        if (num_devices < 0) {
255
 
                g_warning ("libusb_get_device_list failed");
256
 
                return 1;
257
 
        }
258
 
 
259
 
        for (i = 0; i < num_devices; i++) {
260
 
                struct libusb_config_descriptor *cfg;
261
 
                libusb_device *dev = list[i];
262
 
                struct libusb_device_descriptor desc;
263
 
                guint8 j;
264
 
 
265
 
                if (libusb_get_device_descriptor (dev, &desc) < 0) {
266
 
                        g_warning ("libusb_get_device_descriptor failed");
267
 
                        continue;
268
 
                }
269
 
 
270
 
                /* Here we check for the supported devices */
271
 
                if (desc.idVendor != VENDOR || desc.idProduct != PRODUCT)
272
 
                        continue;
273
 
 
274
 
                /* Look for the interface number that interests us */
275
 
                for (j = 0; j < desc.bNumConfigurations; j++) {
276
 
                        struct libusb_config_descriptor *config;
277
 
                        guint8 k;
278
 
 
279
 
                        libusb_get_config_descriptor (dev, j, &config);
280
 
 
281
 
                        for (k = 0; k < config->bNumInterfaces; k++) {
282
 
                                const struct libusb_interface *itf = &config->interface[k];
283
 
                                int l;
284
 
 
285
 
                                for (l = 0; l < itf->num_altsetting ; l++) {
286
 
                                        struct libusb_interface_descriptor alt;
287
 
 
288
 
                                        alt = itf->altsetting[l];
289
 
                                        if (alt.bInterfaceClass == 3) {
290
 
                                                handle_device (dev, cfg, l, &alt);
291
 
                                        }
292
 
                                }
293
 
                        }
294
 
                }
295
 
        }
296
 
 
297
 
        return 0;
298
 
}
299