Exemple #1
0
int
_access_endpoint(struct libusb_transfer *transfer)
{
	struct handle_priv *hpriv;
	struct device_priv *dpriv;
	char devnode[16];
	int fd, endpt;
	mode_t mode;

	hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
	dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;

	endpt = UE_GET_ADDR(transfer->endpoint);
	mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY;

	usbi_dbg("endpoint %d mode %d", endpt, mode);

	if (hpriv->endpoints[endpt] < 0) {
		/* Pick the right endpoint node */
		snprintf(devnode, sizeof(devnode), DEVPATH "%s.%02d",
		    dpriv->devname, endpt);

		/* We may need to read/write to the same endpoint later. */
		if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO))
			if ((fd = open(devnode, mode)) < 0)
				return (-1);

		hpriv->endpoints[endpt] = fd;
	}

	return (hpriv->endpoints[endpt]);
}
API_EXPORTED usb_dev_handle *usb_open(struct usb_device *dev)
{
	int r;
	usbi_dbg("");

	usb_dev_handle *udev = malloc(sizeof(*udev));
	if (!udev)
		return NULL;

	r = libusb_open((libusb_device *) dev->dev, &udev->handle);
	if (r < 0) {
		if (r == LIBUSB_ERROR_ACCESS) {
			usbi_info("Device open failed due to a permission denied error.");
			usbi_info("libusb requires write access to USB device nodes.");
		}
		usbi_err("could not open device, error %d", r);
		free(udev);
		errno = libusb_to_errno(r);
		return NULL;
	}

	udev->last_claimed_interface = -1;
	udev->device = dev;
	return udev;
}
Exemple #3
0
int
obsd_cancel_transfer(struct usbi_transfer *itransfer)
{
	usbi_dbg("");

	return (LIBUSB_ERROR_NOT_SUPPORTED);
}
Exemple #4
0
void
obsd_clear_transfer_priv(struct usbi_transfer *itransfer)
{
	usbi_dbg("");

	/* Nothing to do */
}
Exemple #5
0
int
obsd_reset_device(struct libusb_device_handle *handle)
{
	usbi_dbg("");

	return (LIBUSB_ERROR_NOT_SUPPORTED);
}
Exemple #6
0
int
obsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
{
	struct usb_ctl_request req;
	int fd, err;

	if ((fd = _bus_open(handle->dev->bus_number)) < 0)
		return _errno_to_libusb(errno);

	usbi_dbg("");

	req.ucr_addr = handle->dev->device_address;
	req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT;
	req.ucr_request.bRequest = UR_CLEAR_FEATURE;
	USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT);
	USETW(req.ucr_request.wIndex, endpoint);
	USETW(req.ucr_request.wLength, 0);

	if (ioctl(fd, USB_REQUEST, &req) < 0) {
		err = errno;
		close(fd);
		return _errno_to_libusb(err);
	}
	close(fd);

	return (LIBUSB_SUCCESS);
}
Exemple #7
0
int
obsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
    unsigned char *buf, size_t len, int *host_endian)
{
	struct usb_device_fdesc udf;
	int fd, err;

	if ((fd = _bus_open(dev->bus_number)) < 0)
		return _errno_to_libusb(errno);

	udf.udf_bus = dev->bus_number;
	udf.udf_addr = dev->device_address;
	udf.udf_config_index = idx;
	udf.udf_size = len;
	udf.udf_data = buf;

	usbi_dbg("index %d, len %d", udf.udf_config_index, len);

	if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) {
		err = errno;
		close(fd);
		return _errno_to_libusb(err);
	}
	close(fd);

	*host_endian = 0;

	return (len);
}
Exemple #8
0
static void LIBUSB_CALL sync_transfer_cb(struct libusb_transfer *transfer)
{
	int *completed = transfer->user_data;
	*completed = 1;
	usbi_dbg("actual_length=%d", transfer->actual_length);
	/* caller interprets result and frees transfer */
}
Exemple #9
0
struct discovered_devs *discovered_devs_append(
    struct discovered_devs *discdevs, struct libusb_device *dev)
{
    size_t len = discdevs->len;
    size_t capacity;


