Bluetooth Driver Analytics Linux

Source: Internet
Author: User

Bluetooth Driver Analysis

This driver analysis is the OK6410 Development Board comes with the kernel version is linux3.0.1, the supported WiFi and Bluetooth integrated chip is Marvell 's 8688 and 8787. According to the Development Board design, the chip and the host are Sdio the Protocol interface communicates, so the driver is also Sdio Way of writing.

The personal analysis-driven process begins with an inserted device-driven action.

Each time the device is plugged in and the driver is unplugged, the corresponding information is printed through the terminal to determineSDThe card slot must be a trigger interrupt by looking at the hardware schematic and data sheetSdmmcThe controller indicatesMMCthe interrupt numbers for each are Aboutand the $, back in the code. During the kernel boot process, it is called to theSmdk6410_machine_init () function to initialize the smdk6410This machine platform, in this function, will be called by theS3c_sdhci0_set_platdata () function to set the SDHCI0The platform data for this device is then registered in turnSmdk6410_devices each device in the global variable including S3C_DEVICE_HSMMC0 this platform device, the device is registered, but when the driver is sometimes registered? Find the driver in the code using the device name Mmc/host in the driver directoryunder the directorySDHCI-S3C.Cfile. Through the driver'sModule_initThe system is automatically run by theThe Sdhci_s3c_init () function, in this function, is a sdhci_s3c_driver platform-driven registration. The principle of the device driver registration by the platform knows that when the driver registers, it will match the device on the platform bus by the driver name, and before we have registered the device, we will match the device with the same name, and then the device-driven probe will be called.function, let's analyzeSdhci_s3c_driver's probefunction.

At the beginning of the function is the PLATFORM_GET_IRQ () and Platform_get_resource () two functions to obtain the interrupt resources and memory resources allocated in the device, and then create the allocated memory to the struct sdhci_s3c *sc; , the memory allocation of this structure is involved in how a classic nested structure in Linux is allocated to a contiguous memory space, and here is a brief introduction to the struct sdhci_s3c struct that is involved in allocating struct SDHCI_ Host and struct mmc_host struct, because they are nested relationships with pointers by looking at the members of the struct we can see that the last variable of the struct is unsigned long private[0] ____cacheline_ Aligned is precisely because this long array of length 0 records the address of the superstructure at memory allocation. A little off-topic, back to the drive, and then analyze the probe function and then the variables in the allocation structure is initialized sequentially, after the initialization of the Sdhci_add_ The host () function adds the structure of the host controller to SDHCI , and then parses the Sdhci_add_host () function. This function is very long to initialize the struct mmc_host struct, and then we can see the following code:

Tasklet_init (&host->card_tasklet,

Sdhci_tasklet_card, (unsigned long) host);

Tasklet_init (&host->finish_tasklet,

Sdhci_tasklet_finish, (unsigned long) host);

Two interrupts are initialized with the bottom half of the processing function, followed by the Code through REQUEST_IRQ () to interrupt the application and registration interrupt function SDHCI_IRQ (), to this we know each time we insert the device will trigger this interrupt and run the interrupt handler function, In the interrupt handler we see Tasklet_schedule (&host->card_tasklet), which passes the task to the bottom half of the Sdhci_tasklet_card function to handle, and finally through MMC_ in the bottom half of the function. Detect_change (Host->mmc, Msecs_to_jiffies (200)); call host->mmc->detect () after a function delay of up to a millisecond function is, but which function is the entity of the Detect function pointer? We think that the view code that was initialized when the MMC structure was applied for initialization was passed in the Mmc_alloc_host function.

Init_delayed_work (&host->detect, Mmc_rescan);

The statement initializes the deferred work. The interrupt bottom half is actually called the Mmc_rescan () function, and then we analyze the function, in which the struct is first obtained by passing in the pointer through the struct MMC_HOSTthe pointer, and then you'll judgeBus_opswhether the pointer is empty, because there was no previousBus_opsis assigned, so the program continues to run toMmc_rescan_try_freq() function, inMmc_rescan_try_freqfunction first through theMMCController toMMCpower on the device, send after power-onSd_send_if_cond severalCMD8command toSDSee if there is a response to judge isSD 2.0the card is still1.0card, and then we can see the following lines of code

