📄 bluetooth.c
字号:
copy_from_user(&ping+8, (u8*)arg+8, ping.len); printk("len: %d\n", ping.len); return l2ca_ping(ping.bd, ping.data, ping.len); } case BTGETINFO: { u8 bd[6]; u16 type; /* first byte contains length of whole hci message */ copy_from_user(&bd, (u8*)arg, 6); copy_from_user(&type, (u8*)arg + 6, 2); BT_DRIVER("BTGETINFO: Type %d\n", type); return l2ca_getinfo(bd, type); } /* force m/s switch as server */ case BTSETMSSWITCH: { u8 enable; GET_USER(tmp, (s32*)arg); enable = (u8)(tmp & 0xff); BT_DRIVER("BTSETMSSWITCH: %d\n", enable); hci_force_msswitch(enable); return 0; } /* Set max number of connections */ case BTSETMAXCONNECTIONS: GET_USER(tmp, (s32*)arg); BT_DRIVER("BTSETMAXCONNECTIONS: %d\n", tmp); return hci_set_max_connections(tmp); case BTSETBCSPMODE: GET_USER(tmp, (s32*)arg); BT_DRIVER("BTSETBCSPMODE: %d\n", tmp); tmp = bt_use_bcsp(tmp); put_user(tmp, (s32*)arg); return 0; case BT_SET_DFU_MODE: GET_USER(tmp, (s32*)arg); BT_DRIVER("BT_SET_DFU_MODE: %d\n", tmp); tmp = bt_dfu_mode(tmp); put_user(tmp, (s32*)arg); return 0;#ifdef CONFIG_BLUETOOTH_CSR /* | ps_key (u16) | rw_mode (u16) | len (u16) | params (u16[])| */ case BT_CSR_PSKEY: { u16 u16_size = CSR_PSKEY_MSGHDR_SIZE + CSR_PSKEY_MAXPARAMS; u16 msg[size]; copy_from_user(msg, (u8*)arg, u16_size*sizeof(u16)); BT_DRIVER("BT_CSR_PSKEY [ps:%d type:%d]\n", msg[0], msg[1]); csr_pskey(msg[0], msg[1], &msg[3], msg[2]); copy_to_user((s32*)arg, msg, u16_size*sizeof(u16)); return 0; }#endif /* CONFIG_BLUETOOTH_CSR */#ifdef CONFIG_BLUETOOTH_SUPPORT_BCSP case BTINITBCSP: BT_DRIVER("BTINITBCSP\n"); if (bcsp_init() < 0) { printk("Sync failed\n"); return -ETIMEDOUT; } return 0; case BT_SEND_DFU_COMMAND: { int ret; s32 dfu_len; if (!bt_use_bcsp(-1)) return -EPERM; GET_USER(dfu_len, (s32*)arg); if (dfu_len > sizeof dfu_data) return -EINVAL; copy_from_user(dfu_data, (s32*)arg + 1, dfu_len); ret = bcsp_sequence_send(dfu_data, dfu_len, BCSP_DFU_CHN); if (ret < 0) return ret; return 0; } case BT_RETRIEVE_DFU_RESPONSE: { s32 dfu_len; if (!bt_use_bcsp(-1)) return -EPERM; GET_USER(dfu_len, (s32*)arg); if (dfu_len > sizeof dfu_data) return -EINVAL; dfu_len = hci_read_dfu((u8*)((s32*)arg + 1), dfu_len); if (dfu_len < 0) return dfu_len; put_user(dfu_len, (s32*)arg); return 0; }#endif /* CONFIG_BLUETOOTH_SUPPORT_BCSP */ default: return -ENOIOCTLCMD; } return 0;}static s32bt_ioctl(struct tty_struct *tty, struct file * file, u32 cmd, unsigned long arg){ s32 tmp;// printk(__FUNCTION__ ": [%s:%x] lock !\n", current->comm, cmd); down(&ioctl_sem);// printk(__FUNCTION__ ": [%s:%x] running...\n", current->comm, cmd); tmp = __bt_ioctl(tty, file, cmd, arg); up(&ioctl_sem); return tmp;}static voidbt_throttle(struct tty_struct * tty){ BT_DRIVER(__FUNCTION__ ": Nothing done\n");}static voidbt_unthrottle(struct tty_struct * tty){ BT_DRIVER(__FUNCTION__ ": Nothing done\n");}static voidbt_set_termios(struct tty_struct *tty, struct termios *old_termios){ BT_DRIVER(__FUNCTION__ ": Forwarding to serial driver\n"); /* modify serial tty not bt tty */ if (sertty != NULL) sertty->driver.set_termios(sertty, old_termios); else D_ERR(__FUNCTION__ ": No sertty set!!\n");}static void bt_start(struct tty_struct *tty){ BT_DRIVER(__FUNCTION__ ": Nothing done\n");}static voidbt_stop(struct tty_struct *tty){ BT_DRIVER(__FUNCTION__ ": Nothing done\n");}voidbt_hangup(struct tty_struct *tty){ BT_DRIVER(__FUNCTION__ ": Line %d (nothing done) pid %d (%s)\n", GET_TTYLINE(tty), current->pid, current->comm);}/********************************************//* STACK BOTTOM FUNCTIONS (LINE DISCIPLINE) *//********************************************//* * TTY callbacks */#ifdef __USE_OLD_SYMTAB__/*****************************************************************************//* LINUX 2.0.X SPECIFIC CODE *//*****************************************************************************/static s32 bt_tty_read(struct tty_struct *tty, struct file *file, __u8 * buf, u32 nr)#else/*****************************************************************************//* LINUX 2.2.X SPECIFIC CODE *//*****************************************************************************/static ssize_t bt_tty_read(struct tty_struct * tty, struct file * file, u8 * buf, size_t nr)#endif{ /* should not read data directly over serial tty */ BT_LDISC(__FUNCTION__ ": Disabled\n"); return 0;}#ifdef __USE_OLD_SYMTAB__/*****************************************************************************//* LINUX 2.0.X SPECIFIC CODE *//*****************************************************************************/static s32bt_tty_write(struct tty_struct *tty, struct file *file, const __u8 * data, u32 count)#else/*****************************************************************************//* LINUX 2.2.X SPECIFIC CODE *//*****************************************************************************/static ssize_tbt_tty_write(struct tty_struct * tty, struct file * file, const u8 * data, size_t count)#endif{ /* should simply discard data since ttySx only exists for internal use */ BT_LDISC(__FUNCTION__ ": (%d) done!\n", count); return tty->driver.write(tty, 1/*from user*/, data, count);}static s32bt_tty_ioctl(struct tty_struct *tty, struct file * file, u32 cmd, unsigned long arg){ switch (cmd) { default: /* forward rest to n_tty line discipline, it takes care of termios settings etc, the rest goes to the tty driver (serial driver) */ BT_LDISC(__FUNCTION__ ": Forwarding ioctl 0x%x to n_tty line disc\n", cmd); return n_tty_ioctl(tty, file, cmd, arg); } return -ENOIOCTLCMD;}#ifdef __USE_OLD_SYMTAB__/*****************************************************************************//* LINUX 2.0.X SPECIFIC CODE *//*****************************************************************************/static s32bt_tty_select(struct tty_struct *tty, struct inode *inode, struct file *filp, s32 sel_type, select_table * wait){ BT_LDISC(__FUNCTION__ ": Nothing done!\n"); return 0;}#else/*****************************************************************************//* LINUX 2.2.X SPECIFIC CODE *//*****************************************************************************/static u32 bt_tty_poll(struct tty_struct *tty, struct file *file, struct poll_table_struct *wait){ BT_LDISC(__FUNCTION__ ": Nothing done!\n"); return 0;}#endifstatic s32bt_tty_open(struct tty_struct *tty){ BT_LDISC(__FUNCTION__ "\n"); DSYS("Setting BT driver to use serial tty\n"); sertty = tty; return 0;}static voidbt_tty_close(struct tty_struct *tty){ struct tty_struct *upper_tty; s32 line = 0; /* Now hangup all active upper tty:s */ while (line < BT_NBR_DATAPORTS) { if ((SESSIONSTATE(line) == BT_ACTIVE) || (SESSIONSTATE(line) == BT_UPPERCONNECTED)) { BT_LDISC("Hanging up line %d\n", line); upper_tty = GET_UPPERTTY(line); if (upper_tty) tty_hangup(upper_tty); } line++; } sertty = NULL;}/* * Callback function from tty driver. Return the amount of space left * in the receiver's buffer to decide if remote transmitter is to be * throttled. */static s32bt_tty_room(struct tty_struct *tty){ BT_LDISC(__FUNCTION__ ": Return 65536!\n"); return 65536; /* We can handle an infinite amount of data. :-) */}/* * This function is called by the tty driver when the transmit buffer has * additional space. */static voidbt_tty_wakeup(struct tty_struct *tty){ printk(__FUNCTION__ ": Nothing done\n");}void bt_reset_phys_hw(void){#ifdef __CRIS__#ifdef CONFIG_BLUETOOTH_CSR int do_reset = 1;#else int do_reset = 0;#endif#if defined(CONFIG_BLUETOOTH_RESET_PA7) BT_DRIVER(__FUNCTION__ ": Resetting Bluetooth hardware using pin PA7 (Active %s)\n", (do_reset ? "High" : "Low")); REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, 7, do_reset); udelay(1000); REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, 7, !do_reset);#elif defined(CONFIG_BLUETOOTH_RESET_PB5) BT_DRIVER(__FUNCTION__ ": Resetting Bluetooth hardware using pin PB5 (Active %s)\n", (do_reset ? "High" : "Low")); REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, 5, do_reset); udelay(1000); REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, 5, !do_reset);#elif defined(CONFIG_BLUETOOTH_RESET_G10) BT_DRIVER(__FUNCTION__ ": Resetting Bluetooth hardware using pin G10 (Active %s)\n", (do_reset ? "High" : "Low")); REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow, 10, do_reset); udelay(1000); REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow, 10, !do_reset);#elif defined(CONFIG_BLUETOOTH_RESET_G11) BT_DRIVER(__FUNCTION__ ": Resetting Bluetooth hardware using pin G11 (Active %s)\n", (do_reset ? "High" : "Low")); REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow, 11, do_reset); udelay(1000); REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow, 11, !do_reset);#else D_ERR(__FUNCTION__ ": Resetting Bluetooth hardware: No reset pin defined\n");#endif#else BT_DRIVER(__FUNCTION__ ": Do not know how to reset the Bluetooth hardware!\n");#endif /* __CRIS__ */}/************************//* glue layer functions *//************************//* * HCI calls this function to write to lower layer driver */s32bt_write_lower_driver(u8 *data, s32 len)#ifdef CONFIG_BLUETOOTH_SUPPORT_BCSP{ if (bt_use_bcsp(-1)) return bcsp_write_top(data, len); else return bt_write_lower_driver_real(data, len);}s32bt_write_lower_driver_real(u8 *data, s32 len)#endif{ if (len < 0) { /* (!) */ D_ERR(__FUNCTION__ ": Can't write negative length...\n"); return 0; } /* get lower layer tty and call its write function directly without using its registered line discipline */ BT_DATA("<--|X| %3d\n", len); if (sertty) { s32 tmp; s32 sent; if ((tmp = sertty->driver.write_room(sertty)) < len) { printk(__FUNCTION__ ": ser tx buffers can't send all, wait (%d/%d)\n", tmp, len); return 0; } else { bt_flash_led(); BT_DATADUMP("<--|X|", (u8*)data, len); sent = sertty->driver.write(sertty, 0, data, len); } if (sent != len) { printk(__FUNCTION__ ": Only sent %d of total %d\n", sent, len); /* fixme -- discard packet and add tx error in stat */ } len -= sent; return sent; } else { D_ERR(__FUNCTION__ ": No sertty is set\n"); } return 0;}/* * Callback function when data is available at the tty driver. * Context: timer task or (less likely) hard interrupt. */ static voidbt_receive_lower_stack(struct tty_struct *tty, const __u8 *data, char *flags, s32 count){ BT_DATA("-->|X| %3d\n", count); BT_DATADUMP("-->|X|", (u8*)data, count); bt_flash_led();#ifdef CONFIG_BLUETOOTH_USE_INBUFFER /* store in bt inbuffer and schedule a hci receive task if none is started */ bt_handle_indata(data, count);#else /* process data right away */ bt_receive_data((u8*)data, count);#endif /* CONFIG_BLUETOOTH_USE_INBUFFER */}/* * Upper tty writes to top of stack (BT drivers write()) */static s32bt_write_top(struct tty_struct * tty, s32 from_user, const u8 *buf, s32 count){ s32 line = GET_TTYLINE(tty); s32 bytes_sent; u32 rfcomm_conid; struct bt_session *bt; BT_DATA(" |X|<-- %3d [%d]\n", count, line); BT_DATADUMP("|X|<--", (u8*)buf, count); bt = (bt_session *)tty->driver_data; if ((bt->rfcomm != NULL) && (bt->rfcomm->magic != RFCOMM_MAGIC)) { D_ERR(__FUNCTION__ ": rfcomm magic failed (0x%x != 0x%x)\n", bt->rfcomm->magic, RFCOMM_MAGIC); return 0; } if (SESSIONSTATE(line) != BT_ACTIVE) { D_WARN(__FUNCTION__ ": Line %d is not in active state\n", line); return 0; } rfcomm_conid = CREATE_RFCOMM_ID(line, bt->dlci); if (from_user) { /* Our tmp_bt_buf is only one page, but nothing prevents the * caller from giving us more than that to send. Make sure we * don't try to write beyond the end of tmp_bt_buf. */ count = MIN(count, PAGE_SIZE); copy_from_user(tmp_bt_buf, buf, count); bytes_sent = rfcomm_send_data(rfcomm_conid, tmp_bt_buf, count); } else { bytes_sent = rfcomm_send_data(rfcomm_conid, (u8*)buf, count); } bt_stat.bytes_sent += bytes_sent; return bytes_sent;}/* * RFCOMM calls this function to write to higher layer * "application" e.g ttyBT */s32bt_receive_top(u32 con_id, u8 *data, s32 len) { struct tty_struct *upper_tty; u32 line; line = GET_LINE(con_id); /* get upper tty and call its ldisc->receive_buf */ BT_DATA(" |X|--> %3d [%d]\n", len, line); BT_DATADUMP("|X|-->", data, len); if (SESSIONSTATE(line) != BT_ACTIVE) { /* change debug macro... */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -