HFP: Fix reading multiple AT commands from a single data packet

The `data` received in `_read_at` may have multiple commands.

This fixes `execute_command` timing out when waiting for an `OK`
response when it is in the same data buffer, e.g. during SLC
initialization: b'\r\n+BRSF: 3904\r\n\r\nOK\r\n'
This commit is contained in:
Yegor Pomortsev
2024-10-18 13:21:24 -07:00
parent 23f46b36b3
commit e1714c16cc

View File

@@ -795,29 +795,30 @@ class HfProtocol(pyee.EventEmitter):
# Append to the read buffer. # Append to the read buffer.
self.read_buffer.extend(data) self.read_buffer.extend(data)
# Locate header and trailer. while self.read_buffer:
header = self.read_buffer.find(b'\r\n') # Locate header and trailer.
trailer = self.read_buffer.find(b'\r\n', header + 2) header = self.read_buffer.find(b'\r\n')
if header == -1 or trailer == -1: trailer = self.read_buffer.find(b'\r\n', header + 2)
return if header == -1 or trailer == -1:
return
# Isolate the AT response code and parameters. # Isolate the AT response code and parameters.
raw_response = self.read_buffer[header + 2 : trailer] raw_response = self.read_buffer[header + 2 : trailer]
response = AtResponse.parse_from(raw_response) response = AtResponse.parse_from(raw_response)
logger.debug(f"<<< {raw_response.decode()}") logger.debug(f"<<< {raw_response.decode()}")
# Consume the response bytes. # Consume the response bytes.
self.read_buffer = self.read_buffer[trailer + 2 :] self.read_buffer = self.read_buffer[trailer + 2 :]
# Forward the received code to the correct queue. # Forward the received code to the correct queue.
if self.command_lock.locked() and ( if self.command_lock.locked() and (
response.code in STATUS_CODES or response.code in RESPONSE_CODES response.code in STATUS_CODES or response.code in RESPONSE_CODES
): ):
self.response_queue.put_nowait(response) self.response_queue.put_nowait(response)
elif response.code in UNSOLICITED_CODES: elif response.code in UNSOLICITED_CODES:
self.unsolicited_queue.put_nowait(response) self.unsolicited_queue.put_nowait(response)
else: else:
logger.warning(f"dropping unexpected response with code '{response.code}'") logger.warning(f"dropping unexpected response with code '{response.code}'")
async def execute_command( async def execute_command(
self, self,