Пример #1
0
static void receiveCallback(struct libusb_transfer* transfer) {
    struct FreespaceReceiveTransfer* rt = (struct FreespaceReceiveTransfer*) transfer->user_data;
    struct FreespaceDevice* device = rt->device_;

    if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
        // Canceled. This only happens on cleanup. Don't report errors or resubmit.
        rt->submitted_ = 0;
        return;
    }

    if (device->receiveCallback_ != NULL || device->receiveMessageCallback_ != NULL) {
        // Using async interface, so call user back immediately.
        int rc = libusb_transfer_status_to_freespace_error(transfer->status);
        if (device->receiveCallback_ != NULL) {
            device->receiveCallback_(device->id_, (const uint8_t*) transfer->buffer, transfer->actual_length, device->receiveCookie_, rc);
        }
        if (device->receiveMessageCallback_ != NULL) {
            struct freespace_message m;
            
            rc = freespace_decode_message((const uint8_t*) transfer->buffer, transfer->actual_length, &m, device->api_->hVer_);
            if (rc == FREESPACE_SUCCESS) {
                device->receiveMessageCallback_(device->id_, &m, device->receiveMessageCookie_, FREESPACE_SUCCESS);
            } else {
                device->receiveMessageCallback_(device->id_, NULL, device->receiveMessageCookie_, rc);
            }
        }

        // Re-submit the transfer for the to get the next receive going.
        // NOTE: Can't handle any error returns here.
        libusb_submit_transfer(transfer);
    } else {
        // Using sync interface, so queue.
        rt->submitted_ = 0;
    }
}
Пример #2
0
int freespace_setReceiveMessageCallback(FreespaceDeviceId id,
                                        freespace_receiveMessageCallback callback,
                                        void* cookie) {
    struct FreespaceDevice* device = findDeviceById(id);
    int wereInSyncMode;
    int rc;

    if (device == NULL) {
        return FREESPACE_ERROR_NOT_FOUND;
    }

    wereInSyncMode = (device->receiveMessageCallback_ == NULL && device->receiveCallback_ == NULL);
    device->receiveMessageCallback_ = callback;
    device->receiveMessageCookie_ = cookie;

    if (callback != NULL && wereInSyncMode && device->state_ == FREESPACE_OPENED) {
        struct freespace_message m;
        
        // Transition from sync mode to async mode.

        // Need to run the callback on all received messages.
        struct FreespaceReceiveTransfer* rt;
        rt = &device->receiveQueue_[device->receiveQueueHead_];
        while (rt->submitted_ == 0) {
            rc = freespace_decode_message((const uint8_t*) rt->buffer_, rt->transfer_->actual_length, &m, device->api_->hVer_);
            if (rc == FREESPACE_SUCCESS) {
                callback(device->id_,
                         &m,
                         cookie,
                         libusb_transfer_status_to_freespace_error(rt->transfer_->status));
            } else {
                callback(device->id_,
                         NULL,
                         cookie,
                         rc);
            }

            rt->submitted_ = 1;
            libusb_submit_transfer(rt->transfer_);
            device->receiveQueueHead_++;
            if (device->receiveQueueHead_ >= FREESPACE_RECEIVE_QUEUE_SIZE) {
                device->receiveQueueHead_ = 0;
            }

            rt = &device->receiveQueue_[device->receiveQueueHead_];
        }
    }
    return FREESPACE_SUCCESS;
}
Пример #3
0
int freespace_readMessage(FreespaceDeviceId id,
                          struct freespace_message* message,
                          unsigned int timeoutMs) {
    int rc;
    uint8_t buffer[FREESPACE_MAX_INPUT_MESSAGE_SIZE];
    int actLen;
    struct FreespaceDeviceInfo info;
    
    rc = freespace_getDeviceInfo(id, &info);
    if (rc != FREESPACE_SUCCESS) {
        return rc;
    }
    
    rc = freespace_private_read(id, buffer, sizeof(buffer), timeoutMs, &actLen);
    
    if (rc == FREESPACE_SUCCESS) {
        return freespace_decode_message(buffer, actLen, message, info.hVer);
    } else {
        return rc;
    }
}
int freespace_private_devicePerform(struct FreespaceDeviceStruct* device) {
    int idx;
    BOOL overlappedResult;
    struct FreespaceSendStruct* send;
	int rc;
	struct freespace_message m;

    // Handle the send messages
    for (idx = 0; idx < FREESPACE_MAXIMUM_SEND_MESSAGE_COUNT; idx++) {
        send = &device->send_[idx];
        if (send->interface_ == NULL) {
            continue;
        }
        overlappedResult = GetOverlappedResult(
                                               send->interface_->handle_,
                                               &send->overlapped_,
                                               &send->numBytes_,
                                               FALSE);

        if (!overlappedResult) {
            // No message available yet.
            continue;
        } else if (send->numBytes_ != send->interface_->info_.outputReportByteLength_) {
            // Unexpected error on the sent message.
            DEBUG_PRINTF("freespace_private_devicePerform: error on message size: %d != %d\n",
                         send->numBytes_, send->interface_->info_.outputReportByteLength_);
            if (send->callback_ != NULL) {
                send->callback_(device->id_, send->cookie_, FREESPACE_ERROR_IO);
            }
        } else {
            // successfully sent message
            if (send->callback_ != NULL) {
                send->callback_(device->id_, send->cookie_, FREESPACE_SUCCESS);
            }
        }
        if (finalizeSendStruct(send, FALSE) != FREESPACE_SUCCESS) {
            DEBUG_PRINTF("freespace_private_devicePerform: error while sending message");
        }
    }

    // Call GetOverlappedResult() on everything to check what
    // messages were received.
    for (idx = 0; idx < device->handleCount_; idx++) {
        struct FreespaceSubStruct* s = &device->handle_[idx];

        if (s->readStatus_) {
            int lastErr;
            BOOL bResult = GetOverlappedResult(
                                               s->handle_,                 /* handle to device */
                                               &s->readOverlapped_,        /* long pointer to an OVERLAPPED structure */
                                               &s->readBufferSize,         /* returned buffer size */
                                               FALSE);
            lastErr = GetLastError();
            if (bResult) {
                // Got something, so report it.
                if (device->receiveCallback_ || device->receiveMessageCallback_) {
					if (device->receiveCallback_) {
						device->receiveCallback_(device->id_, (char *) (s->readBuffer), s->readBufferSize, device->receiveCookie_, FREESPACE_SUCCESS);
					}
					if (device->receiveMessageCallback_) {
						rc = freespace_decode_message((char *) (s->readBuffer), s->readBufferSize, &m, device->hVer_);
						if (rc == FREESPACE_SUCCESS) {
							device->receiveMessageCallback_(device->id_, &m, device->receiveMessageCookie_, FREESPACE_SUCCESS);
						} else {
							device->receiveMessageCallback_(device->id_, NULL, device->receiveMessageCookie_, rc);
							DEBUG_PRINTF("freespace_decode_message failed with code %d\n", rc);
						}
					}
				}
                s->readStatus_ = FALSE;
            } else if (lastErr != ERROR_IO_INCOMPLETE) {
                // Something severe happened to our device!
				DEBUG_PRINTF("freespace_private_devicePerform : Error on %d : %d\n", idx, lastErr);
                if (device->receiveCallback_) {
				    device->receiveCallback_(device->id_, NULL, 0, device->receiveCookie_, FREESPACE_ERROR_NO_DATA);
				}
				if (device->receiveMessageCallback_) {
				    device->receiveMessageCallback_(device->id_, NULL, device->receiveMessageCookie_, FREESPACE_ERROR_NO_DATA);
				}
                return handleDeviceFailure(device, lastErr);
            }
        }
    }

    // Re-initiate the ReadFile calls for the next go around.
    return initiateAsyncReceives(device);
}
static int initiateAsyncReceives(struct FreespaceDeviceStruct* device) {
    int idx;
    int funcRc = FREESPACE_SUCCESS;
    int rc;
	struct freespace_message m;

    // If no callback or not opened, then don't need to request to receive anything.
    if (!device->isOpened_ || (device->receiveCallback_ == NULL && device->receiveMessageCallback_ == NULL)) {
        return FREESPACE_SUCCESS;
    }

    // Initialize a new read operation on all handles that need it.
    for (idx = 0; idx < device->handleCount_; idx++) {
        struct FreespaceSubStruct* s = &device->handle_[idx];
        if (!s->readStatus_) {
            for (;;) {
                BOOL bResult = ReadFile(
					s->handle_,                 /* handle to device */
					s->readBuffer,              /* IN report buffer to fill */
					s->info_.inputReportByteLength_,  /* input buffer size */
					&s->readBufferSize,         /* returned buffer size */
					&s->readOverlapped_ );      /* long pointer to an OVERLAPPED structure */
                if (bResult) {
                    // Got something, so report it.
					if (device->receiveCallback_ || device->receiveMessageCallback_) {
						if (device->receiveCallback_) {
							device->receiveCallback_(device->id_, (char *) (s->readBuffer), s->readBufferSize, device->receiveCookie_, FREESPACE_SUCCESS);
						}
						if (device->receiveMessageCallback_) {
							rc = freespace_decode_message((char *) (s->readBuffer), s->readBufferSize, &m, device->hVer_);
							if (rc == FREESPACE_SUCCESS) {
								device->receiveMessageCallback_(device->id_, &m, device->receiveMessageCookie_, FREESPACE_SUCCESS);
							} else {
								device->receiveMessageCallback_(device->id_, NULL, device->receiveMessageCookie_, rc);
								DEBUG_PRINTF("freespace_decode_message failed with code %d\n", rc);
							}
						}
					} else {
                        // If no receiveCallback, then freespace_setReceiveCallback was called to stop
                        // receives from within the receiveCallback. Bail out to let it do its thing.
                        return FREESPACE_SUCCESS;
                    }
                } else {
                    // Error or would block - check below.
                    break;
                }
            }

            rc = GetLastError();
            if (rc == ERROR_IO_PENDING) {
                // We got a ReadFile to block, so mark it.
                s->readStatus_ = TRUE;
            } else {
                // Something severe happened to our device!
				if (device->receiveCallback_) {
				    device->receiveCallback_(device->id_, NULL, 0, device->receiveCookie_, rc);
				}
				if (device->receiveMessageCallback_) {
				    device->receiveMessageCallback_(device->id_, NULL, device->receiveMessageCookie_, rc);
				}
                DEBUG_PRINTF("initiateAsyncReceives : Error on %d : %d\n", idx, rc);
                return handleDeviceFailure(device, rc);
            }
        }
    }

    return funcRc;
}