1/*
2 * tiwlan_loader.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 * \file  tiwlan_loader.c
21 * \brief Loader implementation - sends FW image, NVS image and ini file to the driver
22 */
23
24
25#ifdef ANDROID
26#include <stdio.h>
27#include <stdlib.h>
28#include <errno.h>
29#include <unistd.h>
30#include <string.h>
31#include <cutils/properties.h>
32#include <hardware_legacy/power.h>
33#define PROGRAM_NAME    "wlan_loader"
34#endif
35
36#include "STADExternalIf.h"
37#include "cu_osapi.h"
38#include "ipc_sta.h"
39#include "WlanDrvCommon.h"
40
41#define TIWLAN_DRV_NAME "tiwlan"
42
43S8    g_drv_name[IF_NAME_SIZE + 1];
44
45S32 print_usage(VOID)
46{
47    os_error_printf (CU_MSG_INFO1, (PS8)"Usage: ./wlan_loader [driver_name] [options]\n");
48    os_error_printf (CU_MSG_INFO1, (PS8)"   -e <filename>  - eeprom image file name. default=./nvs_map.bin\n");
49    os_error_printf (CU_MSG_INFO1, (PS8)"   -n - no eeprom file\n");
50    os_error_printf (CU_MSG_INFO1, (PS8)"   -i <filename>  - init file name. default=tiwlan.ini\n");
51    os_error_printf (CU_MSG_INFO1, (PS8)"   -f <filename>  - firmware image file name. default=firmware.bin\n");
52    return 1;
53}
54
55/*  Return '0' if success */
56S32 init_driver( PS8 adapter_name, PS8 eeprom_file_name,
57                 PS8 init_file_name, PS8 firmware_file_name )
58{
59    PVOID f1 = NULL, f2 = NULL, f3 = NULL;
60    S32 eeprom_image_length = 0;
61    S32 init_file_length = 0;
62    S32 firmware_image_length = 0;
63    U32 req_size = 0;
64    TLoaderFilesData *init_info = NULL;
65    S32 rc = -1;
66    THandle hIpcSta;
67
68    if( !adapter_name || !*adapter_name )
69        return rc;
70
71    os_error_printf(CU_MSG_INFO1, (PS8)"+---------------------------+\n");
72    os_error_printf(CU_MSG_INFO1, (PS8)"| wlan_loader: initializing |\n");
73    os_error_printf(CU_MSG_INFO1, (PS8)"+---------------------------+\n");
74
75    hIpcSta = IpcSta_Create(adapter_name);
76    if (hIpcSta == NULL)
77    {
78	os_error_printf (CU_MSG_ERROR, (PS8)"wlan_loader: cant allocate IpcSta context\n", eeprom_file_name);
79	goto init_driver_end;
80    }
81
82    /* Send init request to the driver */
83    if ( (NULL != eeprom_file_name) &&
84         (f1 = os_fopen (eeprom_file_name, OS_FOPEN_READ)) != NULL)
85    {
86        eeprom_image_length = os_getFileSize(f1);
87        if (-1 == eeprom_image_length)
88        {
89            os_error_printf(CU_MSG_ERROR, (PS8)"Cannot get eeprom image file length <%s>\n", eeprom_file_name);
90            goto init_driver_end;
91        }
92    }
93
94    if ( (NULL != firmware_file_name) &&
95         (f2 = os_fopen (firmware_file_name, OS_FOPEN_READ)) != NULL)
96    {
97        firmware_image_length = os_getFileSize(f2);
98        if (-1 == firmware_image_length)
99        {
100            os_error_printf(CU_MSG_ERROR, (PS8)"Cannot get firmware image file length <%s>\n", firmware_file_name);
101            goto init_driver_end;
102        }
103    }
104
105    if ( (NULL != init_file_name) &&
106         (f3 = os_fopen (init_file_name, OS_FOPEN_READ)) != NULL)
107    {
108        init_file_length = os_getFileSize(f3);
109        if (-1 == init_file_length)
110        {
111            os_error_printf(CU_MSG_ERROR, (PS8)"Cannot get init file length <%s>\n", init_file_name);
112            goto init_driver_end;
113        }
114    }
115
116    /* Now when we can calculate the request length. allocate it and read the files */
117    req_size = sizeof(TLoaderFilesData) + eeprom_image_length + (init_file_length+1) + firmware_image_length;
118    init_info = (TLoaderFilesData *)os_MemoryAlloc(req_size);
119    if (!init_info)
120    {
121        os_error_printf(CU_MSG_ERROR, (PS8)"No memory to allocate init request (%d bytes)\n", req_size);
122        goto init_driver_end;
123    }
124    init_info->uNvsFileLength = eeprom_image_length;
125    init_info->uFwFileLength  = firmware_image_length;
126    init_info->uIniFileLength = init_file_length;
127
128    if (!f1 || (eeprom_image_length &&
129        os_fread(&init_info->data[0], 1, eeprom_image_length, f1)<eeprom_image_length))
130    {
131    } else
132        os_error_printf(CU_MSG_INFO1, (PS8)"****  nvs file found %s **** \n", eeprom_file_name);
133
134    if (!f2 || (firmware_image_length &&
135        os_fread(&init_info->data[eeprom_image_length], 1, firmware_image_length, f2)<firmware_image_length))
136    {
137        os_error_printf(CU_MSG_ERROR, (PS8)"Error reading firmware image %s - Aborting...\n", firmware_file_name);
138        goto init_driver_end;
139    }
140
141    if (!f3 || (init_file_length &&
142        os_fread(&init_info->data[eeprom_image_length+firmware_image_length], 1, init_file_length, f3)<init_file_length))
143    {
144        os_error_printf(CU_MSG_ERROR, (PS8)"Warning: Error in reading init_file %s - Using defaults\n", init_file_name);
145    }
146
147    /* Load driver defaults */
148    if(EOALERR_IPC_STA_ERROR_SENDING_WEXT == IPC_STA_Private_Send(hIpcSta, DRIVER_INIT_PARAM, init_info, req_size, NULL, 0))
149    {
150        os_error_printf(CU_MSG_ERROR, (PS8)"Wlan_loader: Error sending init command (DRIVER_INIT_PARAM) to driver\n");
151        goto init_driver_end;
152    }
153
154    /* No Error Found */
155    rc = 0;
156
157init_driver_end:
158    if (f1)
159        os_fclose(f1);
160    if (f2)
161        os_fclose(f2);
162    if (f3)
163        os_fclose(f3);
164    if (init_info)
165        os_MemoryFree(init_info);
166    if (hIpcSta)
167        IpcSta_Destroy(hIpcSta);
168
169    return rc;
170}
171
172#ifdef ANDROID
173int check_and_set_property(char *prop_name, char *prop_val)
174{
175    char prop_status[PROPERTY_VALUE_MAX];
176    int count;
177
178    for(count=4;( count != 0 );count--) {
179        property_set(prop_name, prop_val);
180        if( property_get(prop_name, prop_status, NULL) &&
181            (strcmp(prop_status, prop_val) == 0) )
182	    break;
183    }
184    if( count ) {
185        os_error_printf(CU_MSG_ERROR, (PS8)"Set property %s = %s - Ok\n", prop_name, prop_val);
186    }
187    else {
188        os_error_printf(CU_MSG_ERROR, (PS8)"Set property %s = %s - Fail\n", prop_name, prop_val);
189    }
190    return( count );
191}
192#endif
193
194S32 user_main(S32 argc, PPS8 argv)
195{
196    S32 i;
197    PS8 eeprom_file_name = (PS8)"./nvs_map.bin";
198    PS8 init_file_name = (PS8)"tiwlan.ini";
199    PS8 firmware_file_name = (PS8)"firmware.bin";
200
201    /* Parse command line parameters */
202    if( argc > 1 )
203    {
204        i=1;
205        if( argv[i][0] != '-' )
206        {
207            os_strcpy( g_drv_name, argv[i++] );
208        }
209        for( ;i < argc; i++ )
210        {
211            if( !os_strcmp(argv[i], (PS8)"-h" ) || !os_strcmp(argv[i], (PS8)"--help") )
212                return print_usage();
213            else if(!os_strcmp(argv[i], (PS8)"-f" ) )
214            {
215                firmware_file_name = argv[++i];
216            }
217            else if(!os_strcmp(argv[i], (PS8)"-e") && (i+1<argc))
218            {
219                eeprom_file_name = argv[++i];
220            }
221            else if(!os_strcmp(argv[i], (PS8)"-i") && (i+1<argc))
222            {
223                init_file_name = argv[++i];
224            }
225            else if(!os_strcmp(argv[i], (PS8)"-n" ) )
226            {
227               eeprom_file_name = NULL;
228            }
229            else
230            {
231                os_error_printf (CU_MSG_ERROR, (PS8)"Loader: unknow parameter '%s'\n", argv[i]);
232#ifdef ANDROID
233                check_and_set_property("wlan.driver.status", "failed");
234#endif
235                return -1;
236            }
237        }
238    }
239
240    if( !g_drv_name[0] )
241    {
242        os_strcpy(g_drv_name, (PS8)TIWLAN_DRV_NAME "0" );
243    }
244
245#ifdef ANDROID
246    acquire_wake_lock(PARTIAL_WAKE_LOCK, PROGRAM_NAME);
247#endif
248
249    if (init_driver (g_drv_name, eeprom_file_name, init_file_name, firmware_file_name) != 0)
250    {
251#ifdef ANDROID
252        check_and_set_property("wlan.driver.status", "failed");
253        release_wake_lock(PROGRAM_NAME);
254#endif
255        return -1;
256    }
257#ifdef ANDROID
258    check_and_set_property("wlan.driver.status", "ok");
259    release_wake_lock(PROGRAM_NAME);
260#endif
261    return 0;
262}
263