dn_robotalk.c
Go to the documentation of this file.
00001 
00025 #include "stdint.h"
00026 #include <stdlib.h>
00027 #include <string.h>
00028 
00029 #if defined(_USE_WIN_API)
00030 #include <windows.h>
00031 #elif defined(_USE_LINUX_API)
00032 #include <arpa/inet.h>
00033 #else
00034 #include "dn_additional.h"
00035 #endif
00036 
00037 #include "dn_common.h"
00038 #include "dn_device.h"
00039 #include "dn_udp.h"
00040 #include "dn_robotalk.h"
00041 
00049 static HRESULT
00050 rtk_send_nak(const struct CONN_PARAM_COMMON *device, uint8_t from_id,
00051     uint8_t to_id)
00052 {
00053   union RTK_PACKET *packet = NULL;
00054   HRESULT hr;
00055 
00056   packet = (union RTK_PACKET *) malloc(RTK_SIZE_HEADER + RTK_SIZE_CRC);
00057   if (packet == NULL)
00058     return E_OUTOFMEMORY;
00059 
00060   hr = rtk_param2packet(RTK_CMD_NAK, NULL, 0, from_id, to_id, packet);
00061   if (FAILED(hr))
00062     goto exit_proc;
00063 
00064   hr = rtk_send(device, packet);
00065 
00066 exit_proc:
00067   if (packet != NULL) {
00068     free(packet);
00069     packet = NULL;
00070   }
00071 
00072   return hr;
00073 }
00074 
00085 HRESULT
00086 rtk_param2packet(uint16_t command, const uint8_t *data, uint8_t len_data,
00087     uint8_t from_id, uint8_t to_id, union RTK_PACKET *packet)
00088 {
00089   if (packet == NULL)
00090     return E_INVALIDARG;
00091   if (len_data > 0 && data == NULL)
00092     return E_INVALIDARG;
00093   if (len_data > RTK_SIZE_DATA - RTK_SIZE_CRC)
00094     return E_INVALIDARG;
00095 
00096   packet->enq = RTK_ENQ;
00097   packet->len = len_data;
00098 
00099   /* Orders to ROBOTalk endian */
00100   memcpy_be(&packet->command, &command, RTK_SIZE_COMMAND);
00101 
00102   packet->from_id = from_id;
00103   packet->to_id = to_id;
00104 
00105   if (len_data > 0) {
00106     memcpy(packet->data, data, len_data);
00107   }
00108 
00109   return S_OK;
00110 }
00111 
00117 uint16_t
00118 rtk_calc_crc(const union RTK_PACKET *packet)
00119 {
00120   uint8_t pos, len_data;
00121   uint16_t crc = 0;
00122 
00123   if (packet != NULL) {
00124     len_data =
00125         (packet->len > (RTK_SIZE_DATA - RTK_SIZE_CRC)) ?
00126             (RTK_SIZE_DATA - RTK_SIZE_CRC) : packet->len;
00127 
00128     for (pos = 0; pos < RTK_SIZE_HEADER + len_data; pos++) {
00129       crc += (uint16_t) packet->buf[pos];
00130     }
00131   }
00132 
00133   return crc;
00134 }
00135 
00142 HRESULT
00143 rtk_send(const struct CONN_PARAM_COMMON *device, union RTK_PACKET *packet_send)
00144 {
00145   uint16_t crc;
00146   uint32_t len_send;
00147   void *parg = NULL;
00148   struct udpaddr opt_udp;
00149   HRESULT hr;
00150 
00151   hr = check_conn_param(device, RTK_CHECK_SEND);
00152   if (FAILED(hr))
00153     return hr;
00154 
00155   if (packet_send == NULL)
00156     return E_INVALIDARG;
00157 
00158   if (device->type == CONN_UDP) {
00159     if (device->arg == NULL)
00160       return E_INVALIDARG;
00161     opt_udp.flag = 0;
00162     opt_udp.addr = *(struct sockaddr_in *) device->arg;
00163     parg = &opt_udp;
00164   }
00165 
00166   len_send = RTK_SIZE_HEADER + RTK_SIZE_CRC + packet_send->len;
00167   if (len_send > RTK_SIZE_PACKET) {
00168     hr = E_TOO_MUCH_DATA;
00169     goto send_end;
00170   }
00171 
00172   /* Sets CRC */
00173   crc = rtk_calc_crc(packet_send);
00174   memcpy_be(&packet_send->data[packet_send->len], &crc, RTK_SIZE_CRC);
00175 
00176   hr = device->dn_send(device->sock, (const char *) packet_send->buf, len_send,
00177       parg);
00178   if (FAILED(hr))
00179     goto send_end;
00180 
00181   send_end: return hr;
00182 }
00183 
00192 HRESULT
00193 rtk_recv(const struct CONN_PARAM_COMMON *device, union RTK_PACKET *packet_recv,
00194     int client, unsigned int retry_nak)
00195 {
00196   int flag_init = 0;
00197   unsigned int retry_cnt;
00198   uint16_t crc, crc_recv, command;
00199   uint32_t len_recv, len_recved, len_tmp;
00200   char *pos, buf_tmp[UDP_MAX_PACKET + 1] =
00201     { 0, };
00202   void *parg = NULL;
00203   struct udpaddr opt_udp;
00204   HRESULT hr;
00205 
00206   hr = check_conn_param(device, RTK_CHECK_RECV);
00207   if (FAILED(hr))
00208     return hr;
00209 
00210   if (packet_recv == NULL)
00211     return E_INVALIDARG;
00212 
00213   if (device->type == CONN_UDP) {
00214     if (device->arg == NULL)
00215       return E_INVALIDARG;
00216     opt_udp.flag = 0;
00217     parg = &opt_udp;
00218   }
00219 
00220   for (retry_cnt = 0; retry_cnt <= retry_nak; retry_cnt++) {
00221     len_recved = 0;
00222     while (1) {
00223       pos = (char *) memchr(buf_tmp, RTK_ENQ, len_recved);
00224       if (pos != NULL) {
00225         if (pos != buf_tmp) {
00226           len_recved -= ((long) pos - (long) buf_tmp);
00227           memcpy(buf_tmp, pos, len_recved);
00228         }
00229       } else {
00230         len_recved = 0;
00231       }
00232 
00233       if (len_recved >= RTK_SIZE_HEADER + RTK_SIZE_CRC)
00234         break;
00235 
00236       hr = device->dn_recv(device->sock, &buf_tmp[len_recved],
00237           UDP_MAX_PACKET - len_recved, &len_tmp, device->timeout, parg);
00238 
00239       if (device->type == CONN_UDP) {
00240         if (client || flag_init) {
00241           hr = SUCCEEDED(hr) ?
00242                   udp_check_sockaddr((struct sockaddr_in *) device->arg,
00243                       &opt_udp.addr) : hr;
00244         } else {
00245           flag_init = 1;
00246           *(struct sockaddr_in *) device->arg = opt_udp.addr;
00247         }
00248       }
00249 
00250       if (FAILED(hr))
00251         goto recv_end;
00252 
00253       len_recved += len_tmp;
00254     }
00255 
00256     len_recv = RTK_SIZE_HEADER + RTK_SIZE_CRC
00257         + ((union RTK_PACKET *) buf_tmp)->len;
00258     if (len_recv > RTK_SIZE_PACKET) {
00259       len_recved--;
00260       memcpy(buf_tmp, &buf_tmp[1], len_recved);
00261       continue;
00262     }
00263 
00264     memcpy(packet_recv->buf, buf_tmp,
00265         (len_recv < len_recved) ? len_recv : len_recved);
00266 
00267     while (len_recv > len_recved) {
00268       hr = device->dn_recv(device->sock,
00269           (char *) &packet_recv->buf[len_recved], len_recv - len_recved,
00270           &len_tmp, device->timeout, parg);
00271 
00272       if (device->type == CONN_UDP) {
00273         hr = SUCCEEDED(hr) ?
00274                 udp_check_sockaddr((struct sockaddr_in *) device->arg,
00275                     &opt_udp.addr) : hr;
00276       }
00277 
00278       if (FAILED(hr))
00279         goto recv_end;
00280 
00281       len_recved += len_tmp;
00282     }
00283 
00284     /* Calculates CRC of the received packet */
00285     crc = rtk_calc_crc(packet_recv);
00286     memcpy_be(&crc_recv, &packet_recv->data[packet_recv->len], RTK_SIZE_CRC);
00287 
00288     /* Checks CRC */
00289     if (crc != crc_recv) {
00290       /* If CRC error occurs, then send NAK packet and retry */
00291       hr = rtk_send_nak(device, packet_recv->from_id, packet_recv->to_id);
00292       if (SUCCEEDED(hr)) {
00293         if (retry_cnt == retry_nak)
00294           hr = E_INVALIDPACKET;
00295         continue;
00296       }
00297     }
00298 
00299     /* Orders to host's endian */
00300     command = packet_recv->command;
00301     memcpy_be(&packet_recv->command, &command, RTK_SIZE_COMMAND);
00302 
00303     break;
00304   }
00305 
00306 recv_end:
00307   return hr;
00308 }


bcap_core
Author(s): DENSO WAVE INCORPORATED
autogenerated on Thu Jun 6 2019 21:00:02