#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include <libusb.h>
#include "const-c.inc"
typedef
libusb_context *USB__LibUSB__XS;
typedef
libusb_device *USB__LibUSB__XS__Device;
typedef
libusb_device_handle *USB__LibUSB__XS__Device__Handle;
static
void
do_not_warn_unused(
void
*x __attribute__((__unused__)))
{
}
static
SV *
ss_ep_comp_to_HV(pTHX_
struct
libusb_ss_endpoint_companion_descriptor *ep_comp)
{
HV *rv = newHV();
hv_stores(rv,
"bLength"
, newSVuv(ep_comp->bLength));
hv_stores(rv,
"bDescriptorType"
, newSVuv(ep_comp->bDescriptorType));
hv_stores(rv,
"bMaxBurst"
, newSVuv(ep_comp->bMaxBurst));
hv_stores(rv,
"bmAttributes"
, newSVuv(ep_comp->bmAttributes));
hv_stores(rv,
"wBytesPerInterval"
, newSVuv(ep_comp->wBytesPerInterval));
return
newRV_noinc((SV *) rv);
}
static
SV *
endpoint_descriptor_to_HV(pTHX_ libusb_context *ctx,
const
struct
libusb_endpoint_descriptor *endpoint)
{
HV *rv = newHV();
hv_stores(rv,
"bLength"
, newSVuv(endpoint->bLength));
hv_stores(rv,
"bDescriptorType"
, newSVuv(endpoint->bDescriptorType));
hv_stores(rv,
"bEndpointAddress"
, newSVuv(endpoint->bEndpointAddress));
hv_stores(rv,
"bmAttributes"
, newSVuv(endpoint->bmAttributes));
hv_stores(rv,
"wMaxPacketSize"
, newSVuv(endpoint->wMaxPacketSize));
hv_stores(rv,
"bInterval"
, newSVuv(endpoint->bInterval));
hv_stores(rv,
"bRefresh"
, newSVuv(endpoint->bRefresh));
hv_stores(rv,
"bSynchAddress"
, newSVuv(endpoint->bSynchAddress));
hv_stores(rv,
"extra"
, newSVpvn((
const
char
*)endpoint->extra, endpoint->extra_length));
struct
libusb_ss_endpoint_companion_descriptor *ep_comp;
int
value = libusb_get_ss_endpoint_companion_descriptor(ctx, endpoint, &ep_comp);
if
(value == 0) {
hv_stores(rv,
"ss_endpoint_companion"
, ss_ep_comp_to_HV(aTHX_ ep_comp));
libusb_free_ss_endpoint_companion_descriptor(ep_comp);
}
else
if
(value != LIBUSB_ERROR_NOT_FOUND)
croak(
"Error in libusb_get_ss_endpoint_companion_descriptor"
);
return
newRV_noinc((SV *) rv);
}
static
SV *
endpoint_array_to_AV(pTHX_ libusb_context *ctx,
const
struct
libusb_endpoint_descriptor *endpoint,
int
num_endpoints)
{
AV *rv = newAV();
for
(
int
i = 0; i < num_endpoints; ++i)
av_push(rv, endpoint_descriptor_to_HV(aTHX_ ctx, &endpoint[i]));
return
newRV_noinc((SV *) rv);
}
static
SV *
interface_descriptor_to_HV(pTHX_ libusb_context *ctx,
const
struct
libusb_interface_descriptor *interface)
{
HV *rv = newHV();
hv_stores(rv,
"bLength"
, newSVuv(interface->bLength));
hv_stores(rv,
"bDescriptorType"
, newSVuv(interface->bDescriptorType));
hv_stores(rv,
"bInterfaceNumber"
, newSVuv(interface->bInterfaceNumber));
hv_stores(rv,
"bAlternateSetting"
, newSVuv(interface->bAlternateSetting));
hv_stores(rv,
"bNumEndpoints"
, newSVuv(interface->bNumEndpoints));
hv_stores(rv,
"bInterfaceClass"
, newSVuv(interface->bInterfaceClass));
hv_stores(rv,
"bInterfaceSubClass"
, newSVuv(interface->bInterfaceSubClass));
hv_stores(rv,
"bInterfaceProtocol"
, newSVuv(interface->bInterfaceProtocol));
hv_stores(rv,
"iInterface"
, newSVuv(interface->iInterface));
hv_stores(rv,
"endpoint"
, endpoint_array_to_AV(aTHX_ ctx, interface->endpoint, interface->bNumEndpoints));
hv_stores(rv,
"extra"
, newSVpvn((
const
char
*) interface->extra, interface->extra_length));
return
newRV_noinc((SV *) rv);
}
static
SV *
altsetting_array_to_AV(pTHX_ libusb_context *ctx,
const
struct
libusb_interface *interface)
{
AV *rv = newAV();
for
(
int
i = 0; i < interface->num_altsetting; ++i)
av_push(rv, interface_descriptor_to_HV(aTHX_ ctx, &interface->altsetting[i]));
return
newRV_noinc((SV *) rv);
}
static
SV *
interface_array_to_AV(pTHX_ libusb_context *ctx,
const
struct
libusb_interface *interface,
int
num_interfaces)
{
AV *rv = newAV();
for
(
int
i = 0; i < num_interfaces; ++i)
av_push(rv, altsetting_array_to_AV(aTHX_ ctx, &interface[i]));
return
newRV_noinc((SV *) rv);
}
static
SV *
config_descriptor_to_RV(pTHX_ libusb_context *ctx,
struct
libusb_config_descriptor *config)
{
HV *rv = newHV();
hv_stores(rv,
"bLength"
, newSVuv(config->bLength));
hv_stores(rv,
"bDescriptorType"
, newSVuv(config->bDescriptorType));
hv_stores(rv,
"wTotalLength"
, newSVuv(config->wTotalLength));
hv_stores(rv,
"bNumInterfaces"
, newSVuv(config->bNumInterfaces));
hv_stores(rv,
"bConfigurationValue"
, newSVuv(config->bConfigurationValue));
hv_stores(rv,
"iConfiguration"
, newSVuv(config->iConfiguration));
hv_stores(rv,
"bmAttributes"
, newSVuv(config->bmAttributes));
hv_stores(rv,
"MaxPower"
, newSVuv(config->MaxPower));
hv_stores(rv,
"interface"
, interface_array_to_AV(aTHX_ ctx, config->interface, config->bNumInterfaces));
hv_stores(rv,
"extra"
, newSVpvn((
const
char
*) config->extra, config->extra_length));
return
newRV_noinc((SV *) rv);
}
static
SV *
usb_2_0_extension_to_HV(pTHX_ libusb_context *ctx,
struct
libusb_bos_dev_capability_descriptor *dev_cap)
{
struct
libusb_usb_2_0_extension_descriptor *usb_2_0_extension;
int
value = libusb_get_usb_2_0_extension_descriptor(ctx, dev_cap, &usb_2_0_extension);
if
(value != 0)
croak(
"error in libusb_get_usb_2_0_extension_descriptor"
);
HV *rv = newHV();
hv_stores(rv,
"bLength"
, newSVuv(usb_2_0_extension->bLength));
hv_stores(rv,
"bDescriptorType"
, newSVuv(usb_2_0_extension->bDescriptorType));
hv_stores(rv,
"bDevCapabilityType"
, newSVuv(usb_2_0_extension->bDevCapabilityType));
hv_stores(rv,
"bmAttributes"
, newSVuv(usb_2_0_extension->bmAttributes));
libusb_free_usb_2_0_extension_descriptor(usb_2_0_extension);
return
newRV_noinc((SV *) rv);
}
static
SV *
ss_usb_device_capability_to_HV(pTHX_ libusb_context *ctx,
struct
libusb_bos_dev_capability_descriptor *dev_cap)
{
struct
libusb_ss_usb_device_capability_descriptor *ss_usb_device_capability;
int
value = libusb_get_ss_usb_device_capability_descriptor(ctx, dev_cap, &ss_usb_device_capability);
if
(value != 0)
croak(
"error in libusb_get_ss_usb_device_capability_descriptor"
);
HV *rv = newHV();
hv_stores(rv,
"bLength"
, newSVuv(ss_usb_device_capability->bLength));
hv_stores(rv,
"bDescriptorType"
, newSVuv(ss_usb_device_capability->bDescriptorType));
hv_stores(rv,
"bDevCapabilityType"
, newSVuv(ss_usb_device_capability->bDevCapabilityType));
hv_stores(rv,
"bmAttributes"
, newSVuv(ss_usb_device_capability->bmAttributes));
hv_stores(rv,
"wSpeedSupported"
, newSVuv(ss_usb_device_capability->wSpeedSupported));
hv_stores(rv,
"bFunctionalitySupport"
, newSVuv(ss_usb_device_capability->bFunctionalitySupport));
hv_stores(rv,
"bU1DevExitLat"
, newSVuv(ss_usb_device_capability->bU1DevExitLat));
hv_stores(rv,
"bU2DevExitLat"
, newSVuv(ss_usb_device_capability->bU2DevExitLat));
libusb_free_ss_usb_device_capability_descriptor(ss_usb_device_capability);
return
newRV_noinc((SV *) rv);
}
static
SV *
container_id_to_HV(pTHX_ libusb_context *ctx,
struct
libusb_bos_dev_capability_descriptor *dev_cap)
{
struct
libusb_container_id_descriptor *container_id;
int
value = libusb_get_container_id_descriptor(ctx, dev_cap, &container_id);
if
(value != 0)
croak(
"error in libusb_get_container_id_descriptor"
);
HV *rv = newHV();
hv_stores(rv,
"bLength"
, newSVuv(container_id->bLength));
hv_stores(rv,
"bDescriptorType"
, newSVuv(container_id->bDescriptorType));
hv_stores(rv,
"bDevCapabilityType"
, newSVuv(container_id->bDevCapabilityType));
hv_stores(rv,
"bReserved"
, newSVuv(container_id->bReserved));
hv_stores(rv,
"ContainerID"
, newSVpvn((
const
char
*) container_id->ContainerID, 16));
libusb_free_container_id_descriptor(container_id);
return
newRV_noinc((SV *) rv);
}
static
SV *
bos_dev_capability_descriptor_to_HV(pTHX_ libusb_context *ctx,
struct
libusb_bos_dev_capability_descriptor *dev_cap)
{
HV *rv = newHV();
hv_stores(rv,
"bLength"
, newSVuv(dev_cap->bLength));
hv_stores(rv,
"bDescriptorType"
, newSVuv(dev_cap->bDescriptorType));
unsigned capability_type = dev_cap->bDevCapabilityType;
hv_stores(rv,
"bDevCapabilityType"
, newSVuv(capability_type));
hv_stores(rv,
"dev_capability_data"
, newSVpvn((
const
char
*) dev_cap->dev_capability_data, dev_cap->bLength - 3));
switch
(capability_type) {
case
LIBUSB_BT_USB_2_0_EXTENSION:
hv_stores(rv,
"usb_2_0_extension"
, usb_2_0_extension_to_HV(aTHX_ ctx, dev_cap));
break
;
case
LIBUSB_BT_SS_USB_DEVICE_CAPABILITY:
hv_stores(rv,
"ss_usb_device_capability"
, ss_usb_device_capability_to_HV(aTHX_ ctx, dev_cap));
break
;
case
LIBUSB_BT_CONTAINER_ID:
hv_stores(rv,
"container_id"
, container_id_to_HV(aTHX_ ctx, dev_cap));
break
;
}
return
newRV_noinc((SV *) rv);
}
static
SV *
dev_capability_array_to_AV(pTHX_ libusb_context *ctx,
struct
libusb_bos_dev_capability_descriptor **dev_capability, uint8_t bNumDeviceCaps)
{
AV *rv = newAV();
for
(
int
i = 0; i < bNumDeviceCaps; ++i)
av_push(rv, bos_dev_capability_descriptor_to_HV(aTHX_ ctx, dev_capability[i]));
return
newRV_noinc((SV *) rv);
}
static
SV *
bos_descriptor_to_RV(pTHX_ libusb_context *ctx,
struct
libusb_bos_descriptor *bos)
{
HV *rv = newHV();
hv_stores(rv,
"bLength"
, newSVuv(bos->bLength));
hv_stores(rv,
"bDescriptorType"
, newSVuv(bos->bDescriptorType));
hv_stores(rv,
"wTotalLength"
, newSVuv(bos->wTotalLength));
hv_stores(rv,
"bNumDeviceCaps"
, newSVuv(bos->bNumDeviceCaps));
hv_stores(rv,
"dev_capability"
, dev_capability_array_to_AV(aTHX_ ctx, bos->dev_capability, bos->bNumDeviceCaps));
return
newRV_noinc((SV *) rv);
}
static
SV *
device_descriptor_to_RV(pTHX_
struct
libusb_device_descriptor *desc)
{
HV *rv = newHV();
hv_stores(rv,
"bLength"
, newSVuv(desc->bLength));
hv_stores(rv,
"bDescriptorType"
, newSVuv(desc->bDescriptorType));
hv_stores(rv,
"bcdUSB"
, newSVuv(desc->bcdUSB));
hv_stores(rv,
"bDeviceClass"
, newSVuv(desc->bDeviceClass));
hv_stores(rv,
"bDeviceSubClass"
, newSVuv(desc->bDeviceSubClass));
hv_stores(rv,
"bDeviceProtocol"
, newSVuv(desc->bDeviceProtocol));
hv_stores(rv,
"bMaxPacketSize0"
, newSVuv(desc->bMaxPacketSize0));
hv_stores(rv,
"idVendor"
, newSVuv(desc->idVendor));
hv_stores(rv,
"idProduct"
, newSVuv(desc->idProduct));
hv_stores(rv,
"bcdDevice"
, newSVuv(desc->bcdDevice));
hv_stores(rv,
"iManufacturer"
, newSVuv(desc->iManufacturer));
hv_stores(rv,
"iProduct"
, newSVuv(desc->iProduct));
hv_stores(rv,
"iSerialNumber"
, newSVuv(desc->iSerialNumber));
hv_stores(rv,
"bNumConfigurations"
, newSVuv(desc->bNumConfigurations));
return
newRV_noinc((SV *) rv);
}
static
SV *
version_to_RV(pTHX_
const
struct
libusb_version *version)
{
HV *rv = newHV();
hv_stores(rv,
"major"
, newSVuv(version->major));
hv_stores(rv,
"minor"
, newSVuv(version->minor));
hv_stores(rv,
"micro"
, newSVuv(version->micro));
hv_stores(rv,
"nano"
, newSVuv(version->nano));
hv_stores(rv,
"rc"
, newSVpv(version->rc, 0));
return
newRV_noinc((SV *) rv);
}
static
SV *
pointer_object(pTHX_
const
char
*class_name,
void
*pv)
{
SV *rv = newSV(0);
sv_setref_pv(rv, class_name, pv);
return
rv;
}
MODULE = USB::LibUSB::XS PACKAGE = USB::LibUSB::XS
INCLUDE:
const
-xs.inc
######## Library initialization/deinitialization ##############################
MODULE = USB::LibUSB::XS PACKAGE = USB::LibUSB::XS PREFIX = libusb_
void
libusb_set_debug(USB::LibUSB::XS ctx,
int
level)
void
libusb_init(
char
*
class
)
PPCODE:
libusb_context *ctx;
int
rv = libusb_init(&ctx);
mXPUSHi(rv);
if
(rv == 0)
mXPUSHs(pointer_object(aTHX_
class
, ctx));
void
libusb_exit(USB::LibUSB::XS ctx)
void
DESTROY(USB::LibUSB::XS ctx)
CODE:
do_not_warn_unused(ctx);
######## Device handling and enumeration ######################################
MODULE = USB::LibUSB::XS PACKAGE = USB::LibUSB::XS PREFIX = libusb_
void
libusb_get_device_list(USB::LibUSB::XS ctx)
PPCODE:
libusb_device **list;
ssize_t num = libusb_get_device_list(ctx, &list);
mXPUSHi(num);
ssize_t i;
for
(i = 0; i < num; ++i) {
SV *tmp = newSV(0);
sv_setref_pv(tmp,
"USB::LibUSB::XS::Device"
, (
void
*) list[i]);
mXPUSHs(tmp);
}
if
(num >= 0)
libusb_free_device_list(list, 0);
MODULE = USB::LibUSB::XS PACKAGE = USB::LibUSB::XS::Device PREFIX = libusb_
void
DESTROY(USB::LibUSB::XS::Device dev)
CODE:
do_not_warn_unused(dev);
unsigned
libusb_get_bus_number(USB::LibUSB::XS::Device dev)
unsigned
libusb_get_port_number(USB::LibUSB::XS::Device dev)
void
libusb_get_port_numbers(USB::LibUSB::XS::Device dev)
PPCODE:
int
len = 20;
uint8_t port_numbers[len];
int
num = libusb_get_port_numbers(dev, port_numbers, len);
mXPUSHi(num);
int
i;
for
(i = 0; i < num; ++i) {
mXPUSHu(port_numbers[i]);
}
# libusb_get_port_path is deprecated => do not implement
USB::LibUSB::XS::Device
libusb_get_parent(USB::LibUSB::XS::Device dev)
unsigned
libusb_get_device_address(USB::LibUSB::XS::Device dev)
int
libusb_get_device_speed(USB::LibUSB::XS::Device dev)
int
libusb_get_max_packet_size(USB::LibUSB::XS::Device dev, unsigned
char
endpoint)
int
libusb_get_max_iso_packet_size(USB::LibUSB::XS::Device dev, unsigned
char
endpoint)
USB::LibUSB::XS::Device
libusb_ref_device(USB::LibUSB::XS::Device dev)
void
libusb_unref_device(USB::LibUSB::XS::Device dev)
void
libusb_open(USB::LibUSB::XS::Device dev)
PPCODE:
libusb_device_handle *handle;
int
rv = libusb_open(dev, &handle);
mXPUSHi(rv);
if
(rv == 0)
mXPUSHs(pointer_object(aTHX_
"USB::LibUSB::XS::Device::Handle"
, handle));
MODULE = USB::LibUSB PACKAGE = USB::LibUSB::XS PREFIX = libusb_
USB::LibUSB::XS::Device::Handle
libusb_open_device_with_vid_pid(USB::LibUSB::XS ctx, unsigned vendor_id, unsigned product_id)
MODULE = USB::LibUSB PACKAGE = USB::LibUSB::XS::Device::Handle PREFIX = libusb_
void
DESTROY(USB::LibUSB::XS::Device::Handle handle)
CODE:
do_not_warn_unused(handle);
void
libusb_close(USB::LibUSB::XS::Device::Handle handle)
USB::LibUSB::XS::Device
libusb_get_device(USB::LibUSB::XS::Device::Handle dev_handle)
void
libusb_get_configuration(USB::LibUSB::XS::Device::Handle dev)
PPCODE:
int
config;
int
rv = libusb_get_configuration(dev, &config);
mXPUSHi(rv);
if
(rv == 0)
mXPUSHi(config);
int
libusb_set_configuration(USB::LibUSB::XS::Device::Handle dev,
int
configuration)
int
libusb_claim_interface(USB::LibUSB::XS::Device::Handle dev,
int
interface_number)
int
libusb_release_interface(USB::LibUSB::XS::Device::Handle dev,
int
interface_number)
int
libusb_set_interface_alt_setting(USB::LibUSB::XS::Device::Handle dev,
int
interface_number,
int
alternate_setting)
int
libusb_clear_halt(USB::LibUSB::XS::Device::Handle dev, unsigned endpoint)
int
libusb_reset_device(USB::LibUSB::XS::Device::Handle dev)
int
libusb_kernel_driver_active(USB::LibUSB::XS::Device::Handle dev,
int
interface_number)
int
libusb_detach_kernel_driver(USB::LibUSB::XS::Device::Handle dev,
int
interface_number)
int
libusb_attach_kernel_driver(USB::LibUSB::XS::Device::Handle dev,
int
interface_number)
int
libusb_set_auto_detach_kernel_driver(USB::LibUSB::XS::Device::Handle dev,
int
enable)
######## Miscellaneous ###########################################################
MODULE = USB::LibUSB::XS PACKAGE = USB::LibUSB::XS
int
libusb_has_capability(unsigned capability)
const
char
*
libusb_error_name(
int
error_code)
void
libusb_get_version()
PPCODE:
const
struct
libusb_version *version = libusb_get_version();
mXPUSHs(version_to_RV(aTHX_ version));
int
libusb_setlocale(
const
char
*locale)
const
char
*
libusb_strerror(
int
error_code)
######## USB descriptors ###########################################################
MODULE = USB::LibUSB::XS PACKAGE = USB::LibUSB::XS::Device PREFIX = libusb_
void
libusb_get_device_descriptor(USB::LibUSB::XS::Device dev)
PPCODE:
struct
libusb_device_descriptor desc;
int
rv = libusb_get_device_descriptor(dev, &desc);
mXPUSHi(rv);
mXPUSHs(device_descriptor_to_RV(aTHX_ &desc));
# Can't get ctx arg from libusb_device => Add as extra arg.
void
libusb_get_active_config_descriptor(USB::LibUSB::XS::Device dev, USB::LibUSB::XS ctx)
PPCODE:
struct
libusb_config_descriptor *config;
int
rv = libusb_get_active_config_descriptor(dev, &config);
mXPUSHi(rv);
if
(rv == 0)
mXPUSHs(config_descriptor_to_RV(aTHX_ ctx, config));
void
libusb_get_config_descriptor(USB::LibUSB::XS::Device dev, USB::LibUSB::XS ctx, unsigned config_index)
PPCODE:
struct
libusb_config_descriptor *config;
int
rv = libusb_get_config_descriptor(dev, config_index, &config);
mXPUSHi(rv);
if
(rv == 0) {
mXPUSHs(config_descriptor_to_RV(aTHX_ ctx, config));
libusb_free_config_descriptor(config);
}
void
libusb_get_config_descriptor_by_value(USB::LibUSB::XS::Device dev, USB::LibUSB::XS ctx, unsigned bConfigurationValue)
PPCODE:
struct
libusb_config_descriptor *config;
int
rv = libusb_get_config_descriptor_by_value(dev, bConfigurationValue, &config);
mXPUSHi(rv);
if
(rv == 0) {
mXPUSHs(config_descriptor_to_RV(aTHX_ ctx, config));
libusb_free_config_descriptor(config);
}
MODULE = USB::LibUSB PACKAGE = USB::LibUSB::XS::Device::Handle PREFIX = libusb_
void
libusb_get_bos_descriptor(USB::LibUSB::XS::Device::Handle handle, USB::LibUSB::XS ctx)
PPCODE:
struct
libusb_bos_descriptor *bos;
int
rv = libusb_get_bos_descriptor(handle, &bos);
mXPUSHi(rv);
if
(rv == 0) {
mXPUSHs(bos_descriptor_to_RV(aTHX_ ctx, bos));
libusb_free_bos_descriptor(bos);
}
void
libusb_get_string_descriptor_ascii(USB::LibUSB::XS::Device::Handle dev, unsigned desc_index,
int
length)
PPCODE:
char
*buffer;
Newx(buffer, length,
char
);
int
rv = libusb_get_string_descriptor_ascii(dev, desc_index, (unsigned
char
*) buffer, length);
mXPUSHi(rv);
if
(rv >= 0)
mXPUSHp(buffer, rv);
Safefree(buffer);
void
libusb_get_descriptor(USB::LibUSB::XS::Device::Handle dev, unsigned desc_type, unsigned desc_index,
int
length)
PPCODE:
char
*buffer;
Newx(buffer, length,
char
);
int
rv = libusb_get_descriptor(dev, desc_type, desc_index, (unsigned
char
*) buffer, length);
mXPUSHi(rv);
if
(rv >= 0)
mXPUSHp(buffer, rv);
Safefree(buffer);
void
libusb_get_string_descriptor(USB::LibUSB::XS::Device::Handle dev, unsigned desc_index, unsigned langid,
int
length)
PPCODE:
char
*buffer;
Newx(buffer, length,
char
);
int
rv = libusb_get_string_descriptor(dev, desc_index, langid, (unsigned
char
*) buffer, length);
mXPUSHi(rv);
if
(rv >= 0)
mXPUSHp(buffer, rv);
Safefree(buffer);
######## Device hotplug event notification #########################################
# TODO
######## Asynchronous device I/O ###################################################
# TODO
######## Polling and timing ########################################################
# TODO
######## Synchronous device I/O ####################################################
MODULE = USB::LibUSB PACKAGE = USB::LibUSB::XS::Device::Handle PREFIX = libusb_
void
libusb_control_transfer_write(USB::LibUSB::XS::Device::Handle handle, unsigned bmRequestType, unsigned bRequest, unsigned wValue, unsigned wIndex, SV *data, unsigned timeout)
PPCODE:
const
char
*bytes;
STRLEN len;
bytes = SvPV(data, len);
if
(len == 0)
bytes = NULL;
mXPUSHi(libusb_control_transfer(handle, bmRequestType, bRequest, wValue, wIndex, (unsigned
char
*) bytes, len, timeout));
void
libusb_control_transfer_read(USB::LibUSB::XS::Device::Handle handle, unsigned bmRequestType, unsigned bRequest, unsigned wValue, unsigned wIndex, unsigned length, unsigned timeout)
PPCODE:
char
*data;
Newx(data, length,
char
);
int
rv = libusb_control_transfer(handle, bmRequestType, bRequest, wValue, wIndex, (unsigned
char
*) data, length, timeout);
mXPUSHi(rv);
if
(rv >= 0)
mXPUSHp(data, rv);
Safefree(data);
# Check whether endpoint is host-to-device in high-level code
void
libusb_bulk_transfer_write(USB::LibUSB::XS::Device::Handle handle, unsigned endpoint, SV *data, unsigned timeout)
PPCODE:
STRLEN len;
const
char
*bytes = SvPV(data, len);
int
transferred;
int
rv = libusb_bulk_transfer(handle, endpoint, (unsigned
char
*) bytes, len, &transferred, timeout);
mXPUSHi(rv);
if
(rv == 0 || rv == LIBUSB_ERROR_TIMEOUT)
mXPUSHi(transferred);
# Check whether endpoint is device-to-host in high-level code
void
libusb_bulk_transfer_read(USB::LibUSB::XS::Device::Handle handle, unsigned endpoint,
int
length, unsigned timeout)
PPCODE:
char
*data;
Newx(data, length,
char
);
int
transferred;
int
rv = libusb_bulk_transfer(handle, endpoint, (unsigned
char
*) data, length, &transferred, timeout);
mXPUSHi(rv);
if
(rv == 0 || rv == LIBUSB_ERROR_TIMEOUT)
mXPUSHp(data, transferred);
Safefree(data);
# Check whether endpoint is host-to-device in high-level code
void
libusb_interrupt_transfer_write(USB::LibUSB::XS::Device::Handle handle, unsigned endpoint, SV *data, unsigned timeout)
PPCODE:
STRLEN len;
const
char
*bytes = SvPV(data, len);
int
transferred;
int
rv = libusb_interrupt_transfer(handle, endpoint, (unsigned
char
*) bytes, len, &transferred, timeout);
mXPUSHi(rv);
if
(rv == 0 || rv == LIBUSB_ERROR_TIMEOUT)
mXPUSHi(transferred);
# Check whether endpoint is device-to-host in high-level code
void
libusb_interrupt_transfer_read(USB::LibUSB::XS::Device::Handle handle, unsigned endpoint,
int
length, unsigned timeout)
PPCODE:
char
*data;
Newx(data, length,
char
);
int
transferred;
int
rv = libusb_interrupt_transfer(handle, endpoint, (unsigned
char
*) data, length, &transferred, timeout);
mXPUSHi(rv);
if
(rv == 0 || rv == LIBUSB_ERROR_TIMEOUT)
mXPUSHp(data, transferred);
Safefree(data);