1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include "ar6000_drv.h"
24#include "htc.h"
25#include <linux/vmalloc.h>
26#include <linux/fs.h>
27
28#ifdef CONFIG_HAS_WAKELOCK
29#include <linux/wakelock.h>
30#endif
31#ifdef CONFIG_HAS_EARLYSUSPEND
32#include <linux/earlysuspend.h>
33#endif
34
35A_BOOL enable_mmc_host_detect_change = 0;
36static void ar6000_enable_mmchost_detect_change(int enable);
37
38
39char fwpath[256] = "/system/wifi";
40int wowledon;
41unsigned int enablelogcat;
42
43extern int bmienable;
44extern struct net_device *ar6000_devices[];
45extern char ifname[];
46
47#ifdef CONFIG_HAS_WAKELOCK
48extern struct wake_lock ar6k_wow_wake_lock;
49struct wake_lock ar6k_init_wake_lock;
50#endif
51
52const char def_ifname[] = "wlan0";
53module_param_string(fwpath, fwpath, sizeof(fwpath), 0644);
54module_param(enablelogcat, uint, 0644);
55module_param(wowledon, int, 0644);
56
57#ifdef CONFIG_HAS_EARLYSUSPEND
58static int screen_is_off;
59static struct early_suspend ar6k_early_suspend;
60#endif
61
62static A_STATUS (*ar6000_avail_ev_p)(void *, void *);
63
64#if defined(CONFIG_ANDROID_LOGGER) && (!defined(CONFIG_MMC_MSM))
65int logger_write(const enum logidx index,
66 const unsigned char prio,
67 const char __kernel * const tag,
68 const char __kernel * const fmt,
69 ...)
70{
71 int ret = 0;
72 va_list vargs;
73 struct file *filp = (struct file *)-ENOENT;
74 mm_segment_t oldfs;
75 struct iovec vec[3];
76 int tag_bytes = strlen(tag) + 1, msg_bytes;
77 char *msg;
78 va_start(vargs, fmt);
79 msg = kvasprintf(GFP_ATOMIC, fmt, vargs);
80 va_end(vargs);
81 if (!msg)
82 return -ENOMEM;
83 if (in_interrupt()) {
84
85 printk(KERN_ALERT "%s", msg);
86 goto out_free_message;
87 }
88 msg_bytes = strlen(msg) + 1;
89 if (msg_bytes <= 1)
90 goto out_free_message;
91 if ((msg_bytes + tag_bytes + 1) > 2048) {
92 ret = -E2BIG;
93 goto out_free_message;
94 }
95
96 vec[0].iov_base = (unsigned char *) &prio;
97 vec[0].iov_len = 1;
98 vec[1].iov_base = (void *) tag;
99 vec[1].iov_len = strlen(tag) + 1;
100 vec[2].iov_base = (void *) msg;
101 vec[2].iov_len = strlen(msg) + 1;
102
103 oldfs = get_fs();
104 set_fs(KERNEL_DS);
105 do {
106 filp = filp_open("/dev/log/main", O_WRONLY, S_IRUSR);
107 if (IS_ERR(filp) || !filp->f_op) {
108 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: filp_open /dev/log/main error\n", __FUNCTION__));
109 ret = -ENOENT;
110 break;
111 }
112
113 if (filp->f_op->aio_write) {
114 int nr_segs = sizeof(vec) / sizeof(vec[0]);
115 int len = vec[0].iov_len + vec[1].iov_len + vec[2].iov_len;
116 struct kiocb kiocb;
117 init_sync_kiocb(&kiocb, filp);
118 kiocb.ki_pos = 0;
119 kiocb.ki_left = len;
120 kiocb.ki_nbytes = len;
121 ret = filp->f_op->aio_write(&kiocb, vec, nr_segs, kiocb.ki_pos);
122 }
123
124 } while (0);
125
126 if (!IS_ERR(filp)) {
127 filp_close(filp, NULL);
128 }
129 set_fs(oldfs);
130out_free_message:
131 if (msg) {
132 kfree(msg);
133 }
134 return ret;
135}
136#endif
137
138int android_logger_lv(void *module, int mask)
139{
140 switch (mask) {
141 case ATH_DEBUG_ERR:
142 return 6;
143 case ATH_DEBUG_INFO:
144 return 4;
145 case ATH_DEBUG_WARN:
146 return 5;
147 case ATH_DEBUG_TRC:
148 return 3;
149 default:
150#ifdef DEBUG
151 if (!module) {
152 return 3;
153 } else if (module == &GET_ATH_MODULE_DEBUG_VAR_NAME(driver)) {
154 return (mask <=ATH_DEBUG_MAKE_MODULE_MASK(3)) ? 3 : 2;
155 } else if (module == &GET_ATH_MODULE_DEBUG_VAR_NAME(htc)) {
156 return 2;
157 } else {
158 return 3;
159 }
160#else
161 return 3;
162#endif
163 }
164}
165
166static int android_readwrite_file(const A_CHAR *filename, A_CHAR *rbuf, const A_CHAR *wbuf, size_t length)
167{
168 int ret = 0;
169 struct file *filp = (struct file *)-ENOENT;
170 mm_segment_t oldfs;
171 oldfs = get_fs();
172 set_fs(KERNEL_DS);
173 do {
174 int mode = (wbuf) ? O_RDWR : O_RDONLY;
175 filp = filp_open(filename, mode, S_IRUSR);
176 if (IS_ERR(filp) || !filp->f_op) {
177 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: file %s filp_open error\n", __FUNCTION__, filename));
178 ret = -ENOENT;
179 break;
180 }
181
182 if (length==0) {
183
184 struct inode *inode;
185
186 inode = GET_INODE_FROM_FILEP(filp);
187 if (!inode) {
188 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Get inode from %s failed\n", __FUNCTION__, filename));
189 ret = -ENOENT;
190 break;
191 }
192 ret = i_size_read(inode->i_mapping->host);
193 break;
194 }
195
196 if (wbuf) {
197 if ( (ret=filp->f_op->write(filp, wbuf, length, &filp->f_pos)) < 0) {
198 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Write %u bytes to file %s error %d\n", __FUNCTION__,
199 length, filename, ret));
200 break;
201 }
202 } else {
203 if ( (ret=filp->f_op->read(filp, rbuf, length, &filp->f_pos)) < 0) {
204 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Read %u bytes from file %s error %d\n", __FUNCTION__,
205 length, filename, ret));
206 break;
207 }
208 }
209 } while (0);
210
211 if (!IS_ERR(filp)) {
212 filp_close(filp, NULL);
213 }
214 set_fs(oldfs);
215
216 return ret;
217}
218
219int android_request_firmware(const struct firmware **firmware_p, const char *name,
220 struct device *device)
221{
222 int ret = 0;
223 struct firmware *firmware;
224 char filename[256];
225 const char *raw_filename = name;
226 *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
227 if (!firmware)
228 return -ENOMEM;
229 sprintf(filename, "%s/%s", fwpath, raw_filename);
230 do {
231 size_t length, bufsize, bmisize;
232
233 if ( (ret=android_readwrite_file(filename, NULL, NULL, 0)) < 0) {
234 break;
235 } else {
236 length = ret;
237 }
238
239 bufsize = ALIGN(length, PAGE_SIZE);
240 bmisize = A_ROUND_UP(length, 4);
241 bufsize = max(bmisize, bufsize);
242 firmware->data = vmalloc(bufsize);
243 firmware->size = length;
244 if (!firmware->data) {
245 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: Cannot allocate buffer for firmware\n", __FUNCTION__));
246 ret = -ENOMEM;
247 break;
248 }
249
250 if ( (ret=android_readwrite_file(filename, (char*)firmware->data, NULL, length)) != length) {
251 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: file read error, ret %d request %d\n", __FUNCTION__, ret, length));
252 ret = -1;
253 break;
254 }
255
256 } while (0);
257
258 if (ret<0) {
259 if (firmware) {
260 if (firmware->data)
261 vfree(firmware->data);
262 kfree(firmware);
263 }
264 *firmware_p = NULL;
265 } else {
266 ret = 0;
267 }
268 return ret;
269}
270
271void android_release_firmware(const struct firmware *firmware)
272{
273 if (firmware) {
274 if (firmware->data)
275 vfree(firmware->data);
276 kfree(firmware);
277 }
278}
279
280static A_STATUS ar6000_android_avail_ev(void *context, void *hif_handle)
281{
282 A_STATUS ret;
283#ifdef CONFIG_HAS_WAKELOCK
284 wake_lock(&ar6k_init_wake_lock);
285#endif
286 ar6000_enable_mmchost_detect_change(0);
287 ret = ar6000_avail_ev_p(context, hif_handle);
288#ifdef CONFIG_HAS_WAKELOCK
289 wake_unlock(&ar6k_init_wake_lock);
290#endif
291 return ret;
292}
293
294
295static void ar6000_enable_mmchost_detect_change(int enable)
296{
297#ifdef CONFIG_MMC_MSM
298#define MMC_MSM_DEV "msm_sdcc.1"
299 char buf[3];
300 int length;
301
302 if (!enable_mmc_host_detect_change) {
303 return;
304 }
305 length = snprintf(buf, sizeof(buf), "%d\n", enable ? 1 : 0);
306 if (android_readwrite_file("/sys/devices/platform/" MMC_MSM_DEV "/detect_change",
307 NULL, buf, length) < 0) {
308
309 android_readwrite_file("/sys/devices/platform/" MMC_MSM_DEV "/polling", NULL, buf, length);
310 }
311#endif
312}
313
314#ifdef CONFIG_HAS_EARLYSUSPEND
315static void android_early_suspend(struct early_suspend *h)
316{
317 screen_is_off = 1;
318}
319
320static void android_late_resume(struct early_suspend *h)
321{
322 screen_is_off = 0;
323}
324#endif
325
326void android_module_init(OSDRV_CALLBACKS *osdrvCallbacks)
327{
328 bmienable = 1;
329 if (ifname[0] == '\0')
330 strcpy(ifname, def_ifname);
331#ifdef CONFIG_HAS_WAKELOCK
332 wake_lock_init(&ar6k_init_wake_lock, WAKE_LOCK_SUSPEND, "ar6k_init");
333#endif
334#ifdef CONFIG_HAS_EARLYSUSPEND
335 ar6k_early_suspend.suspend = android_early_suspend;
336 ar6k_early_suspend.resume = android_late_resume;
337 ar6k_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
338 register_early_suspend(&ar6k_early_suspend);
339#endif
340
341 ar6000_avail_ev_p = osdrvCallbacks->deviceInsertedHandler;
342 osdrvCallbacks->deviceInsertedHandler = ar6000_android_avail_ev;
343
344 ar6000_enable_mmchost_detect_change(1);
345}
346
347void android_module_exit(void)
348{
349#ifdef CONFIG_HAS_EARLYSUSPEND
350 unregister_early_suspend(&ar6k_early_suspend);
351#endif
352#ifdef CONFIG_HAS_WAKELOCK
353 wake_lock_destroy(&ar6k_init_wake_lock);
354#endif
355 ar6000_enable_mmchost_detect_change(1);
356}
357
358#ifdef CONFIG_PM
359void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent)
360{
361 if (
362#ifdef CONFIG_HAS_EARLYSUSPEND
363 screen_is_off &&
364#endif
365 skb && ar->arConnected) {
366 A_BOOL needWake = FALSE;
367 if (isEvent) {
368 if (A_NETBUF_LEN(skb) >= sizeof(A_UINT16)) {
369 A_UINT16 cmd = *(const A_UINT16 *)A_NETBUF_DATA(skb);
370 switch (cmd) {
371 case WMI_CONNECT_EVENTID:
372 case WMI_DISCONNECT_EVENTID:
373 needWake = TRUE;
374 break;
375 default:
376
377 break;
378 }
379 }
380 } else if (A_NETBUF_LEN(skb) >= sizeof(ATH_MAC_HDR)) {
381 ATH_MAC_HDR *datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb);
382 if (!IEEE80211_IS_MULTICAST(datap->dstMac)) {
383 switch (A_BE2CPU16(datap->typeOrLen)) {
384 case 0x0800:
385 case 0x888e:
386 case 0x88c7:
387 case 0x88b4:
388 needWake = TRUE;
389 break;
390 case 0x0806:
391 default:
392 break;
393 }
394 }
395 }
396 if (needWake) {
397
398#ifdef CONFIG_HAS_WAKELOCK
399 wake_lock_timeout(&ar6k_wow_wake_lock, 3*HZ);
400#endif
401 if (wowledon) {
402 char buf[32];
403 int len = sprintf(buf, "on");
404 android_readwrite_file("/sys/power/state", NULL, buf, len);
405
406 len = sprintf(buf, "%d", 127);
407 android_readwrite_file("/sys/class/leds/lcd-backlight/brightness",
408 NULL, buf,len);
409 }
410 }
411 }
412}
413#endif
414