diff options
author | David Härdeman <david@hardeman.nu> | 2015-08-15 22:43:32 +0200 |
---|---|---|
committer | David Härdeman <david@hardeman.nu> | 2015-08-15 22:43:32 +0200 |
commit | c420b38a5a4bac32b1086e0359e5f5646880d9f4 (patch) | |
tree | ffcf65dcc3d2e905665f82f57fcc48bccefa4a58 /rcm-server-main.c | |
parent | 6d12cb6b9e9d7b67521f6ca999c933e1555a3226 (diff) |
Add basic transmit support (WIP)
Diffstat (limited to 'rcm-server-main.c')
-rw-r--r-- | rcm-server-main.c | 163 |
1 files changed, 148 insertions, 15 deletions
diff --git a/rcm-server-main.c b/rcm-server-main.c index 4a0adbc..4d23f89 100644 --- a/rcm-server-main.c +++ b/rcm-server-main.c @@ -649,6 +649,58 @@ out: return sd_bus_error_set_errno(error, r); } +static void +lirc_write(int fd, const uint32_t *v, unsigned count) +{ + unsigned nv[count]; + unsigned i; + size_t l = count * sizeof(uint32_t); + + for (i = 0; i < count; i++) + nv[i] = v[i]; + + printf("Write to lirc fd of %zu bytes returned %zi errno is %i aka %s\n", + l, write(fd, nv, l), errno, strerror(errno)); +} + +static int +method_transmit(sd_bus_message *m, void *userdata, sd_bus_error *error) +{ + _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + struct manager *mgr = userdata; + struct device *dev; + const void *v; + size_t l; + int r; + const uint32_t *values; + size_t count; + + printf("Transmit method called\n"); + dev = find_device_by_path(mgr, sd_bus_message_get_path(m)); + if (!dev) { + sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidDevice", "Sorry, invalid device"); + return -EINVAL; + } + + r = sd_bus_message_read_array(m, SD_BUS_TYPE_UINT32, &v, &l); + if (r < 0) { + goto out; + } else if (r == 0 || l % sizeof(uint32_t) != 0) { + r = -EBADMSG; + goto out; + } + + values = v; + count = l / sizeof(uint32_t); + lirc_write(dev->lirc_fd, values, count); + + + return sd_bus_reply_method_return(m, NULL); + +out: + return sd_bus_error_set_errno(error, r); +} + static const sd_bus_vtable device_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("SysName", "s", property_get, 0, 0), @@ -660,6 +712,7 @@ static const sd_bus_vtable device_vtable[] = { SD_BUS_METHOD("ListKeymaps", NULL, "as", method_listkeymaps, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetKeymap", "s", "ssqqaa{sv}aa{sv}", method_getkeymap, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetKeymap", "sssqqaa{sv}aa{sv}", NULL, method_setkeymap, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Transmit", "au", NULL, method_transmit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_SIGNAL("KeyPressed", "sts", 0), SD_BUS_SIGNAL("KeyReleased", "s", 0), SD_BUS_VTABLE_END @@ -684,6 +737,63 @@ remove_device(struct manager *mgr, struct udev_device *udev) } } +static int +lirc_read(sd_event_source *s, int fd, uint32_t revents, void *userdata) +{ + struct device *device = userdata; + uint8_t buf[100]; + ssize_t bytes_read; + + if (fd != device->lirc_fd) + fprintf(stderr, "lirc fd mismatch: %i != %i\n", device->lirc_fd, fd); + + if (revents & EPOLLHUP) { + fprintf(stderr, "lirc connection closed!\n"); + close(fd); + device->lirc_fd = -1; + return 0; + } + + if (!(revents & EPOLLIN)) { + fprintf(stderr, "unexpected lirc event: %" PRIu32 "\n", revents); + return 0; + } + + while ((bytes_read = read(fd, buf, sizeof(buf))) > 0) + printf("Read %zi bytes from lirc dev\n", bytes_read); + + return 0; +} + +static int +lirc_setup(struct device *device, const char *path) +{ + if (!device) + return -EINVAL; + + if (device->lirc_fd >= 0) { + printf("Multiple lirc devices!?\n"); + return 0; + } + + device->lirc_fd = open(path, O_RDWR | O_NONBLOCK); + if (device->lirc_fd < 0) { + printf("Failed to open lirc device %s: %s\n", path, strerror(errno)); + return -errno; + } + + if (sd_event_add_io(device->mgr->event, &device->lirc_ev, + device->lirc_fd, EPOLLIN, lirc_read, device) < 0) { + printf("Failed to add event source for lirc device %s: %s\n", + path, strerror(errno)); + close(device->lirc_fd); + device->lirc_fd = -1; + return -errno; + } + + return 0; +} + static void add_device(struct manager *mgr, struct udev_device *udev) { @@ -693,7 +803,6 @@ add_device(struct manager *mgr, struct udev_device *udev) struct device *device; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; - struct udev_device *evdev; int r; name = udev_device_get_sysname(udev); @@ -714,7 +823,9 @@ add_device(struct manager *mgr, struct udev_device *udev) device->path = path; device->name = device->path + strlen("/org/gnome/RemoteControlManager/"); device->evdev_fd = -1; + device->lirc_fd = -1; device->error = NULL; + device->input_name = NULL; if (keymaps_load(device) < 0) { fprintf(stderr, "failed to load keymaps: %m\n"); @@ -726,12 +837,15 @@ add_device(struct manager *mgr, struct udev_device *udev) enumerate = udev_enumerate_new(mgr->udev); udev_enumerate_add_match_parent(enumerate, udev); udev_enumerate_add_match_sysname(enumerate, "event*"); + udev_enumerate_add_match_sysname(enumerate, "lirc*"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); udev_list_entry_foreach(dev_list_entry, devices) { const char *path; + struct udev_device *udev_dev; const char *devnode; + const char *subsys; path = udev_list_entry_get_name(dev_list_entry); if (!path) { @@ -739,29 +853,47 @@ add_device(struct manager *mgr, struct udev_device *udev) continue; } - evdev = udev_device_new_from_syspath(mgr->udev, path); - if (!evdev) { + udev_dev = udev_device_new_from_syspath(mgr->udev, path); + if (!udev_dev) { printf("Failed to create udev device\n"); continue; } - devnode = udev_device_get_devnode(evdev); + devnode = udev_device_get_devnode(udev_dev); if (!devnode) { - printf("Failed to determine evdev devnode\n"); - udev_device_unref(evdev); - continue; + printf("Failed to determine udev_dev devnode\n"); + goto next; } - r = evdev_setup(device, devnode); - if (r < 0) { - printf("Failed to setup evdev: %s\n", devnode); - device->error = "Error: Failed to setup evdev"; - device->input_name = NULL; - udev_device_unref(evdev); - continue; + subsys = udev_device_get_subsystem(udev_dev); + if (!subsys) { + printf("Failed to determine udev_dev subsystem\n"); + goto next; + } + + if (!strcmp(subsys, "input")) { + r = evdev_setup(device, devnode); + if (r < 0) { + printf("Failed to setup evdev: %s\n", devnode); + device->error = "Error: Failed to setup evdev"; + goto next; + } + + } else if (!strcmp(subsys, "lirc")) { + r = lirc_setup(device, devnode); + if (r < 0) { + printf("Failed to setup lirc: %s\n", devnode); + device->error = "Error: Failed to setup lirc"; + goto next; + } + + } else { + printf("Unknown subsystem, ignored %s\n", devnode); + goto next; } - udev_device_unref(evdev); +next: + udev_device_unref(udev_dev); } udev_enumerate_unref(enumerate); @@ -793,6 +925,7 @@ add_device(struct manager *mgr, struct udev_device *udev) printf("\tDriver : %s\n", device->driver_name); printf("\tKernel map: %s\n", device->keymap_name); printf("\tDevnode fd: %i\n", device->evdev_fd); + printf("\tLIRC fd : %i\n", device->lirc_fd); printf("\tDBUS path : %s\n", device->path); printf("\tProtocols : %s\n", udev_device_get_sysattr_value(udev, "protocols")); |