Hi I am going through hci_send_req implementation in hci.c file. in this function after sending hci command to controller . Controller send event packet. After reading event packet in buffer by read(dd, buf, sizeof(buf)) (dd is hci socket descriptor) , now we need event packet header and to get event packet header, buf is sifted by 1 byte. why??
hdr = (void *) (buf + 1); (line number 1049 of hci.c)
Please let me know about this. Thanks.
HCI Event Packets: the Host Controller notifies the HCI Driver of events:
Packet indicator (for UART interfaces) of 4.
Event code (8 bits): identifies the event.
Parameter length (8-bit): total length of all parameters in bytes.
Event parameters: the number of parameters and their length is event specific.
So first octet is for Packet indicator that is 0x04 for event packet.
for command packet - 0x01 (for UART interface)
for ACL data packet - 0x02 (for UART interface)
for SCO data packet - 0x03 (for UART interface)
Related
In prior kernels and releases of Ubuntu, it was possible to use the hci socket interface to send an arbitrary set of 31 bytes as an advertising beacon, but in ubuntu 20.04 the hci bluetooth tools were deprecated, as were some elements of the socket API they were using.
The goal is to have some N number of devices broadcast 31 bytes of sensor data to each other at a rate of 5 Hz, and have all N read the packets from the other devices.
With the hci socket API being deprecated, the replacements are the DBus BlueZ API and the Management BlueZ API. The DBus API is limited and seems to only allow a max of 25 bytes. The Management API seems more capable, and it seems to work on Ubuntu 18.04/4.15 kernel (though even there the scan seemed to only pick up the advertisements sporadically when switching between scan and advertise every 100ms while with the hci api it was rock solid), but on Ubuntu 20.04/5.4 kernel, various issues crop up.
Using the hci socket API seems like it could still be possible, but even running something like hcitool lescan results in btmon saying Command Disallowed. I believe this might be due to LE Extended Advertising being enabled, but I have not figured out how to disable it yet.
Using the DBus API (or bluetoothctl) is still limited and doesn't allow the full use of the 31 bytes (or even 30 bytes + length)
Using the Management API leads to a Advertising Timeout shortly after setting the advertising data, which I think might be from LE Extended Advertising being enabled. This problem persists even if I explicitly set the timeout in the packet.
For example, running
btmgmt add-adv -c -d 1E000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D 1
to send an advertising packet at a fixed MAC with the advertising data being length:31 payload: 0-30 results in a btmon output of:
< HCI Command:... (0x08|0x0036) plen 25 #631 [hci0] 5676.358401
Handle: 0x01
Properties: 0x0013
Connectable
Scannable
Use legacy advertising PDUs: ADV_IND
Min advertising interval: 1280.000 msec (0x0800)
Max advertising interval: 1280.000 msec (0x0800)
Channel map: 37, 38, 39 (0x07)
Own address type: Public (0x00)
Peer address type: Public (0x00)
Peer address: 00:00:00:00:00:00 (OUI 00-00-00)
Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00)
TX power: 127 dbm (0x7f)
Primary PHY: LE 1M (0x01)
Secondary max skip: 0x00
Secondary PHY: LE 1M (0x01)
SID: 0x00
Scan request notifications: Disabled (0x00)
> HCI Event: Command Co.. (0x0e) plen 5 #632 [hci0] 5676.359321
LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1
Status: Success (0x00)
TX power (selected): 7 dbm (0x07)
< HCI Command: L.. (0x08|0x0039) plen 6 #633 [hci0] 5676.359410
Extended advertising: Enabled (0x01)
Number of sets: 1 (0x01)
Entry 0
Handle: 0x01
Duration: 2000 ms (0xc8)
Max ext adv events: 0
> HCI Event: Command Co.. (0x0e) plen 4 #634 [hci0] 5676.361330
LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2
Status: Success (0x00)
# MGMT Event: Com.. (0x0001) plen 4 {0x0003} [hci0] 5676.361372
Add Advertising (0x003e) plen 1
Status: Success (0x00)
Instance: 1
> HCI Event: LE Meta Ev.. (0x3e) plen 6 #635 [hci0] 5676.362333
LE Advertising Set Terminated (0x12)
Status: Advertising Timeout (0x3c)
Handle: 1
Connection handle: 65535
Number of completed extended advertising events: 0
Is there a good way to recreate the functionality that was available using the hci socket, or a way to disable extended advertising so that the hci socket works again?
This image from Jos Ryke might help explain what is going on. Of those 31 bytes, 3 were always used for setting the advertising flags.
Looking at the source code for btmgmt those flags are now set with the -g, and -l command line switches. Use general discoverable mode to advertise indefinitely.
static void add_adv_usage(void)
{
bt_shell_usage();
print("Options:\n"
"\t -u, --uuid <uuid> Service UUID\n"
"\t -d, --adv-data <data> Advertising Data bytes\n"
"\t -s, --scan-rsp <data> Scan Response Data bytes\n"
"\t -t, --timeout <timeout> Timeout in seconds\n"
"\t -D, --duration <duration> Duration in seconds\n"
"\t -P, --phy <phy> Phy type, Specify 1M/2M/CODED\n"
"\t -c, --connectable \"connectable\" flag\n"
"\t -g, --general-discov \"general-discoverable\" flag\n"
"\t -l, --limited-discov \"limited-discoverable\" flag\n"
"\t -n, --scan-rsp-local-name \"local-name\" flag\n"
"\t -a, --scan-rsp-appearance \"appearance\" flag\n"
"\t -m, --managed-flags \"managed-flags\" flag\n"
"\t -p, --tx-power \"tx-power\" flag\n"
"e.g.:\n"
"\tadd-adv -u 180d -u 180f -d 080954657374204C45 1");
}
The other 28 bytes must start with a byte declaring the length and a byte declaring what data type the rest of the bytes in the declared length are describing.
It is those 28 bytes that is being set with the -d option of btmgmt.
If 28 bytes are not enough, then common workarounds people use is to split the data over multiple adverts or use scan response packet.
There is more detail on the Advertising Data Format in the Core Specification where it defines an Advertising Packet as:
A packet containing an advertising PDU. See [Vol 6]
Part B, Section 2.3.1
More data is section:
BLUETOOTH CORE SPECIFICATION Version 5.2 | Vol 3, Part C | 11 ADVERTISING AND SCAN RESPONSE DATA FORMAT
It has an example for ADV_NONCONN_IND packet type:
PDU Type: 2
ChSel: RFU
TxAdd: 1 (random)
RxAdd: RFU
AdvA: 0xC1A2A3A4A5A6 (a static device address)
AdvData: (3 octets) 0x01 0x02 0x03
Which starts with the flags data type.
For a project I am using an LPC824 MCU from NXP and I want to read out data from the accelerometer over I2C. This accelerometer is the MMA8453Q. Looking into the datasheet of the accelerometer I see the following:
From my understanding this means that you give a start signal, you write the device address and put write behind it, you get an acknowledgement and so on.
The address I have to write is the following:
the register I chose for now was 0x0D which is the "Who am I" register, this should always be read as 0x3A.
For people familiar with NXP examples I based myself on one of them. This is the code I have atm:
*txData = 0x0D;
SetupXferRecAndExecute(0x1C, txData, 1, rxData, 0);
SetupXferRecAndExecute(0x1C, txData, 0, rxData, 1);
and this is what it looks like on the scope
So as i can see I send the Device adress twice, first I write the register address and than i want to read it, but it gives 0x00 back.
Can someone pls help me? Thanks in advance!
My answer is based on those data sheets:
MMA8453Q: https://www.nxp.com/docs/en/data-sheet/MMA8453Q.pdf
LPC82X: https://www.nxp.com/docs/en/data-sheet/LPC82X.pdf
LPC82X is the Master and MMA8453Q is the Slave.
Depending on if you set the pin 7 of the slave to high (SA0 = 1) or low (SA0 = 0) your 7-bit salve address is either 0x1D or 0x1C. Together with the read (1) or write (0) bit the final 8-bit address is as written in the table you have posted in your comment.
For the further example, let's assume SA0 is set to low, means the full 8-bit slave address is 0x3B for reads and 0x3A for writes.
Let's assume you want to read out the single-byte register 0x17, which is the freefall/motion event source register.
Now, the message sequence (that you also showed in your post) is as follows:
Master sends: Start Signal
Master sends: Slave Address + Write-Bit (in our case 0x3A)
Slave sends: ACK (done by hardware)
Master sends: 0x17 (as we assumed you are interested in the content of that
register)
Slave sends: ACK (done by hardware)
Master sends: repeated Start Signal
Master sends: Slave Address + Read-Bit (in our case 0x3B)
Slave sends: ACK (done by hardware)
Slave sends: content of register 0x17
Master sends: NACK
Master sends: Stop Signal
If you want to read out registers like of the MMA8453Q (such as OUT_X_MSB/LSB) which contain two bytes your sequence would be the following:
Master sends: Start Signal
Master sends: Slave Address + Write-Bit (in our case 0x3A)
Slave sends: ACK (done by hardware)
Master sends: 0x01 (as we assumed you are interested in the content of that register)
Slave sends: ACK (done by hardware)
Master sends: repeated Start Signal
Master sends: Slave Address + Read-Bit (in our case 0x3B)
Slave sends: ACK (done by hardware)
Slave sends: MSB of register 0x01
Master sends: ACK
Slave sends: LSB of register 0x01
Master sends: NACK
Slave sends: Stop Signal
It is important for the Master to know in advance how many bytes will be received when requesting the data from a particular register of the slave. Only with that knowledge, the master can send the proper amount of ACK before sending the last NACK followed by the Stop Signal.
I wanna make application in Android Studio for reading data from RGB sensor ISL29125 through NFC tag type 5 (ISO 15693). NFC tag is connected to sensor using I2C bus. I’m using address command for peripheral transaction according to datasheet of the NFC tag. My code for address mode peripheral transaction is following:
byte[] command = new byte[]{
(byte)0x20, //Request flags (Address mode ON)
(byte)0xA2, //PERIPHERAL TRANSACTION command
(byte)0x2B, //Manufacter code byte
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, //UID
(byte)0x00, //Parameter byte = Stop bit disabled
(byte)0x03, //NI2CWR (Number of bytes to be written) = 3
(byte)0x88, //I2C slave address (write)
(byte)0x09, //I2C slaves' register address
(byte)0x89, //I2C slave address (read)
(byte)0x01, //NI2CRD (Number of bytes to be read) = 1
};
System.arraycopy(id,0,command,3,8); //Change of UID to id of the tag
textView.setText("This is command you sent: "+(getHex(command)));
byte[] userdata= nfcvTag.transceive(command);
userdata = Arrays.copyOfRange(userdata, 0, 32);
viewResult.setText(getHex(userdata));
How the peripheral transaction command should look like according to datasheet
After sending this, I receive 32 times 0x00 byte, despite sensor is charged and the light goes to the sensor (RGB sensor). Anyway, there isn't mentioned where the slave address should be placed in the command in the datasheet of NFC tag (I incerted it almost at the end - bytes 88 09 and 89, but I'm not sure if it is right). Tag is MAX66242 and sensor is ISL29125 (https://www.intersil.com/content/dam/Intersil/documents/isl2/isl29125.pdf).
Reading sequence from sensor
I wanna to read data from register 0x09 (Green LOW).
My question is, does anybody know where the problem can be? And why do I reveice just 0x00?
I think, the problem might be with inicialization. How could I do it, if I would like to try it?
Thank you for any advice.
I Don't know whether your question is still valid or just pending...
Have you try to send a stop bit?
That would be:
(byte)0x10, //Parameter byte = Stop bit enabled
instead of "(byte)0x00, //Parameter byte = Stop bit disabled"
That might help to terminate a I2c sequence...
I'm trying to write driver for rtl8139 for linux 2.6 from scratch. I've already written TX path, but I have some problems with RX.
I put RX into promiscous mode and receiving RX irqs. I set RBSTART into physical address of allocated memory by kmalloc.
I don't know how to find out how many received packets there are and how long they are.
I thought that ERBCR, CAPR, CBR registers tell it, but they are == 0.
Maybe I'm doing something wrong? How to find out anything about received packets?
I answer to my question myself.
The received packets are located starting at RBSTART. The first two bytes of rx-ed packet are status bytes, and the next 2 are length of the frame + 4 bytes of crc.
Maybye someone find this info helpful.
On receiving a packet, the data received from the line is stored in the receive FIFO. When Early Receive Threshold is met, the data is moved from FIFO to Recieve Buffer.
So, once you get an interrupt. You need to check the Interrupt Status Register for ROK. Then check the Early Rx status register which gives you the status of the packet received. If EROK is set, then check the Receive buffer status for ROK. Check for are any errors in the ISR and ERSR. Also check your Rx Configuration register for the threshold configuration for Rx FIFO, RX buf length.
Does anybody have experience with the UART and DMA on the 1769 lpcxpresso board without the baseboard? I can get it to transmit the FIFO buffer but I am not able to get it to acknowledge any received chars. If it matters I am using the MCB1700, DMA-UART example code. Is there any place where I can get code examples to get this to work?
I am using the MCB1700 example code which comes with the lpcxpresso code_red. This uses UART0 and UART1 thru a RS-232 cable and 2 DMA channels. but the RS232 connection to connect the 2 ports is on the baseboard but I don't have one. I am just using wires on a breadboard to hook up UART0 TX to UART1 RX and the UART1 TX to the UART0 RX. I am notified that I received the 16 byte FIFO buffer from UART1 but when UART0 transmits to UART1, I am not getting the flag set saying I received the characters on the other DMA channel. I am wondering if something is not being initialized correctly