    if (len < discdevs->capacity) {
        discdevs->devices[len] = libusb_ref_device(dev);
        discdevs->len++;
        return discdevs;
    }


    usbi_dbg("need to increase capacity");
    capacity = discdevs->capacity + DISCOVERED_DEVICES_SIZE_STEP;
    discdevs = usbi_reallocf(discdevs,
                             sizeof(*discdevs) + (sizeof(void *) * capacity));
    if (discdevs) {
        discdevs->capacity = capacity;
        discdevs->devices[len] = libusb_ref_device(dev);
        discdevs->len++;
    }

    return discdevs;
}
Exemple #10
0
API_EXPORTED int usb_claim_interface(usb_dev_handle *dev, int interface)
{
	
	int r;
	usbi_dbg("interface %d", interface);

	r = libusb_claim_interface(dev->handle, interface);
	
	if(r == -6){
		int err = libusb_kernel_driver_active(dev->handle, interface);
		
		if(err == 1){
			err = libusb_detach_kernel_driver(dev->handle, interface);
			
			r = libusb_claim_interface(dev->handle, interface);
		}
	}
	
	
	if (r == 0) {
		dev->last_claimed_interface = interface;
		return 0;
	}

	return compat_err(r);
}
Exemple #11
0
int
obsd_open(struct libusb_device_handle *handle)
{
	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
	char devnode[16];

	if (dpriv->devname) {
		/*
		 * Only open ugen(4) attached devices read-write, all
		 * read-only operations are done through the bus node.
		 */
		snprintf(devnode, sizeof(devnode), DEVPATH "%s.00",
		    dpriv->devname);
		dpriv->fd = open(devnode, O_RDWR);
		if (dpriv->fd < 0)
			return _errno_to_libusb(errno);

		usbi_dbg("open %s: fd %d", devnode, dpriv->fd);
	}

	if (pipe(hpriv->pipe) < 0)
		return _errno_to_libusb(errno);

	return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->pipe[0], POLLIN);
}
Exemple #12
0
API_EXPORTED int usb_close(usb_dev_handle *dev)
{
	usbi_dbg("");
	libusb_close(dev->handle);
	free(dev);
	return 0;
}
Exemple #13
0
ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx,
        libusb_device ***list)
{
    struct discovered_devs *discdevs = discovered_devs_alloc();
    struct libusb_device **ret;
    int r = 0;
    ssize_t i, len;
    USBI_GET_CONTEXT(ctx);
    usbi_dbg("");

    if (!discdevs)
        return LIBUSB_ERROR_NO_MEM;

    if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {

        struct libusb_device *dev;

        if (usbi_backend->hotplug_poll)
            usbi_backend->hotplug_poll();

        usbi_mutex_lock(&ctx->usb_devs_lock);
        list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) {
            discdevs = discovered_devs_append(discdevs, dev);

            if (!discdevs) {
                r = LIBUSB_ERROR_NO_MEM;
                break;
            }
        }
        usbi_mutex_unlock(&ctx->usb_devs_lock);
    } else {
Exemple #14
0
/* Before using the hash table we must allocate memory for it.
   We allocate one element more as the found prime number says.
   This is done for more effective indexing as explained in the
   comment for the hash function.  */
static bool htab_create(struct libusb_context *ctx, unsigned long nel)
{
    if (htab_table != NULL) {
        usbi_err(ctx, "hash table already allocated");
        return true;
    }

    // Create a mutex
    usbi_mutex_init(&htab_write_mutex, NULL);

    // Change nel to the first prime number not smaller as nel.
    nel |= 1;
    while (!isprime(nel))
        nel += 2;

    htab_size = nel;
    usbi_dbg("using %lu entries hash table", nel);
    htab_filled = 0;

    // allocate memory and zero out.
    htab_table = calloc(htab_size + 1, sizeof(htab_entry));
    if (htab_table == NULL) {
        usbi_err(ctx, "could not allocate space for hash table");
        return false;
    }

    return true;
}
Exemple #15
0
API_EXPORTED int usb_control_msg(usb_dev_handle *dev, int bmRequestType,
	int bRequest, int wValue, int wIndex, char *bytes, int size, int timeout)
{
	int r;
	usbi_dbg("RQT=%x RQ=%x V=%x I=%x len=%d timeout=%d", bmRequestType,
		bRequest, wValue, wIndex, size, timeout);

	r = libusb_control_transfer(dev->handle, bmRequestType & 0xff,
		bRequest & 0xff, wValue & 0xffff, wIndex & 0xffff, bytes, size & 0xffff,
		timeout);

	if (r >= 0)
		return r;

	switch (r) {
	case LIBUSB_ERROR_TIMEOUT:
		errno = ETIMEDOUT;
		return -ETIMEDOUT;
	case LIBUSB_ERROR_PIPE:
		errno = EPIPE;
		return -EPIPE;
	default:
		return r;
	}
}
Exemple #16
0
/* return the number of bytes read/written */
static int
usb_do_io(int fd, int stat_fd, char *data, size_t size, int flag, int *status)
{
	int error;
	int ret = -1;

	usbi_dbg("usb_do_io(): datafd=%d statfd=%d size=0x%x flag=%s",
	    fd, stat_fd, size, flag? "WRITE":"READ");

	switch (flag) {
	case READ:
		errno = 0;
		ret = read(fd, data, size);
		usb_dump_data(data, size);
		break;
	case WRITE:
		usb_dump_data(data, size);
		errno = 0;
		ret = write(fd, data, size);
		break;
	}

	usbi_dbg("usb_do_io(): amount=%d", ret);

	if (ret < 0) {
		int save_errno = errno;

		usbi_dbg("TID=%x io %s errno=%d(%s) ret=%d", pthread_self(),
		    flag?"WRITE":"READ", errno, strerror(errno), ret);

		/* sunos_usb_get_status will do a read and overwrite errno */
		error = sunos_usb_get_status(stat_fd);
		usbi_dbg("io status=%d errno=%d(%s)", error,
			save_errno, strerror(save_errno));

		if (status) {
			*status = save_errno;
		}

		return (save_errno);

	} else if (status) {
		*status = 0;
	}

	return (ret);
}
Exemple #17
0
static int wince_clock_gettime(int clk_id, struct timespec *tp)
{
	FILETIME filetime;
	ULARGE_INTEGER rtime;
	DWORD r;
	SYSTEMTIME st;
	switch(clk_id) {
	case USBI_CLOCK_MONOTONIC:
		if (hires_frequency != 0) {
			while (1) {
				InterlockedIncrement((LONG*)&request_count[0]);
				SetEvent(timer_request[0]);
				r = WaitForSingleObject(timer_response, TIMER_REQUEST_RETRY_MS);
				switch(r) {
				case WAIT_OBJECT_0:
					WaitForSingleObject(timer_mutex, INFINITE);
					*tp = timer_tp;
					ReleaseMutex(timer_mutex);
					return LIBUSB_SUCCESS;
				case WAIT_TIMEOUT:
					usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?");
					break; // Retry until successful
				default:
					usbi_dbg("WaitForSingleObject failed: %s", windows_error_str(0));
					return LIBUSB_ERROR_OTHER;
				}
			}
		}
		// Fall through and return real-time if monotonic was not detected @ timer init
	case USBI_CLOCK_REALTIME:
		// We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx
		// with a predef epoch_time to have an epoch that starts at 1970.01.01 00:00
		// Note however that our resolution is bounded by the Windows system time
		// functions and is at best of the order of 1 ms (or, usually, worse)
		GetSystemTime(&st);
		SystemTimeToFileTime(&st, &filetime);
		rtime.LowPart = filetime.dwLowDateTime;
		rtime.HighPart = filetime.dwHighDateTime;
		rtime.QuadPart -= epoch_time;
		tp->tv_sec = (long)(rtime.QuadPart / 10000000);
		tp->tv_nsec = (long)((rtime.QuadPart % 10000000)*100);
		return LIBUSB_SUCCESS;
	default:
		return LIBUSB_ERROR_INVALID_PARAM;
	}
}
Exemple #18
0
/** \ingroup desc
 * Get the USB device descriptor for a given device.
 *
 * This is a non-blocking function; the device descriptor is cached in memory.
 *
 * Note since libusbx-1.0.16, \ref LIBUSBX_API_VERSION >= 0x01000102, this
 * function always succeeds.
 *
 * \param dev the device
 * \param desc output location for the descriptor data
 * \returns 0 on success or a LIBUSB_ERROR code on failure
 */
int API_EXPORTED libusb_get_device_descriptor(libusb_device *dev,
	struct libusb_device_descriptor *desc)
{
	usbi_dbg("");
	memcpy((unsigned char *) desc, (unsigned char *) &dev->device_descriptor,
	       sizeof (dev->device_descriptor));
	return 0;
}
Exemple #19
0
static int windows_clock_gettime(int clk_id, struct timespec *tp)
{
	struct timer_request request;
#if !defined(_MSC_VER) || (_MSC_VER < 1900)
	FILETIME filetime;
	ULARGE_INTEGER rtime;
#endif
	DWORD r;

	switch (clk_id) {
	case USBI_CLOCK_MONOTONIC:
		if (timer_thread) {
			request.tp = tp;
			request.event = CreateEvent(NULL, FALSE, FALSE, NULL);
			if (request.event == NULL)
				return LIBUSB_ERROR_NO_MEM;

			if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_REQUEST, 0, (LPARAM)&request)) {
				usbi_err(NULL, "PostThreadMessage failed for timer thread: %s", windows_error_str(0));
				CloseHandle(request.event);
				return LIBUSB_ERROR_OTHER;
			}

			do {
				r = WaitForSingleObject(request.event, TIMER_REQUEST_RETRY_MS);
				if (r == WAIT_TIMEOUT)
					usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?");
				else if (r == WAIT_FAILED)
					usbi_err(NULL, "WaitForSingleObject failed: %s", windows_error_str(0));
			} while (r == WAIT_TIMEOUT);
			CloseHandle(request.event);

			if (r == WAIT_OBJECT_0)
				return LIBUSB_SUCCESS;
			else
				return LIBUSB_ERROR_OTHER;
		}
		// Fall through and return real-time if monotonic was not detected @ timer init
	case USBI_CLOCK_REALTIME:
#if defined(_MSC_VER) && (_MSC_VER >= 1900)
		timespec_get(tp, TIME_UTC);
#else
		// We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx
		// with a predef epoch time to have an epoch that starts at 1970.01.01 00:00
		// Note however that our resolution is bounded by the Windows system time
		// functions and is at best of the order of 1 ms (or, usually, worse)
		GetSystemTimeAsFileTime(&filetime);
		rtime.LowPart = filetime.dwLowDateTime;
		rtime.HighPart = filetime.dwHighDateTime;
		rtime.QuadPart -= EPOCH_TIME;
		tp->tv_sec = (long)(rtime.QuadPart / 10000000);
		tp->tv_nsec = (long)((rtime.QuadPart % 10000000) * 100);
#endif
		return LIBUSB_SUCCESS;
	default:
		return LIBUSB_ERROR_INVALID_PARAM;
	}
}
Exemple #20
0
API_EXPORTED int usb_set_altinterface(usb_dev_handle *dev, int alternate)
{
	usbi_dbg("alternate %d", alternate);
	if (dev->last_claimed_interface < 0)
		return -(errno=EINVAL);
	
	return compat_err(libusb_set_interface_alt_setting(dev->handle,
		dev->last_claimed_interface, alternate));
}
Exemple #21
0
int API_EXPORTED libusb_attach_kernel_driver(libusb_device_handle *dev,
	int interface_number)
{
	usbi_dbg("interface %d", interface_number);
	if (usbi_backend->attach_kernel_driver)
		return usbi_backend->attach_kernel_driver(dev, interface_number);
	else
		return LIBUSB_ERROR_NOT_SUPPORTED;
}
void
obsd_destroy_device(struct libusb_device *dev)
{
	struct device_priv *dpriv = (struct device_priv *)dev->os_priv;

	usbi_dbg("");

	free(dpriv->cdesc);
}
Exemple #23
0
static inline void setup_cancel_io(void)
{
	HMODULE hKernel32 = GetModuleHandleA("KERNEL32");
	if (hKernel32 != NULL) {
		pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED))
			GetProcAddress(hKernel32, "CancelIoEx");
	}
	usbi_dbg("Will use CancelIo%s for I/O cancellation",
		Use_Duplicate_Handles?"":"Ex");
}
Exemple #24
0
int
sunos_claim_interface(struct libusb_device_handle *handle, int iface)
{
	usbi_dbg("iface %d", iface);
	if (iface < 0) {
		return (LIBUSB_ERROR_INVALID_PARAM);
	}

	return (LIBUSB_SUCCESS);
}
Exemple #25
0
int
sunos_get_active_config_descriptor(struct libusb_device *dev,
    uint8_t *buf, size_t len, int *host_endian)
{
	sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv;
	struct libusb_config_descriptor *cfg;
	int proplen;
	di_node_t node;
	uint8_t	*rdata;

	/*
	 * Keep raw configuration descriptors updated, in case config
	 * has ever been changed through setCfg.
	 */
	if ((node = di_init(dpriv->phypath, DINFOCPYALL)) == DI_NODE_NIL) {
		usbi_dbg("di_int() failed: %s", strerror(errno));
		return (LIBUSB_ERROR_IO);
	}
	proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node,
	    "usb-raw-cfg-descriptors", &rdata);
	if (proplen <= 0) {
		usbi_dbg("can't find raw config descriptors");

		return (LIBUSB_ERROR_IO);
	}
	dpriv->raw_cfgdescr = realloc(dpriv->raw_cfgdescr, proplen);
	if (dpriv->raw_cfgdescr == NULL) {
		return (LIBUSB_ERROR_NO_MEM);
	} else {
		bcopy(rdata, dpriv->raw_cfgdescr, proplen);
		dpriv->cfgvalue = ((struct libusb_config_descriptor *)
		    rdata)->bConfigurationValue;
	}
	di_fini(node);

	cfg = (struct libusb_config_descriptor *)dpriv->raw_cfgdescr;
	len = MIN(len, libusb_le16_to_cpu(cfg->wTotalLength));
	memcpy(buf, dpriv->raw_cfgdescr, len);
	*host_endian = 0;
	usbi_dbg("path:%s len %d", dpriv->phypath, len);

	return (len);
}
static void *linux_udev_event_thread_main(void *arg)
{
	struct pollfd fds = {.fd = udev_monitor_fd,
			     .events = POLLIN};

	usbi_dbg("udev event thread entering.");

	while (1 == poll(&fds, 1, -1)) {
		if (NULL == udev_monitor || POLLIN != fds.revents) {
			break;
		}

		udev_hotplug_event();
	}

	usbi_dbg("udev event thread exiting");

	return NULL;
}
Exemple #27
0
static int wince_handle_events(
	struct libusb_context *ctx,
	struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready)
{
	struct wince_transfer_priv* transfer_priv = NULL;
	POLL_NFDS_TYPE i = 0;
	BOOL found = FALSE;
	struct usbi_transfer *transfer;
	DWORD io_size, io_result;
	int r = LIBUSB_SUCCESS;

	usbi_mutex_lock(&ctx->open_devs_lock);
	for (i = 0; i < nfds && num_ready > 0; i++) {

		usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents);

		if (!fds[i].revents)
			continue;

		num_ready--;

		// Because a Windows OVERLAPPED is used for poll emulation,
		// a pollable fd is created and stored with each transfer
		usbi_mutex_lock(&ctx->flying_transfers_lock);
		list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) {
			transfer_priv = usbi_transfer_get_os_priv(transfer);
			if (transfer_priv->pollable_fd.fd == fds[i].fd) {
				found = TRUE;
				break;
			}
		}
		usbi_mutex_unlock(&ctx->flying_transfers_lock);

		if (found && HasOverlappedIoCompleted(transfer_priv->pollable_fd.overlapped)) {
			io_result = (DWORD)transfer_priv->pollable_fd.overlapped->Internal;
			io_size = (DWORD)transfer_priv->pollable_fd.overlapped->InternalHigh;
			usbi_remove_pollfd(ctx, transfer_priv->pollable_fd.fd);
			// let handle_callback free the event using the transfer wfd
			// If you don't use the transfer wfd, you run a risk of trying to free a
			// newly allocated wfd that took the place of the one from the transfer.
			wince_handle_callback(transfer, io_result, io_size);
		} else if (found) {
			usbi_err(ctx, "matching transfer for fd %d has not completed", fds[i]);
			r = LIBUSB_ERROR_OTHER;
			break;
		} else {
			usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]);
			r = LIBUSB_ERROR_NOT_FOUND;
			break;
		}
	}
	usbi_mutex_unlock(&ctx->open_devs_lock);

	return r;
}
Exemple #28
0
static void wince_exit(void)
{
	int i;
	HANDLE semaphore;
	TCHAR sem_name[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID)

	_stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)GetCurrentProcessId()&0xFFFFFFFF);
	semaphore = CreateSemaphore(NULL, 1, 1, sem_name);
	if (semaphore == NULL) {
		return;
	}

	// A successful wait brings our semaphore count to 0 (unsignaled)
	// => any concurent wait stalls until the semaphore release
	if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
		CloseHandle(semaphore);
		return;
	}

	// Only works if exits and inits are balanced exactly
	if (--concurrent_usage < 0) {	// Last exit
		exit_polling();

		if (timer_thread) {
			SetEvent(timer_request[1]); // actually the signal to quit the thread.
			if (WAIT_OBJECT_0 != WaitForSingleObject(timer_thread, INFINITE)) {
				usbi_dbg("could not wait for timer thread to quit");
				TerminateThread(timer_thread, 1);
			}
			CloseHandle(timer_thread);
			timer_thread = NULL;
		}
		for (i = 0; i < 2; i++) {
			if (timer_request[i]) {
				CloseHandle(timer_request[i]);
				timer_request[i] = NULL;
			}
		}
		if (timer_response) {
			CloseHandle(timer_response);
			timer_response = NULL;
		}
		if (timer_mutex) {
			CloseHandle(timer_mutex);
			timer_mutex = NULL;
		}
		if (driver_handle != INVALID_HANDLE_VALUE) {
			UkwCloseDriver(driver_handle);
			driver_handle = INVALID_HANDLE_VALUE;
		}
	}

	ReleaseSemaphore(semaphore, 1, NULL);	// increase count back to 1
	CloseHandle(semaphore);
}
Exemple #29
0
int
sunos_get_configuration(struct libusb_device_handle *handle, int *config)
{
	sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv;

	*config = dpriv->cfgvalue;

	usbi_dbg("bConfigurationValue %d", *config);

	return (LIBUSB_SUCCESS);
}
Exemple #30
0
void
sunos_destroy_device(struct libusb_device *dev)
{
	sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv;

	usbi_dbg("");

	free(dpriv->raw_cfgdescr);
	free(dpriv->ugenpath);
	free(dpriv->phypath);
}