psvr.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  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. /* Sony PSVR Driver */
  8. #define FEATURE_BUFFER_SIZE 256
  9. #define TICK_LEN (1.0f / 1000000.0f) // 1000 Hz ticks
  10. #define SONY_ID 0x054c
  11. #define PSVR_HMD 0x09af
  12. #include <string.h>
  13. #include <wchar.h>
  14. #include <hidapi.h>
  15. #include <assert.h>
  16. #include <limits.h>
  17. #include <stdint.h>
  18. #include <stdbool.h>
  19. #include "psvr.h"
  20. typedef struct {
  21. ohmd_device base;
  22. hid_device* hmd_handle;
  23. hid_device* hmd_control;
  24. fusion sensor_fusion;
  25. vec3f raw_accel, raw_gyro;
  26. uint32_t last_ticks;
  27. uint8_t last_seq;
  28. psvr_sensor_packet sensor;
  29. } psvr_priv;
  30. void vec3f_from_psvr_vec(const int16_t* smp, vec3f* out_vec)
  31. {
  32. out_vec->x = (float)smp[1] * 0.001f;
  33. out_vec->y = (float)smp[0] * 0.001f;
  34. out_vec->z = (float)smp[2] * 0.001f * -1.0f;
  35. }
  36. static void handle_tracker_sensor_msg(psvr_priv* priv, unsigned char* buffer, int size)
  37. {
  38. uint32_t last_sample_tick = priv->sensor.tick;
  39. if(!psvr_decode_sensor_packet(&priv->sensor, buffer, size)){
  40. LOGE("couldn't decode tracker sensor message");
  41. }
  42. psvr_sensor_packet* s = &priv->sensor;
  43. uint32_t tick_delta = 1000;
  44. if(last_sample_tick > 0) //startup correction
  45. tick_delta = s->tick - last_sample_tick;
  46. float dt = tick_delta * TICK_LEN;
  47. vec3f mag = {{0.0f, 0.0f, 0.0f}};
  48. for(int i = 0; i < 1; i++){ //just use 1 sample since we don't have sample order for frame
  49. vec3f_from_psvr_vec(s->samples[i].accel, &priv->raw_accel);
  50. vec3f_from_psvr_vec(s->samples[i].gyro, &priv->raw_gyro);
  51. ofusion_update(&priv->sensor_fusion, dt, &priv->raw_gyro, &priv->raw_accel, &mag);
  52. // reset dt to tick_len for the last samples if there were more than one sample
  53. dt = TICK_LEN;
  54. }
  55. }
  56. static void update_device(ohmd_device* device)
  57. {
  58. psvr_priv* priv = (psvr_priv*)device;
  59. int size = 0;
  60. unsigned char buffer[FEATURE_BUFFER_SIZE];
  61. while(true){
  62. int size = hid_read(priv->hmd_handle, buffer, FEATURE_BUFFER_SIZE);
  63. if(size < 0){
  64. LOGE("error reading from device");
  65. return;
  66. } else if(size == 0) {
  67. return; // No more messages, return.
  68. }
  69. // currently the only message type the hardware supports (I think)
  70. if(buffer[0] == PSVR_IRQ_SENSORS){
  71. handle_tracker_sensor_msg(priv, buffer, size);
  72. }else if (buffer[0] == PSVR_IRQ_VOLUME_PLUS){
  73. //TODO implement
  74. }else if (buffer[0] == PSVR_IRQ_VOLUME_MINUS){
  75. //TODO implement
  76. }else if (buffer[0] == PSVR_IRQ_MIC_MUTE){
  77. //TODO implement
  78. }else{
  79. LOGE("unknown message type: %u", buffer[0]);
  80. }
  81. }
  82. if(size < 0){
  83. LOGE("error reading from device");
  84. }
  85. }
  86. static int getf(ohmd_device* device, ohmd_float_value type, float* out)
  87. {
  88. psvr_priv* priv = (psvr_priv*)device;
  89. switch(type){
  90. case OHMD_ROTATION_QUAT:
  91. *(quatf*)out = priv->sensor_fusion.orient;
  92. break;
  93. case OHMD_POSITION_VECTOR:
  94. out[0] = out[1] = out[2] = 0;
  95. break;
  96. case OHMD_DISTORTION_K:
  97. // TODO this should be set to the equivalent of no distortion
  98. memset(out, 0, sizeof(float) * 6);
  99. break;
  100. default:
  101. ohmd_set_error(priv->base.ctx, "invalid type given to getf (%ud)", type);
  102. return -1;
  103. break;
  104. }
  105. return 0;
  106. }
  107. static void close_device(ohmd_device* device)
  108. {
  109. psvr_priv* priv = (psvr_priv*)device;
  110. LOGD("closing HTC PSVR device");
  111. hid_close(priv->hmd_handle);
  112. hid_close(priv->hmd_control);
  113. free(device);
  114. }
  115. static hid_device* open_device_idx(int manufacturer, int product, int iface, int iface_tot, int device_index)
  116. {
  117. struct hid_device_info* devs = hid_enumerate(manufacturer, product);
  118. struct hid_device_info* cur_dev = devs;
  119. int idx = 0;
  120. int iface_cur = 0;
  121. hid_device* ret = NULL;
  122. while (cur_dev) {
  123. printf("%04x:%04x %s\n", manufacturer, product, cur_dev->path);
  124. if(findEndPoint(cur_dev->path, device_index) > 0 && iface == iface_cur){
  125. ret = hid_open_path(cur_dev->path);
  126. printf("opening\n");
  127. }
  128. cur_dev = cur_dev->next;
  129. iface_cur++;
  130. if(iface_cur >= iface_tot){
  131. idx++;
  132. iface_cur = 0;
  133. }
  134. }
  135. hid_free_enumeration(devs);
  136. return ret;
  137. }
  138. static ohmd_device* open_device(ohmd_driver* driver, ohmd_device_desc* desc)
  139. {
  140. psvr_priv* priv = ohmd_alloc(driver->ctx, sizeof(psvr_priv));
  141. if(!priv)
  142. return NULL;
  143. priv->base.ctx = driver->ctx;
  144. int idx = atoi(desc->path);
  145. // Open the HMD device
  146. priv->hmd_handle = open_device_idx(SONY_ID, PSVR_HMD, 0, 0, 4);
  147. if(!priv->hmd_handle)
  148. goto cleanup;
  149. if(hid_set_nonblocking(priv->hmd_handle, 1) == -1){
  150. ohmd_set_error(driver->ctx, "failed to set non-blocking on device");
  151. goto cleanup;
  152. }
  153. // Open the HMD Control device
  154. priv->hmd_control = open_device_idx(SONY_ID, PSVR_HMD, 0, 0, 5);
  155. if(!priv->hmd_control)
  156. goto cleanup;
  157. if(hid_set_nonblocking(priv->hmd_control, 1) == -1){
  158. ohmd_set_error(driver->ctx, "failed to set non-blocking on device");
  159. goto cleanup;
  160. }
  161. // turn the display on
  162. hid_write(priv->hmd_control, psvr_power_on, sizeof(psvr_power_on));
  163. // set VR mode for the hmd
  164. hid_write(priv->hmd_control, psvr_vrmode_on, sizeof(psvr_vrmode_on));
  165. // Set default device properties
  166. ohmd_set_default_device_properties(&priv->base.properties);
  167. // Set device properties TODO: Get from device
  168. priv->base.properties.hsize = 0.126; //from calculated specs
  169. priv->base.properties.vsize = 0.071; //from calculated specs
  170. priv->base.properties.hres = 1920;
  171. priv->base.properties.vres = 1080;
  172. priv->base.properties.lens_sep = 0.063500;
  173. priv->base.properties.lens_vpos = 0.049694;
  174. priv->base.properties.fov = DEG_TO_RAD(103.57f); //TODO: Confirm exact mesurements
  175. priv->base.properties.ratio = (1920.0f / 1080.0f) / 2.0f;
  176. // calculate projection eye projection matrices from the device properties
  177. ohmd_calc_default_proj_matrices(&priv->base.properties);
  178. // set up device callbacks
  179. priv->base.update = update_device;
  180. priv->base.close = close_device;
  181. priv->base.getf = getf;
  182. ofusion_init(&priv->sensor_fusion);
  183. return (ohmd_device*)priv;
  184. cleanup:
  185. if(priv)
  186. free(priv);
  187. return NULL;
  188. }
  189. static void get_device_list(ohmd_driver* driver, ohmd_device_list* list)
  190. {
  191. struct hid_device_info* devs = hid_enumerate(SONY_ID, PSVR_HMD);
  192. struct hid_device_info* cur_dev = devs;
  193. int idx = 0;
  194. while (cur_dev) {
  195. ohmd_device_desc* desc = &list->devices[list->num_devices++];
  196. strcpy(desc->driver, "OpenHMD Sony PSVR Driver");
  197. strcpy(desc->vendor, "Sony");
  198. strcpy(desc->product, "PSVR");
  199. desc->revision = 0;
  200. snprintf(desc->path, OHMD_STR_SIZE, "%d", idx);
  201. desc->driver_ptr = driver;
  202. desc->device_class = OHMD_DEVICE_CLASS_HMD;
  203. desc->device_flags = OHMD_DEVICE_FLAGS_ROTATIONAL_TRACKING;
  204. cur_dev = cur_dev->next;
  205. idx++;
  206. }
  207. hid_free_enumeration(devs);
  208. }
  209. static void destroy_driver(ohmd_driver* drv)
  210. {
  211. LOGD("shutting down Sony PSVR driver");
  212. free(drv);
  213. }
  214. ohmd_driver* ohmd_create_psvr_drv(ohmd_context* ctx)
  215. {
  216. ohmd_driver* drv = ohmd_alloc(ctx, sizeof(ohmd_driver));
  217. if(!drv)
  218. return NULL;
  219. drv->get_device_list = get_device_list;
  220. drv->open_device = open_device;
  221. drv->destroy = destroy_driver;
  222. drv->ctx = ctx;
  223. return drv;
  224. }