struct jabra_headset {
GIOChannel *ch;
+ guint watch_src;
int fd;
gboolean muted;
gboolean connected;
if ((fd = open(path, O_RDONLY)) != -1) {
if (ioctl(fd, HIDIOCGDEVINFO, &devinfo) == -1) {
perror("ioctl HIDIOCGDEVINFO");
+ close(fd);
return -1;
}
if (ioctl(fd, HIDIOCGNAME(sizeof(name)), name) == -1) {
perror("ioctl HIDIOCGNAME");
+ close(fd);
return -1;
}
if (ioctl(fd, HIDIOCGVERSION, &version) == -1) {
perror("ioctl HIDIOCGVERSION");
+ close(fd);
return -1;
}
- return (devinfo.vendor == JABRA_VID ||
- devinfo.vendor == PLANTRONICS_VID);
+ if (devinfo.vendor != JABRA_VID &&
+ devinfo.vendor != PLANTRONICS_VID) {
+ close(fd);
+ return -1;
+ }
+ return fd;
}
if (errno == ENOENT) {
gsize rd;
GIOStatus ret = g_io_channel_read_chars(gio, (void *)&ev, sizeof(ev), &rd, NULL);
- if (ret != G_IO_STATUS_NORMAL)
+ if (ret != G_IO_STATUS_NORMAL) {
+ purple_debug(PURPLE_DEBUG_INFO, "headset", "Unplugged\n");
+ shutdown_headset();
return FALSE;
+ }
for (i = 0; i < rd / sizeof(ev[0]); i++) {
fprintf(stdout, "Event: %x = %d\n", ev[i].hid, ev[i].value);
pthread_t event_thread;
__s32 val;
+ fd = -1;
for (i = 0; i < 19; i++) {
sprintf(name, "/dev/usb/hiddev%d", i);
- if (doListDev(name) == 1) {
+ fd = doListDev(name);
+ if (fd != -1)
break;
- }
}
- if (i == 19) {
+ if (fd == -1) {
purple_debug(PURPLE_DEBUG_INFO, "headset", "No Jabra device found\n");
return FALSE;
}
- sprintf(name, "/dev/usb/hiddev%d", i);
purple_debug(PURPLE_DEBUG_INFO, "headset", "Using device %s\n", name);
- if ((fd = open(name, O_RDONLY)) < 0) {
- purple_debug(PURPLE_DEBUG_INFO, "headset", "Failed to open %s\n", name);
- return FALSE;
- }
-
ioctl(fd, HIDIOCINITREPORT, 0);
ioctl(fd, HIDIOCGNAME(sizeof(name)), name);
purple_debug(PURPLE_DEBUG_INFO, "headset", "HID device name: \"%s\"\n", name);
fcntl(fd, F_SETFL, O_NONBLOCK);
- GIOChannel *ch = g_io_channel_unix_new(fd);
- g_io_channel_set_encoding(ch, NULL, NULL);
- g_io_channel_set_close_on_unref(ch, TRUE);
- g_io_channel_set_buffered (ch, FALSE);
- g_io_add_watch(ch, G_IO_IN | G_IO_HUP, jabra_in, NULL);
+ jabra.ch = g_io_channel_unix_new(fd);
+ g_io_channel_set_encoding(jabra.ch, NULL, NULL);
+ g_io_channel_set_close_on_unref(jabra.ch, TRUE);
+ g_io_channel_set_buffered (jabra.ch, FALSE);
+ jabra.watch_src = g_io_add_watch(jabra.ch, G_IO_IN | G_IO_HUP | G_IO_ERR, jabra_in, NULL);
+
return TRUE;
}
void shutdown_headset(void)
{
- g_object_unref(jabra.ch);
- jabra.ch = NULL;
+ if (jabra.watch_src) {
+ g_source_remove(jabra.watch_src);
+ jabra.watch_src = 0;
+ }
+ if (jabra.ch) {
+ g_io_channel_shutdown(jabra.ch, FALSE, NULL);
+ g_io_channel_unref(jabra.ch);
+ jabra.ch = NULL;
+ }
jabra.fd = -1;
}
void connect_headset(gpointer user_data, gboolean connected)
{
purple_debug(PURPLE_DEBUG_INFO, "headset", "connect %d\n", connected);
+
+ /* Rescan headset whenever a call starts */
+ if (connected && jabra.fd == -1)
+ init_headset();
+
if (jabra.connected != connected) {
jabra.connected = connected;
if (!connected) {