00001
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "tm_config.h"
00031 #ifdef TMR_ENABLE_LLRP_TRANSPORT
00032
00033 #include <errno.h>
00034 #include <netdb.h>
00035 #include <stddef.h>
00036 #include <string.h>
00037 #include <stdio.h>
00038 #include <sys/types.h>
00039 #include <sys/stat.h>
00040 #include <sys/select.h>
00041 #include <sys/socket.h>
00042
00043 #include "tm_reader.h"
00044 #include "tmr_utils.h"
00045
00046 #define LLRP_TYPE_CLOSE_CONNECTION_RESPONSE 4
00047 #define LLRP_TYPE_CLOSE_CONNECTION 14
00048 #define LLRP_TYPE_READER_EVENT_NOTIFICATION 63
00049 #define LLRP_TYPE_CUSTOM_MESSAGE 1023
00050
00051 #define LLRP_PARAM_READER_EVENT_NOTIFICATION_DATA 246
00052 #define LLRP_PARAM_CONNECTION_ATTEMPT_EVENT 256
00053 #define LLRP_PARAM_CONNECTION_ATTEMPT_EVENT_SUCCESS 0
00054 #define LLRP_PARAM_CONNECTION_ATTEMPT_EVENT_ANOTHER 4
00055 #define LLRP_PARAM_CONNECTION_CLOSE_EVENT 257
00056 #define LLRP_PARAM_LLRP_STATUS 287
00057 #define LLRP_STATUS_M_SUCCESS 0
00058
00059 #define LLRP_TM_ID 0x67ba
00060 #define LLRP_TM_TYPE_DATA_REQUEST 1
00061 #define LLRP_TM_TYPE_DATA_RESPONSE 2
00062 #define LLRP_TM_TYPE_CONTROL_REQUEST 3
00063 #define LLRP_TM_TYPE_CONTROL_RESPONSE 4
00064 #define LLRP_TM_CONTROL_POWER 1
00065 #define LLRP_TM_CONTROL_BAUD 2
00066
00067 struct llrp_message
00068 {
00069 uint32_t len;
00070
00071 uint32_t id;
00072 uint8_t *value, *rawbuf;
00073 uint8_t ver;
00074 uint16_t type;
00075 };
00076
00077 struct llrp_param
00078 {
00079 uint16_t type;
00080 uint16_t len;
00081
00082 uint8_t *value;
00083 };
00084
00085
00086
00087 static TMR_Status
00088 llrp_receive_message(int sockfd, struct llrp_message *message, uint8_t *buf,
00089 uint16_t buflen, uint32_t timeout)
00090 {
00091 int ret;
00092 ssize_t msgsize, retlen;
00093 struct timeval timeo;
00094
00095 timeo.tv_sec = timeout / 1000;
00096 timeo.tv_usec = 1000 * (timeout % 1000);
00097
00098 ret = setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
00099 if (-1 == ret)
00100 {
00101 return TMR_ERROR_COMM_ERRNO(errno);
00102 }
00103
00104 msgsize = 0;
00105 do
00106 {
00107 retlen = recv(sockfd, buf + msgsize, buflen - msgsize, 0);
00108 if (-1 == retlen)
00109 {
00110 if (EAGAIN == errno)
00111 {
00112 return TMR_ERROR_TIMEOUT;
00113 }
00114 else
00115 {
00116 return TMR_ERROR_COMM_ERRNO(errno);
00117 }
00118 }
00119 msgsize += retlen;
00120 }
00121 while ((msgsize < 10 || msgsize < GETU32AT(buf, 2)) && msgsize < buflen);
00122
00123 message->ver = (GETU8AT(buf, 0) >> 2) & 0x7;
00124 message->type = GETU16AT(buf, 0) & 0x3ff;
00125 message->len = GETU32AT(buf,2) - 10;
00126 message->id = GETU32AT(buf,6);
00127 message->rawbuf = buf;
00128 message->value = buf + 10;
00129
00130 return TMR_SUCCESS;
00131 }
00132
00133 static TMR_Status
00134 llrp_send_message(int sockfd, struct llrp_message *message)
00135 {
00136 uint8_t *buf;
00137 uint8_t i;
00138 uint16_t msgsize;
00139 ssize_t retlen;
00140
00141 buf = message->rawbuf;
00142 i = 0;
00143 SETU16(buf, i, (message->ver << 10) | message->type);
00144 SETU32(buf, i, 10 + message->len);
00145 SETU32(buf, i, message->id);
00146
00147 msgsize = 10 + message->len;
00148
00149 while (msgsize > 0)
00150 {
00151 retlen = send(sockfd, buf, msgsize, 0);
00152 if (-1 == retlen)
00153 {
00154 return TMR_ERROR_COMM_ERRNO(errno);
00155 }
00156 buf += retlen;
00157 msgsize -= retlen;
00158 }
00159 return TMR_SUCCESS;
00160 }
00161
00162
00163
00164
00165
00166
00167 static int llrp_tv_param_len[] =
00168 {
00169
00170 -1, 3, 9, 9, 9, 9, 2, 3, 3, 5,
00171 3, 3, 3, 13, 3, 3, 5, 3, 5
00172 };
00173
00174 static TMR_Status
00175 llrp_get_param(uint8_t *buf, uint16_t buflen, uint16_t paramtype,
00176 struct llrp_param *param)
00177 {
00178 uint16_t offset, type, headersize, len;
00179
00180 offset = 0;
00181 while (offset < buflen)
00182 {
00183 type = GETU16AT(buf, offset);
00184 if (type & 0x8000)
00185 {
00186 type = (type >> 8) & 0x7f;
00187 if (type > numberof(llrp_tv_param_len) ||
00188 -1 == llrp_tv_param_len[type])
00189 {
00190 return TMR_ERROR_LLRP;
00191 }
00192 headersize = 1;
00193 len = llrp_tv_param_len[type];
00194 }
00195 else
00196 {
00197 type = type & 0x3ff;
00198 headersize = 4;
00199 len = GETU16AT(buf, offset+2);
00200 }
00201 if (type == paramtype)
00202 {
00203 param->type = type;
00204 param->len = len - headersize;
00205 param->value = buf + offset + headersize;
00206 return TMR_SUCCESS;
00207 }
00208 offset += len;
00209 }
00210
00211 return TMR_ERROR_NOT_FOUND;
00212 }
00213
00214 static TMR_Status
00215 llrp_check_success(uint8_t *msgptr, uint16_t msglen)
00216 {
00217 struct llrp_param param;
00218 TMR_Status ret;
00219
00220 ret = llrp_get_param(msgptr, msglen,
00221 LLRP_PARAM_LLRP_STATUS, ¶m);
00222 if (TMR_SUCCESS != ret)
00223 return TMR_ERROR_LLRP;
00224
00225 if (LLRP_STATUS_M_SUCCESS != GETU16AT(param.value, 0))
00226 return TMR_ERROR_LLRP;
00228 return TMR_SUCCESS;
00229 }
00230
00231
00232
00233
00234
00235 static TMR_Status
00236 llrp_receive_message_filtered(int sockfd, struct llrp_message *message,
00237 uint8_t *buf, uint16_t buflen, uint32_t timeout)
00238 {
00239 struct llrp_param param;
00240 TMR_Status ret;
00241 uint16_t status;
00242
00243 while (1)
00244 {
00245 ret = llrp_receive_message(sockfd, message, buf, buflen, timeout);
00246 if (TMR_SUCCESS != ret)
00247 {
00248 return ret;
00249 }
00250
00251 if (LLRP_TYPE_READER_EVENT_NOTIFICATION != message->type)
00252 break;
00253
00254 ret = llrp_get_param(message->value, message->len,
00255 LLRP_PARAM_READER_EVENT_NOTIFICATION_DATA, ¶m);
00256 if (TMR_ERROR_NOT_FOUND == ret)
00257 {
00258
00259 break;
00260 }
00261 else if (TMR_SUCCESS != ret)
00262 {
00263 return ret;
00264 }
00265
00266 ret = llrp_get_param(param.value, param.len,
00267 LLRP_PARAM_CONNECTION_ATTEMPT_EVENT, ¶m);
00268 if (TMR_ERROR_NOT_FOUND == ret)
00269 {
00270
00271 break;
00272 }
00273 else if (TMR_SUCCESS != ret)
00274 {
00275 return ret;
00276 }
00277
00278 status = GETU16AT(param.value, 0);
00279 if (LLRP_PARAM_CONNECTION_ATTEMPT_EVENT_ANOTHER != status)
00280 {
00281 break;
00282 }
00283 }
00284
00285 return TMR_SUCCESS;
00286 }
00287
00288
00289 static TMR_Status
00290 s_open(TMR_SR_SerialTransport *this)
00291 {
00292 TMR_Status ret;
00293 TMR_SR_LlrpEapiTransportContext *context;
00294 struct llrp_message message;
00295 struct llrp_param param;
00296 uint8_t buf[270];
00297 uint16_t status;
00298
00299 context = this->cookie;
00300
00301 if (-1 == connect(context->socket, (struct sockaddr *)&context->addr,
00302 context->addrlen))
00303 {
00304 return TMR_ERROR_COMM_ERRNO(errno);
00305 }
00306
00307 ret = llrp_receive_message(context->socket, &message, buf, sizeof(buf), 0);
00308 if (TMR_SUCCESS != ret)
00309 {
00310 return ret;
00311 }
00312
00313 if (LLRP_TYPE_READER_EVENT_NOTIFICATION != message.type)
00314 {
00315 return TMR_ERROR_LLRP;
00316 }
00317
00318 ret = llrp_get_param(message.value, message.len,
00319 LLRP_PARAM_READER_EVENT_NOTIFICATION_DATA, ¶m);
00320 if (TMR_SUCCESS != ret)
00321 {
00322 return ret;
00323 }
00324 ret = llrp_get_param(param.value, param.len,
00325 LLRP_PARAM_CONNECTION_ATTEMPT_EVENT, ¶m);
00326 if (TMR_SUCCESS != ret)
00327 {
00328 return ret;
00329 }
00330
00331 status = GETU16AT(param.value,0);
00332 if (LLRP_PARAM_CONNECTION_ATTEMPT_EVENT_SUCCESS != status)
00333 {
00334 return TMR_ERROR_LLRP;
00335 }
00336
00337 if (true == context->powerCycleAtOpen)
00338 {
00339 ret = TMR_LlrpEapiPowerCycle(this);
00340 if (TMR_SUCCESS != ret)
00341 {
00342 return ret;
00343 }
00344 }
00345
00346 return TMR_SUCCESS;
00347 }
00348
00349 static TMR_Status
00350 s_sendBytes(TMR_SR_SerialTransport *this, uint32_t length,
00351 uint8_t* bytes, const uint32_t timeoutMs)
00352 {
00353 TMR_SR_LlrpEapiTransportContext *context;
00354 struct llrp_message message;
00355 uint8_t buf[270];
00356 int i;
00357
00358 context = this->cookie;
00359 i = 0;
00360
00361 message.ver = 1;
00362 message.type = LLRP_TYPE_CUSTOM_MESSAGE;
00363 message.id = context->sequenceId++;
00364 message.rawbuf = buf;
00365 message.value = buf + 10;
00366
00367 SETU32(message.value, i, LLRP_TM_ID);
00368 SETU8(message.value, i, LLRP_TM_TYPE_DATA_REQUEST);
00369 memcpy(message.value + i, bytes, length);
00370 message.len = length + i;
00371
00372 return llrp_send_message(context->socket, &message);
00373 }
00374
00375 static TMR_Status
00376 s_receiveBytes(TMR_SR_SerialTransport *this, uint32_t length,
00377 uint32_t* messageLength, uint8_t* bytes, const uint32_t timeoutMs)
00378 {
00379 TMR_SR_LlrpEapiTransportContext *context;
00380 struct llrp_message message;
00381 TMR_Status ret;
00382 uint16_t copylen;
00383 uint8_t buf[270];
00384
00385 *messageLength = 0;
00386 context = this->cookie;
00387
00388 if (length > 255)
00389 {
00390 return TMR_ERROR_INVALID;
00391 }
00392
00393 if (context->buflen > 0)
00394 {
00395 copylen = context->buflen;
00396 if (copylen > length)
00397 {
00398 copylen = length;
00399 }
00400 memcpy(bytes, context->buf + context->bufstart, copylen);
00401 context->buflen -= copylen;
00402 context->bufstart += copylen;
00403 bytes += copylen;
00404 *messageLength += copylen;
00405 length -= copylen;
00406 }
00407
00408 if (length == 0)
00409 {
00410 return TMR_SUCCESS;
00411 }
00412
00413 ret = llrp_receive_message_filtered(context->socket, &message, buf,
00414 sizeof(buf), timeoutMs);
00415 if (TMR_SUCCESS != ret)
00416 {
00417 return ret;
00418 }
00419
00420 if (LLRP_TM_ID != GETU32AT(message.value, 0))
00421 {
00422 return TMR_ERROR_LLRP;
00423 }
00424 if (LLRP_TM_TYPE_DATA_RESPONSE != GETU8AT(message.value, 4))
00425 {
00426 return TMR_ERROR_LLRP;
00427 }
00428
00429 copylen = message.len - 5;
00430 if (copylen > length)
00431 {
00432
00433 memcpy(context->buf, message.value + 5 + length, copylen - length);
00434 context->bufstart = 0;
00435 context->buflen = copylen - length;
00436 copylen = length;
00437 }
00438 memcpy(bytes, message.value + 5, copylen);
00439
00440 return TMR_SUCCESS;
00441 }
00442
00443 static TMR_Status
00444 s_setBaudRate(TMR_SR_SerialTransport *this, uint32_t rate)
00445 {
00446 TMR_Status ret;
00447 TMR_SR_LlrpEapiTransportContext *context;
00448 struct llrp_message message;
00449 uint8_t buf[270];
00450 int i;
00451
00452 context = this->cookie;
00453 i = 0;
00454
00455 message.ver = 1;
00456 message.type = LLRP_TYPE_CUSTOM_MESSAGE;
00457 message.id = context->sequenceId++;
00458 message.rawbuf = buf;
00459 message.value = buf + 10;
00460
00461 SETU32(message.value, i, LLRP_TM_ID);
00462 SETU8(message.value, i, LLRP_TM_TYPE_CONTROL_REQUEST);
00463 SETU16(message.value, i, LLRP_TM_CONTROL_BAUD);
00464 SETU32(message.value, i, rate);
00465
00466 message.len = i;
00467
00468 ret = llrp_send_message(context->socket, &message);
00469 if (TMR_SUCCESS != ret)
00470 {
00471 return ret;
00472 }
00473
00474 ret = llrp_receive_message_filtered(context->socket, &message, buf,
00475 sizeof(buf), 0);
00476
00477 if ((LLRP_TYPE_CUSTOM_MESSAGE != message.type) ||
00478 (LLRP_TM_ID != GETU32AT(message.value, 0)))
00479 {
00480 return TMR_ERROR_LLRP;
00481 }
00482
00483 if (LLRP_TM_TYPE_CONTROL_RESPONSE != GETU8AT(message.value, 4))
00484 {
00485 return TMR_ERROR_LLRP;
00486 }
00487
00488 return llrp_check_success(message.value + 5, message.len - 5);
00489 }
00490
00491 static TMR_Status
00492 s_shutdown(TMR_SR_SerialTransport *this)
00493 {
00494 TMR_Status ret;
00495 TMR_SR_LlrpEapiTransportContext *context;
00496 struct llrp_message message;
00497 uint8_t buf[270];
00498
00499 context = this->cookie;
00500
00501 message.ver = 1;
00502 message.type = LLRP_TYPE_CLOSE_CONNECTION;
00503 message.id = context->sequenceId++;
00504 message.rawbuf = buf;
00505 message.value = buf + 10;
00506 message.len = 0;
00507
00508 ret = llrp_send_message(context->socket, &message);
00509 if (TMR_SUCCESS != ret)
00510 {
00511 return ret;
00512 }
00513
00514 ret = llrp_receive_message_filtered(context->socket, &message, buf,
00515 sizeof(buf), 0);
00516 if (TMR_SUCCESS != ret)
00517 {
00518 return ret;
00519 }
00520
00521 if (LLRP_TYPE_CLOSE_CONNECTION_RESPONSE != message.type)
00522 {
00523 return TMR_ERROR_LLRP;
00524 }
00525
00526 return llrp_check_success(message.value, message.len);
00527 }
00528
00529 static TMR_Status
00530 s_flush(TMR_SR_SerialTransport *this)
00531 {
00532
00533 return TMR_SUCCESS;
00534 }
00535
00536
00537 TMR_Status
00538 TMR_LlrpEapiPowerCycle(TMR_SR_SerialTransport *this)
00539 {
00540 TMR_Status ret;
00541 TMR_SR_LlrpEapiTransportContext *context;
00542 struct llrp_message message;
00543 uint8_t buf[270];
00544 int i;
00545
00546 context = this->cookie;
00547 i = 0;
00548
00549 message.ver = 1;
00550 message.type = LLRP_TYPE_CUSTOM_MESSAGE;
00551 message.id = context->sequenceId++;
00552 message.rawbuf = buf;
00553 message.value = buf + 10;
00554
00555 SETU32(message.value, i, LLRP_TM_ID);
00556 SETU8(message.value, i, LLRP_TM_TYPE_CONTROL_REQUEST);
00557 SETU16(message.value, i, LLRP_TM_CONTROL_POWER);
00558
00559 message.len = i;
00560
00561 ret = llrp_send_message(context->socket, &message);
00562 if (TMR_SUCCESS != ret)
00563 {
00564 return ret;
00565 }
00566 ret = llrp_receive_message(context->socket, &message, buf, sizeof(buf), 0);
00567
00568 if ((LLRP_TYPE_CUSTOM_MESSAGE != message.type) ||
00569 (LLRP_TM_ID != GETU32AT(message.value, 0)))
00570 {
00571 return TMR_ERROR_LLRP;
00572 }
00573 if (LLRP_TM_TYPE_CONTROL_RESPONSE != GETU8AT(message.value, 4))
00574 {
00575 return TMR_ERROR_LLRP;
00576 }
00577
00578 return llrp_check_success(message.value + 5, message.len - 5);
00579 }
00580
00581 TMR_Status
00582 TMR_SR_LlrpEapiTransportInit(TMR_SR_SerialTransport *transport,
00583 TMR_SR_LlrpEapiTransportContext *context,
00584 const char *host, int port, bool powerCycleAtOpen)
00585 {
00586 int ret, sfd;
00587 struct addrinfo hints;
00588 struct addrinfo *result, *rp;
00589 char portnum[12];
00590
00591 memset(&hints, 0, sizeof(struct addrinfo));
00592 hints.ai_family = AF_UNSPEC;
00593 hints.ai_socktype = SOCK_STREAM;
00594 #ifdef AI_ADDRCONFIG
00595 hints.ai_flags = AI_ADDRCONFIG;
00596 #else
00597 hints.ai_flags = 0;
00598 #endif
00599
00600 sprintf(portnum, "%d", port);
00601 ret = getaddrinfo(host, portnum, &hints, &result);
00602 if (ret != 0)
00603 {
00604 return TMR_ERROR_NO_HOST;
00605 }
00606
00607 for (rp = result; rp != NULL; rp = rp->ai_next)
00608 {
00609 sfd = socket(rp->ai_family, rp->ai_socktype,
00610 rp->ai_protocol);
00611 if (-1 != sfd)
00612 {
00613 break;
00614 }
00615 }
00616
00617 if (NULL == rp)
00618 {
00619 ret = TMR_ERROR_COMM_ERRNO(errno);
00620 goto out;
00621 }
00622
00623 context->socket = sfd;
00624 memcpy(&context->addr, rp->ai_addr, rp->ai_addrlen);
00625 context->addrlen = rp->ai_addrlen;
00626 context->powerCycleAtOpen = powerCycleAtOpen;
00627 context->sequenceId = 1;
00628 context->bufstart = 0;
00629 context->buflen = 0;
00630
00631 transport->cookie = context;
00632 transport->open = s_open;
00633 transport->sendBytes = s_sendBytes;
00634 transport->receiveBytes = s_receiveBytes;
00635 transport->setBaudRate = s_setBaudRate;
00636 transport->shutdown = s_shutdown;
00637 transport->flush = s_flush;
00638 ret = TMR_SUCCESS;
00639
00640 out:
00641 freeaddrinfo(result);
00642 return ret;
00643 }
00644
00645 #endif