summaryrefslogtreecommitdiffstats
path: root/device.c
blob: 52c49a5bd3167600f1297ebcedb2bf93a2ad1469 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <string.h>
#include "dive.h"
#include "device.h"

static struct device_info *device_info_list;

struct device_info *head_of_device_info_list(void)
{
	return device_info_list;
}

void remove_dive_computer(const char *model, uint32_t deviceid)
{
	free(remove_device_info(model, deviceid));
}

static int match_device_info(struct device_info *entry, const char *model, uint32_t deviceid)
{
	return !strcmp(entry->model, model) && entry->deviceid == deviceid;
}

/* just find the entry for this divecomputer */
struct device_info *get_device_info(const char *model, uint32_t deviceid)
{
	struct device_info *known = device_info_list;

	/* a 0 deviceid doesn't get a nickname - those come from development
	 * versions of Subsurface that didn't store the deviceid in the divecomputer entries */
	if (!deviceid || !model)
		return NULL;
	while (known) {
		if (match_device_info(known, model, deviceid))
			return known;
		known = known->next;
	}
	return NULL;
}

/*
 * Sort the device_info list, so that we write it out
 * in a stable order. Otherwise we'll end up having the
 * XML file have the devices listed in some arbitrary
 * order, which is annoying.
 */
static void add_entry_sorted(struct device_info *entry)
{
	struct device_info *p, **pp = &device_info_list;

	while ((p = *pp) != NULL) {
		int cmp = strcmp(p->model, entry->model);
		if (cmp > 0)
			break;
		if (!cmp && p->deviceid > entry->deviceid)
			break;
		pp = &p->next;
	}

	entry->next = p;
	*pp = entry;
}

/* Get an existing device info model or create a new one if valid */
struct device_info *create_device_info(const char *model, uint32_t deviceid)
{
	struct device_info *entry;

	if (!deviceid || !model || !*model)
		return NULL;
	entry = get_device_info(model, deviceid);
	if (entry)
		return entry;
	entry = calloc(1, sizeof(*entry));
	if (entry) {
		entry->model = strdup(model);
		entry->deviceid = deviceid;
		add_entry_sorted(entry);
	}
	return entry;
}

/* do we have a DIFFERENT divecomputer of the same model? */
struct device_info *get_different_device_info(const char *model, uint32_t deviceid)
{
	struct device_info *known = device_info_list;

	/* a 0 deviceid matches any DC of the same model - those come from development
	 * versions of Subsurface that didn't store the deviceid in the divecomputer entries */
	if (!deviceid)
		return NULL;
	if (!model)
		model = "";
	while (known) {
		if (known->model && !strcmp(known->model, model) &&
		    known->deviceid != deviceid)
			return known;
		known = known->next;
	}
	return NULL;
}

struct device_info *remove_device_info(const char *model, uint32_t deviceid)
{
	struct device_info *entry, **p;

	if (!deviceid || !model || !*model)
		return NULL;
	p = &device_info_list;
	while ((entry = *p) != NULL) {
		if (match_device_info(entry, model, deviceid)) {
			*p = entry->next;
			break;
		}
		p = &entry->next;
	}
	return entry;
}