vive.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. /*
  2. * OpenHMD - Free and Open Source API and drivers for immersive technology.
  3. * Copyright (C) 2013 Fredrik Hultin.
  4. * Copyright (C) 2013 Jakob Bornecrantz.
  5. * Distributed under the Boost 1.0 licence, see LICENSE for full text.
  6. */
  7. /* HTC Vive Driver */
  8. #define FEATURE_BUFFER_SIZE 256
  9. #define HTC_ID 0x0bb4
  10. #define VIVE_HMD 0x2c87
  11. #define VALVE_ID 0x28de
  12. #define VIVE_WATCHMAN_DONGLE 0x2101
  13. #define VIVE_LIGHTHOUSE_FPGA_RX 0x2000
  14. #define VIVE_TIME_DIV 48000000.0f
  15. #include <string.h>
  16. #include <wchar.h>
  17. #include <hidapi.h>
  18. #include <assert.h>
  19. #include <limits.h>
  20. #include <stdint.h>
  21. #include <stdbool.h>
  22. #include "vive.h"
  23. typedef struct {
  24. ohmd_device base;
  25. hid_device* hmd_handle;
  26. hid_device* imu_handle;
  27. fusion sensor_fusion;
  28. vec3f raw_accel, raw_gyro;
  29. uint32_t last_ticks;
  30. uint8_t last_seq;
  31. vive_config_packet vive_config;
  32. vec3f gyro_error;
  33. filter_queue gyro_q;
  34. } vive_priv;
  35. void vec3f_from_vive_vec_accel(const int16_t* smp, vec3f* out_vec)
  36. {
  37. float gravity = 9.81f;
  38. float scaler = 4.0f * gravity / 32768.0f;
  39. out_vec->x = (float)smp[0] * scaler;
  40. out_vec->y = (float)smp[1] * scaler * -1;
  41. out_vec->z = (float)smp[2] * scaler * -1;
  42. }
  43. void vec3f_from_vive_vec_gyro(const int16_t* smp, vec3f* out_vec)
  44. {
  45. float scaler = 8.7f / 32768.0f;
  46. out_vec->x = (float)smp[0] * scaler;
  47. out_vec->y = (float)smp[1] * scaler * -1;
  48. out_vec->z = (float)smp[2] * scaler * -1;
  49. }
  50. static bool process_error(vive_priv* priv)
  51. {
  52. if(priv->gyro_q.at >= priv->gyro_q.size - 1)
  53. return true;
  54. ofq_add(&priv->gyro_q, &priv->raw_gyro);
  55. if(priv->gyro_q.at >= priv->gyro_q.size - 1){
  56. ofq_get_mean(&priv->gyro_q, &priv->gyro_error);
  57. printf("gyro error: %f, %f, %f\n", priv->gyro_error.x, priv->gyro_error.y, priv->gyro_error.z);
  58. }
  59. return false;
  60. }
  61. vive_sensor_sample* get_next_sample(vive_sensor_packet* pkt, int last_seq)
  62. {
  63. int diff[3];
  64. for(int i = 0; i < 3; i++)
  65. {
  66. diff[i] = (int)pkt->samples[i].seq - last_seq;
  67. if(diff[i] < -128){
  68. diff[i] += 256;
  69. }
  70. }
  71. int closest_diff = INT_MAX;
  72. int closest_idx = -1;
  73. for(int i = 0; i < 3; i++)
  74. {
  75. if(diff[i] < closest_diff && diff[i] > 0 && diff[i] < 128){
  76. closest_diff = diff[i];
  77. closest_idx = i;
  78. }
  79. }
  80. if(closest_idx != -1)
  81. return pkt->samples + closest_idx;
  82. return NULL;
  83. }
  84. static void update_device(ohmd_device* device)
  85. {
  86. vive_priv* priv = (vive_priv*)device;
  87. int size = 0;
  88. unsigned char buffer[FEATURE_BUFFER_SIZE];
  89. while((size = hid_read(priv->imu_handle, buffer, FEATURE_BUFFER_SIZE)) > 0){
  90. if(buffer[0] == VIVE_IRQ_SENSORS){
  91. vive_sensor_packet pkt;
  92. vive_decode_sensor_packet(&pkt, buffer, size);
  93. vive_sensor_sample* smp = NULL;
  94. while((smp = get_next_sample(&pkt, priv->last_seq)) != NULL)
  95. {
  96. if(priv->last_ticks == 0)
  97. priv->last_ticks = smp->time_ticks;
  98. uint32_t t1, t2;
  99. t1 = smp->time_ticks;
  100. t2 = priv->last_ticks;
  101. float dt = (t1 - t2) / VIVE_TIME_DIV;
  102. priv->last_ticks = smp->time_ticks;
  103. vec3f_from_vive_vec_accel(smp->acc, &priv->raw_accel);
  104. vec3f_from_vive_vec_gyro(smp->rot, &priv->raw_gyro);
  105. if(process_error(priv)){
  106. vec3f mag = {{0.0f, 0.0f, 0.0f}};
  107. vec3f gyro;
  108. ovec3f_subtract(&priv->raw_gyro, &priv->gyro_error, &gyro);
  109. ofusion_update(&priv->sensor_fusion, dt, &gyro, &priv->raw_accel, &mag);
  110. }
  111. priv->last_seq = smp->seq;
  112. }
  113. }else{
  114. LOGE("unknown message type: %u", buffer[0]);
  115. }
  116. }
  117. if(size < 0){
  118. LOGE("error reading from device");
  119. }
  120. }
  121. static int getf(ohmd_device* device, ohmd_float_value type, float* out)
  122. {
  123. vive_priv* priv = (vive_priv*)device;
  124. switch(type){
  125. case OHMD_ROTATION_QUAT:
  126. *(quatf*)out = priv->sensor_fusion.orient;
  127. break;
  128. case OHMD_POSITION_VECTOR:
  129. out[0] = out[1] = out[2] = 0;
  130. break;
  131. case OHMD_DISTORTION_K:
  132. // TODO this should be set to the equivalent of no distortion
  133. memset(out, 0, sizeof(float) * 6);
  134. break;
  135. default:
  136. ohmd_set_error(priv->base.ctx, "invalid type given to getf (%ud)", type);
  137. return -1;
  138. break;
  139. }
  140. return 0;
  141. }
  142. static void close_device(ohmd_device* device)
  143. {
  144. int hret = 0;
  145. vive_priv* priv = (vive_priv*)device;
  146. LOGD("closing HTC Vive device");
  147. // turn the display off
  148. hret = hid_send_feature_report(priv->hmd_handle, vive_magic_power_off1, sizeof(vive_magic_power_off1));
  149. printf("power off magic 1: %d\n", hret);
  150. hret = hid_send_feature_report(priv->hmd_handle, vive_magic_power_off2, sizeof(vive_magic_power_off2));
  151. printf("power off magic 2: %d\n", hret);
  152. hid_close(priv->hmd_handle);
  153. hid_close(priv->imu_handle);
  154. free(device);
  155. }
  156. #if 0
  157. static void dump_indexed_string(hid_device* device, int index)
  158. {
  159. wchar_t wbuffer[512] = {0};
  160. char buffer[1024] = {0};
  161. int hret = hid_get_indexed_string(device, index, wbuffer, 511);
  162. if(hret == 0){
  163. wcstombs(buffer, wbuffer, sizeof(buffer));
  164. printf("indexed string 0x%02x: '%s'\n", index, buffer);
  165. }
  166. }
  167. #endif
  168. static void dump_info_string(int (*fun)(hid_device*, wchar_t*, size_t), const char* what, hid_device* device)
  169. {
  170. wchar_t wbuffer[512] = {0};
  171. char buffer[1024] = {0};
  172. int hret = fun(device, wbuffer, 511);
  173. if(hret == 0){
  174. wcstombs(buffer, wbuffer, sizeof(buffer));
  175. printf("%s: '%s'\n", what, buffer);
  176. }
  177. }
  178. #if 0
  179. static void dumpbin(const char* label, const unsigned char* data, int length)
  180. {
  181. printf("%s:\n", label);
  182. for(int i = 0; i < length; i++){
  183. printf("%02x ", data[i]);
  184. if((i % 16) == 15)
  185. printf("\n");
  186. }
  187. printf("\n");
  188. }
  189. #endif
  190. static hid_device* open_device_idx(int manufacturer, int product, int iface, int iface_tot, int device_index)
  191. {
  192. struct hid_device_info* devs = hid_enumerate(manufacturer, product);
  193. struct hid_device_info* cur_dev = devs;
  194. int idx = 0;
  195. int iface_cur = 0;
  196. hid_device* ret = NULL;
  197. while (cur_dev) {
  198. printf("%04x:%04x %s\n", manufacturer, product, cur_dev->path);
  199. if(idx == device_index && iface == iface_cur){
  200. ret = hid_open_path(cur_dev->path);
  201. printf("opening\n");
  202. }
  203. cur_dev = cur_dev->next;
  204. iface_cur++;
  205. if(iface_cur >= iface_tot){
  206. idx++;
  207. iface_cur = 0;
  208. }
  209. }
  210. hid_free_enumeration(devs);
  211. return ret;
  212. }
  213. static ohmd_device* open_device(ohmd_driver* driver, ohmd_device_desc* desc)
  214. {
  215. vive_priv* priv = ohmd_alloc(driver->ctx, sizeof(vive_priv));
  216. if(!priv)
  217. return NULL;
  218. int hret = 0;
  219. priv->base.ctx = driver->ctx;
  220. int idx = atoi(desc->path);
  221. // Open the HMD device
  222. priv->hmd_handle = open_device_idx(HTC_ID, VIVE_HMD, 0, 1, idx);
  223. if(!priv->hmd_handle)
  224. goto cleanup;
  225. if(hid_set_nonblocking(priv->hmd_handle, 1) == -1){
  226. ohmd_set_error(driver->ctx, "failed to set non-blocking on device");
  227. goto cleanup;
  228. }
  229. // Open the lighthouse device
  230. priv->imu_handle = open_device_idx(VALVE_ID, VIVE_LIGHTHOUSE_FPGA_RX, 0, 2, idx);
  231. if(!priv->imu_handle)
  232. goto cleanup;
  233. if(hid_set_nonblocking(priv->imu_handle, 1) == -1){
  234. ohmd_set_error(driver->ctx, "failed to set non-blocking on device");
  235. goto cleanup;
  236. }
  237. dump_info_string(hid_get_manufacturer_string, "manufacturer", priv->hmd_handle);
  238. dump_info_string(hid_get_product_string , "product", priv->hmd_handle);
  239. dump_info_string(hid_get_serial_number_string, "serial number", priv->hmd_handle);
  240. // turn the display on
  241. hret = hid_send_feature_report(priv->hmd_handle, vive_magic_power_on, sizeof(vive_magic_power_on));
  242. printf("power on magic: %d\n", hret);
  243. // enable lighthouse
  244. //hret = hid_send_feature_report(priv->hmd_handle, vive_magic_enable_lighthouse, sizeof(vive_magic_enable_lighthouse));
  245. //printf("enable lighthouse magic: %d\n", hret);
  246. unsigned char buffer[128];
  247. int bytes;
  248. printf("Getting feature report 16 to 39\n");
  249. buffer[0] = 16;
  250. bytes = hid_get_feature_report(priv->imu_handle, buffer, sizeof(buffer));
  251. printf("got %i bytes\n", bytes);
  252. for (int i = 0; i < bytes; i++) {
  253. printf("%02hx ", buffer[i]);
  254. }
  255. printf("\n\n");
  256. unsigned char* packet_buffer = malloc(4096);
  257. int offset = 0;
  258. while (buffer[1] != 0) {
  259. buffer[0] = 17;
  260. bytes = hid_get_feature_report(priv->imu_handle, buffer, sizeof(buffer));
  261. memcpy((uint8_t*)packet_buffer + offset, buffer+2, buffer[1]);
  262. offset += buffer[1];
  263. }
  264. packet_buffer[offset] = '\0';
  265. //printf("Result: %s\n", packet_buffer);
  266. vive_decode_config_packet(&priv->vive_config, packet_buffer, offset);
  267. free(packet_buffer);
  268. // Set default device properties
  269. ohmd_set_default_device_properties(&priv->base.properties);
  270. // Set device properties TODO: Get from device
  271. priv->base.properties.hsize = 0.122822f;
  272. priv->base.properties.vsize = 0.068234f;
  273. priv->base.properties.hres = 2160;
  274. priv->base.properties.vres = 1200;
  275. priv->base.properties.lens_sep = 0.063500;
  276. priv->base.properties.lens_vpos = 0.049694;
  277. priv->base.properties.fov = DEG_TO_RAD(111.435f); //TODO: Confirm exact mesurements
  278. priv->base.properties.ratio = (2160.0f / 1200.0f) / 2.0f;
  279. // calculate projection eye projection matrices from the device properties
  280. ohmd_calc_default_proj_matrices(&priv->base.properties);
  281. // set up device callbacks
  282. priv->base.update = update_device;
  283. priv->base.close = close_device;
  284. priv->base.getf = getf;
  285. ofusion_init(&priv->sensor_fusion);
  286. ofq_init(&priv->gyro_q, 128);
  287. return (ohmd_device*)priv;
  288. cleanup:
  289. if(priv)
  290. free(priv);
  291. return NULL;
  292. }
  293. static void get_device_list(ohmd_driver* driver, ohmd_device_list* list)
  294. {
  295. struct hid_device_info* devs = hid_enumerate(HTC_ID, VIVE_HMD);
  296. struct hid_device_info* cur_dev = devs;
  297. int idx = 0;
  298. while (cur_dev) {
  299. ohmd_device_desc* desc = &list->devices[list->num_devices++];
  300. strcpy(desc->driver, "OpenHMD HTC Vive Driver");
  301. strcpy(desc->vendor, "HTC/Valve");
  302. strcpy(desc->product, "HTC Vive");
  303. desc->revision = 0;
  304. snprintf(desc->path, OHMD_STR_SIZE, "%d", idx);
  305. desc->driver_ptr = driver;
  306. cur_dev = cur_dev->next;
  307. idx++;
  308. }
  309. hid_free_enumeration(devs);
  310. }
  311. static void destroy_driver(ohmd_driver* drv)
  312. {
  313. LOGD("shutting down HTC Vive driver");
  314. free(drv);
  315. }
  316. ohmd_driver* ohmd_create_htc_vive_drv(ohmd_context* ctx)
  317. {
  318. ohmd_driver* drv = ohmd_alloc(ctx, sizeof(ohmd_driver));
  319. if(!drv)
  320. return NULL;
  321. drv->get_device_list = get_device_list;
  322. drv->open_device = open_device;
  323. drv->destroy = destroy_driver;
  324. drv->ctx = ctx;
  325. return drv;
  326. }