vrpn 07.35
Virtual Reality Peripheral Network
 
Loading...
Searching...
No Matches
vrpn_Tracker_SpacePoint.C
Go to the documentation of this file.
1/*
2 * vrpn_Tracker_SpacePoint.cpp
3 *
4 * Created on: Nov 22, 2010
5 * Author: janoc
6 */
7
8#include <stdio.h> // for fprintf, stderr
9#include <string.h> // for memset
10#include <string>
11#include <set>
12
13#include "vrpn_Connection.h" // for vrpn_CONNECTION_LOW_LATENCY, etc
15
16const unsigned SPACEPOINT_VENDOR = 0x20ff;
17const unsigned SPACEPOINT_PRODUCT = 0x0100;
18
20
21#ifdef VRPN_USE_HID
22
23/*
24 * Hackish acceptor to work around the broken Windows 10 behavior
25 * where devices are opened in shared mode by default. That prevents
26 * using opening failure to detect an already-in-use device and thus
27 * it is impossible to instantiate multiple copies of this driver for
28 * multiple sensors (they will all read from the first accepted
29 * device).
30 *
31 * This acceptor works it around by keeping a track of already
32 * accepted devices and forcing the use of the next device when
33 * attempting to accept an already accepted one.
34 *
35 * BUGS: the reset() method is useless - we need the device set be
36 * persistent between instantiations of this acceptor and the reset
37 * gets called at the start by all constructors of vrpn_HidInterface :(
38 */
39
40class SpacePointAcceptor : public vrpn_HidAcceptor {
41public:
42 SpacePointAcceptor(unsigned index)
43 : m_index(index)
44 {}
45
46 virtual ~SpacePointAcceptor()
47 {}
48
49 bool accept(const vrpn_HIDDEVINFO &device)
50 {
51 // device.interface_number - SpacePoint clones have only
52 // a single interface and report -1 there, genuine PNI SpacePoint has 2 interfaces
53 // a we need the device with iface num 1 (0 is the raw sensor interface)
54 if((device.vendor == SPACEPOINT_VENDOR) &&
55 (device.product == SPACEPOINT_PRODUCT) &&
56 (device.interface_number < 0 || device.interface_number == 1) &&
57 (m_accepted_already.size() == m_index) &&
58 (m_accepted_already.find(device.path) == m_accepted_already.end()))
59 {
60 m_accepted_already.insert(device.path);
61 return true;
62 }
63 else
64 return false;
65 }
66
67 void reset()
68 {
69 // disabled, see comment above
70 // m_accepted_already.clear();
71 }
72
73private:
74 unsigned m_index;
75 static std::set<std::string> m_accepted_already;
76};
77
78std::set<std::string> SpacePointAcceptor::m_accepted_already;
79
80//new vrpn_HidNthMatchAcceptor(index, new vrpn_HidProductAcceptor(SPACEPOINT_VENDOR, SPACEPOINT_PRODUCT))
81vrpn_Tracker_SpacePoint::vrpn_Tracker_SpacePoint(const char * name, vrpn_Connection * trackercon, int index)
82 : vrpn_Tracker(name, trackercon)
83 , vrpn_Button(name, trackercon)
84 , vrpn_HidInterface(new SpacePointAcceptor(index), SPACEPOINT_VENDOR, SPACEPOINT_PRODUCT)
85{
86 memset(d_quat, 0, 4 * sizeof(float));
87 d_quat[3] = 1.0;
88
91}
92
93void vrpn_Tracker_SpacePoint::on_data_received(size_t bytes, vrpn_uint8 *buffer)
94{
95 /*
96 * Horrible kludge - as we do not have a way to select the correct endpoint, we have to use a hack
97 * to identify the correct device. In Windows the SpacePoint appears as 2 devices with same VID/PID, one for each endpoint
98 * The correct device sends a report 15 bytes long. If we get a report of a different length, we try to open
99 * the other device instead.
100 */
101
102 // test from the app note
103 // the quaternion should be: 0.2474, -0.1697, -0.1713, 0.9384
104 /*
105 bytes = 15;
106 vrpn_uint8 test_dta[] =
107 { 0x2f, 0x85, 0x23, 0x8a, 0x5b, 0x90, 0xac, 0x9f, 0x49, 0x6a, 0x12, 0x6a, 0x1e, 0xf8, 0xd0 };
108 memcpy(buffer, test_dta, 15 * sizeof(vrpn_uint8));
109 */
110
111 if (bytes == 15) {
112 vrpn_uint8 * bufptr = buffer + 6;
113
114 for (int i = 0; i < 4; i++) {
115 d_quat[i] = (vrpn_unbuffer_from_little_endian<vrpn_uint16>(bufptr) - 32768) / 32768.0;
116 }
117
118 buttons[0] = buffer[14] & 0x1;
119 buttons[1] = buffer[14] & 0x2;
120
121 // Find out what time we received the new information, then send any
122 // changes to the client.
126
127 // send tracker orientation
128 d_sensor = 0;
129 memset(pos, 0, sizeof(vrpn_float64) * 3); // no position
130
131 char msgbuf[1000];
132 int len = vrpn_Tracker::encode_to(msgbuf);
134 fprintf(stderr, "SpacePoint tracker: can't write message: tossing\n");
135 }
136
137 // send buttons
139
140 } else {
141 // try the other iface
142 // as we are keeping the first one open,
143 // it will not enumerate and we get the next one. Horrible kludge :(
144 reconnect();
145 }
146}
147
149{
150 if (connected()) {
151 // device update. This will call on_data_received() if we get something.
152 update();
153
154 // server update
156 }
157}
158
159#endif
vrpn_Connection * d_connection
Connection that this object talks to.
vrpn_int32 d_sender_id
Sender ID registered with the connection.
void server_mainloop(void)
Handles functions that all servers should provide in their mainloop() (ping/pong, for example) Should...
vrpn_int32 num_buttons
Definition vrpn_Button.h:48
struct timeval timestamp
Definition vrpn_Button.h:49
vrpn_Button(const char *name, vrpn_Connection *c=NULL)
Definition vrpn_Button.C:91
virtual void report_changes(void)
unsigned char buttons[vrpn_BUTTON_MAX_BUTTONS]
Definition vrpn_Button.h:45
virtual bool reconnect()
Tries to reconnect to an acceptable device. Call this if you suspect a hotplug event has occurred.
vrpn_HidInterface(vrpn_HidAcceptor *acceptor, vrpn_uint16 vendor=0, vrpn_uint16 product=0, hid_device *device=NULL)
Constructor If we already have a HID device from some other source, it can be passed and we'll take o...
virtual void update()
Polls the device buffers and causes on_data_received callbacks if appropriate You NEED to call this f...
virtual bool connected() const
Returns true iff the last device I/O succeeded.
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
virtual void on_data_received(size_t bytes, vrpn_uint8 *buffer)
Derived class reimplements this callback.
vrpn_Tracker_SpacePoint(const char *name, vrpn_Connection *trackercon, int index=0)
virtual int encode_to(char *buf)
vrpn_float64 d_quat[4]
vrpn_Tracker(const char *name, vrpn_Connection *c=NULL, const char *tracker_cfg_file_name=NULL)
vrpn_int32 d_sensor
vrpn_float64 pos[3]
struct timeval timestamp
vrpn_int32 position_m_id
#define VRPN_SUPPRESS_EMPTY_OBJECT_WARNING()
const vrpn_uint32 vrpn_CONNECTION_LOW_LATENCY
#define vrpn_gettimeofday
Definition vrpn_Shared.h:99
const unsigned SPACEPOINT_VENDOR
const unsigned SPACEPOINT_PRODUCT
class VRPN_API vrpn_Connection