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 300