A Port of TI's Webserver for the CC3000
Embed:
(wiki syntax)
Show/hide line numbers
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, 00317 ptr, SOCKET_ACCEPT_PARAMS_LEN); 00318 00319 // Since we are in blocking state - wait for event complete 00320 SimpleLinkWaitEvent(HCI_CMND_ACCEPT, &tAcceptReturnArguments); 00321 00322 00323 // need specify return parameters!!! 00324 memcpy(addr, &tAcceptReturnArguments.tSocketAddress, ASIC_ADDR_LEN); 00325 *addrlen = ASIC_ADDR_LEN; 00326 errno = tAcceptReturnArguments.iStatus; 00327 ret = errno; 00328 00329 // if succeeded, iStatus = new socket descriptor. otherwise - error number 00330 if(M_IS_VALID_SD(ret)) 00331 { 00332 set_socket_active_status(ret, SOCKET_STATUS_ACTIVE); 00333 } 00334 else 00335 { 00336 set_socket_active_status(sd, SOCKET_STATUS_INACTIVE); 00337 } 00338 00339 return(ret); 00340 } 00341 00342 //***************************************************************************** 00343 // 00344 //! bind 00345 //! 00346 //! @param[in] sd socket descriptor (handle) 00347 //! @param[out] addr specifies the destination address. On this version 00348 //! only AF_INET is supported. 00349 //! @param[out] addrlen contains the size of the structure pointed to by addr. 00350 //! 00351 //! @return On success, zero is returned. On error, -1 is returned. 00352 //! 00353 //! @brief assign a name to a socket 00354 //! This function gives the socket the local address addr. 00355 //! addr is addrlen bytes long. Traditionally, this is called when a 00356 //! socket is created with socket, it exists in a name space (address 00357 //! family) but has no name assigned. 00358 //! It is necessary to assign a local address before a SOCK_STREAM 00359 //! socket may receive connections. 00360 //! 00361 //! @sa socket ; accept ; listen 00362 // 00363 //***************************************************************************** 00364 00365 long 00366 bind(long sd, const sockaddr *addr, long addrlen) 00367 { 00368 long ret; 00369 unsigned char *ptr, *args; 00370 00371 ret = EFAIL; 00372 ptr = tSLInformation.pucTxCommandBuffer; 00373 args = (ptr + HEADERS_SIZE_CMD); 00374 00375 addrlen = ASIC_ADDR_LEN; 00376 00377 // Fill in temporary command buffer 00378 args = UINT32_TO_STREAM(args, sd); 00379 args = UINT32_TO_STREAM(args, 0x00000008); 00380 args = UINT32_TO_STREAM(args, addrlen); 00381 ARRAY_TO_STREAM(args, ((unsigned char *)addr), addrlen); 00382 00383 // Initiate a HCI command 00384 hci_command_send(HCI_CMND_BIND, 00385 ptr, SOCKET_BIND_PARAMS_LEN); 00386 00387 // Since we are in blocking state - wait for event complete 00388 SimpleLinkWaitEvent(HCI_CMND_BIND, &ret); 00389 00390 errno = ret; 00391 00392 return(ret); 00393 } 00394 00395 //***************************************************************************** 00396 // 00397 //! listen 00398 //! 00399 //! @param[in] sd socket descriptor (handle) 00400 //! @param[in] backlog specifies the listen queue depth. On this version 00401 //! backlog is not supported. 00402 //! @return On success, zero is returned. On error, -1 is returned. 00403 //! 00404 //! @brief listen for connections on a socket 00405 //! The willingness to accept incoming connections and a queue 00406 //! limit for incoming connections are specified with listen(), 00407 //! and then the connections are accepted with accept. 00408 //! The listen() call applies only to sockets of type SOCK_STREAM 00409 //! The backlog parameter defines the maximum length the queue of 00410 //! pending connections may grow to. 00411 //! 00412 //! @sa socket ; accept ; bind 00413 //! 00414 //! @note On this version, backlog is not supported 00415 // 00416 //***************************************************************************** 00417 00418 long 00419 listen(long sd, long backlog) 00420 { 00421 long ret; 00422 unsigned char *ptr, *args; 00423 00424 ret = EFAIL; 00425 ptr = tSLInformation.pucTxCommandBuffer; 00426 args = (ptr + HEADERS_SIZE_CMD); 00427 00428 // Fill in temporary command buffer 00429 args = UINT32_TO_STREAM(args, sd); 00430 args = UINT32_TO_STREAM(args, backlog); 00431 00432 // Initiate a HCI command 00433 hci_command_send(HCI_CMND_LISTEN, 00434 ptr, SOCKET_LISTEN_PARAMS_LEN); 00435 00436 // Since we are in blocking state - wait for event complete 00437 SimpleLinkWaitEvent(HCI_CMND_LISTEN, &ret); 00438 errno = ret; 00439 00440 return(ret); 00441 } 00442 00443 //***************************************************************************** 00444 // 00445 //! gethostbyname 00446 //! 00447 //! @param[in] hostname host name 00448 //! @param[in] usNameLen name length 00449 //! @param[out] out_ip_addr This parameter is filled in with host IP address. 00450 //! In case that host name is not resolved, 00451 //! out_ip_addr is zero. 00452 //! @return On success, positive is returned. On error, negative is returned 00453 //! 00454 //! @brief Get host IP by name. Obtain the IP Address of machine on network, 00455 //! by its name. 00456 //! 00457 //! @note On this version, only blocking mode is supported. Also note that 00458 //! the function requires DNS server to be configured prior to its usage. 00459 // 00460 //***************************************************************************** 00461 00462 #ifndef CC3000_TINY_DRIVER 00463 int 00464 gethostbyname(char * hostname, unsigned short usNameLen, 00465 unsigned long* out_ip_addr) 00466 { 00467 tBsdGethostbynameParams ret; 00468 unsigned char *ptr, *args; 00469 00470 errno = EFAIL; 00471 00472 if (usNameLen > HOSTNAME_MAX_LENGTH) 00473 { 00474 return errno; 00475 } 00476 00477 ptr = tSLInformation.pucTxCommandBuffer; 00478 args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); 00479 00480 // Fill in HCI packet structure 00481 args = UINT32_TO_STREAM(args, 8); 00482 args = UINT32_TO_STREAM(args, usNameLen); 00483 ARRAY_TO_STREAM(args, hostname, usNameLen); 00484 00485 // Initiate a HCI command 00486 hci_command_send(HCI_CMND_GETHOSTNAME, ptr, SOCKET_GET_HOST_BY_NAME_PARAMS_LEN 00487 + usNameLen - 1); 00488 00489 // Since we are in blocking state - wait for event complete 00490 SimpleLinkWaitEvent(HCI_EVNT_BSD_GETHOSTBYNAME, &ret); 00491 00492 errno = ret.retVal; 00493 00494 (*((long*)out_ip_addr)) = ret.outputAddress; 00495 00496 return (errno); 00497 00498 } 00499 #endif 00500 00501 //***************************************************************************** 00502 // 00503 //! connect 00504 //! 00505 //! @param[in] sd socket descriptor (handle) 00506 //! @param[in] addr specifies the destination addr. On this version 00507 //! only AF_INET is supported. 00508 //! @param[out] addrlen contains the size of the structure pointed to by addr 00509 //! @return On success, zero is returned. On error, -1 is returned 00510 //! 00511 //! @brief initiate a connection on a socket 00512 //! Function connects the socket referred to by the socket descriptor 00513 //! sd, to the address specified by addr. The addrlen argument 00514 //! specifies the size of addr. The format of the address in addr is 00515 //! determined by the address space of the socket. If it is of type 00516 //! SOCK_DGRAM, this call specifies the peer with which the socket is 00517 //! to be associated; this address is that to which datagrams are to be 00518 //! sent, and the only address from which datagrams are to be received. 00519 //! If the socket is of type SOCK_STREAM, this call attempts to make a 00520 //! connection to another socket. The other socket is specified by 00521 //! address, which is an address in the communications space of the 00522 //! socket. Note that the function implements only blocking behavior 00523 //! thus the caller will be waiting either for the connection 00524 //! establishment or for the connection establishment failure. 00525 //! 00526 //! @sa socket 00527 // 00528 //***************************************************************************** 00529 00530 long 00531 connect(long sd, const sockaddr *addr, long addrlen) 00532 { 00533 long int ret; 00534 unsigned char *ptr, *args; 00535 00536 ret = EFAIL; 00537 ptr = tSLInformation.pucTxCommandBuffer; 00538 args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); 00539 addrlen = 8; 00540 00541 // Fill in temporary command buffer 00542 args = UINT32_TO_STREAM(args, sd); 00543 args = UINT32_TO_STREAM(args, 0x00000008); 00544 args = UINT32_TO_STREAM(args, addrlen); 00545 ARRAY_TO_STREAM(args, ((unsigned char *)addr), addrlen); 00546 00547 // Initiate a HCI command 00548 hci_command_send(HCI_CMND_CONNECT, 00549 ptr, SOCKET_CONNECT_PARAMS_LEN); 00550 00551 // Since we are in blocking state - wait for event complete 00552 SimpleLinkWaitEvent(HCI_CMND_CONNECT, &ret); 00553 00554 errno = ret; 00555 00556 return((long)ret); 00557 } 00558 00559 00560 //***************************************************************************** 00561 // 00562 //! select 00563 //! 00564 //! @param[in] nfds the highest-numbered file descriptor in any of the 00565 //! three sets, plus 1. 00566 //! @param[out] writesds socket descriptors list for write monitoring 00567 //! @param[out] readsds socket descriptors list for read monitoring 00568 //! @param[out] exceptsds socket descriptors list for exception monitoring 00569 //! @param[in] timeout is an upper bound on the amount of time elapsed 00570 //! before select() returns. Null means infinity 00571 //! timeout. The minimum timeout is 5 milliseconds, 00572 //! less than 5 milliseconds will be set 00573 //! automatically to 5 milliseconds. 00574 //! @return On success, select() returns the number of file descriptors 00575 //! contained in the three returned descriptor sets (that is, the 00576 //! total number of bits that are set in readfds, writefds, 00577 //! exceptfds) which may be zero if the timeout expires before 00578 //! anything interesting happens. 00579 //! On error, -1 is returned. 00580 //! *readsds - return the sockets on which Read request will 00581 //! return without delay with valid data. 00582 //! *writesds - return the sockets on which Write request 00583 //! will return without delay. 00584 //! *exceptsds - return the sockets which closed recently. 00585 //! 00586 //! @brief Monitor socket activity 00587 //! Select allow a program to monitor multiple file descriptors, 00588 //! waiting until one or more of the file descriptors become 00589 //! "ready" for some class of I/O operation 00590 //! 00591 //! @Note If the timeout value set to less than 5ms it will automatically set 00592 //! to 5ms to prevent overload of the system 00593 //! 00594 //! @sa socket 00595 // 00596 //***************************************************************************** 00597 00598 int 00599 select(long nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds, 00600 struct timeval *timeout) 00601 { 00602 unsigned char *ptr, *args; 00603 tBsdSelectRecvParams tParams; 00604 unsigned long is_blocking; 00605 00606 if( timeout == NULL) 00607 { 00608 is_blocking = 1; /* blocking , infinity timeout */ 00609 } 00610 else 00611 { 00612 is_blocking = 0; /* no blocking, timeout */ 00613 } 00614 00615 // Fill in HCI packet structure 00616 ptr = tSLInformation.pucTxCommandBuffer; 00617 args = (ptr + HEADERS_SIZE_CMD); 00618 00619 // Fill in temporary command buffer 00620 args = UINT32_TO_STREAM(args, nfds); 00621 args = UINT32_TO_STREAM(args, 0x00000014); 00622 args = UINT32_TO_STREAM(args, 0x00000014); 00623 args = UINT32_TO_STREAM(args, 0x00000014); 00624 args = UINT32_TO_STREAM(args, 0x00000014); 00625 args = UINT32_TO_STREAM(args, is_blocking); 00626 args = UINT32_TO_STREAM(args, ((readsds) ? *(unsigned long*)readsds : 0)); 00627 args = UINT32_TO_STREAM(args, ((writesds) ? *(unsigned long*)writesds : 0)); 00628 args = UINT32_TO_STREAM(args, ((exceptsds) ? *(unsigned long*)exceptsds : 0)); 00629 00630 if (timeout) 00631 { 00632 if ( 0 == timeout->tv_sec && timeout->tv_usec < 00633 SELECT_TIMEOUT_MIN_MICRO_SECONDS) 00634 { 00635 timeout->tv_usec = SELECT_TIMEOUT_MIN_MICRO_SECONDS; 00636 } 00637 args = UINT32_TO_STREAM(args, timeout->tv_sec); 00638 args = UINT32_TO_STREAM(args, timeout->tv_usec); 00639 } 00640 00641 // Initiate a HCI command 00642 hci_command_send(HCI_CMND_BSD_SELECT, ptr, SOCKET_SELECT_PARAMS_LEN); 00643 00644 // Since we are in blocking state - wait for event complete 00645 SimpleLinkWaitEvent(HCI_EVNT_SELECT, &tParams); 00646 00647 // Update actually read FD 00648 if (tParams.iStatus >= 0) 00649 { 00650 if (readsds) 00651 { 00652 memcpy(readsds, &tParams.uiRdfd, sizeof(tParams.uiRdfd)); 00653 } 00654 00655 if (writesds) 00656 { 00657 memcpy(writesds, &tParams.uiWrfd, sizeof(tParams.uiWrfd)); 00658 } 00659 00660 if (exceptsds) 00661 { 00662 memcpy(exceptsds, &tParams.uiExfd, sizeof(tParams.uiExfd)); 00663 } 00664 00665 return(tParams.iStatus); 00666 00667 } 00668 else 00669 { 00670 errno = tParams.iStatus; 00671 return(-1); 00672 } 00673 } 00674 00675 //***************************************************************************** 00676 // 00677 //! setsockopt 00678 //! 00679 //! @param[in] sd socket handle 00680 //! @param[in] level defines the protocol level for this option 00681 //! @param[in] optname defines the option name to Interrogate 00682 //! @param[in] optval specifies a value for the option 00683 //! @param[in] optlen specifies the length of the option value 00684 //! @return On success, zero is returned. On error, -1 is returned 00685 //! 00686 //! @brief set socket options 00687 //! This function manipulate the options associated with a socket. 00688 //! Options may exist at multiple protocol levels; they are always 00689 //! present at the uppermost socket level. 00690 //! When manipulating socket options the level at which the option 00691 //! resides and the name of the option must be specified. 00692 //! To manipulate options at the socket level, level is specified as 00693 //! SOL_SOCKET. To manipulate options at any other level the protocol 00694 //! number of the appropriate protocol controlling the option is 00695 //! supplied. For example, to indicate that an option is to be 00696 //! interpreted by the TCP protocol, level should be set to the 00697 //! protocol number of TCP; 00698 //! The parameters optval and optlen are used to access optval - 00699 //! use for setsockopt(). For getsockopt() they identify a buffer 00700 //! in which the value for the requested option(s) are to 00701 //! be returned. For getsockopt(), optlen is a value-result 00702 //! parameter, initially containing the size of the buffer 00703 //! pointed to by option_value, and modified on return to 00704 //! indicate the actual size of the value returned. If no option 00705 //! value is to be supplied or returned, option_value may be NULL. 00706 //! 00707 //! @Note On this version the following two socket options are enabled: 00708 //! The only protocol level supported in this version 00709 //! is SOL_SOCKET (level). 00710 //! 1. SOCKOPT_RECV_TIMEOUT (optname) 00711 //! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout 00712 //! in milliseconds. 00713 //! In that case optval should be pointer to unsigned long. 00714 //! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on 00715 //! or off. 00716 //! In that case optval should be SOCK_ON or SOCK_OFF (optval). 00717 //! 00718 //! @sa getsockopt 00719 // 00720 //***************************************************************************** 00721 00722 #ifndef CC3000_TINY_DRIVER 00723 int 00724 setsockopt(long sd, long level, long optname, const void *optval, 00725 socklen_t optlen) 00726 { 00727 int ret; 00728 unsigned char *ptr, *args; 00729 00730 ptr = tSLInformation.pucTxCommandBuffer; 00731 args = (ptr + HEADERS_SIZE_CMD); 00732 00733 // Fill in temporary command buffer 00734 args = UINT32_TO_STREAM(args, sd); 00735 args = UINT32_TO_STREAM(args, level); 00736 args = UINT32_TO_STREAM(args, optname); 00737 args = UINT32_TO_STREAM(args, 0x00000008); 00738 args = UINT32_TO_STREAM(args, optlen); 00739 ARRAY_TO_STREAM(args, ((unsigned char *)optval), optlen); 00740 00741 // Initiate a HCI command 00742 hci_command_send(HCI_CMND_SETSOCKOPT, 00743 ptr, SOCKET_SET_SOCK_OPT_PARAMS_LEN + optlen); 00744 00745 // Since we are in blocking state - wait for event complete 00746 SimpleLinkWaitEvent(HCI_CMND_SETSOCKOPT, &ret); 00747 00748 if (ret >= 0) 00749 { 00750 return (0); 00751 } 00752 else 00753 { 00754 errno = ret; 00755 return (errno); 00756 } 00757 } 00758 #endif 00759 00760 //***************************************************************************** 00761 // 00762 //! getsockopt 00763 //! 00764 //! @param[in] sd socket handle 00765 //! @param[in] level defines the protocol level for this option 00766 //! @param[in] optname defines the option name to Interrogate 00767 //! @param[out] optval specifies a value for the option 00768 //! @param[out] optlen specifies the length of the option value 00769 //! @return On success, zero is returned. On error, -1 is returned 00770 //! 00771 //! @brief set socket options 00772 //! This function manipulate the options associated with a socket. 00773 //! Options may exist at multiple protocol levels; they are always 00774 //! present at the uppermost socket level. 00775 //! When manipulating socket options the level at which the option 00776 //! resides and the name of the option must be specified. 00777 //! To manipulate options at the socket level, level is specified as 00778 //! SOL_SOCKET. To manipulate options at any other level the protocol 00779 //! number of the appropriate protocol controlling the option is 00780 //! supplied. For example, to indicate that an option is to be 00781 //! interpreted by the TCP protocol, level should be set to the 00782 //! protocol number of TCP; 00783 //! The parameters optval and optlen are used to access optval - 00784 //! use for setsockopt(). For getsockopt() they identify a buffer 00785 //! in which the value for the requested option(s) are to 00786 //! be returned. For getsockopt(), optlen is a value-result 00787 //! parameter, initially containing the size of the buffer 00788 //! pointed to by option_value, and modified on return to 00789 //! indicate the actual size of the value returned. If no option 00790 //! value is to be supplied or returned, option_value may be NULL. 00791 //! 00792 //! @Note On this version the following two socket options are enabled: 00793 //! The only protocol level supported in this version 00794 //! is SOL_SOCKET (level). 00795 //! 1. SOCKOPT_RECV_TIMEOUT (optname) 00796 //! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout 00797 //! in milliseconds. 00798 //! In that case optval should be pointer to unsigned long. 00799 //! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on 00800 //! or off. 00801 //! In that case optval should be SOCK_ON or SOCK_OFF (optval). 00802 //! 00803 //! @sa setsockopt 00804 // 00805 //***************************************************************************** 00806 00807 int 00808 getsockopt (long sd, long level, long optname, void *optval, socklen_t *optlen) 00809 { 00810 unsigned char *ptr, *args; 00811 tBsdGetSockOptReturnParams tRetParams; 00812 00813 ptr = tSLInformation.pucTxCommandBuffer; 00814 args = (ptr + HEADERS_SIZE_CMD); 00815 00816 // Fill in temporary command buffer 00817 args = UINT32_TO_STREAM(args, sd); 00818 args = UINT32_TO_STREAM(args, level); 00819 args = UINT32_TO_STREAM(args, optname); 00820 00821 // Initiate a HCI command 00822 hci_command_send(HCI_CMND_GETSOCKOPT, 00823 ptr, SOCKET_GET_SOCK_OPT_PARAMS_LEN); 00824 00825 // Since we are in blocking state - wait for event complete 00826 SimpleLinkWaitEvent(HCI_CMND_GETSOCKOPT, &tRetParams); 00827 00828 if (((signed char)tRetParams.iStatus) >= 0) 00829 { 00830 *optlen = 4; 00831 memcpy(optval, tRetParams.ucOptValue, 4); 00832 return (0); 00833 } 00834 else 00835 { 00836 errno = tRetParams.iStatus; 00837 return (errno); 00838 } 00839 } 00840 00841 //***************************************************************************** 00842 // 00843 //! simple_link_recv 00844 //! 00845 //! @param sd socket handle 00846 //! @param buf read buffer 00847 //! @param len buffer length 00848 //! @param flags indicates blocking or non-blocking operation 00849 //! @param from pointer to an address structure indicating source address 00850 //! @param fromlen source address structure size 00851 //! 00852 //! @return Return the number of bytes received, or -1 if an error 00853 //! occurred 00854 //! 00855 //! @brief Read data from socket 00856 //! Return the length of the message on successful completion. 00857 //! If a message is too long to fit in the supplied buffer, 00858 //! excess bytes may be discarded depending on the type of 00859 //! socket the message is received from 00860 // 00861 //***************************************************************************** 00862 int 00863 simple_link_recv(long sd, void *buf, long len, long flags, sockaddr *from, 00864 socklen_t *fromlen, long opcode) 00865 { 00866 unsigned char *ptr, *args; 00867 tBsdReadReturnParams tSocketReadEvent; 00868 00869 ptr = tSLInformation.pucTxCommandBuffer; 00870 args = (ptr + HEADERS_SIZE_CMD); 00871 00872 // Fill in HCI packet structure 00873 args = UINT32_TO_STREAM(args, sd); 00874 args = UINT32_TO_STREAM(args, len); 00875 args = UINT32_TO_STREAM(args, flags); 00876 00877 // Generate the read command, and wait for the 00878 hci_command_send(opcode, ptr, SOCKET_RECV_FROM_PARAMS_LEN); 00879 00880 // Since we are in blocking state - wait for event complete 00881 SimpleLinkWaitEvent(opcode, &tSocketReadEvent); 00882 00883 // In case the number of bytes is more then zero - read data 00884 if (tSocketReadEvent.iNumberOfBytes > 0) 00885 { 00886 // Wait for the data in a synchronous way. Here we assume that the bug is 00887 // big enough to store also parameters of receive from too.... 00888 SimpleLinkWaitData((unsigned char *)buf, (unsigned char *)from, (unsigned char *)fromlen); 00889 } 00890 00891 errno = tSocketReadEvent.iNumberOfBytes; 00892 00893 return(tSocketReadEvent.iNumberOfBytes); 00894 } 00895 00896 //***************************************************************************** 00897 // 00898 //! recv 00899 //! 00900 //! @param[in] sd socket handle 00901 //! @param[out] buf Points to the buffer where the message should be stored 00902 //! @param[in] len Specifies the length in bytes of the buffer pointed to 00903 //! by the buffer argument. 00904 //! @param[in] flags Specifies the type of message reception. 00905 //! On this version, this parameter is not supported. 00906 //! 00907 //! @return Return the number of bytes received, or -1 if an error 00908 //! occurred 00909 //! 00910 //! @brief function receives a message from a connection-mode socket 00911 //! 00912 //! @sa recvfrom 00913 //! 00914 //! @Note On this version, only blocking mode is supported. 00915 // 00916 //***************************************************************************** 00917 00918 int 00919 recv(long sd, void *buf, long len, long flags) 00920 { 00921 return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV)); 00922 } 00923 00924 //***************************************************************************** 00925 // 00926 //! recvfrom 00927 //! 00928 //! @param[in] sd socket handle 00929 //! @param[out] buf Points to the buffer where the message should be stored 00930 //! @param[in] len Specifies the length in bytes of the buffer pointed to 00931 //! by the buffer argument. 00932 //! @param[in] flags Specifies the type of message reception. 00933 //! On this version, this parameter is not supported. 00934 //! @param[in] from pointer to an address structure indicating the source 00935 //! address: sockaddr. On this version only AF_INET is 00936 //! supported. 00937 //! @param[in] fromlen source address tructure size 00938 //! 00939 //! @return Return the number of bytes received, or -1 if an error 00940 //! occurred 00941 //! 00942 //! @brief read data from socket 00943 //! function receives a message from a connection-mode or 00944 //! connectionless-mode socket. Note that raw sockets are not 00945 //! supported. 00946 //! 00947 //! @sa recv 00948 //! 00949 //! @Note On this version, only blocking mode is supported. 00950 // 00951 //***************************************************************************** 00952 int 00953 recvfrom(long sd, void *buf, long len, long flags, sockaddr *from, 00954 socklen_t *fromlen) 00955 { 00956 return(simple_link_recv(sd, buf, len, flags, from, fromlen, 00957 HCI_CMND_RECVFROM)); 00958 } 00959 00960 //***************************************************************************** 00961 // 00962 //! simple_link_send 00963 //! 00964 //! @param sd socket handle 00965 //! @param buf write buffer 00966 //! @param len buffer length 00967 //! @param flags On this version, this parameter is not supported 00968 //! @param to pointer to an address structure indicating destination 00969 //! address 00970 //! @param tolen destination address structure size 00971 //! 00972 //! @return Return the number of bytes transmitted, or -1 if an error 00973 //! occurred, or -2 in case there are no free buffers available 00974 //! (only when SEND_NON_BLOCKING is enabled) 00975 //! 00976 //! @brief This function is used to transmit a message to another 00977 //! socket 00978 // 00979 //***************************************************************************** 00980 int 00981 simple_link_send(long sd, const void *buf, long len, long flags, 00982 const sockaddr *to, long tolen, long opcode) 00983 { 00984 unsigned char uArgSize, addrlen; 00985 unsigned char *ptr, *pDataPtr, *args; 00986 unsigned long addr_offset; 00987 int res; 00988 tBsdReadReturnParams tSocketSendEvent; 00989 00990 // Check the bsd_arguments 00991 if (0 != (res = HostFlowControlConsumeBuff(sd))) 00992 { 00993 return res; 00994 } 00995 00996 //Update the number of sent packets 00997 tSLInformation.NumberOfSentPackets++; 00998 00999 // Allocate a buffer and construct a packet and send it over spi 01000 ptr = tSLInformation.pucTxCommandBuffer; 01001 args = (ptr + HEADERS_SIZE_DATA); 01002 01003 // Update the offset of data and parameters according to the command 01004 switch(opcode) 01005 { 01006 case HCI_CMND_SENDTO: 01007 { 01008 addr_offset = len + sizeof(len) + sizeof(len); 01009 addrlen = 8; 01010 uArgSize = SOCKET_SENDTO_PARAMS_LEN; 01011 pDataPtr = ptr + HEADERS_SIZE_DATA + SOCKET_SENDTO_PARAMS_LEN; 01012 break; 01013 } 01014 01015 case HCI_CMND_SEND: 01016 { 01017 tolen = 0; 01018 to = NULL; 01019 uArgSize = HCI_CMND_SEND_ARG_LENGTH; 01020 pDataPtr = ptr + HEADERS_SIZE_DATA + HCI_CMND_SEND_ARG_LENGTH; 01021 break; 01022 } 01023 01024 default: 01025 { 01026 break; 01027 } 01028 } 01029 01030 // Fill in temporary command buffer 01031 args = UINT32_TO_STREAM(args, sd); 01032 args = UINT32_TO_STREAM(args, uArgSize - sizeof(sd)); 01033 args = UINT32_TO_STREAM(args, len); 01034 args = UINT32_TO_STREAM(args, flags); 01035 01036 if (opcode == HCI_CMND_SENDTO) 01037 { 01038 args = UINT32_TO_STREAM(args, addr_offset); 01039 args = UINT32_TO_STREAM(args, addrlen); 01040 } 01041 01042 // Copy the data received from user into the TX Buffer 01043 ARRAY_TO_STREAM(pDataPtr, ((unsigned char *)buf), len); 01044 01045 // In case we are using SendTo, copy the to parameters 01046 if (opcode == HCI_CMND_SENDTO) 01047 { 01048 ARRAY_TO_STREAM(pDataPtr, ((unsigned char *)to), tolen); 01049 } 01050 01051 // Initiate a HCI command 01052 hci_data_send(opcode, ptr, uArgSize, len,(unsigned char*)to, tolen); 01053 01054 if (opcode == HCI_CMND_SENDTO) 01055 SimpleLinkWaitEvent(HCI_EVNT_SENDTO, &tSocketSendEvent); 01056 else 01057 SimpleLinkWaitEvent(HCI_EVNT_SEND, &tSocketSendEvent); 01058 01059 return (len); 01060 } 01061 01062 01063 //***************************************************************************** 01064 // 01065 //! send 01066 //! 01067 //! @param sd socket handle 01068 //! @param buf Points to a buffer containing the message to be sent 01069 //! @param len message size in bytes 01070 //! @param flags On this version, this parameter is not supported 01071 //! 01072 //! @return Return the number of bytes transmitted, or -1 if an 01073 //! error occurred 01074 //! 01075 //! @brief Write data to TCP socket 01076 //! This function is used to transmit a message to another 01077 //! socket. 01078 //! 01079 //! @Note On this version, only blocking mode is supported. 01080 //! 01081 //! @sa sendto 01082 // 01083 //***************************************************************************** 01084 01085 int 01086 send(long sd, const void *buf, long len, long flags) 01087 { 01088 return(simple_link_send(sd, buf, len, flags, NULL, 0, HCI_CMND_SEND)); 01089 } 01090 01091 //***************************************************************************** 01092 // 01093 //! sendto 01094 //! 01095 //! @param sd socket handle 01096 //! @param buf Points to a buffer containing the message to be sent 01097 //! @param len message size in bytes 01098 //! @param flags On this version, this parameter is not supported 01099 //! @param to pointer to an address structure indicating the destination 01100 //! address: sockaddr. On this version only AF_INET is 01101 //! supported. 01102 //! @param tolen destination address structure size 01103 //! 01104 //! @return Return the number of bytes transmitted, or -1 if an 01105 //! error occurred 01106 //! 01107 //! @brief Write data to TCP socket 01108 //! This function is used to transmit a message to another 01109 //! socket. 01110 //! 01111 //! @Note On this version, only blocking mode is supported. 01112 //! 01113 //! @sa send 01114 // 01115 //***************************************************************************** 01116 01117 int 01118 sendto(long sd, const void *buf, long len, long flags, const sockaddr *to, 01119 socklen_t tolen) 01120 { 01121 return(simple_link_send(sd, buf, len, flags, to, tolen, HCI_CMND_SENDTO)); 01122 } 01123 01124 //***************************************************************************** 01125 // 01126 //! mdnsAdvertiser 01127 //! 01128 //! @param[in] mdnsEnabled flag to enable/disable the mDNS feature 01129 //! @param[in] deviceServiceName Service name as part of the published 01130 //! canonical domain name 01131 //! @param[in] deviceServiceNameLength Length of the service name 01132 //! 01133 //! 01134 //! @return On success, zero is returned, return SOC_ERROR if socket was not 01135 //! opened successfully, or if an error occurred. 01136 //! 01137 //! @brief Set CC3000 in mDNS advertiser mode in order to advertise itself. 01138 // 01139 //***************************************************************************** 01140 01141 int 01142 mdnsAdvertiser(unsigned short mdnsEnabled, char * deviceServiceName, unsigned short deviceServiceNameLength) 01143 { 01144 int ret; 01145 unsigned char *pTxBuffer, *pArgs; 01146 01147 if (deviceServiceNameLength > MDNS_DEVICE_SERVICE_MAX_LENGTH) 01148 { 01149 return EFAIL; 01150 } 01151 01152 pTxBuffer = tSLInformation.pucTxCommandBuffer; 01153 pArgs = (pTxBuffer + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); 01154 01155 // Fill in HCI packet structure 01156 pArgs = UINT32_TO_STREAM(pArgs, mdnsEnabled); 01157 pArgs = UINT32_TO_STREAM(pArgs, 8); 01158 pArgs = UINT32_TO_STREAM(pArgs, deviceServiceNameLength); 01159 ARRAY_TO_STREAM(pArgs, deviceServiceName, deviceServiceNameLength); 01160 01161 // Initiate a HCI command 01162 hci_command_send(HCI_CMND_MDNS_ADVERTISE, pTxBuffer, SOCKET_MDNS_ADVERTISE_PARAMS_LEN + deviceServiceNameLength); 01163 01164 // Since we are in blocking state - wait for event complete 01165 SimpleLinkWaitEvent(HCI_EVNT_MDNS_ADVERTISE, &ret); 01166 01167 return ret; 01168 01169 } 01170
Generated on Wed Jul 13 2022 13:30:51 by
1.7.2