From 6fbf635a468fb86516effb0a3015b2e4736eb850 Mon Sep 17 00:00:00 2001 From: Igor Pashev Date: Mon, 29 Dec 2014 14:54:15 +0000 Subject: Added Solaris backend stubs --- libusb/os/solaris_usb.c | 464 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 464 insertions(+) create mode 100644 libusb/os/solaris_usb.c (limited to 'libusb/os/solaris_usb.c') diff --git a/libusb/os/solaris_usb.c b/libusb/os/solaris_usb.c new file mode 100644 index 0000000..5360452 --- /dev/null +++ b/libusb/os/solaris_usb.c @@ -0,0 +1,464 @@ +/* + * Copyright (c) 2013 Igor Pashev (http://osdyson.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "libusb.h" +#include "libusbi.h" + +static const char dev_usb[] = "/dev/usb"; +static const char devices[] = "/devices"; +static const size_t devices_len = sizeof (devices) - 1; + + +/* + * Backend functions + */ +static int solaris_get_device_list (struct libusb_context *, + struct discovered_devs **); +static int solaris_open (struct libusb_device_handle *); +static void solaris_close (struct libusb_device_handle *); + +static int solaris_get_device_descriptor (struct libusb_device *, + unsigned char *, int *); +static int solaris_get_active_config_descriptor (struct libusb_device *, + unsigned char *, size_t, + int *); +static int solaris_get_config_descriptor (struct libusb_device *, uint8_t, + unsigned char *, size_t, int *); + +static int solaris_get_configuration (struct libusb_device_handle *, int *); +static int solaris_set_configuration (struct libusb_device_handle *, int); + +static int solaris_claim_interface (struct libusb_device_handle *, int); +static int solaris_release_interface (struct libusb_device_handle *, int); + +static int solaris_set_interface_altsetting (struct libusb_device_handle *, + int, int); +static int solaris_clear_halt (struct libusb_device_handle *, unsigned char); +static int solaris_reset_device (struct libusb_device_handle *); +static void solaris_destroy_device (struct libusb_device *); + +static int solaris_submit_transfer (struct usbi_transfer *); +static int solaris_cancel_transfer (struct usbi_transfer *); +static void solaris_clear_transfer_priv (struct usbi_transfer *); +static int solaris_handle_events (struct libusb_context *ctx, struct pollfd *, + nfds_t, int); +static int solaris_clock_gettime (int, struct timespec *); + + +const struct usbi_os_backend solaris_backend = { + .name = "Synchronous Solaris backend", + .init = NULL, + .exit = NULL, + .get_device_list = solaris_get_device_list, + .open = solaris_open, + .close = solaris_close, + + .get_device_descriptor = solaris_get_device_descriptor, + .get_active_config_descriptor = solaris_get_active_config_descriptor, + .get_config_descriptor = solaris_get_config_descriptor, + + .get_configuration = solaris_get_configuration, + .set_configuration = solaris_set_configuration, + + .claim_interface = solaris_claim_interface, + .release_interface = solaris_release_interface, + + .set_interface_altsetting = solaris_set_interface_altsetting, + .clear_halt = solaris_clear_halt, + .reset_device = solaris_reset_device, + + .kernel_driver_active = NULL, + .detach_kernel_driver = NULL, + .attach_kernel_driver = NULL, + + .destroy_device = solaris_destroy_device, + + .submit_transfer = solaris_submit_transfer, + .cancel_transfer = solaris_cancel_transfer, + .clear_transfer_priv = solaris_clear_transfer_priv, + + .handle_events = solaris_handle_events, + + .clock_gettime = solaris_clock_gettime, + + .device_priv_size = 0, + .device_handle_priv_size = 0, + .transfer_priv_size = 0, + .add_iso_packet_size = 0, +}; + + +static int +di_prop_get_int (di_node_t dn, const char *propname, int *out) +{ + int retval; + int *intp; + + usbi_dbg ("looking for \"%s\" property", propname); + + retval = di_prop_lookup_ints (DDI_DEV_T_ANY, dn, propname, &intp); + if (1 == retval) + { + if (NULL != out) + *out = *intp; + usbi_dbg ("found %s = %d", propname, *intp); + } + else if (0 == retval) + usbi_dbg ("property \"%s\" is empty", propname); + else if (retval < 0) + usbi_dbg ("failed to get property \"%s\": %s", propname, + strerror (errno)); + else + usbi_dbg ("got %d values of \"%s\"", retval, propname); + + return retval; +} + +static void +solaris_add_device (struct libusb_context *ctx, + struct discovered_devs **discdevs, + const char *device_node_path) +{ + int busnum = 0; + int devaddr = 0; + int numconf = 1; + unsigned long session_id; + enum libusb_speed speed; + + usbi_info (ctx, "device node \"%s\"", device_node_path); + + di_node_t devnode = di_init (device_node_path, DINFOPROP); + if (DI_NODE_NIL == devnode) + { + usbi_err (ctx, "di_init() failed: %s, skipping", strerror (errno)); + return; + } + + /* From now work with libdevinfo */ + + if (1 != di_prop_get_int (devnode, "assigned-address", &busnum)) + goto cleanup; + + if (1 != di_prop_get_int (devnode, "usb-num-configs", &numconf)) + goto cleanup; + + /* XXX: Super speed is not supported. */ + /* XXX: if no *-speed property exists, it is full-speed device. */ + if (0 <= di_prop_get_int (devnode, "low-speed", NULL)) + speed = LIBUSB_SPEED_LOW; + else if (0 <= di_prop_get_int (devnode, "full-speed", NULL)) + speed = LIBUSB_SPEED_FULL; + else if (0 <= di_prop_get_int (devnode, "high-speed", NULL)) + speed = LIBUSB_SPEED_HIGH; + else if (0 <= di_prop_get_int (devnode, "super-speed", NULL)) + speed = LIBUSB_SPEED_SUPER; + else + speed = LIBUSB_SPEED_FULL; + + + /* get device address - a number after @ in device_node_path: + * in "pci@0,0/pci106b,3f@6/device@2" device address is 2 + */ + char *at = strrchr (device_node_path, '@'); + if (NULL == at) + { /* can't happen! */ + usbi_err (ctx, + "failed to parse device node to device address, skipping"); + goto cleanup; + } + at++; + devaddr = atoi (at); + + session_id = busnum << 8 | devaddr; + usbi_dbg ("busnum %d devaddr %d session_id %u", busnum, devaddr, + session_id); + +cleanup: + di_fini (devnode); + return; +} + + +int +solaris_get_device_list (struct libusb_context *ctx, + struct discovered_devs **discdevs) +{ + char vidpid_path[sizeof ("/dev/usb/vvvv.pppp")]; + char devstat_path[sizeof ("/dev/usb/vvvv.pppp/iiii/devstat")]; /* 9999 instances should be enough. */ + + /* for realpath(): */ + char + device_path[sizeof + ("/devices/pci@NNNN,MMMM/pciXXXX,YYYY@IIII/device@IIII:AAAA.BBBB.devstat")]; + + regex_t regex; + int retval; + char *device_node_path; + + if (0 != regcomp (®ex, "[0-9a-f]+\\.[0-9a-f]+", REG_EXTENDED)) + { + usbi_err (ctx, "regcomp() failed"); + return (LIBUSB_ERROR_NO_MEM); + } + + /* open /dev/usb for browsing. */ + DIR *dev_usb_dir = opendir (dev_usb); + if (NULL == dev_usb_dir) + { + usbi_err (ctx, "opendir(\"%s\") failed: %s", dev_usb, strerror (errno)); + regfree (®ex); + return (LIBUSB_ERROR_ACCESS); + } + + struct dirent *vidpid; + usbi_dbg ("start browsing %s", dev_usb); + while ((vidpid = readdir (dev_usb_dir)) != NULL) + { + if (0 != regexec (®ex, vidpid->d_name, 0, NULL, 0)) + { + if ('.' != vidpid->d_name[0]) + usbi_dbg ("skipping %s", vidpid->d_name); + continue; + } + + usbi_dbg ("found %s", vidpid->d_name); + + retval = + snprintf (vidpid_path, sizeof (vidpid_path), "%s/%s", dev_usb, + vidpid->d_name); + if (retval >= sizeof (vidpid_path)) + { + usbi_err (ctx, "vidpid_path: snprintf() failed, skipping"); + continue; + } + + /* open /dev/usb/. for browsing. */ + DIR *vidpid_dir = opendir (vidpid_path); + if (NULL == vidpid_dir) + { + usbi_err (ctx, "opendir(\"%s\") failed: %s, skipping", vidpid_path, + strerror (errno)); + continue; + } + + struct dirent *inst; + usbi_dbg ("start browsing %s", vidpid_path); + while ((inst = readdir (vidpid_dir)) != NULL) + { + if ('.' == inst->d_name[0]) + continue; + + usbi_dbg ("found instance %s", inst->d_name); + + usbi_info (ctx, "found ugen device %s/%s", vidpid_path, + inst->d_name); + + /* We need *any* file in the instance subdir + * only to get the real device path under /devices. + * E. g. given /dev/usb/a12.1/0/devstat -> /devices/pci@0,0/pci106b,3f@6/device@2:a12.1.devstat + * we should get /devices/pci@0,0/pci106b,3f@6/device@2 + * devstat always exists, so use it. + */ + retval = + snprintf (devstat_path, sizeof (devstat_path), "%s/%s/devstat", + vidpid_path, inst->d_name); + if (retval >= sizeof (devstat_path)) + { + usbi_err (ctx, "devstat_path: snprintf() failed, skipping"); + continue; + } + + device_node_path = realpath (devstat_path, device_path); + if (NULL == device_node_path) + { + usbi_err (ctx, "realpath() for \"%s\" failed: %s", devstat_path, + strerror (errno)); + continue; + } + + usbi_dbg ("device path \"%s\"", device_path); + + /* is real path under /devices directory? */ + if (strncmp (device_path, devices, devices_len) != 0) + { + /* No */ + usbi_warn (ctx, "\"%s\" is not under /devices, skipping", + device_path); + continue; + } + + /* for di_init() we need to: + * + * a) strip /devices from the beginning of device_path + * b) strip everything after the colon in device_path + * + * E. g. /devices/pci@0,0/pci106b,3f@6/device@2:a12.1.devstat + * should become /pci@0,0/pci106b,3f@6/device@2 + */ + + /* a) */ + device_node_path += devices_len; + + /* b) */ + char *colon = strrchr (device_node_path, ':'); + if (colon) + *colon = '\0'; + else + usbi_warn (ctx, "no colon in device node path"); + + solaris_add_device (ctx, discdevs, device_node_path); + } + usbi_dbg ("stop browsing %s", vidpid_path); + } + usbi_dbg ("stop browsing %s", dev_usb); + + (void) closedir (dev_usb_dir); + + return (LIBUSB_ERROR_NO_DEVICE); +} + +int +solaris_open (struct libusb_device_handle *handle) +{ + return (LIBUSB_ERROR_NO_DEVICE); +} + +void +solaris_close (struct libusb_device_handle *handle) +{ +} + +int +solaris_get_device_descriptor (struct libusb_device *dev, unsigned char *buf, + int *host_endian) +{ + return (LIBUSB_ERROR_NO_DEVICE); +} + +int +solaris_get_active_config_descriptor (struct libusb_device *dev, + unsigned char *buf, size_t len, + int *host_endian) +{ + return (LIBUSB_ERROR_NO_DEVICE); +} + +int +solaris_get_config_descriptor (struct libusb_device *dev, uint8_t idx, + unsigned char *buf, size_t len, + int *host_endian) +{ + return (LIBUSB_ERROR_NO_DEVICE); +} + +int +solaris_get_configuration (struct libusb_device_handle *handle, int *config) +{ + return (LIBUSB_ERROR_NO_DEVICE); +} + +int +solaris_set_configuration (struct libusb_device_handle *handle, int config) +{ + return (LIBUSB_ERROR_NO_DEVICE); +} + +int +solaris_claim_interface (struct libusb_device_handle *handle, int iface) +{ + return (LIBUSB_ERROR_NO_DEVICE); +} + +int +solaris_release_interface (struct libusb_device_handle *handle, int iface) +{ + return (LIBUSB_ERROR_NO_DEVICE); +} + +int +solaris_set_interface_altsetting (struct libusb_device_handle *handle, + int iface, int altsetting) +{ + return (LIBUSB_ERROR_NO_DEVICE); +} + +int +solaris_clear_halt (struct libusb_device_handle *handle, + unsigned char endpoint) +{ + return (LIBUSB_ERROR_NO_DEVICE); +} + +int +solaris_reset_device (struct libusb_device_handle *handle) +{ + return (LIBUSB_ERROR_NO_DEVICE); +} + +void +solaris_destroy_device (struct libusb_device *dev) +{ +} + +int +solaris_submit_transfer (struct usbi_transfer *itransfer) +{ + return (LIBUSB_ERROR_NO_DEVICE); +} + +int +solaris_cancel_transfer (struct usbi_transfer *itransfer) +{ + usbi_dbg (""); + + return (LIBUSB_ERROR_NOT_SUPPORTED); +} + +void +solaris_clear_transfer_priv (struct usbi_transfer *itransfer) +{ +} + +int +solaris_handle_events (struct libusb_context *ctx, struct pollfd *fds, + nfds_t nfds, int num_ready) +{ + return (LIBUSB_ERROR_NO_DEVICE); +} + +int +solaris_clock_gettime (int clkid, struct timespec *tp) +{ + usbi_dbg ("clock %d", clkid); + + if (clkid == USBI_CLOCK_REALTIME) + return clock_gettime (CLOCK_REALTIME, tp); + + if (clkid == USBI_CLOCK_MONOTONIC) + return clock_gettime (CLOCK_MONOTONIC, tp); + + return (LIBUSB_ERROR_INVALID_PARAM); +} -- cgit v1.2.3