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...
This is the base class for both the client and server for a button device (a device with one or more ...
Definition vrpn_Button.h:31
vrpn_int32 num_buttons
Definition vrpn_Button.h:48
struct timeval timestamp
Definition vrpn_Button.h:49
virtual void report_changes(void)
unsigned char buttons[vrpn_BUTTON_MAX_BUTTONS]
Definition vrpn_Button.h:45
Generic connection class not specific to the transport mechanism.
virtual int pack_message(vrpn_uint32 len, struct timeval time, vrpn_int32 type, vrpn_int32 sender, const char *buffer, vrpn_uint32 class_of_service)
Pack a message that will be sent the next time mainloop() is called. Turn off the RELIABLE flag if yo...
virtual bool reconnect()
Tries to reconnect to an acceptable device. Call this if you suspect a hotplug event has occurred.
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_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