Remember fake devices for the daemon's lifetime

This would allow faster reconnection of already known devices,
so that no keypresses would be lost when reconnecting.

We only setup uinput the first time around, which will avoid
problems with devices not disappearing when disconnected.

Based on patch by Ruslan N. Marchenko <rufferson@gmail.com>
This commit is contained in:
Bastien Nocera 2010-09-02 17:09:37 +01:00 committed by Johan Hedberg
parent 5774e8c883
commit 6f605b8435
4 changed files with 36 additions and 8 deletions

View File

@ -635,12 +635,16 @@ static int hidp_add_connection(const struct input_device *idev,
fake_hid = get_fake_hid(req->vendor, req->product);
if (fake_hid) {
err = 0;
fake = g_new0(struct fake_input, 1);
fake->connect = fake_hid_connect;
fake->disconnect = fake_hid_disconnect;
fake->priv = fake_hid;
err = fake_hid_connadd(fake, iconn->intr_io, fake_hid);
if (err == 0)
fake->idev = idev;
fake = fake_hid_connadd(fake, iconn->intr_io, fake_hid);
if (fake == NULL)
err = -ENOMEM;
else
fake->flags |= FI_FLAG_CONNECTED;
goto cleanup;
}

View File

@ -39,6 +39,7 @@ struct fake_input {
gboolean (*connect) (struct input_conn *iconn, GError **err);
int (*disconnect) (struct input_conn *iconn);
void *priv;
const struct input_device *idev;
};
int fake_input_register(DBusConnection *conn, struct btd_device *device,

View File

@ -348,6 +348,7 @@ static struct fake_hid fake_hid_table[] = {
.disconnect = fake_hid_common_disconnect,
.event = ps3remote_event,
.setup_uinput = ps3remote_setup_uinput,
.devices = NULL,
},
{ },
@ -370,12 +371,33 @@ struct fake_hid *get_fake_hid(uint16_t vendor, uint16_t product)
return NULL;
}
int fake_hid_connadd(struct fake_input *fake, GIOChannel *intr_io,
struct fake_input *fake_hid_connadd(struct fake_input *fake, GIOChannel *intr_io,
struct fake_hid *fake_hid)
{
if (fake_hid->setup_uinput(fake, fake_hid)) {
error("Error setting up uinput");
return ENOMEM;
GList *l;
struct fake_input *old = NULL;
/* Look for an already setup device */
for (l = fake_hid->devices; l != NULL; l = l->next) {
old = l->data;
if (old->idev == fake->idev) {
g_free (fake);
fake = old;
fake_hid->connect(fake, NULL);
break;
}
old = NULL;
}
/* New device? Add it to the list of known devices,
* and create the uinput necessary */
if (old == NULL) {
if (fake_hid->setup_uinput(fake, fake_hid)) {
error("Error setting up uinput");
g_free(fake);
return NULL;
}
fake_hid->devices = g_list_append(fake_hid->devices, fake);
}
fake->io = g_io_channel_ref(intr_io);
@ -383,5 +405,5 @@ int fake_hid_connadd(struct fake_input *fake, GIOChannel *intr_io,
g_io_add_watch(fake->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
(GIOFunc) fake_hid->event, fake);
return 0;
return fake;
}

View File

@ -31,9 +31,10 @@ struct fake_hid {
int (*disconnect) (struct fake_input *fake_input);
gboolean (*event) (GIOChannel *chan, GIOCondition cond, gpointer data);
int (*setup_uinput) (struct fake_input *fake, struct fake_hid *fake_hid);
GList *devices;
};
struct fake_hid *get_fake_hid(uint16_t vendor, uint16_t product);
int fake_hid_connadd(struct fake_input *fake, GIOChannel *intr_io,
struct fake_input *fake_hid_connadd(struct fake_input *fake, GIOChannel *intr_io,
struct fake_hid *fake_hid);