📄 bluetooth.c
字号:
static s32 bt_disconnect(u32 con_id){ int line = GET_LINE(con_id); s32 retval = 0; if ((SESSIONSTATE(line) != BT_LOWERCONNECTED) && (SESSIONSTATE(line) != BT_ACTIVE)) { D_ERR(__FUNCTION__ ": Line not connected\n"); return -MSGCODE(MSG_BT_INTERFACE, BT_NOTCONNECTED); } switch(GET_PSM(con_id)) { case RFCOMM_LAYER: BT_DRIVER(__FUNCTION__ ": Disconnecting line %d (ONLY RFCOMM)\n", line); CHECK_RFCOMM(con_id); bt_ctrl.session[line].disconnect_status = -1; if ((retval = rfcomm_disconnect_req(line)) < 0) { BT_DRIVER(__FUNCTION__ ": Failed\n"); return retval; } /* fixme -- remove timers, useless when rfcomm blocks ? */ /* Sleep if not yet disconnected */ if (bt_ctrl.session[line].disconnect_status == -1) { start_wq_timer(&bt_timer, BT_CON_TIMEOUT, &bt_ctrl.connect_wq[line]); interruptible_sleep_on(&bt_ctrl.connect_wq[line]); } return bt_ctrl.session[line].disconnect_status; case L2CAP_TEST_LAYER: retval = test_disconnect_req(testcon); /* extern l2cap_con set in test.c */ return bt_ctrl.session[line].disconnect_status; case L2CAP_TEST2_LAYER: retval = test_disconnect_req(testcon2); return bt_ctrl.session[line].disconnect_status; case L2CAP_TEST3_LAYER: retval = test_disconnect_req(testcon3); return bt_ctrl.session[line].disconnect_status; default: BT_DRIVER(__FUNCTION__ ": Can't disconnect this layer (PSM %x)\n", GET_PSM(con_id)); return -EINVAL; } return retval;}/* This function is currently not used in OpenBT for any useful stuff, however other ports of OpenBT uses this to notify applications */voidbt_disconnect_ind(u32 con_id) { if (GET_PSM(con_id) == RFCOMM_LAYER) BT_DRIVER(__FUNCTION__ ": RFCOMM dlci: %d\n", GET_RFCOMMDLCI(con_id)); else BT_DRIVER(__FUNCTION__ ": PSM %d\n", GET_PSM(con_id));}voidbt_disconnect_cfm(u32 con_id, s32 status) { u32 line = GET_LINE(con_id); BT_DRIVER(__FUNCTION__ ": PSM %d, status %d\n", GET_PSM(con_id), status); bt_ctrl.session[line].disconnect_status = status; release_wq_timer(&bt_timer); wake_up_interruptible(&bt_ctrl.connect_wq[line]);}/* notified upper tty application that this line is down */voidbt_hangupline(s32 line){ struct tty_struct *upper_tty; BT_DRIVER(__FUNCTION__ ": Hanging up line %d\n", line); /* find corresponding upper tty */ upper_tty = GET_UPPERTTY(line); if (upper_tty) tty_hangup(upper_tty); else D_WARN(__FUNCTION__ ": No upper tty\n");}#ifdef __CRIS__/* is run once every 10 jiffies which clears any lit led if it has been lit for at least BT_FLASH_LED_TIME jiffies */static voidbt_clear_led(unsigned long dummy){ if (bt_led_active && jiffies > bt_led_next_time) { bt_set_leds(NO_BLUETOOTH_ACTIVITY); /* Set the earliest time we may set the LED */ bt_led_next_time = jiffies + BT_FLASH_LED_PAUSE; bt_led_active = 0; } bt_clear_led_timer.expires = jiffies + HZ/10; add_timer(&bt_clear_led_timer);}static voidbt_flash_led(void){ if (!bt_led_active && jiffies > bt_led_next_time) { bt_set_leds(BLUETOOTH_ACTIVITY); /* Set the earliest time we may clear the LED */ bt_led_next_time = jiffies + BT_FLASH_LED_TIME; bt_led_active = 1; }}static voidbt_set_leds(int active){ if ((!hci_ctrl.nbr_of_connections && active == BLUETOOTH_ACTIVITY) || (hci_ctrl.nbr_of_connections && active == NO_BLUETOOTH_ACTIVITY)) { LED_ACTIVE_SET(bt_dfu_mode(-1) ? LED_ORANGE : LED_GREEN); } else { LED_ACTIVE_SET(LED_OFF); }}#elsestatic voidbt_flash_led(void){ /* blink blink :) */}#endif/**********************************//* Bluetooth Stack Initialisation *//**********************************/#if defined(MODULE) || defined(__KERNEL__)static int __init bt_init(void)#elses32 bt_init(void)#endif{ static struct tty_ldisc bt_ldisc; s32 status;#ifdef CONFIG_BLUETOOTH_PROC s32 procfs_status = -1;#endif bt_show_version(); /* Initialise the tty_driver structure */ memset(&bt_driver, 0, sizeof(bt_driver)); bt_driver.magic = BT_TTY_DRIVER_MAGIC; bt_driver.name = "ttyBT"; bt_driver.major = BT_TTY_MAJOR; bt_driver.minor_start = 0; bt_driver.num = BT_NBR_PORTS; bt_driver.type = TTY_DRIVER_TYPE_SERIAL; bt_driver.subtype = BLUETOOTH_TYPE_DATA; bt_driver.init_termios = tty_std_termios; bt_driver.init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* no output processing */ bt_driver.init_termios.c_oflag = 0; /* no echo ... */ bt_driver.init_termios.c_lflag = 0; bt_driver.flags = TTY_DRIVER_REAL_RAW; bt_driver.refcount = &bluetooth_refcount; bt_driver.table = bt_table; bt_driver.termios = bt_termios; bt_driver.termios_locked = bt_termios_locked; /* Register the interface against usermode applications */ bt_driver.open = bt_open; bt_driver.close = bt_close; bt_driver.write = bt_write_top; bt_driver.put_char = bt_put_char; bt_driver.flush_chars = bt_flush_chars; bt_driver.write_room = bt_write_room; bt_driver.chars_in_buffer = bt_chars_in_buffer; bt_driver.flush_buffer = bt_flush_buffer; bt_driver.ioctl = bt_ioctl; bt_driver.throttle = bt_throttle; bt_driver.unthrottle = bt_unthrottle; bt_driver.set_termios = bt_set_termios; bt_driver.stop = bt_stop; bt_driver.start = bt_start; bt_driver.hangup = bt_hangup; if (tty_register_driver(&bt_driver)) panic("Could not register bluetooth driver\n"); DSYS("Bluetooth driver registered as %s\n", bt_driver.name);/* * Register the tty discipline * (Interface against lower hardware driver) */ memset(&bt_ldisc, 0, sizeof(bt_ldisc)); bt_ldisc.magic = TTY_LDISC_MAGIC; bt_ldisc.open = bt_tty_open; bt_ldisc.close = bt_tty_close; bt_ldisc.read = bt_tty_read; bt_ldisc.write = bt_tty_write; /* bypass stack ...*/ bt_ldisc.ioctl = bt_tty_ioctl;#ifdef __USE_OLD_SYMTAB__ bt_ldisc.select = bt_tty_select;#else bt_ldisc.poll = bt_tty_poll;#endif bt_ldisc.receive_room = bt_tty_room; bt_ldisc.receive_buf = bt_receive_lower_stack; bt_ldisc.write_wakeup = bt_tty_wakeup; status = tty_register_ldisc(N_BT, &bt_ldisc); if (status == 0) { DSYS("Bluetooth line discipline registered.\n"); } else { printk (KERN_ERR "Error registering line discipline: %d\n", status); return status; } /* Initialise the tty_driver structure */ bt_ctrl_init(); sertty = NULL; DSYS("Registering BT proc files\n"); #ifdef CONFIG_BLUETOOTH_PROC#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) { procfs_status = -1; if (create_proc_info_entry(bt_status.name, bt_status.mode, &proc_root, bt_status.get_info)) procfs_status = 1; }#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0) procfs_status = proc_register(&proc_root, &bt_status);#else procfs_status = proc_register_dynamic(&proc_root, &bt_status);#endif /* LINUX_VERSION_CODE */ if (procfs_status < 0) { D_ERR("Couldn't register proc file bt_status %d\n", procfs_status); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) { procfs_status = -1; if (create_proc_info_entry(bt_internal_info.name, bt_internal_info.mode, &proc_root, bt_internal_info.get_info)) procfs_status = 1; }#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0) procfs_status = proc_register(&proc_root, &bt_internal_info);#else procfs_status = proc_register_dynamic(&proc_root, &bt_internal_info);#endif /* LINUX_VERSION_CODE */ if (procfs_status < 0) { D_ERR("Could not register proc file bt_internal_info %d\n", procfs_status); }#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) { procfs_status = -1; if (create_proc_info_entry(bt_proc_doit.name, bt_proc_doit.mode, &proc_root, bt_proc_doit.get_info)) procfs_status = 1;}#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0) procfs_status = proc_register(&proc_root, &bt_proc_doit);#else procfs_status = proc_register_dynamic(&proc_root, &bt_proc_doit);#endif /* LINUX_VERSION_CODE */ if (procfs_status < 0) { D_ERR("Could not register proc file bt_status %d\n", procfs_status); }#endif /* CONFIG_BLUETOOTH_PROC */#ifdef CONFIG_BLUETOOTH_USE_TCI#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) { procfs_status = -1; if (create_proc_info_entry(tci_proc_entry.name, tci_proc_entry.mode, &proc_root, tci_proc_entry.get_info)) procfs_status = 1; }#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0) procfs_status = proc_register(&proc_root, &tci_proc_entry);#else procfs_status = proc_register_dynamic(&proc_root, &tci_proc_entry);#endif /* LINUX_VERSION_CODE */ if (procfs_status < 0) { D_ERR("Could not register proc file for tci database %d\n", procfs_status); }#endif /* CONFIG_BLUETOOTH_USE_TCI */ sdp_create_proc_file();#ifdef CONFIG_BLUETOOTH_USE_SECURITY_MANAGER sec_man_create_proc_file();#endif DSYS("Bluetooth Driver Using ttyBT[0-%d] (data), ttyBTC (ctrl [%d])\n", BT_NBR_DATAPORTS-1, BT_NBR_PORTS-1);#ifdef CONFIG_BLUETOOTH_USE_INBUFFER DSYS("Using BT Inbuffers [%d]\n", BT_INBUFFER_SIZE); /* Init hci inbuffer */ hci_data.head = &hci_data.data[0]; hci_data.tail = &hci_data.data[BT_INBUFFER_SIZE-1]; hci_data.put = hci_data.head; hci_data.get = hci_data.head;;#endif#ifdef __KERNEL__#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) sema_init(&ioctl_sem, 1);#endif /* LINUX_VERSION_CODE */#endif /* __KERNEL__ */ hci_module_init(); rfcomm_module_init(); return 0; /* success */}static voidbt_show_version(void){ printk("Bluetooth Driver v1.3, Copyright (c) 2000, 2001 Axis Communications AB\n");}s32bt_initiated(void){ return bt_stack_initiated;}s32bt_use_bcsp(s32 new_use_bcsp){ /* default val */#ifdef CONFIG_BLUETOOTH_USE_BCSP static s32 use_bcsp = 1;#else static s32 use_bcsp = 0;#endif s32 old = use_bcsp; if (new_use_bcsp >= 0) {#ifdef CONFIG_BLUETOOTH_SUPPORT_BCSP use_bcsp = new_use_bcsp;#endif } return old;}s32bt_dfu_mode(s32 new_dfu_mode){ static s32 dfu_mode = 0; s32 old = dfu_mode; if (new_dfu_mode >= 0) {#ifdef CONFIG_BLUETOOTH_SUPPORT_BCSP dfu_mode = new_dfu_mode;#endif } return old;}s32bt_init_stack(void){ unsigned long page; /* shutdown if already initiated */ if (bt_stack_initiated) bt_shutdown(); /* The following part of the code is originally from the Linux serial driver (serial.c). The last conditional is used to prevent that only one "tmp_bt_buf" is allocated even if many tty's are opened. This is because the kernel may schedule after get_free_page is called. */ if (!tmp_bt_buf) { page = get_free_page(GFP_KERNEL); if (!page) return -ENOMEM; if (tmp_bt_buf) free_page(page); else tmp_bt_buf = (u8 *) page; } /* Initialise all layers in the bluetooth stack */ DSYS("Initialising Bluetooth Stack\n"); DSYS("Current HW: %s\n", bt_hw_vendor());#ifdef __CRIS__ /* start led timer */ bt_set_leds(NO_BLUETOOTH_ACTIVITY); init_timer(&bt_clear_led_timer); bt_clear_led_timer.function = &bt_clear_led; bt_clear_led_timer.expires = jiffies + HZ/10; add_timer(&bt_clear_led_timer);#endif btmem_init();#ifdef CONFIG_BLUETOOTH_SUPPORT_BCSP if (bt_use_bcsp(-1) && !bcsp_issyncronized()) { if (bcsp_init() < 0) { bcsp_shutdown(); goto init_failed_exit0; } }#endif /* Always check if hci succeeded */ if (hci_init() < 0) { D_ERR("HCI failed to initialise\n"); goto init_failed_exit1; } if (!bt_dfu_mode(-1)) { l2cap_init();#ifdef CONFIG_BLUETOOTH_USE_TCI tci_init();#else rfcomm_init(); sdp_init(1); /* For now always init as server */ tcs_init(); test_init();#endif } bt_stack_initiated = 1; bt_stat.bytes_received = 0; bt_stat.bytes_sent = 0;#ifdef BT_USELINEBUF bt_reset_linebuf();#endif return 0;init_failed_exit1: hci_shutdown();#ifdef CONFIG_BLUETOOTH_SUPPORT_BCSP bcsp_shutdown();#endifinit_failed_exit0: btmem_shutdown(); if (tmp_bt_buf) { free_page((unsigned long) tmp_bt_buf); tmp_bt_buf = NULL; }#ifdef __CRIS__ del_timer(&bt_clear_led_timer); bt_set_leds(NO_BLUETOOTH_ACTIVITY);#endif return -1;}#ifdef BT_USELINEBUFvoid bt_reset_linebuf(){ /* init tty line buffer */ tty_linebuf.line = TTY_NOLINE; tty_linebuf.cur_len = 0; memset(tty_linebuf.data, 0, TTY_LINEBUFLEN);}void bt_linebuf
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -