+ break;
+ case DEVICE_TYPE_CULFW:
+ {
+ char buf[256];
+ int i;
+
+ memset(buf, 0, sizeof(buf));
+ buf[0] = 'A';
+ buf[1] = 's';
+ for (i = 0; i < msg[0] + 1; i++) {
+ buf[2 + (i * 2)] = nibble_to_ascii((msg[i] >> 4) & 0xf);
+ buf[2 + (i * 2) + 1] = nibble_to_ascii(msg[i] & 0xf);
+ }
+ buf[2 + (i * 2) ] = '\r';
+ buf[2 + (i * 2) + 1] = '\n';
+
+ memset(rdata, 0, sizeof(struct recv_data));
+ if (culfw_send(dev->culfw, buf, 2 + (i * 2) + 1) == 0) {
+ fprintf(stderr, "culfw_send failed!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (msg[CTL] & 0x20) {
+ int cnt = 5;
+ int pfd;
+ do {
+ errno = 0;
+ pfd = culfw_poll(dev->culfw, 200);
+ if ((pfd < 0) && errno) {
+ if (errno != ETIMEDOUT) {
+ perror("\n\nculfw_poll");
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (rdata->message_type == MESSAGE_TYPE_E) {
+ if (rdata->message[TYPE] == 0x02) {
+ if (rdata->message[PAYLOAD] == 0x04) {
+ int32_t req_kNo;
+ uint8_t challenge[6];
+ uint8_t respbuf[16];
+ uint8_t *resp;
+
+ req_kNo = rdata->message[rdata->message[LEN]] / 2;
+ memcpy(challenge, &(rdata->message[PAYLOAD+1]), 6);
+
+ if (req_kNo != kNo) {
+ fprintf(stderr, "AES request for unknown key %d!\n", req_kNo);
+ } else {
+ resp = hm_sign(key, challenge, msg, NULL, respbuf);
+ if (resp) {
+ uint8_t rbuf[64];
+
+ memset(rbuf, 0, sizeof(rbuf));
+ rbuf[MSGID] = rdata->message[MSGID];
+ rbuf[CTL] = rdata->message[CTL];
+ rbuf[TYPE] = 0x03;
+ SET_SRC(rbuf, DST(rdata->message));
+ SET_DST(rbuf, SRC(rdata->message));
+ memcpy(&(rbuf[PAYLOAD]), resp, 16);
+ SET_LEN_FROM_PAYLOADLEN(rbuf, 16);
+
+ usleep(110000); /* Determined by a fair dice roll */
+ return send_hm_message(dev, rdata, rbuf);
+ }
+ }
+ } else if (rdata->message[PAYLOAD] >= 0x80 && rdata->message[PAYLOAD] <= 0x8f) {
+ fprintf(stderr, "NACK\n");
+ } else { /* ACK or ACKinfo */
+ break;
+ }
+ } else {
+ fprintf(stderr, "Unexpected message received: ");
+ for (i = 0; i < rdata->message[LEN]; i++) {
+ fprintf(stderr, "%02x", rdata->message[i+1]);
+ }
+ fprintf(stderr, "\n");
+ }
+ }
+ } while(cnt--);
+
+ if (cnt == -1) {
+ fprintf(stderr, "\nMissing ACK!\n");
+ return 0;
+ }
+ }