Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
socket.cpp
00001 /***************************************************************************** 00002 * 00003 * socket.c - CC3000 Host Driver Implementation. 00004 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 00010 * Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 00013 * Redistributions in binary form must reproduce the above copyright 00014 * notice, this list of conditions and the following disclaimer in the 00015 * documentation and/or other materials provided with the 00016 * distribution. 00017 * 00018 * Neither the name of Texas Instruments Incorporated nor the names of 00019 * its contributors may be used to endorse or promote products derived 00020 * from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00023 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00024 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00025 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00026 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00027 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00028 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00029 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00030 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00031 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00032 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 * 00034 *****************************************************************************/ 00035 00036 //***************************************************************************** 00037 // 00038 //! \addtogroup socket_api 00039 //! @{ 00040 // 00041 //***************************************************************************** 00042 00043 #include <stdio.h> 00044 #include <string.h> 00045 #include <stdlib.h> 00046 #include "hci.h" 00047 #include "socket.h" 00048 #include "evnt_handler.h" 00049 #include "netapp.h" 00050 00051 00052 00053 //Enable this flag if and only if you must comply with BSD socket 00054 //close() function 00055 #ifdef _API_USE_BSD_CLOSE 00056 #define close(sd) closesocket(sd) 00057 #endif 00058 00059 //Enable this flag if and only if you must comply with BSD socket read() and 00060 //write() functions 00061 #ifdef _API_USE_BSD_READ_WRITE 00062 #define read(sd, buf, len, flags) recv(sd, buf, len, flags) 00063 #define write(sd, buf, len, flags) send(sd, buf, len, flags) 00064 #endif 00065 00066 #define SOCKET_OPEN_PARAMS_LEN (12) 00067 #define SOCKET_CLOSE_PARAMS_LEN (4) 00068 #define SOCKET_ACCEPT_PARAMS_LEN (4) 00069 #define SOCKET_BIND_PARAMS_LEN (20) 00070 #define SOCKET_LISTEN_PARAMS_LEN (8) 00071 #define SOCKET_GET_HOST_BY_NAME_PARAMS_LEN (9) 00072 #define SOCKET_CONNECT_PARAMS_LEN (20) 00073 #define SOCKET_SELECT_PARAMS_LEN (44) 00074 #define SOCKET_SET_SOCK_OPT_PARAMS_LEN (20) 00075 #define SOCKET_GET_SOCK_OPT_PARAMS_LEN (12) 00076 #define SOCKET_RECV_FROM_PARAMS_LEN (12) 00077 #define SOCKET_SENDTO_PARAMS_LEN (24) 00078 #define SOCKET_MDNS_ADVERTISE_PARAMS_LEN (12) 00079 00080 00081 // The legnth of arguments for the SEND command: sd + buff_offset + len + flags, 00082 // while size of each parameter is 32 bit - so the total length is 16 bytes; 00083 00084 #define HCI_CMND_SEND_ARG_LENGTH (16) 00085 00086 00087 #define SELECT_TIMEOUT_MIN_MICRO_SECONDS 5000 00088 00089 #define HEADERS_SIZE_DATA (SPI_HEADER_SIZE + 5) 00090 00091 #define SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE) 00092 00093 #define MDNS_DEVICE_SERVICE_MAX_LENGTH (32) 00094 00095 00096 //***************************************************************************** 00097 // 00098 //! HostFlowControlConsumeBuff 00099 //! 00100 //! @param sd socket descriptor 00101 //! 00102 //! @return 0 in case there are buffers available, 00103 //! -1 in case of bad socket 00104 //! -2 if there are no free buffers present (only when 00105 //! SEND_NON_BLOCKING is enabled) 00106 //! 00107 //! @brief if SEND_NON_BLOCKING not define - block until have free buffer 00108 //! becomes available, else return immediately with correct status 00109 //! regarding the buffers available. 00110 // 00111 //***************************************************************************** 00112 int 00113 HostFlowControlConsumeBuff(int sd) 00114 { 00115 #ifndef SEND_NON_BLOCKING 00116 /* wait in busy loop */ 00117 do 00118 { 00119 // In case last transmission failed then we will return the last failure 00120 // reason here. 00121 // Note that the buffer will not be allocated in this case 00122 if (tSLInformation.slTransmitDataError != 0) 00123 { 00124 errno = tSLInformation.slTransmitDataError; 00125 tSLInformation.slTransmitDataError = 0; 00126 return errno; 00127 } 00128 00129 if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd)) 00130 return -1; 00131 } while(0 == tSLInformation.usNumberOfFreeBuffers); 00132 00133 tSLInformation.usNumberOfFreeBuffers--; 00134 00135 return 0; 00136 #else 00137 00138 // In case last transmission failed then we will return the last failure 00139 // reason here. 00140 // Note that the buffer will not be allocated in this case 00141 if (tSLInformation.slTransmitDataError != 0) 00142 { 00143 errno = tSLInformation.slTransmitDataError; 00144 tSLInformation.slTransmitDataError = 0; 00145 return errno; 00146 } 00147 if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd)) 00148 return -1; 00149 00150 //If there are no available buffers, return -2. It is recommended to use 00151 // select or receive to see if there is any buffer occupied with received data 00152 // If so, call receive() to release the buffer. 00153 if(0 == tSLInformation.usNumberOfFreeBuffers) 00154 { 00155 return -2; 00156 } 00157 else 00158 { 00159 tSLInformation.usNumberOfFreeBuffers--; 00160 return 0; 00161 } 00162 #endif 00163 } 00164 00165 //***************************************************************************** 00166 // 00167 //! socket 00168 //! 00169 //! @param domain selects the protocol family which will be used for 00170 //! communication. On this version only AF_INET is supported 00171 //! @param type specifies the communication semantics. On this version 00172 //! only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported 00173 //! @param protocol specifies a particular protocol to be used with the 00174 //! socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are 00175 //! supported. 00176 //! 00177 //! @return On success, socket handle that is used for consequent socket 00178 //! operations. On error, -1 is returned. 00179 //! 00180 //! @brief create an endpoint for communication 00181 //! The socket function creates a socket that is bound to a specific 00182 //! transport service provider. This function is called by the 00183 //! application layer to obtain a socket handle. 00184 // 00185 //***************************************************************************** 00186 00187 int 00188 socket(long domain, long type, long protocol) 00189 { 00190 long ret; 00191 unsigned char *ptr, *args; 00192 00193 ret = EFAIL; 00194 ptr = tSLInformation.pucTxCommandBuffer; 00195 args = (ptr + HEADERS_SIZE_CMD); 00196 00197 // Fill in HCI packet structure 00198 args = UINT32_TO_STREAM(args, domain); 00199 args = UINT32_TO_STREAM(args, type); 00200 args = UINT32_TO_STREAM(args, protocol); 00201 00202 // Initiate a HCI command 00203 hci_command_send(HCI_CMND_SOCKET, ptr, SOCKET_OPEN_PARAMS_LEN); 00204 00205 // Since we are in blocking state - wait for event complete 00206 SimpleLinkWaitEvent(HCI_CMND_SOCKET, &ret); 00207 00208 // Process the event 00209 errno = ret; 00210 00211 set_socket_active_status(ret, SOCKET_STATUS_ACTIVE); 00212 00213 return(ret); 00214 } 00215 00216 //***************************************************************************** 00217 // 00218 //! closesocket 00219 //! 00220 //! @param sd socket handle. 00221 //! 00222 //! @return On success, zero is returned. On error, -1 is returned. 00223 //! 00224 //! @brief The socket function closes a created socket. 00225 // 00226 //***************************************************************************** 00227 00228 long 00229 closesocket(long sd) 00230 { 00231 long ret; 00232 unsigned char *ptr, *args; 00233 00234 ret = EFAIL; 00235 ptr = tSLInformation.pucTxCommandBuffer; 00236 args = (ptr + HEADERS_SIZE_CMD); 00237 00238 // Fill in HCI packet structure 00239 args = UINT32_TO_STREAM(args, sd); 00240 00241 // Initiate a HCI command 00242 hci_command_send(HCI_CMND_CLOSE_SOCKET, 00243 ptr, SOCKET_CLOSE_PARAMS_LEN); 00244 00245 // Since we are in blocking state - wait for event complete 00246 SimpleLinkWaitEvent(HCI_CMND_CLOSE_SOCKET, &ret); 00247 errno = ret; 00248 00249 // since 'close' call may result in either OK (and then it closed) or error 00250 // mark this socket as invalid 00251 set_socket_active_status(sd, SOCKET_STATUS_INACTIVE); 00252 00253 return(ret); 00254 } 00255 00256 //***************************************************************************** 00257 // 00258 //! accept 00259 //! 00260 //! @param[in] sd socket descriptor (handle) 00261 //! @param[out] addr the argument addr is a pointer to a sockaddr structure 00262 //! This structure is filled in with the address of the 00263 //! peer socket, as known to the communications layer. 00264 //! determined. The exact format of the address returned 00265 //! addr is by the socket's address sockaddr. 00266 //! On this version only AF_INET is supported. 00267 //! This argument returns in network order. 00268 //! @param[out] addrlen the addrlen argument is a value-result argument: 00269 //! it should initially contain the size of the structure 00270 //! pointed to by addr. 00271 //! 00272 //! @return For socket in blocking mode: 00273 //! On success, socket handle. on failure negative 00274 //! For socket in non-blocking mode: 00275 //! - On connection establishment, socket handle 00276 //! - On connection pending, SOC_IN_PROGRESS (-2) 00277 //! - On failure, SOC_ERROR (-1) 00278 //! 00279 //! @brief accept a connection on a socket: 00280 //! This function is used with connection-based socket types 00281 //! (SOCK_STREAM). It extracts the first connection request on the 00282 //! queue of pending connections, creates a new connected socket, and 00283 //! returns a new file descriptor referring to that socket. 00284 //! The newly created socket is not in the listening state. 00285 //! The original socket sd is unaffected by this call. 00286 //! The argument sd is a socket that has been created with socket(), 00287 //! bound to a local address with bind(), and is listening for 00288 //! connections after a listen(). The argument addr is a pointer 00289 //! to a sockaddr structure. This structure is filled in with the 00290 //! address of the peer socket, as known to the communications layer. 00291 //! The exact format of the address returned addr is determined by the 00292 //! socket's address family. The addrlen argument is a value-result 00293 //! argument: it should initially contain the size of the structure 00294 //! pointed to by addr, on return it will contain the actual 00295 //! length (in bytes) of the address returned. 00296 //! 00297 //! @sa socket ; bind ; listen 00298 // 00299 //***************************************************************************** 00300 00301 long 00302 accept(long sd, sockaddr *addr, socklen_t *addrlen) 00303 { 00304 long ret; 00305 unsigned char *ptr, *args; 00306 tBsdReturnParams tAcceptReturnArguments; 00307 00308 ret = EFAIL; 00309 ptr = tSLInformation.pucTxCommandBuffer; 00310 args = (ptr + HEADERS_SIZE_CMD); 00311 00312 // Fill in temporary command buffer 00313 args = UINT32_TO_STREAM(args, sd); 00314 00315 // Initiate a HCI command 00316 hci_command_send(HCI_CMND_ACCEPT, ptr, SOCKET_ACCEPT_PARAMS_LEN); 00317 00318 // Since we are in blocking state - wait for event complete 00319 SimpleLinkWaitEvent(HCI_CMND_ACCEPT, (long*)&tAcceptReturnArguments); 00320 00321 00322 // need specify return parameters!!! 00323 memcpy(addr, &tAcceptReturnArguments.tSocketAddress, ASIC_ADDR_LEN); 00324 *addrlen = ASIC_ADDR_LEN; 00325 errno = tAcceptReturnArguments.iStatus; 00326 ret = errno; 00327 00328 // if succeeded, iStatus = new socket descriptor. otherwise - error number 00329 if(M_IS_VALID_SD(ret)) 00330 { 00331 set_socket_active_status(ret, SOCKET_STATUS_ACTIVE); 00332 } 00333 else 00334 { 00335 set_socket_active_status(sd, SOCKET_STATUS_INACTIVE); 00336 } 00337 00338 return(ret); 00339 } 00340 00341 //***************************************************************************** 00342 // 00343 //! bind 00344 //! 00345 //! @param[in] sd socket descriptor (handle) 00346 //! @param[out] addr specifies the destination address. On this version 00347 //! only AF_INET is supported. 00348 //! @param[out] addrlen contains the size of the structure pointed to by addr. 00349 //! 00350 //! @return On success, zero is returned. On error, -1 is returned. 00351 //! 00352 //! @brief assign a name to a socket 00353 //! This function gives the socket the local address addr. 00354 //! addr is addrlen bytes long. Traditionally, this is called when a 00355 //! socket is created with socket, it exists in a name space (address 00356 //! family) but has no name assigned. 00357 //! It is necessary to assign a local address before a SOCK_STREAM 00358 //! socket may receive connections. 00359 //! 00360 //! @sa socket ; accept ; listen 00361 // 00362 //***************************************************************************** 00363 00364 long 00365 bind(long sd, const sockaddr *addr, long addrlen) 00366 { 00367 long ret; 00368 unsigned char *ptr, *args; 00369 00370 ret = EFAIL; 00371 ptr = tSLInformation.pucTxCommandBuffer; 00372 args = (ptr + HEADERS_SIZE_CMD); 00373 00374 addrlen = ASIC_ADDR_LEN; 00375 00376 // Fill in temporary command buffer 00377 args = UINT32_TO_STREAM(args, sd); 00378 args = UINT32_TO_STREAM(args, 0x00000008); 00379 args = UINT32_TO_STREAM(args, addrlen); 00380 ARRAY_TO_STREAM(args, ((unsigned char *)addr), addrlen); 00381 00382 // Initiate a HCI command 00383 hci_command_send(HCI_CMND_BIND, ptr, SOCKET_BIND_PARAMS_LEN); 00384 00385 // Since we are in blocking state - wait for event complete 00386 SimpleLinkWaitEvent(HCI_CMND_BIND, &ret); 00387 00388 errno = ret; 00389 00390 return(ret); 00391 } 00392 00393 //***************************************************************************** 00394 // 00395 //! listen 00396 //! 00397 //! @param[in] sd socket descriptor (handle) 00398 //! @param[in] backlog specifies the listen queue depth. On this version 00399 //! backlog is not supported. 00400 //! @return On success, zero is returned. On error, -1 is returned. 00401 //! 00402 //! @brief listen for connections on a socket 00403 //! The willingness to accept incoming connections and a queue 00404 //! limit for incoming connections are specified with listen(), 00405 //! and then the connections are accepted with accept. 00406 //! The listen() call applies only to sockets of type SOCK_STREAM 00407 //! The backlog parameter defines the maximum length the queue of 00408 //! pending connections may grow to. 00409 //! 00410 //! @sa socket ; accept ; bind 00411 //! 00412 //! @note On this version, backlog is not supported 00413 // 00414 //***************************************************************************** 00415 00416 long 00417 listen(long sd, long backlog) 00418 { 00419 long ret; 00420 unsigned char *ptr, *args; 00421 00422 ret = EFAIL; 00423 ptr = tSLInformation.pucTxCommandBuffer; 00424 args = (ptr + HEADERS_SIZE_CMD); 00425 00426 // Fill in temporary command buffer 00427 args = UINT32_TO_STREAM(args, sd); 00428 args = UINT32_TO_STREAM(args, backlog); 00429 00430 // Initiate a HCI command 00431 hci_command_send(HCI_CMND_LISTEN, ptr, SOCKET_LISTEN_PARAMS_LEN); 00432 00433 // Since we are in blocking state - wait for event complete 00434 SimpleLinkWaitEvent(HCI_CMND_LISTEN, &ret); 00435 errno = ret; 00436 00437 return(ret); 00438 } 00439 00440 //***************************************************************************** 00441 // 00442 //! gethostbyname 00443 //! 00444 //! @param[in] hostname host name 00445 //! @param[in] usNameLen name length 00446 //! @param[out] out_ip_addr This parameter is filled in with host IP address. 00447 //! In case that host name is not resolved, 00448 //! out_ip_addr is zero. 00449 //! @return On success, positive is returned. On error, negative is returned 00450 //! 00451 //! @brief Get host IP by name. Obtain the IP Address of machine on network, 00452 //! by its name. 00453 //! 00454 //! @note On this version, only blocking mode is supported. Also note that 00455 //! the function requires DNS server to be configured prior to its usage. 00456 // 00457 //***************************************************************************** 00458 00459 #ifndef CC3000_TINY_DRIVER 00460 int 00461 gethostbyname(char * hostname, unsigned short usNameLen, unsigned long* out_ip_addr) 00462 { 00463 tBsdGethostbynameParams ret; 00464 unsigned char *ptr, *args; 00465 00466 errno = EFAIL; 00467 00468 if (usNameLen > HOSTNAME_MAX_LENGTH) 00469 { 00470 return errno; 00471 } 00472 00473 ptr = tSLInformation.pucTxCommandBuffer; 00474 args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); 00475 00476 // Fill in HCI packet structure 00477 args = UINT32_TO_STREAM(args, 8); 00478 args = UINT32_TO_STREAM(args, usNameLen); 00479 ARRAY_TO_STREAM(args, hostname, usNameLen); 00480 00481 // Initiate a HCI command 00482 hci_command_send(HCI_CMND_GETHOSTNAME, ptr, SOCKET_GET_HOST_BY_NAME_PARAMS_LEN + usNameLen - 1); 00483 00484 // Since we are in blocking state - wait for event complete 00485 SimpleLinkWaitEvent(HCI_EVNT_BSD_GETHOSTBYNAME, (long*)&ret); 00486 00487 errno = ret.retVal; 00488 00489 (*((long*)out_ip_addr)) = ret.outputAddress; 00490 00491 return (errno); 00492 00493 } 00494 #endif 00495 00496 //***************************************************************************** 00497 // 00498 //! connect 00499 //! 00500 //! @param[in] sd socket descriptor (handle) 00501 //! @param[in] addr specifies the destination addr. On this version 00502 //! only AF_INET is supported. 00503 //! @param[out] addrlen contains the size of the structure pointed to by addr 00504 //! @return On success, zero is returned. On error, -1 is returned 00505 //! 00506 //! @brief initiate a connection on a socket 00507 //! Function connects the socket referred to by the socket descriptor 00508 //! sd, to the address specified by addr. The addrlen argument 00509 //! specifies the size of addr. The format of the address in addr is 00510 //! determined by the address space of the socket. If it is of type 00511 //! SOCK_DGRAM, this call specifies the peer with which the socket is 00512 //! to be associated; this address is that to which datagrams are to be 00513 //! sent, and the only address from which datagrams are to be received. 00514 //! If the socket is of type SOCK_STREAM, this call attempts to make a 00515 //! connection to another socket. The other socket is specified by 00516 //! address, which is an address in the communications space of the 00517 //! socket. Note that the function implements only blocking behavior 00518 //! thus the caller will be waiting either for the connection 00519 //! establishment or for the connection establishment failure. 00520 //! 00521 //! @sa socket 00522 // 00523 //***************************************************************************** 00524 00525 long 00526 connect(long sd, const sockaddr *addr, long addrlen) 00527 { 00528 long int ret; 00529 unsigned char *ptr, *args; 00530 00531 ret = EFAIL; 00532 ptr = tSLInformation.pucTxCommandBuffer; 00533 args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); 00534 addrlen = 8; 00535 00536 // Fill in temporary command buffer 00537 args = UINT32_TO_STREAM(args, sd); 00538 args = UINT32_TO_STREAM(args, 0x00000008); 00539 args = UINT32_TO_STREAM(args, addrlen); 00540 ARRAY_TO_STREAM(args, ((unsigned char *)addr), addrlen); 00541 00542 // Initiate a HCI command 00543 hci_command_send(HCI_CMND_CONNECT, 00544 ptr, SOCKET_CONNECT_PARAMS_LEN); 00545 00546 // Since we are in blocking state - wait for event complete 00547 SimpleLinkWaitEvent(HCI_CMND_CONNECT, &ret); 00548 00549 errno = ret; 00550 00551 return((long)ret); 00552 } 00553 00554 00555 //***************************************************************************** 00556 // 00557 //! select 00558 //! 00559 //! @param[in] nfds the highest-numbered file descriptor in any of the 00560 //! three sets, plus 1. 00561 //! @param[out] writesds socket descriptors list for write monitoring 00562 //! @param[out] readsds socket descriptors list for read monitoring 00563 //! @param[out] exceptsds socket descriptors list for exception monitoring 00564 //! @param[in] timeout is an upper bound on the amount of time elapsed 00565 //! before select() returns. Null means infinity 00566 //! timeout. The minimum timeout is 5 milliseconds, 00567 //! less than 5 milliseconds will be set 00568 //! automatically to 5 milliseconds. 00569 //! @return On success, select() returns the number of file descriptors 00570 //! contained in the three returned descriptor sets (that is, the 00571 //! total number of bits that are set in readfds, writefds, 00572 //! exceptfds) which may be zero if the timeout expires before 00573 //! anything interesting happens. 00574 //! On error, -1 is returned. 00575 //! *readsds - return the sockets on which Read request will 00576 //! return without delay with valid data. 00577 //! *writesds - return the sockets on which Write request 00578 //! will return without delay. 00579 //! *exceptsds - return the sockets which closed recently. 00580 //! 00581 //! @brief Monitor socket activity 00582 //! Select allow a program to monitor multiple file descriptors, 00583 //! waiting until one or more of the file descriptors become 00584 //! "ready" for some class of I/O operation 00585 //! 00586 //! @Note If the timeout value set to less than 5ms it will automatically set 00587 //! to 5ms to prevent overload of the system 00588 //! 00589 //! @sa socket 00590 // 00591 //***************************************************************************** 00592 00593 int 00594 select(long nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds, 00595 struct timeval *timeout) 00596 { 00597 unsigned char *ptr, *args; 00598 tBsdSelectRecvParams tParams; 00599 unsigned long is_blocking; 00600 00601 if( timeout == NULL) 00602 { 00603 is_blocking = 1; /* blocking , infinity timeout */ 00604 } 00605 else 00606 { 00607 is_blocking = 0; /* no blocking, timeout */ 00608 } 00609 00610 // Fill in HCI packet structure 00611 ptr = tSLInformation.pucTxCommandBuffer; 00612 args = (ptr + HEADERS_SIZE_CMD); 00613 00614 // Fill in temporary command buffer 00615 args = UINT32_TO_STREAM(args, nfds); 00616 args = UINT32_TO_STREAM(args, 0x00000014); 00617 args = UINT32_TO_STREAM(args, 0x00000014); 00618 args = UINT32_TO_STREAM(args, 0x00000014); 00619 args = UINT32_TO_STREAM(args, 0x00000014); 00620 args = UINT32_TO_STREAM(args, is_blocking); 00621 args = UINT32_TO_STREAM(args, ((readsds) ? *(unsigned long*)readsds : 0)); 00622 args = UINT32_TO_STREAM(args, ((writesds) ? *(unsigned long*)writesds : 0)); 00623 args = UINT32_TO_STREAM(args, ((exceptsds) ? *(unsigned long*)exceptsds : 0)); 00624 00625 if (timeout) 00626 { 00627 if ( 0 == timeout->tv_sec && timeout->tv_usec < 00628 SELECT_TIMEOUT_MIN_MICRO_SECONDS) 00629 { 00630 timeout->tv_usec = SELECT_TIMEOUT_MIN_MICRO_SECONDS; 00631 } 00632 args = UINT32_TO_STREAM(args, timeout->tv_sec); 00633 args = UINT32_TO_STREAM(args, timeout->tv_usec); 00634 } 00635 00636 // Initiate a HCI command 00637 hci_command_send(HCI_CMND_BSD_SELECT, ptr, SOCKET_SELECT_PARAMS_LEN); 00638 00639 // Since we are in blocking state - wait for event complete 00640 SimpleLinkWaitEvent(HCI_EVNT_SELECT, (long*)&tParams); 00641 00642 // Update actually read FD 00643 if (tParams.iStatus >= 0) 00644 { 00645 if (readsds) 00646 { 00647 memcpy(readsds, &tParams.uiRdfd, sizeof(tParams.uiRdfd)); 00648 } 00649 00650 if (writesds) 00651 { 00652 memcpy(writesds, &tParams.uiWrfd, sizeof(tParams.uiWrfd)); 00653 } 00654 00655 if (exceptsds) 00656 { 00657 memcpy(exceptsds, &tParams.uiExfd, sizeof(tParams.uiExfd)); 00658 } 00659 00660 return(tParams.iStatus); 00661 00662 } 00663 else 00664 { 00665 errno = tParams.iStatus; 00666 return(-1); 00667 } 00668 } 00669 00670 //***************************************************************************** 00671 // 00672 //! setsockopt 00673 //! 00674 //! @param[in] sd socket handle 00675 //! @param[in] level defines the protocol level for this option 00676 //! @param[in] optname defines the option name to Interrogate 00677 //! @param[in] optval specifies a value for the option 00678 //! @param[in] optlen specifies the length of the option value 00679 //! @return On success, zero is returned. On error, -1 is returned 00680 //! 00681 //! @brief set socket options 00682 //! This function manipulate the options associated with a socket. 00683 //! Options may exist at multiple protocol levels; they are always 00684 //! present at the uppermost socket level. 00685 //! When manipulating socket options the level at which the option 00686 //! resides and the name of the option must be specified. 00687 //! To manipulate options at the socket level, level is specified as 00688 //! SOL_SOCKET. To manipulate options at any other level the protocol 00689 //! number of the appropriate protocol controlling the option is 00690 //! supplied. For example, to indicate that an option is to be 00691 //! interpreted by the TCP protocol, level should be set to the 00692 //! protocol number of TCP; 00693 //! The parameters optval and optlen are used to access optval - 00694 //! use for setsockopt(). For getsockopt() they identify a buffer 00695 //! in which the value for the requested option(s) are to 00696 //! be returned. For getsockopt(), optlen is a value-result 00697 //! parameter, initially containing the size of the buffer 00698 //! pointed to by option_value, and modified on return to 00699 //! indicate the actual size of the value returned. If no option 00700 //! value is to be supplied or returned, option_value may be NULL. 00701 //! 00702 //! @Note On this version the following two socket options are enabled: 00703 //! The only protocol level supported in this version 00704 //! is SOL_SOCKET (level). 00705 //! 1. SOCKOPT_RECV_TIMEOUT (optname) 00706 //! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout 00707 //! in milliseconds. 00708 //! In that case optval should be pointer to unsigned long. 00709 //! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on 00710 //! or off. 00711 //! In that case optval should be SOCK_ON or SOCK_OFF (optval). 00712 //! 00713 //! @sa getsockopt 00714 // 00715 //***************************************************************************** 00716 00717 #ifndef CC3000_TINY_DRIVER 00718 int 00719 setsockopt(long sd, long level, long optname, const void *optval, 00720 socklen_t optlen) 00721 { 00722 int ret; 00723 unsigned char *ptr, *args; 00724 00725 ptr = tSLInformation.pucTxCommandBuffer; 00726 args = (ptr + HEADERS_SIZE_CMD); 00727 00728 // Fill in temporary command buffer 00729 args = UINT32_TO_STREAM(args, sd); 00730 args = UINT32_TO_STREAM(args, level); 00731 args = UINT32_TO_STREAM(args, optname); 00732 args = UINT32_TO_STREAM(args, 0x00000008); 00733 args = UINT32_TO_STREAM(args, optlen); 00734 ARRAY_TO_STREAM(args, ((unsigned char *)optval), optlen); 00735 00736 // Initiate a HCI command 00737 hci_command_send(HCI_CMND_SETSOCKOPT, ptr, SOCKET_SET_SOCK_OPT_PARAMS_LEN + optlen); 00738 00739 // Since we are in blocking state - wait for event complete 00740 SimpleLinkWaitEvent(HCI_CMND_SETSOCKOPT, (long*)&ret); 00741 00742 if (ret >= 0) 00743 { 00744 return (0); 00745 } 00746 else 00747 { 00748 errno = ret; 00749 return (errno); 00750 } 00751 } 00752 #endif 00753 00754 //***************************************************************************** 00755 // 00756 //! getsockopt 00757 //! 00758 //! @param[in] sd socket handle 00759 //! @param[in] level defines the protocol level for this option 00760 //! @param[in] optname defines the option name to Interrogate 00761 //! @param[out] optval specifies a value for the option 00762 //! @param[out] optlen specifies the length of the option value 00763 //! @return On success, zero is returned. On error, -1 is returned 00764 //! 00765 //! @brief set socket options 00766 //! This function manipulate the options associated with a socket. 00767 //! Options may exist at multiple protocol levels; they are always 00768 //! present at the uppermost socket level. 00769 //! When manipulating socket options the level at which the option 00770 //! resides and the name of the option must be specified. 00771 //! To manipulate options at the socket level, level is specified as 00772 //! SOL_SOCKET. To manipulate options at any other level the protocol 00773 //! number of the appropriate protocol controlling the option is 00774 //! supplied. For example, to indicate that an option is to be 00775 //! interpreted by the TCP protocol, level should be set to the 00776 //! protocol number of TCP; 00777 //! The parameters optval and optlen are used to access optval - 00778 //! use for setsockopt(). For getsockopt() they identify a buffer 00779 //! in which the value for the requested option(s) are to 00780 //! be returned. For getsockopt(), optlen is a value-result 00781 //! parameter, initially containing the size of the buffer 00782 //! pointed to by option_value, and modified on return to 00783 //! indicate the actual size of the value returned. If no option 00784 //! value is to be supplied or returned, option_value may be NULL. 00785 //! 00786 //! @Note On this version the following two socket options are enabled: 00787 //! The only protocol level supported in this version 00788 //! is SOL_SOCKET (level). 00789 //! 1. SOCKOPT_RECV_TIMEOUT (optname) 00790 //! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout 00791 //! in milliseconds. 00792 //! In that case optval should be pointer to unsigned long. 00793 //! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on 00794 //! or off. 00795 //! In that case optval should be SOCK_ON or SOCK_OFF (optval). 00796 //! 00797 //! @sa setsockopt 00798 // 00799 //***************************************************************************** 00800 00801 int 00802 getsockopt (long sd, long level, long optname, void *optval, socklen_t *optlen) 00803 { 00804 unsigned char *ptr, *args; 00805 tBsdGetSockOptReturnParams tRetParams; 00806 00807 ptr = tSLInformation.pucTxCommandBuffer; 00808 args = (ptr + HEADERS_SIZE_CMD); 00809 00810 // Fill in temporary command buffer 00811 args = UINT32_TO_STREAM(args, sd); 00812 args = UINT32_TO_STREAM(args, level); 00813 args = UINT32_TO_STREAM(args, optname); 00814 00815 // Initiate a HCI command 00816 hci_command_send(HCI_CMND_GETSOCKOPT, ptr, SOCKET_GET_SOCK_OPT_PARAMS_LEN); 00817 00818 // Since we are in blocking state - wait for event complete 00819 SimpleLinkWaitEvent(HCI_CMND_GETSOCKOPT, (long*)&tRetParams); 00820 00821 if (((signed char)tRetParams.iStatus) >= 0) 00822 { 00823 *optlen = 4; 00824 memcpy(optval, tRetParams.ucOptValue, 4); 00825 return (0); 00826 } 00827 else 00828 { 00829 errno = tRetParams.iStatus; 00830 return (errno); 00831 } 00832 } 00833 00834 //***************************************************************************** 00835 // 00836 //! simple_link_recv 00837 //! 00838 //! @param sd socket handle 00839 //! @param buf read buffer 00840 //! @param len buffer length 00841 //! @param flags indicates blocking or non-blocking operation 00842 //! @param from pointer to an address structure indicating source address 00843 //! @param fromlen source address structure size 00844 //! 00845 //! @return Return the number of bytes received, or -1 if an error 00846 //! occurred 00847 //! 00848 //! @brief Read data from socket 00849 //! Return the length of the message on successful completion. 00850 //! If a message is too long to fit in the supplied buffer, 00851 //! excess bytes may be discarded depending on the type of 00852 //! socket the message is received from 00853 // 00854 //***************************************************************************** 00855 int 00856 simple_link_recv(long sd, unsigned char *buf, long len, long flags, sockaddr *from, socklen_t *fromlen, long opcode) 00857 { 00858 unsigned char *ptr, *args; 00859 tBsdReadReturnParams tSocketReadEvent; 00860 00861 ptr = tSLInformation.pucTxCommandBuffer; 00862 args = (ptr + HEADERS_SIZE_CMD); 00863 00864 // Fill in HCI packet structure 00865 args = UINT32_TO_STREAM(args, sd); 00866 args = UINT32_TO_STREAM(args, len); 00867 args = UINT32_TO_STREAM(args, flags); 00868 00869 // Generate the read command, and wait for the 00870 hci_command_send(opcode, ptr, SOCKET_RECV_FROM_PARAMS_LEN); 00871 00872 // Since we are in blocking state - wait for event complete 00873 SimpleLinkWaitEvent(opcode, (long*)&tSocketReadEvent); 00874 00875 // In case the number of bytes is more then zero - read data 00876 if (tSocketReadEvent.iNumberOfBytes > 0) 00877 { 00878 // Wait for the data in a synchronous way. Here we assume that the bug is 00879 // big enough to store also parameters of receive from too.... 00880 SimpleLinkWaitData(buf, (unsigned char *)from, (unsigned char *)fromlen); 00881 } 00882 00883 errno = tSocketReadEvent.iNumberOfBytes; 00884 00885 return(tSocketReadEvent.iNumberOfBytes); 00886 } 00887 00888 //***************************************************************************** 00889 // 00890 //! recv 00891 //! 00892 //! @param[in] sd socket handle 00893 //! @param[out] buf Points to the buffer where the message should be stored 00894 //! @param[in] len Specifies the length in bytes of the buffer pointed to 00895 //! by the buffer argument. 00896 //! @param[in] flags Specifies the type of message reception. 00897 //! On this version, this parameter is not supported. 00898 //! 00899 //! @return Return the number of bytes received, or -1 if an error 00900 //! occurred 00901 //! 00902 //! @brief function receives a message from a connection-mode socket 00903 //! 00904 //! @sa recvfrom 00905 //! 00906 //! @Note On this version, only blocking mode is supported. 00907 // 00908 //***************************************************************************** 00909 00910 int 00911 recv(long sd, unsigned char *buf, long len, long flags) 00912 { 00913 return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV)); 00914 } 00915 00916 //***************************************************************************** 00917 // 00918 //! recvfrom 00919 //! 00920 //! @param[in] sd socket handle 00921 //! @param[out] buf Points to the buffer where the message should be stored 00922 //! @param[in] len Specifies the length in bytes of the buffer pointed to 00923 //! by the buffer argument. 00924 //! @param[in] flags Specifies the type of message reception. 00925 //! On this version, this parameter is not supported. 00926 //! @param[in] from pointer to an address structure indicating the source 00927 //! address: sockaddr. On this version only AF_INET is 00928 //! supported. 00929 //! @param[in] fromlen source address tructure size 00930 //! 00931 //! @return Return the number of bytes received, or -1 if an error 00932 //! occurred 00933 //! 00934 //! @brief read data from socket 00935 //! function receives a message from a connection-mode or 00936 //! connectionless-mode socket. Note that raw sockets are not 00937 //! supported. 00938 //! 00939 //! @sa recv 00940 //! 00941 //! @Note On this version, only blocking mode is supported. 00942 // 00943 //***************************************************************************** 00944 int 00945 recvfrom(long sd, unsigned char *buf, long len, long flags, sockaddr *from, socklen_t *fromlen) 00946 { 00947 return(simple_link_recv(sd, buf, len, flags, from, fromlen, HCI_CMND_RECVFROM)); 00948 } 00949 00950 //***************************************************************************** 00951 // 00952 //! simple_link_send 00953 //! 00954 //! @param sd socket handle 00955 //! @param buf write buffer 00956 //! @param len buffer length 00957 //! @param flags On this version, this parameter is not supported 00958 //! @param to pointer to an address structure indicating destination 00959 //! address 00960 //! @param tolen destination address structure size 00961 //! 00962 //! @return Return the number of bytes transmitted, or -1 if an error 00963 //! occurred, or -2 in case there are no free buffers available 00964 //! (only when SEND_NON_BLOCKING is enabled) 00965 //! 00966 //! @brief This function is used to transmit a message to another 00967 //! socket 00968 // 00969 //***************************************************************************** 00970 int 00971 simple_link_send(long sd, const void *buf, long len, long flags, const sockaddr *to, long tolen, long opcode) 00972 { 00973 unsigned char uArgSize, addrlen; 00974 unsigned char *ptr, *pDataPtr, *args; 00975 unsigned long addr_offset; 00976 int res; 00977 tBsdReadReturnParams tSocketSendEvent; 00978 00979 // Check the bsd_arguments 00980 if (0 != (res = HostFlowControlConsumeBuff(sd))) 00981 { 00982 return res; 00983 } 00984 00985 //Update the number of sent packets 00986 tSLInformation.NumberOfSentPackets++; 00987 00988 // Allocate a buffer and construct a packet and send it over spi 00989 ptr = tSLInformation.pucTxCommandBuffer; 00990 args = (ptr + HEADERS_SIZE_DATA); 00991 00992 // Update the offset of data and parameters according to the command 00993 switch(opcode) 00994 { 00995 case HCI_CMND_SENDTO: 00996 { 00997 addr_offset = len + sizeof(len) + sizeof(len); 00998 addrlen = 8; 00999 uArgSize = SOCKET_SENDTO_PARAMS_LEN; 01000 pDataPtr = ptr + HEADERS_SIZE_DATA + SOCKET_SENDTO_PARAMS_LEN; 01001 break; 01002 } 01003 01004 case HCI_CMND_SEND: 01005 { 01006 tolen = 0; 01007 to = NULL; 01008 uArgSize = HCI_CMND_SEND_ARG_LENGTH; 01009 pDataPtr = ptr + HEADERS_SIZE_DATA + HCI_CMND_SEND_ARG_LENGTH; 01010 break; 01011 } 01012 01013 default: 01014 { 01015 break; 01016 } 01017 } 01018 01019 // Fill in temporary command buffer 01020 args = UINT32_TO_STREAM(args, sd); 01021 args = UINT32_TO_STREAM(args, uArgSize - sizeof(sd)); 01022 args = UINT32_TO_STREAM(args, len); 01023 args = UINT32_TO_STREAM(args, flags); 01024 01025 if (opcode == HCI_CMND_SENDTO) 01026 { 01027 args = UINT32_TO_STREAM(args, addr_offset); 01028 args = UINT32_TO_STREAM(args, addrlen); 01029 } 01030 01031 // Copy the data received from user into the TX Buffer 01032 ARRAY_TO_STREAM(pDataPtr, ((unsigned char *)buf), len); 01033 01034 // In case we are using SendTo, copy the to parameters 01035 if (opcode == HCI_CMND_SENDTO) 01036 { 01037 ARRAY_TO_STREAM(pDataPtr, ((unsigned char *)to), tolen); 01038 } 01039 01040 // Initiate a HCI command 01041 hci_data_send(opcode, ptr, uArgSize, len,(unsigned char*)to, tolen); 01042 01043 if (opcode == HCI_CMND_SENDTO) 01044 SimpleLinkWaitEvent(HCI_EVNT_SENDTO, (long*)&tSocketSendEvent); 01045 else 01046 SimpleLinkWaitEvent(HCI_EVNT_SEND, (long*)&tSocketSendEvent); 01047 01048 return (len); 01049 } 01050 01051 01052 //***************************************************************************** 01053 // 01054 //! send 01055 //! 01056 //! @param sd socket handle 01057 //! @param buf Points to a buffer containing the message to be sent 01058 //! @param len message size in bytes 01059 //! @param flags On this version, this parameter is not supported 01060 //! 01061 //! @return Return the number of bytes transmitted, or -1 if an 01062 //! error occurred 01063 //! 01064 //! @brief Write data to TCP socket 01065 //! This function is used to transmit a message to another 01066 //! socket. 01067 //! 01068 //! @Note On this version, only blocking mode is supported. 01069 //! 01070 //! @sa sendto 01071 // 01072 //***************************************************************************** 01073 01074 int 01075 send(long sd, const void *buf, long len, long flags) 01076 { 01077 return(simple_link_send(sd, buf, len, flags, NULL, 0, HCI_CMND_SEND)); 01078 } 01079 01080 //***************************************************************************** 01081 // 01082 //! sendto 01083 //! 01084 //! @param sd socket handle 01085 //! @param buf Points to a buffer containing the message to be sent 01086 //! @param len message size in bytes 01087 //! @param flags On this version, this parameter is not supported 01088 //! @param to pointer to an address structure indicating the destination 01089 //! address: sockaddr. On this version only AF_INET is 01090 //! supported. 01091 //! @param tolen destination address structure size 01092 //! 01093 //! @return Return the number of bytes transmitted, or -1 if an 01094 //! error occurred 01095 //! 01096 //! @brief Write data to TCP socket 01097 //! This function is used to transmit a message to another 01098 //! socket. 01099 //! 01100 //! @Note On this version, only blocking mode is supported. 01101 //! 01102 //! @sa send 01103 // 01104 //***************************************************************************** 01105 01106 int 01107 sendto(long sd, const void *buf, long len, long flags, const sockaddr *to, socklen_t tolen) 01108 { 01109 return(simple_link_send(sd, buf, len, flags, to, tolen, HCI_CMND_SENDTO)); 01110 } 01111 01112 //***************************************************************************** 01113 // 01114 //! mdnsAdvertiser 01115 //! 01116 //! @param[in] mdnsEnabled flag to enable/disable the mDNS feature 01117 //! @param[in] deviceServiceName Service name as part of the published 01118 //! canonical domain name 01119 //! @param[in] deviceServiceNameLength Length of the service name 01120 //! 01121 //! 01122 //! @return On success, zero is returned, return SOC_ERROR if socket was not 01123 //! opened successfully, or if an error occurred. 01124 //! 01125 //! @brief Set CC3000 in mDNS advertiser mode in order to advertise itself. 01126 // 01127 //***************************************************************************** 01128 01129 int 01130 mdnsAdvertiser(unsigned short mdnsEnabled, char * deviceServiceName, unsigned short deviceServiceNameLength) 01131 { 01132 int ret; 01133 unsigned char *pTxBuffer, *pArgs; 01134 01135 if (deviceServiceNameLength > MDNS_DEVICE_SERVICE_MAX_LENGTH) 01136 { 01137 return EFAIL; 01138 } 01139 01140 pTxBuffer = tSLInformation.pucTxCommandBuffer; 01141 pArgs = (pTxBuffer + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); 01142 01143 // Fill in HCI packet structure 01144 pArgs = UINT32_TO_STREAM(pArgs, mdnsEnabled); 01145 pArgs = UINT32_TO_STREAM(pArgs, 8); 01146 pArgs = UINT32_TO_STREAM(pArgs, deviceServiceNameLength); 01147 ARRAY_TO_STREAM(pArgs, deviceServiceName, deviceServiceNameLength); 01148 01149 // Initiate a HCI command 01150 hci_command_send(HCI_CMND_MDNS_ADVERTISE, pTxBuffer, SOCKET_MDNS_ADVERTISE_PARAMS_LEN + deviceServiceNameLength); 01151 01152 // Since we are in blocking state - wait for event complete 01153 SimpleLinkWaitEvent(HCI_EVNT_MDNS_ADVERTISE, (long*)&ret); 01154 01155 return ret; 01156 01157 } 01158
Generated on Tue Jul 12 2022 19:26:44 by
1.7.2