1 /*
2 * Copyright 2013, Fredrik Hultin.
3 * Copyright 2013, Jakob Bornecrantz.
4 * Copyright 2016 Philipp Zabel
5 * Copyright 2019 Jan Schmidt
6 * SPDX-License-Identifier: BSL-1.0
7 *
8 * OpenHMD - Free and Open Source API and drivers for immersive technology.
9 */
10
11 /* Oculus Rift Driver - Packet Decoding and Utilities */
12
13
14 #include <stdio.h>
15 #include <string.h>
16 #include "rift.h"
17
18 #define SKIP8 (buffer++)
19 #define SKIP16 (buffer+=2)
20 #define SKIP_CMD (buffer++)
21 #define READ8 *(buffer++);
22 #define READ16 *buffer | (*(buffer + 1) << 8); buffer += 2;
23 #define READ32 *buffer | (*(buffer + 1) << 8) | (*(buffer + 2) << 16) | (*(buffer + 3) << 24); buffer += 4;
24 #define READFLOAT ((float)(*buffer)); buffer += 4;
25 #define READFIXED (float)(*buffer | (*(buffer + 1) << 8) | (*(buffer + 2) << 16) | (*(buffer + 3) << 24)) / 1000000.0f; buffer += 4;
26
27 #define WRITE8(_val) *(buffer++) = (_val);
28 #define WRITE16(_val) WRITE8((_val) & 0xff); WRITE8(((_val) >> 8) & 0xff);
29 #define WRITE32(_val) WRITE16((_val) & 0xffff) *buffer; WRITE16(((_val) >> 16) & 0xffff);
30
decode_position_info(pkt_position_info * p,const unsigned char * buffer,int size)31 bool decode_position_info(pkt_position_info* p, const unsigned char* buffer, int size)
32 {
33 if(size != 30) {
34 LOGE("invalid packet size (expected 30 but got %d)", size);
35 return false;
36 }
37
38 SKIP_CMD;
39 SKIP16;
40 p->flags = READ8;
41 p->pos_x = READ32;
42 p->pos_y = READ32;
43 p->pos_z = READ32;
44 p->dir_x = READ16;
45 p->dir_y = READ16;
46 p->dir_z = READ16;
47 SKIP16;
48 p->index = READ8;
49 SKIP8;
50 p->num = READ8;
51 SKIP8;
52 p->type = READ8;
53
54 return true;
55 }
56
decode_led_pattern_info(pkt_led_pattern_report * p,const unsigned char * buffer,int size)57 bool decode_led_pattern_info(pkt_led_pattern_report * p, const unsigned char* buffer, int size)
58 {
59 if(size != 12) {
60 LOGE("invalid packet size (expected 12 but got %d)", size);
61 return false;
62 }
63
64 SKIP_CMD;
65 SKIP16;
66 p->pattern_length = READ8;
67 p->pattern = READ32;
68 p->index = READ16;
69 p->num = READ16;
70
71 return true;
72 }
73
decode_sensor_range(pkt_sensor_range * range,const unsigned char * buffer,int size)74 bool decode_sensor_range(pkt_sensor_range* range, const unsigned char* buffer, int size)
75 {
76 if(!(size == 8 || size == 9)){
77 LOGE("invalid packet size (expected 8 or 9 but got %d)", size);
78 return false;
79 }
80
81 SKIP_CMD;
82 range->command_id = READ16;
83 range->accel_scale = READ8;
84 range->gyro_scale = READ16;
85 range->mag_scale = READ16;
86
87 return true;
88 }
89
decode_sensor_display_info(pkt_sensor_display_info * info,const unsigned char * buffer,int size)90 bool decode_sensor_display_info(pkt_sensor_display_info* info, const unsigned char* buffer, int size)
91 {
92 if(!(size == 56 || size == 57)){
93 LOGE("invalid packet size (expected 56 or 57 but got %d)", size);
94 return false;
95 }
96
97 SKIP_CMD;
98 info->command_id = READ16;
99 info->distortion_type = READ8;
100 info->h_resolution = READ16;
101 info->v_resolution = READ16;
102 info->h_screen_size = READFIXED;
103 info->v_screen_size = READFIXED;
104 info->v_center = READFIXED;
105 info->lens_separation = READFIXED;
106 info->eye_to_screen_distance[0] = READFIXED;
107 info->eye_to_screen_distance[1] = READFIXED;
108
109 info->distortion_type_opts = 0;
110
111 for(int i = 0; i < 6; i++){
112 info->distortion_k[i] = READFLOAT;
113 }
114
115 return true;
116 }
117
decode_sensor_config(pkt_sensor_config * config,const unsigned char * buffer,int size)118 bool decode_sensor_config(pkt_sensor_config* config, const unsigned char* buffer, int size)
119 {
120 if(!(size == 7 || size == 8)){
121 LOGE("invalid packet size (expected 7 or 8 but got %d)", size);
122 return false;
123 }
124
125 SKIP_CMD;
126 config->command_id = READ16;
127 config->flags = READ8;
128 config->packet_interval = READ8;
129 config->keep_alive_interval = READ16;
130
131 return true;
132 }
133
decode_sample(const unsigned char * buffer,int32_t * smp)134 static void decode_sample(const unsigned char* buffer, int32_t* smp)
135 {
136 /*
137 * Decode 3 tightly packed 21 bit values from 4 bytes.
138 * We unpack them in the higher 21 bit values first and then shift
139 * them down to the lower in order to get the sign bits correct.
140 */
141
142 int x = (buffer[0] << 24) | (buffer[1] << 16) | ((buffer[2] & 0xF8) << 8);
143 int y = ((buffer[2] & 0x07) << 29) | (buffer[3] << 21) | (buffer[4] << 13) | ((buffer[5] & 0xC0) << 5);
144 int z = ((buffer[5] & 0x3F) << 26) | (buffer[6] << 18) | (buffer[7] << 10);
145
146 smp[0] = x >> 11;
147 smp[1] = y >> 11;
148 smp[2] = z >> 11;
149 }
150
decode_tracker_sensor_msg_dk1(pkt_tracker_sensor * msg,const unsigned char * buffer,int size)151 bool decode_tracker_sensor_msg_dk1(pkt_tracker_sensor* msg, const unsigned char* buffer, int size)
152 {
153 if(!(size == 62 || size == 64)){
154 LOGE("invalid packet size (expected 62 or 64 but got %d)", size);
155 return false;
156 }
157
158 SKIP_CMD;
159 msg->num_samples = READ8;
160 msg->total_sample_count = 0; /* No sample count in DK1 */
161 msg->timestamp = READ16;
162 msg->timestamp *= 1000; // DK1 timestamps are in milliseconds
163 buffer += 2; /* Skip unused last_command_id */
164 msg->temperature = READ16;
165
166 msg->num_samples = OHMD_MIN(msg->num_samples, 3);
167 for(int i = 0; i < msg->num_samples; i++){
168 decode_sample(buffer, msg->samples[i].accel);
169 buffer += 8;
170
171 decode_sample(buffer, msg->samples[i].gyro);
172 buffer += 8;
173 }
174
175 // Skip empty samples
176 buffer += (3 - msg->num_samples) * 16;
177 for(int i = 0; i < 3; i++){
178 msg->mag[i] = READ16;
179 }
180
181 // positional tracking data and frame data - do these exist on DK1?
182 msg->frame_count = 0;
183 msg->frame_timestamp = 0;
184 msg->frame_id = 0;
185 msg->led_pattern_phase = 0;
186 msg->exposure_count = 0;
187 msg->exposure_timestamp = 0;
188
189 return true;
190 }
191
decode_tracker_sensor_msg_dk2(pkt_tracker_sensor * msg,const unsigned char * buffer,int size)192 bool decode_tracker_sensor_msg_dk2(pkt_tracker_sensor* msg, const unsigned char* buffer, int size)
193 {
194 if(!(size == 64)){
195 LOGE("invalid packet size (expected 64 but got %d)", size);
196 return false;
197 }
198
199 SKIP_CMD;
200 SKIP16;
201 msg->num_samples = READ8;
202 /* Next is the number of samples since start, excluding the samples
203 contained in this packet */
204 msg->total_sample_count = READ16;
205 msg->temperature = READ16;
206 msg->timestamp = READ32;
207
208 /* Second sample value is junk (outdated/uninitialized) value if
209 num_samples < 2. */
210 msg->num_samples = OHMD_MIN(msg->num_samples, 2);
211 for(int i = 0; i < msg->num_samples; i++){
212 decode_sample(buffer, msg->samples[i].accel);
213 buffer += 8;
214
215 decode_sample(buffer, msg->samples[i].gyro);
216 buffer += 8;
217 }
218
219 // Skip empty samples
220 buffer += (2 - msg->num_samples) * 16;
221
222 for(int i = 0; i < 3; i++){
223 msg->mag[i] = READ16;
224 }
225
226 // positional tracking data and frame data
227 msg->frame_count = READ16;
228 msg->frame_timestamp = READ32;
229 msg->frame_id = READ8;
230 msg->led_pattern_phase = READ8;
231 msg->exposure_count = READ16;
232 msg->exposure_timestamp = READ32;
233
234 return true;
235 }
236
decode_radio_address(uint8_t radio_address[5],const unsigned char * buffer,int size)237 bool decode_radio_address(uint8_t radio_address[5], const unsigned char* buffer, int size)
238 {
239 if (size < 8)
240 return false;
241
242 /* Ignore the command and echo bytes, then 5 bytes of radio address payload */
243 SKIP_CMD;
244 SKIP16;
245
246 memcpy (radio_address, buffer, 5);
247
248 return true;
249 }
250
decode_rift_radio_message(pkt_rift_radio_message * m,const unsigned char * buffer)251 static bool decode_rift_radio_message(pkt_rift_radio_message *m, const unsigned char* buffer)
252 {
253 int i;
254
255 m->flags = READ16;
256 m->device_type = READ8;
257
258 /* 2019-6 All the valid messages I've seen have 0x1c or 0x5 in these 16 bits - JS */
259 /* 0x5 always seems to be the rift remote, and there are 2 other cases I've seen:
260 * device type 0x22 flags 0x0000 and device type 0x04 flags 0x7600 */
261 m->valid = (m->flags == 0x1c || m->flags == 0x05);
262
263 if (!m->valid) {
264 LOGV ("Invalid radio report from unknown remote device type 0x%02x flags 0x%04x",
265 m->device_type, m->flags);
266 return true;
267 }
268
269 switch (m->device_type) {
270 case RIFT_REMOTE:
271 m->remote.buttons = READ16;
272 break;
273 case RIFT_TOUCH_CONTROLLER_LEFT:
274 case RIFT_TOUCH_CONTROLLER_RIGHT: {
275 uint8_t tgs[5];
276
277 m->touch.timestamp = READ32;
278 for (i = 0; i < 3; i++) {
279 m->touch.accel[i] = READ16;
280 }
281 for (i = 0; i < 3; i++) {
282 m->touch.gyro[i] = READ16;
283 }
284
285 m->touch.buttons = READ8;
286
287 for (i = 0; i < 5; i++) {
288 tgs[i] = READ8;
289 }
290
291 m->touch.trigger = tgs[0] | ((tgs[1] & 0x03) << 8);
292 m->touch.grip = ((tgs[1] & 0xfc) >> 2) | ((tgs[2] & 0x0f) << 6);
293 m->touch.stick[0] = ((tgs[2] & 0xf0) >> 4) | ((tgs[3] & 0x3f) << 4);
294 m->touch.stick[1] = ((tgs[3] & 0xc0) >> 6) | ((tgs[4] & 0xff) << 2);
295
296 m->touch.adc_channel = READ8;
297 m->touch.adc_value = READ16;
298 break;
299 }
300 default:
301 LOGE ("Radio report from unknown remote device type 0x%02x flags 0x%04x",
302 m->device_type, m->flags);
303 return false;
304 }
305
306 return true;
307 }
308
decode_rift_radio_report(pkt_rift_radio_report * r,const unsigned char * buffer,int size)309 bool decode_rift_radio_report(pkt_rift_radio_report *r, const unsigned char* buffer, int size)
310 {
311 if (size != RIFT_RADIO_REPORT_SIZE) {
312 LOGE("invalid packet size (expected 64 but got %d)", size);
313 return false;
314 }
315
316 if (buffer[0] != RIFT_RADIO_REPORT_ID) {
317 LOGE("Unknown radio report id 0x%02x\n", buffer[0]);
318 return false;
319 }
320
321 r->id = READ8;
322 SKIP16; // Ignore the echo
323
324 for (int i = 0; i < 2; i++) {
325 if (!decode_rift_radio_message (&r->message[i], buffer))
326 return false;
327 buffer += 28;
328 }
329
330 return true;
331 }
332
333 // TODO do we need to consider HMD vs sensor "centric" values
vec3f_from_rift_vec(const int32_t * smp,vec3f * out_vec)334 void vec3f_from_rift_vec(const int32_t* smp, vec3f* out_vec)
335 {
336 out_vec->x = (float)smp[0] * 0.0001f;
337 out_vec->y = (float)smp[1] * 0.0001f;
338 out_vec->z = (float)smp[2] * 0.0001f;
339 }
340
encode_sensor_config(unsigned char * buffer,const pkt_sensor_config * config)341 int encode_sensor_config(unsigned char* buffer, const pkt_sensor_config* config)
342 {
343 WRITE8(RIFT_CMD_SENSOR_CONFIG);
344 WRITE16(config->command_id);
345 WRITE8(config->flags);
346 WRITE8(config->packet_interval);
347 WRITE16(config->keep_alive_interval);
348 return 7; // sensor config packet size
349 }
350
encode_tracking_config(unsigned char * buffer,const pkt_tracking_config * tracking)351 int encode_tracking_config(unsigned char* buffer, const pkt_tracking_config* tracking)
352 {
353 WRITE8(RIFT_CMD_TRACKING_CONFIG);
354 WRITE16(tracking->command_id);
355 WRITE8(tracking->pattern);
356 WRITE8(tracking->flags);
357 WRITE8(tracking->reserved);
358 WRITE16(tracking->exposure_us);
359 WRITE16(tracking->period_us);
360 WRITE16(tracking->vsync_offset);
361 WRITE8 (tracking->duty_cycle);
362
363 return 13;
364 }
365
encode_dk1_keep_alive(unsigned char * buffer,const pkt_keep_alive * keep_alive)366 int encode_dk1_keep_alive(unsigned char* buffer, const pkt_keep_alive* keep_alive)
367 {
368 WRITE8(RIFT_CMD_DK1_KEEP_ALIVE);
369 WRITE16(keep_alive->command_id);
370 WRITE16(keep_alive->keep_alive_interval);
371 return 5; // keep alive packet size
372 }
373
encode_enable_components(unsigned char * buffer,bool display,bool audio,bool leds)374 int encode_enable_components(unsigned char* buffer, bool display, bool audio, bool leds)
375 {
376 uint8_t flags = 0;
377
378 WRITE8(RIFT_CMD_ENABLE_COMPONENTS);
379 WRITE16(0); // last command ID
380
381 if (display)
382 flags |= RIFT_COMPONENT_DISPLAY;
383 if (audio)
384 flags |= RIFT_COMPONENT_AUDIO;
385 if (leds)
386 flags |= RIFT_COMPONENT_LEDS;
387 WRITE8(flags);
388 return 4; // component flags packet size
389 }
390
encode_radio_control_cmd(unsigned char * buffer,uint8_t a,uint8_t b,uint8_t c)391 int encode_radio_control_cmd(unsigned char* buffer, uint8_t a, uint8_t b, uint8_t c)
392 {
393 WRITE8(RIFT_CMD_RADIO_CONTROL);
394 WRITE16(0); // last command ID
395 WRITE8(a);
396 WRITE8(b);
397 WRITE8(c);
398
399 return 6;
400 }
401
encode_radio_data_read_cmd(unsigned char * buffer,uint16_t offset,uint16_t length)402 int encode_radio_data_read_cmd(unsigned char *buffer, uint16_t offset, uint16_t length)
403 {
404 int i;
405 WRITE8(RIFT_CMD_RADIO_READ_DATA);
406 WRITE16(0); // last command ID
407 WRITE16(offset);
408 WRITE16(length);
409
410 for (i = 0; i < 28; i++) {
411 WRITE8(0);
412 }
413
414 return 31;
415 }
416
dump_packet_sensor_range(const pkt_sensor_range * range)417 void dump_packet_sensor_range(const pkt_sensor_range* range)
418 {
419 (void)range;
420
421 LOGD("sensor range\n");
422 LOGD(" command id: %d", range->command_id);
423 LOGD(" accel scale: %d", range->accel_scale);
424 LOGD(" gyro scale: %d", range->gyro_scale);
425 LOGD(" mag scale: %d", range->mag_scale);
426 }
427
dump_packet_sensor_display_info(const pkt_sensor_display_info * info)428 void dump_packet_sensor_display_info(const pkt_sensor_display_info* info)
429 {
430 (void)info;
431
432 LOGD("display info");
433 LOGD(" command id: %d", info->command_id);
434 LOGD(" distortion_type: %d", info->distortion_type);
435 LOGD(" resolution: %d x %d", info->h_resolution, info->v_resolution);
436 LOGD(" screen size: %f x %f", info->h_screen_size, info->v_screen_size);
437 LOGD(" vertical center: %f", info->v_center);
438 LOGD(" lens_separation: %f", info->lens_separation);
439 LOGD(" eye_to_screen_distance: %f, %f", info->eye_to_screen_distance[0], info->eye_to_screen_distance[1]);
440 LOGD(" distortion_k: %f, %f, %f, %f, %f, %f",
441 info->distortion_k[0], info->distortion_k[1], info->distortion_k[2],
442 info->distortion_k[3], info->distortion_k[4], info->distortion_k[5]);
443 }
444
dump_packet_sensor_config(const pkt_sensor_config * config)445 void dump_packet_sensor_config(const pkt_sensor_config* config)
446 {
447 (void)config;
448
449 LOGD("sensor config");
450 LOGD(" command id: %u", config->command_id);
451 LOGD(" flags: %02x", config->flags);
452 LOGD(" raw mode: %d", !!(config->flags & RIFT_SCF_RAW_MODE));
453 LOGD(" calibration test: %d", !!(config->flags & RIFT_SCF_CALIBRATION_TEST));
454 LOGD(" use calibration: %d", !!(config->flags & RIFT_SCF_USE_CALIBRATION));
455 LOGD(" auto calibration: %d", !!(config->flags & RIFT_SCF_AUTO_CALIBRATION));
456 LOGD(" motion keep alive: %d", !!(config->flags & RIFT_SCF_MOTION_KEEP_ALIVE));
457 LOGD(" motion command keep alive: %d", !!(config->flags & RIFT_SCF_COMMAND_KEEP_ALIVE));
458 LOGD(" sensor coordinates: %d", !!(config->flags & RIFT_SCF_SENSOR_COORDINATES));
459 LOGD(" packet interval: %u", config->packet_interval);
460 LOGD(" keep alive interval: %u", config->keep_alive_interval);
461 }
462
dump_packet_tracker_sensor(const pkt_tracker_sensor * sensor)463 void dump_packet_tracker_sensor(const pkt_tracker_sensor* sensor)
464 {
465 (void)sensor;
466
467 LOGD("tracker sensor:");
468 LOGD(" total sample count: %u", sensor->total_sample_count);
469 LOGD(" timestamp: %u", sensor->timestamp);
470 LOGD(" temperature: %d", sensor->temperature);
471 LOGD(" num samples: %u", sensor->num_samples);
472 LOGD(" magnetic field: %i %i %i", sensor->mag[0], sensor->mag[1], sensor->mag[2]);
473
474 for(int i = 0; i < sensor->num_samples; i++){
475 LOGD(" accel: %d %d %d", sensor->samples[i].accel[0], sensor->samples[i].accel[1], sensor->samples[i].accel[2]);
476 LOGD(" gyro: %d %d %d", sensor->samples[i].gyro[0], sensor->samples[i].gyro[1], sensor->samples[i].gyro[2]);
477 }
478 LOGD("frame_id %u frame count %u timestamp %u led pattern %u exposure_count %u exposure time %u",
479 sensor->frame_id,
480 sensor->frame_count, sensor->frame_timestamp,
481 sensor->led_pattern_phase, sensor->exposure_count,
482 sensor->exposure_timestamp);
483 }
484