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
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
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
00285 crc = rtk_calc_crc(packet_recv);
00286 memcpy_be(&crc_recv, &packet_recv->data[packet_recv->len], RTK_SIZE_CRC);
00287
00288
00289 if (crc != crc_recv) {
00290
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
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 }