2727// We can't include stdio.h because it defines _types_fd_set, but we
2828// need to use the CC3000 version of this type.
2929
30- // We can't include errno.h because CC3000 defines its own errnos.
31- // (And they are different to the standard ones!)
32-
3330#include <std.h>
3431#include <string.h>
32+ #include <stdarg.h>
33+ #include <errno.h>
34+
35+ // CC3000 defines its own ENOBUFS (different to standard one!)
36+ // CC3000 uses global variable called errno
37+ #undef ENOBUFS
38+ #undef errno
3539
3640#include "stm32f4xx_hal.h"
3741#include "mpconfig.h"
4549#include "pin.h"
4650#include "genhdr/pins.h"
4751#include "spi.h"
52+ #include "pybioctl.h"
4853
4954#include "hci.h"
5055#include "socket.h"
@@ -61,17 +66,20 @@ STATIC const mp_obj_type_t cc3k_socket_type;
6166
6267STATIC mp_obj_t cc3k_socket_new (mp_uint_t family , mp_uint_t type , mp_uint_t protocol );
6368
64- STATIC volatile uint32_t fd_state = 0 ;
69+ STATIC volatile uint32_t fd_closed_state = 0 ;
6570STATIC volatile bool wlan_connected = false;
6671STATIC volatile bool ip_obtained = false;
6772
68- STATIC int cc3k_get_fd_state (int fd ) {
69- return ( fd_state & (1 << fd ) );
73+ STATIC int cc3k_get_fd_closed_state (int fd ) {
74+ return fd_closed_state & (1 << fd );
7075}
7176
72- STATIC void cc3k_clear_fd_state (int fd ) {
73- // reset socket state
74- fd_state &= ~(1 <<fd );
77+ STATIC void cc3k_set_fd_closed_state (int fd ) {
78+ fd_closed_state |= 1 << fd ;
79+ }
80+
81+ STATIC void cc3k_reset_fd_closed_state (int fd ) {
82+ fd_closed_state &= ~(1 << fd );
7583}
7684
7785STATIC void cc3k_callback (long event_type , char * data , unsigned char length ) {
@@ -89,7 +97,7 @@ STATIC void cc3k_callback(long event_type, char *data, unsigned char length) {
8997 break ;
9098 case HCI_EVNT_BSD_TCP_CLOSE_WAIT :
9199 // mark socket for closure
92- fd_state |= ( 1 <<(( uint8_t ) data [0 ]) );
100+ cc3k_set_fd_closed_state ( data [0 ]);
93101 break ;
94102 }
95103}
@@ -338,8 +346,6 @@ STATIC const mp_obj_type_t cc3k_type = {
338346/******************************************************************************/
339347// Micro Python bindings; CC3k socket class
340348
341- #define EPIPE (32)
342- //#define MAX_FD (8)
343349#define MAX_ADDRSTRLEN (128)
344350#define MAX_RX_PACKET (CC3000_RX_BUFFER_SIZE-CC3000_MINIMAL_RX_SIZE-1)
345351#define MAX_TX_PACKET (CC3000_TX_BUFFER_SIZE-CC3000_MINIMAL_TX_SIZE-1)
@@ -362,7 +368,7 @@ STATIC mp_obj_t cc3k_socket_new(mp_uint_t family, mp_uint_t type, mp_uint_t prot
362368 }
363369
364370 // clear socket state
365- cc3k_clear_fd_state (s -> fd );
371+ cc3k_reset_fd_closed_state (s -> fd );
366372
367373 return s ;
368374}
@@ -375,7 +381,7 @@ STATIC void cc3k_socket_print(void (*print)(void *env, const char *fmt, ...), vo
375381STATIC mp_uint_t cc3k_socket_send (mp_obj_t self_in , const void * buf , mp_uint_t size , int * errcode ) {
376382 cc3k_socket_obj_t * self = self_in ;
377383
378- if (cc3k_get_fd_state (self -> fd )) {
384+ if (cc3k_get_fd_closed_state (self -> fd )) {
379385 closesocket (self -> fd );
380386 * errcode = EPIPE ;
381387 return 0 ;
@@ -401,7 +407,7 @@ STATIC mp_uint_t cc3k_socket_send(mp_obj_t self_in, const void *buf, mp_uint_t s
401407STATIC mp_uint_t cc3k_socket_recv (mp_obj_t self_in , void * buf , mp_uint_t size , int * errcode ) {
402408 cc3k_socket_obj_t * self = self_in ;
403409
404- if (cc3k_get_fd_state (self -> fd )) {
410+ if (cc3k_get_fd_closed_state (self -> fd )) {
405411 closesocket (self -> fd );
406412 return 0 ;
407413 }
@@ -475,7 +481,7 @@ STATIC mp_obj_t cc3k_socket_accept(mp_obj_t self_in) {
475481 }
476482
477483 // clear socket state
478- cc3k_clear_fd_state (fd );
484+ cc3k_reset_fd_closed_state (fd );
479485
480486 // create new socket object
481487 cc3k_socket_obj_t * socket_obj = m_new_obj_with_finaliser (cc3k_socket_obj_t );
@@ -587,9 +593,74 @@ STATIC const mp_map_elem_t cc3k_socket_locals_dict_table[] = {
587593
588594STATIC MP_DEFINE_CONST_DICT (cc3k_socket_locals_dict , cc3k_socket_locals_dict_table );
589595
596+ mp_uint_t cc3k_ioctl (mp_obj_t self_in , mp_uint_t request , int * errcode , ...) {
597+ cc3k_socket_obj_t * self = self_in ;
598+ va_list vargs ;
599+ va_start (vargs , errcode );
600+ mp_uint_t ret ;
601+ if (request == MP_IOCTL_POLL ) {
602+ mp_uint_t flags = va_arg (vargs , mp_uint_t );
603+ ret = 0 ;
604+ int fd = self -> fd ;
605+
606+ // init fds
607+ fd_set rfds , wfds , xfds ;
608+ FD_ZERO (& rfds );
609+ FD_ZERO (& wfds );
610+ FD_ZERO (& xfds );
611+
612+ // set fds if needed
613+ if (flags & MP_IOCTL_POLL_RD ) {
614+ FD_SET (fd , & rfds );
615+
616+ // A socked that just closed is available for reading. A call to
617+ // recv() returns 0 which is consistent with BSD.
618+ if (cc3k_get_fd_closed_state (fd )) {
619+ ret |= MP_IOCTL_POLL_RD ;
620+ }
621+ }
622+ if (flags & MP_IOCTL_POLL_WR ) {
623+ FD_SET (fd , & wfds );
624+ }
625+ if (flags & MP_IOCTL_POLL_HUP ) {
626+ FD_SET (fd , & xfds );
627+ }
628+
629+ // call cc3000 select with minimum timeout
630+ timeval tv ;
631+ tv .tv_sec = 0 ;
632+ tv .tv_usec = 1 ;
633+ int nfds = select (fd + 1 , & rfds , & wfds , & xfds , & tv );
634+
635+ // check for error
636+ if (nfds == -1 ) {
637+ * errcode = errno ; // return cc3000's errno
638+ return -1 ;
639+ }
640+
641+ // check return of select
642+ if (FD_ISSET (fd , & rfds )) {
643+ ret |= MP_IOCTL_POLL_RD ;
644+ }
645+ if (FD_ISSET (fd , & wfds )) {
646+ ret |= MP_IOCTL_POLL_WR ;
647+ }
648+ if (FD_ISSET (fd , & xfds )) {
649+ ret |= MP_IOCTL_POLL_HUP ;
650+ }
651+ } else {
652+ * errcode = EINVAL ;
653+ ret = -1 ;
654+ }
655+ va_end (vargs );
656+ return ret ;
657+ }
658+
590659STATIC const mp_stream_p_t cc3k_socket_stream_p = {
591660 .read = cc3k_socket_recv ,
592661 .write = cc3k_socket_send ,
662+ .ioctl = cc3k_ioctl ,
663+ .is_text = false,
593664};
594665
595666STATIC const mp_obj_type_t cc3k_socket_type = {
@@ -602,114 +673,6 @@ STATIC const mp_obj_type_t cc3k_socket_type = {
602673 .locals_dict = (mp_obj_t )& cc3k_socket_locals_dict ,
603674};
604675
605- // the following code is for select, which is yet to be implemented
606- #if 0
607- #define MP_ASSERT_TYPE (obj , type ) \
608- do { \
609- __typeof__ (obj) _a = (obj); \
610- __typeof__ (type) _b = (type); \
611- if (!MP_OBJ_IS_TYPE(_a, _b)) { \
612- nlr_jump(mp_obj_new_exception_msg_varg( \
613- &mp_type_TypeError, \
614- "can't convert %s to %s", \
615- mp_obj_get_type_str(_a), \
616- _b->name)); \
617- } \
618- } while(0)
619-
620- // select helper functions
621- STATIC void set_fds (int * nfds , mp_obj_t * fdlist , mp_uint_t fdlist_len , fd_set * fdset ) {
622-
623- // clear fd set
624- FD_ZERO (fdset );
625-
626- // add sockets to fd set
627- for (int i = 0 ; i < fdlist_len ; i ++ ) {
628- socket_t * s = fdlist [i ];
629-
630- // check arg type
631- MP_ASSERT_TYPE (s , & cc3k_socket_type );
632-
633- // add to fd set
634- FD_SET (s -> fd , fdset );
635-
636- if (s -> fd > (* nfds )) {
637- * nfds = s -> fd ;
638- }
639- }
640- }
641-
642- STATIC void get_fds (mp_obj_t * fdlist , mp_uint_t fdlist_len , mp_obj_t * fdlist_out , fd_set * fdset ) {
643- for (int i = 0 ; i < fdlist_len ; i ++ ) {
644- socket_t * s = fdlist [i ];
645- if (FD_ISSET (s -> fd , fdset )) {
646- socket_t * socket_obj = m_new_obj_with_finaliser (socket_t );
647- socket_obj -> base .type = (mp_obj_t )& socket_type ;
648- socket_obj -> fd = s -> fd ;
649- mp_obj_list_append (fdlist_out , socket_obj );
650- }
651- }
652- }
653-
654- STATIC mp_obj_t cc3k_select (mp_uint_t n_args , const mp_obj_t * args ) {
655- int nfds = 0 ; //highest-numbered fd plus 1
656- timeval tv = {0 };
657- fd_set rfds , wfds , xfds ;
658-
659- mp_obj_t * rlist , * wlist , * xlist ;
660- mp_uint_t rlist_len , wlist_len , xlist_len ;
661-
662- // read args
663- mp_obj_get_array (args [0 ], & rlist_len , & rlist );
664- mp_obj_get_array (args [1 ], & wlist_len , & wlist );
665- mp_obj_get_array (args [2 ], & xlist_len , & xlist );
666-
667- if (n_args == 4 ) {
668- float timeout = mp_obj_get_float (args [3 ]);
669- tv .tv_sec = (int )timeout ;
670- tv .tv_usec = (timeout - (int )timeout )* 1000 * 1000 ;
671- }
672-
673- // add fds to their respective sets
674- set_fds (& nfds , rlist , rlist_len , & rfds );
675- set_fds (& nfds , wlist , wlist_len , & wfds );
676- set_fds (& nfds , xlist , xlist_len , & xfds );
677-
678- // call select
679- nfds = select (nfds + 1 , & rfds , & wfds , & xfds , & tv );
680-
681- // if any of the read sockets is closed, we add it to the read fd set,
682- // a subsequent call to recv() returns 0. This behavior is consistent with BSD.
683- for (int i = 0 ; i < rlist_len ; i ++ ) {
684- socket_t * s = rlist [i ];
685- if (cc3k_get_fd_state (s -> fd )) {
686- FD_SET (s -> fd , & rfds );
687- nfds = (nfds > s -> fd )? nfds :s -> fd ;
688- }
689- }
690-
691- // return value; a tuple of 3 lists
692- mp_obj_t fds [3 ] = {
693- mp_obj_new_list (0 , NULL ),
694- mp_obj_new_list (0 , NULL ),
695- mp_obj_new_list (0 , NULL )
696- };
697-
698- // On success, select() returns the number of file descriptors contained
699- // in the three returned descriptor sets which may be zero if the timeout
700- // expires before anything interesting happens, -1 is returned on error.
701- if (nfds == -1 ) { // select failed
702- nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , "select failed" ));
703- } else if (nfds ) { // an fd is ready
704- get_fds (rlist , rlist_len , fds [0 ], & rfds );
705- get_fds (wlist , wlist_len , fds [1 ], & wfds );
706- get_fds (xlist , xlist_len , fds [2 ], & xfds );
707- } // select timedout
708-
709- return mp_obj_new_tuple (3 , fds );
710- }
711- #endif
712-
713676/******************************************************************************/
714677// Micro Python bindings; CC3k module
715678
0 commit comments