Taking hci_ldisc.c as an example, we will sort out the line procedure registration process in the kernel. Our n_hci registration process is as follows: Bluetooth/hci_ldisc.c module_init (hci_uart_init) // callback a series of callback Drivers/tty/commandid (INT disc, struct tty_ldisc_ops * new_ldisc) tty_ldiscs [Disc] = new_ldisc; // operation of the line procedure, save to Global Array
New_ldisc-> num = disc;
New_ldisc-> refcount = 0; in this way, you can set this procedure by calling the ioctl tiosetd command. Take hciattach as an example: the startup of the hciattach process takes A20 4.1 RealTek as an example: init. sun6i. RC: #3. realTek rtl8723as BT hciattach
Service hciattach/system/bin/logwrapper/system/bin/hciattach-n-s 115200/dev/ttys1 rtk_h5 1500000
User Root
Group Bluetooth net_bt_admin
Disabled
The oneshothciattach code is located at: external/Bluetooth/bluez/tools/hciattach. cexternal/Bluetooth/bluez/tools/hciattach_rtk.chciattach.c main. First, parse the parameter, which determines the UART interface. {"Rtk_h5", 0x0000, 0x0000, hci_uart_3wire, 115200,150 0000, flow_ctl, 0, null, realtek_init, realtek_post}, n = init_uart (Dev, U, send_break, raw); // initialize UART Dev =/dev/ttys1 U. Set this parameter to rtk_h5, int FD = open (Dev, o_rdwr | o_noctty ); // open the serial port U-> Init (FD, U, & Ti); // call the callback initialization function rtk_init_h5 (FD, Ti ); // prepare for firmware download rtk_config (FD, proto, speed, Ti); // download the Bluetooth firmware set_speed (FD, & Ti, U-> init_speed ); // set the initial baud rate 1 15200 int I = n_hci; IOCTL (FD, tiocsetd, & I); // set tty to n_hci line procedure IOCTL (FD, hciuartsetproto, U-> PROTO ); // set it to hci_uart_3wire U-> post (FD, U, & Ti); // call the callback function post, // set the processing capacity of the high-speed mode kernel for tiosetd in drivers/tty/tty_io.c to process tiosetdlong tty_ioctl (struct file * file, unsigned int cmd, unsigned long Arg) // tty IOCTL callback handler function return tiocsetd (TTY, P); // set the line procedure return tty_set_ldisc (TTY, ldisc); // tty = n_hcidrivers/tty/tty_ldisc. CINT struct (struct tty_struct * tty, int ldisc) struct tty_ldisc * new_ldisc = tty_ldisc_get (ldisc); // converts n_hci to the data structure of tty_ldisc, including ops callback, in fact, it uses n_hci as the index to retrieve the corresponding item in a tty_ldisc array, which is the hci_uart_ldisc. As mentioned above, it uses int tty_register_ldisc (INT disc, struct tty_ldisc_ops * new_ldisc) registration. Work = tty_ldisc_halt (TTY); // terminate the original line rule tty_ldisc_assign (TTY, new_ldisc); disconnect (TTY, ldisc); // set the new line rule tty_ldisc_open (TTY, new_ldisc); // call the open callback of hci_uart_ldisc to perform initialization such as clearing the buffer. tty-> OPS-> set_ldisc (TTY ); // call hci_uart_ldisc to set it to tty_struct to handle hciuartsetproto. Now, the serial port device has used a new line procedure, which will process the hciuartsetproto command, however, in/Drivers/tty/tty_io.c, if the CMD cannot be processed, call IOCTL in ops of the corresponding line procedure to handle the problem: Long tty_ioctl (struct File * file, unsigned int cmd, unsigned long Arg) LD-> OPS-> IOCTL (TTY, file, CMD, ARG ); // call hci_ldisc.chci_uart_tty_ioctl hci_uart_proto (Hu, ARG); // Arg = hci_uart_3wire wire CT hci_uart_proto * P = require (ID) in hci_uart_ldisc; // obtain HCI protocol, it contains a series of open and other callbacks. In fact, here, an item in the hci_uart_proto array is obtained based on the ID as the index. These items are registered and filled by hci_uart_register_proto. P-> open (HU); // call the corresponding open interface and save the corresponding proto callback to the hci_uart structure hci_uart_register_dev (HU ); // register the HCI device struct hci_dev * hdev; construct an hci_dev structure and fill in the hci_uart-related callback. Hci_register_dev (hdev); // register the device // first traverse all current HCI devices. These devices are saved to a Global Array hci_dev_list, get the suffix ID sprintf (hdev-> name, "HCI % d", ID) of the HCI device; // Save the name hci_register_sysfs (hdev); // in the SYS file system, register a device node. Hdev-> rfkill = rfkill_alloc (hdev-> name, & hdev-> Dev,
Rfkill_type_bluetooth, & hci_rfkill_ops, hdev );
Rfkill_register (hdev-> rfkill); // register the rfkill Node
So far, hci0 has been registered, and bluez on the android layer can be accessed through af_bluetooth to obtain HCI information.