seat: Convert device list to linked list
This commit is contained in:
parent
4afe674e54
commit
9b7a12d90a
5 changed files with 33 additions and 32 deletions
|
@ -6,6 +6,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
#include "linked_list.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
|
||||||
struct server;
|
struct server;
|
||||||
|
@ -23,7 +24,7 @@ struct client {
|
||||||
int seat_vt;
|
int seat_vt;
|
||||||
bool pending_disable;
|
bool pending_disable;
|
||||||
|
|
||||||
struct list devices;
|
struct linked_list devices;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct client *client_create(struct server *server, int client_fd);
|
struct client *client_create(struct server *server, int client_fd);
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
#ifndef _SEATD_SEAT_H
|
#ifndef _SEATD_SEAT_H
|
||||||
#define _SEATD_SEAT_H
|
#define _SEATD_SEAT_H
|
||||||
|
|
||||||
#include "list.h"
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "linked_list.h"
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
struct client;
|
struct client;
|
||||||
|
|
||||||
enum seat_device_type {
|
enum seat_device_type {
|
||||||
|
@ -15,6 +17,7 @@ enum seat_device_type {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct seat_device {
|
struct seat_device {
|
||||||
|
struct linked_list link; // client::devices
|
||||||
int device_id;
|
int device_id;
|
||||||
int fd;
|
int fd;
|
||||||
int ref_cnt;
|
int ref_cnt;
|
||||||
|
|
|
@ -78,6 +78,7 @@ private_deps = []
|
||||||
|
|
||||||
server_files = [
|
server_files = [
|
||||||
'common/log.c',
|
'common/log.c',
|
||||||
|
'common/linked_list.c',
|
||||||
'common/list.c',
|
'common/list.c',
|
||||||
'common/terminal.c',
|
'common/terminal.c',
|
||||||
'common/connection.c',
|
'common/connection.c',
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
#include "linked_list.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "poller.h"
|
#include "poller.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
|
@ -67,7 +68,7 @@ struct client *client_create(struct server *server, int client_fd) {
|
||||||
client->pid = pid;
|
client->pid = pid;
|
||||||
client->server = server;
|
client->server = server;
|
||||||
client->connection.fd = client_fd;
|
client->connection.fd = client_fd;
|
||||||
list_init(&client->devices);
|
linked_list_init(&client->devices);
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,8 +103,7 @@ void client_destroy(struct client *client) {
|
||||||
client->connection.fd = -1;
|
client->connection.fd = -1;
|
||||||
}
|
}
|
||||||
connection_close_fds(&client->connection);
|
connection_close_fds(&client->connection);
|
||||||
assert(client->devices.length == 0);
|
assert(linked_list_empty(&client->devices));
|
||||||
list_free(&client->devices);
|
|
||||||
free(client);
|
free(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
50
seatd/seat.c
50
seatd/seat.c
|
@ -95,9 +95,10 @@ int seat_remove_client(struct client *client) {
|
||||||
seat->next_client = NULL;
|
seat->next_client = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (client->devices.length > 0) {
|
while (!linked_list_empty(&client->devices)) {
|
||||||
struct seat_device *device = list_pop_back(&client->devices);
|
struct seat_device *device = (struct seat_device *)client->devices.next;
|
||||||
seat_close_device(client, device);
|
seat_close_device(client, device);
|
||||||
|
linked_list_remove(&device->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seat->active_client == client) {
|
if (seat->active_client == client) {
|
||||||
|
@ -115,8 +116,9 @@ struct seat_device *seat_find_device(struct client *client, int device_id) {
|
||||||
assert(client->seat);
|
assert(client->seat);
|
||||||
assert(device_id != 0);
|
assert(device_id != 0);
|
||||||
|
|
||||||
for (size_t idx = 0; idx < client->devices.length; idx++) {
|
for (struct linked_list *elem = client->devices.next; elem != &client->devices;
|
||||||
struct seat_device *seat_device = client->devices.items[idx];
|
elem = elem->next) {
|
||||||
|
struct seat_device *seat_device = (struct seat_device *)elem;
|
||||||
if (seat_device->device_id == device_id) {
|
if (seat_device->device_id == device_id) {
|
||||||
return seat_device;
|
return seat_device;
|
||||||
}
|
}
|
||||||
|
@ -159,8 +161,10 @@ struct seat_device *seat_open_device(struct client *client, const char *path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int device_id = 1;
|
int device_id = 1;
|
||||||
for (size_t idx = 0; idx < client->devices.length; idx++) {
|
size_t device_count = 0;
|
||||||
struct seat_device *device = client->devices.items[idx];
|
for (struct linked_list *elem = client->devices.next; elem != &client->devices;
|
||||||
|
elem = elem->next) {
|
||||||
|
struct seat_device *device = (struct seat_device *)elem;
|
||||||
|
|
||||||
// If the device already exists, increase the ref count and
|
// If the device already exists, increase the ref count and
|
||||||
// return it.
|
// return it.
|
||||||
|
@ -173,9 +177,10 @@ struct seat_device *seat_open_device(struct client *client, const char *path) {
|
||||||
if (device->device_id >= device_id) {
|
if (device->device_id >= device_id) {
|
||||||
device_id = device->device_id + 1;
|
device_id = device->device_id + 1;
|
||||||
}
|
}
|
||||||
|
device_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client->devices.length >= MAX_SEAT_DEVICES) {
|
if (device_count >= MAX_SEAT_DEVICES) {
|
||||||
log_error("max seat devices exceeded");
|
log_error("max seat devices exceeded");
|
||||||
errno = EMFILE;
|
errno = EMFILE;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -225,7 +230,7 @@ struct seat_device *seat_open_device(struct client *client, const char *path) {
|
||||||
device->fd = fd;
|
device->fd = fd;
|
||||||
device->device_id = device_id;
|
device->device_id = device_id;
|
||||||
device->active = true;
|
device->active = true;
|
||||||
list_add(&client->devices, device);
|
linked_list_insert(&client->devices, &device->link);
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,14 +239,6 @@ int seat_close_device(struct client *client, struct seat_device *seat_device) {
|
||||||
assert(client->seat);
|
assert(client->seat);
|
||||||
assert(seat_device && seat_device->fd != -1);
|
assert(seat_device && seat_device->fd != -1);
|
||||||
|
|
||||||
// Find the device in our list
|
|
||||||
size_t idx = list_find(&client->devices, seat_device);
|
|
||||||
if (idx == -1UL) {
|
|
||||||
log_error("seat device not registered by client");
|
|
||||||
errno = ENOENT;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_debugf("seat: %p, client: %p, path: '%s', device_id: %d", (void *)client->seat,
|
log_debugf("seat: %p, client: %p, path: '%s', device_id: %d", (void *)client->seat,
|
||||||
(void *)client, seat_device->path, seat_device->device_id);
|
(void *)client, seat_device->path, seat_device->device_id);
|
||||||
|
|
||||||
|
@ -252,7 +249,7 @@ int seat_close_device(struct client *client, struct seat_device *seat_device) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The ref count hit zero, so destroy the device
|
// The ref count hit zero, so destroy the device
|
||||||
list_del(&client->devices, idx);
|
linked_list_remove(&seat_device->link);
|
||||||
if (seat_device->active && seat_device->fd != -1) {
|
if (seat_device->active && seat_device->fd != -1) {
|
||||||
switch (seat_device->type) {
|
switch (seat_device->type) {
|
||||||
case SEAT_DEVICE_TYPE_DRM:
|
case SEAT_DEVICE_TYPE_DRM:
|
||||||
|
@ -372,15 +369,14 @@ int seat_open_client(struct seat *seat, struct client *client) {
|
||||||
seat->curttyfd = ttyfd;
|
seat->curttyfd = ttyfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t idx = 0; idx < client->devices.length; idx++) {
|
for (struct linked_list *elem = client->devices.next; elem != &client->devices;
|
||||||
struct seat_device *device = client->devices.items[idx];
|
elem = elem->next) {
|
||||||
|
struct seat_device *device = (struct seat_device *)elem;
|
||||||
if (seat_activate_device(client, device) == -1) {
|
if (seat_activate_device(client, device) == -1) {
|
||||||
log_errorf("unable to activate '%s': %s", device->path, strerror(errno));
|
log_errorf("unable to activate '%s': %s", device->path, strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_debugf("activated %zd devices", client->devices.length);
|
|
||||||
|
|
||||||
seat->active_client = client;
|
seat->active_client = client;
|
||||||
if (client_send_enable_seat(client) == -1) {
|
if (client_send_enable_seat(client) == -1) {
|
||||||
seat_remove_client(client);
|
seat_remove_client(client);
|
||||||
|
@ -403,11 +399,12 @@ int seat_close_client(struct client *client) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (client->devices.length > 0) {
|
while (!linked_list_empty(&client->devices)) {
|
||||||
struct seat_device *device = list_pop_back(&client->devices);
|
struct seat_device *device = (struct seat_device *)client->devices.next;
|
||||||
if (seat_close_device(client, device) == -1) {
|
if (seat_close_device(client, device) == -1) {
|
||||||
log_errorf("unable to close '%s': %s", device->path, strerror(errno));
|
log_errorf("unable to close '%s': %s", device->path, strerror(errno));
|
||||||
}
|
}
|
||||||
|
linked_list_remove(&device->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
client->pending_disable = false;
|
client->pending_disable = false;
|
||||||
|
@ -433,15 +430,14 @@ static int seat_disable_client(struct client *client) {
|
||||||
// The reason we cannot just close them is that certain device fds, such
|
// The reason we cannot just close them is that certain device fds, such
|
||||||
// as for DRM, must maintain the exact same file description for their
|
// as for DRM, must maintain the exact same file description for their
|
||||||
// contexts to remain valid.
|
// contexts to remain valid.
|
||||||
for (size_t idx = 0; idx < client->devices.length; idx++) {
|
for (struct linked_list *elem = client->devices.next; elem != &client->devices;
|
||||||
struct seat_device *device = client->devices.items[idx];
|
elem = elem->next) {
|
||||||
|
struct seat_device *device = (struct seat_device *)elem;
|
||||||
if (seat_deactivate_device(client, device) == -1) {
|
if (seat_deactivate_device(client, device) == -1) {
|
||||||
log_errorf("unable to deactivate '%s': %s", device->path, strerror(errno));
|
log_errorf("unable to deactivate '%s': %s", device->path, strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_debugf("deactivated %zd devices", client->devices.length);
|
|
||||||
|
|
||||||
client->pending_disable = true;
|
client->pending_disable = true;
|
||||||
if (client_send_disable_seat(seat->active_client) == -1) {
|
if (client_send_disable_seat(seat->active_client) == -1) {
|
||||||
seat_remove_client(client);
|
seat_remove_client(client);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue