22adc3e945618192a359af2f268e61d65ab5a5d9
[carl9170fw.git] / tools / carlu / src / main.c
1 /*
2  * carl9170user - userspace testing utility for ar9170 devices
3  *
4  * main program routine
5  *
6  * Copyright 2009, 2010 Christian Lamparter <chunkeey@googlemail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <stdbool.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include "SDL.h"
34 #include <SDL_version.h>
35
36 #include "debug.h"
37 #include "carlu.h"
38 #include "usb.h"
39 #include "frame.h"
40 #include "test.h"
41 #include "cmd.h"
42
43 void *carlu_alloc_driver(size_t size)
44 {
45         unsigned int i;
46         struct carlu *ar;
47
48         if (size < sizeof(*ar)) {
49                 err("bogus driver context request.");
50                 return NULL;
51         }
52
53         ar = malloc(size);
54         if (ar == NULL) {
55                 err("failed to alloc driver context.");
56                 return NULL;
57         }
58         memset(ar, 0, size);
59
60         for (i = 0; i < __AR9170_NUM_TXQ; i++)
61                 frame_queue_init(&ar->tx_sent_queue[i]);
62         ar->resp_lock = SDL_CreateMutex();
63         ar->mem_lock = SDL_CreateMutex();
64         ar->resp_pend = SDL_CreateCond();
65         ar->tx_pending = 0;
66         return ar;
67 }
68
69 void carlu_free_driver(struct carlu *ar)
70 {
71         unsigned int i;
72
73         dbg("destroy driver struct.\n");
74         SDL_DestroyMutex(ar->resp_lock);
75         SDL_DestroyMutex(ar->mem_lock);
76         SDL_DestroyCond(ar->resp_pend);
77
78         for (i = 0; i < __AR9170_NUM_TXQ; i++)
79                 frame_queue_kill(&ar->tx_sent_queue[i]);
80
81         free(ar);
82 }
83
84 static int carlu_init()
85 {
86         struct SDL_version compiled;
87         int ret;
88
89         SDL_VERSION(&compiled);
90         dbg("=== SDL %d.%d.%d ===\n", compiled.major, compiled.minor, compiled.patch);
91
92         ret = SDL_Init(SDL_INIT_TIMER);
93         if (ret != 0) {
94                 err("Unable to initialize SDL: (%s)\n", SDL_GetError());
95                 return EXIT_FAILURE;
96         }
97
98         return usb_init();
99 }
100
101 static void carlu_exit()
102 {
103         SDL_Quit();
104         usb_exit();
105 }
106
107 static int carlu_dump_eeprom(void)
108 {
109         struct carlu *carl = NULL;
110         uint8_t data[8192] = { 0 };
111         int err;
112
113         err = carlu_init();
114         if (err)
115                 goto out;
116
117         carl = carlusb_probe();
118         if (IS_ERR_OR_NULL(carl)) {
119                 err = PTR_ERR(carl);
120                 goto out;
121         }
122
123         err = carlu_cmd_mem_dump(carl, 0, sizeof(data), &data);
124         if (err)
125                 goto out_close;
126
127         print_hex_dump_bytes(INFO, "EEPROM:", data, sizeof(data));
128
129 out_close:
130         carlusb_close(carl);
131
132 out:
133         carlu_exit();
134         return err ? EXIT_FAILURE : EXIT_SUCCESS;
135 }
136
137 static int carlu_run_loop_test(void)
138 {
139         struct carlu *carl;
140         int err;
141
142         err = carlu_init();
143         if (err)
144                 return EXIT_FAILURE;
145
146         carl = carlusb_probe();
147         if (IS_ERR_OR_NULL(carl)) {
148                 err = PTR_ERR(carl);
149                 goto out;
150         }
151
152         carlu_cmd_write_mem(carl, AR9170_MAC_REG_BCN_PERIOD, 0xFFFFFFFF);
153         carlu_cmd_write_mem(carl, AR9170_MAC_REG_PRETBTT, 0xFFFFFFFF);
154
155         /* different payload test */
156         carlu_loopback_test(carl, 9000, 1000, 1566, 1566);
157         carlusb_close(carl);
158
159 out:
160         return err ? EXIT_FAILURE : EXIT_SUCCESS;
161 }
162
163 static int carlu_probe_all(void)
164 {
165         struct carlu *carl[32] = { 0 };
166         unsigned int devs;
167         int ret;
168
169         ret = carlu_init();
170         if (ret)
171                 return EXIT_FAILURE;
172
173         for (devs = 0; devs < ARRAY_SIZE(carl); devs++) {
174                 carl[devs] = carlusb_probe();
175                 if (IS_ERR_OR_NULL(carl[devs]))
176                         break;
177         }
178
179         info("Found %d devices\n", devs);
180
181         for (; devs > 0; devs--)
182                 carlusb_close(carl[devs - 1]);
183
184         carlu_exit();
185         return EXIT_SUCCESS;
186 }
187
188 struct menu_struct {
189         char option;
190         unsigned int parameters;
191         int (*function)(void);
192         char help_text[80];
193 };
194
195 #define MENU_ITEM(op, func, helpme)     \
196         {                               \
197                 .option = op,           \
198                 .parameters = 0,        \
199                 .function = func,       \
200                 .help_text = helpme,    \
201         }
202
203 static int show_help(void);
204
205 static const struct menu_struct menu[] = {
206         [0] = MENU_ITEM('h', show_help, "shows this useless help message text."),       /* keep this entry at 0! */
207               MENU_ITEM('e', carlu_dump_eeprom, "hexdumps eeprom content to stdout."),
208               MENU_ITEM('l', carlusb_print_known_devices, "list of all known ar9170 usb devices."),
209               MENU_ITEM('p', carlu_probe_all, "probe all possible devices."),
210               MENU_ITEM('t', carlu_run_loop_test, "run tx/rx test."),
211 };
212
213 static int show_help(void)
214 {
215         unsigned int i;
216         char parameters[ARRAY_SIZE(menu) + 1];
217
218         for (i = 0; i < ARRAY_SIZE(menu); i++)
219                 parameters[i] = menu[i].option;
220
221         parameters[ARRAY_SIZE(menu)] = '\0';
222
223         info("usage: ar9170user -[%s]\n", parameters);
224
225         for (i = 0; i < ARRAY_SIZE(menu); i++)
226                 info("\t-%c\t%s\n", menu[i].option, menu[i].help_text);
227
228         return EXIT_FAILURE;
229 }
230
231 static int select_menu_item(const char arg)
232 {
233         unsigned int i;
234
235         for (i = ARRAY_SIZE(menu) - 1; i != 0; i--) {
236                 if (arg == menu[i].option)
237                         break;
238         }
239
240         return menu[i].function();
241 }
242
243 int main(int argc, char *argv[])
244 {
245         init_debug();
246
247         if (argc != 2 || strlen(argv[1]) != 2 || argv[1][0] != '-')
248                 return show_help();
249
250         return select_menu_item(argv[1][1]);
251 }