blob: 93c96ad2a832aeb7c0ed65833eb001c731d0312c [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License version 2 as
5 published by the Free Software Foundation.
6
7 You should have received a copy of the GNU General Public License
8 along with this program; if not, write to the Free Software
9 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16
17 Copyright (C) 2006-2007 - Motorola
Duy Truong790f06d2013-02-13 16:38:12 -080018 Copyright (c) 2008-2010, The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070019
20 Date Author Comment
21 ----------- -------------- --------------------------------
22 2006-Apr-28 Motorola The kernel module for running the Bluetooth(R)
23 Sleep-Mode Protocol from the Host side
24 2006-Sep-08 Motorola Added workqueue for handling sleep work.
25 2007-Jan-24 Motorola Added mbm_handle_ioi() call to ISR.
26
27*/
28
29#include <linux/module.h> /* kernel module definitions */
30#include <linux/errno.h>
31#include <linux/init.h>
32#include <linux/interrupt.h>
33#include <linux/kernel.h>
34#include <linux/notifier.h>
35#include <linux/proc_fs.h>
36#include <linux/spinlock.h>
37#include <linux/timer.h>
38#include <linux/uaccess.h>
39#include <linux/version.h>
40#include <linux/workqueue.h>
41#include <linux/platform_device.h>
42
43#include <linux/irq.h>
44#include <linux/param.h>
45#include <linux/bitops.h>
46#include <linux/termios.h>
47#include <mach/gpio.h>
48#include <mach/msm_serial_hs.h>
49
50#include <net/bluetooth/bluetooth.h>
51#include <net/bluetooth/hci_core.h> /* event notifications */
52#include "hci_uart.h"
Kevin F. Haggertyad69d2a2016-06-19 08:05:01 -060053#include <linux/jiffies.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070054
55#define BT_SLEEP_DBG
56#ifndef BT_SLEEP_DBG
57#define BT_DBG(fmt, arg...)
58#endif
59/*
60 * Defines
61 */
62
63#define VERSION "1.1"
64#define PROC_DIR "bluetooth/sleep"
65
66struct bluesleep_info {
67 unsigned host_wake;
68 unsigned ext_wake;
69 unsigned host_wake_irq;
70 struct uart_port *uport;
71};
72
73/* work function */
74static void bluesleep_sleep_work(struct work_struct *work);
75
76/* work queue */
77DECLARE_DELAYED_WORK(sleep_workqueue, bluesleep_sleep_work);
78
79/* Macros for handling sleep work */
80#define bluesleep_rx_busy() schedule_delayed_work(&sleep_workqueue, 0)
81#define bluesleep_tx_busy() schedule_delayed_work(&sleep_workqueue, 0)
82#define bluesleep_rx_idle() schedule_delayed_work(&sleep_workqueue, 0)
83#define bluesleep_tx_idle() schedule_delayed_work(&sleep_workqueue, 0)
84
85/* 1 second timeout */
86#define TX_TIMER_INTERVAL 1
87
88/* state variable names and bit positions */
89#define BT_PROTO 0x01
90#define BT_TXDATA 0x02
91#define BT_ASLEEP 0x04
92
93/* global pointer to a single hci device. */
94static struct hci_dev *bluesleep_hdev;
95
96static struct bluesleep_info *bsi;
97
98/* module usage */
99static atomic_t open_count = ATOMIC_INIT(1);
100
101/*
102 * Local function prototypes
103 */
104
105static int bluesleep_hci_event(struct notifier_block *this,
106 unsigned long event, void *data);
107
108/*
109 * Global variables
110 */
111
112/** Global state flags */
113static unsigned long flags;
114
115/** Tasklet to respond to change in hostwake line */
116static struct tasklet_struct hostwake_task;
117
118/** Transmission timer */
119static struct timer_list tx_timer;
120
121/** Lock for state transitions */
122static spinlock_t rw_lock;
123
124/** Notifier block for HCI events */
125struct notifier_block hci_event_nblock = {
126 .notifier_call = bluesleep_hci_event,
127};
128
129struct proc_dir_entry *bluetooth_dir, *sleep_dir;
130
131/*
132 * Local functions
133 */
134
135static void hsuart_power(int on)
136{
137 if (on) {
138 msm_hs_request_clock_on(bsi->uport);
139 msm_hs_set_mctrl(bsi->uport, TIOCM_RTS);
140 } else {
141 msm_hs_set_mctrl(bsi->uport, 0);
142 msm_hs_request_clock_off(bsi->uport);
143 }
144}
145
146
147/**
148 * @return 1 if the Host can go to sleep, 0 otherwise.
149 */
150static inline int bluesleep_can_sleep(void)
151{
152 /* check if MSM_WAKE_BT_GPIO and BT_WAKE_MSM_GPIO are both deasserted */
153 return gpio_get_value(bsi->ext_wake) &&
154 gpio_get_value(bsi->host_wake) &&
155 (bsi->uport != NULL);
156}
157
158void bluesleep_sleep_wakeup(void)
159{
160 if (test_bit(BT_ASLEEP, &flags)) {
161 BT_DBG("waking up...");
162 /* Start the timer */
Kevin F. Haggertyad69d2a2016-06-19 08:05:01 -0600163 mod_timer(&tx_timer,
164 jiffies + msecs_to_jiffies(TX_TIMER_INTERVAL * 1000));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700165 gpio_set_value(bsi->ext_wake, 0);
166 clear_bit(BT_ASLEEP, &flags);
167 /*Activating UART */
168 hsuart_power(1);
169 }
170}
171
172/**
173 * @brief@ main sleep work handling function which update the flags
174 * and activate and deactivate UART ,check FIFO.
175 */
176static void bluesleep_sleep_work(struct work_struct *work)
177{
178 if (bluesleep_can_sleep()) {
179 /* already asleep, this is an error case */
180 if (test_bit(BT_ASLEEP, &flags)) {
181 BT_DBG("already asleep");
182 return;
183 }
184
185 if (msm_hs_tx_empty(bsi->uport)) {
186 BT_DBG("going to sleep...");
187 set_bit(BT_ASLEEP, &flags);
188 /*Deactivating UART */
189 hsuart_power(0);
190 } else {
191
Kevin F. Haggertyad69d2a2016-06-19 08:05:01 -0600192 mod_timer(&tx_timer,
193 jiffies + msecs_to_jiffies(TX_TIMER_INTERVAL * 1000));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700194 return;
195 }
196 } else {
197 bluesleep_sleep_wakeup();
198 }
199}
200
201/**
202 * A tasklet function that runs in tasklet context and reads the value
203 * of the HOST_WAKE GPIO pin and further defer the work.
204 * @param data Not used.
205 */
206static void bluesleep_hostwake_task(unsigned long data)
207{
208 BT_DBG("hostwake line change");
209
210 spin_lock(&rw_lock);
211
212 if (gpio_get_value(bsi->host_wake))
213 bluesleep_rx_busy();
214 else
215 bluesleep_rx_idle();
216
217 spin_unlock(&rw_lock);
218}
219
220/**
221 * Handles proper timer action when outgoing data is delivered to the
222 * HCI line discipline. Sets BT_TXDATA.
223 */
224static void bluesleep_outgoing_data(void)
225{
226 unsigned long irq_flags;
227
228 spin_lock_irqsave(&rw_lock, irq_flags);
229
230 /* log data passing by */
231 set_bit(BT_TXDATA, &flags);
232
233 /* if the tx side is sleeping... */
234 if (gpio_get_value(bsi->ext_wake)) {
235
236 BT_DBG("tx was sleeping");
237 bluesleep_sleep_wakeup();
238 }
239
240 spin_unlock_irqrestore(&rw_lock, irq_flags);
241}
242
243/**
244 * Handles HCI device events.
245 * @param this Not used.
246 * @param event The event that occurred.
247 * @param data The HCI device associated with the event.
248 * @return <code>NOTIFY_DONE</code>.
249 */
250static int bluesleep_hci_event(struct notifier_block *this,
251 unsigned long event, void *data)
252{
253 struct hci_dev *hdev = (struct hci_dev *) data;
254 struct hci_uart *hu;
255 struct uart_state *state;
256
257 if (!hdev)
258 return NOTIFY_DONE;
259
260 switch (event) {
261 case HCI_DEV_REG:
262 if (!bluesleep_hdev) {
263 bluesleep_hdev = hdev;
264 hu = (struct hci_uart *) hdev->driver_data;
265 state = (struct uart_state *) hu->tty->driver_data;
266 bsi->uport = state->uart_port;
267 }
268 break;
269 case HCI_DEV_UNREG:
270 bluesleep_hdev = NULL;
271 bsi->uport = NULL;
272 break;
273 case HCI_DEV_WRITE:
274 bluesleep_outgoing_data();
275 break;
276 }
277
278 return NOTIFY_DONE;
279}
280
281/**
282 * Handles transmission timer expiration.
283 * @param data Not used.
284 */
285static void bluesleep_tx_timer_expire(unsigned long data)
286{
287 unsigned long irq_flags;
288
289 spin_lock_irqsave(&rw_lock, irq_flags);
290
291 BT_DBG("Tx timer expired");
292
293 /* were we silent during the last timeout? */
294 if (!test_bit(BT_TXDATA, &flags)) {
295 BT_DBG("Tx has been idle");
296 gpio_set_value(bsi->ext_wake, 1);
297 bluesleep_tx_idle();
298 } else {
299 BT_DBG("Tx data during last period");
Kevin F. Haggertyad69d2a2016-06-19 08:05:01 -0600300 mod_timer(&tx_timer,
301 jiffies + msecs_to_jiffies(TX_TIMER_INTERVAL * 1000));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700302 }
303
304 /* clear the incoming data flag */
305 clear_bit(BT_TXDATA, &flags);
306
307 spin_unlock_irqrestore(&rw_lock, irq_flags);
308}
309
310/**
311 * Schedules a tasklet to run when receiving an interrupt on the
312 * <code>HOST_WAKE</code> GPIO pin.
313 * @param irq Not used.
314 * @param dev_id Not used.
315 */
316static irqreturn_t bluesleep_hostwake_isr(int irq, void *dev_id)
317{
318 /* schedule a tasklet to handle the change in the host wake line */
319 tasklet_schedule(&hostwake_task);
320 return IRQ_HANDLED;
321}
322
323/**
324 * Starts the Sleep-Mode Protocol on the Host.
325 * @return On success, 0. On error, -1, and <code>errno</code> is set
326 * appropriately.
327 */
328static int bluesleep_start(void)
329{
330 int retval;
331 unsigned long irq_flags;
332
333 spin_lock_irqsave(&rw_lock, irq_flags);
334
335 if (test_bit(BT_PROTO, &flags)) {
336 spin_unlock_irqrestore(&rw_lock, irq_flags);
337 return 0;
338 }
339
340 spin_unlock_irqrestore(&rw_lock, irq_flags);
341
342 if (!atomic_dec_and_test(&open_count)) {
343 atomic_inc(&open_count);
344 return -EBUSY;
345 }
346
347 /* start the timer */
348
Kevin F. Haggertyad69d2a2016-06-19 08:05:01 -0600349 mod_timer(&tx_timer,
350 jiffies + msecs_to_jiffies(TX_TIMER_INTERVAL * 1000));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700351
352 /* assert BT_WAKE */
353 gpio_set_value(bsi->ext_wake, 0);
354 retval = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
355 IRQF_DISABLED | IRQF_TRIGGER_FALLING,
356 "bluetooth hostwake", NULL);
357 if (retval < 0) {
358 BT_ERR("Couldn't acquire BT_HOST_WAKE IRQ");
359 goto fail;
360 }
361
362 retval = enable_irq_wake(bsi->host_wake_irq);
363 if (retval < 0) {
364 BT_ERR("Couldn't enable BT_HOST_WAKE as wakeup interrupt");
365 free_irq(bsi->host_wake_irq, NULL);
366 goto fail;
367 }
368
369 set_bit(BT_PROTO, &flags);
370 return 0;
371fail:
372 del_timer(&tx_timer);
373 atomic_inc(&open_count);
374
375 return retval;
376}
377
378/**
379 * Stops the Sleep-Mode Protocol on the Host.
380 */
381static void bluesleep_stop(void)
382{
383 unsigned long irq_flags;
384
385 spin_lock_irqsave(&rw_lock, irq_flags);
386
387 if (!test_bit(BT_PROTO, &flags)) {
388 spin_unlock_irqrestore(&rw_lock, irq_flags);
389 return;
390 }
391
392 /* assert BT_WAKE */
393 gpio_set_value(bsi->ext_wake, 0);
394 del_timer(&tx_timer);
395 clear_bit(BT_PROTO, &flags);
396
397 if (test_bit(BT_ASLEEP, &flags)) {
398 clear_bit(BT_ASLEEP, &flags);
399 hsuart_power(1);
400 }
401
402 atomic_inc(&open_count);
403
404 spin_unlock_irqrestore(&rw_lock, irq_flags);
405 if (disable_irq_wake(bsi->host_wake_irq))
406 BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n");
407 free_irq(bsi->host_wake_irq, NULL);
408}
409/**
410 * Read the <code>BT_WAKE</code> GPIO pin value via the proc interface.
411 * When this function returns, <code>page</code> will contain a 1 if the
412 * pin is high, 0 otherwise.
413 * @param page Buffer for writing data.
414 * @param start Not used.
415 * @param offset Not used.
416 * @param count Not used.
417 * @param eof Whether or not there is more data to be read.
418 * @param data Not used.
419 * @return The number of bytes written.
420 */
421static int bluepower_read_proc_btwake(char *page, char **start, off_t offset,
422 int count, int *eof, void *data)
423{
424 *eof = 1;
425 return sprintf(page, "btwake:%u\n", gpio_get_value(bsi->ext_wake));
426}
427
428/**
429 * Write the <code>BT_WAKE</code> GPIO pin value via the proc interface.
430 * @param file Not used.
431 * @param buffer The buffer to read from.
432 * @param count The number of bytes to be written.
433 * @param data Not used.
434 * @return On success, the number of bytes written. On error, -1, and
435 * <code>errno</code> is set appropriately.
436 */
437static int bluepower_write_proc_btwake(struct file *file, const char *buffer,
438 unsigned long count, void *data)
439{
440 char *buf;
441
442 if (count < 1)
443 return -EINVAL;
444
445 buf = kmalloc(count, GFP_KERNEL);
446 if (!buf)
447 return -ENOMEM;
448
449 if (copy_from_user(buf, buffer, count)) {
450 kfree(buf);
451 return -EFAULT;
452 }
453
454 if (buf[0] == '0') {
455 gpio_set_value(bsi->ext_wake, 0);
456 } else if (buf[0] == '1') {
457 gpio_set_value(bsi->ext_wake, 1);
458 } else {
459 kfree(buf);
460 return -EINVAL;
461 }
462
463 kfree(buf);
464 return count;
465}
466
467/**
468 * Read the <code>BT_HOST_WAKE</code> GPIO pin value via the proc interface.
469 * When this function returns, <code>page</code> will contain a 1 if the pin
470 * is high, 0 otherwise.
471 * @param page Buffer for writing data.
472 * @param start Not used.
473 * @param offset Not used.
474 * @param count Not used.
475 * @param eof Whether or not there is more data to be read.
476 * @param data Not used.
477 * @return The number of bytes written.
478 */
479static int bluepower_read_proc_hostwake(char *page, char **start, off_t offset,
480 int count, int *eof, void *data)
481{
482 *eof = 1;
483 return sprintf(page, "hostwake: %u \n", gpio_get_value(bsi->host_wake));
484}
485
486
487/**
488 * Read the low-power status of the Host via the proc interface.
489 * When this function returns, <code>page</code> contains a 1 if the Host
490 * is asleep, 0 otherwise.
491 * @param page Buffer for writing data.
492 * @param start Not used.
493 * @param offset Not used.
494 * @param count Not used.
495 * @param eof Whether or not there is more data to be read.
496 * @param data Not used.
497 * @return The number of bytes written.
498 */
499static int bluesleep_read_proc_asleep(char *page, char **start, off_t offset,
500 int count, int *eof, void *data)
501{
502 unsigned int asleep;
503
504 asleep = test_bit(BT_ASLEEP, &flags) ? 1 : 0;
505 *eof = 1;
506 return sprintf(page, "asleep: %u\n", asleep);
507}
508
509/**
510 * Read the low-power protocol being used by the Host via the proc interface.
511 * When this function returns, <code>page</code> will contain a 1 if the Host
512 * is using the Sleep Mode Protocol, 0 otherwise.
513 * @param page Buffer for writing data.
514 * @param start Not used.
515 * @param offset Not used.
516 * @param count Not used.
517 * @param eof Whether or not there is more data to be read.
518 * @param data Not used.
519 * @return The number of bytes written.
520 */
521static int bluesleep_read_proc_proto(char *page, char **start, off_t offset,
522 int count, int *eof, void *data)
523{
524 unsigned int proto;
525
526 proto = test_bit(BT_PROTO, &flags) ? 1 : 0;
527 *eof = 1;
528 return sprintf(page, "proto: %u\n", proto);
529}
530
531/**
532 * Modify the low-power protocol used by the Host via the proc interface.
533 * @param file Not used.
534 * @param buffer The buffer to read from.
535 * @param count The number of bytes to be written.
536 * @param data Not used.
537 * @return On success, the number of bytes written. On error, -1, and
538 * <code>errno</code> is set appropriately.
539 */
540static int bluesleep_write_proc_proto(struct file *file, const char *buffer,
541 unsigned long count, void *data)
542{
543 char proto;
544
545 if (count < 1)
546 return -EINVAL;
547
548 if (copy_from_user(&proto, buffer, 1))
549 return -EFAULT;
550
551 if (proto == '0')
552 bluesleep_stop();
553 else
554 bluesleep_start();
555
556 /* claim that we wrote everything */
557 return count;
558}
559
560static int __init bluesleep_probe(struct platform_device *pdev)
561{
562 int ret;
563 struct resource *res;
564
565 bsi = kzalloc(sizeof(struct bluesleep_info), GFP_KERNEL);
566 if (!bsi)
567 return -ENOMEM;
568
569 res = platform_get_resource_byname(pdev, IORESOURCE_IO,
570 "gpio_host_wake");
571 if (!res) {
572 BT_ERR("couldn't find host_wake gpio\n");
573 ret = -ENODEV;
574 goto free_bsi;
575 }
576 bsi->host_wake = res->start;
577
578 ret = gpio_request(bsi->host_wake, "bt_host_wake");
579 if (ret)
580 goto free_bsi;
581 ret = gpio_direction_input(bsi->host_wake);
582 if (ret)
583 goto free_bt_host_wake;
584
585 res = platform_get_resource_byname(pdev, IORESOURCE_IO,
586 "gpio_ext_wake");
587 if (!res) {
588 BT_ERR("couldn't find ext_wake gpio\n");
589 ret = -ENODEV;
590 goto free_bt_host_wake;
591 }
592 bsi->ext_wake = res->start;
593
594 ret = gpio_request(bsi->ext_wake, "bt_ext_wake");
595 if (ret)
596 goto free_bt_host_wake;
597 /* assert bt wake */
598 ret = gpio_direction_output(bsi->ext_wake, 0);
599 if (ret)
600 goto free_bt_ext_wake;
601
602 bsi->host_wake_irq = platform_get_irq_byname(pdev, "host_wake");
603 if (bsi->host_wake_irq < 0) {
604 BT_ERR("couldn't find host_wake irq\n");
605 ret = -ENODEV;
606 goto free_bt_ext_wake;
607 }
608
609
610 return 0;
611
612free_bt_ext_wake:
613 gpio_free(bsi->ext_wake);
614free_bt_host_wake:
615 gpio_free(bsi->host_wake);
616free_bsi:
617 kfree(bsi);
618 return ret;
619}
620
621static int bluesleep_remove(struct platform_device *pdev)
622{
623 /* assert bt wake */
624 gpio_set_value(bsi->ext_wake, 0);
625 if (test_bit(BT_PROTO, &flags)) {
626 if (disable_irq_wake(bsi->host_wake_irq))
627 BT_ERR("Couldn't disable hostwake IRQ wakeup mode \n");
628 free_irq(bsi->host_wake_irq, NULL);
629 del_timer(&tx_timer);
630 if (test_bit(BT_ASLEEP, &flags))
631 hsuart_power(1);
632 }
633
634 gpio_free(bsi->host_wake);
635 gpio_free(bsi->ext_wake);
636 kfree(bsi);
637 return 0;
638}
639
640static struct platform_driver bluesleep_driver = {
641 .remove = bluesleep_remove,
642 .driver = {
643 .name = "bluesleep",
644 .owner = THIS_MODULE,
645 },
646};
647/**
648 * Initializes the module.
649 * @return On success, 0. On error, -1, and <code>errno</code> is set
650 * appropriately.
651 */
652static int __init bluesleep_init(void)
653{
654 int retval;
655 struct proc_dir_entry *ent;
656
657 BT_INFO("MSM Sleep Mode Driver Ver %s", VERSION);
658
659 retval = platform_driver_probe(&bluesleep_driver, bluesleep_probe);
660 if (retval)
661 return retval;
662
663 bluesleep_hdev = NULL;
664
665 bluetooth_dir = proc_mkdir("bluetooth", NULL);
666 if (bluetooth_dir == NULL) {
667 BT_ERR("Unable to create /proc/bluetooth directory");
668 return -ENOMEM;
669 }
670
671 sleep_dir = proc_mkdir("sleep", bluetooth_dir);
672 if (sleep_dir == NULL) {
673 BT_ERR("Unable to create /proc/%s directory", PROC_DIR);
674 return -ENOMEM;
675 }
676
677 /* Creating read/write "btwake" entry */
678 ent = create_proc_entry("btwake", 0, sleep_dir);
679 if (ent == NULL) {
680 BT_ERR("Unable to create /proc/%s/btwake entry", PROC_DIR);
681 retval = -ENOMEM;
682 goto fail;
683 }
684 ent->read_proc = bluepower_read_proc_btwake;
685 ent->write_proc = bluepower_write_proc_btwake;
686
687 /* read only proc entries */
688 if (create_proc_read_entry("hostwake", 0, sleep_dir,
689 bluepower_read_proc_hostwake, NULL) == NULL) {
690 BT_ERR("Unable to create /proc/%s/hostwake entry", PROC_DIR);
691 retval = -ENOMEM;
692 goto fail;
693 }
694
695 /* read/write proc entries */
696 ent = create_proc_entry("proto", 0, sleep_dir);
697 if (ent == NULL) {
698 BT_ERR("Unable to create /proc/%s/proto entry", PROC_DIR);
699 retval = -ENOMEM;
700 goto fail;
701 }
702 ent->read_proc = bluesleep_read_proc_proto;
703 ent->write_proc = bluesleep_write_proc_proto;
704
705 /* read only proc entries */
706 if (create_proc_read_entry("asleep", 0,
707 sleep_dir, bluesleep_read_proc_asleep, NULL) == NULL) {
708 BT_ERR("Unable to create /proc/%s/asleep entry", PROC_DIR);
709 retval = -ENOMEM;
710 goto fail;
711 }
712
713 flags = 0; /* clear all status bits */
714
715 /* Initialize spinlock. */
716 spin_lock_init(&rw_lock);
717
718 /* Initialize timer */
719 init_timer(&tx_timer);
720 tx_timer.function = bluesleep_tx_timer_expire;
721 tx_timer.data = 0;
722
723 /* initialize host wake tasklet */
724 tasklet_init(&hostwake_task, bluesleep_hostwake_task, 0);
725
726 hci_register_notifier(&hci_event_nblock);
727
728 return 0;
729
730fail:
731 remove_proc_entry("asleep", sleep_dir);
732 remove_proc_entry("proto", sleep_dir);
733 remove_proc_entry("hostwake", sleep_dir);
734 remove_proc_entry("btwake", sleep_dir);
735 remove_proc_entry("sleep", bluetooth_dir);
736 remove_proc_entry("bluetooth", 0);
737 return retval;
738}
739
740/**
741 * Cleans up the module.
742 */
743static void __exit bluesleep_exit(void)
744{
745 hci_unregister_notifier(&hci_event_nblock);
746 platform_driver_unregister(&bluesleep_driver);
747
748 remove_proc_entry("asleep", sleep_dir);
749 remove_proc_entry("proto", sleep_dir);
750 remove_proc_entry("hostwake", sleep_dir);
751 remove_proc_entry("btwake", sleep_dir);
752 remove_proc_entry("sleep", bluetooth_dir);
753 remove_proc_entry("bluetooth", 0);
754}
755
756module_init(bluesleep_init);
757module_exit(bluesleep_exit);
758
759MODULE_DESCRIPTION("Bluetooth Sleep Mode Driver ver %s " VERSION);
760#ifdef MODULE_LICENSE
761MODULE_LICENSE("GPL");
762#endif