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 */ 52typedef 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 */ 71static 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@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 */ 103static inline VOID IpcSta_Sockets_Close(S32 skfd) 104{ 105 close(skfd); 106} 107 108 109/* functions */ 110/*************/ 111THandle 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 134VOID 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 144S32 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 177S32 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