carlu: add GPIO test
[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_gpio_test(void)
138 {
139         struct carlu *carl = NULL;
140         int err;
141
142         err = carlu_init();
143         if (err)
144                 goto out;
145
146         carl = carlusb_probe();
147         if (IS_ERR_OR_NULL(carl)) {
148                 err = PTR_ERR(carl);
149                 goto out;
150         }
151
152         err = carlu_gpio_test(carl);
153         if (err)
154                 goto out_close;
155
156 out_close:
157         carlusb_close(carl);
158
159 out:
160         carlu_exit();
161         return err ? EXIT_FAILURE : EXIT_SUCCESS;
162 }
163
164 static int carlu_run_loop_test(void)
165 {
166         struct carlu *carl;
167         int err;
168
169         err = carlu_init();
170         if (err)
171                 return EXIT_FAILURE;
172
173         carl = carlusb_probe();
174         if (IS_ERR_OR_NULL(carl)) {
175                 err = PTR_ERR(carl);
176                 goto out;
177         }
178
179         carlu_cmd_write_mem(carl, AR9170_MAC_REG_BCN_PERIOD, 0xFFFFFFFF);
180         carlu_cmd_write_mem(carl, AR9170_MAC_REG_PRETBTT, 0xFFFFFFFF);
181
182         /* different payload test */
183         carlu_loopback_test(carl, 9000, 1000, 1566, 1566);
184         carlusb_close(carl);
185
186 out:
187         return err ? EXIT_FAILURE : EXIT_SUCCESS;
188 }
189
190 static int carlu_probe_all(void)
191 {
192         struct carlu *carl[32] = { 0 };
193         unsigned int devs;
194         int ret;
195
196         ret = carlu_init();
197         if (ret)
198                 return EXIT_FAILURE;
199
200         for (devs = 0; devs < ARRAY_SIZE(carl); devs++) {
201                 carl[devs] = carlusb_probe();
202                 if (IS_ERR_OR_NULL(carl[devs]))
203                         break;
204         }
205
206         info("Found %d devices\n", devs);
207
208         for (; devs > 0; devs--)
209                 carlusb_close(carl[devs - 1]);
210
211         carlu_exit();
212         return EXIT_SUCCESS;
213 }
214
215 struct menu_struct {
216         char option;
217         unsigned int parameters;
218         int (*function)(void);
219         char help_text[80];
220 };
221
222 #define MENU_ITEM(op, func, helpme)     \
223         {                               \
224                 .option = op,           \
225                 .parameters = 0,        \
226                 .function = func,       \
227                 .help_text = helpme,    \
228         }
229
230 static int show_help(void);
231
232 static const struct menu_struct menu[] = {
233         [0] = MENU_ITEM('h', show_help, "shows this useless help message text."),       /* keep this entry at 0! */
234               MENU_ITEM('e', carlu_dump_eeprom, "hexdumps eeprom content to stdout."),
235               MENU_ITEM('l', carlusb_print_known_devices, "list of all known ar9170 usb devices."),
236               MENU_ITEM('p', carlu_probe_all, "probe all possible devices."),
237               MENU_ITEM('t', carlu_run_loop_test, "run tx/rx test."),
238               MENU_ITEM('g', carlu_run_gpio_test, "flash the leds."),
239 };
240
241 static int show_help(void)
242 {
243         unsigned int i;
244         char parameters[ARRAY_SIZE(menu) + 1];
245
246         for (i = 0; i < ARRAY_SIZE(menu); i++)
247                 parameters[i] = menu[i].option;
248
249         parameters[ARRAY_SIZE(menu)] = '\0';
250
251         info("usage: ar9170user -[%s]\n", parameters);
252
253         for (i = 0; i < ARRAY_SIZE(menu); i++)
254                 info("\t-%c\t%s\n", menu[i].option, menu[i].help_text);
255
256         return EXIT_FAILURE;
257 }
258
259 static int select_menu_item(const char arg)
260 {
261         unsigned int i;
262
263         for (i = ARRAY_SIZE(menu) - 1; i != 0; i--) {
264                 if (arg == menu[i].option)
265                         break;
266         }
267
268         return menu[i].function();
269 }
270
271 int main(int argc, char *argv[])
272 {
273         init_debug();
274
275         if (argc != 2 || strlen(argv[1]) != 2 || argv[1][0] != '-')
276                 return show_help();
277
278         return select_menu_item(argv[1][1]);
279 }