static int usb_send_cmd_packet(uint8_t *packet, int size){ int r; if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) return -1; // async libusb_fill_control_setup(hci_cmd_buffer, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, 0, 0, 0, size); memcpy(hci_cmd_buffer + LIBUSB_CONTROL_SETUP_SIZE, packet, size); // prepare transfer int completed = 0; libusb_fill_control_transfer(command_out_transfer, handle, hci_cmd_buffer, async_callback, &completed, 0); command_out_transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER; // update stata before submitting transfer usb_command_active = 1; // submit transfer r = libusb_submit_transfer(command_out_transfer); if (r < 0) { usb_command_active = 0; log_error("Error submitting cmd transfer %d", r); return -1; } return 0; }
static void sm_write_reg(struct fpi_ssm *ssm, unsigned char reg, unsigned char value) { struct fp_img_dev *dev = ssm->priv; struct libusb_transfer *transfer = libusb_alloc_transfer(0); unsigned char *data; int r; if (!transfer) { fpi_ssm_mark_aborted(ssm, -ENOMEM); return; } fp_dbg("set %02x=%02x", reg, value); data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE); libusb_fill_control_setup(data, CTRL_OUT, reg, value, 0, 0); libusb_fill_control_transfer(transfer, dev->udev, data, sm_write_reg_cb, ssm, CTRL_TIMEOUT); r = libusb_submit_transfer(transfer); if (r < 0) { g_free(data); libusb_free_transfer(transfer); fpi_ssm_mark_aborted(ssm, r); } }
static void sm_exec_cmd(struct fpi_ssm *ssm, unsigned char cmd, unsigned char param) { struct fp_img_dev *dev = ssm->priv; struct libusb_transfer *transfer = libusb_alloc_transfer(0); unsigned char *data; int r; if (!transfer) { fpi_ssm_mark_aborted(ssm, -ENOMEM); return; } fp_dbg("cmd %02x param %02x", cmd, param); data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE); libusb_fill_control_setup(data, CTRL_IN, cmd, param, 0, 0); libusb_fill_control_transfer(transfer, dev->udev, data, sm_exec_cmd_cb, ssm, CTRL_TIMEOUT); r = libusb_submit_transfer(transfer); if (r < 0) { g_free(data); libusb_free_transfer(transfer); fpi_ssm_mark_aborted(ssm, r); } }
void cp_usb_async_read(struct cp_usb_async *cp, uint8_t *valuep) { int p; int ret; if (cp->p == MAX_OUTSTANDING) cp_usb_async_sync(cp); p = cp->p; if (!cp->packet[p].transfer) cp->packet[p].transfer = libusb_alloc_transfer(0); cp->packet[p].valuep = valuep; cp->packet[p].direction = packet_read; libusb_fill_control_setup(cp->packet[p].data, 0xc0, /* request */ 0xff, /* request type */ 0x00c2, /* value */ 0, /* index */ 1); /* length */ libusb_fill_control_transfer(cp->packet[p].transfer, cp->handle, cp->packet[p].data, cp_usb_async_transfer_callback, cp, CP_TIMEOUT); ccdbg_debug(CC_DEBUG_USB_ASYNC, "Read packet %d\n", p); ret = libusb_submit_transfer(cp->packet[p].transfer); if (ret) fprintf(stderr, "libusb_submit_transfer failed %d\n", ret); cp->p++; }
int LibusbDevice::SubmitTransfer(std::unique_ptr<CtrlMessage> cmd) { if (!m_device_attached) return LIBUSB_ERROR_NOT_FOUND; DEBUG_LOG(IOS_USB, "[%04x:%04x %d] Control: bRequestType=%02x bRequest=%02x wValue=%04x" " wIndex=%04x wLength=%04x", m_vid, m_pid, m_active_interface, cmd->request_type, cmd->request, cmd->value, cmd->index, cmd->length); switch ((cmd->request_type << 8) | cmd->request) { // The following requests have to go through libusb and cannot be directly sent to the device. case USBHDR(DIR_HOST2DEVICE, TYPE_STANDARD, REC_INTERFACE, REQUEST_SET_INTERFACE): { INFO_LOG(IOS_USB, "[%04x:%04x %d] REQUEST_SET_INTERFACE index=%04x value=%04x", m_vid, m_pid, m_active_interface, cmd->index, cmd->value); if (static_cast<u8>(cmd->index) != m_active_interface) { const int ret = ChangeInterface(static_cast<u8>(cmd->index)); if (ret < 0) { ERROR_LOG(IOS_USB, "[%04x:%04x %d] Failed to change interface to %d: %s", m_vid, m_pid, m_active_interface, cmd->index, libusb_error_name(ret)); return ret; } } const int ret = SetAltSetting(static_cast<u8>(cmd->value)); if (ret == 0) m_ios.EnqueueIPCReply(cmd->ios_request, cmd->length); return ret; } case USBHDR(DIR_HOST2DEVICE, TYPE_STANDARD, REC_DEVICE, REQUEST_SET_CONFIGURATION): { INFO_LOG(IOS_USB, "[%04x:%04x %d] REQUEST_SET_CONFIGURATION index=%04x value=%04x", m_vid, m_pid, m_active_interface, cmd->index, cmd->value); ReleaseAllInterfacesForCurrentConfig(); const int ret = libusb_set_configuration(m_handle, cmd->value); if (ret == 0) { ClaimAllInterfaces(cmd->value); m_ios.EnqueueIPCReply(cmd->ios_request, cmd->length); } return ret; } } const size_t size = cmd->length + LIBUSB_CONTROL_SETUP_SIZE; auto buffer = std::make_unique<u8[]>(size); libusb_fill_control_setup(buffer.get(), cmd->request_type, cmd->request, cmd->value, cmd->index, cmd->length); Memory::CopyFromEmu(buffer.get() + LIBUSB_CONTROL_SETUP_SIZE, cmd->data_address, cmd->length); libusb_transfer* transfer = libusb_alloc_transfer(0); transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER; libusb_fill_control_transfer(transfer, m_handle, buffer.release(), CtrlTransferCallback, this, 0); m_transfer_endpoints[0].AddTransfer(std::move(cmd), transfer); return libusb_submit_transfer(transfer); }
static void susb_issue_call(struct aura_node *node, struct aura_buffer *buf) { struct aura_object *o = buf->object; struct usb_dev_info *inf = aura_get_transportdata(node); uint8_t rqtype; uint16_t wIndex, wValue, *ptr; size_t datalen; /*Actual data in packet, save for setup */ if (o->retlen) { rqtype = LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN; datalen = o->retlen; } else { datalen = o->arglen - 2 * sizeof(uint16_t); rqtype = LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT; } ptr = (uint16_t *)&buf->data[buf->pos]; wValue = *ptr++; wIndex = *ptr++; memmove(&buf->data[buf->pos], ptr, datalen); /* * VUSB-based devices (or libusb?) do not seem to play nicely when we have the * setup packet with no data. Transfers may fail instantly. * A typical run at my box gives: * * 9122 succeeded, 878 failed total 10000 * * See tests-transports/test-susb-stability-none * Adding just one byte of data to the packet fix the issue. * Posible workarounds are: * 1. Retry N times * 2. Add just one dummy byte for the transfer * Since nobody reported this workaround breaking support for their * hardware - we'll do it the second way. For now. */ if (!datalen) datalen++; /* buffer's big enough anyway */ /* e.g if device is big endian, but has le descriptors * we have to be extra careful here */ if (node->need_endian_swap) { wValue = __swap16(wValue); wIndex = __swap16(wValue); } inf->current_buffer = buf; libusb_fill_control_setup((unsigned char *)buf->data, rqtype, o->id, wValue, wIndex, datalen); libusb_fill_control_transfer(inf->ctransfer, inf->handle, (unsigned char *)buf->data, cb_call_done, node, 4000); inf->control_retry_count = 0; submit_control(node); }
static void request_object(struct aura_node *node, int id) { struct usb_dev_info *inf = aura_get_transportdata(node); libusb_fill_control_setup(inf->ctrlbuf, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, RQ_GET_OBJ_INFO, 0, id, inf->io_buf_size - LIBUSB_CONTROL_SETUP_SIZE); libusb_fill_control_transfer(inf->ctransfer, inf->handle, inf->ctrlbuf, cb_parse_object, node, 1500); submit_control(node); }
static void submit_call_write(struct aura_node *node, struct aura_buffer *buf) { struct aura_object *o = buf->object; struct usb_dev_info *inf = aura_get_transportdata(node); slog(4, SLOG_DEBUG, "Writing call %s data to device, %d bytes", o->name, buf->size); inf->current_buffer = buf; libusb_fill_control_setup((unsigned char *)buf->data, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT, RQ_PUT_CALL, 0, 0, buf->size - LIBUSB_CONTROL_SETUP_SIZE); libusb_fill_control_transfer(inf->ctransfer, inf->handle, (unsigned char *) buf->data, cb_call_write_done, node, 1500); submit_control(node); }
static void submit_event_readout(struct aura_node *node) { struct usb_dev_info *inf = aura_get_transportdata(node); struct aura_buffer *buf = aura_buffer_request(node, inf->io_buf_size); if (!buf) return; /* Nothing bad, we'll try again later */ slog(0, SLOG_DEBUG, "Starting evt readout, max %d bytes, pending %d", inf->io_buf_size, inf->pending); libusb_fill_control_setup((unsigned char *)buf->data, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, RQ_GET_EVENT, 0, 0, buf->size - LIBUSB_CONTROL_SETUP_SIZE); libusb_fill_control_transfer(inf->ctransfer, inf->handle, (unsigned char *)buf->data, cb_event_readout_done, node, 1500); inf->current_buffer = buf; submit_control(node); }
libusb_error LibusbSoundplaneDriver::processThreadSendControl( libusb_device_handle *device, uint8_t request, uint16_t value, uint16_t index, const unsigned char *data, size_t dataSize) { if (processThreadShouldStopTransfers()) { return LIBUSB_ERROR_OTHER; } unsigned char *buf = static_cast<unsigned char*>(malloc(LIBUSB_CONTROL_SETUP_SIZE + dataSize)); struct libusb_transfer *transfer; if (!buf) { return LIBUSB_ERROR_NO_MEM; } memcpy(buf + LIBUSB_CONTROL_SETUP_SIZE, data, dataSize); transfer = libusb_alloc_transfer(0); if (!transfer) { free(buf); return LIBUSB_ERROR_NO_MEM; } static constexpr auto kCtrlOut = LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT; libusb_fill_control_setup(buf, kCtrlOut, request, value, index, dataSize); libusb_fill_control_transfer(transfer, device, buf, &LibusbSoundplaneDriver::processThreadControlTransferCallback, this, 1000); transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK | LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER; const auto result = static_cast<libusb_error>(libusb_submit_transfer(transfer)); if (result >= 0) { mOutstandingTransfers++; } return result; }
void cp_usb_async_write(struct cp_usb_async *cp, uint8_t mask, uint8_t value) { int p; uint16_t gpio_set; int ret; if (cp->set) { value = (cp->value & ~mask) | (value & mask); mask = value ^ cp->value; } cp->set = 1; cp->value = value; gpio_set = ((uint16_t) value << 8) | mask; if (cp->p == MAX_OUTSTANDING) cp_usb_async_sync(cp); p = cp->p; if (!cp->packet[p].transfer) cp->packet[p].transfer = libusb_alloc_transfer(0); cp->packet[p].direction = packet_write; libusb_fill_control_setup(cp->packet[p].data, 0x40, /* request */ 0xff, /* request type */ 0x37e1, /* value */ gpio_set, /* index */ 0); /* length */ libusb_fill_control_transfer(cp->packet[p].transfer, cp->handle, cp->packet[p].data, cp_usb_async_transfer_callback, cp, CP_TIMEOUT); ccdbg_debug(CC_DEBUG_USB_ASYNC, "Write packet %d 0x%x 0x%x\n", p, mask, value); ret = libusb_submit_transfer(cp->packet[p].transfer); if (ret) fprintf(stderr, "libusb_submit_transfer failed %d\n", ret); cp->p++; }
static int set_mode_async(unsigned char data) { unsigned char *buf = malloc(LIBUSB_CONTROL_SETUP_SIZE + 1); struct libusb_transfer *transfer; if (!buf) return -ENOMEM; transfer = libusb_alloc_transfer(0); if (!transfer) { free(buf); return -ENOMEM; } printf("async set mode %02x\n", data); libusb_fill_control_setup(buf, CTRL_OUT, USB_RQ, 0x4e, 0, 1); buf[LIBUSB_CONTROL_SETUP_SIZE] = data; libusb_fill_control_transfer(transfer, devh, buf, cb_mode_changed, NULL, 1000); transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK | LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER; return libusb_submit_transfer(transfer); }
/** * cd_sensor_munki_refresh_state: **/ static gboolean cd_sensor_munki_refresh_state (CdSensor *sensor, GError **error) { gint retval; gboolean ret = FALSE; static guint8 *request; libusb_device_handle *handle; CdSensorMunkiPrivate *priv = cd_sensor_munki_get_private (sensor); /* do sync request */ handle = cd_usb_get_device_handle (priv->usb); /* request new button task */ request = g_new0 (guint8, LIBUSB_CONTROL_SETUP_SIZE + 2); libusb_fill_control_setup (request, LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, MUNKI_REQUEST_GET_STATUS, 0x00, 0, 2); libusb_fill_control_transfer (priv->transfer_state, handle, request, &cd_sensor_munki_refresh_state_transfer_cb, sensor, 2000); /* submit transfer */ retval = libusb_submit_transfer (priv->transfer_state); if (retval < 0) { g_set_error (error, 1, 0, "failed to submit transfer: %s", libusb_strerror (retval)); goto out; } /* success */ ret = TRUE; out: return ret; }
void Chatpad::send_ctrl(uint8_t request_type, uint8_t request, uint16_t value, uint16_t index, uint8_t* data_in, uint16_t length, libusb_transfer_cb_fn callback, void* userdata) { libusb_transfer* transfer = libusb_alloc_transfer(0); transfer->flags |= LIBUSB_TRANSFER_FREE_BUFFER; transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER; // create and fill control buffer uint8_t* data = static_cast<uint8_t*>(malloc(length + 8)); libusb_fill_control_setup(data, request_type, request, value, index, length); memcpy(data + 8, data_in, length); libusb_fill_control_transfer(transfer, m_handle, data, callback, userdata, 0); int ret; ret = libusb_submit_transfer(transfer); if (ret != LIBUSB_SUCCESS) { raise_exception(std::runtime_error, "libusb_submit_transfer(): " << usb_strerror(ret)); } }
static int usb_start_ops(struct libusb_device_handle *hndl, void *arg) { /* FixMe: Reading descriptors is synchronos. This is not needed * often, but leaves a possibility of a flaky usb device to * screw up the event processing. * A proper workaround would be manually reading out string descriptors * from a device in an async fasion in the background. */ int ret; struct usb_dev_info *inf = arg; struct aura_node *node = inf->node; inf->handle = hndl; libusb_fill_interrupt_transfer(inf->itransfer, inf->handle, 0x81, inf->ibuffer, 8, cb_interrupt, node, 10000); libusb_fill_control_setup(inf->ctrlbuf, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, RQ_GET_DEV_INFO, 0, 0, inf->io_buf_size); libusb_fill_control_transfer(inf->ctransfer, inf->handle, inf->ctrlbuf, cb_got_dev_info, node, 1500); ret = libusb_submit_transfer(inf->ctransfer); if (ret!= 0) { libusb_close(inf->handle); return -1; } inf->state = AUSB_DEVICE_INIT; /* Change our state */ inf->cbusy = true; slog(4, SLOG_DEBUG, "usb: Device opened, info packet requested"); return 0; };
/** \ingroup syncio * Perform a USB control transfer. * * The direction of the transfer is inferred from the bmRequestType field of * the setup packet. * * The wValue, wIndex and wLength fields values should be given in host-endian * byte order. * * \param dev_handle a handle for the device to communicate with * \param bmRequestType the request type field for the setup packet * \param bRequest the request field for the setup packet * \param wValue the value field for the setup packet * \param wIndex the index field for the setup packet * \param data a suitably-sized data buffer for either input or output * (depending on direction bits within bmRequestType) * \param wLength the length field for the setup packet. The data buffer should * be at least this size. * \param timeout timeout (in millseconds) that this function should wait * before giving up due to no response being received. For an unlimited * timeout, use value 0. * \returns on success, the number of bytes actually transferred * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out * \returns LIBUSB_ERROR_PIPE if the control request was not supported by the * device * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * \returns another LIBUSB_ERROR code on other failures */ API_EXPORTED int libusb_control_transfer(libusb_device_handle *dev_handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, unsigned int timeout) { struct libusb_transfer *transfer = libusb_alloc_transfer(0); unsigned char *buffer; int completed = 0; int r; if (!transfer) return LIBUSB_ERROR_NO_MEM; buffer = malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength); if (!buffer) { libusb_free_transfer(transfer); return LIBUSB_ERROR_NO_MEM; } libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex, wLength); if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength); libusb_fill_control_transfer(transfer, dev_handle, buffer, ctrl_transfer_cb, &completed, timeout); transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER; r = libusb_submit_transfer(transfer); if (r < 0) { libusb_free_transfer(transfer); return r; } while (!completed) { r = libusb_handle_events(HANDLE_CTX(dev_handle)); if (r < 0) { if (r == LIBUSB_ERROR_INTERRUPTED) continue; libusb_cancel_transfer(transfer); while (!completed) if (libusb_handle_events(HANDLE_CTX(dev_handle)) < 0) break; libusb_free_transfer(transfer); return r; } } if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) memcpy(data, libusb_control_transfer_get_data(transfer), transfer->actual_length); switch (transfer->status) { case LIBUSB_TRANSFER_COMPLETED: r = transfer->actual_length; break; case LIBUSB_TRANSFER_TIMED_OUT: r = LIBUSB_ERROR_TIMEOUT; break; case LIBUSB_TRANSFER_STALL: r = LIBUSB_ERROR_PIPE; break; case LIBUSB_TRANSFER_NO_DEVICE: r = LIBUSB_ERROR_NO_DEVICE; break; default: usbi_warn(HANDLE_CTX(dev_handle), "unrecognised status code %d", transfer->status); r = LIBUSB_ERROR_OTHER; } libusb_free_transfer(transfer); return r; }
static GSList *scan(GSList *options) { GSList *usb_devices, *devices, *l; struct drv_context *drvc; struct sr_dev_inst *sdi; struct sr_probe *probe; struct dev_context *devc; struct sr_usb_dev_inst *usb; struct device_info dev_info; int ret, device_index, i; char *fw_ver_str; (void)options; devices = NULL; drvc = di->priv; drvc->instances = NULL; device_index = 0; usb_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, USB_VID_PID); if (usb_devices == NULL) return NULL; for (l = usb_devices; l; l = l->next) { usb = l->data; if ((ret = sl2_get_device_info(*usb, &dev_info)) < 0) { sr_warn("Failed to get device information: %d.", ret); sr_usb_dev_inst_free(usb); continue; } if (!(devc = g_try_malloc(sizeof(struct dev_context)))) { sr_err("Device instance malloc failed."); sr_usb_dev_inst_free(usb); continue; } if (!(devc->xfer_in = libusb_alloc_transfer(0))) { sr_err("Transfer malloc failed."); sr_usb_dev_inst_free(usb); g_free(devc); continue; } if (!(devc->xfer_out = libusb_alloc_transfer(0))) { sr_err("Transfer malloc failed."); sr_usb_dev_inst_free(usb); libusb_free_transfer(devc->xfer_in); g_free(devc); continue; } fw_ver_str = g_strdup_printf("%u.%u", dev_info.fw_ver_major, dev_info.fw_ver_minor); if (!fw_ver_str) { sr_err("Firmware string malloc failed."); sr_usb_dev_inst_free(usb); libusb_free_transfer(devc->xfer_in); libusb_free_transfer(devc->xfer_out); g_free(devc); continue; } sdi = sr_dev_inst_new(device_index, SR_ST_INACTIVE, VENDOR_NAME, MODEL_NAME, fw_ver_str); g_free(fw_ver_str); if (!sdi) { sr_err("sr_dev_inst_new failed."); sr_usb_dev_inst_free(usb); libusb_free_transfer(devc->xfer_in); libusb_free_transfer(devc->xfer_out); g_free(devc); continue; } sdi->priv = devc; sdi->driver = di; sdi->inst_type = SR_INST_USB; sdi->conn = usb; for (i = 0; probe_names[i]; i++) { probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, probe_names[i]); sdi->probes = g_slist_append(sdi->probes, probe); devc->probes[i] = probe; } devc->state = STATE_IDLE; devc->next_state = STATE_IDLE; /* Set default samplerate. */ sl2_set_samplerate(sdi, DEFAULT_SAMPLERATE); /* Set default capture ratio. */ devc->capture_ratio = 0; /* Set default after trigger delay. */ devc->after_trigger_delay = 0; memset(devc->xfer_buf_in, 0, LIBUSB_CONTROL_SETUP_SIZE + PACKET_LENGTH); memset(devc->xfer_buf_out, 0, LIBUSB_CONTROL_SETUP_SIZE + PACKET_LENGTH); libusb_fill_control_setup(devc->xfer_buf_in, USB_REQUEST_TYPE_IN, USB_HID_GET_REPORT, USB_HID_REPORT_TYPE_FEATURE, USB_INTERFACE, PACKET_LENGTH); libusb_fill_control_setup(devc->xfer_buf_out, USB_REQUEST_TYPE_OUT, USB_HID_SET_REPORT, USB_HID_REPORT_TYPE_FEATURE, USB_INTERFACE, PACKET_LENGTH); devc->xfer_data_in = devc->xfer_buf_in + LIBUSB_CONTROL_SETUP_SIZE; devc->xfer_data_out = devc->xfer_buf_out + LIBUSB_CONTROL_SETUP_SIZE; drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); device_index++; } g_slist_free(usb_devices); return devices; }
static GSList *scan(struct sr_dev_driver *di, GSList *options) { GSList *usb_devices, *devices, *l; struct drv_context *drvc; struct sr_dev_inst *sdi; struct dev_context *devc; struct sr_usb_dev_inst *usb; struct device_info dev_info; unsigned int i; int ret; (void)options; devices = NULL; drvc = di->context; drvc->instances = NULL; usb_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, USB_VID_PID); if (!usb_devices) return NULL; for (l = usb_devices; l; l = l->next) { usb = l->data; if ((ret = sl2_get_device_info(*usb, &dev_info)) < 0) { sr_warn("Failed to get device information: %d.", ret); sr_usb_dev_inst_free(usb); continue; } devc = g_malloc0(sizeof(struct dev_context)); if (!(devc->xfer_in = libusb_alloc_transfer(0))) { sr_err("Transfer malloc failed."); sr_usb_dev_inst_free(usb); g_free(devc); continue; } if (!(devc->xfer_out = libusb_alloc_transfer(0))) { sr_err("Transfer malloc failed."); sr_usb_dev_inst_free(usb); libusb_free_transfer(devc->xfer_in); g_free(devc); continue; } sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = SR_ST_INACTIVE; sdi->vendor = g_strdup(VENDOR_NAME); sdi->model = g_strdup(MODEL_NAME); sdi->version = g_strdup_printf("%u.%u", dev_info.fw_ver_major, dev_info.fw_ver_minor); sdi->serial_num = g_strdup_printf("%d", dev_info.serial); sdi->priv = devc; sdi->driver = di; sdi->inst_type = SR_INST_USB; sdi->conn = usb; for (i = 0; i < ARRAY_SIZE(channel_names); i++) devc->channels[i] = sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_names[i]); devc->state = STATE_IDLE; devc->next_state = STATE_IDLE; /* Set default samplerate. */ sl2_set_samplerate(sdi, DEFAULT_SAMPLERATE); /* Set default capture ratio. */ devc->capture_ratio = 0; /* Set default after trigger delay. */ devc->after_trigger_delay = 0; memset(devc->xfer_buf_in, 0, LIBUSB_CONTROL_SETUP_SIZE + PACKET_LENGTH); memset(devc->xfer_buf_out, 0, LIBUSB_CONTROL_SETUP_SIZE + PACKET_LENGTH); libusb_fill_control_setup(devc->xfer_buf_in, USB_REQUEST_TYPE_IN, USB_HID_GET_REPORT, USB_HID_REPORT_TYPE_FEATURE, USB_INTERFACE, PACKET_LENGTH); libusb_fill_control_setup(devc->xfer_buf_out, USB_REQUEST_TYPE_OUT, USB_HID_SET_REPORT, USB_HID_REPORT_TYPE_FEATURE, USB_INTERFACE, PACKET_LENGTH); devc->xfer_data_in = devc->xfer_buf_in + LIBUSB_CONTROL_SETUP_SIZE; devc->xfer_data_out = devc->xfer_buf_out + LIBUSB_CONTROL_SETUP_SIZE; drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); } g_slist_free(usb_devices); return devices; }
bool CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress) { u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC); u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10); u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14); u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18); u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C); u32 ReturnValue = 0; switch (Parameter) { case IOCTL_HID_GET_ATTACHED: { DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Get Attached) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", BufferIn, BufferInSize, BufferOut, BufferOutSize); deviceCommandAddress = _CommandAddress; return false; break; } case IOCTL_HID_OPEN: { DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Open) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", BufferIn, BufferInSize, BufferOut, BufferOutSize); //hid version, apparently ReturnValue = 0x40001; break; } case IOCTL_HID_SET_SUSPEND: { DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Set Suspend) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", BufferIn, BufferInSize, BufferOut, BufferOutSize); // not actually implemented in IOS ReturnValue = 0; break; } case IOCTL_HID_CANCEL_INTERRUPT: { DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Cancel Interrupt) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", BufferIn, BufferInSize, BufferOut, BufferOutSize); ReturnValue = 0; break; } case IOCTL_HID_CONTROL: { /* ERROR CODES: -4 Cant find device specified */ u32 dev_num = Memory::Read_U32(BufferIn+0x10); u8 bmRequestType = Memory::Read_U8(BufferIn+0x14); u8 bRequest = Memory::Read_U8(BufferIn+0x15); u16 wValue = Memory::Read_U16(BufferIn+0x16); u16 wIndex = Memory::Read_U16(BufferIn+0x18); u16 wLength = Memory::Read_U16(BufferIn+0x1A); u32 data = Memory::Read_U32(BufferIn+0x1C); ReturnValue = HIDERR_NO_DEVICE_FOUND; libusb_device_handle * dev_handle = GetDeviceByDevNum(dev_num); if (dev_handle == NULL) { DEBUG_LOG(WII_IPC_HID, "Could not find handle: %X", dev_num); break; } struct libusb_transfer *transfer = libusb_alloc_transfer(0); transfer->flags |= LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER; u8 * buffer = (u8*)malloc(wLength + LIBUSB_CONTROL_SETUP_SIZE); libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex, wLength); memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, Memory::GetPointer(data), wLength); libusb_fill_control_transfer(transfer, dev_handle, buffer, handleUsbUpdates, (void*)(size_t)_CommandAddress, /* no timeout */ 0); libusb_submit_transfer(transfer); //DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Control)(%02X, %02X) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", // bmRequestType, bRequest, BufferIn, BufferInSize, BufferOut, BufferOutSize); // It's the async way! return false; break; } case IOCTL_HID_INTERRUPT_OUT: case IOCTL_HID_INTERRUPT_IN: { u32 dev_num = Memory::Read_U32(BufferIn+0x10); u32 endpoint = Memory::Read_U32(BufferIn+0x14); u32 length = Memory::Read_U32(BufferIn+0x18); u32 data = Memory::Read_U32(BufferIn+0x1C); ReturnValue = HIDERR_NO_DEVICE_FOUND; libusb_device_handle * dev_handle = GetDeviceByDevNum(dev_num); if (dev_handle == NULL) { DEBUG_LOG(WII_IPC_HID, "Could not find handle: %X", dev_num); break; } struct libusb_transfer *transfer = libusb_alloc_transfer(0); transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER; libusb_fill_interrupt_transfer(transfer, dev_handle, endpoint, Memory::GetPointer(data), length, handleUsbUpdates, (void*)(size_t)_CommandAddress, 0); libusb_submit_transfer(transfer); //DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Interrupt %s)(%d,%d,%X) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", // Parameter == IOCTL_HID_INTERRUPT_IN ? "In" : "Out", endpoint, length, data, BufferIn, BufferInSize, BufferOut, BufferOutSize); // It's the async way! return false; break; } case IOCTL_HID_SHUTDOWN: { std::lock_guard<std::mutex> lk(s_device_list_reply); if (deviceCommandAddress != 0){ Memory::Write_U32(0xFFFFFFFF, Memory::Read_U32(deviceCommandAddress + 0x18)); Memory::Write_U32(8, deviceCommandAddress); // IOS seems to write back the command that was responded to Memory::Write_U32(/*COMMAND_IOCTL*/ 6, deviceCommandAddress + 8); // Return value Memory::Write_U32(-1, deviceCommandAddress + 4); WII_IPC_HLE_Interface::EnqueReplyCallback(deviceCommandAddress); deviceCommandAddress = 0; } DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Shutdown) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", BufferIn, BufferInSize, BufferOut, BufferOutSize); break; } default: { DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(0x%x) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", Parameter, BufferIn, BufferInSize, BufferOut, BufferOutSize); break; } } Memory::Write_U32(ReturnValue, _CommandAddress + 4); return true; }