1 //------------------------------------------------------------------------------
2 // Copyright (c) 2004-2010 Atheros Communications Inc.
3 // All rights reserved.
7 // Permission to use, copy, modify, and/or distribute this software for any
8 // purpose with or without fee is hereby granted, provided that the above
9 // copyright notice and this permission notice appear in all copies.
11 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 // Author(s): ="Atheros"
22 //------------------------------------------------------------------------------
23 #include "ar6000_drv.h"
25 #include <linux/vmalloc.h>
28 #ifdef CONFIG_HAS_EARLYSUSPEND
29 #include <linux/earlysuspend.h>
32 bool enable_mmc_host_detect_change = false;
33 static void ar6000_enable_mmchost_detect_change(int enable);
36 char fwpath[256] = "/system/wifi";
38 unsigned int enablelogcat;
41 extern struct net_device *ar6000_devices[];
44 const char def_ifname[] = "wlan0";
45 module_param_string(fwpath, fwpath, sizeof(fwpath), 0644);
46 module_param(enablelogcat, uint, 0644);
47 module_param(wowledon, int, 0644);
49 #ifdef CONFIG_HAS_EARLYSUSPEND
50 static int screen_is_off;
51 static struct early_suspend ar6k_early_suspend;
54 static int (*ar6000_avail_ev_p)(void *, void *);
56 #if defined(CONFIG_ANDROID_LOGGER) && (!defined(CONFIG_MMC_MSM))
57 int logger_write(const enum logidx index,
58 const unsigned char prio,
59 const char __kernel * const tag,
60 const char __kernel * const fmt,
65 struct file *filp = (struct file *)-ENOENT;
68 int tag_bytes = strlen(tag) + 1, msg_bytes;
71 msg = kvasprintf(GFP_ATOMIC, fmt, vargs);
76 /* we have no choice since aio_write may be blocked */
77 printk(KERN_ALERT "%s", msg);
78 goto out_free_message;
80 msg_bytes = strlen(msg) + 1;
81 if (msg_bytes <= 1) /* empty message? */
82 goto out_free_message; /* don't bother, then */
83 if ((msg_bytes + tag_bytes + 1) > 2048) {
85 goto out_free_message;
88 vec[0].iov_base = (unsigned char *) &prio;
90 vec[1].iov_base = (void *) tag;
91 vec[1].iov_len = strlen(tag) + 1;
92 vec[2].iov_base = (void *) msg;
93 vec[2].iov_len = strlen(msg) + 1;
98 filp = filp_open("/dev/log/main", O_WRONLY, S_IRUSR);
99 if (IS_ERR(filp) || !filp->f_op) {
100 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: filp_open /dev/log/main error\n", __FUNCTION__));
105 if (filp->f_op->aio_write) {
106 int nr_segs = sizeof(vec) / sizeof(vec[0]);
107 int len = vec[0].iov_len + vec[1].iov_len + vec[2].iov_len;
109 init_sync_kiocb(&kiocb, filp);
112 kiocb.ki_nbytes = len;
113 ret = filp->f_op->aio_write(&kiocb, vec, nr_segs, kiocb.ki_pos);
119 filp_close(filp, NULL);
128 int android_logger_lv(void *module, int mask)
143 } else if (module == &GET_ATH_MODULE_DEBUG_VAR_NAME(driver)) {
144 return (mask <=ATH_DEBUG_MAKE_MODULE_MASK(3)) ? 3 : 2;
145 } else if (module == &GET_ATH_MODULE_DEBUG_VAR_NAME(htc)) {
151 return 3; /* DEBUG */
156 static int android_readwrite_file(const char *filename, char *rbuf, const char *wbuf, size_t length)
159 struct file *filp = (struct file *)-ENOENT;
164 int mode = (wbuf) ? O_RDWR : O_RDONLY;
165 filp = filp_open(filename, mode, S_IRUSR);
166 if (IS_ERR(filp) || !filp->f_op) {
167 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: file %s filp_open error\n", __FUNCTION__, filename));
173 /* Read the length of the file only */
176 inode = GET_INODE_FROM_FILEP(filp);
178 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Get inode from %s failed\n", __FUNCTION__, filename));
182 ret = i_size_read(inode->i_mapping->host);
187 if ( (ret=filp->f_op->write(filp, wbuf, length, &filp->f_pos)) < 0) {
188 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Write %u bytes to file %s error %d\n", __FUNCTION__,
189 length, filename, ret));
193 if ( (ret=filp->f_op->read(filp, rbuf, length, &filp->f_pos)) < 0) {
194 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Read %u bytes from file %s error %d\n", __FUNCTION__,
195 length, filename, ret));
202 filp_close(filp, NULL);
209 int android_request_firmware(const struct firmware **firmware_p, const char *name,
210 struct device *device)
213 struct firmware *firmware;
215 const char *raw_filename = name;
216 *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
219 sprintf(filename, "%s/%s", fwpath, raw_filename);
221 size_t length, bufsize, bmisize;
223 if ( (ret=android_readwrite_file(filename, NULL, NULL, 0)) < 0) {
229 bufsize = ALIGN(length, PAGE_SIZE);
230 bmisize = A_ROUND_UP(length, 4);
231 bufsize = max(bmisize, bufsize);
232 firmware->data = vmalloc(bufsize);
233 firmware->size = length;
234 if (!firmware->data) {
235 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: Cannot allocate buffer for firmware\n", __FUNCTION__));
240 if ( (ret=android_readwrite_file(filename, (char*)firmware->data, NULL, length)) != length) {
241 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: file read error, ret %d request %d\n", __FUNCTION__, ret, length));
251 vfree(firmware->data);
261 void android_release_firmware(const struct firmware *firmware)
265 vfree(firmware->data);
270 static int ar6000_android_avail_ev(void *context, void *hif_handle)
273 ar6000_enable_mmchost_detect_change(0);
274 ret = ar6000_avail_ev_p(context, hif_handle);
278 /* Useful for qualcom platform to detect our wlan card for mmc stack */
279 static void ar6000_enable_mmchost_detect_change(int enable)
281 #ifdef CONFIG_MMC_MSM
282 #define MMC_MSM_DEV "msm_sdcc.1"
286 if (!enable_mmc_host_detect_change) {
289 length = snprintf(buf, sizeof(buf), "%d\n", enable ? 1 : 0);
290 if (android_readwrite_file("/sys/devices/platform/" MMC_MSM_DEV "/detect_change",
291 NULL, buf, length) < 0) {
292 /* fall back to polling */
293 android_readwrite_file("/sys/devices/platform/" MMC_MSM_DEV "/polling", NULL, buf, length);
298 #ifdef CONFIG_HAS_EARLYSUSPEND
299 static void android_early_suspend(struct early_suspend *h)
304 static void android_late_resume(struct early_suspend *h)
310 void android_module_init(OSDRV_CALLBACKS *osdrvCallbacks)
313 if (ifname[0] == '\0')
314 strcpy(ifname, def_ifname);
315 #ifdef CONFIG_HAS_EARLYSUSPEND
316 ar6k_early_suspend.suspend = android_early_suspend;
317 ar6k_early_suspend.resume = android_late_resume;
318 ar6k_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
319 register_early_suspend(&ar6k_early_suspend);
322 ar6000_avail_ev_p = osdrvCallbacks->deviceInsertedHandler;
323 osdrvCallbacks->deviceInsertedHandler = ar6000_android_avail_ev;
325 ar6000_enable_mmchost_detect_change(1);
328 void android_module_exit(void)
330 #ifdef CONFIG_HAS_EARLYSUSPEND
331 unregister_early_suspend(&ar6k_early_suspend);
333 ar6000_enable_mmchost_detect_change(1);
337 void android_ar6k_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, bool isEvent)
340 #ifdef CONFIG_HAS_EARLYSUSPEND
343 skb && ar->arConnected) {
344 bool needWake = false;
346 if (A_NETBUF_LEN(skb) >= sizeof(u16)) {
347 u16 cmd = *(const u16 *)A_NETBUF_DATA(skb);
349 case WMI_CONNECT_EVENTID:
350 case WMI_DISCONNECT_EVENTID:
354 /* dont wake lock the system for other event */
358 } else if (A_NETBUF_LEN(skb) >= sizeof(ATH_MAC_HDR)) {
359 ATH_MAC_HDR *datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb);
360 if (!IEEE80211_IS_MULTICAST(datap->dstMac)) {
361 switch (A_BE2CPU16(datap->typeOrLen)) {
362 case 0x0800: /* IP */
363 case 0x888e: /* EAPOL */
364 case 0x88c7: /* RSN_PREAUTH */
365 case 0x88b4: /* WAPI */
368 case 0x0806: /* ARP is not important to hold wake lock */
375 /* keep host wake up if there is any event and packate coming in*/
378 int len = sprintf(buf, "on");
379 android_readwrite_file("/sys/power/state", NULL, buf, len);
381 len = sprintf(buf, "%d", 127);
382 android_readwrite_file("/sys/class/leds/lcd-backlight/brightness",
388 #endif /* CONFIG_PM */