| /* |
| * ipc_sta.c |
| * |
| * Copyright 2001-2009 Texas Instruments, Inc. - http://www.ti.com/ |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /**************************************************************************** |
| * |
| * MODULE: IPC_STA.c |
| * |
| * PURPOSE: |
| * |
| * DESCRIPTION: |
| * ============ |
| * |
| * |
| ****************************************************************************/ |
| |
| /* includes */ |
| /************/ |
| #include <sys/types.h> |
| #include <sys/socket.h> |
| #include <net/if.h> |
| #include <linux/rtnetlink.h> |
| #include <errno.h> |
| #include <sys/ioctl.h> |
| #include <unistd.h> |
| #include <linux/wireless.h> |
| #include "cu_osapi.h" |
| #include "oserr.h" |
| #include "STADExternalIf.h" |
| #include "ipc_sta.h" |
| |
| /* defines */ |
| /***********/ |
| |
| /* local types */ |
| /***************/ |
| /* Module control block */ |
| typedef struct IpcSta_t |
| { |
| struct iwreq wext_req; |
| ti_private_cmd_t private_cmd; |
| S32 STA_socket; |
| |
| } IpcSta_t; |
| |
| /* local variables */ |
| /*******************/ |
| |
| /* local fucntions */ |
| /*******************/ |
| |
| /* |
| * IpcSta_Sockets_Open - Open a socket. |
| * Depending on the protocol present, open the right socket. The socket |
| * will allow us to talk to the driver. |
| */ |
| static S32 IpcSta_Sockets_Open(VOID) |
| { |
| static const S32 families[] = { |
| AF_INET, AF_IPX, AF_APPLETALK |
| }; |
| U32 i; |
| S32 sock; |
| |
| /* |
| * Now pick any (exisiting) useful socket family for generic queries |
| * Note : don't open all the socket, only returns when one matches, |
| * all protocols might not be valid. |
| * Workaround by Jim Kaba <jkaba@sarnoff.com> |
| * Note : in 2001% of the case, we will just open the inet_sock. |
| * The remaining 2002% case are not fully correct... |
| */ |
| |
| /* Try all families we support */ |
| for(i = 0; i < sizeof(families)/sizeof(int); ++i) |
| { |
| /* Try to open the socket, if success returns it */ |
| sock = socket(families[i], SOCK_DGRAM, 0); |
| if(sock >= 0) |
| return sock; |
| } |
| |
| return -1; |
| } |
| |
| /* |
| * IpcSta_Sockets_Close - Close the socket used for ioctl. |
| */ |
| static inline VOID IpcSta_Sockets_Close(S32 skfd) |
| { |
| close(skfd); |
| } |
| |
| |
| /* functions */ |
| /*************/ |
| THandle IpcSta_Create(const PS8 device_name) |
| { |
| IpcSta_t* pIpcSta = (IpcSta_t*)os_MemoryCAlloc(sizeof(IpcSta_t), sizeof(U8)); |
| if(pIpcSta == NULL) |
| { |
| os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - IpcSta_Create - cant allocate control block\n"); |
| return NULL; |
| } |
| |
| /* open the socket to the driver */ |
| pIpcSta->STA_socket = IpcSta_Sockets_Open(); |
| if(pIpcSta->STA_socket == -1) |
| { |
| os_error_printf(CU_MSG_ERROR, (PS8)"ERROR - IpcSta_Create - cant open socket for communication with the driver\n"); |
| return NULL; |
| } |
| |
| /* set the driver name */ |
| os_strcpy((PS8)pIpcSta->wext_req.ifr_ifrn.ifrn_name, device_name); |
| |
| return pIpcSta; |
| } |
| |
| VOID IpcSta_Destroy(THandle hIpcSta) |
| { |
| IpcSta_t* pIpcSta = (IpcSta_t*)hIpcSta; |
| |
| /* close the socket to the driver */ |
| IpcSta_Sockets_Close(pIpcSta->STA_socket); |
| |
| os_MemoryFree(pIpcSta); |
| } |
| |
| S32 IPC_STA_Private_Send(THandle hIpcSta, U32 ioctl_cmd, PVOID bufIn, U32 sizeIn, |
| PVOID bufOut, U32 sizeOut) |
| |
| { |
| IpcSta_t* pIpcSta = (IpcSta_t*)hIpcSta; |
| S32 res; |
| |
| pIpcSta ->private_cmd.cmd = ioctl_cmd; |
| if(bufOut == NULL) |
| pIpcSta ->private_cmd.flags = PRIVATE_CMD_SET_FLAG; |
| else |
| pIpcSta ->private_cmd.flags = PRIVATE_CMD_GET_FLAG; |
| |
| pIpcSta ->private_cmd.in_buffer = bufIn; |
| pIpcSta ->private_cmd.in_buffer_len = sizeIn; |
| pIpcSta ->private_cmd.out_buffer = bufOut; |
| pIpcSta ->private_cmd.out_buffer_len = sizeOut; |
| |
| |
| pIpcSta->wext_req.u.data.pointer = &pIpcSta->private_cmd; |
| pIpcSta->wext_req.u.data.length = sizeof(ti_private_cmd_t); |
| pIpcSta->wext_req.u.data.flags = 0; |
| |
| res = ioctl(pIpcSta->STA_socket, SIOCIWFIRSTPRIV, &pIpcSta->wext_req); |
| if(res != OK) |
| { |
| 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); |
| return EOALERR_IPC_STA_ERROR_SENDING_WEXT; |
| } |
| |
| return OK; |
| } |
| |
| S32 IPC_STA_Wext_Send(THandle hIpcSta, U32 wext_request_id, PVOID p_iwreq_data, U32 len) |
| { |
| IpcSta_t* pIpcSta = (IpcSta_t*)hIpcSta; |
| S32 res; |
| |
| os_memcpy(&pIpcSta->wext_req.u.data, p_iwreq_data, len); |
| |
| res = ioctl(pIpcSta->STA_socket, wext_request_id, &pIpcSta->wext_req); |
| if(res != OK) |
| { |
| 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); |
| return EOALERR_IPC_STA_ERROR_SENDING_WEXT; |
| } |
| |
| os_memcpy(p_iwreq_data, &pIpcSta->wext_req.u.data, len); |
| |
| return OK; |
| } |
| |