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