source: arduino-1-6-7/trunk/fuentes/arduino-ide-amd64/hardware/arduino/avr/firmwares/wifishield/wifiHD/src/cmd_wl.c @ 4837

Last change on this file since 4837 was 4837, checked in by daduve, 2 years ago

Adding new version

File size: 19.8 KB
Line 
1/* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
2
3/*! \page License
4 * Copyright (C) 2009, H&D Wireless AB All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * 3. The name of H&D Wireless AB may not be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY H&D WIRELESS AB ``AS IS'' AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
22 * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30#include <top_defs.h>
31#include <ctype.h>
32#include <stdlib.h>
33#include <string.h>
34
35#include <cmd_wl.h>
36
37#include <wl_cm.h>
38#include <console.h>
39#include <util.h>
40#include <lwip_setup.h>
41
42#include "lwip/netif.h"
43#include "lwip/dns.h"
44#include "debug.h"
45#include "ard_spi.h"
46#include "ard_tcp.h"
47#include "ard_utils.h"
48
49extern void showTTCPstatus();
50
51#define  _DNS_CMD_
52
53/**
54 *
55 */
56cmd_state_t 
57cmd_scan(int argc, char* argv[], void* ctx)
58{
59        /* Note that the scan results presented will
60         * be from the last scan, not this one.
61         */
62        wl_scan();
63        print_network_list();
64        return CMD_DONE;
65}
66
67cmd_state_t 
68cmd_debug_toggle(int argc, char* argv[], void* ctx)
69{
70        extern uint8_t tr_data_trace;
71        if ( argc != 2 ) {
72                printk("usage: dt <1|0>\n");
73                return CMD_DONE;
74        }
75        if ( '0' == argv[1][0] ) {
76                tr_data_trace = 0;
77        }
78        if ( '1' == argv[1][0] ) {
79                tr_data_trace = 1;
80        }
81        return CMD_DONE;
82}
83
84/**
85 *
86 */
87cmd_state_t 
88cmd_connect(int argc, char* argv[], void* ctx)
89{
90        struct wl_ssid_t ssid;
91        char desired_ssid[WL_SSID_MAX_LENGTH];
92        int len = 0;
93       
94        if (argc < 2) {
95                printk("usage: connect <ssid>\n");
96                return CMD_DONE;
97        }
98       
99        len = join_argv(desired_ssid, sizeof desired_ssid, argc - 1, argv + 1);
100        if (0 == len) {
101                return CMD_DONE;
102        }
103
104        memcpy(ssid.ssid, desired_ssid, len);
105        ssid.len = len;
106        /* Start connection manager */
107        wl_cm_set_network(&ssid, NULL);
108        wl_cm_start();
109        return CMD_DONE;
110}
111
112#ifdef WFE_6_12
113cmd_state_t 
114cmd_ibss(int argc, char* argv[], void* ctx)
115{
116        struct wl_ssid_t ssid;
117        char desired_ssid[WL_SSID_MAX_LENGTH];
118        uint8_t channel;
119        enum wl_auth_mode amode;
120        int len = 0;
121        wl_err_t ret;
122       
123        if ( 2 == argc && ! strncmp(argv[1], "none", 4) ) {
124                printk("Disconnecting\n");
125                wl_disconnect();
126                wl_cm_stop();
127                return CMD_DONE;
128        }
129        if (argc < 4) {
130                printk("usage: ibss <ssid> <channel (1-14)> <wep_enable (1|0)>\n");
131                printk("       ibss none\n");
132                return CMD_DONE;
133        }
134       
135        channel = atoi(argv[argc - 2]);
136        if ( *argv[argc - 1] == '0' ) {
137                amode = AUTH_MODE_OPEN_SYSTEM;
138        } else {
139                amode = AUTH_MODE_SHARED_KEY;
140        }
141        len = join_argv(desired_ssid, sizeof desired_ssid, argc - 3, argv + 1);
142        if (0 == len) {
143                return CMD_DONE;
144        }
145        if ( channel > 14 ) {
146                printk("Invalid channel %d\n", (int)channel);
147                return CMD_DONE;
148        }
149        printk("%s : Start with ssid \"%s\", channel %d\n", __func__,
150               desired_ssid, channel);
151        memcpy(ssid.ssid, desired_ssid, len);
152        ssid.len = len;
153        /* Stop the connection manager */
154        wl_cm_stop();
155       
156        ret = wl_start_adhoc_net(ssid, channel, amode);
157        switch (ret) {
158        case WL_BUSY:
159                printk("Driver is busy. Already connected?\n");
160                break;
161        case WL_RETRY:
162                printk("Driver is busy. Retry operation\n");
163                break;
164        case WL_OOM:
165                printk("Out of memory\n");
166                break;
167        case WL_INVALID_ARGS:
168                printk("Invalid argument\n");
169                break;
170        case WL_SUCCESS:
171                break;
172        default:
173                printk("Unknown error %d\n", ret);
174                break;
175        }
176        return CMD_DONE;
177}
178#endif
179/**
180 *
181 */
182cmd_state_t 
183cmd_set_ip(int argc, char* argv[], void* ctx)
184{
185        struct ctx_server *hs = ctx;
186    struct net_cfg *ncfg = &(hs->net_cfg);
187        struct ip_addr lwip_addr;
188        struct netif *nif = ncfg->netif;
189
190        if (argc == 2 && 
191            (strncmp(argv[1], "none", 4) == 0)) {
192                ncfg->dhcp_enabled = DYNAMIC_IP_CONFIG;
193               
194                return CMD_DONE;
195        }
196        else if (argc != 4 ) {
197                printk("usage: ipconfig <ip> <netmask> <gateway-ip>\n");
198                printk("  or : ipconfig none (to enable DHCP)\n");
199                return CMD_DONE;
200        }
201
202        /* IP address */
203        lwip_addr = str2ip(argv[1]);
204        INFO_SPI("nif:%p lwip_addr=0x%x\n", nif, lwip_addr.addr);
205        netif_set_ipaddr(nif, &lwip_addr);
206        /* Netmask */
207        lwip_addr = str2ip(argv[2]);
208        netif_set_netmask(nif, &lwip_addr);
209        /* Default Gateway address */
210        lwip_addr = str2ip(argv[3]);
211        netif_set_gw(nif, &lwip_addr);
212        /* Disable DHCP */
213        ncfg->dhcp_enabled = STATIC_IP_CONFIG;
214
215        return CMD_DONE;
216}
217
218#ifdef WITH_WPA
219
220/**
221 *
222 */
223cmd_state_t
224cmd_delpass(int argc, char* argv[], void* ctx)
225{
226        const char *usage = "usage: dpass <ssid>\n";
227        struct wl_network_t net;
228        char desired_ssid[WL_SSID_MAX_LENGTH];
229        int len = 0;
230
231        if (argc != 2) {
232                printk(usage);
233                return CMD_DONE;
234        }
235
236        memset(&net, 0, sizeof net);
237        memset(net.bssid.octet, 0xFF, sizeof net.bssid.octet);
238
239        len = join_argv(desired_ssid, sizeof desired_ssid, argc - 1, argv + 1);
240        if (0 == len) {
241                return CMD_DONE;
242        }
243        memcpy(net.ssid.ssid, desired_ssid, len);
244        net.ssid.len = len;
245        net.enc_type = ENC_TYPE_AUTO;
246        if (wl_clear_passphrase(&net) != WL_SUCCESS) {
247                printk("%s : Failed to delete passphrase\n", __func__);
248        }
249
250        return CMD_DONE;
251}
252
253
254/**
255 *
256 */
257cmd_state_t
258cmd_setpass(int argc, char* argv[], void* ctx)
259{
260        const char *usage = "usage: wpass <ssid> <passphrase>\n";
261        struct wl_network_t net;
262        char desired_ssid[WL_SSID_MAX_LENGTH];
263        int len = 0;
264
265        if (argc < 3) {
266                printk(usage);
267                return CMD_DONE;
268        }
269        /* Not really kosher, an ssid may legally contain 0-bytes but
270         * the console interface does not deal with that.
271         */
272        memset(&net, 0, sizeof net);
273        memset(net.bssid.octet, 0xFF, sizeof net.bssid.octet);
274
275        len = join_argv(desired_ssid, sizeof desired_ssid, argc - 2, argv + 1);
276        if (0 == len) {
277                return CMD_DONE;
278        }
279
280        memcpy(net.ssid.ssid, desired_ssid, len);
281        net.ssid.len = len;
282        net.enc_type = ENC_TYPE_AUTO;
283        if (wl_set_passphrase(&net, 
284                              argv[argc - 1], 
285                              strlen(argv[argc - 1]), 
286                              ENC_TYPE_AUTO,
287                              AUTH_MODE_AUTO) 
288            != WL_SUCCESS) {
289                printk("%s : Failed to add passphrase\n", __func__);
290        }
291
292        return CMD_DONE;
293}
294#endif
295
296#ifdef _DNS_CMD_
297void foundHost(const char *name, struct ip_addr *ipaddr, void *callback_arg)
298{
299        printk("Found Host: name=%s ip=0x%x\n", name, ipaddr->addr);
300}
301
302/**
303 *
304 */
305cmd_state_t
306cmd_gethostbyname(int argc, char* argv[], void* ctx)
307{
308        const char *usage = "usage: getHost <hostname>\n";
309        char hostname[DNS_MAX_NAME_LENGTH];
310        struct ip_addr _addr;
311        int len = 0;
312
313        if (argc < 2) {
314                printk(usage);
315                return CMD_DONE;
316        }
317
318        len = join_argv(hostname, sizeof hostname, argc - 1, argv + 1);
319        if (0 == len) {
320                return CMD_DONE;
321        }
322        err_t err = dns_gethostbyname(hostname, &_addr, foundHost, NULL);
323        if (err == ERR_OK)
324        {
325                printk("Found Host: name=%s ip=0x%x\n", hostname, _addr.addr);
326        }
327
328        return CMD_DONE;
329}
330
331/**
332 *
333 */
334cmd_state_t
335cmd_setDnsServer(int argc, char* argv[], void* ctx)
336{
337        const char *usage = "usage: setdns [1-2] aaa.bbb.ccc.ddd\n";
338        struct ip_addr dnsIp;
339        int dnsIdx = 0;
340
341        if (argc < 3) {
342                printk(usage);
343                return CMD_DONE;
344        }
345
346        /* DNS IDX */
347        dnsIdx = atoi(argv[1])-1;
348        /* IP address */
349        dnsIp = str2ip(argv[2]);
350
351        printk("Set DNS server %d to %s\n", dnsIdx, ip2str(dnsIp));
352        dns_setserver(dnsIdx, &dnsIp);
353        struct ip_addr addr1 = dns_getserver(0);
354        struct ip_addr addr2 = dns_getserver(1);
355
356        printk("==> DNS1: %s\n", ip2str(addr1), addr1);
357        printk("==> DNS2: %s\n", ip2str(addr2), addr2);
358
359        return CMD_DONE;
360}
361
362/**
363 *
364 */
365cmd_state_t
366cmd_startSrv(int argc, char* argv[], void* ctx)
367{
368        const char *usage = "usage: startSrv <port> <sock> <tcp(0)/udp(1)>\n";
369
370        int port = 0;
371        int sock = 0;
372                int protMode = 0;
373
374        if (argc < 4) {
375                printk(usage);
376                return CMD_DONE;
377        }
378
379        /* TCP port */
380        port = atoi(argv[1]);
381        /* socket index */
382        sock = atoi(argv[2]);
383                /* Protocol Mode */
384                protMode = atoi(argv[3]);
385
386        printk("Start %s server on port %d sock %d\n", ProtMode2Str(protMode), port, sock);
387        if (start_server_tcp(port, sock, protMode) == -1)
388        {
389                WARN("Start %s server on port %d sock %d FAILED\n", ProtMode2Str(protMode), port, sock);
390        }
391        return CMD_DONE;
392}
393
394/**
395 *
396 */
397cmd_state_t
398cmd_startCli(int argc, char* argv[], void* ctx)
399{
400        const char *usage = "usage: startCli <ipaddr> <port> <sock> <tcp(0)/udp(1)>\n";
401                struct ip_addr addr = {0};
402        int port = 0;
403        int sock = 0;
404                int protMode = 0;
405
406        if (argc < 5) {
407                printk(usage);
408                return CMD_DONE;
409        }
410
411        /* IP address */
412        addr = str2ip(argv[1]);
413        /* TCP port */
414        port = atoi(argv[2]);
415        /* socket index */
416        sock = atoi(argv[3]);
417                /* Protocol Mode */
418                protMode = atoi(argv[4]);
419
420        printk("Start client on addr 0x%x, port %d sock %d mode %d\n", addr, port, sock, protMode);
421        if (start_client_tcp(addr.addr, port, sock, protMode) == -1)
422        {
423                WARN("Start client on port %d sock %d prot %d mode %d FAILED\n", port, sock, protMode);
424        }
425        return CMD_DONE;
426}
427
428#endif
429
430
431/**
432 *
433 */
434cmd_state_t
435cmd_status(int argc, char* argv[], void* ctx)
436{
437        struct net_cfg *ncfg = ctx;
438        struct wl_network_t* net;
439        uint8_t mac[WL_MAC_ADDR_LENGTH];
440
441        printk("wl_api version " WL_API_RELEASE_NAME "\n");
442        /* print mac address */
443        if (wl_get_mac_addr(mac) != WL_SUCCESS) {
444                printk("failed to get mac address\n");
445        }else{
446        printk("hw addr: %s\n", mac2str(mac));
447        }
448
449        /* print network info */
450        net = wl_get_current_network();
451        printk("link status: "); 
452        if (!net) { 
453                printk("down\n");
454
455        }else{
456        print_network(net);
457        }
458       
459        /* print ip address */
460        if (netif_is_up(netif_default))
461                {
462                printk("ip addr: %s - ", ip2str(netif_default->ip_addr));
463                                printk("netmask: %s - ", ip2str(netif_default->netmask));
464                                printk("gateway: %s\n", ip2str(netif_default->gw));
465                }                                       
466        else
467                printk("ip interface is down\n");
468        printk("dhcp : ");
469        if (ncfg->dhcp_enabled == DYNAMIC_IP_CONFIG) {
470                printk("enabled\n");
471        }
472        else {
473                printk("disabled\n");
474        }
475        struct ip_addr addr1 = dns_getserver(0);
476        struct ip_addr addr2 = dns_getserver(1);
477
478        printk("DNS: %s - ", ip2str(addr1));
479                printk("%s\n", ip2str(addr2));
480
481        showTTCPstatus();
482        return CMD_DONE;
483}
484
485#ifdef ADD_CMDS
486/**
487 *
488 */
489cmd_state_t
490cmd_power(int argc, char* argv[], void* ctx)
491{
492        const char *usage = "usage: powersave <on|off>\n";
493       
494        if (argc < 2) {
495                printk(usage);
496                return CMD_DONE;
497        }
498       
499        if (!strcmp(argv[1], "on")) {
500                if (wl_enable_ps() != WL_SUCCESS) {
501                        printk("could not enable power save\n");
502                        return CMD_DONE;
503                }
504                return CMD_DONE;
505        }
506        else if(!strcmp(argv[1], "off")) {
507                if (wl_disable_ps() != WL_SUCCESS) {
508                        printk("could not disable power save\n");
509                        return CMD_DONE;
510                }
511                return CMD_DONE;
512        }
513
514        printk(usage);
515        return CMD_DONE;
516}
517#endif
518
519#ifdef ADD_CMDS
520/**
521 *
522 */
523cmd_state_t
524cmd_psconf(int argc, char* argv[], void* ctx)
525{
526        const char *usage = 
527                "usage: psconf <use_ps_poll>      (0/1       default 0)\n" \
528                "              <traffic_timeout>  ([ms]      default 10)\n" \
529                "              <ps_delay>         ([ms]      default 5000)\n"\
530                "              <rx_all_dtim>      (0/1       default 1)\n"\
531                "              <listen_interval>  ([beacons] default 20)\n";
532       
533        uint8_t use_ps_poll;
534        uint32_t traffic_timeout;
535        uint32_t ps_delay;
536        uint8_t rx_all_dtim;
537        uint16_t listen_interval;
538       
539        if (argc < 6) {
540                printk(usage);
541                return CMD_DONE;
542        }
543       
544        use_ps_poll = atoi(argv[1]);
545        traffic_timeout = atoi(argv[2]);
546        ps_delay = atoi(argv[3]);
547        rx_all_dtim = atoi(argv[4]);
548        listen_interval = atoi(argv[5]);
549
550        if (use_ps_poll > 1) {
551                printk(usage);
552                return CMD_DONE;
553        }
554
555        if (rx_all_dtim > 1) {
556                printk(usage);
557                return CMD_DONE;
558        }
559
560        if (wl_conf_ps(use_ps_poll, traffic_timeout, ps_delay,
561                       rx_all_dtim, listen_interval) != WL_SUCCESS)
562                printk("configuration failed\n");
563       
564        return CMD_DONE;
565}
566#endif
567
568/**
569 *
570 */
571cmd_state_t
572cmd_setkey(int argc, char* argv[], void* ctx)
573{
574        int idx, len;
575        char key[13];
576        struct wl_mac_addr_t bssid;
577        const char *usage = "usage: setkey <key_idx (0-3)> <key in hex>\n\t "\
578                "or: setkey none\n";
579
580        memset(&bssid.octet, 0xff, sizeof bssid.octet);
581        if (argc == 2 && strcmp(argv[1], "none") == 0) {
582                printk("Deleting WEP keys\n");
583                wl_delete_wep_key(0, &bssid);
584                wl_delete_wep_key(1, &bssid);
585                wl_delete_wep_key(2, &bssid);
586                wl_delete_wep_key(3, &bssid);
587                return CMD_DONE;
588        }
589        if (argc < 3) {
590                printk(usage);
591                return CMD_DONE;
592        }
593        idx = atoi(argv[1]);
594        len = strlen(argv[2]);
595        /* Pass phrase? */
596        if ( 5 == len || 13 == len ) {
597                strncpy(key, argv[2], len);
598        }
599        /* Otherwise it's a hex string */
600        else {
601                len = ascii_to_key(key, argv[2]);
602                if (0 == len || idx > 3 || idx < 0 || (idx == 0 && *argv[1] != '0')) {
603                        printk(usage);
604                        return CMD_DONE;
605                }
606                if (len != 5 && len != 13) {
607                        printk(" WEP key must be 10 (WEP-40) or 26 (WEP-104) digits\n");
608                        return CMD_DONE;
609                }
610        }
611        wl_add_wep_key(idx, len, key, &bssid);
612        wl_set_default_wep_key(idx);
613
614        return CMD_DONE;
615}
616
617cmd_state_t
618cmd_debug(int argc, char* argv[], void* ctx)
619{
620        int level;
621        const char *usage = "usage: debug <section> <level>\n\t"\
622                        "section: init, cm, spi, tcp , util, warn\n\t"
623                        "level  : 0 (off), 1 (on), 2 (verbose)\n\t"
624                "or: debug print/on/off\n";
625
626        if (argc == 2 && strcmp(argv[1], "off") == 0) {
627                printk("Debug OFF\n");
628                INIT_DEBUG_VARIABLES()
629                return CMD_DONE;
630        }else if (argc == 2 && strcmp(argv[1], "print") == 0) {
631                PRINT_DEBUG_VARIABLES()
632            return CMD_DONE;
633        }else if (argc == 2 && strcmp(argv[1], "on") == 0) {
634            printk("Debug ON\n");
635            TURNON_DEBUG_VARIABLES();
636            return CMD_DONE;
637        }
638        if (argc < 3) {
639                printk(usage);
640                return CMD_DONE;
641        }
642        level = atoi(argv[2]);
643        if (argc == 3 && strcmp(argv[1], "init") == 0) {
644                CHECK_DEBUG_LEVEL(level, INFO_INIT_FLAG);
645        }else if (argc == 3 && strcmp(argv[1], "spi") == 0) {
646                CHECK_DEBUG_LEVEL(level, INFO_SPI_FLAG);
647        }else if (argc == 3 && strcmp(argv[1], "tcp") == 0) {
648                CHECK_DEBUG_LEVEL(level, INFO_TCP_FLAG);
649        }else if (argc == 3 && strcmp(argv[1], "cm") == 0) {
650                CHECK_DEBUG_LEVEL(level, INFO_CM_FLAG);
651        }else if (argc == 3 && strcmp(argv[1], "util") == 0) {
652                CHECK_DEBUG_LEVEL(level, INFO_UTIL_FLAG);
653        }else if (argc == 3 && strcmp(argv[1], "warn") == 0) {
654                CHECK_DEBUG_LEVEL(level, INFO_WARN_FLAG);
655        }
656        return CMD_DONE;
657}
658
659extern void dumpPbuf(uint8_t sock);
660
661/**
662 *
663 */
664cmd_state_t
665cmd_dumpBuf(int argc, char* argv[], void* ctx)
666{
667    const char *usage = "usage: dumpPbuf [sock]\n\t"\
668                "sock: socket Number\n";
669
670    if (argc == 2 && strcmp(argv[1], "all") == 0) {
671        printk("Dump All Buffers\n");
672        int i = 0;
673        for (; i<MAX_SOCK_NUM; ++i)
674        {
675                        printk("Socket: %d\n", i);
676                dumpPbuf(i);
677        }
678    }else if (argc == 2) {
679        uint8_t sock = atoi(argv[1]);
680        printk("Socket: %d\n", sock);
681        dumpPbuf(sock);
682    }else {
683                printk(usage);
684        }               
685        return CMD_DONE;
686}
687
688
689
690/**
691 *
692 */
693cmd_state_t
694cmd_sendUdpData(int argc, char* argv[], void* ctx)
695{
696        const char pattern[]={'M', 'I', 'M', 'L', 'F', 'D'};
697        const char* pattern2[]={"Prova", "1234567890","FineTest"};
698    const char *usage = "usage: sendUdp [sock]\n\t"\
699                "sock: socket Number\n";
700
701    if (argc < 2)
702        printk(usage);
703
704    if (argc >= 2) {
705
706                uint8_t sock = atoi(argv[1]);
707                printk("Socket: %d\n", sock);
708
709                if (argc >= 3) {
710                        uint8_t patternType = atoi(argv[2]);
711                        printk("PatternType: %d\n", patternType);
712                        if (patternType == 1)
713                        {
714                                insertBuf(sock, (uint8_t*)pattern2[0], strlen(pattern2[0]));
715                                insertBuf(sock, (uint8_t*)pattern2[1], strlen(pattern2[1]));
716                                insertBuf(sock, (uint8_t*)pattern2[2], strlen(pattern2[2]));
717                        }
718                        if (patternType == 2)
719                        {
720                                mergeBuf(sock, NULL, NULL);
721                        }
722                }else{
723                        if (sock < MAX_SOCK_NUM)
724                        {
725                                sendUdpData(getTTCP(sock, TTCP_MODE_TRANSMIT), (uint8_t*)pattern, sizeof(pattern)/sizeof(char));
726                        }
727                }
728
729    }
730        return CMD_DONE;
731}
Note: See TracBrowser for help on using the repository browser.