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