diff options
Diffstat (limited to 'video-ps3eye/PS3EYEDriver/urb.cpp')
-rw-r--r-- | video-ps3eye/PS3EYEDriver/urb.cpp | 307 |
1 files changed, 0 insertions, 307 deletions
diff --git a/video-ps3eye/PS3EYEDriver/urb.cpp b/video-ps3eye/PS3EYEDriver/urb.cpp deleted file mode 100644 index 7e931490..00000000 --- a/video-ps3eye/PS3EYEDriver/urb.cpp +++ /dev/null @@ -1,307 +0,0 @@ -#include "urb.hpp" -#include "singleton.hpp" -#include "frame-queue.hpp" -#include "internal.hpp" - -#include <algorithm> -#include <cstring> - -/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ -enum { - UVC_STREAM_EOH = (1 << 7), - UVC_STREAM_ERR = (1 << 6), - UVC_STREAM_STI = (1 << 5), - UVC_STREAM_RES = (1 << 4), - UVC_STREAM_SCR = (1 << 3), - UVC_STREAM_PTS = (1 << 2), - UVC_STREAM_EOF = (1 << 1), - UVC_STREAM_FID = (1 << 0), -}; - -void USB_CALLBACK URBDesc::transfer_completed_callback(struct libusb_transfer *xfr) -{ - URBDesc *urb = reinterpret_cast<URBDesc*>(xfr->user_data); - enum libusb_transfer_status status = xfr->status; - - switch (status) - { - case LIBUSB_TRANSFER_TIMED_OUT: - urb->frame_add(URBDesc::DISCARD_PACKET, nullptr, 0); - break; - case LIBUSB_TRANSFER_COMPLETED: - urb->pkt_scan(xfr->buffer, xfr->actual_length); - if (int error = libusb_submit_transfer(xfr); error < 0) { - debug("libusb_submit_transfer(%d), exiting\n", error); - urb->close_transfers(); - } - break; - default: - debug("transfer 0x%p failed(%d)\n", (void*)xfr, status); - urb->close_transfers(); - break; - case LIBUSB_TRANSFER_CANCELLED: - urb->transfer_cancelled(); - debug("transfer 0x%p cancelled\n", (void*)xfr); - break; - } - - //debug("length:%u, actual_length:%u\n", xfr->length, xfr->actual_length); -} - -URBDesc::~URBDesc() -{ - close_transfers(); - free_transfers(); -} - -bool URBDesc::start_transfers(libusb_device_handle* handle, uint32_t curr_frame_size) -{ - // Initialize the frame queue - frame_size = curr_frame_size; - frame_queue = std::make_shared<FrameQueue>(frame_size); - - // Initialize the current frame pointer to the start of the buffer; it will be updated as frames are completed and pushed onto the frame queue - cur_frame_start = frame_queue->ptr(); - cur_frame_data_len = 0; - - // Find the bulk transfer endpoint - uint8_t bulk_endpoint = find_ep(libusb_get_device(handle)); - libusb_clear_halt(handle, bulk_endpoint); - - // Allocate the transfer buffer - memset(transfer_buffer, 0, sizeof(transfer_buffer)); - - bool res = true; - for (int index = 0; index < NUM_TRANSFERS; ++index) - { - // Create & submit the transfer - xfers[index] = libusb_alloc_transfer(0); - - if (!xfers[index]) - { - debug("libusb_alloc_transfer failed\n"); - res = false; - break; - } - - libusb_fill_bulk_transfer(xfers[index], handle, bulk_endpoint, transfer_buffer + index * TRANSFER_SIZE, TRANSFER_SIZE, transfer_completed_callback, reinterpret_cast<void*>(this), 0); - - if (int status = libusb_submit_transfer(xfers[index]); status != LIBUSB_SUCCESS) - { - debug("libusb_submit_transfer status %d\n", status); - libusb_free_transfer(xfers[index]); - xfers[index] = nullptr; - res = false; - break; - } - - num_active_transfers++; - } - - last_pts = 0; - last_fid = 0; - - USBMgr::instance().camera_started(); - - return res; -} - -void URBDesc::close_transfers() -{ - std::unique_lock<std::mutex> lock(num_active_transfers_mutex); - - if (teardown) - return; - teardown = true; - - // Cancel any pending transfers - for (int i = 0; i < NUM_TRANSFERS; ++i) - { - if (!xfers[i]) - continue; - enum libusb_error status = (enum libusb_error)libusb_cancel_transfer(xfers[i]); - if (status) - debug("libusb_cancel_transfer error(%d) %s\n", status, libusb_strerror(status)); - } - num_active_transfers_condition.notify_one(); -} - -void URBDesc::free_transfers() -{ - std::unique_lock<std::mutex> lock(num_active_transfers_mutex); - - // Wait for cancelation to finish - num_active_transfers_condition.wait(lock, [this] { return num_active_transfers == 0; }); - - // Free completed transfers - for (libusb_transfer*& xfer : xfers) - { - if (!xfer) - continue; - libusb_free_transfer(xfer); - xfer = nullptr; - } - - USBMgr::instance().camera_stopped(); -} - -int URBDesc::transfer_cancelled() -{ - std::lock_guard<std::mutex> lock(num_active_transfers_mutex); - int refcnt = --num_active_transfers; - num_active_transfers_condition.notify_one(); - - return refcnt; -} - -void URBDesc::frame_add(enum gspca_packet_type packet_type, const uint8_t* data, int len) -{ - if (packet_type == FIRST_PACKET) - cur_frame_data_len = 0; - else - switch(last_packet_type) // ignore warning. - { - case DISCARD_PACKET: - if (packet_type == LAST_PACKET) { - last_packet_type = packet_type; - cur_frame_data_len = 0; - } - return; - case LAST_PACKET: - return; - default: - break; - } - - /* append the packet to the frame buffer */ - if (len > 0) - { - if(cur_frame_data_len + len > frame_size) - { - packet_type = DISCARD_PACKET; - cur_frame_data_len = 0; - } else { - memcpy(cur_frame_start+cur_frame_data_len, data, (size_t) len); - cur_frame_data_len += len; - } - } - - last_packet_type = packet_type; - - if (packet_type == LAST_PACKET) { - cur_frame_data_len = 0; - cur_frame_start = frame_queue->Enqueue(); - //debug("frame completed %d\n", frame_complete_ind); - } -} - -void URBDesc::pkt_scan(uint8_t* data, int len) -{ - uint32_t this_pts; - uint16_t this_fid; - int remaining_len = len; - constexpr int payload_len = 2048; // bulk type - - do { - len = std::min(remaining_len, payload_len); - - /* Payloads are prefixed with a UVC-style header. We - consider a frame to start when the FID toggles, or the PTS - changes. A frame ends when EOF is set, and we've received - the correct number of bytes. */ - - /* Verify UVC header. Header length is always 12 */ - if (data[0] != 12 || len < 12) { - debug("bad header\n"); - goto discard; - } - - /* Check errors */ - if (data[1] & UVC_STREAM_ERR) { - debug("payload error\n"); - goto discard; - } - - /* Extract PTS and FID */ - if (!(data[1] & UVC_STREAM_PTS)) { - debug("PTS not present\n"); - goto discard; - } - - this_pts = (data[5] << 24) | (data[4] << 16) | (data[3] << 8) | data[2]; - this_fid = (uint16_t) ((data[1] & UVC_STREAM_FID) ? 1 : 0); - - /* If PTS or FID has changed, start a new frame. */ - if (this_pts != last_pts || this_fid != last_fid) { - if (last_packet_type == INTER_PACKET) - { - /* The last frame was incomplete, so don't keep it or we will glitch */ - frame_add(DISCARD_PACKET, nullptr, 0); - } - last_pts = this_pts; - last_fid = this_fid; - frame_add(FIRST_PACKET, data + 12, len - 12); - } /* If this packet is marked as EOF, end the frame */ - else if (data[1] & UVC_STREAM_EOF) - { - last_pts = 0; - if (cur_frame_data_len + len - 12 != frame_size) - goto discard; - frame_add(LAST_PACKET, data + 12, len - 12); - } else { - /* Add the data from this payload */ - frame_add(INTER_PACKET, data + 12, len - 12); - } - - /* Done this payload */ - goto scan_next; - -discard: - /* Discard data until a new frame starts. */ - frame_add(DISCARD_PACKET, nullptr, 0); -scan_next: - remaining_len -= len; - data += len; - } while (remaining_len > 0); -} - -/* - * look for an input transfer endpoint in an alternate setting - * libusb_endpoint_descriptor - */ -uint8_t URBDesc::find_ep(struct libusb_device *device) -{ - const struct libusb_interface_descriptor *altsetting = nullptr; - const struct libusb_endpoint_descriptor *ep; - struct libusb_config_descriptor *config = nullptr; - int i; - uint8_t ep_addr = 0; - - libusb_get_active_config_descriptor(device, &config); - - if (!config) return 0; - - for (i = 0; i < config->bNumInterfaces; i++) { - altsetting = config->interface[i].altsetting; - if (altsetting[0].bInterfaceNumber == 0) { - break; - } - } - - if (altsetting) - for (i = 0; i < altsetting->bNumEndpoints; i++) { - ep = &altsetting->endpoint[i]; - if ((ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK - && ep->wMaxPacketSize != 0) - { - ep_addr = ep->bEndpointAddress; - break; - } - } - - libusb_free_config_descriptor(config); - - return ep_addr; -} - - |