if (!mmc_attach_sdio (host))

return 0;

if (!MMC_ATTACH_SD (host))

return 0;

if (!MMC_ATTACH_MMC (host))

return 0;

From the literal meaning of the function name we can see that the device that matches the insertion in turn isSdiothe memory card orSDthe card orSPIthe device. Our BluetoothWiFimodule is using theSdiothe interface is thereforeMmc_attach_sdioThe function should match to and return0value, but how exactly does that match us intoMmc_attach_sdiofunction. In theMmc_attach_sdiothe function will first sendCMD5command to the device by judging if there is a sign of response and response to determine whetherSdiodevice, if sentCMD5a response after the command can be judged asSdioThe device function continues to execute or it returns, and the function calls theMmc_attach_bus function to initialize Bus_opsPointer toMmc_sdio_ops the bus operation set. Then set and insert the voltage matching the device, then call the Mmc_sdio_init_card function to request the initialization of the struct cardstruct, and then callSdio_init_func function to initialize cardinside the structureThe SDIO_FUNC structure is our counterpart Sdiothe device. At the end of initialization we see that throughMmc_add_card (host->card); function will carddevice registered to the kernelMmc_bus_type on the bus, the Sdio_add_func function is then called to move the Functhe equipment is ourSdioDevice Registration toSdio_bus_type on the bus, so far from our device inserted into the card slot after the operation of the core is basically done, although we will be specific sdiodevice registered in the kernel but how to match our pre-driver? We know that inserting the device finally we are going toSdiodevice is registered toSdio_bus_type on the bus, we know that in the device registration will go on the bus to match the corresponding driver is through the bus match function is the Sdio_bus_match function, by analyzing the function we know that the bus matching principle is to determine the driver Sdio_device_ Sdio of ID structure bodyInterfaceID, the manufacturer of the equipmentIDand EquipmentIDwith the manufacturer of the insertion deviceID, EquipmentIDand theSdioInterfaceIDis equal to match the driver. But how to know the device's manufacturer information and equipment when the device is plugged inID, continue to return to the code to see how the callThe Sdio_init_func function calls the SDIO_READ_FUNC_CIS function inside the function to read the CIS of the device.registers to obtain information about the device and to match the driver.

All right, let's go back to Marvell 's bluetooth wifi one chip, drive files in the drive directory in Bluetooth file for BTMRVL_SDIO.C, the initialization function of the module is btmrvl_sdio_init_module The function is relatively short as follows

static int __init btmrvl_sdio_init_module (void)

{

if (Sdio_register_driver (&bt_mrvl_sdio)! = 0) {

Bt_err ("SDIO Driver registration Failed");

Return-enodev;

}

User_rmmod = 0;

return 0;

}

We look at the function of the red flag as follows:

int sdio_register_driver (struct sdio_driver *drv)

{

Drv->drv.name = drv->name;

Drv->drv.bus = &sdio_bus_type;

Return Driver_register (&DRV->DRV);

}

It is relatively simple to see the bus (red part) that we previously registered to insert the device so that the drivers and devices are registered on the Sdio_bus_type bus and are matched to each other through the device's information. Let's take a look at the driver definition device information where we look at the registered drive structure Bt_mrvl_sdio

static struct Sdio_driver Bt_mrvl_sdio = {

. Name = "Btmrvl_sdio",

. id_table = Btmrvl_sdio_ids,

. Probe = Btmrvl_sdio_probe,

. remove = Btmrvl_sdio_remove,

};

static const struct SDIO_DEVICE_ID btmrvl_sdio_ids[] = {

{Sdio_device (Sdio_vendor_id_marvell, 0x9105),

. Driver_data = (unsigned long) &btmrvl_sdio_sd6888},

{Sdio_device (Sdio_vendor_id_marvell, 0x911a),

. Driver_data = (unsigned long) &btmrvl_sdio_sd8787},

{ }

};

It is known that the device information is pre-defined in Btmrvl_sdio_ids.

Bluetooth Driver Analytics Linux

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.