dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
uavtalk.c
Go to the documentation of this file.
1 
22 /*
23  * This program is free software; you can redistribute it and/or modify
24  * it under the terms of the GNU General Public License as published by
25  * the Free Software Foundation; either version 3 of the License, or
26  * (at your option) any later version.
27  *
28  * This program is distributed in the hope that it will be useful, but
29  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
30  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
31  * for more details.
32  *
33  * You should have received a copy of the GNU General Public License along
34  * with this program; if not, see <http://www.gnu.org/licenses/>
35  */
36 
37 #include "openpilot.h"
38 #include "uavtalk.h"
39 #include "uavtalk_priv.h"
40 #include "pios_mutex.h"
41 #include "pios_thread.h"
42 
43 // Private functions
44 static int32_t objectTransaction(UAVTalkConnectionData *connection, UAVObjHandle objectId, uint16_t instId, uint8_t type);
45 static int32_t sendObject(UAVTalkConnectionData *connection, UAVObjHandle obj, uint16_t instId, uint8_t type);
46 static int32_t sendSingleObject(UAVTalkConnectionData *connection, UAVObjHandle obj, uint16_t instId, uint8_t type);
47 static int32_t receiveObject(UAVTalkConnectionData *connection);
48 static int32_t sendNack(UAVTalkConnectionData *connection, uint32_t objId, uint16_t instId);
49 
61  UAVTalkFileCb fileCallback)
62 {
63  // allocate object
65  if (!connection) return 0;
66 
67  *connection = (UAVTalkConnectionData) {
69  .iproc = { .state = UAVTALK_STATE_SYNC, },
70  .cbCtx = ctx,
71  .outCb = outputStream,
72  .ackCb = ackCallback,
73  .reqCb = reqCallback,
74  .fileCb = fileCallback,
75  };
76 
77  connection->lock = PIOS_Recursive_Mutex_Create();
78  PIOS_Assert(connection->lock != NULL);
79  // allocate buffers
81  if (!connection->rxBuffer) return 0;
83  if (!connection->txBuffer) return 0;
84 
85  return (UAVTalkConnection) connection;
86 }
87 
93 void UAVTalkGetStats(UAVTalkConnection connectionHandle, UAVTalkStats* statsOut)
94 {
95  UAVTalkConnectionData *connection;
96  CHECKCONHANDLE(connectionHandle,connection,return );
97 
98  // Lock
100 
101  // Copy stats
102  memcpy(statsOut, &connection->stats, sizeof(UAVTalkStats));
103 
104  // And reset.
105  memset(&connection->stats, 0, sizeof(UAVTalkStats));
106 
107  // Release lock
108  PIOS_Recursive_Mutex_Unlock(connection->lock);
109 }
110 
120 int32_t UAVTalkSendObject(UAVTalkConnection connectionHandle, UAVObjHandle obj, uint16_t instId, uint8_t acked)
121 {
122  UAVTalkConnectionData *connection;
123  CHECKCONHANDLE(connectionHandle,connection,return -1);
124  // Send object
125  if (acked) {
126  return objectTransaction(connection, obj, instId, UAVTALK_TYPE_OBJ_ACK);
127  } else {
128  return objectTransaction(connection, obj, instId, UAVTALK_TYPE_OBJ);
129  }
130 }
131 
142 int32_t UAVTalkSendObjectTimestamped(UAVTalkConnection connectionHandle, UAVObjHandle obj, uint16_t instId)
143 {
144  UAVTalkConnectionData *connection;
145  CHECKCONHANDLE(connectionHandle,connection,return -1);
146  // Send object
147  return objectTransaction(connection, obj, instId, UAVTALK_TYPE_OBJ_TS);
148 }
149 
162 static int32_t objectTransaction(UAVTalkConnectionData *connection, UAVObjHandle obj, uint16_t instId, uint8_t type)
163 {
164  if (type == UAVTALK_TYPE_OBJ || type == UAVTALK_TYPE_OBJ_TS ||
165  type == UAVTALK_TYPE_OBJ_ACK) {
166  sendObject(connection, obj, instId, type);
167 
168  return 0;
169  } else {
170  return -1;
171  }
172 }
173 
181 {
182  UAVTalkConnectionData *connection;
183  CHECKCONHANDLE(connectionHandle,connection,return -1);
184 
185  UAVTalkInputProcessor *iproc = &connection->iproc;
186  ++connection->stats.rxBytes;
187 
188  if (iproc->state == UAVTALK_STATE_ERROR) {
189  connection->stats.rxErrors++;
190  iproc->state = UAVTALK_STATE_SYNC;
191  } else if (iproc->state == UAVTALK_STATE_COMPLETE) {
192  iproc->state = UAVTALK_STATE_SYNC;
193  }
194 
195  if (iproc->rxPacketLength < 0xffff)
196  iproc->rxPacketLength++; // update packet byte count
197 
198  // Receive state machine
199  switch (iproc->state)
200  {
201  case UAVTALK_STATE_SYNC:
202  if (rxbyte != UAVTALK_SYNC_VAL)
203  break;
204 
205  // Initialize and update the CRC
206  iproc->cs = PIOS_CRC_updateByte(0, rxbyte);
207 
208  iproc->rxPacketLength = 1;
209 
210  iproc->state = UAVTALK_STATE_TYPE;
211  break;
212 
213  case UAVTALK_STATE_TYPE:
214 
215  // update the CRC
216  iproc->cs = PIOS_CRC_updateByte(iproc->cs, rxbyte);
217 
218  if ((rxbyte & UAVTALK_TYPE_MASK) != UAVTALK_TYPE_VER) {
219  iproc->state = UAVTALK_STATE_ERROR;
220  break;
221  }
222 
223  iproc->type = rxbyte;
224 
225  iproc->packet_size = 0;
226 
227  iproc->state = UAVTALK_STATE_SIZE;
228  iproc->rxCount = 0;
229  break;
230 
231  case UAVTALK_STATE_SIZE:
232 
233  // update the CRC
234  iproc->cs = PIOS_CRC_updateByte(iproc->cs, rxbyte);
235 
236  if (iproc->rxCount == 0) {
237  iproc->packet_size += rxbyte;
238  iproc->rxCount++;
239  break;
240  }
241 
242  iproc->packet_size += rxbyte << 8;
243 
244  if (iproc->packet_size < UAVTALK_MIN_HEADER_LENGTH ||
245  iproc->packet_size > UAVTALK_MAX_HEADER_LENGTH + UAVTALK_MAX_PAYLOAD_LENGTH) { // incorrect packet size
246  iproc->state = UAVTALK_STATE_ERROR;
247  break;
248  }
249 
250  iproc->rxCount = 0;
251  iproc->objId = 0;
252  iproc->state = UAVTALK_STATE_OBJID;
253  break;
254 
255  case UAVTALK_STATE_OBJID:
256 
257  // update the CRC
258  iproc->cs = PIOS_CRC_updateByte(iproc->cs, rxbyte);
259 
260  iproc->objId += rxbyte << (8*(iproc->rxCount++));
261 
262  if (iproc->rxCount < 4)
263  break;
264 
265  if (iproc->type == UAVTALK_TYPE_FILEREQ) {
266  /* Slightly overloaded from "normal" case. Consume
267  * 4 bytes of offset and 2 bytes of flags.
268  */
269 
270  iproc->instanceLength = 0;
271  iproc->rxCount = 0;
272  iproc->length = 6;
273 
274  if ((iproc->packet_size - iproc->rxPacketLength) !=
275  iproc->length) {
276  iproc->state = UAVTALK_STATE_ERROR;
277  break;
278  }
279 
280  iproc->state = UAVTALK_STATE_DATA;
281 
282  break;
283  }
284 
285  // Search for object.
286  iproc->obj = UAVObjGetByID(iproc->objId);
287 
288  // Determine data length
289  if (iproc->type == UAVTALK_TYPE_OBJ_REQ || iproc->type == UAVTALK_TYPE_ACK || iproc->type == UAVTALK_TYPE_NACK) {
290  iproc->length = 0;
291  iproc->instanceLength = 0;
292 
293  /* Length is always pretty much expected to be 0
294  * here, but it can be 2 if it's a multiple inst
295  * obj requested. Don't peer into metadata to
296  * figure this out-- use the packet length
297  * [so we can properly NAK objects we don't know]
298  */
299  if ((iproc->packet_size - iproc->rxPacketLength) == 2) {
300  iproc->instanceLength = 2;
301  } else if (iproc->length > 0) {
302  iproc->state = UAVTALK_STATE_ERROR;
303  break;
304  }
305  } else {
306  if (iproc->obj) {
307  iproc->length = UAVObjGetNumBytes(iproc->obj);
308  iproc->instanceLength = (UAVObjIsSingleInstance(iproc->obj) ? 0 : 2);
309  } else {
310  // We don't know if it's a multi-instance object, so just assume it's 0.
311  iproc->instanceLength = 0;
312  iproc->length = iproc->packet_size - iproc->rxPacketLength;
313  }
314  }
315 
316  // Check length and determine next state
317  if (iproc->length >= UAVTALK_MAX_PAYLOAD_LENGTH) {
318  iproc->state = UAVTALK_STATE_ERROR;
319  break;
320  }
321 
322  // Check the lengths match
323  if ((iproc->rxPacketLength + iproc->instanceLength + iproc->length) != iproc->packet_size) { // packet error - mismatched packet size
324  if (iproc->instanceLength == 0) {
325  // Try again with a 2 inst len
326  // to accept LP's fork of
327  // protocol.
328  iproc->instanceLength = 2;
329  }
330  }
331 
332  if ((iproc->rxPacketLength + iproc->instanceLength + iproc->length) != iproc->packet_size) { // packet error - mismatched packet size
333  iproc->state = UAVTALK_STATE_ERROR;
334  break;
335  }
336 
337  iproc->instId = 0;
338  if (iproc->type == UAVTALK_TYPE_NACK) {
339  // If this is a NACK, we skip to Checksum
340  iproc->state = UAVTALK_STATE_CS;
341  }
342  // Check if this is a single instance object (i.e. if the instance ID field is coming next)
343  else if (iproc->instanceLength) {
344  iproc->state = UAVTALK_STATE_INSTID;
345  } else {
346  // If there is a payload get it, otherwise receive checksum
347  if (iproc->length > 0)
348  iproc->state = UAVTALK_STATE_DATA;
349  else
350  iproc->state = UAVTALK_STATE_CS;
351  }
352  iproc->rxCount = 0;
353 
354  break;
355 
357 
358  // update the CRC
359  iproc->cs = PIOS_CRC_updateByte(iproc->cs, rxbyte);
360 
361  iproc->instId += rxbyte << (8*(iproc->rxCount++));
362 
363  if (iproc->rxCount < 2)
364  break;
365 
366  iproc->rxCount = 0;
367 
368  // If there is a payload get it, otherwise receive checksum
369  if (iproc->length > 0)
370  iproc->state = UAVTALK_STATE_DATA;
371  else
372  iproc->state = UAVTALK_STATE_CS;
373 
374  break;
375 
376  case UAVTALK_STATE_DATA:
377 
378  // update the CRC
379  iproc->cs = PIOS_CRC_updateByte(iproc->cs, rxbyte);
380 
381  connection->rxBuffer[iproc->rxCount++] = rxbyte;
382  if (iproc->rxCount < iproc->length)
383  break;
384 
385  iproc->state = UAVTALK_STATE_CS;
386  iproc->rxCount = 0;
387  break;
388 
389  case UAVTALK_STATE_CS:
390 
391  // the CRC byte
392  if (rxbyte != iproc->cs) { // packet error - faulty CRC
393  connection->stats.rxCRC++;
394  iproc->state = UAVTALK_STATE_ERROR;
395  break;
396  }
397 
398  if (iproc->rxPacketLength != (iproc->packet_size + 1)) { // packet error - mismatched packet size
399  iproc->state = UAVTALK_STATE_ERROR;
400  break;
401  }
402 
403  connection->stats.rxObjectBytes += iproc->length;
404  connection->stats.rxObjects++;
405 
406  iproc->state = UAVTALK_STATE_COMPLETE;
407  break;
408 
409  default:
410  iproc->state = UAVTALK_STATE_ERROR;
411  }
412 
413  // Done
414  return iproc->state;
415 }
416 
423 void UAVTalkProcessInputStream(UAVTalkConnection connectionHandle, uint8_t *rxbytes,
424  int numbytes)
425 {
426  UAVTalkConnectionData *connection;
427 
428  CHECKCONHANDLE(connectionHandle,connection,return);
429 
430  for (int i = 0; i < numbytes; i++) {
432  UAVTalkProcessInputStreamQuiet(connectionHandle,
433  rxbytes[i]);
434 
435  if (state == UAVTALK_STATE_COMPLETE) {
436  receiveObject(connection);
437  }
438  }
439 }
440 
451 int32_t UAVTalkRelayPacket(UAVTalkConnection inConnectionHandle, UAVTalkConnection outConnectionHandle)
452 {
453  UAVTalkConnectionData *inConnection;
454 
455  CHECKCONHANDLE(inConnectionHandle, inConnection, return -1);
456  UAVTalkInputProcessor *inIproc = &inConnection->iproc;
457 
458  // The input packet must be completely parsed.
459  if (inIproc->state != UAVTALK_STATE_COMPLETE) {
460  return -1;
461  }
462 
463  UAVTalkConnectionData *outConnection;
464  CHECKCONHANDLE(outConnectionHandle, outConnection, return -1);
465 
466  if (!outConnection->outCb) {
467  outConnection->stats.txErrors++;
468 
469  return -1;
470  }
471 
472  // Lock
474 
475  outConnection->txBuffer[0] = UAVTALK_SYNC_VAL;
476  // Setup type
477  outConnection->txBuffer[1] = inIproc->type;
478  // next 2 bytes are reserved for data length (inserted here later)
479  // Setup object ID
480  outConnection->txBuffer[4] = (uint8_t)(inIproc->objId & 0xFF);
481  outConnection->txBuffer[5] = (uint8_t)((inIproc->objId >> 8) & 0xFF);
482  outConnection->txBuffer[6] = (uint8_t)((inIproc->objId >> 16) & 0xFF);
483  outConnection->txBuffer[7] = (uint8_t)((inIproc->objId >> 24) & 0xFF);
484  int32_t headerLength = 8;
485 
486  if (inIproc->instanceLength) {
487  // Setup instance ID
488  outConnection->txBuffer[8] = (uint8_t)(inIproc->instId & 0xFF);
489  outConnection->txBuffer[9] = (uint8_t)((inIproc->instId >> 8) & 0xFF);
490  headerLength = 10;
491  }
492 
493  // Copy data (if any)
494  if (inIproc->length > 0) {
495  memcpy(&outConnection->txBuffer[headerLength], inConnection->rxBuffer, inIproc->length);
496  }
497 
498  // Store the packet length
499  outConnection->txBuffer[2] = (uint8_t)((headerLength + inIproc->length) & 0xFF);
500  outConnection->txBuffer[3] = (uint8_t)(((headerLength + inIproc->length) >> 8) & 0xFF);
501 
502  // Copy the checksum
503  outConnection->txBuffer[headerLength + inIproc->length] = inIproc->cs;
504 
505  // Send the buffer.
506  int32_t rc = (*outConnection->outCb)(outConnection->cbCtx, outConnection->txBuffer, headerLength + inIproc->length + UAVTALK_CHECKSUM_LENGTH);
507 
508  // Update stats
509  outConnection->stats.txBytes += (rc > 0) ? rc : 0;
510 
511  // evaluate return value before releasing the lock
512  int32_t ret = 0;
513  if (rc != (int32_t)(headerLength + inIproc->length + UAVTALK_CHECKSUM_LENGTH)) {
514  outConnection->stats.txErrors++;
515  ret = -1;
516  }
517 
518  // Release lock
519  PIOS_Recursive_Mutex_Unlock(outConnection->lock);
520 
521  // Done
522  return ret;
523 }
524 
531 int32_t UAVTalkReceiveObject(UAVTalkConnection connectionHandle)
532 {
533  UAVTalkConnectionData *connection;
534 
535  CHECKCONHANDLE(connectionHandle, connection, return -1);
536 
537  UAVTalkInputProcessor *iproc = &connection->iproc;
538  if (iproc->state != UAVTALK_STATE_COMPLETE) {
539  return -1;
540  }
541 
542  return receiveObject(connection);
543 }
544 
550 uint32_t UAVTalkGetPacketObjId(UAVTalkConnection connectionHandle)
551 {
552  UAVTalkConnectionData *connection;
553 
554  CHECKCONHANDLE(connectionHandle, connection, return 0);
555 
556  return connection->iproc.objId;
557 }
558 
564 uint32_t UAVTalkGetPacketInstId(UAVTalkConnection connectionHandle)
565 {
566  UAVTalkConnectionData *connection;
567 
568  CHECKCONHANDLE(connectionHandle, connection, return 0);
569 
570  return connection->iproc.instId;
571 }
572 
577 static void handleFileReq(UAVTalkConnectionData *connection)
578 {
579  UAVTalkInputProcessor *iproc = &connection->iproc;
580  uint32_t file_id = iproc->objId;
581 
582  struct filereq_data *req = (struct filereq_data *) connection->rxBuffer;
583 
584  /* printf("Got filereq for file_id=%08x offs=%d\n", file_id, req->offset); */
585 
586  /* Need txbuffer, and need to make sure file response msgs
587  * are contiguous on link.
588  */
590 
591  connection->txBuffer[0] = UAVTALK_SYNC_VAL; // sync byte
592  connection->txBuffer[1] = UAVTALK_TYPE_FILEDATA;
593  // data length inserted here below
594  connection->txBuffer[4] = (uint8_t)(file_id & 0xFF);
595  connection->txBuffer[5] = (uint8_t)((file_id >> 8) & 0xFF);
596  connection->txBuffer[6] = (uint8_t)((file_id >> 16) & 0xFF);
597  connection->txBuffer[7] = (uint8_t)((file_id >> 24) & 0xFF);
598 
599  uint8_t data_offs = 8;
600 
601  struct fileresp_data *resp =
602  (struct fileresp_data *) (connection->txBuffer + data_offs);
603 
604  data_offs += sizeof(*resp);
605 
606  uint32_t file_offset = req->offset;
607 
608  for (int i = 0; ; i++) {
609  resp->offset = file_offset;
610  resp->flags = 0;
611 
612  int32_t cb_numbytes = -1;
613 
614  if (connection->fileCb) {
615  cb_numbytes = connection->fileCb(connection->cbCtx,
616  connection->txBuffer + data_offs,
617  file_id, file_offset, 100);
618  }
619 
620  uint8_t total_len = data_offs;
621 
622  if (cb_numbytes > 0) {
623  total_len += cb_numbytes;
624 
625  file_offset += cb_numbytes;
626 
627  if (i == 5) { /* 6 messages per chunk */
629  } else {
630  resp->flags = 0;
631  }
632  } else {
633  /* End of file, last chunk in sequence */
634  resp->flags = UAVTALK_FILEDATA_LAST |
636  }
637 
638  // Store the packet length
639  connection->txBuffer[2] = (uint8_t)((total_len) & 0xFF);
640  connection->txBuffer[3] = (uint8_t)(((total_len) >> 8) & 0xFF);
641 
642  // Calculate checksum
643  connection->txBuffer[total_len] = PIOS_CRC_updateCRC(0,
644  connection->txBuffer, total_len);
645 
646  int32_t rc = (*connection->outCb)(connection->cbCtx,
647  connection->txBuffer, total_len + 1);
648 
649  if (rc == total_len) {
650  // Update stats
651  connection->stats.txBytes += total_len;
652  }
653 
654  if (resp->flags & UAVTALK_FILEDATA_LAST) {
655  break;
656  }
657  }
658 
659  PIOS_Recursive_Mutex_Unlock(connection->lock);
660 }
661 
673 static int32_t receiveObject(UAVTalkConnectionData *connection)
674 {
675  int32_t ret = 0;
676 
677  UAVTalkInputProcessor *iproc = &connection->iproc;
678 
679  uint8_t type = iproc->type;
680  uint32_t objId = iproc->objId;
681  uint16_t instId = iproc->instId;
682 
683  UAVObjHandle obj = iproc->obj;
684 
685  /* Handle ACK/NACK --- don't bother to look up IDs etc for these
686  * because we don't need it.
687  *
688  * Treat NACKs and ACKs identically -- ground has done all it wants
689  * with them. This incurs a small penalty from calling the callback
690  * when GCS is a mismatched version and likes NACKing us, but ensures
691  * that we don't start blocking the telemetry session for an ACK that
692  * will never come.
693  */
694 
695  if ((type == UAVTALK_TYPE_NACK) || (type == UAVTALK_TYPE_ACK)) {
696  if (connection->ackCb) {
697  connection->ackCb(connection->cbCtx, objId, instId);
698  }
699 
700  return 0;
701  } else if (type == UAVTALK_TYPE_OBJ_REQ) {
702  if (connection->reqCb) {
703  connection->reqCb(connection->cbCtx, objId, instId);
704  return 0;
705  }
706 
707  return -1;
708  }
709 
710  /* File request data is a special case. */
711  if (type == UAVTALK_TYPE_FILEREQ) {
712  handleFileReq(connection);
713 
714  return 0;
715  }
716 
718 
719  // Process message type
720  switch (type) {
721  case UAVTALK_TYPE_OBJ:
722  // All instances, not allowed for OBJ messages
723  if (obj && (instId != UAVOBJ_ALL_INSTANCES)) {
724  // Unpack object, if the instance does not exist it will be created!
725  UAVObjUnpack(obj, instId, connection->rxBuffer);
726  } else {
727  ret = -1;
728  }
729  break;
731  // All instances, not allowed for OBJ_ACK messages
732  if (obj && (instId != UAVOBJ_ALL_INSTANCES)) {
733  // Unpack object, if the instance does not exist it will be created!
734  if (UAVObjUnpack(obj, instId, connection->rxBuffer) == 0) {
735  // Transmit ACK
736  sendObject(connection, obj, instId, UAVTALK_TYPE_ACK);
737  } else {
738  ret = -1;
739  }
740  } else {
741  // We don't know this object, and we complain about it
742  sendNack(connection, objId, 0);
743  ret = -1;
744  }
745  break;
746  default:
747  ret = -1;
748  }
749 
750  PIOS_Recursive_Mutex_Unlock(connection->lock);
751 
752  // Done
753  return ret;
754 }
755 
765 static int32_t sendObject(UAVTalkConnectionData *connection, UAVObjHandle obj, uint16_t instId, uint8_t type)
766 {
767  uint32_t numInst;
768  uint32_t n;
769 
770  // If all instances are requested and this is a single instance object, force instance ID to zero
771  if (instId == UAVOBJ_ALL_INSTANCES && UAVObjIsSingleInstance(obj) ) {
772  instId = 0;
773  }
774 
775  // Process message type
776  // XXX some of these combinations don't make sense, like obj with ack
777  // requested for all instances [because if we implemented it properly
778  // it would be -exceptionally- costly]
779  if (type == UAVTALK_TYPE_OBJ || type == UAVTALK_TYPE_OBJ_TS ||
780  type == UAVTALK_TYPE_OBJ_ACK) {
781  if (instId == UAVOBJ_ALL_INSTANCES) {
782  // Get number of instances
783  numInst = UAVObjGetNumInstances(obj);
784  // Send all instances
785  for (n = 0; n < numInst; ++n) {
786  sendSingleObject(connection, obj, n, type);
787  }
788  return 0;
789  } else {
790  return sendSingleObject(connection, obj, instId, type);
791  }
792  } else if (type == UAVTALK_TYPE_OBJ_REQ) {
793  return sendSingleObject(connection, obj, instId, UAVTALK_TYPE_OBJ_REQ);
794  } else if (type == UAVTALK_TYPE_ACK) {
795  if (instId != UAVOBJ_ALL_INSTANCES) {
796  return sendSingleObject(connection, obj, instId, UAVTALK_TYPE_ACK);
797  } else {
798  return -1;
799  }
800  } else {
801  return -1;
802  }
803 }
804 
814 static int32_t sendSingleObject(UAVTalkConnectionData *connection, UAVObjHandle obj, uint16_t instId, uint8_t type)
815 {
816  int32_t length;
817  int32_t dataOffset;
818  uint32_t objId;
819 
820  if (!connection->outCb) return -1;
821 
822  // Determine data length
823  if (type == UAVTALK_TYPE_OBJ_REQ || type == UAVTALK_TYPE_ACK) {
824  length = 0;
825  } else {
826  length = UAVObjGetNumBytes(obj);
827  }
828 
829  // Check length
830  if (length >= UAVTALK_MAX_PAYLOAD_LENGTH) {
831  return -1;
832  }
833 
834  // Setup type and object id fields
835  objId = UAVObjGetID(obj);
836 
838 
839  connection->txBuffer[0] = UAVTALK_SYNC_VAL; // sync byte
840  connection->txBuffer[1] = type;
841  // data length inserted here below
842  connection->txBuffer[4] = (uint8_t)(objId & 0xFF);
843  connection->txBuffer[5] = (uint8_t)((objId >> 8) & 0xFF);
844  connection->txBuffer[6] = (uint8_t)((objId >> 16) & 0xFF);
845  connection->txBuffer[7] = (uint8_t)((objId >> 24) & 0xFF);
846 
847  // Setup instance ID if one is required
848  if (UAVObjIsSingleInstance(obj)) {
849  dataOffset = 8;
850  } else {
851  connection->txBuffer[8] = (uint8_t)(instId & 0xFF);
852  connection->txBuffer[9] = (uint8_t)((instId >> 8) & 0xFF);
853  dataOffset = 10;
854  }
855 
856  // Add timestamp when the transaction type is appropriate
857  if (type & UAVTALK_TIMESTAMPED) {
858  uint32_t time = PIOS_Thread_Systime();
859  connection->txBuffer[dataOffset] = (uint8_t)(time & 0xFF);
860  connection->txBuffer[dataOffset + 1] = (uint8_t)((time >> 8) & 0xFF);
861  dataOffset += 2;
862  }
863 
864  // Copy data (if any)
865  if (length > 0) {
866  if (UAVObjPack(obj, instId, &connection->txBuffer[dataOffset]) < 0) {
867  PIOS_Recursive_Mutex_Unlock(connection->lock);
868  return -1;
869  }
870  }
871 
872  // Store the packet length
873  connection->txBuffer[2] = (uint8_t)((dataOffset+length) & 0xFF);
874  connection->txBuffer[3] = (uint8_t)(((dataOffset+length) >> 8) & 0xFF);
875 
876  // Calculate checksum
877  connection->txBuffer[dataOffset+length] = PIOS_CRC_updateCRC(0, connection->txBuffer, dataOffset+length);
878 
879  uint16_t tx_msg_len = dataOffset+length+UAVTALK_CHECKSUM_LENGTH;
880  int32_t rc = (*connection->outCb)(connection->cbCtx, connection->txBuffer,
881  tx_msg_len);
882 
883  if (rc == tx_msg_len) {
884  // Update stats
885  ++connection->stats.txObjects;
886  connection->stats.txBytes += tx_msg_len;
887  connection->stats.txObjectBytes += length;
888  }
889 
890  // Done
891  PIOS_Recursive_Mutex_Unlock(connection->lock);
892  return 0;
893 }
894 
903 int32_t UAVTalkSendNack(UAVTalkConnection connectionHandle, uint32_t objId,
904  uint16_t instId)
905 {
906  UAVTalkConnectionData *connection;
907  CHECKCONHANDLE(connectionHandle, connection, return -1);
908 
909  return sendNack(connection, objId, instId);
910 }
911 
912 static int32_t sendNack(UAVTalkConnectionData *connection, uint32_t objId,
913  uint16_t instId)
914 {
915  int32_t dataOffset;
916 
917  if (!connection->outCb) return -1;
918 
920  connection->txBuffer[0] = UAVTALK_SYNC_VAL; // sync byte
921  connection->txBuffer[1] = UAVTALK_TYPE_NACK;
922  // data length inserted here below
923  connection->txBuffer[4] = (uint8_t)(objId & 0xFF);
924  connection->txBuffer[5] = (uint8_t)((objId >> 8) & 0xFF);
925  connection->txBuffer[6] = (uint8_t)((objId >> 16) & 0xFF);
926  connection->txBuffer[7] = (uint8_t)((objId >> 24) & 0xFF);
927 
928  dataOffset = 8;
929 
930  if (instId) {
931  dataOffset += 2;
932 
933  connection->txBuffer[8] = (uint8_t)(instId & 0xFF);
934  connection->txBuffer[9] = (uint8_t)((instId >> 8) & 0xFF);
935  }
936 
937  // Store the packet length
938  connection->txBuffer[2] = (uint8_t)((dataOffset) & 0xFF);
939  connection->txBuffer[3] = (uint8_t)(((dataOffset) >> 8) & 0xFF);
940 
941  // Calculate checksum
942  connection->txBuffer[dataOffset] = PIOS_CRC_updateCRC(0, connection->txBuffer, dataOffset);
943 
944  uint16_t tx_msg_len = dataOffset + UAVTALK_CHECKSUM_LENGTH;
945  int32_t rc = (*connection->outCb)(connection->cbCtx, connection->txBuffer,
946  tx_msg_len);
947 
948  if (rc == tx_msg_len) {
949  // Update stats
950  connection->stats.txBytes += tx_msg_len;
951  }
952 
953  PIOS_Recursive_Mutex_Unlock(connection->lock);
954 
955  // Done
956  return 0;
957 }
958 
#define UAVTALK_FILEDATA_EOF
Definition: uavtalk_priv.h:122
uint32_t PIOS_Thread_Systime(void)
Definition: pios_thread.c:212
#define UAVTALK_MAX_HEADER_LENGTH
Definition: uavtalk_priv.h:56
#define UAVTALK_MIN_HEADER_LENGTH
Definition: uavtalk_priv.h:46
int32_t(* UAVTalkOutputCb)(void *ctx, uint8_t *data, int32_t length)
Definition: uavtalk.h:34
void(* UAVTalkAckCb)(void *ctx, uint32_t obj_id, uint16_t inst_id)
Definition: uavtalk.h:35
UAVObjHandle UAVObjGetByID(uint32_t id)
static int32_t sendNack(UAVTalkConnectionData *connection, uint32_t objId, uint16_t instId)
Definition: uavtalk.c:912
int32_t UAVTalkSendObjectTimestamped(UAVTalkConnection connectionHandle, UAVObjHandle obj, uint16_t instId)
Definition: uavtalk.c:142
UAVTalkRxState state
Definition: uavtalk_priv.h:85
static int32_t sendSingleObject(UAVTalkConnectionData *connection, UAVObjHandle obj, uint16_t instId, uint8_t type)
Definition: uavtalk.c:814
uint32_t rxErrors
Definition: uavtalk.h:49
#define UAVTALK_MAX_PAYLOAD_LENGTH
Definition: uavtalk_priv.h:70
int32_t UAVTalkSendNack(UAVTalkConnection connectionHandle, uint32_t objId, uint16_t instId)
Definition: uavtalk.c:903
#define UAVTALK_TYPE_NACK
Definition: uavtalk_priv.h:117
static void ackCallback(void *ctx, uint32_t obj_id, uint16_t inst_id)
Definition: telemetry.c:520
void UAVTalkGetStats(UAVTalkConnection connection, UAVTalkStats *stats)
Definition: uavtalk.c:93
uint32_t txObjectBytes
Definition: uavtalk.h:44
static int32_t objectTransaction(UAVTalkConnectionData *connection, UAVObjHandle objectId, uint16_t instId, uint8_t type)
Definition: uavtalk.c:162
uint32_t rxObjects
Definition: uavtalk.h:46
int32_t UAVObjUnpack(UAVObjHandle obj_handle, uint16_t instId, const uint8_t *dataIn)
#define UAVTALK_TYPE_VER
Definition: uavtalk_priv.h:111
#define CHECKCONHANDLE(handle, variable, failcommand)
Definition: uavtalk_priv.h:126
uint32_t UAVObjGetNumBytes(UAVObjHandle obj)
#define UAVOBJ_ALL_INSTANCES
int32_t UAVObjPack(UAVObjHandle obj_handle, uint16_t instId, uint8_t *dataOut)
UAVTalkInputProcessor iproc
Definition: uavtalk_priv.h:94
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
uint32_t rxCRC
Definition: uavtalk.h:50
void(* UAVTalkReqCb)(void *ctx, uint32_t obj_id, uint16_t inst_id)
Definition: uavtalk.h:36
void UAVTalkProcessInputStream(UAVTalkConnection connectionHandle, uint8_t *rxbytes, int numbytes)
Definition: uavtalk.c:423
void * PIOS_malloc_no_dma(size_t size)
Definition: pios_heap.c:166
static void reqCallback(void *ctx, uint32_t obj_id, uint16_t inst_id)
Definition: telemetry.c:488
uint32_t offset
Definition: uavtalk_priv.h:59
uint32_t txBytes
Definition: uavtalk.h:42
#define UAVTALK_TYPE_OBJ
Definition: uavtalk_priv.h:113
uint8_t length
uint32_t rxBytes
Definition: uavtalk.h:43
void * UAVTalkConnection
Definition: uavtalk.h:53
struct pios_recursive_mutex * PIOS_Recursive_Mutex_Create(void)
Definition: pios_mutex.c:115
UAVTalkConnection UAVTalkInitialize(void *ctx, UAVTalkOutputCb outputStream, UAVTalkAckCb ackCallback, UAVTalkReqCb reqCallback, UAVTalkFileCb fileCallback)
Definition: uavtalk.c:59
uint8_t PIOS_CRC_updateByte(uint8_t crc, const uint8_t data)
Definition: pios_crc.c:141
uint32_t UAVObjGetID(UAVObjHandle obj)
#define UAVTALK_SYNC_VAL
Definition: uavtalk_priv.h:109
bool UAVObjIsSingleInstance(UAVObjHandle obj)
int32_t(* UAVTalkFileCb)(void *ctx, uint8_t *buf, uint32_t file_id, uint32_t offset, uint32_t len)
Definition: uavtalk.h:37
#define UAVTALK_TYPE_MASK
Definition: uavtalk_priv.h:110
#define UAVTALK_MAX_PACKET_LENGTH
Definition: uavtalk_priv.h:72
Private include file of the UAVTalk library.
bool PIOS_Recursive_Mutex_Lock(struct pios_recursive_mutex *mtx, uint32_t timeout_ms)
Definition: pios_mutex.c:139
uint32_t txObjects
Definition: uavtalk.h:47
#define UAVTALK_TYPE_ACK
Definition: uavtalk_priv.h:116
uint32_t rxObjectBytes
Definition: uavtalk.h:45
UAVTalkOutputCb outCb
Definition: uavtalk_priv.h:99
uint8_t i
Definition: msp_messages.h:97
struct pios_recursive_mutex * lock
Definition: uavtalk_priv.h:92
uint32_t UAVTalkGetPacketInstId(UAVTalkConnection connection)
Definition: uavtalk.c:564
State information for the UAVTalk parser.
Definition: uavtalk_priv.h:75
#define UAVTALK_TYPE_OBJ_REQ
Definition: uavtalk_priv.h:114
uint32_t offset
Definition: uavtalk_priv.h:64
Tracking statistics for a UAVTalk connection.
Definition: uavtalk.h:41
#define UAVTALK_CHECKSUM_LENGTH
Definition: uavtalk_priv.h:69
#define UAVTALK_FILEDATA_LAST
Definition: uavtalk_priv.h:123
Information for the physical link.
Definition: uavtalk_priv.h:90
#define UAVTALK_TYPE_OBJ_ACK
Definition: uavtalk_priv.h:115
static void handleFileReq(UAVTalkConnectionData *connection)
Definition: uavtalk.c:577
#define UAVTALK_TYPE_OBJ_TS
Definition: uavtalk_priv.h:120
uint8_t type
UAVTalkFileCb fileCb
Definition: uavtalk_priv.h:102
int32_t UAVTalkSendObject(UAVTalkConnection connection, UAVObjHandle obj, uint16_t instId, uint8_t acked)
Definition: uavtalk.c:120
uint8_t flags
Definition: uavtalk_priv.h:65
UAVTalkRxState
Definition: uavtalk.h:55
UAVTalkRxState UAVTalkProcessInputStreamQuiet(UAVTalkConnection connection, uint8_t rxbyte)
Definition: uavtalk.c:180
UAVTalkStats stats
Definition: uavtalk_priv.h:93
Includes PiOS and core architecture components.
uint16_t UAVObjGetNumInstances(UAVObjHandle obj)
uint8_t PIOS_CRC_updateCRC(uint8_t crc, const uint8_t *data, int32_t length)
Update a CRC with a data buffer.
Definition: pios_crc.c:153
int32_t UAVTalkReceiveObject(UAVTalkConnection connectionHandle)
Definition: uavtalk.c:531
uint32_t file_id
#define UAVTALK_TYPE_FILEDATA
Definition: uavtalk_priv.h:119
#define UAVTALK_TYPE_FILEREQ
Definition: uavtalk_priv.h:118
#define UAVTALK_TIMESTAMPED
Definition: uavtalk_priv.h:112
int32_t UAVTalkRelayPacket(UAVTalkConnection inConnectionHandle, UAVTalkConnection outConnectionHandle)
Definition: uavtalk.c:451
uint32_t txErrors
Definition: uavtalk.h:48
#define PIOS_Assert(test)
Definition: pios_debug.h:52
Include file of the UAVTalk library.
static int32_t receiveObject(UAVTalkConnectionData *connection)
Definition: uavtalk.c:673
bool PIOS_Recursive_Mutex_Unlock(struct pios_recursive_mutex *mtx)
Definition: pios_mutex.c:144
uint32_t UAVTalkGetPacketObjId(UAVTalkConnection connection)
Definition: uavtalk.c:550
static int32_t sendObject(UAVTalkConnectionData *connection, UAVObjHandle obj, uint16_t instId, uint8_t type)
Definition: uavtalk.c:765
#define PIOS_MUTEX_TIMEOUT_MAX
Definition: pios_mutex.h:30
enum arena_state state
#define UAVTALK_CANARI
Definition: uavtalk_priv.h:106