* [PATCHes] Add sixpair
@ 2008-10-15 15:15 Bastien Nocera
2008-10-15 15:22 ` Marcel Holtmann
2008-10-15 23:52 ` Marcel Holtmann
0 siblings, 2 replies; 8+ messages in thread
From: Bastien Nocera @ 2008-10-15 15:15 UTC (permalink / raw)
To: BlueZ development
[-- Attachment #1: Type: text/plain, Size: 733 bytes --]
Heya,
Here are the patches to get sixpair support built into BlueZ. It uses
libusb-1.0 as well as a yet to be merged libusb-1.0 patch to allow
re-attaching a driver to a device.
Problems left to solve:
- sixaxis enabler code (as seen in enable_sixaxis() in compat/hidd.c)
seems to have disappeared from the input plugin. Is that done in the
kernel now, or was it just removed?
- After "cable pairing" the device, I need to unplug/replug the adapter,
or restart bluetoothd. Can anyone think of a better way of getting the
list of devices updated?
- Some minor niggles in the code itself (use D-Bus instead of parsing
command-line tools)
- udev rule(s) and parsing only the selected device would be necessary
if not required
Cheers
[-- Attachment #2: 0001-Add-sixpair-tool.patch --]
[-- Type: text/x-patch, Size: 10178 bytes --]
>From c06f9fa3f7d088c173403d602209d7a18e7b00e5 Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Sat, 11 Oct 2008 00:55:02 +0100
Subject: [PATCH] Add sixpair tool
Sixpair is an unfinished helper to automatically pair a
plugged in Playstation 3 Sixaxis Bluetooth joypad.
---
input/sixpair.c | 393 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 393 insertions(+), 0 deletions(-)
create mode 100644 input/sixpair.c
diff --git a/input/sixpair.c b/input/sixpair.c
new file mode 100644
index 0000000..818d283
--- /dev/null
+++ b/input/sixpair.c
@@ -0,0 +1,393 @@
+/* To compile
+ * 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` -lbluetooth
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <sdp.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hidp.h>
+#include <glib.h>
+#include <usb.h>
+
+#include "storage.h"
+
+/* Vendor and product ID for the Sixaxis PS3 controller */
+#define VENDOR 0x054c
+#define PRODUCT 0x0268
+
+#define USB_DIR_IN 0x80
+#define USB_DIR_OUT 0
+
+gboolean option_get_master = TRUE;
+char *option_master= NULL;
+gboolean option_store_info = TRUE;
+const char *option_device = NULL;
+gboolean option_quiet = FALSE;
+
+const GOptionEntry options[] = {
+ { "get-master", '\0', 0, G_OPTION_ARG_NONE, &option_get_master, "Get currently set master address", NULL },
+ { "set-master", '\0', 0, G_OPTION_ARG_STRING, &option_master, "Set master address (\"auto\" for automatic)", NULL },
+ { "store-info", '\0', 0, G_OPTION_ARG_NONE, &option_store_info, "Store the HID info into the input database", NULL },
+ { "device", '\0', 0, G_OPTION_ARG_STRING, &option_device, "Only handle one device (default, all supported", NULL },
+ { "quiet", 'q', 0, G_OPTION_ARG_NONE, &option_quiet, "Quieten the output", NULL },
+ { NULL }
+};
+
+static gboolean
+show_master (usb_dev_handle *devh, int itfnum)
+{
+ unsigned char msg[8];
+ int res;
+
+ res = usb_control_msg (devh,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 0x01, 0x03f5, itfnum,
+ (void*) msg, sizeof(msg),
+ 5000);
+
+ if (res < 0) {
+ g_warning ("Getting the master Bluetooth address failed");
+ return FALSE;
+ }
+ g_print ("Current Bluetooth master: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ msg[2], msg[3], msg[4], msg[5], msg[6], msg[7]);
+
+ return TRUE;
+}
+
+static char *
+get_bdaddr (usb_dev_handle *devh, int itfnum)
+{
+ unsigned char msg[17];
+ char *address;
+ int res;
+
+ res = usb_control_msg (devh,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 0x01, 0x03f2, itfnum,
+ (void*) msg, sizeof(msg),
+ 5000);
+
+ if (res < 0) {
+ g_warning ("Getting the device Bluetooth address failed");
+ return NULL;
+ }
+
+ address = g_strdup_printf ("%02x:%02x:%02x:%02x:%02x:%02x",
+ msg[4], msg[5], msg[6], msg[7], msg[8], msg[9]);
+
+ if (option_quiet == FALSE) {
+ g_print ("Device Bluetooth address: %s\n", address);
+ }
+
+ return address;
+}
+
+static gboolean
+set_master_bdaddr (usb_dev_handle *devh, int itfnum, char *host)
+{
+ unsigned char msg[8];
+ int mac[6];
+ int res;
+
+ if (sscanf(host, "%x:%x:%x:%x:%x:%x",
+ &mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]) != 6) {
+ return FALSE;
+ }
+
+ msg[0] = 0x01;
+ msg[1] = 0x00;
+ msg[2] = mac[0];
+ msg[3] = mac[1];
+ msg[4] = mac[2];
+ msg[5] = mac[3];
+ msg[6] = mac[4];
+ msg[7] = mac[5];
+
+ res = usb_control_msg (devh,
+ USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 0x09, 0x03f5, itfnum,
+ (void*) msg, sizeof(msg),
+ 5000);
+
+ if (res < 0) {
+ g_warning ("Setting the master Bluetooth address failed");
+ return FALSE;
+ }
+
+ return TRUE;
+
+}
+
+static char *
+get_host_bdaddr (void)
+{
+ FILE *f;
+ int mac[6];
+
+ //FIXME use dbus to get the default adapter
+
+ f = popen("hcitool dev", "r");
+
+ if (f == NULL) {
+ //FIXME
+ return NULL;
+ }
+ if (fscanf(f, "%*s\n%*s %x:%x:%x:%x:%x:%x",
+ &mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]) != 6) {
+ //FIXME
+ return NULL;
+ }
+
+ return g_strdup_printf ("%x:%x:%x:%x:%x:%x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+}
+
+static int
+get_record_info (struct usb_interface_descriptor *alt, unsigned int *_len, unsigned int *_country, uint16_t *_version)
+{
+ unsigned char *buf;
+ unsigned int size, len, country;
+ uint16_t version;
+ int l;
+
+ len = 0;
+ country = 0;
+ version = 0;
+
+ if (!alt->extralen)
+ return 0;
+
+ size = alt->extralen;
+ buf = alt->extra;
+ while (size >= 2 * sizeof(u_int8_t)) {
+ if (buf[0] < 2 || buf[1] != USB_DT_HID)
+ continue;
+
+ //FIXME that should be "21"
+ //g_message ("country: %u", buf[4]);
+ //country = buf[4];
+ //country = 0x21;
+ country = 0;
+ version = (buf[3] << 8) + buf[2];
+
+ for (l = 0; l < buf[5]; l++) {
+ /* we are just interested in report descriptors*/
+ if (buf[6+3*l] != USB_DT_REPORT)
+ continue;
+ len = buf[7+3*l] | (buf[8+3*l] << 8);
+ }
+ size -= buf[0];
+ buf += buf[0];
+ }
+
+ if (len == 0)
+ return -1;
+ *_len = len;
+ *_country = country;
+ *_version = version;
+
+ return 0;
+}
+
+static void
+fill_req_from_usb (struct usb_device *dev, struct hidp_connadd_req *req, void *data, unsigned int len, unsigned int country, uint16_t version)
+{
+ req->vendor = dev->descriptor.idVendor;
+ req->product = dev->descriptor.idProduct;
+ req->version = version;
+ /* req->subclass already set */
+ req->country = country;
+ /* Default value */
+ req->parser = 0x0100;
+ /* What are we expecting here? No idea, but we don't seem to need it */
+ req->flags = 0;
+
+ req->rd_size = len;
+ req->rd_data = data;
+}
+
+static void
+store_info (const char *host, const char *device, struct hidp_connadd_req *req)
+{
+ bdaddr_t dest, src;
+
+ if (str2ba (host, &src) < 0) {
+ //FIXME
+ return;
+ }
+ if (str2ba (device, &dest) < 0) {
+ //FIXME
+ return;
+ }
+
+#if 0
+ if (store_device_info (&src, &dest, req) < 0)
+#endif
+ g_message ("store_device_info failed");
+}
+
+static int
+handle_device (struct usb_device *dev, struct usb_config_descriptor *cfg, int itfnum, struct usb_interface_descriptor *alt)
+{
+ usb_dev_handle *devh;
+ int res, retval;
+
+ retval = -1;
+
+ devh = usb_open (dev);
+ if (devh == NULL) {
+ g_warning ("Can't open device");
+ goto bail;
+ }
+ usb_detach_kernel_driver_np (devh, itfnum);
+
+ res = usb_claim_interface (devh, itfnum);
+ if (res < 0) {
+ g_warning ("Can't claim interface %d", itfnum);
+ goto bail;
+ }
+
+ if (option_get_master != FALSE) {
+ if (show_master (devh, itfnum) == FALSE)
+ goto bail;
+ retval = 0;
+ }
+
+ if (option_master != NULL) {
+ if (strcmp (option_master, "auto") == 0) {
+ g_free (option_master);
+ option_master = get_host_bdaddr ();
+ if (option_master == NULL) {
+ g_warning ("Can't get bdaddr from default device");
+ retval = -1;
+ goto bail;
+ }
+ }
+ } else {
+ option_master = get_host_bdaddr ();
+ if (option_master == NULL) {
+ g_warning ("Can't get bdaddr from default device");
+ retval = -1;
+ goto bail;
+ }
+ }
+
+ if (option_store_info != FALSE) {
+ unsigned char data[8192];
+ struct hidp_connadd_req req;
+ unsigned int len, country;
+ int n;
+ uint16_t version;
+ char *device;
+
+ device = get_bdaddr (devh, itfnum);
+ if (device == NULL) {
+ retval = -1;
+ goto bail;
+ }
+
+ if (get_record_info (alt, &len, &country, &version) < 0) {
+ g_warning ("Can't get record info");
+ retval = -1;
+ goto bail;
+ }
+
+ if ((n = usb_control_msg(devh,
+ USB_ENDPOINT_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE,
+ USB_REQ_GET_DESCRIPTOR,
+ (USB_DT_REPORT << 8),
+ itfnum, (void *) &data, len, 5000)) < 0) {
+ g_warning ("Can't get report descriptor (length: %d, interface: %d)", len, itfnum);
+ retval = -1;
+ goto bail;
+ }
+
+ req.subclass = alt->bInterfaceSubClass;
+ fill_req_from_usb (dev, &req, data, len, country, version);
+
+ store_info (option_master, device, &req);
+
+ if (set_master_bdaddr (devh, itfnum, option_master) == FALSE) {
+ retval = -1;
+ goto bail;
+ }
+
+ //FIXME finally, set device as trusted
+ }
+
+bail:
+ if (devh != NULL)
+ usb_close (devh);
+
+ return retval;
+}
+
+int main (int argc, char **argv)
+{
+ GOptionContext *context;
+ GError *error = NULL;
+ struct usb_bus *busses, *bus;
+
+ context = g_option_context_new ("- Manage Sixaxis PS3 controllers");
+ g_option_context_add_main_entries (context, options, NULL);
+ if (g_option_context_parse (context, &argc, &argv, &error) == FALSE) {
+ g_warning ("Couldn't parse command-line options: %s", error->message);
+ return 1;
+ }
+
+ /* Check that the passed bdaddr is correct */
+ if (option_master != NULL && strcmp (option_master, "auto") != 0) {
+ //FIXME check bdaddr
+ }
+
+ /* Find device(s) */
+ usb_init ();
+ if (usb_find_busses () < 0) {
+ g_warning ("usb_find_busses failed");
+ return 1;
+ }
+ if (usb_find_devices () < 0) {
+ g_warning ("usb_find_devices failed");
+ return 1;
+ }
+
+ busses = usb_get_busses();
+ if (busses == NULL) {
+ g_warning ("usb_get_busses failed");
+ return 1;
+ }
+
+ for (bus = busses; bus; bus = bus->next) {
+ struct usb_device *dev;
+
+ for (dev = bus->devices; dev; dev = dev->next) {
+ struct usb_config_descriptor *cfg;
+
+ /* Here we check for the supported devices */
+ if (dev->descriptor.idVendor != VENDOR || dev->descriptor.idProduct != PRODUCT)
+ continue;
+
+ /* Look for the interface number that interests us */
+ for (cfg = dev->config; cfg < dev->config + dev->descriptor.bNumConfigurations; ++cfg) {
+ int itfnum;
+
+ for (itfnum = 0; itfnum < cfg->bNumInterfaces; ++itfnum) {
+ struct usb_interface *itf = &cfg->interface[itfnum];
+ struct usb_interface_descriptor *alt;
+
+ for (alt = itf->altsetting; alt < itf->altsetting + itf->num_altsetting; ++alt) {
+ if (alt->bInterfaceClass == 3) {
+ handle_device (dev, cfg, itfnum, alt);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
--
1.5.5.2
[-- Attachment #3: 0002-Port-sixpair-to-libusb-1.0.patch --]
[-- Type: text/x-patch, Size: 9897 bytes --]
>From a08bf92d81cf0bd5201a5de18b313836726c2a7f Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Sat, 11 Oct 2008 23:34:34 +0100
Subject: [PATCH] Port sixpair to libusb 1.0
Port sixpair to libusb-1.0, as it allows us to re-attach
the driver to the device after we're done.
---
input/sixpair.c | 142 ++++++++++++++++++++++++++++---------------------------
1 files changed, 72 insertions(+), 70 deletions(-)
diff --git a/input/sixpair.c b/input/sixpair.c
index 818d283..07fa679 100644
--- a/input/sixpair.c
+++ b/input/sixpair.c
@@ -1,5 +1,5 @@
/* To compile
- * 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` -lbluetooth
+ * 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
*/
#include <unistd.h>
@@ -10,7 +10,7 @@
#include <bluetooth/bluetooth.h>
#include <bluetooth/hidp.h>
#include <glib.h>
-#include <usb.h>
+#include <libusb.h>
#include "storage.h"
@@ -18,9 +18,6 @@
#define VENDOR 0x054c
#define PRODUCT 0x0268
-#define USB_DIR_IN 0x80
-#define USB_DIR_OUT 0
-
gboolean option_get_master = TRUE;
char *option_master= NULL;
gboolean option_store_info = TRUE;
@@ -37,16 +34,16 @@ const GOptionEntry options[] = {
};
static gboolean
-show_master (usb_dev_handle *devh, int itfnum)
+show_master (libusb_device_handle *devh, int itfnum)
{
unsigned char msg[8];
int res;
- res = usb_control_msg (devh,
- USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- 0x01, 0x03f5, itfnum,
- (void*) msg, sizeof(msg),
- 5000);
+ res = libusb_control_transfer (devh,
+ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
+ 0x01, 0x03f5, itfnum,
+ (void*) msg, sizeof(msg),
+ 5000);
if (res < 0) {
g_warning ("Getting the master Bluetooth address failed");
@@ -59,17 +56,17 @@ show_master (usb_dev_handle *devh, int itfnum)
}
static char *
-get_bdaddr (usb_dev_handle *devh, int itfnum)
+get_bdaddr (libusb_device_handle *devh, int itfnum)
{
unsigned char msg[17];
char *address;
int res;
- res = usb_control_msg (devh,
- USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- 0x01, 0x03f2, itfnum,
- (void*) msg, sizeof(msg),
- 5000);
+ res = libusb_control_transfer (devh,
+ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
+ 0x01, 0x03f2, itfnum,
+ (void*) msg, sizeof(msg),
+ 5000);
if (res < 0) {
g_warning ("Getting the device Bluetooth address failed");
@@ -87,7 +84,7 @@ get_bdaddr (usb_dev_handle *devh, int itfnum)
}
static gboolean
-set_master_bdaddr (usb_dev_handle *devh, int itfnum, char *host)
+set_master_bdaddr (libusb_device_handle *devh, int itfnum, char *host)
{
unsigned char msg[8];
int mac[6];
@@ -107,11 +104,11 @@ set_master_bdaddr (usb_dev_handle *devh, int itfnum, char *host)
msg[6] = mac[4];
msg[7] = mac[5];
- res = usb_control_msg (devh,
- USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- 0x09, 0x03f5, itfnum,
- (void*) msg, sizeof(msg),
- 5000);
+ res = libusb_control_transfer (devh,
+ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
+ 0x09, 0x03f5, itfnum,
+ (void*) msg, sizeof(msg),
+ 5000);
if (res < 0) {
g_warning ("Setting the master Bluetooth address failed");
@@ -119,7 +116,6 @@ set_master_bdaddr (usb_dev_handle *devh, int itfnum, char *host)
}
return TRUE;
-
}
static char *
@@ -146,8 +142,9 @@ get_host_bdaddr (void)
}
static int
-get_record_info (struct usb_interface_descriptor *alt, unsigned int *_len, unsigned int *_country, uint16_t *_version)
+get_record_info (const struct libusb_interface_descriptor *alt, unsigned int *_len, unsigned int *_country, uint16_t *_version)
{
+#if 0
unsigned char *buf;
unsigned int size, len, country;
uint16_t version;
@@ -188,13 +185,14 @@ get_record_info (struct usb_interface_descriptor *alt, unsigned int *_len, unsig
*_len = len;
*_country = country;
*_version = version;
-
+#endif
return 0;
}
static void
-fill_req_from_usb (struct usb_device *dev, struct hidp_connadd_req *req, void *data, unsigned int len, unsigned int country, uint16_t version)
+fill_req_from_usb (libusb_device *dev, struct hidp_connadd_req *req, void *data, unsigned int len, unsigned int country, uint16_t version)
{
+#if 0
req->vendor = dev->descriptor.idVendor;
req->product = dev->descriptor.idProduct;
req->version = version;
@@ -207,6 +205,7 @@ fill_req_from_usb (struct usb_device *dev, struct hidp_connadd_req *req, void *d
req->rd_size = len;
req->rd_data = data;
+#endif
}
static void
@@ -230,21 +229,20 @@ store_info (const char *host, const char *device, struct hidp_connadd_req *req)
}
static int
-handle_device (struct usb_device *dev, struct usb_config_descriptor *cfg, int itfnum, struct usb_interface_descriptor *alt)
+handle_device (libusb_device *dev, struct libusb_config_descriptor *cfg, int itfnum, const struct libusb_interface_descriptor *alt)
{
- usb_dev_handle *devh;
+ libusb_device_handle *devh;
int res, retval;
retval = -1;
- devh = usb_open (dev);
- if (devh == NULL) {
+ if (libusb_open (dev, &devh) < 0) {
g_warning ("Can't open device");
goto bail;
}
- usb_detach_kernel_driver_np (devh, itfnum);
+ libusb_detach_kernel_driver (devh, itfnum);
- res = usb_claim_interface (devh, itfnum);
+ res = libusb_claim_interface (devh, itfnum);
if (res < 0) {
g_warning ("Can't claim interface %d", itfnum);
goto bail;
@@ -279,7 +277,6 @@ handle_device (struct usb_device *dev, struct usb_config_descriptor *cfg, int it
unsigned char data[8192];
struct hidp_connadd_req req;
unsigned int len, country;
- int n;
uint16_t version;
char *device;
@@ -295,11 +292,11 @@ handle_device (struct usb_device *dev, struct usb_config_descriptor *cfg, int it
goto bail;
}
- if ((n = usb_control_msg(devh,
- USB_ENDPOINT_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE,
- USB_REQ_GET_DESCRIPTOR,
- (USB_DT_REPORT << 8),
- itfnum, (void *) &data, len, 5000)) < 0) {
+ if (libusb_control_transfer(devh,
+ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
+ LIBUSB_REQUEST_GET_DESCRIPTOR,
+ (LIBUSB_DT_REPORT << 8),
+ itfnum, (void *) &data, len, 5000) < 0) {
g_warning ("Can't get report descriptor (length: %d, interface: %d)", len, itfnum);
retval = -1;
goto bail;
@@ -319,8 +316,10 @@ handle_device (struct usb_device *dev, struct usb_config_descriptor *cfg, int it
}
bail:
+ libusb_release_interface (devh, itfnum);
+ libusb_attach_kernel_driver(devh, itfnum);
if (devh != NULL)
- usb_close (devh);
+ libusb_close (devh);
return retval;
}
@@ -329,7 +328,8 @@ int main (int argc, char **argv)
{
GOptionContext *context;
GError *error = NULL;
- struct usb_bus *busses, *bus;
+ libusb_device **list;
+ ssize_t num_devices, i;
context = g_option_context_new ("- Manage Sixaxis PS3 controllers");
g_option_context_add_main_entries (context, options, NULL);
@@ -343,45 +343,47 @@ int main (int argc, char **argv)
//FIXME check bdaddr
}
+ libusb_init (NULL);
+
/* Find device(s) */
- usb_init ();
- if (usb_find_busses () < 0) {
- g_warning ("usb_find_busses failed");
- return 1;
- }
- if (usb_find_devices () < 0) {
- g_warning ("usb_find_devices failed");
+ num_devices = libusb_get_device_list (NULL, &list);
+ if (num_devices < 0) {
+ g_warning ("libusb_get_device_list failed");
return 1;
}
- busses = usb_get_busses();
- if (busses == NULL) {
- g_warning ("usb_get_busses failed");
- return 1;
- }
+ for (i = 0; i < num_devices; i++) {
+ struct libusb_config_descriptor *cfg;
+ libusb_device *dev = list[i];
+ struct libusb_device_descriptor desc;
+ guint8 j;
+
+ if (libusb_get_device_descriptor (dev, &desc) < 0) {
+ g_warning ("libusb_get_device_descriptor failed");
+ continue;
+ }
- for (bus = busses; bus; bus = bus->next) {
- struct usb_device *dev;
+ /* Here we check for the supported devices */
+ if (desc.idVendor != VENDOR || desc.idProduct != PRODUCT)
+ continue;
- for (dev = bus->devices; dev; dev = dev->next) {
- struct usb_config_descriptor *cfg;
+ /* Look for the interface number that interests us */
+ for (j = 0; j < desc.bNumConfigurations; j++) {
+ struct libusb_config_descriptor *config;
+ guint8 k;
- /* Here we check for the supported devices */
- if (dev->descriptor.idVendor != VENDOR || dev->descriptor.idProduct != PRODUCT)
- continue;
+ libusb_get_config_descriptor (dev, j, &config);
- /* Look for the interface number that interests us */
- for (cfg = dev->config; cfg < dev->config + dev->descriptor.bNumConfigurations; ++cfg) {
- int itfnum;
+ for (k = 0; k < config->bNumInterfaces; k++) {
+ const struct libusb_interface *itf = &config->interface[k];
+ int l;
- for (itfnum = 0; itfnum < cfg->bNumInterfaces; ++itfnum) {
- struct usb_interface *itf = &cfg->interface[itfnum];
- struct usb_interface_descriptor *alt;
+ for (l = 0; l < itf->num_altsetting ; l++) {
+ struct libusb_interface_descriptor alt;
- for (alt = itf->altsetting; alt < itf->altsetting + itf->num_altsetting; ++alt) {
- if (alt->bInterfaceClass == 3) {
- handle_device (dev, cfg, itfnum, alt);
- }
+ alt = itf->altsetting[l];
+ if (alt.bInterfaceClass == 3) {
+ handle_device (dev, cfg, l, &alt);
}
}
}
--
1.5.5.2
[-- Attachment #4: 0006-Fix-setting-the-master-address-on-the-sixaxis.patch --]
[-- Type: text/x-patch, Size: 2019 bytes --]
>From 4a45364efa67dc7c5546f180bc7b67d64186d24c Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Wed, 15 Oct 2008 12:50:40 +0100
Subject: [PATCH] Fix setting the master address on the sixaxis
Direction for the USB command was wrong, also disable
all the report code, so sixpair can run (minus saving device
records)
---
input/sixpair.c | 12 ++++++++----
1 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/input/sixpair.c b/input/sixpair.c
index 07fa679..92aa5f7 100644
--- a/input/sixpair.c
+++ b/input/sixpair.c
@@ -105,7 +105,7 @@ set_master_bdaddr (libusb_device_handle *devh, int itfnum, char *host)
msg[7] = mac[5];
res = libusb_control_transfer (devh,
- LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
+ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
0x09, 0x03f5, itfnum,
(void*) msg, sizeof(msg),
5000);
@@ -285,7 +285,7 @@ handle_device (libusb_device *dev, struct libusb_config_descriptor *cfg, int itf
retval = -1;
goto bail;
}
-
+#if 0
if (get_record_info (alt, &len, &country, &version) < 0) {
g_warning ("Can't get record info");
retval = -1;
@@ -306,7 +306,7 @@ handle_device (libusb_device *dev, struct libusb_config_descriptor *cfg, int itf
fill_req_from_usb (dev, &req, data, len, country, version);
store_info (option_master, device, &req);
-
+#endif
if (set_master_bdaddr (devh, itfnum, option_master) == FALSE) {
retval = -1;
goto bail;
@@ -317,7 +317,11 @@ handle_device (libusb_device *dev, struct libusb_config_descriptor *cfg, int itf
bail:
libusb_release_interface (devh, itfnum);
- libusb_attach_kernel_driver(devh, itfnum);
+ res = libusb_attach_kernel_driver(devh, itfnum);
+ if (res < 0) {
+ //FIXME sometimes the kernel tells us ENOENT, but succeeds anyway...
+ g_warning ("Reattaching the driver failed: %d", res);
+ }
if (devh != NULL)
libusb_close (devh);
--
1.5.5.2
[-- Attachment #5: 0007-Export-record_from_string-from-the-storage-functio.patch --]
[-- Type: text/x-patch, Size: 1547 bytes --]
>From 44c1f80129e2279246fff4e33fe7b2e89dc200a6 Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Wed, 15 Oct 2008 15:20:22 +0100
Subject: [PATCH] Export record_from_string() from the storage functions
Export record_from_string() from the storage functions,
so it can be used to generate an sdp_record from a
static string in sixpair.c
---
src/storage.c | 2 +-
src/storage.h | 1 +
2 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/src/storage.c b/src/storage.c
index d99fb33..ac1ec5b 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -771,7 +771,7 @@ int store_record(const gchar *src, const gchar *dst, sdp_record_t *rec)
return err;
}
-static sdp_record_t *record_from_string(const gchar *str)
+sdp_record_t *record_from_string(const gchar *str)
{
sdp_record_t *rec;
int size, i, len;
diff --git a/src/storage.h b/src/storage.h
index bff36a7..29f08d8 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -57,6 +57,7 @@ GSList *list_trusts(bdaddr_t *local, const char *service);
int write_device_profiles(bdaddr_t *src, bdaddr_t *dst, const char *profiles);
int delete_entry(bdaddr_t *src, const char *storage, const char *key);
int store_record(const gchar *src, const gchar *dst, sdp_record_t *rec);
+sdp_record_t *record_from_string(const gchar *str);
sdp_record_t *fetch_record(const gchar *src, const gchar *dst, const uint32_t handle);
int delete_record(const gchar *src, const gchar *dst, const uint32_t handle);
sdp_list_t *read_records(bdaddr_t *src, bdaddr_t *dst);
--
1.5.5.2
[-- Attachment #6: 0008-Store-every-record-information-for-the-sixaxis-contr.patch --]
[-- Type: text/x-patch, Size: 6831 bytes --]
>From c78d0dfeeda1208bad41686b51b0a815c372be95 Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Wed, 15 Oct 2008 15:25:13 +0100
Subject: [PATCH] Store every record information for the sixaxis controllers
Remove out-dated code to parse the HID input descriptor
Make sure that all the Bluetooth addresses used are upper-case
Add captured once SDP PNP record for the sixaxis controller
Store device id, profile, and trust information about the device
---
input/sixpair.c | 137 +++++++-----------------------------------------------
1 files changed, 18 insertions(+), 119 deletions(-)
diff --git a/input/sixpair.c b/input/sixpair.c
index 92aa5f7..3a2bd32 100644
--- a/input/sixpair.c
+++ b/input/sixpair.c
@@ -8,7 +8,7 @@
#include <sdp.h>
#include <bluetooth/bluetooth.h>
-#include <bluetooth/hidp.h>
+#include <bluetooth/sdp_lib.h>
#include <glib.h>
#include <libusb.h>
@@ -18,6 +18,8 @@
#define VENDOR 0x054c
#define PRODUCT 0x0268
+#define PS3_PNP_RECORD "3601920900000A000100000900013503191124090004350D35061901000900113503190011090006350909656E09006A0901000900093508350619112409010009000D350F350D350619010009001335031900110901002513576972656C65737320436F6E74726F6C6C65720901012513576972656C65737320436F6E74726F6C6C6572090102251B536F6E7920436F6D707574657220456E7465727461696E6D656E740902000901000902010901000902020800090203082109020428010902052801090206359A35980822259405010904A101A102850175089501150026FF00810375019513150025013500450105091901291381027501950D0600FF8103150026FF0005010901A10075089504350046FF0009300931093209358102C0050175089527090181027508953009019102750895300901B102C0A1028502750895300901B102C0A10285EE750895300901B102C0A10285EF750895300901B102C0C0090207350835060904090901000902082800090209280109020A280109020B09010009020C093E8009020D280009020E2800"
+
gboolean option_get_master = TRUE;
char *option_master= NULL;
gboolean option_store_info = TRUE;
@@ -49,7 +51,7 @@ show_master (libusb_device_handle *devh, int itfnum)
g_warning ("Getting the master Bluetooth address failed");
return FALSE;
}
- g_print ("Current Bluetooth master: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ g_print ("Current Bluetooth master: %02X:%02X:%02X:%02X:%02X:%02X\n",
msg[2], msg[3], msg[4], msg[5], msg[6], msg[7]);
return TRUE;
@@ -73,7 +75,7 @@ get_bdaddr (libusb_device_handle *devh, int itfnum)
return NULL;
}
- address = g_strdup_printf ("%02x:%02x:%02x:%02x:%02x:%02x",
+ address = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
msg[4], msg[5], msg[6], msg[7], msg[8], msg[9]);
if (option_quiet == FALSE) {
@@ -90,7 +92,7 @@ set_master_bdaddr (libusb_device_handle *devh, int itfnum, char *host)
int mac[6];
int res;
- if (sscanf(host, "%x:%x:%x:%x:%x:%x",
+ if (sscanf(host, "%X:%X:%X:%X:%X:%X",
&mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]) != 6) {
return FALSE;
}
@@ -132,100 +134,13 @@ get_host_bdaddr (void)
//FIXME
return NULL;
}
- if (fscanf(f, "%*s\n%*s %x:%x:%x:%x:%x:%x",
+ if (fscanf(f, "%*s\n%*s %X:%X:%X:%X:%X:%X",
&mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]) != 6) {
//FIXME
return NULL;
}
- return g_strdup_printf ("%x:%x:%x:%x:%x:%x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
-}
-
-static int
-get_record_info (const struct libusb_interface_descriptor *alt, unsigned int *_len, unsigned int *_country, uint16_t *_version)
-{
-#if 0
- unsigned char *buf;
- unsigned int size, len, country;
- uint16_t version;
- int l;
-
- len = 0;
- country = 0;
- version = 0;
-
- if (!alt->extralen)
- return 0;
-
- size = alt->extralen;
- buf = alt->extra;
- while (size >= 2 * sizeof(u_int8_t)) {
- if (buf[0] < 2 || buf[1] != USB_DT_HID)
- continue;
-
- //FIXME that should be "21"
- //g_message ("country: %u", buf[4]);
- //country = buf[4];
- //country = 0x21;
- country = 0;
- version = (buf[3] << 8) + buf[2];
-
- for (l = 0; l < buf[5]; l++) {
- /* we are just interested in report descriptors*/
- if (buf[6+3*l] != USB_DT_REPORT)
- continue;
- len = buf[7+3*l] | (buf[8+3*l] << 8);
- }
- size -= buf[0];
- buf += buf[0];
- }
-
- if (len == 0)
- return -1;
- *_len = len;
- *_country = country;
- *_version = version;
-#endif
- return 0;
-}
-
-static void
-fill_req_from_usb (libusb_device *dev, struct hidp_connadd_req *req, void *data, unsigned int len, unsigned int country, uint16_t version)
-{
-#if 0
- req->vendor = dev->descriptor.idVendor;
- req->product = dev->descriptor.idProduct;
- req->version = version;
- /* req->subclass already set */
- req->country = country;
- /* Default value */
- req->parser = 0x0100;
- /* What are we expecting here? No idea, but we don't seem to need it */
- req->flags = 0;
-
- req->rd_size = len;
- req->rd_data = data;
-#endif
-}
-
-static void
-store_info (const char *host, const char *device, struct hidp_connadd_req *req)
-{
- bdaddr_t dest, src;
-
- if (str2ba (host, &src) < 0) {
- //FIXME
- return;
- }
- if (str2ba (device, &dest) < 0) {
- //FIXME
- return;
- }
-
-#if 0
- if (store_device_info (&src, &dest, req) < 0)
-#endif
- g_message ("store_device_info failed");
+ return g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
static int
@@ -274,45 +189,29 @@ handle_device (libusb_device *dev, struct libusb_config_descriptor *cfg, int itf
}
if (option_store_info != FALSE) {
- unsigned char data[8192];
- struct hidp_connadd_req req;
- unsigned int len, country;
- uint16_t version;
+ sdp_record_t *rec;
char *device;
+ bdaddr_t dst, src;
device = get_bdaddr (devh, itfnum);
if (device == NULL) {
retval = -1;
goto bail;
}
-#if 0
- if (get_record_info (alt, &len, &country, &version) < 0) {
- g_warning ("Can't get record info");
- retval = -1;
- goto bail;
- }
- if (libusb_control_transfer(devh,
- LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
- LIBUSB_REQUEST_GET_DESCRIPTOR,
- (LIBUSB_DT_REPORT << 8),
- itfnum, (void *) &data, len, 5000) < 0) {
- g_warning ("Can't get report descriptor (length: %d, interface: %d)", len, itfnum);
- retval = -1;
- goto bail;
- }
-
- req.subclass = alt->bInterfaceSubClass;
- fill_req_from_usb (dev, &req, data, len, country, version);
+ rec = record_from_string (PS3_PNP_RECORD);
+ store_record(option_master, device, rec);
+ write_trust(option_master, device, "[all]", TRUE);
+ store_device_id(option_master, device, 0xffff, 0x054c, 0x0268, 0);
+ str2ba(option_master, &src);
+ str2ba(device, &dst);
+ write_device_profiles(&src, &dst, "");
+ sdp_record_free(rec);
- store_info (option_master, device, &req);
-#endif
if (set_master_bdaddr (devh, itfnum, option_master) == FALSE) {
retval = -1;
goto bail;
}
-
- //FIXME finally, set device as trusted
}
bail:
--
1.5.5.2
[-- Attachment #7: 0009-Save-name-for-the-sixaxis-controller.patch --]
[-- Type: text/x-patch, Size: 830 bytes --]
>From 48e9d01b184c9ff5a353dd6502847fb249d278c1 Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Wed, 15 Oct 2008 15:28:42 +0100
Subject: [PATCH] Save name for the sixaxis controller
The name won't be there until we connect otherwise
---
input/sixpair.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/input/sixpair.c b/input/sixpair.c
index 3a2bd32..5c58b9b 100644
--- a/input/sixpair.c
+++ b/input/sixpair.c
@@ -206,6 +206,7 @@ handle_device (libusb_device *dev, struct libusb_config_descriptor *cfg, int itf
str2ba(option_master, &src);
str2ba(device, &dst);
write_device_profiles(&src, &dst, "");
+ write_device_name(&src, &dst, "PLAYSTATION(R)3 Controller");
sdp_record_free(rec);
if (set_master_bdaddr (devh, itfnum, option_master) == FALSE) {
--
1.5.5.2
[-- Attachment #8: 0010-Detect-libusb-1.0-and-enable-it-by-default.patch --]
[-- Type: text/x-patch, Size: 2891 bytes --]
>From c9b2d0599a6a1d30f96a0064a524a7f904faf1a0 Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Wed, 15 Oct 2008 15:47:28 +0100
Subject: [PATCH] Detect libusb 1.0 and enable it by default
Necessary for sixpair to compile
---
acinclude.m4 | 15 +++++++++++++++
bootstrap-configure | 1 +
configure.ac | 1 +
3 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/acinclude.m4 b/acinclude.m4
index 45dd909..0a8fdbb 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -156,6 +156,12 @@ AC_DEFUN([AC_PATH_USB], [
[Define to 1 if you need the usb_interrupt_read() function.]))
])
+AC_DEFUN([AC_PATH_USB1], [
+ PKG_CHECK_MODULES(USB1, libusb-1.0, usb1_found=yes, usb1_found=no)
+ AC_SUBST(USB_CFLAGS)
+ AC_SUBST(USB_LIBS)
+])
+
AC_DEFUN([AC_PATH_NETLINK], [
PKG_CHECK_MODULES(NETLINK, libnl-1, netlink_found=yes, netlink_found=no)
AC_SUBST(NETLINK_CFLAGS)
@@ -238,6 +244,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [
usb_enable=${enableval}
])
+ AC_ARG_ENABLE(usb1, AC_HELP_STRING([--enable-usb1], [enable libusb 1.0 support]), [
+ usb1_enable=${enableval}
+ ])
+
AC_ARG_ENABLE(netlink, AC_HELP_STRING([--enable-netlink], [enable NETLINK support]), [
netlink_enable=${enableval}
])
@@ -321,6 +331,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [
AC_DEFINE(HAVE_LIBUSB, 1, [Define to 1 if you have USB library.])
fi
+ if (test "${usb1_enable}" = "yes" && test "${usb1_found}" = "yes"); then
+ AC_DEFINE(HAVE_LIBUSB1, 1, [Define to 1 if you have libusb-1.0.])
+ fi
+
AC_SUBST([BLUEZ_CFLAGS], ['-I$(top_builddir)/include'])
AC_SUBST([BLUEZ_LIBS], ['$(top_builddir)/lib/libbluetooth.la'])
@@ -333,6 +347,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
AM_CONDITIONAL(SNDFILE, test "${sndfile_enable}" = "yes" && test "${sndfile_found}" = "yes")
AM_CONDITIONAL(NETLINK, test "${netlink_enable}" = "yes" && test "${netlink_found}" = "yes")
AM_CONDITIONAL(USB, test "${usb_enable}" = "yes" && test "${usb_found}" = "yes")
+ AM_CONDITIONAL(USB1, test "${usb1_enable}" = "yes" && test "${usb1_found}" = "yes")
AM_CONDITIONAL(SBC, test "${alsa_enable}" = "yes" || test "${gstreamer_enable}" = "yes")
AM_CONDITIONAL(ALSA, test "${alsa_enable}" = "yes" && test "${alsa_found}" = "yes")
AM_CONDITIONAL(GSTREAMER, test "${gstreamer_enable}" = "yes" && test "${gstreamer_found}" = "yes")
diff --git a/bootstrap-configure b/bootstrap-configure
index 7b07fe1..3b22dd5 100755
--- a/bootstrap-configure
+++ b/bootstrap-configure
@@ -27,6 +27,7 @@ fi
--enable-dund \
--enable-test \
--enable-cups \
+ --enable-usb1 \
--disable-manpages \
--disable-configfiles \
--disable-initscripts \
diff --git a/configure.ac b/configure.ac
index 33b4583..f603223 100644
--- a/configure.ac
+++ b/configure.ac
@@ -32,6 +32,7 @@ AC_PATH_GMODULE
AC_PATH_ALSA
AC_PATH_GSTREAMER
AC_PATH_USB
+AC_PATH_USB1
AC_PATH_NETLINK
AC_PATH_SNDFILE
--
1.5.5.2
[-- Attachment #9: 0011-Separate-storage-functions-into-a-library.patch --]
[-- Type: text/x-patch, Size: 1215 bytes --]
>From 8c2c57718e32d4da5c49c8df38f5a48a1c105375 Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Wed, 15 Oct 2008 15:48:51 +0100
Subject: [PATCH] Separate storage functions into a library
The separate storage functions will be used by sixpair
---
src/Makefile.am | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am
index 2a353a4..d39d73d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,15 +13,19 @@ statedir = $(localstatedir)/lib/bluetooth
state_DATA =
endif
+noinst_LIBRARIES = libbtd-storage.a
+libbtd_storage_a_SOURCES = storage.h storage.c
+
sbin_PROGRAMS = bluetoothd
bluetoothd_SOURCES = main.c security.c hcid.h sdpd.h \
sdpd-server.c sdpd-request.c sdpd-service.c sdpd-database.c \
- plugin.h plugin.c storage.h storage.c agent.h agent.c \
+ plugin.h plugin.c agent.h agent.c \
error.h error.c manager.h manager.c adapter.h adapter.c \
device.h device.c dbus-common.c dbus-common.h dbus-hci.h dbus-hci.c
bluetoothd_LDADD = $(top_builddir)/common/libhelper.a \
+ $(builddir)/libbtd-storage.a \
@GDBUS_LIBS@ @GMODULE_LIBS@ @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@
if MAINTAINER_MODE
--
1.5.5.2
[-- Attachment #10: 0012-Build-sixpair-through-the-build-system.patch --]
[-- Type: text/x-patch, Size: 1366 bytes --]
>From 444bfee09d378ac4e5fdd8c05b8bb01b8b57f418 Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Wed, 15 Oct 2008 15:49:58 +0100
Subject: [PATCH] Build sixpair through the build system
Using the libusb 1.0 libs as well as the separate storage
library, compile sixpair without hacks
---
input/Makefile.am | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/input/Makefile.am b/input/Makefile.am
index 1b3ab5d..59cf481 100644
--- a/input/Makefile.am
+++ b/input/Makefile.am
@@ -8,14 +8,23 @@ input_la_SOURCES = main.c manager.h manager.c \
server.h server.c device.h device.c \
fakehid.c fakehid.h
-LDADD = $(top_builddir)/common/libhelper.a \
+input_la_LIBADD = $(top_builddir)/common/libhelper.a \
@GDBUS_LIBS@ @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@
+
+if USB1
+bin_PROGRAMS = sixpair
+sixpair_SOURCES = sixpair.c
+sixpair_LDADD = $(top_builddir)/src/libbtd-storage.a \
+ $(top_builddir)/common/libhelper.a \
+ @USB1_LIBS@ @GLIB_LIBS@ @BLUEZ_LIBS@
+endif
+
endif
AM_LDFLAGS = -module -avoid-version -no-undefined \
-export-symbols-regex bluetooth_plugin_desc
-AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ @GDBUS_CFLAGS@
+AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ @GDBUS_CFLAGS@ @USB1_CFLAGS@
INCLUDES = -I$(top_srcdir)/common -I$(top_srcdir)/src
--
1.5.5.2
[-- Attachment #11: 0013-Remove-compilation-instructions-from-sixpair.patch --]
[-- Type: text/x-patch, Size: 771 bytes --]
>From b2c8fe5f5b1141284dce71a0345712cf16c1f665 Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Wed, 15 Oct 2008 15:50:29 +0100
Subject: [PATCH] Remove compilation instructions from sixpair
Not needed anymore
---
input/sixpair.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)
diff --git a/input/sixpair.c b/input/sixpair.c
index 5c58b9b..41d7791 100644
--- a/input/sixpair.c
+++ b/input/sixpair.c
@@ -1,7 +1,3 @@
-/* To compile
- * 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
- */
-
#include <unistd.h>
#include <stdio.h>
#include <inttypes.h>
--
1.5.5.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCHes] Add sixpair
2008-10-15 15:15 [PATCHes] Add sixpair Bastien Nocera
@ 2008-10-15 15:22 ` Marcel Holtmann
2008-10-15 23:52 ` Marcel Holtmann
1 sibling, 0 replies; 8+ messages in thread
From: Marcel Holtmann @ 2008-10-15 15:22 UTC (permalink / raw)
To: Bastien Nocera; +Cc: BlueZ development
Hi Bastien,
> Here are the patches to get sixpair support built into BlueZ. It uses
> libusb-1.0 as well as a yet to be merged libusb-1.0 patch to allow
> re-attaching a driver to a device.
with the 2.6.28 kernel we should get a better HID driver model (aka HID
bus) and then we might not need to libusb stuff anymore. We can go
directly to HID and read the descriptors and send vendor HID reports.
Regards
Marcel
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCHes] Add sixpair
2008-10-15 15:15 [PATCHes] Add sixpair Bastien Nocera
2008-10-15 15:22 ` Marcel Holtmann
@ 2008-10-15 23:52 ` Marcel Holtmann
2008-10-16 0:28 ` Bastien Nocera
1 sibling, 1 reply; 8+ messages in thread
From: Marcel Holtmann @ 2008-10-15 23:52 UTC (permalink / raw)
To: Bastien Nocera; +Cc: BlueZ development
Hi Bastien,
> Here are the patches to get sixpair support built into BlueZ. It uses
> libusb-1.0 as well as a yet to be merged libusb-1.0 patch to allow
> re-attaching a driver to a device.
so I applied all patches except the changes for the build system. I am
not sure that this is the right way to go.
If we require libusb-1.0, then we should just change our current code
that depends on libusb-0.1 and require libusb-1.0 for all of it.
> Problems left to solve:
> - sixaxis enabler code (as seen in enable_sixaxis() in compat/hidd.c)
> seems to have disappeared from the input plugin. Is that done in the
> kernel now, or was it just removed?
The kernel is not doing it. Seems to be an oversight.
> - After "cable pairing" the device, I need to unplug/replug the adapter,
> or restart bluetoothd. Can anyone think of a better way of getting the
> list of devices updated?
We could use inotify or SIGUSR2 or something to re-read the database.
> - Some minor niggles in the code itself (use D-Bus instead of parsing
> command-line tools)
Of course.
> - udev rule(s) and parsing only the selected device would be necessary
> if not required
If we can do this via the HID bus, then we can do it every time and it
would not affect the controller itself.
Regards
Marcel
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCHes] Add sixpair
2008-10-15 23:52 ` Marcel Holtmann
@ 2008-10-16 0:28 ` Bastien Nocera
2008-10-23 4:52 ` Marcel Holtmann
2009-02-28 21:48 ` AddCablePairedDevice (was Re: [PATCHes] Add sixpair) Bastien Nocera
0 siblings, 2 replies; 8+ messages in thread
From: Bastien Nocera @ 2008-10-16 0:28 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: BlueZ development
On Thu, 2008-10-16 at 01:52 +0200, Marcel Holtmann wrote:
> Hi Bastien,
>
> > Here are the patches to get sixpair support built into BlueZ. It uses
> > libusb-1.0 as well as a yet to be merged libusb-1.0 patch to allow
> > re-attaching a driver to a device.
>
> so I applied all patches except the changes for the build system. I am
> not sure that this is the right way to go.
>
> If we require libusb-1.0, then we should just change our current code
> that depends on libusb-0.1 and require libusb-1.0 for all of it.
That'd mean porting:
- dfutool
- avctrl
- bccmd's csr_usb code
- hid2hci
The code isn't too complicated, but I wouldn't be able to test any of
the code (apart from maybe hid2hci). Is this something I can promise to
do in the future? It's not very complicated, just time consuming.
> > Problems left to solve:
> > - sixaxis enabler code (as seen in enable_sixaxis() in compat/hidd.c)
> > seems to have disappeared from the input plugin. Is that done in the
> > kernel now, or was it just removed?
>
> The kernel is not doing it. Seems to be an oversight.
OK. I'll re-add the code to the input plugin.
> > - After "cable pairing" the device, I need to unplug/replug the adapter,
> > or restart bluetoothd. Can anyone think of a better way of getting the
> > list of devices updated?
>
> We could use inotify or SIGUSR2 or something to re-read the database.
There's a problem with the current method in that there might be data
loss if we're adding data from both bluetoothd, and an external program
(both processes writing the same file at the same time).
We could solve the data loss, and update problem by having an internal,
root only, dbus method available for cable pairing of that sort. For
example, on org.bluez.Adapter:
void AddCablePairedDevice (string name,
string address,
unsigned int vendor_id,
unsigned int product_id,
string pnp_record);
The function would just need to do all the storage work sixpair
currently does, and create the device internally similarly to
create_stored_device_from_profiles().
It might also be useful to have an internal (non-dbus) API at the
manager level for hid proxy dongles (where the adapter wouldn't yet
exist when we store the to-be-created devices, not sure how to be
certain those devices will be temporary though).
> > - Some minor niggles in the code itself (use D-Bus instead of parsing
> > command-line tools)
>
> Of course.
>
> > - udev rule(s) and parsing only the selected device would be necessary
> > if not required
>
> If we can do this via the HID bus, then we can do it every time and it
> would not affect the controller itself.
Unless I misunderstood the feature, when claiming the interface, that
would actually remove the pad as an input device.
Cheers
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCHes] Add sixpair
2008-10-16 0:28 ` Bastien Nocera
@ 2008-10-23 4:52 ` Marcel Holtmann
2009-02-28 21:48 ` AddCablePairedDevice (was Re: [PATCHes] Add sixpair) Bastien Nocera
1 sibling, 0 replies; 8+ messages in thread
From: Marcel Holtmann @ 2008-10-23 4:52 UTC (permalink / raw)
To: Bastien Nocera; +Cc: BlueZ development
Hi Bastien,
> > > Here are the patches to get sixpair support built into BlueZ. It uses
> > > libusb-1.0 as well as a yet to be merged libusb-1.0 patch to allow
> > > re-attaching a driver to a device.
> >
> > so I applied all patches except the changes for the build system. I am
> > not sure that this is the right way to go.
> >
> > If we require libusb-1.0, then we should just change our current code
> > that depends on libusb-0.1 and require libusb-1.0 for all of it.
>
> That'd mean porting:
> - dfutool
> - avctrl
> - bccmd's csr_usb code
> - hid2hci
>
> The code isn't too complicated, but I wouldn't be able to test any of
> the code (apart from maybe hid2hci). Is this something I can promise to
> do in the future? It's not very complicated, just time consuming.
once I upgraded my laptop with the next generation distros, I will start
porting dfutool, avctrl and bccmd over. Would be nice if you look at the
hid2hci.
> > > Problems left to solve:
> > > - sixaxis enabler code (as seen in enable_sixaxis() in compat/hidd.c)
> > > seems to have disappeared from the input plugin. Is that done in the
> > > kernel now, or was it just removed?
> >
> > The kernel is not doing it. Seems to be an oversight.
>
> OK. I'll re-add the code to the input plugin.
Any updates here?
> > > - After "cable pairing" the device, I need to unplug/replug the adapter,
> > > or restart bluetoothd. Can anyone think of a better way of getting the
> > > list of devices updated?
> >
> > We could use inotify or SIGUSR2 or something to re-read the database.
>
> There's a problem with the current method in that there might be data
> loss if we're adding data from both bluetoothd, and an external program
> (both processes writing the same file at the same time).
>
> We could solve the data loss, and update problem by having an internal,
> root only, dbus method available for cable pairing of that sort. For
> example, on org.bluez.Adapter:
> void AddCablePairedDevice (string name,
> string address,
> unsigned int vendor_id,
> unsigned int product_id,
> string pnp_record);
>
> The function would just need to do all the storage work sixpair
> currently does, and create the device internally similarly to
> create_stored_device_from_profiles().
>
> It might also be useful to have an internal (non-dbus) API at the
> manager level for hid proxy dongles (where the adapter wouldn't yet
> exist when we store the to-be-created devices, not sure how to be
> certain those devices will be temporary though).
I think the D-Bus one would be good enough. Check with Claudio and lets
come up with a patch proposal.
> > > - Some minor niggles in the code itself (use D-Bus instead of parsing
> > > command-line tools)
> >
> > Of course.
> >
> > > - udev rule(s) and parsing only the selected device would be necessary
> > > if not required
> >
> > If we can do this via the HID bus, then we can do it every time and it
> > would not affect the controller itself.
>
> Unless I misunderstood the feature, when claiming the interface, that
> would actually remove the pad as an input device.
Not with the HID bus and the HID raw support. In that case it should be
possible.
Regards
Marcel
^ permalink raw reply [flat|nested] 8+ messages in thread
* AddCablePairedDevice (was Re: [PATCHes] Add sixpair)
2008-10-16 0:28 ` Bastien Nocera
2008-10-23 4:52 ` Marcel Holtmann
@ 2009-02-28 21:48 ` Bastien Nocera
2009-02-28 22:44 ` Marcel Holtmann
1 sibling, 1 reply; 8+ messages in thread
From: Bastien Nocera @ 2009-02-28 21:48 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: BlueZ development
[-- Attachment #1: Type: text/plain, Size: 2002 bytes --]
On Thu, 2008-10-16 at 01:28 +0100, Bastien Nocera wrote:
<snip>
> We could solve the data loss, and update problem by having an internal,
> root only, dbus method available for cable pairing of that sort. For
> example, on org.bluez.Adapter:
> void AddCablePairedDevice (string name,
> string address,
> unsigned int vendor_id,
> unsigned int product_id,
> string pnp_record);
>
> The function would just need to do all the storage work sixpair
> currently does, and create the device internally similarly to
> create_stored_device_from_profiles().
Patch to do that attached.
After setting the master bdaddr on the sixaxis using sixpair, I ran:
dbus-send --system --type=method_call --print-reply --dest="org.bluez" /org/bluez/11043/hci0 org.bluez.Adapter.AddCablePairedDevice string:Foobar string:00:19:C1:61:D6:62 uint32:0x054c uint32:0x0268 string:3601920900000A000100000900013503191124090004350D35061901000900113503190011090006350909656E09006A0901000900093508350619112409010009000D350F350D350619010009001335031900110901002513576972656C65737320436F6E74726F6C6C65720901012513576972656C65737320436F6E74726F6C6C6572090102251B536F6E7920436F6D707574657220456E7465727461696E6D656E740902000901000902010901000902020800090203082109020428010902052801090206359A35980822259405010904A101A102850175089501150026FF00810375019513150025013500450105091901291381027501950D0600FF8103150026FF0005010901A10075089504350046FF0009300931093209358102C0050175089527090181027508953009019102750895300901B102C0A1028502750895300901B102C0A10285EE750895300901B102C0A10285EF750895300901B102C0C0090207350835060904090901000902082800090209280109020A280109020B09010009020C093E8009020D280009020E2800
Which created the device in bluez. I'd leave it up to sixpair to remove
the device from other adapters, and setting the device as trusted
(though this didn't seem necessary for the pad to work).
Cheers
[-- Attachment #2: bluez-create-paired-device-api.patch --]
[-- Type: text/x-patch, Size: 6015 bytes --]
diff --git a/src/adapter.c b/src/adapter.c
index c1995a3..ba2c5fb 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -977,6 +977,36 @@ struct btd_device *adapter_create_device(DBusConnection *conn,
return device;
}
+struct btd_device *adapter_add_cable_paired_device(DBusConnection *conn,
+ struct btd_adapter *adapter,
+ const char *name,
+ const char *address,
+ guint32 vendor_id,
+ guint32 product_id,
+ const char *pnp_record)
+{
+ struct btd_device *device;
+ const char *path;
+
+ debug("adapter_add_cable_paired_device(%s)", address);
+
+ device = device_create_cable_paired_device(conn, adapter, name, address, vendor_id, product_id, pnp_record);
+ if (!device)
+ return NULL;
+
+ adapter->devices = g_slist_append(adapter->devices, device);
+
+ path = device_get_path(device);
+ g_dbus_emit_signal(conn, adapter->path,
+ ADAPTER_INTERFACE, "DeviceCreated",
+ DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID);
+
+ adapter_update_devices(adapter);
+
+ return device;
+}
+
void adapter_remove_device(DBusConnection *conn, struct btd_adapter *adapter,
struct btd_device *device)
{
@@ -1508,6 +1538,41 @@ static DBusMessage *create_device(DBusConnection *conn,
return NULL;
}
+static DBusMessage *add_cable_paired_device(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ struct btd_adapter *adapter = data;
+ struct btd_device *device;
+ guint vendor_id, product_id;
+ const gchar *address, *pnp_record, *name;
+
+ if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_STRING, &address,
+ DBUS_TYPE_UINT32, &vendor_id,
+ DBUS_TYPE_UINT32, &product_id,
+ DBUS_TYPE_STRING, &pnp_record,
+ DBUS_TYPE_INVALID) == FALSE)
+ return invalid_args(msg);
+
+ if (check_address(address) < 0)
+ return invalid_args(msg);
+
+ if (adapter_find_device(adapter, address))
+ return g_dbus_create_error(msg,
+ ERROR_INTERFACE ".AlreadyExists",
+ "Device already exists");
+
+ debug("create_device(%s)", address);
+
+ device = adapter_add_cable_paired_device(conn, adapter, name, address, vendor_id, product_id, pnp_record);
+ if (!device)
+ return NULL;
+
+ device_set_temporary(device, FALSE);
+
+ return dbus_message_new_method_return(msg);
+}
+
static uint8_t parse_io_capability(const char *capability)
{
if (g_str_equal(capability, ""))
@@ -1707,6 +1772,7 @@ static GDBusMethodTable adapter_methods[] = {
G_DBUS_METHOD_FLAG_ASYNC},
{ "ListDevices", "", "ao", list_devices,
G_DBUS_METHOD_FLAG_DEPRECATED},
+ { "AddCablePairedDevice", "ssuus", "o", add_cable_paired_device },
{ "CreateDevice", "s", "o", create_device,
G_DBUS_METHOD_FLAG_ASYNC},
{ "CreatePairedDevice", "sos", "o", create_paired_device,
diff --git a/src/adapter.h b/src/adapter.h
index 06f558a..1a24a1a 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -91,6 +91,14 @@ void adapter_remove_device(DBusConnection *conn, struct btd_adapter *adapter,
struct btd_device *adapter_create_device(DBusConnection *conn,
struct btd_adapter *adapter, const char *address);
+struct btd_device *adapter_add_cable_paired_device(DBusConnection *conn,
+ struct btd_adapter *adapter,
+ const char *name,
+ const char *address,
+ guint vendor_id,
+ guint product_id,
+ const char *pnp_record);
+
int pending_remote_name_cancel(struct btd_adapter *adapter);
void remove_pending_device(struct btd_adapter *adapter);
diff --git a/src/device.c b/src/device.c
index 9b32379..6a153dc 100644
--- a/src/device.c
+++ b/src/device.c
@@ -654,6 +654,57 @@ struct btd_device *device_create(DBusConnection *conn,
return device;
}
+struct btd_device *device_create_cable_paired_device(DBusConnection *conn,
+ struct btd_adapter *adapter,
+ const char *name,
+ const char *address,
+ guint32 vendor_id,
+ guint32 product_id,
+ const char *pnp_record)
+{
+ gchar *address_up;
+ sdp_record_t *rec;
+ struct btd_device *device;
+ const gchar *adapter_path = adapter_get_path(adapter);
+ bdaddr_t src;
+ char srcaddr[18];
+
+ device = g_try_malloc0(sizeof(struct btd_device));
+ if (device == NULL)
+ return NULL;
+
+ address_up = g_ascii_strup(address, -1);
+ device->path = g_strdup_printf("%s/dev_%s", adapter_path, address_up);
+ g_strdelimit(device->path, ":", '_');
+ g_free(address_up);
+
+ debug("Creating cable paired device %s", device->path);
+
+ if (g_dbus_register_interface(conn, device->path, DEVICE_INTERFACE,
+ device_methods, device_signals, NULL,
+ device, device_free) == FALSE) {
+ device_free(device);
+ return NULL;
+ }
+
+ str2ba(address, &device->bdaddr);
+ device->adapter = adapter;
+ adapter_get_address(adapter, &src);
+ ba2str(&src, srcaddr);
+ write_device_name(&device->bdaddr, &src, name);
+ device_set_name (device, name);
+
+ /* Store the device's SDP record */
+ rec = record_from_string (pnp_record);
+ store_record(srcaddr, address, rec);
+ sdp_record_free(rec);
+ /* Set the device id */
+ store_device_id(srcaddr, address, 0xffff, vendor_id, product_id, 0);
+ /* Don't write a profile, it will be updated when the device connects */
+
+ return device;
+}
+
void device_set_name(struct btd_device *device, const char *name)
{
DBusConnection *conn = get_dbus_connection();
diff --git a/src/device.h b/src/device.h
index 5c230b8..a3e5447 100644
--- a/src/device.h
+++ b/src/device.h
@@ -36,6 +36,13 @@ typedef enum {
struct btd_device *device_create(DBusConnection *conn, struct btd_adapter *adapter,
const gchar *address);
+struct btd_device *device_create_cable_paired_device(DBusConnection *conn,
+ struct btd_adapter *adapter,
+ const char *name,
+ const char *address,
+ guint32 vendor_id,
+ guint32 product_id,
+ const char *pnp_record);
void device_set_name(struct btd_device *device, const char *name);
void device_remove(struct btd_device *device, DBusConnection *conn,
gboolean remove_stored);
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: AddCablePairedDevice (was Re: [PATCHes] Add sixpair)
2009-02-28 21:48 ` AddCablePairedDevice (was Re: [PATCHes] Add sixpair) Bastien Nocera
@ 2009-02-28 22:44 ` Marcel Holtmann
2009-02-28 23:47 ` Bastien Nocera
0 siblings, 1 reply; 8+ messages in thread
From: Marcel Holtmann @ 2009-02-28 22:44 UTC (permalink / raw)
To: Bastien Nocera; +Cc: BlueZ development
Hi Bastien,
> > We could solve the data loss, and update problem by having an internal,
> > root only, dbus method available for cable pairing of that sort. For
> > example, on org.bluez.Adapter:
> > void AddCablePairedDevice (string name,
> > string address,
> > unsigned int vendor_id,
> > unsigned int product_id,
> > string pnp_record);
> >
> > The function would just need to do all the storage work sixpair
> > currently does, and create the device internally similarly to
> > create_stored_device_from_profiles().
>
> Patch to do that attached.
>
> After setting the master bdaddr on the sixaxis using sixpair, I ran:
> dbus-send --system --type=method_call --print-reply --dest="org.bluez" /org/bluez/11043/hci0 org.bluez.Adapter.AddCablePairedDevice string:Foobar string:00:19:C1:61:D6:62 uint32:0x054c uint32:0x0268 string:3601920900000A000100000900013503191124090004350D35061901000900113503190011090006350909656E09006A0901000900093508350619112409010009000D350F350D350619010009001335031900110901002513576972656C65737320436F6E74726F6C6C65720901012513576972656C65737320436F6E74726F6C6C6572090102251B536F6E7920436F6D707574657220456E7465727461696E6D656E740902000901000902010901000902020800090203082109020428010902052801090206359A35980822259405010904A101A102850175089501150026FF00810375019513150025013500450105091901291381027501950D0600FF8103150026FF0005010901A10075089504350046FF0009300931093209358102C0050175089527090181027508953009019102750895300901B102C0A1028502750895300901B102C0A10285EE750895300901B102C0A10285EF750895300901B102C0C0090207350835060904090901000902082800090209280109020A280109020B09010009020C093E8009020D280009020E2800
>
> Which created the device in bluez. I'd leave it up to sixpair to remove
> the device from other adapters, and setting the device as trusted
> (though this didn't seem necessary for the pad to work).
can this be made a little bit more generic. For example Bluetooth 2.1
has the out-of-band (OOB) ways for Simple Pairing and if we can design
something generic here that would help a lot.
Regards
Marcel
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: AddCablePairedDevice (was Re: [PATCHes] Add sixpair)
2009-02-28 22:44 ` Marcel Holtmann
@ 2009-02-28 23:47 ` Bastien Nocera
0 siblings, 0 replies; 8+ messages in thread
From: Bastien Nocera @ 2009-02-28 23:47 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: BlueZ development
On Sat, 2009-02-28 at 23:44 +0100, Marcel Holtmann wrote:
> Hi Bastien,
>=20
> > > We could solve the data loss, and update problem by having an interna=
l,
> > > root only, dbus method available for cable pairing of that sort. For
> > > example, on org.bluez.Adapter:
> > > void AddCablePairedDevice (string name,
> > > string address,
> > > unsigned int vendor_id,
> > > unsigned int product_id,
> > > string pnp_record);
> > >=20
> > > The function would just need to do all the storage work sixpair
> > > currently does, and create the device internally similarly to
> > > create_stored_device_from_profiles().
> >=20
> > Patch to do that attached.
> >=20
> > After setting the master bdaddr on the sixaxis using sixpair, I ran:
> > dbus-send --system --type=3Dmethod_call --print-reply --dest=3D"org.blu=
ez" /org/bluez/11043/hci0 org.bluez.Adapter.AddCablePairedDevice string:Foo=
bar string:00:19:C1:61:D6:62 uint32:0x054c uint32:0x0268 string:36019209000=
00A000100000900013503191124090004350D35061901000900113503190011090006350909=
656E09006A0901000900093508350619112409010009000D350F350D3506190100090013350=
31900110901002513576972656C65737320436F6E74726F6C6C65720901012513576972656C=
65737320436F6E74726F6C6C6572090102251B536F6E7920436F6D707574657220456E74657=
27461696E6D656E740902000901000902010901000902020800090203082109020428010902=
052801090206359A35980822259405010904A101A102850175089501150026FF00810375019=
513150025013500450105091901291381027501950D0600FF8103150026FF0005010901A100=
75089504350046FF0009300931093209358102C005017508952709018102750895300901910=
2750895300901B102C0A1028502750895300901B102C0A10285EE750895300901B102C0A102=
85EF750895300901B102C0C0090207350835060904090901000902082800090209280109020=
A280109020B09010009020C093E8009020D280009020E2800
> >=20
> > Which created the device in bluez. I'd leave it up to sixpair to remove
> > the device from other adapters, and setting the device as trusted
> > (though this didn't seem necessary for the pad to work).
>=20
> can this be made a little bit more generic. For example Bluetooth 2.1
> has the out-of-band (OOB) ways for Simple Pairing and if we can design
> something generic here that would help a lot.
What does it need for SP to work?
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2009-02-28 23:47 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-10-15 15:15 [PATCHes] Add sixpair Bastien Nocera
2008-10-15 15:22 ` Marcel Holtmann
2008-10-15 23:52 ` Marcel Holtmann
2008-10-16 0:28 ` Bastien Nocera
2008-10-23 4:52 ` Marcel Holtmann
2009-02-28 21:48 ` AddCablePairedDevice (was Re: [PATCHes] Add sixpair) Bastien Nocera
2009-02-28 22:44 ` Marcel Holtmann
2009-02-28 23:47 ` Bastien Nocera
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox