short id fix
[debian/gnuradio] / usrp / host / lib / inband / qa_inband_usrp_server.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2007,2008 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <usrp_inband_usb_packet.h>
27 #include <qa_inband_usrp_server.h>
28 #include <cppunit/TestAssert.h>
29 #include <stdio.h>
30 #include <usrp_server.h>
31 #include <mblock/mblock.h>
32 #include <mblock/runtime.h>
33 #include <mblock/protocol_class.h>
34 #include <mblock/class_registry.h>
35 #include <vector>
36 #include <iostream>
37 #include <pmt.h>
38
39 #include <symbols_usrp_server_cs.h>
40 #include <symbols_usrp_tx.h>
41 #include <symbols_usrp_rx.h>
42 #include <symbols_usrp_channel.h>
43 #include <symbols_usrp_low_level_cs.h>
44
45 typedef usrp_inband_usb_packet transport_pkt;   // makes conversion to gigabit easy
46
47 static bool verbose = false;
48
49 static pmt_t s_timeout = pmt_intern("%timeout");
50
51 // ----------------------------------------------------------------------------------------------
52
53 class qa_alloc_top : public mb_mblock
54 {
55   mb_port_sptr d_tx;
56   mb_port_sptr d_rx;
57   mb_port_sptr d_cs;
58
59   long d_nmsgs_to_recv;
60   long d_nrecvd;
61
62   long d_max_capacity;
63   long d_ntx_chan, d_nrx_chan;
64
65   long d_nstatus;
66   long d_nstatus_to_recv;
67
68  public:
69   qa_alloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
70   ~qa_alloc_top();
71   void initial_transition();
72   void handle_message(mb_message_sptr msg);
73
74  protected:
75   void check_message(mb_message_sptr msg);
76   void run_tests();
77 };
78
79 qa_alloc_top::qa_alloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
80   : mb_mblock(runtime, instance_name, user_arg)
81
82   d_nrecvd=0;
83   d_nmsgs_to_recv = 6;
84   d_nstatus=0;
85   d_nstatus_to_recv = 50;
86   
87   d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
88   d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
89   d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
90  
91   // Use the stub with the usrp_server
92   pmt_t usrp_server_dict = pmt_make_dict();
93   pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T);
94
95   // Test the TX side
96   define_component("server", "usrp_server", usrp_server_dict);
97   connect("self", "tx0", "server", "tx0");
98   connect("self", "rx0", "server", "rx0");
99   connect("self", "cs", "server", "cs");
100
101 }
102
103 qa_alloc_top::~qa_alloc_top(){}
104
105 void
106 qa_alloc_top::initial_transition()
107 {
108   // Allocations should fail before open
109   d_tx->send(s_cmd_allocate_channel, 
110              pmt_list2(pmt_list2(s_response_allocate_channel, 
111                                  s_err_usrp_not_opened), 
112                        pmt_from_long(1)));
113
114   d_rx->send(s_cmd_allocate_channel, 
115              pmt_list2(pmt_list2(s_response_allocate_channel,
116                                  s_err_usrp_not_opened), 
117                        pmt_from_long(1)));
118
119   // Retrieve information about the USRP, then run tests
120   d_cs->send(s_cmd_open, 
121              pmt_list2(pmt_list2(s_response_open, PMT_T), 
122              pmt_from_long(0)));
123
124   d_cs->send(s_cmd_max_capacity, 
125              pmt_list1(pmt_list2(s_response_max_capacity, PMT_T)));
126   
127   d_cs->send(s_cmd_ntx_chan, 
128              pmt_list1(pmt_list2(s_response_ntx_chan, PMT_T)));
129   
130   d_cs->send(s_cmd_nrx_chan, 
131              pmt_list1(pmt_list2(s_response_nrx_chan,PMT_T)));
132 }
133
134 void
135 qa_alloc_top::run_tests()
136 {
137   if(verbose)
138     std::cout << "[qa_alloc_top] Starting tests...\n";
139
140   // should be able to allocate 1 byte
141   d_tx->send(s_cmd_allocate_channel, 
142              pmt_list2(PMT_T, pmt_from_long(1)));
143   
144   // should not be able to allocate max capacity after 100 bytes were allocated
145   d_tx->send(s_cmd_allocate_channel, 
146              pmt_list2(s_err_requested_capacity_unavailable, 
147                        pmt_from_long(d_max_capacity)));  
148   
149   // keep allocating a little more until all of the channels are used and test
150   // the error response we start at 1 since we've already allocated 1 channel
151   for(int i=1; i < d_ntx_chan; i++) {
152
153     if(verbose)
154       std::cout << "[qa_alloc_top] Sent allocation request...\n";
155   
156     d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
157
158     d_nmsgs_to_recv++;
159   }
160
161   // No more channels after allocating all of them is expected
162   d_tx->send(s_cmd_allocate_channel, 
163              pmt_list2(s_err_channel_unavailable, 
164                        pmt_from_long(1)));
165
166   // test out the same on the RX side
167   d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
168
169   d_rx->send(s_cmd_allocate_channel, 
170              pmt_list2(s_err_requested_capacity_unavailable, 
171                        pmt_from_long(d_max_capacity)));  
172
173   for(int i=1; i < d_nrx_chan; i++) {
174     
175     d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
176     
177     d_nmsgs_to_recv++;
178   }
179
180   d_rx->send(s_cmd_allocate_channel, 
181              pmt_list2(s_err_channel_unavailable, 
182              pmt_from_long(1)));
183
184   // when all is said and done, there should be d_ntx_chan+d_ntx_chan bytes
185   // allocated
186   d_cs->send(s_cmd_current_capacity_allocation, 
187              pmt_list1(pmt_from_long(d_ntx_chan+d_nrx_chan)));
188 }
189
190 void
191 qa_alloc_top::handle_message(mb_message_sptr msg)
192 {
193   pmt_t data = msg->data();
194
195   if ((pmt_eq(msg->port_id(), d_tx->port_symbol())
196        || pmt_eq(msg->port_id(), d_rx->port_symbol()))
197        && pmt_eq(msg->signal(), s_response_allocate_channel))
198     check_message(msg);
199   
200   if (pmt_eq(msg->port_id(), d_cs->port_symbol())) {
201       
202     if(pmt_eq(msg->signal(), s_response_max_capacity)) {
203       d_max_capacity = pmt_to_long(pmt_nth(2, data));
204       if(verbose)
205         std::cout << "[qa_alloc_top] USRP has max capacity of " 
206                   << d_max_capacity << "\n";
207     }
208     else if(pmt_eq(msg->signal(), s_response_ntx_chan)) {
209       d_ntx_chan = pmt_to_long(pmt_nth(2, data));
210       if(verbose)
211         std::cout << "[qa_alloc_top] USRP tx channels: " 
212                   << d_ntx_chan << "\n";
213     }
214     else if(pmt_eq(msg->signal(), s_response_nrx_chan)) {
215       d_nrx_chan = pmt_to_long(pmt_nth(2, data));
216       if(verbose)
217         std::cout << "[qa_alloc_top] USRP rx channels: " 
218                   << d_nrx_chan << "\n";
219     }
220     else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) {
221       check_message(msg);
222     }
223     
224     d_nstatus++;
225
226     check_message(msg);
227
228     if(d_nstatus==d_nstatus_to_recv)
229       run_tests();
230   }
231 }
232
233 void
234 qa_alloc_top::check_message(mb_message_sptr msg)
235 {
236   pmt_t data = msg->data();
237   pmt_t event = msg->signal();
238
239   pmt_t expected = pmt_nth(0, data);
240   pmt_t status = pmt_nth(1, data);
241
242   pmt_t e_event = pmt_nth(0, expected);
243   pmt_t e_status = pmt_nth(1, expected);
244   
245   d_nrecvd++;
246
247
248   if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) {
249     if(verbose)
250       std::cout << "Got: " << status << " Expected: " << e_status << "\n";
251     shutdown_all(PMT_F);
252     return;
253   } else {
254     if(verbose)
255       std::cout << "[qa_alloc_top] Received expected response for message " 
256                 << d_nrecvd << " (" << event << ")\n";
257   }
258
259   if(d_nrecvd == d_nmsgs_to_recv)
260     shutdown_all(PMT_T);
261 }
262
263 REGISTER_MBLOCK_CLASS(qa_alloc_top);
264
265 // ----------------------------------------------------------------------------------------------
266
267 class qa_dealloc_top : public mb_mblock
268 {
269   mb_port_sptr d_tx;
270   mb_port_sptr d_rx;
271   mb_port_sptr d_cs;
272   
273   long d_max_capacity;
274   long d_ntx_chan, d_nrx_chan;
275
276   long d_nstatus;
277   long d_nstatus_to_recv;
278
279   long d_nalloc_to_recv;
280   long d_nalloc_recvd;
281
282   long d_ndealloc_to_recv;
283   long d_ndealloc_recvd;
284
285   std::vector<long> d_tx_chans;
286   std::vector<long> d_rx_chans;
287
288  public:
289   qa_dealloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
290   ~qa_dealloc_top();
291   void initial_transition();
292   void handle_message(mb_message_sptr msg);
293
294  protected:
295   void check_allocation(mb_message_sptr msg);
296   void check_deallocation(mb_message_sptr msg);
297   void allocate_max();
298   void deallocate_all();
299 };
300
301 qa_dealloc_top::qa_dealloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
302   : mb_mblock(runtime, instance_name, user_arg)
303
304   d_ndealloc_recvd=0;
305   d_ndealloc_to_recv = 0;
306   d_nalloc_recvd=0;
307   d_nalloc_to_recv = 0;   // auto-set
308   d_nstatus=0;
309   d_nstatus_to_recv = 4;
310   
311   d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
312   d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
313   d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
314
315   // Use the stub with the usrp_server
316   pmt_t usrp_server_dict = pmt_make_dict();
317   pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T);
318
319   // Test the TX side
320   define_component("server", "usrp_server", usrp_server_dict);
321   connect("self", "tx0", "server", "tx0");
322   connect("self", "rx0", "server", "rx0");
323   connect("self", "cs", "server", "cs");
324 }
325
326 qa_dealloc_top::~qa_dealloc_top(){}
327
328 void
329 qa_dealloc_top::initial_transition()
330 {
331
332   if(verbose)
333     std::cout << "[qa_dealloc_top] Initializing...\n";
334
335   // Retrieve information about the USRP, then run tests
336   d_cs->send(s_cmd_open, 
337              pmt_list2(pmt_list2(s_response_open,PMT_T), 
338              pmt_from_long(0)));
339
340   d_cs->send(s_cmd_max_capacity, 
341              pmt_list1(pmt_list2(s_response_max_capacity,PMT_T)));
342
343   d_cs->send(s_cmd_ntx_chan, 
344              pmt_list1(pmt_list2(s_response_ntx_chan,PMT_T)));
345
346   d_cs->send(s_cmd_nrx_chan, 
347              pmt_list1(pmt_list2(s_response_nrx_chan,PMT_T)));
348 }
349
350 void
351 qa_dealloc_top::allocate_max()
352 {
353
354   // Keep allocating until we hit the maximum number of channels
355   for(int i=0; i < d_ntx_chan; i++) {
356     d_tx->send(s_cmd_allocate_channel, 
357                pmt_list2(pmt_list2(s_response_allocate_channel,PMT_T),
358                pmt_from_long(1)));  // 1 byte is good enough
359
360     d_nalloc_to_recv++;
361   }
362
363   for(int i=0; i < d_nrx_chan; i++) {
364     d_rx->send(s_cmd_allocate_channel, 
365                pmt_list2(pmt_list2(s_response_allocate_channel,PMT_T), 
366                pmt_from_long(1)));
367
368     d_nalloc_to_recv++;
369   }
370
371 }
372
373 void
374 qa_dealloc_top::deallocate_all() {
375   
376   // Deallocate all of the channels that were allocated from allocate_max()
377   for(int i=0; i < (int)d_tx_chans.size(); i++) {
378
379     if(verbose)
380       std::cout << "[qa_dealloc_top] Trying to dealloc TX " 
381                 << d_tx_chans[i] << std::endl;
382
383     d_tx->send(s_cmd_deallocate_channel, 
384                pmt_list2(pmt_list2(s_response_deallocate_channel,PMT_T), 
385                pmt_from_long(d_tx_chans[i])));
386
387     d_ndealloc_to_recv++;
388   }
389
390   // Deallocate the RX side now
391   for(int i=0; i < (int)d_rx_chans.size(); i++) {
392
393     if(verbose)
394       std::cout << "[qa_dealloc_top] Trying to dealloc RX " 
395                 << d_tx_chans[i] << std::endl;
396
397     d_rx->send(s_cmd_deallocate_channel, 
398                pmt_list2(pmt_list2(s_response_deallocate_channel,PMT_T), 
399                pmt_from_long(d_rx_chans[i])));
400
401     d_ndealloc_to_recv++;
402   }
403
404   // Should get permission denied errors trying to re-dealloc the channels, as
405   // we no longer have permission to them after deallocating
406   for(int i=0; i < (int)d_tx_chans.size(); i++) {
407
408     d_tx->send(s_cmd_deallocate_channel, 
409                pmt_list2(pmt_list2(s_response_deallocate_channel,
410                              s_err_channel_permission_denied), 
411                          pmt_from_long(d_tx_chans[i])));
412
413     d_ndealloc_to_recv++;
414   }
415
416   // Same for RX
417   for(int i=0; i < (int)d_rx_chans.size(); i++) {
418
419     d_rx->send(s_cmd_deallocate_channel, 
420                pmt_list2(pmt_list2(s_response_deallocate_channel,
421                              s_err_channel_permission_denied), 
422                          pmt_from_long(d_rx_chans[i])));
423   
424     d_ndealloc_to_recv++;
425   }
426
427   // Try to deallocate a channel that doesn't exist on both sides, the last
428   // element in the vectors is the highest channel number, so we take that plus
429   // 1
430   d_ndealloc_to_recv+=2;
431   d_tx->send(s_cmd_deallocate_channel, 
432              pmt_list2(pmt_list2(s_response_deallocate_channel,
433                                  s_err_channel_invalid), 
434                        pmt_from_long(d_rx_chans.back()+1)));
435
436   d_rx->send(s_cmd_deallocate_channel, 
437              pmt_list2(pmt_list2(s_response_deallocate_channel,
438                                  s_err_channel_invalid), 
439                        pmt_from_long(d_rx_chans.back()+1)));
440
441
442   // The used capacity should be back to 0 now that we've deallocated everything
443   d_cs->send(s_cmd_current_capacity_allocation,
444              pmt_list1(pmt_list2(s_response_current_capacity_allocation,
445                                  PMT_T)));
446 }
447
448 void
449 qa_dealloc_top::handle_message(mb_message_sptr msg)
450 {
451   pmt_t data = msg->data();
452   pmt_t event = msg->signal();
453   
454   if(pmt_eq(event, pmt_intern("%shutdown")))
455     return;
456
457   pmt_t expected = pmt_nth(0, data);
458   pmt_t status = pmt_nth(1, data);
459
460   pmt_t e_event = pmt_nth(0, expected);
461   pmt_t e_status = pmt_nth(1, expected);
462
463   if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) {
464     if(verbose)
465       std::cout << "Got: " << status << " Expected: " << e_status << "\n";
466     shutdown_all(PMT_F);
467     return;
468   } else {
469     if(verbose)
470       std::cout << "[qa_alloc_top] Received expected response for message " 
471                 << d_ndealloc_recvd
472       << " (" << event << ")\n";
473   }
474
475   if (pmt_eq(msg->port_id(), d_tx->port_symbol())
476        || pmt_eq(msg->port_id(), d_rx->port_symbol())) {
477     
478     if(pmt_eq(msg->signal(), s_response_allocate_channel)) {
479       check_allocation(msg);
480     }
481     
482   }
483   
484   if (pmt_eq(msg->port_id(), d_cs->port_symbol())) {
485       
486     if(pmt_eq(msg->signal(), s_response_max_capacity)) {
487       d_max_capacity = pmt_to_long(pmt_nth(2, data));
488     }
489     else if(pmt_eq(msg->signal(), s_response_ntx_chan)) {
490       d_ntx_chan = pmt_to_long(pmt_nth(2, data));
491     }
492     else if(pmt_eq(msg->signal(), s_response_nrx_chan)) {
493       d_nrx_chan = pmt_to_long(pmt_nth(2, data));
494     }
495     else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) {
496       // the final command is a capacity check which should be 0, then we
497       // shutdown
498       pmt_t expected_result = pmt_from_long(0);
499       pmt_t result = pmt_nth(2, data);
500
501       if(pmt_eqv(expected_result, result)) {
502         shutdown_all(PMT_T);
503         return;
504       } else {
505         shutdown_all(PMT_F);
506         return;
507       }
508     }
509     
510     d_nstatus++;
511
512     if(d_nstatus==d_nstatus_to_recv)
513       allocate_max();
514   }
515 }
516
517
518 void
519 qa_dealloc_top::check_allocation(mb_message_sptr msg)
520 {
521   pmt_t data = msg->data();
522   pmt_t event = msg->signal();
523
524   pmt_t expected = pmt_nth(0, data);
525   pmt_t status = pmt_nth(1, data);
526   pmt_t channel = pmt_nth(2, data);
527
528   d_nalloc_recvd++;
529
530   if(!pmt_eqv(status, PMT_T)) {
531     shutdown_all(PMT_F);
532     return;
533   } else {
534     // store all of the allocate channel numbers
535     if(pmt_eq(msg->port_id(), d_tx->port_symbol()))
536       d_tx_chans.push_back(pmt_to_long(channel));
537     if(pmt_eq(msg->port_id(), d_rx->port_symbol()))
538       d_rx_chans.push_back(pmt_to_long(channel));
539   }
540
541   if(d_nalloc_recvd == d_nalloc_to_recv) {
542
543     if(verbose) {
544       std::cout << "[qa_dealloc_top] Allocated TX channels: ";
545       for(int i=0; i < (int)d_tx_chans.size(); i++)
546         std::cout << d_tx_chans[i] << " ";
547
548       std::cout << "\n[qa_dealloc_top] Allocated RX channels: ";
549       for(int i=0; i < (int)d_rx_chans.size(); i++)
550         std::cout << d_rx_chans[i] << " ";
551       std::cout << "\n";
552     }
553
554     deallocate_all();   // once we've allocated all of our channels, try to
555                         // dealloc them
556   }
557 }
558
559 REGISTER_MBLOCK_CLASS(qa_dealloc_top);
560
561 // ----------------------------------------------------------------------------------------------
562
563 class qa_open_close_top : public mb_mblock
564 {
565   mb_port_sptr d_cs;
566   
567   long d_max_capacity;
568
569   long d_nmsg_to_recv;
570   long d_nmsg_recvd;
571
572  public:
573   qa_open_close_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
574   ~qa_open_close_top();
575   void initial_transition();
576   void handle_message(mb_message_sptr msg);
577
578  protected:
579   void check_cs(mb_message_sptr msg);
580   void run_tests();
581 };
582
583 qa_open_close_top::qa_open_close_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
584   : mb_mblock(runtime, instance_name, user_arg)
585
586
587   d_nmsg_to_recv=7;
588   d_nmsg_recvd=0;
589   
590   d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
591
592   // Use the stub with the usrp_server
593   pmt_t usrp_server_dict = pmt_make_dict();
594   pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T);
595
596   // Test the TX side
597   define_component("server", "usrp_server", usrp_server_dict);
598   connect("self", "cs", "server", "cs");
599 }
600
601 qa_open_close_top::~qa_open_close_top(){}
602
603 void
604 qa_open_close_top::initial_transition()
605 {
606   run_tests();
607 }
608
609 void
610 qa_open_close_top::run_tests()
611 {
612   // std::cout << "[qa_open_close_top] Starting tests\n";
613
614   // A close before an open should fail
615   d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close, 
616                                               s_err_usrp_already_closed)));
617   
618   // Perform an open, and a second open which should fail
619   d_cs->send(s_cmd_open, 
620              pmt_list2(pmt_list2(s_response_open,PMT_T), 
621                        pmt_from_long(0)));
622
623   d_cs->send(s_cmd_open, 
624              pmt_list2(pmt_list2(s_response_open,
625                                  s_err_usrp_already_opened), 
626                        pmt_from_long(0)));
627
628   // A close should now be successful since the interface is open
629   d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T)));
630
631   // But, a second close should fail
632   d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,
633                                               s_err_usrp_already_closed)));
634   
635   // Just to be thorough, try an open and close again
636   d_cs->send(s_cmd_open, 
637              pmt_list2(pmt_list2(s_response_open,PMT_T), 
638                        pmt_from_long(0)));
639
640   d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T)));
641   
642 }
643
644
645 void
646 qa_open_close_top::handle_message(mb_message_sptr msg)
647 {
648   pmt_t data = msg->data();
649
650   if (pmt_eq(msg->port_id(), d_cs->port_symbol())) {
651       check_cs(msg);
652   }
653
654   d_nmsg_recvd++;
655
656   if(d_nmsg_to_recv == d_nmsg_recvd)
657     shutdown_all(PMT_T);
658 }
659
660 void
661 qa_open_close_top::check_cs(mb_message_sptr msg)
662 {
663   pmt_t data = msg->data();
664   pmt_t event = msg->signal();
665
666   pmt_t expected = pmt_nth(0, data);
667   pmt_t status = pmt_nth(1, data);
668
669   pmt_t e_event = pmt_nth(0, expected);
670   pmt_t e_status = pmt_nth(1, expected);
671
672   if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) {
673
674     if(verbose)
675       std::cout << "[qa_open_close_top] FAILED check_cs... Got: " << status
676                 << " Expected: " << e_status
677                 << " for event " << event << "\n";
678
679     shutdown_all(PMT_F);
680   } else {
681     if(verbose)
682       std::cout << "[qa_open_close_top] Received expected CS response (" 
683                 << event << ")\n";
684   }
685
686 }
687
688 REGISTER_MBLOCK_CLASS(qa_open_close_top);
689
690 // ----------------------------------------------------------------------------------------------
691
692 class qa_tx_top : public mb_mblock
693 {
694   mb_port_sptr d_tx;
695   mb_port_sptr d_rx;
696   mb_port_sptr d_cs;
697   
698   long d_max_capacity;
699   long d_ntx_chan, d_nrx_chan;
700
701   long d_tx_chan;
702   long d_rx_chan;
703
704   long d_nmsg_to_recv;
705   long d_nmsg_recvd;
706
707  public:
708   qa_tx_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
709   ~qa_tx_top();
710   void initial_transition();
711   void handle_message(mb_message_sptr msg);
712
713  protected:
714   void check_allocation(mb_message_sptr msg);
715   void check_deallocation(mb_message_sptr msg);
716   void check_xmit(mb_message_sptr msg);
717   void check_cs(mb_message_sptr msg);
718   void run_tests();
719 };
720
721 qa_tx_top::qa_tx_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
722   : mb_mblock(runtime, instance_name, user_arg)
723
724
725   d_nmsg_to_recv=10;
726   d_nmsg_recvd=0;
727   
728   d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
729   d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
730   d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
731
732   // Use the stub with the usrp_server
733   pmt_t usrp_server_dict = pmt_make_dict();
734   pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T);
735
736   // Test the TX side
737   define_component("server", "usrp_server", usrp_server_dict);
738   connect("self", "tx0", "server", "tx0");
739   connect("self", "rx0", "server", "rx0");
740   connect("self", "cs", "server", "cs");
741 }
742
743 qa_tx_top::~qa_tx_top(){}
744
745 void
746 qa_tx_top::initial_transition()
747 {
748   run_tests();
749 }
750
751 void
752 qa_tx_top::run_tests()
753 {
754   if(verbose)
755    std::cout << "[qa_tx_top] Starting tests\n";
756
757   // A transmit before an open should fail
758   d_tx->send(s_cmd_xmit_raw_frame, 
759              pmt_list4(pmt_list2(s_response_xmit_raw_frame, 
760                                  s_err_usrp_not_opened), 
761                        pmt_from_long(0), 
762                        pmt_make_u32vector(transport_pkt::max_payload()/4, 0),
763                        pmt_from_long(0)));
764   
765   // Now open
766   d_cs->send(s_cmd_open, 
767              pmt_list2(pmt_list2(s_response_open,PMT_T), 
768                        pmt_from_long(0)));
769
770   // Try to transmit on a channel that we have no allocation for
771   d_tx->send(s_cmd_xmit_raw_frame, 
772              pmt_list4(pmt_list2(s_response_xmit_raw_frame,
773                                  s_err_channel_permission_denied), 
774                        pmt_from_long(0), 
775                        pmt_make_u32vector(transport_pkt::max_payload()/4, 0), 
776                        pmt_from_long(0)));
777
778   // Get a channel allocation and send on it, we assume 0 (FIXME) until 'defer'
779   // is implemented for simplicity
780   d_tx->send(s_cmd_allocate_channel, 
781              pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T), 
782                        pmt_from_long(1)));
783
784   d_tx->send(s_cmd_xmit_raw_frame, 
785              pmt_list4(pmt_list2(s_response_xmit_raw_frame, PMT_T), 
786                        pmt_from_long(0), 
787                        pmt_make_u32vector(transport_pkt::max_payload()/4, 0), 
788                        pmt_from_long(0)));
789
790   // Close should be successful
791   d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T)));
792
793   // After closing, a new transmit raw frame should fail again
794   d_tx->send(s_cmd_xmit_raw_frame, 
795              pmt_list4(pmt_list2(s_response_xmit_raw_frame, 
796                                  s_err_usrp_not_opened), 
797                        pmt_from_long(0), 
798                        pmt_make_u32vector(transport_pkt::max_payload()/4, 0), 
799                        pmt_from_long(0)));
800
801   // Reopen and retry before getting an allocation, the first xmit should fail,
802   // after we allocate it should work again
803   d_cs->send(s_cmd_open, 
804              pmt_list2(pmt_list2(s_response_open, PMT_T), 
805                        pmt_from_long(0)));
806
807   d_tx->send(s_cmd_xmit_raw_frame, 
808              pmt_list4(pmt_list2(s_response_xmit_raw_frame,
809                                  s_err_channel_permission_denied), 
810                        pmt_from_long(0), 
811                        pmt_make_u32vector(transport_pkt::max_payload()/4, 0), 
812                        pmt_from_long(0)));
813
814   d_tx->send(s_cmd_allocate_channel, 
815              pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T), 
816                        pmt_from_long(1)));
817
818   d_tx->send(s_cmd_xmit_raw_frame, 
819              pmt_list4(pmt_list2(s_response_xmit_raw_frame,PMT_T), 
820                        pmt_from_long(0), 
821                        pmt_make_u32vector(transport_pkt::max_payload()/4, 0), 
822                        pmt_from_long(0)));
823
824   // A final close which should be successful
825   d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T)));
826   
827 }
828
829
830 void
831 qa_tx_top::handle_message(mb_message_sptr msg)
832 {
833   pmt_t data = msg->data();
834   pmt_t event = msg->signal();
835   
836   if(pmt_eq(event, pmt_intern("%shutdown")))
837     return;
838
839   pmt_t expected = pmt_nth(0, data);
840   pmt_t status = pmt_nth(1, data);
841
842   pmt_t e_event = pmt_nth(0, expected);
843   pmt_t e_status = pmt_nth(1, expected);
844
845   if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) {
846     if(verbose)
847       std::cout << "[qa_xmit_top] Got: " << status 
848                 << " Expected: " << e_status 
849                 << "For signal: " << event << "\n";
850     shutdown_all(PMT_F);
851     return;
852   } else {
853     if(verbose)
854       std::cout << "[qa_xmit_top] Received expected response for message " 
855                 << d_nmsg_recvd
856       << " (" << event << ")\n";
857   }
858
859   if (pmt_eq(msg->port_id(), d_tx->port_symbol())
860        || pmt_eq(msg->port_id(), d_rx->port_symbol())) {
861     
862     if(pmt_eq(msg->signal(), s_response_allocate_channel)) 
863       check_allocation(msg);
864     
865   }
866   
867   d_nmsg_recvd++;
868
869   if(d_nmsg_to_recv == d_nmsg_recvd){
870     shutdown_all(PMT_T);
871     return;
872   }
873 }
874
875 void
876 qa_tx_top::check_allocation(mb_message_sptr msg)
877 {
878   pmt_t data = msg->data();
879   pmt_t event = msg->signal();
880   
881   pmt_t expected = pmt_nth(0, data);
882   pmt_t status = pmt_nth(1, data);
883   pmt_t channel = pmt_nth(2, data);
884
885   if(pmt_eqv(status, PMT_T)) {
886     // store all of the allocate channel numbers
887     if(pmt_eq(msg->port_id(), d_tx->port_symbol()))
888       d_tx_chan = pmt_to_long(channel);
889     if(pmt_eq(msg->port_id(), d_rx->port_symbol()))
890       d_rx_chan = pmt_to_long(channel);
891   }
892 }
893
894 REGISTER_MBLOCK_CLASS(qa_tx_top);
895
896 // ----------------------------------------------------------------------------------------------
897
898 class qa_rx_top : public mb_mblock
899 {
900   mb_port_sptr d_rx;
901   mb_port_sptr d_cs;
902   
903   long d_max_capacity;
904   long d_ntx_chan, d_nrx_chan;
905
906   long d_rx_chan;
907
908   bool d_got_response_recv;
909
910   mb_time d_t0;
911   double d_delta_t;
912
913  public:
914   qa_rx_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
915   ~qa_rx_top();
916   void initial_transition();
917   void handle_message(mb_message_sptr msg);
918
919  protected:
920   void check_allocation(mb_message_sptr msg);
921   void check_deallocation(mb_message_sptr msg);
922   void check_xmit(mb_message_sptr msg);
923   void check_cs(mb_message_sptr msg);
924   void run_tests();
925 };
926
927 qa_rx_top::qa_rx_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
928   : mb_mblock(runtime, instance_name, user_arg),
929     d_got_response_recv(false)
930
931
932   d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
933   d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
934
935   // Use the stub with the usrp_server
936   pmt_t usrp_dict = pmt_make_dict();
937   // Set TX and RX interpolations
938   pmt_dict_set(usrp_dict,
939                pmt_intern("decim-rx"),
940                pmt_from_long(128));
941   pmt_dict_set(usrp_dict, pmt_intern("fake-usrp"), PMT_T);
942
943   // Test the TX side
944   define_component("server", "usrp_server", usrp_dict);
945   connect("self", "rx0", "server", "rx0");
946   connect("self", "cs", "server", "cs");
947 }
948
949 qa_rx_top::~qa_rx_top(){}
950
951 void
952 qa_rx_top::initial_transition()
953 {
954   run_tests();
955 }
956
957 void
958 qa_rx_top::run_tests()
959 {
960   if(verbose)
961     std::cout << "[qa_rx_top] Starting tests\n";
962
963   d_cs->send(s_cmd_open, pmt_list2(pmt_list2(s_response_open,PMT_T), pmt_from_long(0)));
964
965   d_rx->send(s_cmd_allocate_channel, 
966              pmt_list2(pmt_list2(s_response_allocate_channel,PMT_T), 
967              pmt_from_long(1)));
968
969   d_rx->send(s_cmd_start_recv_raw_samples, 
970              pmt_list2(PMT_NIL, 
971                        pmt_from_long(0)));
972
973   // Schedule a small timeout in which we expect to have received at least one
974   // packet worth of samples from the stub
975   d_t0 = mb_time::time();
976   schedule_one_shot_timeout(d_t0 + 0.01, PMT_NIL);
977 }
978
979
980 void
981 qa_rx_top::handle_message(mb_message_sptr msg)
982 {
983   pmt_t data = msg->data();
984   pmt_t event = msg->signal();
985   
986   if(pmt_eq(event, pmt_intern("%shutdown")))
987     return;
988   
989   pmt_t expected = pmt_nth(0, data);
990   pmt_t status = pmt_nth(1, data);
991
992   // If we get a timeout we shutdown
993   if(pmt_eq(event, s_timeout)) {
994     if(verbose)
995       std::cout << "[qa_rx_top] Got timeout\n";
996     d_rx->send(s_cmd_stop_recv_raw_samples, 
997                pmt_list2(PMT_NIL, 
998                          pmt_from_long(0)));
999
1000     d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T)));
1001     return;
1002   }
1003   
1004   // For testing RX, an invocation handle is not generated by the stub,
1005   // therefore the same approach for testing is not used.  We simply
1006   // expect all responses to be true.
1007   if(pmt_eq(event, s_response_recv_raw_samples)) {
1008     if(pmt_eqv(status, PMT_T)) {
1009
1010       if(verbose)
1011         std::cout << "[qa_rx_top] Received expected response for message " 
1012                   << " (" << event << ")\n";
1013
1014       // All we want is 1 response receive!  Can't guarantee exact numbers
1015       d_got_response_recv = true;
1016     }
1017     else {
1018       if(verbose)
1019         std::cout << "Got: " << status << " Expected: " << PMT_T << "\n";
1020       shutdown_all(PMT_F);
1021     }
1022     return;
1023   }
1024
1025   pmt_t e_event = pmt_nth(0, expected);
1026   pmt_t e_status = pmt_nth(1, expected);
1027
1028   if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) {
1029    if(verbose)
1030       std::cout << "Got: " << status << " Expected: " << e_status << "\n";
1031     shutdown_all(PMT_F);
1032     return;
1033   } else {
1034     if(verbose)
1035       std::cout << "[qa_rx_top] Received expected response for message " 
1036                 << " (" << event << ")\n";
1037   }
1038
1039   if (pmt_eq(msg->port_id(), d_rx->port_symbol())) {
1040     
1041     if(pmt_eq(msg->signal(), s_response_allocate_channel)) 
1042       check_allocation(msg);
1043
1044   }
1045
1046   // We stop when we get a close, we are successful if we
1047   // got a response from recv, fail if we never got a recv response
1048   if(pmt_eq(msg->signal(), s_response_close)) {
1049     
1050     if(d_got_response_recv) {
1051       shutdown_all(PMT_T);
1052       return;
1053     }
1054     else {
1055       shutdown_all(PMT_F);
1056       if(verbose)
1057         std::cout << "[qa_rx_top] No response message before close\n";
1058       return;
1059     }
1060   }
1061 }
1062
1063
1064 void
1065 qa_rx_top::check_allocation(mb_message_sptr msg)
1066 {
1067   pmt_t data = msg->data();
1068   pmt_t event = msg->signal();
1069   
1070   pmt_t expected = pmt_nth(0, data);
1071   pmt_t status = pmt_nth(1, data);
1072   pmt_t channel = pmt_nth(2, data);
1073
1074   if(pmt_eqv(status, PMT_T)) {
1075     // store all of the allocate channel numbers
1076     if(pmt_eq(msg->port_id(), d_rx->port_symbol()))
1077       d_rx_chan = pmt_to_long(channel);
1078   }
1079 }
1080
1081 REGISTER_MBLOCK_CLASS(qa_rx_top);
1082
1083 // ----------------------------------------------------------------------------------------------
1084
1085 class qa_rid_top : public mb_mblock
1086 {
1087   mb_port_sptr d_tx;
1088   mb_port_sptr d_rx;
1089   mb_port_sptr d_cs;
1090
1091   long d_npongs;
1092   long d_tcycles;
1093   long d_cycles;
1094   long d_max_rid;
1095   
1096   mb_time d_t0;
1097   double d_delta_t;
1098
1099  public:
1100   qa_rid_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
1101   ~qa_rid_top();
1102   void initial_transition();
1103   void handle_message(mb_message_sptr msg);
1104
1105  protected:
1106   void run_tests();
1107   void send_max_pings();
1108 };
1109
1110 qa_rid_top::qa_rid_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
1111   : mb_mblock(runtime, instance_name, user_arg)
1112
1113   d_npongs = 0;
1114   d_tcycles = 3;
1115   d_cycles = d_tcycles;
1116   d_max_rid = usrp_server::D_MAX_RID;
1117   d_delta_t = 0.1;
1118
1119
1120   d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
1121   d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
1122   d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
1123  
1124   // Use the stub with the usrp_server
1125   pmt_t usrp_server_dict = pmt_make_dict();
1126   pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T);
1127
1128   // Test the TX side
1129   define_component("server", "usrp_server", usrp_server_dict);
1130   connect("self", "tx0", "server", "tx0");
1131   connect("self", "rx0", "server", "rx0");
1132   connect("self", "cs", "server", "cs");
1133
1134 }
1135
1136 qa_rid_top::~qa_rid_top(){}
1137
1138 void
1139 qa_rid_top::initial_transition()
1140 {
1141   run_tests();
1142 }
1143
1144 void
1145 qa_rid_top::run_tests()
1146 {
1147   if(verbose)
1148     std::cout << "[qa_rid_top] Starting tests...\n";
1149   
1150   // Retrieve information about the USRP, then run tests
1151   d_cs->send(s_cmd_open, 
1152              pmt_list2(pmt_list2(s_response_open, PMT_T), 
1153              pmt_from_long(0)));
1154
1155   // should be able to allocate 1 byte
1156   d_tx->send(s_cmd_allocate_channel, 
1157              pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T), 
1158                        pmt_from_long(1)));
1159   
1160   d_rx->send(s_cmd_allocate_channel, 
1161              pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T), 
1162                        pmt_from_long(1)));
1163   
1164   // Need to start receiving to read from the USRP to get C/S responses
1165   d_rx->send(s_cmd_start_recv_raw_samples, 
1166              pmt_list2(PMT_NIL, 
1167                        pmt_from_long(0)));
1168
1169   // Build a subpacket of MAX_RID pings and wait a small amount for all of the
1170   // responses and fire off another MAX_RID.  If MAX_RID*2 responses are
1171   // received, the RID recycling is working correctly.
1172   // Schedule a timer in which we expect to have received all of the responses,
1173   // which will send off another MAX_RID worth.
1174   send_max_pings();
1175   d_t0 = mb_time::time();
1176   schedule_one_shot_timeout(d_t0 + d_delta_t, PMT_NIL);
1177 }
1178
1179 void
1180 qa_rid_top::send_max_pings()
1181 {
1182   pmt_t ping = pmt_list2(s_op_ping_fixed,
1183                          pmt_list2(pmt_from_long(0),
1184                                    pmt_from_long(0)));
1185
1186   pmt_t sub_packets = PMT_NIL;
1187
1188   for(int i=0; i<d_max_rid; i++) 
1189     sub_packets = pmt_list_add(sub_packets, ping);
1190
1191   d_tx->send(s_cmd_to_control_channel,
1192              pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
1193                        sub_packets));
1194 }
1195
1196 void
1197 qa_rid_top::handle_message(mb_message_sptr msg)
1198 {
1199   pmt_t data = msg->data();
1200   pmt_t event = msg->signal();
1201
1202   // If we get a timeout we ensure we got a maximum RID number of responses.
1203   if(pmt_eq(event, s_timeout)) {
1204     if(verbose)
1205       std::cout << "[qa_rid_top] Got timeout, received so far: " 
1206                 << d_npongs << "\n";
1207
1208     d_cycles--;
1209     
1210     if(d_cycles==0 && d_npongs == d_max_rid*d_tcycles) {
1211       shutdown_all(PMT_T);
1212     }
1213     else if(d_cycles==0) {
1214
1215       std::cout << "[qa_rid_top] d_npongs: " << d_npongs
1216                 << " expected: " << d_max_rid*d_tcycles
1217                 << std::endl;
1218
1219       shutdown_all(PMT_F);
1220     }
1221     else {
1222       send_max_pings();
1223       d_t0 = mb_time::time();
1224       schedule_one_shot_timeout(d_t0 + d_delta_t, PMT_NIL);
1225     }
1226
1227   }
1228   else if(pmt_eq(event, s_response_from_control_channel))
1229   {
1230     d_npongs++;
1231   }
1232
1233 }
1234
1235 REGISTER_MBLOCK_CLASS(qa_rid_top);
1236
1237
1238 // ----------------------------------------------------------------------------------------------
1239
1240 class qa_cs_top : public mb_mblock
1241 {
1242   mb_port_sptr d_tx;
1243   mb_port_sptr d_rx;
1244   mb_port_sptr d_cs;
1245
1246   long d_nmsgs_to_recv;
1247   long d_nrecvd;
1248
1249   long d_max_capacity;
1250   long d_ntx_chan, d_nrx_chan;
1251
1252   long d_nstatus;
1253   long d_nstatus_to_recv;
1254
1255  public:
1256   qa_cs_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
1257   ~qa_cs_top();
1258   void initial_transition();
1259   void handle_message(mb_message_sptr msg);
1260
1261  protected:
1262   void check_message(mb_message_sptr msg);
1263   void run_tests();
1264 };
1265
1266 qa_cs_top::qa_cs_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
1267   : mb_mblock(runtime, instance_name, user_arg)
1268
1269   d_nrecvd=0;
1270   d_nmsgs_to_recv = 8;
1271   d_nstatus=0;
1272   d_nstatus_to_recv = 50;
1273   
1274   d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
1275   d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
1276   d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
1277  
1278   // Use the stub with the usrp_server
1279   pmt_t usrp_server_dict = pmt_make_dict();
1280   pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T);
1281
1282   // Test the TX side
1283   define_component("server", "usrp_server", usrp_server_dict);
1284   connect("self", "tx0", "server", "tx0");
1285   connect("self", "rx0", "server", "rx0");
1286   connect("self", "cs", "server", "cs");
1287
1288 }
1289
1290 qa_cs_top::~qa_cs_top(){}
1291
1292 void
1293 qa_cs_top::initial_transition()
1294 {
1295   run_tests();
1296 }
1297
1298 void
1299 qa_cs_top::run_tests()
1300 {
1301   if(verbose)
1302     std::cout << "[qa_cs_top] Starting tests...\n";
1303   
1304   // Retrieve information about the USRP, then run tests
1305   d_cs->send(s_cmd_open, 
1306              pmt_list2(pmt_list2(s_response_open, PMT_T), 
1307              pmt_from_long(0)));
1308
1309   // should be able to allocate 1 byte
1310   d_tx->send(s_cmd_allocate_channel, 
1311              pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T), 
1312                        pmt_from_long(1)));
1313   
1314   d_rx->send(s_cmd_allocate_channel, 
1315              pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T), 
1316                        pmt_from_long(1)));
1317   
1318   // Need to start receiving to read from the USRP to get C/S responses
1319   d_rx->send(s_cmd_start_recv_raw_samples, 
1320              pmt_list2(PMT_NIL, 
1321                        pmt_from_long(0)));
1322
1323   d_tx->send(s_cmd_to_control_channel,
1324              pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
1325                        pmt_list1(
1326                             pmt_list2(s_op_ping_fixed, 
1327                                       pmt_list2(pmt_from_long(3), 
1328                                       pmt_from_long(0))))));
1329   
1330   d_tx->send(s_cmd_to_control_channel,
1331              pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
1332                        pmt_list1(
1333                             pmt_list2(s_op_write_reg, 
1334                                       pmt_list2(
1335                                       pmt_from_long(0x3), 
1336                                       pmt_from_long(0x4))))));
1337   
1338   d_tx->send(s_cmd_to_control_channel,
1339              pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
1340                        pmt_list1(
1341                             pmt_list2(s_op_write_reg_masked, 
1342                                       pmt_list3(
1343                                       pmt_from_long(0x3), 
1344                                       pmt_from_long(0x4),
1345                                       pmt_from_long(0x5))))));
1346   
1347   d_tx->send(s_cmd_to_control_channel,
1348              pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
1349                        pmt_list1(
1350                             pmt_list2(s_op_read_reg, 
1351                                       pmt_list2(pmt_from_long(0), 
1352                                       pmt_from_long(0x6))))));
1353   
1354   d_tx->send(s_cmd_to_control_channel,
1355              pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
1356                        pmt_list1(
1357                             pmt_list2(s_op_delay, 
1358                                       pmt_list1(pmt_from_long(0x7))))));
1359
1360   pmt_t subpackets = pmt_list5(
1361                         pmt_list2(s_op_ping_fixed, pmt_list2(pmt_from_long(0), pmt_from_long(0))),
1362                         pmt_list2(s_op_delay, pmt_list1(pmt_from_long(0x7))),
1363                         pmt_list2(s_op_write_reg_masked, pmt_list3(pmt_from_long(3),
1364                                                                    pmt_from_long(4),
1365                                                                    pmt_from_long(5))),
1366                         pmt_list2(s_op_write_reg, pmt_list2(pmt_from_long(3),
1367                                                             pmt_from_long(4))),
1368                         pmt_list2(s_op_read_reg, pmt_list2(pmt_from_long(0),
1369                                                            pmt_from_long(6)))
1370                      );
1371
1372   d_tx->send(s_cmd_to_control_channel, 
1373               pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
1374                         subpackets));
1375
1376   pmt_t i2c_data = pmt_make_u8vector(8, 0xff);
1377
1378   subpackets = pmt_list2(
1379                         pmt_list2(s_op_i2c_write, 
1380                                   pmt_list2(pmt_from_long(8), i2c_data)),
1381                         pmt_list2(s_op_i2c_read,
1382                                   pmt_list3(pmt_from_long(0), pmt_from_long(9), pmt_from_long(1)))
1383
1384                      );
1385
1386   d_tx->send(s_cmd_to_control_channel, 
1387               pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
1388                         subpackets));
1389   
1390 }
1391
1392 void
1393 qa_cs_top::handle_message(mb_message_sptr msg)
1394 {
1395   pmt_t data = msg->data();
1396
1397   if ((pmt_eq(msg->port_id(), d_tx->port_symbol())
1398        || pmt_eq(msg->port_id(), d_rx->port_symbol()))
1399        && pmt_eq(msg->signal(), s_response_allocate_channel))
1400     check_message(msg);
1401
1402   if (pmt_eq(msg->port_id(), d_tx->port_symbol())
1403       && pmt_eq(msg->signal(), s_response_from_control_channel))
1404     check_message(msg);
1405   
1406   if (pmt_eq(msg->port_id(), d_cs->port_symbol())) {
1407       
1408     if(pmt_eq(msg->signal(), s_response_max_capacity)) {
1409       d_max_capacity = pmt_to_long(pmt_nth(2, data));
1410       if(verbose)
1411         std::cout << "[qa_cs_top] USRP has max capacity of " 
1412                   << d_max_capacity << "\n";
1413     }
1414     else if(pmt_eq(msg->signal(), s_response_ntx_chan)) {
1415       d_ntx_chan = pmt_to_long(pmt_nth(2, data));
1416       if(verbose)
1417         std::cout << "[qa_cs_top] USRP tx channels: " 
1418                   << d_ntx_chan << "\n";
1419     }
1420     else if(pmt_eq(msg->signal(), s_response_nrx_chan)) {
1421       d_nrx_chan = pmt_to_long(pmt_nth(2, data));
1422       if(verbose)
1423         std::cout << "[qa_cs_top] USRP rx channels: " 
1424                   << d_nrx_chan << "\n";
1425     }
1426     else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) {
1427       check_message(msg);
1428     }
1429     
1430     d_nstatus++;
1431
1432     check_message(msg);
1433
1434     if(d_nstatus==d_nstatus_to_recv)
1435       run_tests();
1436   }
1437 }
1438
1439 void
1440 qa_cs_top::check_message(mb_message_sptr msg)
1441 {
1442   pmt_t data = msg->data();
1443   pmt_t event = msg->signal();
1444
1445   pmt_t expected = pmt_nth(0, data);
1446   pmt_t status = pmt_nth(1, data);
1447
1448   pmt_t e_event = pmt_nth(0, expected);
1449   pmt_t e_status = pmt_nth(1, expected);
1450   
1451   d_nrecvd++;
1452
1453
1454   if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) {
1455     if(verbose)
1456       std::cout << "[qa_cs_top] Got: " << status << " Expected: " << e_status << "\n";
1457     shutdown_all(PMT_F);
1458     return;
1459   } else {
1460     if(verbose)
1461       std::cout << "[qa_cs_top] Received expected response for message " 
1462                 << d_nrecvd << " (" << event << ")\n";
1463   }
1464
1465   if(d_nrecvd == d_nmsgs_to_recv)
1466     shutdown_all(PMT_T);
1467 }
1468
1469 REGISTER_MBLOCK_CLASS(qa_cs_top);
1470
1471 // ----------------------------------------------------------------------------------------------
1472
1473 void 
1474 qa_inband_usrp_server::test_open_close()
1475 {
1476   mb_runtime_sptr rt = mb_make_runtime();
1477   pmt_t result = PMT_T;
1478
1479   // std::cout << "\n\n----------------------------\n";
1480   // std::cout << "    RUNNING OPEN/CLOSE TESTS  \n";
1481
1482   rt->run("top", "qa_open_close_top", PMT_F, &result);
1483
1484   CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
1485 }
1486
1487 void 
1488 qa_inband_usrp_server::test_chan_allocation()
1489 {
1490   mb_runtime_sptr rt = mb_make_runtime();
1491   pmt_t result = PMT_T;
1492
1493   // std::cout << "\n\n----------------------------\n";
1494   // std::cout << "    RUNNING ALLOCATION TESTS  \n";
1495
1496   rt->run("qa_alloc_top", "qa_alloc_top", PMT_F, &result);
1497   
1498   CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
1499 }
1500
1501 void
1502 qa_inband_usrp_server::test_chan_deallocation()
1503 {
1504   mb_runtime_sptr rt = mb_make_runtime();
1505   pmt_t result = PMT_T;
1506
1507   // std::cout << "\n\n----------------------------\n";
1508   // std::cout << "  RUNNING DEALLOCATION TESTS  \n";
1509
1510   rt->run("qa_dealloc_top", "qa_dealloc_top", PMT_F, &result);
1511   
1512   CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
1513 }
1514
1515 void
1516 qa_inband_usrp_server::test_tx()
1517 {
1518   mb_runtime_sptr rt = mb_make_runtime();
1519   pmt_t result = PMT_T;
1520
1521   // std::cout << "\n\n-----------------\n";
1522   // std::cout << "  RUNNING TX TESTS  \n";
1523
1524   rt->run("top", "qa_tx_top", PMT_F, &result);
1525   
1526   CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
1527 }
1528
1529 void
1530 qa_inband_usrp_server::test_rx()
1531 {
1532   mb_runtime_sptr rt = mb_make_runtime();
1533   pmt_t result = PMT_T;
1534
1535   // std::cout << "\n\n-----------------\n";
1536   // std::cout << "  RUNNING RX TESTS  \n";
1537
1538   rt->run("top", "qa_rx_top", PMT_F, &result);
1539   
1540   CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
1541 }
1542
1543 void
1544 qa_inband_usrp_server::test_cs()
1545 {
1546   // FIXME This test is disabled because it hangs with the change to use usrp_standard_*_sptr's
1547   return;
1548
1549   mb_runtime_sptr rt = mb_make_runtime();
1550   pmt_t result = PMT_T;
1551
1552   // std::cout << "\n\n-----------------\n";
1553   // std::cout << "  RUNNING CS TESTS  \n";
1554
1555   rt->run("top", "qa_cs_top", PMT_F, &result);
1556   
1557   CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
1558 }
1559
1560 void
1561 qa_inband_usrp_server::test_rid()
1562 {
1563   // FIXME This test is disabled because it hangs with the change to use usrp_standard_*_sptr's
1564   return;
1565
1566   mb_runtime_sptr rt = mb_make_runtime();
1567   pmt_t result = PMT_T;
1568
1569   // std::cout << "\n\n-----------------\n";
1570   // std::cout << "  RUNNING RID TESTS  \n";
1571
1572   rt->run("top", "qa_rid_top", PMT_F, &result);
1573   
1574   CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
1575 }