• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "wifi_hal_bcm43340"
18 
19 #include <fcntl.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <sys/socket.h>
27 #include <net/if.h>
28 #include <net/if_arp.h>
29 #include <netinet/in.h>
30 #include <cutils/log.h>
31 #include <cutils/properties.h>
32 #include <hardware_brillo/wifi_driver_hal.h>
33 
34 const char kStationDeviceName[] = "wlan0";
35 
write_file(const char * filename,const char * content)36 static bool write_file(const char *filename, const char *content) {
37     int fd = open(filename, O_WRONLY);
38     if (fd < 0) {
39         ALOGE("Cannot open %s for writing", filename);
40         return false;
41     }
42 
43     ssize_t write_count = strlen(content);
44     ssize_t actual_count = write(fd, content, write_count);
45     close(fd);
46 
47     if (actual_count != write_count) {
48         ALOGE("Expected to write %d bytes to %s but write returns %d",
49             write_count, filename, actual_count);
50         return false;
51     }
52     return true;
53 }
54 
55 /* Our HAL needs to set the AP/Station mode prior to actually initializing
56  * the wifi. We use a dummy function for the initialize.
57  */
wifi_driver_initialize_bcm43340(void)58 static wifi_driver_error wifi_driver_initialize_bcm43340(void) {
59     return WIFI_SUCCESS;
60 }
61 
wifi_driver_initialize_bcm43340_internal(void)62 static wifi_driver_error wifi_driver_initialize_bcm43340_internal(void) {
63    struct ifreq req;
64    int rc, socketfd;
65 
66    socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
67    if (socketfd < 0) {
68 	ALOGE("%s: unable to open control socket\n", __func__);
69 	return WIFI_ERROR_UNKNOWN;
70    }
71 
72    strcpy (req.ifr_name, kStationDeviceName);
73    rc = ioctl(socketfd, SIOCGIFFLAGS, &req);
74    if (rc < 0) {
75 	ALOGE("%s: unable to query interface wlan0\n", __func__);
76 	return WIFI_ERROR_UNKNOWN;
77    }
78 
79    req.ifr_flags &= ~(IFF_UP|IFF_RUNNING);
80    rc = ioctl(socketfd, SIOCSIFFLAGS, &req);
81    if (rc < 0) {
82 	ALOGE("%s: unable to down interface wlan0\n", __func__);
83 	return WIFI_ERROR_UNKNOWN;
84    }
85 
86    req.ifr_flags |= IFF_UP|IFF_RUNNING;
87    rc = ioctl(socketfd, SIOCSIFFLAGS, &req);
88    if (rc < 0) {
89 	ALOGE("%s: unable to up interface wlan0\n", __func__);
90 	return WIFI_ERROR_UNKNOWN;
91    }
92 
93     return WIFI_SUCCESS;
94 }
95 
96 static wifi_driver_error
wifi_driver_set_mode_bcm43340(wifi_driver_mode mode,char * wifi_device_name,size_t wifi_device_name_size)97 wifi_driver_set_mode_bcm43340(
98     wifi_driver_mode mode,
99     char* wifi_device_name,
100     size_t wifi_device_name_size) {
101 
102     const char *firmware_path = nullptr;
103 
104     switch (mode) {
105     case WIFI_MODE_AP:
106       firmware_path = WIFI_DRIVER_FW_PATH_AP;
107       break;
108 
109     case WIFI_MODE_STATION:
110       firmware_path = WIFI_DRIVER_FW_PATH_STA;
111       break;
112 
113 #ifdef WIFI_MODE_P2P
114     case WIFI_MODE_P2P:
115       firmware_path = WIFI_DRIVER_FW_PATH_P2P;
116       break;
117 #endif
118 
119     default:
120       ALOGE("Unkonwn WiFi driver mode %d", mode);
121       return WIFI_ERROR_INVALID_ARGS;
122     }
123 
124     if (true != write_file(WIFI_DRIVER_NVRAM_PATH_PARAM, WIFI_DRIVER_NVRAM_PATH))
125 	return WIFI_ERROR_UNKNOWN;
126     if (true != write_file(WIFI_DRIVER_FW_PATH_PARAM, firmware_path))
127 	return WIFI_ERROR_UNKNOWN;
128 
129     strlcpy(wifi_device_name, kStationDeviceName, wifi_device_name_size);
130     return wifi_driver_initialize_bcm43340_internal();
131 }
132 
133 
134 static int
close_bcm43340_driver(struct hw_device_t * device)135 close_bcm43340_driver(struct hw_device_t *device) {
136     wifi_driver_device_t *dev = (wifi_driver_device_t *)device;
137     if (dev)
138         free(dev);
139     return 0;
140 }
141 
142 static int
open_bcm43340_driver(const struct hw_module_t * module,const char *,struct hw_device_t ** device)143 open_bcm43340_driver(const struct hw_module_t* module, const char*, struct hw_device_t** device) {
144     wifi_driver_device_t* dev = (wifi_driver_device_t *)calloc(1, sizeof(wifi_driver_device_t));
145 
146     dev->common.tag = HARDWARE_DEVICE_TAG;
147     dev->common.version = WIFI_DRIVER_DEVICE_API_VERSION_0_1;
148 
149     // We're forced into this cast by the existing API.  This pattern is
150     // common among users of the HAL.
151     dev->common.module = (hw_module_t *)module;
152 
153     dev->common.close = close_bcm43340_driver;
154     dev->wifi_driver_initialize = wifi_driver_initialize_bcm43340;
155     dev->wifi_driver_set_mode = wifi_driver_set_mode_bcm43340;
156 
157     *device = &dev->common;
158 
159     return 0;
160 }
161 
162 static struct hw_module_methods_t bcm43340_driver_module_methods = {
163     open:		open_bcm43340_driver
164 };
165 
166 hw_module_t HAL_MODULE_INFO_SYM = {
167   tag: 			HARDWARE_MODULE_TAG,
168   version_major:	1,
169   version_minor:	0,
170   id:			WIFI_DRIVER_HARDWARE_MODULE_ID,
171   name:			"BCM43340 / Edison module",
172   author:		"Intel",
173   methods:		&bcm43340_driver_module_methods,
174   dso:			NULL,
175   reserved:		{0},
176 };
177