1 /* 2 * ipc_sta.c 3 * 4 * Copyright 2001-2009 Texas Instruments, Inc. - http://www.ti.com/ 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 /**************************************************************************** 20 * 21 * MODULE: IPC_STA.c 22 * 23 * PURPOSE: 24 * 25 * DESCRIPTION: 26 * ============ 27 * 28 * 29 ****************************************************************************/ 30 31 /* includes */ 32 /************/ 33 #include <sys/types.h> 34 #include <sys/socket.h> 35 #include <net/if.h> 36 #include <linux/rtnetlink.h> 37 #include <errno.h> 38 #include <sys/ioctl.h> 39 #include <unistd.h> 40 #include <linux/wireless.h> 41 #include "cu_osapi.h" 42 #include "oserr.h" 43 #include "STADExternalIf.h" 44 #include "ipc_sta.h" 45 46 /* defines */ 47 /***********/ 48 49 /* local types */ 50 /***************/ 51 /* Module control block */ 52 typedef struct IpcSta_t 53 { 54 struct iwreq wext_req; 55 ti_private_cmd_t private_cmd; 56 S32 STA_socket; 57 58 } IpcSta_t; 59 60 /* local variables */ 61 /*******************/ 62 63 /* local fucntions */ 64 /*******************/ 65 66 /* 67 * IpcSta_Sockets_Open - Open a socket. 68 * Depending on the protocol present, open the right socket. The socket 69 * will allow us to talk to the driver. 70 */ 71 static S32 IpcSta_Sockets_Open(VOID) 72 { 73 static const S32 families[] = { 74 AF_INET, AF_IPX, AF_APPLETALK 75 }; 76 U32 i; 77 S32 sock; 78 79 /* 80 * Now pick any (exisiting) useful socket family for generic queries 81 * Note : don't open all the socket, only returns when one matches, 82 * all protocols might not be valid. 83 * Workaround by Jim Kaba <jkaba (at) sarnoff.com> 84 * Note : in 2001% of the case, we will just open the inet_sock. 85 * The remaining 2002% case are not fully correct... 86 */ 87 88 /* Try all families we support */ 89 for(i = 0; i < sizeof(families)/sizeof(int); ++i) 90 { 91 /* Try to open the socket, if success returns it */ 92 sock = socket(families[i], SOCK_DGRAM, 0); 93 if(sock >= 0) 94 return sock; 95 } 96 97 return -1; 98 } 99 100 /* 101 * IpcSta_Sockets_Close - Close the socket used for ioctl. 102 */ 103 static inline VOID IpcSta_Sockets_Close(S32 skfd) 104 { 105 close(skfd); 106 } 107 108 109 /* functions */ 110 /*************/ 111 THandle IpcSta_Create(const PS8 device_name) 112 { 113 IpcSta_t* pIpcSta = (IpcSta_t*)os_MemoryCAlloc(sizeof(IpcSta_t), sizeof(U8)); 114 if(pIpcSta == NULL) 115 { 116 os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - IpcSta_Create - cant allocate control block\n"); 117 return NULL; 118 } 119 120 /* open the socket to the driver */ 121 pIpcSta->STA_socket = IpcSta_Sockets_Open(); 122 if(pIpcSta->STA_socket == -1) 123 { 124 os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - IpcSta_Create - cant open socket for communication with the driver\n"); 125 return NULL; 126 } 127 128 /* set the driver name */ 129 os_strcpy((PS8)pIpcSta->wext_req.ifr_ifrn.ifrn_name, device_name); 130 131 return pIpcSta; 132 } 133 134 VOID IpcSta_Destroy(THandle hIpcSta) 135 { 136 IpcSta_t* pIpcSta = (IpcSta_t*)hIpcSta; 137 138 /* close the socket to the driver */ 139 IpcSta_Sockets_Close(pIpcSta->STA_socket); 140 141 os_MemoryFree(pIpcSta); 142 } 143 144 S32 IPC_STA_Private_Send(THandle hIpcSta, U32 ioctl_cmd, PVOID bufIn, U32 sizeIn, 145 PVOID bufOut, U32 sizeOut) 146 147 { 148 IpcSta_t* pIpcSta = (IpcSta_t*)hIpcSta; 149 S32 res; 150 151 pIpcSta ->private_cmd.cmd = ioctl_cmd; 152 if(bufOut == NULL) 153 pIpcSta ->private_cmd.flags = PRIVATE_CMD_SET_FLAG; 154 else 155 pIpcSta ->private_cmd.flags = PRIVATE_CMD_GET_FLAG; 156 157 pIpcSta ->private_cmd.in_buffer = bufIn; 158 pIpcSta ->private_cmd.in_buffer_len = sizeIn; 159 pIpcSta ->private_cmd.out_buffer = bufOut; 160 pIpcSta ->private_cmd.out_buffer_len = sizeOut; 161 162 163 pIpcSta->wext_req.u.data.pointer = &pIpcSta->private_cmd; 164 pIpcSta->wext_req.u.data.length = sizeof(ti_private_cmd_t); 165 pIpcSta->wext_req.u.data.flags = 0; 166 167 res = ioctl(pIpcSta->STA_socket, SIOCIWFIRSTPRIV, &pIpcSta->wext_req); 168 if(res != OK) 169 { 170 os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - IPC_STA_Private_Send - error sending Wext private IOCTL to STA driver (ioctl_cmd = %x, res = %d, errno = %d)\n", ioctl_cmd,res,errno); 171 return EOALERR_IPC_STA_ERROR_SENDING_WEXT; 172 } 173 174 return OK; 175 } 176 177 S32 IPC_STA_Wext_Send(THandle hIpcSta, U32 wext_request_id, PVOID p_iwreq_data, U32 len) 178 { 179 IpcSta_t* pIpcSta = (IpcSta_t*)hIpcSta; 180 S32 res; 181 182 os_memcpy(&pIpcSta->wext_req.u.data, p_iwreq_data, len); 183 184 res = ioctl(pIpcSta->STA_socket, wext_request_id, &pIpcSta->wext_req); 185 if(res != OK) 186 { 187 os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - IPC_STA_Wext_Send - error sending Wext IOCTL to STA driver (wext_request_id = 0x%x, res = %d, errno = %d)\n",wext_request_id,res,errno); 188 return EOALERR_IPC_STA_ERROR_SENDING_WEXT; 189 } 190 191 os_memcpy(p_iwreq_data, &pIpcSta->wext_req.u.data, len); 192 193 return OK; 194 } 195 196