root/src/include/private/sangoma_tdm_api.h

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tdmv_api_wait_socket
  2. tdmv_api_readmsg_tdm
  3. tdmv_api_writemsg_tdm

   1 /*****************************************************************************
   2  * sangoma_tdm_api.h    Sangoma TDM API Portability functions
   3  *
   4  * Author(s):   Anthony Minessale II <anthm@freeswitch.org>
   5  *              Nenad Corbic <ncorbic@sangoma.com>
   6  *                              Michael Jerris <mike@jerris.com>
   7  *                              David Rokhvarg <davidr@sangoma.com>
   8  *
   9  * Copyright:   (c) 2006 Nenad Corbic <ncorbic@sangoma.com>
  10  *                       Anthony Minessale II
  11  *                              (c) 1984-2007 Sangoma Technologies Inc.
  12  *
  13  * ============================================================================
  14  */
  15 
  16 #ifndef _SANGOMA_TDM_API_H
  17 #define _SANGOMA_TDM_API_H
  18 
  19 /* This entire block of defines and includes from this line, through #define FNAME_LEN probably dont belong here */
  20 /* most of them probably belong in wanpipe_defines.h, then each header file listed included below properly included */
  21 /* in the header files that depend on them, leaving only the include for wanpipe_tdm_api.h left in this file or */
  22 /* possibly integrating the rest of this file diretly into wanpipe_tdm_api.h */
  23 #ifndef __WINDOWS__
  24 #if defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)
  25 #define __WINDOWS__
  26 #endif /* defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32) */
  27 #endif /* ndef __WINDOWS__ */
  28 
  29 #if defined(__WINDOWS__)
  30 #if defined(_MSC_VER)
  31 /* disable some warnings caused by wanpipe headers that will need to be fixed in those headers */
  32 #pragma warning(disable:4201 4214)
  33 
  34 /* sang_api.h(74) : warning C4201: nonstandard extension used : nameless struct/union */
  35 
  36 /* wanpipe_defines.h(219) : warning C4214: nonstandard extension used : bit field types other than int */
  37 /* wanpipe_defines.h(220) : warning C4214: nonstandard extension used : bit field types other than int */
  38 /* this will break for any compilers that are strict ansi or strict c99 */
  39 
  40 /* The following definition for that struct should resolve this warning and work for 32 and 64 bit */
  41 #if 0
  42 struct iphdr {
  43         
  44 #if defined(__LITTLE_ENDIAN_BITFIELD)
  45         unsigned    ihl:4,
  46                 version:4;
  47 #elif defined (__BIG_ENDIAN_BITFIELD)
  48         unsigned    version:4,
  49                 ihl:4;
  50 #else
  51 # error  "unknown byteorder!"
  52 #endif
  53         unsigned    tos:8;
  54         unsigned                tot_len:16;
  55         unsigned                id:16;
  56         unsigned                frag_off:16;
  57         __u8    ttl;
  58         __u8    protocol;
  59         __u16   check;
  60         __u32   saddr;
  61         __u32   daddr;
  62         /*The options start here. */
  63 };
  64 #endif /* #if 0 */
  65 
  66 #define __inline__ __inline
  67 #endif /* defined(_MSC_VER) */
  68 #include <windows.h>
  69 /* do we like the name WP_INVALID_SOCKET or should it be changed? */
  70 #define WP_INVALID_SOCKET INVALID_HANDLE_VALUE
  71 #else /* defined(__WINDOWS__) */ 
  72 #define WP_INVALID_SOCKET -1
  73 #include <stropts.h>
  74 #include <poll.h>
  75 #include <sys/socket.h>
  76 #endif
  77 
  78 #include <wanpipe_defines.h>
  79 #include <wanpipe_cfg.h>
  80 #include <wanpipe_tdm_api.h>
  81 #include <sdla_te1_pmc.h>
  82 #ifdef __WINDOWS__
  83 #include <sang_status_defines.h>
  84 #include <sang_api.h>
  85 #endif
  86 #include <sdla_aft_te1.h>
  87 
  88 #define FNAME_LEN       50
  89 
  90 
  91 #if defined(__WINDOWS__)
  92 /* This might be broken on windows, as POLL_EVENT_TELEPHONY seems to be commented out in sang_api.h.. it should be added to POLLPRI */
  93 #define POLLPRI (POLL_EVENT_LINK_STATE | POLL_EVENT_LINK_CONNECT | POLL_EVENT_LINK_DISCONNECT)
  94 #endif
  95 
  96 /* return -1 for error, 0 for timeout or 1 for success. *flags is set to the poll evetns POLLIN | POLLOUT | POLLPRI based on the result of the poll */
  97 /* on windows we actually have POLLPRI defined with several events, so we could theoretically poll */
  98 /* for specific events.  Is there any way to do this on *nix as well? */ 
  99 
 100 /* a cross platform way to poll on an actual pollset (span and/or list of spans) will probably also be needed for analog */
 101 /* so we can have one analong handler thread that will deal with all the idle analog channels for events */
 102 /* the alternative would be for the driver to provide one socket for all of the oob events for all analog channels */
 103 static __inline__ int tdmv_api_wait_socket(sng_fd_t fd, int timeout, int *flags)
 104 {
 105 #if defined(__WINDOWS__)
 106         DWORD ln;
 107         API_POLL_STRUCT api_poll;
 108 
 109         memset(&api_poll, 0x00, sizeof(API_POLL_STRUCT));
 110         
 111         api_poll.user_flags_bitmap = *flags;
 112         api_poll.timeout = timeout;
 113 
 114         if (!DeviceIoControl(
 115                                                  fd,
 116                                                  IoctlApiPoll,
 117                                                  (LPVOID)NULL,
 118                                                  0L,
 119                                                  (LPVOID)&api_poll,
 120                                                  sizeof(API_POLL_STRUCT),
 121                                                  (LPDWORD)(&ln),
 122                                                  (LPOVERLAPPED)NULL)) {
 123                 return -1;
 124         }
 125 
 126         *flags = 0;
 127 
 128         switch(api_poll.operation_status)
 129                 {
 130                 case SANG_STATUS_RX_DATA_AVAILABLE:
 131                         break;
 132 
 133                 case SANG_STATUS_RX_DATA_TIMEOUT:
 134                         return 0;
 135 
 136                 default:
 137                         return -1;
 138                 }
 139 
 140         if (api_poll.poll_events_bitmap == 0){
 141                 return -1;
 142         }
 143 
 144         if (api_poll.poll_events_bitmap & POLL_EVENT_TIMEOUT) {
 145                 return 0;
 146         }
 147 
 148         *flags = api_poll.poll_events_bitmap;
 149 
 150         return 1;
 151 #else
 152     struct pollfd pfds[1];
 153     int res;
 154 
 155     memset(&pfds[0], 0, sizeof(pfds[0]));
 156     pfds[0].fd = fd;
 157     pfds[0].events = *flags;
 158     res = poll(pfds, 1, timeout);
 159         *flags = 0;
 160 
 161         if (pfds[0].revents & POLLERR) {
 162                 res = -1;
 163         }
 164 
 165         if (res > 0) {
 166                 *flags = pfds[0].revents;
 167         }
 168 
 169     return res;
 170 #endif
 171 }
 172 
 173 /* on windows right now, there is no way to specify if we want to read events here or not, we allways get them here */
 174 /* we need some what to select if we are reading regular tdm msgs or events */
 175 /* need to either have 2 functions, 1 for events, 1 for regural read, or a flag on this function to choose */
 176 /* 2 functions preferred.  Need implementation for the event function for both nix and windows that is threadsafe */
 177 static __inline__ int tdmv_api_readmsg_tdm(sng_fd_t fd, void *hdrbuf, int hdrlen, void *databuf, int datalen)
 178 {
 179         /* What do we need to do here to avoid having to do all */
 180         /* the memcpy's on windows and still maintain api compat with nix */
 181         int rx_len=0;
 182 #if defined(__WINDOWS__)
 183         static RX_DATA_STRUCT   rx_data;
 184         api_header_t                    *pri;
 185         wp_tdm_api_rx_hdr_t             *tdm_api_rx_hdr;
 186         wp_tdm_api_rx_hdr_t             *user_buf = (wp_tdm_api_rx_hdr_t*)hdrbuf;
 187         DWORD ln;
 188 
 189         if (hdrlen != sizeof(wp_tdm_api_rx_hdr_t)){
 190                 return -1;
 191         }
 192 
 193         if (!DeviceIoControl(
 194                                                  fd,
 195                                                  IoctlReadCommand,
 196                                                  (LPVOID)NULL,
 197                                                  0L,
 198                                                  (LPVOID)&rx_data,
 199                                                  sizeof(RX_DATA_STRUCT),
 200                                                  (LPDWORD)(&ln),
 201                                                  (LPOVERLAPPED)NULL
 202                                                  )){
 203                 return -1;
 204         }
 205 
 206         pri = &rx_data.api_header;
 207         tdm_api_rx_hdr = (wp_tdm_api_rx_hdr_t*)rx_data.data;
 208 
 209         user_buf->wp_tdm_api_event_type = pri->operation_status;
 210 
 211         switch(pri->operation_status)
 212                 {
 213                 case SANG_STATUS_RX_DATA_AVAILABLE:
 214                         if (pri->data_length > datalen){
 215                                 break;
 216                         }
 217                         memcpy(databuf, rx_data.data, pri->data_length);
 218                         rx_len = pri->data_length;
 219                         break;
 220 
 221                 default:
 222                         break;
 223                 }
 224 
 225 #else
 226         struct msghdr msg;
 227         struct iovec iov[2];
 228 
 229         memset(&msg,0,sizeof(struct msghdr));
 230 
 231         iov[0].iov_len=hdrlen;
 232         iov[0].iov_base=hdrbuf;
 233 
 234         iov[1].iov_len=datalen;
 235         iov[1].iov_base=databuf;
 236 
 237         msg.msg_iovlen=2;
 238         msg.msg_iov=iov;
 239 
 240         rx_len = read(fd,&msg,datalen+hdrlen);
 241 
 242         if (rx_len <= sizeof(wp_tdm_api_rx_hdr_t)){
 243                 return -EINVAL;
 244         }
 245 
 246         rx_len-=sizeof(wp_tdm_api_rx_hdr_t);
 247 #endif
 248     return rx_len;
 249 }                    
 250 
 251 static __inline__ int tdmv_api_writemsg_tdm(sng_fd_t fd, void *hdrbuf, int hdrlen, void *databuf, unsigned short datalen)
 252 {
 253         /* What do we need to do here to avoid having to do all */
 254         /* the memcpy's on windows and still maintain api compat with nix */
 255         int bsent = 0;
 256 #if defined(__WINDOWS__)
 257         static TX_DATA_STRUCT   local_tx_data;
 258         api_header_t                    *pri;
 259         DWORD ln;
 260 
 261         /* Are these really not needed or used???  What about for nix?? */
 262         (void)hdrbuf;
 263         (void)hdrlen;
 264 
 265         pri = &local_tx_data.api_header;
 266 
 267         pri->data_length = datalen;
 268         memcpy(local_tx_data.data, databuf, pri->data_length);
 269 
 270         if (!DeviceIoControl(
 271                                                  fd,
 272                                                  IoctlWriteCommand,
 273                                                  (LPVOID)&local_tx_data,
 274                                                  (ULONG)sizeof(TX_DATA_STRUCT),
 275                                                  (LPVOID)&local_tx_data,
 276                                                  sizeof(TX_DATA_STRUCT),
 277                                                  (LPDWORD)(&ln),
 278                                                  (LPOVERLAPPED)NULL
 279                                                  )){
 280                 return -1;
 281         }
 282 
 283         if (local_tx_data.api_header.operation_status == SANG_STATUS_SUCCESS) {
 284                 bsent = datalen;
 285         }
 286 #else
 287         struct msghdr msg;
 288         struct iovec iov[2];
 289 
 290         memset(&msg,0,sizeof(struct msghdr));
 291 
 292         iov[0].iov_len = hdrlen;
 293         iov[0].iov_base = hdrbuf;
 294 
 295         iov[1].iov_len = datalen;
 296         iov[1].iov_base = databuf;
 297 
 298         msg.msg_iovlen = 2;
 299         msg.msg_iov = iov;
 300 
 301         bsent = write(fd, &msg, datalen + hdrlen);
 302         if (bsent > 0){
 303                 bsent -= sizeof(wp_tdm_api_tx_hdr_t);
 304         }
 305 #endif
 306         return bsent;
 307 }
 308 
 309 #endif /* _SANGOMA_TDM_API_H */
 310 
 311 /* For Emacs:
 312  * Local Variables:
 313  * mode:c
 314  * indent-tabs-mode:t
 315  * tab-width:4
 316  * c-basic-offset:4
 317  * End:
 318  * For VIM:
 319  * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
 320  */
 321 

/* [<][>][^][v][top][bottom][index][help] */