diff --git a/cc3200/mods/modusocket.c b/cc3200/mods/modusocket.c
index ad59493ea6c62c412db3dde6d87aa7fd0fbe9bb3..42163b68b254834c116c03b21861eddb70c13064 100644
--- a/cc3200/mods/modusocket.c
+++ b/cc3200/mods/modusocket.c
@@ -397,6 +397,21 @@ STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t blocking) {
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
 
+STATIC mp_obj_t socket_makefile(mp_uint_t n_args, const mp_obj_t *args) {
+    // TODO: CPython explicitly says that closing the returned object doesn't
+    // close the original socket (Python2 at all says that fd is dup()ed). But
+    // we save on the bloat.
+    mod_network_socket_obj_t *self = args[0];
+    if (n_args > 1) {
+        const char *mode = mp_obj_str_get_str(args[1]);
+        if (strcmp(mode, "rb") && strcmp(mode, "wb")) {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+        }
+    }
+    return self;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_makefile_obj, 1, 6, socket_makefile);
+
 STATIC const mp_map_elem_t socket_locals_dict_table[] = {
     { MP_OBJ_NEW_QSTR(MP_QSTR___del__),         (mp_obj_t)&socket_close_obj },
     { MP_OBJ_NEW_QSTR(MP_QSTR_close),           (mp_obj_t)&socket_close_obj },
@@ -412,7 +427,7 @@ STATIC const mp_map_elem_t socket_locals_dict_table[] = {
     { MP_OBJ_NEW_QSTR(MP_QSTR_setsockopt),      (mp_obj_t)&socket_setsockopt_obj },
     { MP_OBJ_NEW_QSTR(MP_QSTR_settimeout),      (mp_obj_t)&socket_settimeout_obj },
     { MP_OBJ_NEW_QSTR(MP_QSTR_setblocking),     (mp_obj_t)&socket_setblocking_obj },
-    { MP_OBJ_NEW_QSTR(MP_QSTR_makefile),        (mp_obj_t)&mp_identity_obj },
+    { MP_OBJ_NEW_QSTR(MP_QSTR_makefile),        (mp_obj_t)&socket_makefile_obj },
 
     // stream methods
     { MP_OBJ_NEW_QSTR(MP_QSTR_read),            (mp_obj_t)&mp_stream_read_obj },
diff --git a/cc3200/mods/modussl.c b/cc3200/mods/modussl.c
index a11d2b2ef92b88e73e7d1d5ca9d5fce417eedbf7..ce3067d963e5893224f2aa1597eabd8ffd756af5 100644
--- a/cc3200/mods/modussl.c
+++ b/cc3200/mods/modussl.c
@@ -61,7 +61,7 @@ STATIC const mp_obj_type_t ssl_socket_type;
 /******************************************************************************/
 // Micro Python bindings; SSL class
 
-// ssl socket inherits from normal socket, so we take its
+// ssl sockets inherit from normal socket, so we take its
 // locals and stream methods
 STATIC const mp_obj_type_t ssl_socket_type = {
     { &mp_type_type },
@@ -116,7 +116,7 @@ STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args,
 
     // create the ssl socket
     mp_obj_ssl_socket_t *ssl_sock = m_new_obj(mp_obj_ssl_socket_t);
-    // ssl socket inherits all properties from the original socket
+    // ssl sockets inherit all properties from the original socket
     memcpy (&ssl_sock->sock_base, &((mod_network_socket_obj_t *)args[0].u_obj)->sock_base, sizeof(mod_network_socket_base_t));
     ssl_sock->base.type = &ssl_socket_type;
     ssl_sock->sock_base.cert_req = (args[4].u_int == SSL_CERT_REQUIRED) ? true : false;
diff --git a/docs/library/index.rst b/docs/library/index.rst
index 81a9824efd64b254db91168388fefc747b28e162..60882598eaf48b7cbe961a186d89a1f4c391fb98 100644
--- a/docs/library/index.rst
+++ b/docs/library/index.rst
@@ -92,6 +92,7 @@ it will fallback to loading the built-in ``ujson`` module.
       ujson.rst
       ure.rst
       usocket.rst
+      ussl.rst
 
 .. only:: port_wipy
 
diff --git a/docs/library/network.rst b/docs/library/network.rst
index c0115864d33d3bc4cb7e4cfab0306a6bfecbe9b7..0b9acf6423483666d5b84e52235c59f80cd14867 100644
--- a/docs/library/network.rst
+++ b/docs/library/network.rst
@@ -378,16 +378,16 @@ For example::
     .. method:: wlan.isconnected()
 
        In case of STA mode, returns ``True`` if connected to a wifi access point and has a valid IP address.
-       In AP mode returns ``True`` when a station is connected. Returns ``False`` otherwise.
+       In AP mode returns ``True`` when a station is connected, ``False`` otherwise.
 
     .. method:: wlan.ifconfig(if_id=0, config=['dhcp' or configtuple])
 
        With no parameters given eturns a 4-tuple of ``(ip, subnet_mask, gateway, DNS_server)``.
-       
+
        if ``'dhcp'`` is passed as a parameter then the DHCP client is enabled and the IP params
        are negotiated with the AP.
-       
-       if the 4-tuple config is given then a static IP is configured. For example::
+
+       If the 4-tuple config is given then a static IP is configured. For instance::
 
           wlan.ifconfig(config=('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
 
@@ -423,7 +423,7 @@ For example::
             - ``handler`` is the function that gets called when the irq is triggered.
             - ``wake`` must be ``machine.SLEEP``.
 
-        Returns a irq object.
+        Returns an irq object.
 
     Constants
     ---------
diff --git a/docs/library/usocket.rst b/docs/library/usocket.rst
index cf79973f17c9a0b3d5e947ebc629461efe4b1b41..a83a87d2e0c6bb1f4dde56fed81529dd77df8af5 100644
--- a/docs/library/usocket.rst
+++ b/docs/library/usocket.rst
@@ -1,17 +1,193 @@
+*******************************
 :mod:`usocket` -- socket module
-===============================
+*******************************
 
 .. module:: usocket
    :synopsis: socket module
 
-Socket functionality.
+This module provides access to the BSD socket interface.
 
 Functions
 ---------
 
-.. function:: getaddrinfo(host, port)
+.. function:: socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
 
+   Create a new socket using the given address family, socket type and protocol number.
 
-.. function:: socket(family=AF_INET, type=SOCK_STREAM, fileno=-1)
+    .. only:: port_wipy
 
-   Create a socket.
+        .. note::
+
+           SSL sockets need to be created the following way before wrapping them with 
+           ``ssl.wrap_socket``::
+
+              import socket
+              import ssl
+              s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
+              ss = ssl.wrap_socket(s)
+
+.. function:: socket.getaddrinfo(host, port)
+
+   Translate the host/port argument into a sequence of 5-tuples that contain all the 
+   necessary arguments for creating a socket connected to that service. The list of 
+   5-tuples has following structure::
+
+      (family, type, proto, canonname, sockaddr)
+
+   The following example shows how to connect to a given url::
+
+      s = socket.socket()
+      s.connect(socket.getaddrinfo('www.micropython.org', 80)[0][4])
+
+Exceptions
+----------
+
+.. data:: socket.error
+.. data:: socket.timeout
+
+Constants
+---------
+
+.. data:: socket.AF_INET
+
+   family types
+
+.. data:: socket.SOCK_STREAM
+.. data:: socket.SOCK_DGRAM
+
+   socket types
+
+.. data:: socket.IPPROTO_UDP
+.. data:: socket.IPPROTO_TCP
+.. data:: socket.IPPROTO_SEC
+
+   protocol numbers
+
+class socket
+============
+
+Methods
+-------
+
+    .. method:: socket.close
+
+       Mark the socket closed. Once that happens, all future operations on the socket 
+       object will fail. The remote end will receive no more data (after queued data is flushed).
+
+       Sockets are automatically closed when they are garbage-collected, but it is recommended 
+       to close() them explicitly, or to use a with statement around them.
+
+    .. method:: socket.bind(address)
+
+       Bind the socket to address. The socket must not already be bound. The format of ``address``
+       is: ``(ipv4 address, port)``
+
+    .. method:: socket.listen([backlog])
+
+       Enable a server to accept connections. If backlog is specified, it must be at least 0 
+       (if it's lower, it will be set to 0); and specifies the number of unaccepted connections
+       tha the system will allow before refusing new connections. If not specified, a default
+       reasonable value is chosen.
+
+    .. method:: socket.accept()
+
+       Accept a connection. The socket must be bound to an address and listening for connections.
+       The return value is a pair (conn, address) where conn is a new socket object usable to send
+       and receive data on the connection, and address is the address bound to the socket on the
+       other end of the connection.
+
+    .. method:: socket.connect(address)
+
+       Connect to a remote socket at address. The format of address is: ``(ipv4 address, port)``
+
+    .. method:: socket.send(bytes)
+
+       Send data to the socket. The socket must be connected to a remote socket.
+
+    .. method:: socket.sendall(bytes)
+
+       Send data to the socket. The socket must be connected to a remote socket.
+
+    .. method:: socket.recv(bufsize)
+
+       Receive data from the socket. The return value is a bytes object representing the data
+       received. The maximum amount of data to be received at once is specified by bufsize.
+
+    .. method:: socket.sendto(bytes, address)
+
+       Send data to the socket. The socket should not be connected to a remote socket, since the
+       destination socket is specified by address. The ``address`` has the same format as the
+       rest of the methods, see above.
+
+    .. method:: socket.recvfrom(bufsize)
+
+      Receive data from the socket. The return value is a pair (bytes, address) where bytes is a
+      bytes object representing the data received and address is the address of the socket sending
+      the data.
+
+    .. method:: socket.setsockopt(level, optname, value)
+
+       Set the value of the given socket option. The needed symbolic constants are defined in the
+       socket module (SO_* etc.). The value can be an integer or a bytes-like object representing
+       a buffer.
+
+    .. method:: socket.settimeout(value)
+
+       Set a timeout on blocking socket operations. The value argument can be a nonnegative floating
+       point number expressing seconds, or None. If a non-zero value is given, subsequent socket operations
+       will raise a timeout exception if the timeout period value has elapsed before the operation has
+       completed. If zero is given, the socket is put in non-blocking mode. If None is given, the socket
+       is put in blocking mode.
+
+    .. method:: socket.setblocking(flag)
+
+       Set blocking or non-blocking mode of the socket: if flag is false, the socket is set to non-blocking,
+       else to blocking mode.
+
+       This method is a shorthand for certain ``settimeout()`` calls::
+
+          sock.setblocking(True) is equivalent to sock.settimeout(None)
+          sock.setblocking(False) is equivalent to sock.settimeout(0.0)
+
+    .. method:: socket.makefile(mode='rb')
+
+       Return a file object associated with the socket. The exact returned type depends on the arguments
+       given to makefile(). The support is limited to binary modes only ('rb' and 'wb').
+       CPython's arguments: ``encoding``, ``errors`` and ``newline`` are not supported.
+
+       The socket must be in blocking mode; it can have a timeout, but the file object’s internal buffer
+       may end up in a inconsistent state if a timeout occurs.
+
+       .. note::
+
+          **CPython difference:** closing the file object returned by makefile() WILL close the 
+          original socket as well.
+
+    .. method:: socket.read(size)
+
+       Read up to size bytes from the socket. Return a bytes object. If ``size`` is not given, it
+       behaves just like ``socket.readall()``, see below.
+
+    .. method:: socket.readall()
+
+       Read all data available from the socket until ``EOF``. This function will not return until
+       the socket is closed.
+
+    .. method:: socket.readinto(buf[, nbytes])
+
+       Read bytes into the ``buf``.  If ``nbytes`` is specified then read at most
+       that many bytes.  Otherwise, read at most ``len(buf)`` bytes.
+
+       Return value: number of bytes read and stored into ``buf``.
+
+    .. method:: socket.readline()
+
+       Read a line, ending in a newline character.
+
+       Return value: the line read.
+
+    .. method:: socket.write(buf)
+
+       Write the buffer of bytes to the socket.
+
+       Return value: number of bytes written.
diff --git a/docs/library/ussl.rst b/docs/library/ussl.rst
new file mode 100644
index 0000000000000000000000000000000000000000..9e97fac5021014b7680a8b9912c911f32f60aa8e
--- /dev/null
+++ b/docs/library/ussl.rst
@@ -0,0 +1,56 @@
+:mod:`ussl` -- ssl module
+===============================
+
+.. module:: ussl
+   :synopsis: TLS/SSL wrapper for socket objects
+
+This module provides access to Transport Layer Security (often known as 
+“Secure Sockets Layer”) encryption and peer authentication facilities for
+network sockets, both client-side and server-side.
+
+Functions
+---------
+
+.. function:: ssl.wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ca_certs=None)
+
+   Takes an instance sock of socket.socket, and returns an instance of ssl.SSLSocket, a subtype of 
+   ``socket.socket``, which wraps the underlying socket in an SSL context. sock must be a ``SOCK_STREAM``
+   socket and protocol number ``socket.IPPROTO_SEC``; other socket types are unsupported. Example::
+
+      import socket
+      import ssl
+      s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
+      ss = ssl.wrap_socket(s)
+      ss.connect(socket.getaddrinfo('www.google.com', 443)[0][4])
+
+   Certificates must be used in order to validate the other side of the connection, and also to
+   authenticate ourselves with the other end. Such certificates must be stored as files using the
+   FTP server, and they must be placed in specific paths with specific names.
+
+   - The certificate to validate the other side goes in: **'/flash/cert/ca.pem'**
+   - The certificate to authenticate ourselves goes in: **'/flash/cert/cert.pem'**
+   - The key for our own certificate goes in: **'/flash/cert/private.key'**
+
+   For instance to connect to the Blynk servers using certificates, take the file ``ca.pem`` located
+   in the `blynk examples folder <https://github.com/wipy/wipy/tree/master/examples/blynk>`_ 
+   and put it in '/flash/cert/'. Then do::
+
+      import socket
+      import ssl
+      s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
+      ss = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED, ca_certs='/flash/cert/ca.pem')
+      ss.connect(socket.getaddrinfo('cloud.blynk.cc', 8441)[0][4])
+
+Exceptions
+----------
+
+.. data:: ssl.SSLError
+
+Constants
+---------
+
+.. data:: ssl.CERT_NONE
+.. data:: ssl.CERT_OPTIONAL
+.. data:: ssl.CERT_REQUIRED
+
+    supported values in ``cert_reqs``
diff --git a/docs/library/wipy.rst b/docs/library/wipy.rst
index 66aecd05305aefa3ac9c81e405cd5b93f29e47a0..cdece7b82b5c378e24c8e7ba4b829408a3e5af3d 100644
--- a/docs/library/wipy.rst
+++ b/docs/library/wipy.rst
@@ -1,5 +1,6 @@
+*************************************
 :mod:`wipy` -- WiPy specific features
-=====================================
+*************************************
 
 .. module:: wipy
    :synopsis: WiPy specific features
@@ -12,4 +13,5 @@ Functions
 
 .. function:: heartbeat([enable])
 
-   Get or set the state (enabled or disabled) of the heartbeat LED.
+   Get or set the state (enabled or disabled) of the heartbeat LED. Accepts and
+   returns boolean values (``True`` or ``False``).