-
Notifications
You must be signed in to change notification settings - Fork 50
/
co2mon.c
138 lines (123 loc) · 3.3 KB
/
co2mon.c
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
* co2mon - programming interface to CO2 sensor.
* Copyright (C) 2015 Oleg Bulatov <oleg@bulatov.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "co2mon.h"
int
co2mon_init()
{
int r = hid_init();
if (r < 0)
{
fprintf(stderr, "hid_init: error\n");
}
return r;
}
void
co2mon_exit()
{
int r = hid_exit();
if (r < 0)
{
fprintf(stderr, "hid_exit: error\n");
}
}
hid_device *
co2mon_open_device()
{
hid_device *dev = hid_open(0x04d9, 0xa052, NULL);
if (!dev)
{
fprintf(stderr, "hid_open: error\n");
}
return dev;
}
void
co2mon_close_device(hid_device *dev)
{
hid_close(dev);
}
int
co2mon_device_path(hid_device *dev, char *str, size_t maxlen)
{
str[0] = '\0';
return 1;
}
int
co2mon_send_magic_table(hid_device *dev, co2mon_data_t magic_table)
{
int r = hid_send_feature_report(dev, magic_table, sizeof(co2mon_data_t));
if (r < 0 || r != sizeof(co2mon_data_t))
{
fprintf(stderr, "hid_send_feature_report: error\n");
return 0;
}
return 1;
}
static void
swap_char(unsigned char *a, unsigned char *b)
{
unsigned char tmp = *a;
*a = *b;
*b = tmp;
}
static void
decode_buf(co2mon_data_t result, co2mon_data_t buf, co2mon_data_t magic_table)
{
swap_char(&buf[0], &buf[2]);
swap_char(&buf[1], &buf[4]);
swap_char(&buf[3], &buf[7]);
swap_char(&buf[5], &buf[6]);
for (int i = 0; i < 8; ++i)
{
buf[i] ^= magic_table[i];
}
unsigned char tmp = (buf[7] << 5);
result[7] = (buf[6] << 5) | (buf[7] >> 3);
result[6] = (buf[5] << 5) | (buf[6] >> 3);
result[5] = (buf[4] << 5) | (buf[5] >> 3);
result[4] = (buf[3] << 5) | (buf[4] >> 3);
result[3] = (buf[2] << 5) | (buf[3] >> 3);
result[2] = (buf[1] << 5) | (buf[2] >> 3);
result[1] = (buf[0] << 5) | (buf[1] >> 3);
result[0] = tmp | (buf[0] >> 3);
const unsigned char magic_word[8] = "Htemp99e";
for (int i = 0; i < 8; ++i)
{
result[i] -= (magic_word[i] << 4) | (magic_word[i] >> 4);
}
}
int
co2mon_read_data(hid_device *dev, co2mon_data_t magic_table, co2mon_data_t result)
{
co2mon_data_t data = { 0 };
int actual_length = hid_read_timeout(dev, data, sizeof(co2mon_data_t), 5000 /* milliseconds */);
if (actual_length < 0)
{
fprintf(stderr, "hid_read_timeout: error\n");
return actual_length;
}
if (actual_length != sizeof(co2mon_data_t))
{
fprintf(stderr, "hid_read_timeout: trasferred %d bytes, expected %lu bytes\n", actual_length, (unsigned long)sizeof(co2mon_data_t));
return 0;
}
decode_buf(result, data, magic_table);
return actual_length;
}