1 #include "core/controllerframe.hpp"
7 std::set
<porttype_info
*>& porttypes()
9 static std::set
<porttype_info
*> p
;
14 const porttype_info
& porttype_info::lookup(porttype_t p
) throw(std::runtime_error
)
16 for(auto i
: porttypes())
19 throw std::runtime_error("Bad port type");
22 const porttype_info
& porttype_info::lookup(const std::string
& p
) throw(std::runtime_error
)
24 for(auto i
: porttypes())
27 throw std::runtime_error("Bad port type");
30 porttype_info::~porttype_info() throw()
32 porttypes().erase(this);
35 porttype_info::porttype_info(porttype_t ptype
, const std::string
& pname
, size_t psize
) throw(std::bad_alloc
)
40 porttypes().insert(this);
43 pollcounter_vector::pollcounter_vector() throw()
48 void pollcounter_vector::clear() throw()
51 memset(ctrs
, 0, sizeof(ctrs
));
54 void pollcounter_vector::set_all_DRDY() throw()
56 for(size_t i
= 0; i
< MAX_BUTTONS
; i
++)
57 ctrs
[i
] |= 0x80000000UL
;
60 #define INDEXOF(pid, ctrl) ((pid) * MAX_CONTROLS_PER_CONTROLLER + (ctrl))
62 void pollcounter_vector::clear_DRDY(unsigned pid
, unsigned ctrl
) throw()
64 ctrs
[INDEXOF(pid
, ctrl
)] &= 0x7FFFFFFFUL
;
67 bool pollcounter_vector::get_DRDY(unsigned pid
, unsigned ctrl
) throw()
69 return ((ctrs
[INDEXOF(pid
, ctrl
)] & 0x80000000UL
) != 0);
72 bool pollcounter_vector::has_polled() throw()
74 uint32_t res
= system_flag
? 1 : 0;
75 for(size_t i
= 0; i
< MAX_BUTTONS
; i
++)
77 return ((res
& 0x7FFFFFFFUL
) != 0);
80 uint32_t pollcounter_vector::get_polls(unsigned pid
, unsigned ctrl
) throw()
82 return ctrs
[INDEXOF(pid
, ctrl
)] & 0x7FFFFFFFUL
;
85 uint32_t pollcounter_vector::increment_polls(unsigned pid
, unsigned ctrl
) throw()
87 size_t i
= INDEXOF(pid
, ctrl
);
88 uint32_t x
= ctrs
[i
] & 0x7FFFFFFFUL
;
93 void pollcounter_vector::set_system() throw()
98 bool pollcounter_vector::get_system() throw()
103 uint32_t pollcounter_vector::max_polls() throw()
105 uint32_t max
= system_flag
? 1 : 0;
106 for(unsigned i
= 0; i
< MAX_BUTTONS
; i
++) {
107 uint32_t tmp
= ctrs
[i
] & 0x7FFFFFFFUL
;
108 max
= (max
< tmp
) ? tmp
: max
;
113 void pollcounter_vector::save_state(std::vector
<uint32_t>& mem
) throw(std::bad_alloc
)
115 mem
.resize(4 + MAX_BUTTONS
);
117 mem
[0] = 0x80000000UL
;
118 mem
[1] = system_flag
? 1 : 0x80000000UL
;
119 mem
[2] = system_flag
? 1 : 0x80000000UL
;
120 mem
[3] = system_flag
? 1 : 0x80000000UL
;
121 for(size_t i
= 0; i
< MAX_BUTTONS
; i
++)
122 mem
[4 + i
] = ctrs
[i
];
125 void pollcounter_vector::load_state(const std::vector
<uint32_t>& mem
) throw()
127 system_flag
= (mem
[1] | mem
[2] | mem
[3]) & 0x7FFFFFFFUL
;
128 for(size_t i
= 0; i
< MAX_BUTTONS
; i
++)
129 ctrs
[i
] = mem
[i
+ 4];
132 bool pollcounter_vector::check(const std::vector
<uint32_t>& mem
) throw()
134 return (mem
.size() == MAX_BUTTONS
+ 4);
138 controller_frame::controller_frame(porttype_t p1
, porttype_t p2
) throw(std::runtime_error
)
140 memset(memory
, 0, sizeof(memory
));
147 controller_frame::controller_frame(unsigned char* mem
, porttype_t p1
, porttype_t p2
) throw(std::runtime_error
)
150 throw std::runtime_error("NULL backing memory not allowed");
151 memset(memory
, 0, sizeof(memory
));
158 controller_frame::controller_frame(const controller_frame
& obj
) throw()
160 memset(memory
, 0, sizeof(memory
));
162 set_types(obj
.types
);
163 memcpy(backing
, obj
.backing
, totalsize
);
166 controller_frame
& controller_frame::operator=(const controller_frame
& obj
) throw(std::runtime_error
)
168 set_types(obj
.types
);
169 memcpy(backing
, obj
.backing
, totalsize
);
172 void controller_frame::set_types(const porttype_t
* tarr
)
174 for(unsigned i
= 0; i
< MAX_PORTS
; i
++) {
175 if(memory
!= backing
&& types
[i
] != tarr
[i
])
176 throw std::runtime_error("Controller_frame: Type mismatch");
177 if(!porttype_info::lookup(tarr
[i
]).legal(i
))
178 throw std::runtime_error("Illegal port type for port index");
180 size_t offset
= SYSTEM_BYTES
;
181 for(unsigned i
= 0; i
< MAX_PORTS
; i
++) {
184 pinfo
[i
] = &porttype_info::lookup(tarr
[i
]);
185 offset
+= pinfo
[i
]->storage_size
;
190 size_t controller_frame_vector::walk_helper(size_t frame
, bool sflag
) throw()
192 size_t ret
= sflag
? frame
: 0;
197 size_t page
= frame
/ frames_per_page
;
198 size_t offset
= frame_size
* (frame
% frames_per_page
);
199 size_t index
= frame
% frames_per_page
;
200 if(cache_page_num
!= page
) {
201 cache_page
= &pages
[page
];
202 cache_page_num
= page
;
204 while(frame
< frames
) {
205 if(index
== frames_per_page
) {
207 cache_page
= &pages
[page
];
208 cache_page_num
= page
;
210 if(controller_frame::sync(cache_page
->content
+ offset
))
213 offset
+= frame_size
;
220 size_t controller_frame_vector::count_frames() throw()
226 cache_page
= &pages
[0];
229 for(size_t i
= 0; i
< frames
; i
++) {
230 if(index
== frames_per_page
) {
232 cache_page
= &cache_page
[cache_page_num
];
236 if(controller_frame::sync(cache_page
->content
+ offset
))
239 offset
+= frame_size
;
245 void controller_frame_vector::clear(enum porttype_t p1
, enum porttype_t p2
) throw(std::runtime_error
)
247 controller_frame
check(p1
, p2
);
248 frame_size
= check
.size();
249 frames_per_page
= CONTROLLER_PAGE_SIZE
/ frame_size
;
257 controller_frame_vector::~controller_frame_vector() throw()
263 controller_frame_vector::controller_frame_vector(enum porttype_t p1
, enum porttype_t p2
) throw(std::runtime_error
)
268 void controller_frame_vector::append(controller_frame frame
) throw(std::bad_alloc
, std::runtime_error
)
270 controller_frame
check(types
[0], types
[1]);
271 if(!check
.types_match(frame
))
272 throw std::runtime_error("controller_frame_vector::append: Type mismatch");
273 if(frames
% frames_per_page
== 0) {
275 pages
[frames
/ frames_per_page
];
278 size_t page
= frames
/ frames_per_page
;
279 size_t offset
= frame_size
* (frames
% frames_per_page
);
280 cache_page_num
= page
;
281 cache_page
= &pages
[page
];
282 controller_frame(cache_page
->content
+ offset
, types
[0], types
[1]) = frame
;
286 controller_frame_vector::controller_frame_vector(const controller_frame_vector
& vector
) throw(std::bad_alloc
)
288 clear(vector
.types
[0], vector
.types
[1]);
292 controller_frame_vector
& controller_frame_vector::operator=(const controller_frame_vector
& v
)
293 throw(std::bad_alloc
)
301 frame_size
= v
.frame_size
;
302 frames_per_page
= v
.frames_per_page
;
303 for(size_t i
= 0; i
< MAX_PORTS
; i
++)
304 types
[i
] = v
.types
[i
];
306 //This can't fail anymore. Copy the raw page contents.
307 size_t pagecount
= (frames
+ frames_per_page
- 1) / frames_per_page
;
308 for(size_t i
= 0; i
< pagecount
; i
++) {
310 const page
& pg2
= v
.pages
.find(i
)->second
;
317 size_t controller_frame::system_serialize(const unsigned char* buffer
, char* textbuf
)
320 if(buffer
[1] || buffer
[2] || buffer
[3] || buffer
[4])
321 sprintf(tmp
, "%c%c %i %i", ((buffer
[0] & 1) ? 'F' : '.'), ((buffer
[0] & 2) ? 'R' : '.'),
322 unserialize_short(buffer
+ 1), unserialize_short(buffer
+ 3));
324 sprintf(tmp
, "%c%c", ((buffer
[0] & 1) ? 'F' : '.'), ((buffer
[0] & 2) ? 'R' : '.'));
325 size_t len
= strlen(tmp
);
326 memcpy(textbuf
, tmp
, len
);
330 size_t controller_frame::system_deserialize(unsigned char* buffer
, const char* textbuf
)
334 if(read_button_value(textbuf
, idx
))
336 if(read_button_value(textbuf
, idx
))
338 serialize_short(buffer
+ 1, read_axis_value(textbuf
, idx
));
339 serialize_short(buffer
+ 3, read_axis_value(textbuf
, idx
));
340 skip_rest_of_field(textbuf
, idx
, false);
344 short read_axis_value(const char* buf
, size_t& idx
) throw()
348 while(is_nonterminator(buf
[idx
])) {
350 if(ch
!= ' ' && ch
!= '\t')
354 //Read the sign if any.
355 if(!is_nonterminator(buf
[idx
]))
357 bool negative
= false;
365 //Read numeric value.
367 while(!is_nonterminator(buf
[idx
]) && isdigit(static_cast<unsigned char>(ch
= buf
[idx
]))) {
368 numval
= numval
* 10 + (ch
- '0');
374 return static_cast<short>(numval
);
377 void controller_frame_vector::resize(size_t newsize
) throw(std::bad_alloc
)
382 } else if(newsize
< frames
) {
384 size_t current_pages
= (frames
+ frames_per_page
- 1) / frames_per_page
;
385 size_t pages_needed
= (newsize
+ frames_per_page
- 1) / frames_per_page
;
386 for(size_t i
= pages_needed
; i
< current_pages
; i
++)
388 //Now zeroize the excess memory.
389 size_t offset
= frame_size
* (newsize
% frames_per_page
);
390 memset(pages
[pages_needed
- 1].content
+ offset
, 0, CONTROLLER_PAGE_SIZE
- offset
);
392 } else if(newsize
> frames
) {
394 size_t current_pages
= (frames
+ frames_per_page
- 1) / frames_per_page
;
395 size_t pages_needed
= (newsize
+ frames_per_page
- 1) / frames_per_page
;
396 //Create the needed pages.
397 for(size_t i
= current_pages
; i
< pages_needed
; i
++) {
401 for(size_t i
= current_pages
; i
< pages_needed
; i
++)
411 controller_frame::controller_frame() throw()
413 memset(memory
, 0, sizeof(memory
));
415 for(unsigned i
= 0; i
< MAX_PORTS
; i
++) {
416 offsets
[i
] = SYSTEM_BYTES
;
417 types
[i
] = PT_INVALID
;
420 totalsize
= SYSTEM_BYTES
;
423 void controller_frame::set_port_type(unsigned port
, porttype_t ptype
) throw(std::runtime_error
)
425 char tmp
[MAXIMUM_CONTROLLER_FRAME_SIZE
] = {0};
426 if(!porttype_info::lookup(ptype
).legal(port
))
427 throw std::runtime_error("Illegal port type for port index");
428 if(memory
!= backing
)
429 throw std::runtime_error("Can't set port type on non-dedicated controller frame");
430 if(port
>= MAX_PORTS
)
432 const porttype_info
* newpinfo
[MAX_PORTS
];
433 size_t newoffsets
[MAX_PORTS
];
434 size_t offset
= SYSTEM_BYTES
;
435 for(size_t i
= 0; i
< MAX_PORTS
; i
++) {
437 newpinfo
[i
] = pinfo
[i
];
439 newpinfo
[i
] = &porttype_info::lookup(ptype
);
440 newoffsets
[i
] = offset
;
442 offset
+= newpinfo
[i
]->storage_size
;
443 if(i
!= port
&& newpinfo
[i
] && newpinfo
[i
]->storage_size
)
444 memcpy(tmp
+ newoffsets
[i
], backing
+ offsets
[i
], newpinfo
[i
]->storage_size
);
446 memcpy(memory
, tmp
, MAXIMUM_CONTROLLER_FRAME_SIZE
);
448 pinfo
[port
] = newpinfo
[port
];