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
);
130 int android_logger_lv(void *module
, int mask
)
145 } else if (module
== &GET_ATH_MODULE_DEBUG_VAR_NAME(driver
)) {
146 return (mask
<=ATH_DEBUG_MAKE_MODULE_MASK(3)) ? 3 : 2;
147 } else if (module
== &GET_ATH_MODULE_DEBUG_VAR_NAME(htc
)) {
153 return 3; /* DEBUG */
158 static int android_readwrite_file(const char *filename
, char *rbuf
, const char *wbuf
, size_t length
)
161 struct file
*filp
= (struct file
*)-ENOENT
;
166 int mode
= (wbuf
) ? O_RDWR
: O_RDONLY
;
167 filp
= filp_open(filename
, mode
, S_IRUSR
);
168 if (IS_ERR(filp
) || !filp
->f_op
) {
169 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("%s: file %s filp_open error\n", __FUNCTION__
, filename
));
175 /* Read the length of the file only */
178 inode
= GET_INODE_FROM_FILEP(filp
);
180 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("%s: Get inode from %s failed\n", __FUNCTION__
, filename
));
184 ret
= i_size_read(inode
->i_mapping
->host
);
189 if ( (ret
=filp
->f_op
->write(filp
, wbuf
, length
, &filp
->f_pos
)) < 0) {
190 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("%s: Write %u bytes to file %s error %d\n", __FUNCTION__
,
191 length
, filename
, ret
));
195 if ( (ret
=filp
->f_op
->read(filp
, rbuf
, length
, &filp
->f_pos
)) < 0) {
196 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("%s: Read %u bytes from file %s error %d\n", __FUNCTION__
,
197 length
, filename
, ret
));
204 filp_close(filp
, NULL
);
211 int android_request_firmware(const struct firmware
**firmware_p
, const char *name
,
212 struct device
*device
)
215 struct firmware
*firmware
;
217 const char *raw_filename
= name
;
218 *firmware_p
= firmware
= kzalloc(sizeof(*firmware
), GFP_KERNEL
);
221 sprintf(filename
, "%s/%s", fwpath
, raw_filename
);
223 size_t length
, bufsize
, bmisize
;
225 if ( (ret
=android_readwrite_file(filename
, NULL
, NULL
, 0)) < 0) {
231 bufsize
= ALIGN(length
, PAGE_SIZE
);
232 bmisize
= A_ROUND_UP(length
, 4);
233 bufsize
= max(bmisize
, bufsize
);
234 firmware
->data
= vmalloc(bufsize
);
235 firmware
->size
= length
;
236 if (!firmware
->data
) {
237 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("%s: Cannot allocate buffer for firmware\n", __FUNCTION__
));
242 if ( (ret
=android_readwrite_file(filename
, (char*)firmware
->data
, NULL
, length
)) != length
) {
243 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("%s: file read error, ret %d request %d\n", __FUNCTION__
, ret
, length
));
253 vfree(firmware
->data
);
263 void android_release_firmware(const struct firmware
*firmware
)
267 vfree(firmware
->data
);
272 static int ar6000_android_avail_ev(void *context
, void *hif_handle
)
275 ar6000_enable_mmchost_detect_change(0);
276 ret
= ar6000_avail_ev_p(context
, hif_handle
);
280 /* Useful for qualcom platform to detect our wlan card for mmc stack */
281 static void ar6000_enable_mmchost_detect_change(int enable
)
283 #ifdef CONFIG_MMC_MSM
284 #define MMC_MSM_DEV "msm_sdcc.1"
288 if (!enable_mmc_host_detect_change
) {
291 length
= snprintf(buf
, sizeof(buf
), "%d\n", enable
? 1 : 0);
292 if (android_readwrite_file("/sys/devices/platform/" MMC_MSM_DEV
"/detect_change",
293 NULL
, buf
, length
) < 0) {
294 /* fall back to polling */
295 android_readwrite_file("/sys/devices/platform/" MMC_MSM_DEV
"/polling", NULL
, buf
, length
);
300 #ifdef CONFIG_HAS_EARLYSUSPEND
301 static void android_early_suspend(struct early_suspend
*h
)
306 static void android_late_resume(struct early_suspend
*h
)
312 void android_module_init(OSDRV_CALLBACKS
*osdrvCallbacks
)
315 if (ifname
[0] == '\0')
316 strcpy(ifname
, def_ifname
);
317 #ifdef CONFIG_HAS_EARLYSUSPEND
318 ar6k_early_suspend
.suspend
= android_early_suspend
;
319 ar6k_early_suspend
.resume
= android_late_resume
;
320 ar6k_early_suspend
.level
= EARLY_SUSPEND_LEVEL_BLANK_SCREEN
;
321 register_early_suspend(&ar6k_early_suspend
);
324 ar6000_avail_ev_p
= osdrvCallbacks
->deviceInsertedHandler
;
325 osdrvCallbacks
->deviceInsertedHandler
= ar6000_android_avail_ev
;
327 ar6000_enable_mmchost_detect_change(1);
330 void android_module_exit(void)
332 #ifdef CONFIG_HAS_EARLYSUSPEND
333 unregister_early_suspend(&ar6k_early_suspend
);
335 ar6000_enable_mmchost_detect_change(1);
339 void android_ar6k_check_wow_status(AR_SOFTC_T
*ar
, struct sk_buff
*skb
, bool isEvent
)
342 #ifdef CONFIG_HAS_EARLYSUSPEND
345 skb
&& ar
->arConnected
) {
346 bool needWake
= false;
348 if (A_NETBUF_LEN(skb
) >= sizeof(u16
)) {
349 u16 cmd
= *(const u16
*)A_NETBUF_DATA(skb
);
351 case WMI_CONNECT_EVENTID
:
352 case WMI_DISCONNECT_EVENTID
:
356 /* dont wake lock the system for other event */
360 } else if (A_NETBUF_LEN(skb
) >= sizeof(ATH_MAC_HDR
)) {
361 ATH_MAC_HDR
*datap
= (ATH_MAC_HDR
*)A_NETBUF_DATA(skb
);
362 if (!IEEE80211_IS_MULTICAST(datap
->dstMac
)) {
363 switch (A_BE2CPU16(datap
->typeOrLen
)) {
364 case 0x0800: /* IP */
365 case 0x888e: /* EAPOL */
366 case 0x88c7: /* RSN_PREAUTH */
367 case 0x88b4: /* WAPI */
370 case 0x0806: /* ARP is not important to hold wake lock */
377 /* keep host wake up if there is any event and packate comming in*/
380 int len
= sprintf(buf
, "on");
381 android_readwrite_file("/sys/power/state", NULL
, buf
, len
);
383 len
= sprintf(buf
, "%d", 127);
384 android_readwrite_file("/sys/class/leds/lcd-backlight/brightness",
390 #endif /* CONFIG_PM */