Skip to content

Extend and rework WiFi interface #2627

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 15, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions features/net/network-socket/NetworkInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ class NetworkInterface {
*/
virtual const char *get_ip_address() = 0;

/** Get the local MAC address
*
* @return Null-terminated representation of the local MAC address
*/
virtual const char *get_mac_address() = 0;

protected:
friend class Socket;
friend class UDPSocket;
Expand Down
92 changes: 71 additions & 21 deletions features/net/network-socket/WiFiInterface.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* WiFiInterface
* Copyright (c) 2015 ARM Limited
* Copyright (c) 2015 - 2016 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -17,22 +17,19 @@
#ifndef WIFI_INTERFACE_H
#define WIFI_INTERFACE_H

#include <string.h>
#include "network-socket/NetworkInterface.h"

typedef struct wifi_ap {
char ssid[33]; /* 32 is what 802.11 defines as longest possible name; +1 for the \0 */
uint8_t bssid[6];
nsapi_security_t security;
int8_t rssi;
uint8_t channel;
} wifi_ap_t;

/** Enum of WiFi encryption types
*
* The security type specifies a particular security to use when
* connected to a WiFi network
*
* @enum nsapi_protocol_t
*/
enum nsapi_security_t {
NSAPI_SECURITY_NONE = 0, /*!< open access point */
NSAPI_SECURITY_WEP, /*!< phrase conforms to WEP */
NSAPI_SECURITY_WPA, /*!< phrase conforms to WPA */
NSAPI_SECURITY_WPA2, /*!< phrase conforms to WPA2 */
};
typedef void (*wifi_ap_scan_cb_t)(wifi_ap_t *ap, void *data);
typedef void (*wifi_connect_cb_t)(nsapi_error_t res, void *data);

/** WiFiInterface class
*
Expand All @@ -43,28 +40,81 @@ class WiFiInterface: public NetworkInterface
public:
/** Start the interface
*
* Attempts to connect to a WiFi network. If passphrase is invalid,
* NSAPI_ERROR_AUTH_ERROR is returned.
* Attempts to connect to a WiFi network.
*
* @param ssid Name of the network to connect to
* @param pass Security passphrase to connect to the network
* @param security Type of encryption for connection
* @param timeout Timeout in milliseconds; 0 for no timeout
* @return 0 on success, or error code on failure
*/
virtual nsapi_error_t connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE,
unsigned timeout = 0) = 0;

/** Start the interface
*
* Attempts to connect to a WiFi network asynchronously, the call will return straight away. If the @a cb was NULL
* you'll need to query @a get_state until it's in NSAPI_IF_STATE_CONNECTED state, otherwise the @a cb will be
* called with connection results.
*
* Note: @a ssid and @a pass must be kept until the connection is made, that is the callback has been called or the
* state changed to @a NSAPI_IF_STATE_CONNECTED as they are passed by value.
*
* @param ssid Name of the network to connect to
* @param pass Security passphrase to connect to the network
* @param security Type of encryption for connection
* @return 0 on success, negative error code on failure
* @param cb Function to be called when the connect finishes
* @param data Arbitrary user data to pass to @a cb function
*/
virtual int connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE) = 0;
virtual void connect_async(const char *ssid, const char *pass,nsapi_security_t security = NSAPI_SECURITY_NONE,
wifi_connect_cb_t cb = NULL, void *data = NULL) = 0;

/** Stop the interface
*
* @return 0 on success, negative error code on failure
* @return 0 on success, or error code on failure
*/
virtual int disconnect() = 0;
virtual nsapi_error_t disconnect() = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small request: Can we hold off on adopting the nsapi_error_t in this pr?

I agree it should be adopted for clarity, but the return types should be kept consistent untile then to avoid confusion.

IMO: We should make a separate pr to adopt these types across the entire network-socket API:

nsapi_error_t
nsapi_size_t
nsapi_size_or_error_t

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well I agree keeping them in sync would be good, but on the same note we sort of promised API for 5.2 for some partners to implement. If they do it once just so we can change the return type month later, they would have to go back to it and change it and also error handling code implemented for that 'new' API. Also I don't think there's much consistency required between interfaces on a technical level, as in it wouldn't cause anyone problems to have it different till we have time for the new PR. I would argue it will cause more confusion and work for apps to change the error checking code when we keep changing what the functions return.

I guess it's a call how much we don't want partners to go back and change things.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree we should avoid changing code underneath our partner's feet as much as possible. However this change should be easy enough to accomplish without requiring user code changes.

I haven't verified this yet (some of the motivation for another pr) but these types would work:

// previously an int, however enums are implicitly casted to/from ints
// avoiding breaking changes
typedef enum nsapi_error nsapi_error_t;

