How to enable Data Length Extension (DLE) in Bluetooth Low Energy (BLE) - embedded-linux

I am working on embedded linux platform and I want to increase data length in BLE communication but I can't find an api function to change data packet length. The module used is SparkLAN AP6256. Is there any configuration parameter to enable DLE (Data Length Extension).
Currently I am using gattool to connect to the device (configured as ble device) and the data length is set to 23 bytes by default. Also tried using btgatt-server and btgatt-client but didn't see any option to enable DLE.

Related

What happens when we press a key on Windows?

First of all, I would say to you that I write this question from nothing because I have attempt to find good documentation but nothing stand out...
What happens when we squeeze a key?
I think this is complex but I hope you can help me.
What I search to know : all (but especially the program start on the host machine and how the key electric signal is encoded and send...)
The eXtensible Host Controller (xHC) has a Periodic Transfer Ring. Windows programs this ring to trigger a transfer every time an interval in milliseconds has passed. The right interval is specified in the USB descriptor returned by the USB device. When the transfer occurs, the xHC puts a Transfer Event TRB on the event ring and triggers an MSI-X interrupt which bypasses the IOAPIC as some kind of inter-processor interrupt. If Windows detects some change in the keys pressed, it will send a message to the application which currently has focus (calling the window's procedure) with the key pressed in one of the argument.
I don't know about electrical signals but I know the eXtensible Host Controller is the USB controller responsible to interact with USB on modern Windows systems. Since Windows nowadays requires an x64 processor, the xHC must be present on your motherboard. The xHC is a PCI-Express device which is compliant with the PCI-Express specification.
To find an xHC, you:
Find the RSDP ACPI table in RAM;
This table will be found by the UEFI firmware which acts as some kind of small operating-system (OS) during boot of the computer. Then, the OS developers will write a small UEFI application named bootx64.efi that they will place on a FAT32 partition on the hard-disk. They will place this app in the /boot/efi directory. The UEFI firmware will directly launch that application on boot of the computer which allows to have an OS which doesn't require user input to be launched (similarly to how it used to work with the legacy BIOS fetching the first sector of the hard-disk and executing the instructions found there).
The UEFI application is compiled in practice with either EDK2 or gnu-efi. These compilers are aware of the UEFI environment and specification. They thus compile the code to system calls that are present during boot and available for the UEFI application written by the OS developers. The System Tables (often the ACPI tables) are given as an argument to the "main" function (often called UefiMain) called by the UEFI firmware in the UEFI application. The code of the application can thus simply use these arguments to find the RSDP table and pass it to the OS.
Find the MCFG ACPI table using the RSDP;
The chain of table is RSDP -> XSDT -> MCFG. Once the OS found the MCFG, this table specifies the base address of the PCI configuration space. To interact with PCI devices you use memory mapped IO (MMIO). You write to some position in RAM and it will instead write to the registers of the PCI devices. The MCFG thus specifies the base address at which you will start finding MMIO registers for the different PCI devices that are plugged into the computer.
Iterate on the PCI devices and look at their IDs until you find an xHC.
To iterate on the PCI devices, the PCI convention specifies a formula which is the following:
UINT64 physical_address = base_address + ((bus - first_bus) << 20 | device << 15 | function << 12);
The base_address is for a specific segment group. Each segment group can have 256 buses (suitable for large servers or large computers with lots of components). There can be up to 65536 segment groups and each can have up to 256 PCI buses. Each PCI bus can have up to 32 devices plugged onto it and each device can have up to 8 functions. Each function can also be a PCI bridge. This is quite straightforward to understand because the terminology is clear. The bus here is an actual serial bus that the PCI devices (like a network card, a graphics card, an xHC, an AHCI, etc.) use to communicate with RAM. The function is a functionality of the PCI device like controlling USB devices, hard-disks, HDMI screens (for graphics cards), etc. The PCI bridge bridges a PCI bus to another PCI bus. It means you can have almost an infinite amount of devices with the PCI specification because the bridges allow to extend the tree of devices by adding other PCI host controllers.
Meanwhile, the bus is simply a number between 0 and 255. The first bus is specified in the MCFG ACPI table for a specific segment group. The device is a number between 0 and 31 and the function is a number between 0 and 7. This formula returns a physical address which points to a conventional configuration space (it is the same for all functions) which has specific registers. These registers are used to determine what is the type of device and to load a proper driver for it. Each function of each device thus gets a configuration space.
For the xHC, there will be only one function and the IDs returned by its configuration space will be 0x0C for the class ID and 0x03 for the subclass ID (https://wiki.osdev.org/EXtensible_Host_Controller_Interface).
Once you found an xHC, it gets rather complex. You need to initialize it and get the USB devices which are plugged in the computer at the current moment. You need to take several steps to get the xHC operational. For this part, I'll leave you to read the xHCI specification which (on chapter 4) specifies exactly the steps which need to be taken (https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf).
For the keyboard portion I'll leave you to read one of my answer on the stackexchange for computer science: https://cs.stackexchange.com/questions/141870/when-are-a-controllers-registers-loaded-and-ready-to-inform-an-i-o-operation/141918#141918.
Some good links:
https://wiki.osdev.org/Universal_Serial_Bus
https://wiki.osdev.org/PCI

Client USB device driver query

How does an OS maps USB device with its device driver? I understand that in the interface descriptor of client USB firmware if no class type has been selected for the device then developer has to provide its own device driver.
I am keen to know how OS maps the pluggged USB device with its device driver? Does descriptors in the USB client firmware contains the file name of the custom device driver? Please let me know.
As a hobby, I have done quite a bit of work with the USB hardware, and had these same questions when I first started.
An OS can map a USB device any way it wants. However, to be more precise toward your question, a USB device will, and must return a class and interface code. Granted, that class code can be 0xFF for user-defined, where the device now must require a unique driver.
In my opinion, this is where the USB shines. All USB devices that return a valid class code specified within the USB specification, will and must follow a specific sequence of events and will "work right out of the box" as indicated. However, this doesn't mean that it cannot have extra capabilities.
For example. A pointing device, such as a mouse, will probably always follow the boot protocol when first plugged in. This is the protocol used and specified in the USB specification so that any OS that follows this protocol can use this pointing device. This protocol specifies a simple three (or more) byte packet for pointer input.
Byte Description
0 Button(s)
1 X Displacement
2 Y Displacement
3 (Device Specific) (optional)
Any pointing device that follows the USB specification most likely has this protocol and will use this protocol until told otherwise. This is so any USB capable OS can use the pointing device.
Every USB device also has a vendor, device, and protocol definition. Once the OS has found this device, it can search through its drivers for a driver that can support this device. That driver, once loaded, can then tell the device to now use a different protocol. i.e.: Return a different Input Report.
Here is an example. Let's say that you have a fancy gaming mouse with three directions of displacement (X, Y and Z), and six buttons. As the OS is booting, it probably has no idea how to use that mouse. Therefore, the manufacturer creates the mouse to use the boot protocol shown above until the driver can be loaded. Once the driver is loaded, which knows how to use the three direction displacements and all six buttons, it can tell the mouse, through a Control packet, maybe the SET INTERFACE command as well, to now start sending a different report, now using the full capabilities of the mouse.
So, as along as the device is USB specification accurate, and has a class code not of user defined (0xFF), the device will be recognized, even if it is a minimal use and/or is to show a statement that a driver is needed.
As for giving a file name of a custom device driver, this is all up to the device manufacturer. However, usually this is not that case. Usually, the OS will retrieve the DEVICE DESCRIPTOR which contains the manufacturer, device, protocol, and other fields. It will then match any driver to those fields. If it does not find a compatible driver, it will ask for one.
For example, one of the pointing devices I used with my research has the following few bytes of the 18-byte Device Descriptor:
Offset Field Value
0 Length 0x12
1 Type 0x01
2 Release Num 0x0110
4 Device Class 0x00
5 Sub Class 0x00
6 Protocol 0x00
7 MaxPacketSz 0x08
8 VendorID 0x04FC
10 Product ID 0x0003
...
Notice that it specifies the Vendor and the Product. Using these two values, a compatible driver can be found.
Now, notice that the class code is zero. This is not an error and is a perfectly valid class code, and simply means that the interface descriptor is to be used instead.
So, hopefully with this information, and specifically, the Manufacturer and Product codes within the DEVICE DESCRIPTOR, you can now see how an OS can find the correct driver for any device.

M600/A3 uart problems

I'm eventually trying to use transparent data transmission to pass messages between the mobile SDK and an onboard device using the A3 API/UART port.
Right now I used DJI assistant to output a timestamp to the API port at 1hz. When I connect a TTL>USB device, I see garbage data coming through. When I connect an oscilloscope with a protocol analyzer, I see one frame every second, but the frame is variable size. The ASCII representation of what does come through is nonsense.
I have double checked that baud is set correctly (and have tried other baud rates). I've made sure the grounding is proper. I've tried probing the pin on the actual A3 port (to remove possibility of EMI on the serial cable). It seems like I'm getting garbage data on the serial line, or I don't know how to decode it properly.
Hi,maybe you can refer to the open-protocol of M100 Link.I think it's difficult to decode the protocol of N3,unless DJI publishes that。

Programmatically determine NUMA node or PCI bus, device, function number of Direct3D9Ex device

I'm looking for a way to programmatically determine which NUMA node a particular Direct3D9Ex display adapter is connected to so that I can allocate memory for host to device transfers on that node.
I can use IDirect3D9Ex::GetAdapterIdentifier() to obtain a DeviceName of the form "\.\DISPLAY1".
I can use EnumDisplayDevices() to enumerate the display devices and match this DeviceName to a DeviceKey of the form "\Registry\Machine\System\CurrentControlSet\Control\Video{62E184AC-2614-4AA8-844C-47454B92C142}\0000".
I can use SetupDiEnumDeviceInfo() to enumerate devices and SetupDiGetDeviceProperty() to query properties including DEVPKEY_NAME (e.g. "NVIDIA GeForce GTX TITAN X"), DEVPKEY_Device_LocationInfo (e.g. "PCI bus 2, device 0, function 0") and DEVPKEY_Device_Numa_Node (e.g. 0) but I can't find anything to link one of these devices to either the DeviceName or DeviceKey in EnumDisplayDevices().
I can do equivalent thing is CUDA because cudaDeviceGetPCIBusId() provides the PCI bus, device and function information but I also need to do it in Direct3D9Ex (when CUDA is unavailable).
The other thing I've noticed is that in the registry under "HKLM\SYSTEM\CurrentControlSet\Enum\PCI\VEN_10DE&DEV_17C2&SUBSYS_113210DE&REV_A1" there is a key for each of my display devices and each one contains another key called "Device Parameters" with a value called "VideoID" of the form "{62E184AC-2614-4AA8-844C-47454B92C142}". Unfortunately applications are not supposed to read this part of the registry directly and I don't know how to obtain the same information through the SETUPAPI.

Difference between uart_register_driver and platform_driver_register?

I am studying UART Driver in kernel code and want to know, who first comes into picture, device_register() or driver_register() call?
For difference between them follow this.
and in UART probing, we call
uart_register_driver(struct uart_driver *drv)
and after successfully registration,
uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
Please explain this in details.
That's actually two questions, but I'll try to address both of them.
who first comes into picture, device_register() or driver_register() call?
As it stated in Documentation/driver-model/binding.txt, it doesn't matter in which particular order you call device_register() and driver_register().
device_register() adds device to device list and iterates over driver list to find the match
driver_register() adds driver to driver list and iterates over device list to find the match
Once match is found, matched device and driver are binded and corresponding probe function is called in driver code.
If you are still curious which one is called first (because it doesn't matter) -- usually it's device_register(), because devices are usually being registered on initcalls from core_initcall to arch_initcall, and drivers are usually being registered on device_initcall, which executed later.
See also:
[1] From where platform device gets it name
[2] Who calls the probe() of driver
[3] module_init() vs. core_initcall() vs. early_initcall()
Difference between uart_register_driver and platform_driver_register?
As you noticed there are 2 drivers (platform driver and UART driver) for one device. But don't let this confuse you: those are just two driver APIs used in one (in fact) driver. The explanation is simple: UART driver API just lacks some functionality we need, and this functionality is implemented in platform driver API. Here is responsibility of each API in regular tty driver:
platform driver API is used for 3 things:
Matching device (described in device tree file) with driver; this way probe function will be executed for us by platform driver framework
Obtaining device information (reading from device tree)
Handling Power Management (PM) operations (suspend/resume)
UART driver API: handling actual UART functionality: read, write, etc.
Let's use drivers/tty/serial/omap-serial.c for driver reference and arch/arm/boot/dts/omap5.dtsi for device reference. Let's say, for example, we have next device described in device tree:
uart1: serial#4806a000 {
compatible = "ti,omap4-uart";
reg = <0x4806a000 0x100>;
interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart1";
clock-frequency = <48000000>;
};
It will be matched with platform driver in omap-serial.c by "ti,omap4-uart" string (you can find it in driver code). Then, using that platform driver, we can read properties from device tree node above, and use them for some platform stuff (setting up clocks, handling UART interrupt, etc.).
But in order to expose our device as standard TTY device we need to use UART framework (all those uart_* functions). Hence 2 different APIs: platform driver and UART driver.

Resources