How to send more than 8 byte message in a single frame using ELM327 device in KWP2000 protocol - can-bus

I tried sending a Higher payload data frame (containing more than 8 bytes) in KWP2000 protocol but I'm getting '?' response fron the ELM327 device. In CAN this can be achieved by using Flow control and sending the data in multiple lines seperately one-by-one.......my question is, is there any way of doing the same in KWP2000?

In general, sending multiframe payloads is not supported by plain ELM327 devices. Although with some crude combinations of ATR0 and ATR1 or alternatively appending 0 and 1 to your frames to distinguish whether you want a response or not, you could do it in theory, but it's pretty unreliable on most adapters.
There are – however – several ELM327-compatible adapters (notably those based on the STN11xx and STN22xx chipsets) which have support for builtin ISOTP (if that's what you need) transmission with payloads up to the ISOTP maximum of 4095 bytes.

Related

What does CBATTError Code insufficientResources really mean?

I'm trying to send data over BLE from my iPhone to an ESP32 board. I'm developing in flutter platform and I'm using flutter_reactive_ble library.
My iPhone can connect to the other device and it can also send 1 byte using writeCharacterisiticWithResponse function. But when I try to send my real data which is large (>7000 bytes), it then gives me the error:
flutter: Error occured when writing 9f714672-888c-4450-845f-602c1331cdeb :
Exception: GenericFailure<WriteCharacteristicFailure>(
code: WriteCharacteristicFailure.unknown,
message: "Error Domain=CBATTErrorDomain Code=17
"Resources are insufficient."
UserInfo={NSLocalizedDescription=Resources are insufficient.}")
I tried searching for this error but didn't find additional info, even in Apple Developer website. It just says:
Resources are insufficient to complete the ATT request.
What does this error really means? Which resources are not sufficient and how to work around this problem?
This is almost certainly larger than this characteristic's maximum value length (which is probably on the order of 10s of bytes, not 1000s of bytes). Before writing, you need to call maximumWriteValueLength(for:) to see how much data can be written. If you're trying to send serial data over a characteristic (which is common, but not really what they were designed for), you'll need to break your data up into chunks and reassemble them on the peripheral. You will likely either need an "end" indicator of some kind, or you will need to send the length of the payload first so that the receiver knows how much to excpect.
First of all, a characteristic value cannot be larger than 512 bytes. This is set by the ATT standard (Bluetooth Core Specification v5.3, Vol 3, Part F (ATT), section 3.2.9). This number has been set arbitrarily by the protocol designers and does not map to any technical limitation of the protocol.
So, don't send 7000 bytes in a single write. You need to keep it at most 512 to be standard compliant.
If you say that it works with another Bluetooth stack running on the GATT server, then I guess CoreBluetooth does not enforce/check the maximum length of 512 bytes on the client side (I haven't tested). Therefore I also guess the error code you see was sent by the remote device rather than by CoreBluetooth locally as a pre-check.
There are three different common ways of writing a characteristic on the protocol level (Bluetooth Core Specification v5.3, Vol 3, Part G (GATT), section 4.9 Characteristic Value Write):
Write Without Response (4.9.1)
Write Characteristic Value (4.9.3)
Write Long Characteristic Values (4.9.4)
Number one is unidirectional and does not result in a response packet. It uses a single ATT_WRITE_CMD packet where the value must be at most ATT_MTU-3 bytes in length. This length can be retrieved using maximumWriteValueLength(for:) with .withoutResponse. The requestMtu method in flutter_reactive_ble uses this method internally. If you execute many writes of this type rapidly, be sure to add flow control to avoid CoreBluetooth dropping outgoing packets before they are sent. This can be done through peripheralIsReadyToSendWriteWithoutResponse by simply always waiting for this callback after each write, before you write the next packet. Unfortunately, it seems flutter_reactive_ble does not implement this flow control mechanism.
Number two uses a single ATT_WRITE_REQ where the value must be at most ATT_MTU-3 bytes in length, just as above. Use the same approach as above to retrieve that maximum length (note that maximumWriteValueLength with .withResponse always returns 512 and is not what you want). Here however, either an ATT_WRITE_RSP will be returned on success or an error packet will be received with an error code. Only one ATT transaction can be outstanding at a time, which significantly lowers throughput compared to Write Without Response.
Number three uses a sequence of multiple ATT_PREPARE_WRITE_REQ packets (containing offset and value) followed by an ATT_EXECUTE_WRITE_REQ. The maximum length of the value in each each chunk is ATT_MTU-5. Each _REQ packet also requires a corresponding _RSP packet before it can continue (alternatively, an error code could be sent by the remote device). This approach is used when the characteristic value to be written is too long to be sent using a single ATT_WRITE_REQ.
For any of the above write methods, you are always also limited by the maximum attribute size of 512 bytes as per the specification.
Any Bluetooth stack I know of transparently chooses between "Write Characteristic Value" and "Write Long Characteristic Values" when you tell it to write with response, depending on the value length and MTU. Server side it's a bit different. Some stacks put the burden on the user to combine all packets but it seems nimble handles that on its own. From what I can see in the source code (https://github.com/apache/mynewt-nimble/blob/26ccb8af1f3ea6ad81d5d7cbb762747c6e06a24b/nimble/host/src/ble_att_svr.c#L2099) it can return the "Insufficient Resources" error code when it tries to allocate memory but fails (most likely due to too much buffered data). This is what might happen for you. To answer your first actual question, the standard itself does not say anything else about this error code than simply "Insufficient Resources to complete the request".
The error has nothing to do with LE Data Length extension, which is simply an optimization for a lower layer (BLE Link Layer) that does not affect the functionality of the host stack. The L2CAP layer will take care of the reassembling of smaller link layer packets if necessary, and must always support up to the negotiated MTU without overflowing any buffers.
Now, to answer your second question, if you send very large amounts of data (7000 bytes), you must divide the data in multiple chunks and come up with a way to correctly be able to combine them. Each chunk is written as a full characteristic value. When you do this, be sure to send values at most of size ATT_MTU-3 (but never larger than 512 bytes), to avoid the inefficient overheads of "Write Long Characteristic Values". It's then up to your application code to make sure you don't run out of memory in case too much data is sent.

Controller Area Network (CAN)

The standard message frame size for CAN is 108-bits (correct me if I am wrong about this... I am still learning about CAN)
Would I be able to send a message that has the sizes of 750 bytes, 2 bytes, or 510 bytes?
Since 108-bits = 13.50 bytes, I assume I could send the 2 bytes message, but how about the other message sizes?
CAN is a datalink protocol with a maximum payload of 8 bytes (64 bytes if you are using CAN-FD) per frame. If you need to send a message larger than that, you will need to make use of a transport protocol to split the message up into individual frames. Depending on the context, you can create your own ad-hoc protocol to do this, or you may look into a standard protocol such as CANopen or J1939 to provide transport services for you.

Is Delphi jvclHidDevice ReportID the equivalent of USB endpoint?

I can make USB HID work in Delphi (2010) for simple stuff (one endpoint, ReportID = 0).
But now I need to send 96 words (192 bytes) of data every millisecond. I see how to do that in the slave (PICmicro) with three 64 byte endpoints. (Full speed Interrupt transfer is limited to 64 bytes per endpoint.) But I don't see either a more flexible USB/Delphi object or a way to specify endpoints in the JvclHIDDeviceController object.
Is ReportID telling me the received endpoint?
Is ReportID telling me the received endpoint?
No. When used, it is the first of the 64 (maximum) data bytes.
I need to send 96 words (192 bytes) of data every millisecond
Using WinUSB (or LibUSB-win32) and a bulk pipe sounds simpler to me than trying to create and access a composite device with 3 HID interfaces.

Discriminate between MSDU, MMPDU while using Native WiFi for retrieving incoming number of frames?

I have some problems whiling using Mircosoft Native Wifi API.
I can use queryinterface function to get the current value of counter to know the frames received.
But the statistic involves not only MSDU but also MMPDU and MPDU, which cause the result inaccurate.
as the link: See the site
The members of this structure are used to record MAC-level statistics for:
MAC service data unit (MSDU) packets.
MAC protocol data unit (MPDU) frames.
MPDU frame counters must include all MPDU fragments sent for an MSDU packet.
Management MPDU (MMPDU) frames.
So, is there any way to obtain only the received number of MSDU ??? THX!!

Is transmitted bytes event exist in Linux kernel?

I need to write a rate limiter, that will perform some stuff each time X bytes were transmitted.
The straightforward is to check the length of each transmitted packet, but I think it will be to slow for me.
Is there a way to use some kind of network event, that will be triggered by transmitted packets/bytes?
I think you may look at netfilter.
Using its (kernel level) api, you can have your custom code triggered by network events, modify received messages before passing it to application, and so on.
http://www.netfilter.org/
It's protocol dependent, actually. But for TCP, you can setsockopt the SO_RCVLOWAT option to define the minimum number of bytes (watermark) to permit the read operation.
If you need to enforce the maximum size too, adjust the receive buffer size using SO_RCVBUF.

Resources