// identical to previous type 
typedef unsigned nsapi_size_t;            

// identical to previous type
typedef int nsapi_size_or_error_t;         

Adopting the types would be opt in and suggested, but the only change a user would notice would possibly be (correct) warnings related to unexhausted switch case statements:

switch (iface.connect()) {
    case NSAPI_ERROR_OK:
        blablabla;
    case NSAPI_ERROR_NO_CONNECTION:
        blablabla;
    // warning for not handling all possible error cases
}


/** Get the local MAC address
*
* @return Null-terminated representation of the local MAC address
*/
virtual const char *get_mac_address() = 0;
};

/** Get the current WiFi interface state
*
* @returns Interface state enum
*/
virtual nsapi_if_state_t get_state() = 0;

/** Gets the current radio signal strength for active connection
*
* @return Connection strength in dBm (negative value), or 0 if measurement impossible
*/
virtual int8_t get_rssi() = 0;

/** Scan for available networks
*
* This function will block.
*
* @param ap Pointer to allocated array to store discovered AP
* @param count Size of allocated @a res array, or 0 to only count available AP
* @param timeout Timeout in milliseconds; 0 for no timeout
* @return Number of entries in @a, or if @a count was 0 number of available networks, negative on error
* see @a nsapi_error
*/
virtual int scan(wifi_ap_t *res, unsigned count, unsigned timeout = 0) = 0;

/** Scan for available networks
*
* This function won't block, it'll return immediately and call provided callback for each discovered network with
* AP data and user @a data. After the last discovered network @a cb will be called with NULL as @a ap, so it
* will be always called at least once.
*
* @param cb Function to be called for every discovered network
* @param data A user handle that will be passed to @a cb along with the AP data
*/
virtual void scan_async(wifi_ap_scan_cb_t cb, void *data = NULL) = 0;
};

#endif
33 changes: 30 additions & 3 deletions features/net/network-socket/nsapi_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ extern "C" {
#endif


/** Enum of standardized error codes
/** Enum of standardized error codes
*
* Valid error codes have negative values and may
* be returned by any network operation.
*
* @enum nsapi_error_t
*/
typedef enum nsapi_error {
NSAPI_ERROR_OK = 0, /*!< no error */
NSAPI_ERROR_WOULD_BLOCK = -3001, /*!< no data is not available but call is non-blocking */
NSAPI_ERROR_UNSUPPORTED = -3002, /*!< unsupported functionality */
NSAPI_ERROR_PARAMETER = -3003, /*!< invalid configuration */
Expand All @@ -41,10 +42,36 @@ typedef enum nsapi_error {
NSAPI_ERROR_NO_MEMORY = -3007, /*!< memory resource not available */
NSAPI_ERROR_DNS_FAILURE = -3008, /*!< DNS failed to complete successfully */
NSAPI_ERROR_DHCP_FAILURE = -3009, /*!< DHCP failed to complete successfully */
NSAPI_ERROR_AUTH_FAILURE = -3010, /*!< connection to access point faield */
NSAPI_ERROR_DEVICE_ERROR = -3011, /*!< failure interfacing with the network procesor */
NSAPI_ERROR_AUTH_FAILURE = -3010, /*!< connection to access point failed */
NSAPI_ERROR_DEVICE_ERROR = -3011, /*!< failure interfacing with the network processor */
NSAPI_ERROR_TIMEOUT = -3012, /*!< operation timed out */
NSAPI_ERROR_BAD_SSID = -3013, /*!< ssid not found */
} nsapi_error_t;

/** Enum of encryption types
*
* The security type specifies a particular security to use when
* connected to a WiFi network
*/
typedef enum nsapi_security {
NSAPI_SECURITY_NONE = 0x0, /*!< open access point */
NSAPI_SECURITY_WEP = 0x1, /*!< phrase conforms to WEP */
NSAPI_SECURITY_WPA = 0x2, /*!< phrase conforms to WPA */
NSAPI_SECURITY_WPA2 = 0x3, /*!< phrase conforms to WPA2 */
NSAPI_SECURITY_WPA_WPA2 = 0x4, /*!< phrase conforms to WPA/WPA2 */
NSAPI_SECURITY_UNSSUPPORTED = 0xFF, /*!< unknown/unsupported security in scan results */
} nsapi_security_t;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for moving these guys here


/** Enum of interface states
*
* List of all possible states a WiFi network interface can be in
*/
typedef enum nsapi_if_state {
NSAPI_IF_STATE_NOT_CONNECTED = 0x0,
NSAPI_IF_STATE_CONNECTING = 0x01,
NSAPI_IF_STATE_CONNECTED = 0x02,
NSAPI_IF_STATE_ERROR = 0xFF
} nsapi_if_state_t;

/** Maximum size of IP address representation
*/
Expand Down