From ee3e3ff5c201f0b8942ea912ce7ebfdccb32af52 Mon Sep 17 00:00:00 2001 From: Andrew Thompson Date: Fri, 27 Feb 2009 17:27:16 +0000 Subject: [PATCH] Change USB over to make_dev() for all device nodes, previously it hooked into the devfs clone handler to open the (invisible) devices on the fly. The /dev entries are layed out as follows, /dev/usbctl = master device /dev/usb/0.1.0.5 = usb device, (...) /dev/ugen0.1 -> usb/0.1.0.0 = ugen link to ctrl endpoint This also removes the custom permissions model from USB. Bump __FreeBSD_version to 800066. Submitted by: rink (earlier version) --- lib/libusb20/libusb20.3 | 140 --- lib/libusb20/libusb20.c | 154 ---- lib/libusb20/libusb20.h | 19 - lib/libusb20/libusb20_int.h | 32 - lib/libusb20/libusb20_ugen20.c | 194 +---- sys/dev/sound/usb/uaudio.c | 18 +- sys/dev/usb/bluetooth/ubtbcmfw.c | 13 +- sys/dev/usb/image/uscanner.c | 10 +- sys/dev/usb/input/uhid.c | 12 +- sys/dev/usb/input/ums.c | 14 +- sys/dev/usb/misc/ufm.c | 11 +- sys/dev/usb/serial/ulpt.c | 20 +- sys/dev/usb/storage/urio.c | 12 +- sys/dev/usb/usb_bus.h | 1 - sys/dev/usb/usb_core.h | 34 - sys/dev/usb/usb_dev.c | 1367 +++++++++--------------------- sys/dev/usb/usb_dev.h | 52 +- sys/dev/usb/usb_device.c | 182 +++- sys/dev/usb/usb_device.h | 11 +- sys/dev/usb/usb_generic.c | 19 +- sys/dev/usb/usb_ioctl.h | 24 +- sys/sys/param.h | 2 +- usr.sbin/usbconfig/dump.c | 101 --- usr.sbin/usbconfig/dump.h | 3 - usr.sbin/usbconfig/usbconfig.c | 139 +-- 25 files changed, 643 insertions(+), 1941 deletions(-) diff --git a/lib/libusb20/libusb20.3 b/lib/libusb20/libusb20.3 index 3fe864226652..bbf98fdd6ac4 100644 --- a/lib/libusb20/libusb20.3 +++ b/lib/libusb20/libusb20.3 @@ -514,72 +514,6 @@ returned. . .Pp . -.Fn libusb20_dev_set_owner pdev uid gid -This function will set the ownership of the given USB device. -. -This function returns zero on success else a LIBUSB20_ERROR value is -returned. -. -.Pp -. -.Fn libusb20_dev_set_perm pdev mode -This function will set the permissions of the given USB device. -. -This function returns zero on success else a LIBUSB20_ERROR value is -returned. -. -.Pp -. -.Fn libusb20_dev_set_iface_owner pdev iface_index uid gid -This function will set the ownership of the given USB interface. -. -This function returns zero on success else a LIBUSB20_ERROR value is -returned. -. -.Pp -. -.Fn libusb20_dev_set_iface_perm pdev iface_index mode -This function will set the permissions of the given USB interface. -. -This function returns zero on success else a LIBUSB20_ERROR value is -returned. -. -.Pp -. -.Fn libusb20_dev_get_owner pdev puid pgid -This function will retrieve the current USB device ownership. -. -This function returns zero on success else a LIBUSB20_ERROR value is -returned. -. -.Pp -. -.Fn libusb20_dev_get_perm pdev pmode -This function will retrieve the current USB device permissions. -. -This function returns zero on success else a LIBUSB20_ERROR value is -returned. -. -.Pp -. -.Fn libusb20_dev_get_iface_owner pdev iface_index puid pgid -This function will retrieve the current USB interface ownership for -the given USB interface. -. -This function returns zero on success else a LIBUSB20_ERROR value is -returned. -. -.Pp -. -.Fn libusb20_dev_get_iface_perm pdev iface_index pmode -This function will retrieve the current USB interface permissions for -the given USB interface. -. -This function returns zero on success else a LIBUSB20_ERROR value is -returned. -. -.Pp -. .Fn libusb20_dev_get_device_desc pdev This function returns a pointer to the decoded and host endian version of the device descriptor. @@ -663,39 +597,6 @@ A timeout value can be specified which is passed on to the .Xr 2 poll function. . -.Sh USB BUS OPERATIONS -. -.Fn libusb20_bus_set_owner pbackend bus_index uid gid -This function will set the ownership for the given USB bus. -. -This function returns zero on success else a LIBUSB20_ERROR value is -returned. -. -.Pp -. -.Fn libusb20_bus_set_perm pbackend bus_index mode -This function will set the permissions for the given USB bus. -. -This function returns zero on success else a LIBUSB20_ERROR value is -returned. -. -.Pp -. -.Fn libusb20_bus_get_owner pbackend bus_index puid pgid -This function will retrieve the ownership for the given USB bus. -. -This function returns zero on success else a LIBUSB20_ERROR value is -returned. -. -.Pp -. -.Fn libusb20_bus_get_perm pbackend bus_index pmode -This function will retrieve the permissions for the given USB bus. -. -This function returns zero on success else a LIBUSB20_ERROR value is -returned. -. -. .Sh USB BACKEND OPERATIONS . .Fn libusb20_be_get_template pbackend ptemp @@ -772,47 +673,6 @@ returned. If the given quirk does not exist LIBUSB20_ERROR_NOT_FOUND is returned. . -.Pp -. -.Fn libusb20_be_set_owner pbackend uid gid -This function will set the ownership for the given backend. -. -This function returns zero on success else a LIBUSB20_ERROR value is -returned. -. -.Pp -. -.Fn libusb20_be_set_perm pbackend mode -This function will set the permissions for the given backend. -. -This function returns zero on success else a LIBUSB20_ERROR value is -returned. -. -.Pp -. -.Fn libusb20_be_get_owner pbackend puid pgid -This function will retrieve the ownership of the given backend. -. -This function returns zero on success else a LIBUSB20_ERROR value is -returned. -. -.Pp -. -.Fn libusb20_be_get_perm pbackend pmode -This function will retrieve the permissions of the given backend. -. -. -This function returns zero on success else a LIBUSB20_ERROR value is -returned. -. -.Pp -. -.Fn libusb20_be_alloc pmethods -This is an internal function to allocate a USB backend. -. -.Pp -.Fn libusb20_be_alloc_default void -.Fn libusb20_be_alloc_freebsd void .Fn libusb20_be_alloc_linux void These functions are used to allocate a specific USB backend or the operating system default USB backend. Allocating a backend is a way to diff --git a/lib/libusb20/libusb20.c b/lib/libusb20/libusb20.c index 52c447d471cb..704480ab1ba7 100644 --- a/lib/libusb20/libusb20.c +++ b/lib/libusb20/libusb20.c @@ -970,86 +970,6 @@ libusb20_dev_get_bus_number(struct libusb20_device *pdev) return (pdev->bus_number); } -int -libusb20_dev_set_owner(struct libusb20_device *pdev, uid_t user, gid_t group) -{ - return (pdev->beMethods->dev_set_owner(pdev, user, group)); -} - -int -libusb20_dev_set_perm(struct libusb20_device *pdev, mode_t mode) -{ - return (pdev->beMethods->dev_set_perm(pdev, mode)); -} - -int -libusb20_dev_set_iface_owner(struct libusb20_device *pdev, - uint8_t iface_index, uid_t user, gid_t group) -{ - return (pdev->beMethods->dev_set_iface_owner( - pdev, iface_index, user, group)); -} - -int -libusb20_dev_set_iface_perm(struct libusb20_device *pdev, - uint8_t iface_index, mode_t mode) -{ - return (pdev->beMethods->dev_set_iface_perm( - pdev, iface_index, mode)); -} - -int -libusb20_dev_get_owner(struct libusb20_device *pdev, uid_t *user, gid_t *group) -{ - uid_t a; - gid_t b; - - if (user == NULL) - user = &a; - if (group == NULL) - group = &b; - - return (pdev->beMethods->dev_get_owner(pdev, user, group)); -} - -int -libusb20_dev_get_perm(struct libusb20_device *pdev, mode_t *mode) -{ - mode_t a; - - if (mode == NULL) - mode = &a; - return (pdev->beMethods->dev_get_perm(pdev, mode)); -} - -int -libusb20_dev_get_iface_owner(struct libusb20_device *pdev, - uint8_t iface_index, uid_t *user, gid_t *group) -{ - uid_t a; - gid_t b; - - if (user == NULL) - user = &a; - if (group == NULL) - group = &b; - - return (pdev->beMethods->dev_get_iface_owner( - pdev, iface_index, user, group)); -} - -int -libusb20_dev_get_iface_perm(struct libusb20_device *pdev, - uint8_t iface_index, mode_t *mode) -{ - mode_t a; - - if (mode == NULL) - mode = &a; - return (pdev->beMethods->dev_get_iface_perm( - pdev, iface_index, mode)); -} - int libusb20_dev_get_iface_desc(struct libusb20_device *pdev, uint8_t iface_index, char *buf, uint8_t len) @@ -1061,45 +981,6 @@ libusb20_dev_get_iface_desc(struct libusb20_device *pdev, pdev, iface_index, buf, len)); } -/* USB bus operations */ - -int -libusb20_bus_set_owner(struct libusb20_backend *pbe, - uint8_t bus, uid_t user, gid_t group) -{ - return (pbe->methods->bus_set_owner(pbe, bus, user, group)); -} - -int -libusb20_bus_set_perm(struct libusb20_backend *pbe, uint8_t bus, mode_t mode) -{ - return (pbe->methods->bus_set_perm(pbe, bus, mode)); -} - -int -libusb20_bus_get_owner(struct libusb20_backend *pbe, - uint8_t bus, uid_t *user, gid_t *group) -{ - uid_t a; - gid_t b; - - if (user == NULL) - user = &a; - if (group == NULL) - group = &b; - return (pbe->methods->bus_get_owner(pbe, bus, user, group)); -} - -int -libusb20_bus_get_perm(struct libusb20_backend *pbe, uint8_t bus, mode_t *mode) -{ - mode_t a; - - if (mode == NULL) - mode = &a; - return (pbe->methods->bus_get_perm(pbe, bus, mode)); -} - /* USB backend operations */ int @@ -1130,41 +1011,6 @@ libusb20_be_remove_dev_quirk(struct libusb20_backend *pbe, return (pbe->methods->root_remove_dev_quirk(pbe, pq)); } -int -libusb20_be_set_owner(struct libusb20_backend *pbe, uid_t user, gid_t group) -{ - return (pbe->methods->root_set_owner(pbe, user, group)); -} - -int -libusb20_be_set_perm(struct libusb20_backend *pbe, mode_t mode) -{ - return (pbe->methods->root_set_perm(pbe, mode)); -} - -int -libusb20_be_get_owner(struct libusb20_backend *pbe, uid_t *user, gid_t *group) -{ - uid_t a; - gid_t b; - - if (user == NULL) - user = &a; - if (group == NULL) - group = &b; - return (pbe->methods->root_get_owner(pbe, user, group)); -} - -int -libusb20_be_get_perm(struct libusb20_backend *pbe, mode_t *mode) -{ - mode_t a; - - if (mode == NULL) - mode = &a; - return (pbe->methods->root_get_perm(pbe, mode)); -} - int libusb20_be_set_template(struct libusb20_backend *pbe, int temp) { diff --git a/lib/libusb20/libusb20.h b/lib/libusb20/libusb20.h index 051548ecd6ea..89cb75eaa999 100644 --- a/lib/libusb20/libusb20.h +++ b/lib/libusb20/libusb20.h @@ -253,14 +253,6 @@ int libusb20_dev_reset(struct libusb20_device *pdev); int libusb20_dev_set_power_mode(struct libusb20_device *pdev, uint8_t power_mode); uint8_t libusb20_dev_get_power_mode(struct libusb20_device *pdev); int libusb20_dev_set_alt_index(struct libusb20_device *pdev, uint8_t iface_index, uint8_t alt_index); -int libusb20_dev_set_owner(struct libusb20_device *pdev, uid_t user, gid_t group); -int libusb20_dev_set_perm(struct libusb20_device *pdev, mode_t mode); -int libusb20_dev_set_iface_owner(struct libusb20_device *pdev, uint8_t iface_index, uid_t user, gid_t group); -int libusb20_dev_set_iface_perm(struct libusb20_device *pdev, uint8_t iface_index, mode_t mode); -int libusb20_dev_get_owner(struct libusb20_device *pdev, uid_t *user, gid_t *group); -int libusb20_dev_get_perm(struct libusb20_device *pdev, mode_t *mode); -int libusb20_dev_get_iface_owner(struct libusb20_device *pdev, uint8_t iface_index, uid_t *user, gid_t *group); -int libusb20_dev_get_iface_perm(struct libusb20_device *pdev, uint8_t iface_index, mode_t *mode); int libusb20_dev_get_info(struct libusb20_device *pdev, struct usb2_device_info *pinfo); int libusb20_dev_get_iface_desc(struct libusb20_device *pdev, uint8_t iface_index, char *buf, uint8_t len); @@ -276,23 +268,12 @@ void libusb20_dev_free(struct libusb20_device *pdev); void libusb20_dev_set_debug(struct libusb20_device *pdev, int debug); void libusb20_dev_wait_process(struct libusb20_device *pdev, int timeout); -/* USB bus operations */ - -int libusb20_bus_set_owner(struct libusb20_backend *pbe, uint8_t bus, uid_t user, gid_t group); -int libusb20_bus_set_perm(struct libusb20_backend *pbe, uint8_t bus, mode_t mode); -int libusb20_bus_get_owner(struct libusb20_backend *pbe, uint8_t bus, uid_t *user, gid_t *group); -int libusb20_bus_get_perm(struct libusb20_backend *pbe, uint8_t bus, mode_t *mode); - /* USB global operations */ int libusb20_be_get_dev_quirk(struct libusb20_backend *pbe, uint16_t index, struct libusb20_quirk *pq); int libusb20_be_get_quirk_name(struct libusb20_backend *pbe, uint16_t index, struct libusb20_quirk *pq); int libusb20_be_add_dev_quirk(struct libusb20_backend *pbe, struct libusb20_quirk *pq); int libusb20_be_remove_dev_quirk(struct libusb20_backend *pbe, struct libusb20_quirk *pq); -int libusb20_be_set_owner(struct libusb20_backend *be, uid_t user, gid_t group); -int libusb20_be_set_perm(struct libusb20_backend *be, mode_t mode); -int libusb20_be_get_owner(struct libusb20_backend *be, uid_t *user, gid_t *group); -int libusb20_be_get_perm(struct libusb20_backend *be, mode_t *mode); /* USB backend operations */ diff --git a/lib/libusb20/libusb20_int.h b/lib/libusb20/libusb20_int.h index b65aac0c3919..494aa6d7bf39 100644 --- a/lib/libusb20/libusb20_int.h +++ b/lib/libusb20/libusb20_int.h @@ -48,27 +48,11 @@ typedef int (libusb20_root_get_dev_quirk_t)(struct libusb20_backend *pbe, uint16 typedef int (libusb20_root_get_quirk_name_t)(struct libusb20_backend *pbe, uint16_t index, struct libusb20_quirk *pq); typedef int (libusb20_root_add_dev_quirk_t)(struct libusb20_backend *pbe, struct libusb20_quirk *pq); typedef int (libusb20_root_remove_dev_quirk_t)(struct libusb20_backend *pbe, struct libusb20_quirk *pq); -typedef int (libusb20_bus_get_owner_t)(struct libusb20_backend *pbe, uint8_t bus, uid_t *user, gid_t *group); -typedef int (libusb20_bus_get_perm_t)(struct libusb20_backend *pbe, uint8_t bus, mode_t *mode); -typedef int (libusb20_bus_set_owner_t)(struct libusb20_backend *pbe, uint8_t bus, uid_t user, gid_t group); -typedef int (libusb20_bus_set_perm_t)(struct libusb20_backend *pbe, uint8_t bus, mode_t mode); typedef int (libusb20_close_device_t)(struct libusb20_device *pdev); -typedef int (libusb20_dev_get_iface_owner_t)(struct libusb20_device *pdev, uint8_t iface_index, uid_t *user, gid_t *group); -typedef int (libusb20_dev_get_iface_perm_t)(struct libusb20_device *pdev, uint8_t iface_index, mode_t *mode); -typedef int (libusb20_dev_get_owner_t)(struct libusb20_device *pdev, uid_t *user, gid_t *group); -typedef int (libusb20_dev_get_perm_t)(struct libusb20_device *pdev, mode_t *mode); typedef int (libusb20_dev_get_info_t)(struct libusb20_device *pdev, struct usb2_device_info *pinfo); typedef int (libusb20_dev_get_iface_desc_t)(struct libusb20_device *pdev, uint8_t iface_index, char *buf, uint8_t len); -typedef int (libusb20_dev_set_iface_owner_t)(struct libusb20_device *pdev, uint8_t iface_index, uid_t user, gid_t group); -typedef int (libusb20_dev_set_iface_perm_t)(struct libusb20_device *pdev, uint8_t iface_index, mode_t mode); -typedef int (libusb20_dev_set_owner_t)(struct libusb20_device *pdev, uid_t user, gid_t group); -typedef int (libusb20_dev_set_perm_t)(struct libusb20_device *pdev, mode_t mode); typedef int (libusb20_init_backend_t)(struct libusb20_backend *pbe); typedef int (libusb20_open_device_t)(struct libusb20_device *pdev, uint16_t transfer_count_max); -typedef int (libusb20_root_get_owner_t)(struct libusb20_backend *pbe, uid_t *user, gid_t *group); -typedef int (libusb20_root_get_perm_t)(struct libusb20_backend *pbe, mode_t *mode); -typedef int (libusb20_root_set_owner_t)(struct libusb20_backend *pbe, uid_t user, gid_t group); -typedef int (libusb20_root_set_perm_t)(struct libusb20_backend *pbe, mode_t mode); typedef void (libusb20_exit_backend_t)(struct libusb20_backend *pbe); typedef int (libusb20_root_set_template_t)(struct libusb20_backend *pbe, int temp); typedef int (libusb20_root_get_template_t)(struct libusb20_backend *pbe, int *ptemp); @@ -85,28 +69,12 @@ typedef int (libusb20_root_get_template_t)(struct libusb20_backend *pbe, int *pt /* optional backend methods */ \ m(n, init_backend) \ m(n, exit_backend) \ - m(n, bus_set_owner) \ - m(n, bus_get_owner) \ - m(n, bus_set_perm) \ - m(n, bus_get_perm) \ m(n, dev_get_info) \ - m(n, dev_get_iface_owner) \ - m(n, dev_get_iface_perm) \ m(n, dev_get_iface_desc) \ - m(n, dev_get_owner) \ - m(n, dev_get_perm) \ - m(n, dev_set_iface_owner) \ - m(n, dev_set_iface_perm) \ - m(n, dev_set_owner) \ - m(n, dev_set_perm) \ m(n, root_get_dev_quirk) \ m(n, root_get_quirk_name) \ m(n, root_add_dev_quirk) \ m(n, root_remove_dev_quirk) \ - m(n, root_set_owner) \ - m(n, root_get_owner) \ - m(n, root_set_perm) \ - m(n, root_get_perm) \ m(n, root_set_template) \ m(n, root_get_template) \ /* mandatory device methods */ \ diff --git a/lib/libusb20/libusb20_ugen20.c b/lib/libusb20/libusb20_ugen20.c index 17a54ea393a4..1d97db66a65d 100644 --- a/lib/libusb20/libusb20_ugen20.c +++ b/lib/libusb20/libusb20_ugen20.c @@ -50,28 +50,12 @@ static libusb20_open_device_t ugen20_open_device; static libusb20_close_device_t ugen20_close_device; static libusb20_get_backend_name_t ugen20_get_backend_name; static libusb20_exit_backend_t ugen20_exit_backend; -static libusb20_bus_set_owner_t ugen20_bus_set_owner; -static libusb20_bus_get_owner_t ugen20_bus_get_owner; -static libusb20_bus_set_perm_t ugen20_bus_set_perm; -static libusb20_bus_get_perm_t ugen20_bus_get_perm; -static libusb20_dev_get_iface_owner_t ugen20_dev_get_iface_owner; -static libusb20_dev_get_iface_perm_t ugen20_dev_get_iface_perm; -static libusb20_dev_get_owner_t ugen20_dev_get_owner; -static libusb20_dev_get_perm_t ugen20_dev_get_perm; static libusb20_dev_get_iface_desc_t ugen20_dev_get_iface_desc; static libusb20_dev_get_info_t ugen20_dev_get_info; -static libusb20_dev_set_iface_owner_t ugen20_dev_set_iface_owner; -static libusb20_dev_set_iface_perm_t ugen20_dev_set_iface_perm; -static libusb20_dev_set_owner_t ugen20_dev_set_owner; -static libusb20_dev_set_perm_t ugen20_dev_set_perm; static libusb20_root_get_dev_quirk_t ugen20_root_get_dev_quirk; static libusb20_root_get_quirk_name_t ugen20_root_get_quirk_name; static libusb20_root_add_dev_quirk_t ugen20_root_add_dev_quirk; static libusb20_root_remove_dev_quirk_t ugen20_root_remove_dev_quirk; -static libusb20_root_set_owner_t ugen20_root_set_owner; -static libusb20_root_get_owner_t ugen20_root_get_owner; -static libusb20_root_set_perm_t ugen20_root_set_perm; -static libusb20_root_get_perm_t ugen20_root_get_perm; static libusb20_root_set_template_t ugen20_root_set_template; static libusb20_root_get_template_t ugen20_root_get_template; @@ -152,7 +136,7 @@ ugen20_enumerate(struct libusb20_device *pdev, const char *id) pdev->bus_number = ugen20_path_convert_one(&tmp); pdev->device_address = ugen20_path_convert_one(&tmp); - snprintf(buf, sizeof(buf), "/dev/ugen%u.%u", + snprintf(buf, sizeof(buf), "/dev/" USB_GENERIC_NAME "%u.%u", pdev->bus_number, pdev->device_address); f = open(buf, O_RDWR); @@ -218,7 +202,7 @@ ugen20_enumerate(struct libusb20_device *pdev, const char *id) /* generate a nice description for printout */ snprintf(pdev->usb_desc, sizeof(pdev->usb_desc), - "ugen%u.%u: <%s %s> at usbus%u", pdev->bus_number, + USB_GENERIC_NAME "%u.%u: <%s %s> at usbus%u", pdev->bus_number, pdev->device_address, devinfo.udi_product, devinfo.udi_vendor, pdev->bus_number); @@ -284,7 +268,7 @@ ugen20_init_backend(struct libusb20_backend *pbe) memset(&state, 0, sizeof(state)); - state.f = open("/dev/usb", O_RDONLY); + state.f = open("/dev/" USB_DEVICE_NAME, O_RDONLY); if (state.f < 0) return (LIBUSB20_ERROR_OTHER); @@ -379,7 +363,7 @@ ugen20_open_device(struct libusb20_device *pdev, uint16_t nMaxTransfer) int g; int error; - snprintf(buf, sizeof(buf), "/dev/ugen%u.%u", + snprintf(buf, sizeof(buf), "/dev/" USB_GENERIC_NAME "%u.%u", pdev->bus_number, pdev->device_address); /* @@ -873,7 +857,7 @@ ugen20_be_ioctl(uint32_t cmd, void *data) int f; int error; - f = open("/dev/usb", O_RDONLY); + f = open("/dev/" USB_DEVICE_NAME, O_RDONLY); if (f < 0) return (LIBUSB20_ERROR_OTHER); error = ioctl(f, cmd, data); @@ -888,75 +872,6 @@ ugen20_be_ioctl(uint32_t cmd, void *data) return (error); } -static int -ugen20_be_do_perm(uint32_t get_cmd, uint32_t set_cmd, uint8_t bus, - uint8_t dev, uint8_t iface, uid_t *uid, - gid_t *gid, mode_t *mode) -{ - struct usb2_dev_perm perm; - int error; - - memset(&perm, 0, sizeof(perm)); - - perm.bus_index = bus; - perm.dev_index = dev; - perm.iface_index = iface; - - error = ugen20_be_ioctl(get_cmd, &perm); - if (error) - return (error); - - if (set_cmd == 0) { - if (uid) - *uid = perm.user_id; - if (gid) - *gid = perm.group_id; - if (mode) - *mode = perm.mode; - return (0); - } - if (uid) - perm.user_id = *uid; - if (gid) - perm.group_id = *gid; - if (mode) - perm.mode = *mode; - - return (ugen20_be_ioctl(set_cmd, &perm)); -} - -static int -ugen20_bus_set_owner(struct libusb20_backend *pbe, - uint8_t bus, uid_t user, gid_t group) -{ - return (ugen20_be_do_perm(USB_GET_BUS_PERM, USB_SET_BUS_PERM, - bus, 0, 0, &user, &group, NULL)); -} - -static int -ugen20_bus_get_owner(struct libusb20_backend *pbe, uint8_t bus, - uid_t *user, gid_t *group) -{ - return (ugen20_be_do_perm(USB_GET_BUS_PERM, 0, - bus, 0, 0, user, group, NULL)); -} - -static int -ugen20_bus_set_perm(struct libusb20_backend *pbe, - uint8_t bus, mode_t mode) -{ - return (ugen20_be_do_perm(USB_GET_BUS_PERM, USB_SET_BUS_PERM, - bus, 0, 0, NULL, NULL, &mode)); -} - -static int -ugen20_bus_get_perm(struct libusb20_backend *pbe, - uint8_t bus, mode_t *mode) -{ - return (ugen20_be_do_perm(USB_GET_BUS_PERM, 0, - bus, 0, 0, NULL, NULL, mode)); -} - static int ugen20_dev_get_iface_desc(struct libusb20_device *pdev, uint8_t iface_index, char *buf, uint8_t len) @@ -985,59 +900,6 @@ ugen20_dev_get_info(struct libusb20_device *pdev, return (0); } -static int -ugen20_dev_get_iface_owner(struct libusb20_device *pdev, - uint8_t iface_index, uid_t *user, gid_t *group) -{ - return (ugen20_be_do_perm(USB_GET_IFACE_PERM, 0, - pdev->bus_number, pdev->device_address, iface_index, - user, group, NULL)); -} - -static int -ugen20_dev_get_iface_perm(struct libusb20_device *pdev, - uint8_t iface_index, mode_t *mode) -{ - return (ugen20_be_do_perm(USB_GET_IFACE_PERM, 0, - pdev->bus_number, pdev->device_address, iface_index, - NULL, NULL, mode)); -} - -static int -ugen20_dev_get_owner(struct libusb20_device *pdev, - uid_t *user, gid_t *group) -{ - return (ugen20_be_do_perm(USB_GET_DEVICE_PERM, 0, - pdev->bus_number, pdev->device_address, 0, - user, group, NULL)); -} - -static int -ugen20_dev_get_perm(struct libusb20_device *pdev, mode_t *mode) -{ - return (ugen20_be_do_perm(USB_GET_DEVICE_PERM, 0, - pdev->bus_number, pdev->device_address, 0, - NULL, NULL, mode)); -} - -static int -ugen20_dev_set_iface_owner(struct libusb20_device *pdev, - uint8_t iface_index, uid_t user, gid_t group) -{ - return (ugen20_be_do_perm(USB_GET_IFACE_PERM, USB_SET_IFACE_PERM, - pdev->bus_number, pdev->device_address, iface_index, - &user, &group, NULL)); -} - -static int -ugen20_dev_set_iface_perm(struct libusb20_device *pdev, - uint8_t iface_index, mode_t mode) -{ - return (ugen20_be_do_perm(USB_GET_IFACE_PERM, USB_SET_IFACE_PERM, - pdev->bus_number, pdev->device_address, iface_index, - NULL, NULL, &mode)); -} - static int ugen20_root_get_dev_quirk(struct libusb20_backend *pbe, uint16_t quirk_index, struct libusb20_quirk *pq) @@ -1136,52 +998,6 @@ ugen20_root_remove_dev_quirk(struct libusb20_backend *pbe, return (error); } -static int -ugen20_dev_set_owner(struct libusb20_device *pdev, - uid_t user, gid_t group) -{ - return (ugen20_be_do_perm(USB_GET_DEVICE_PERM, USB_SET_DEVICE_PERM, - pdev->bus_number, pdev->device_address, 0, - &user, &group, NULL)); -} - -static int -ugen20_dev_set_perm(struct libusb20_device *pdev, mode_t mode) -{ - return (ugen20_be_do_perm(USB_GET_DEVICE_PERM, USB_SET_DEVICE_PERM, - pdev->bus_number, pdev->device_address, 0, - NULL, NULL, &mode)); -} - -static int -ugen20_root_set_owner(struct libusb20_backend *pbe, - uid_t user, gid_t group) -{ - return (ugen20_be_do_perm(USB_GET_ROOT_PERM, USB_SET_ROOT_PERM, 0, 0, 0, - &user, &group, NULL)); -} - -static int -ugen20_root_get_owner(struct libusb20_backend *pbe, uid_t *user, gid_t *group) -{ - return (ugen20_be_do_perm(USB_GET_ROOT_PERM, 0, 0, 0, 0, - user, group, NULL)); -} - -static int -ugen20_root_set_perm(struct libusb20_backend *pbe, mode_t mode) -{ - return (ugen20_be_do_perm(USB_GET_ROOT_PERM, USB_SET_ROOT_PERM, 0, 0, 0, - NULL, NULL, &mode)); -} - -static int -ugen20_root_get_perm(struct libusb20_backend *pbe, mode_t *mode) -{ - return (ugen20_be_do_perm(USB_GET_ROOT_PERM, 0, 0, 0, 0, - NULL, NULL, mode)); -} - static int ugen20_root_set_template(struct libusb20_backend *pbe, int temp) { diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c index 7ea61f3fd66c..2c00e27625eb 100644 --- a/sys/dev/sound/usb/uaudio.c +++ b/sys/dev/sound/usb/uaudio.c @@ -379,9 +379,9 @@ static void umidi_start_read(struct usb2_fifo *); static void umidi_stop_read(struct usb2_fifo *); static void umidi_start_write(struct usb2_fifo *); static void umidi_stop_write(struct usb2_fifo *); -static int umidi_open(struct usb2_fifo *, int, struct thread *); -static int umidi_ioctl(struct usb2_fifo *, u_long cmd, void *, int, struct thread *); -static void umidi_close(struct usb2_fifo *, int, struct thread *); +static int umidi_open(struct usb2_fifo *, int); +static int umidi_ioctl(struct usb2_fifo *, u_long cmd, void *, int); +static void umidi_close(struct usb2_fifo *, int); static void umidi_init(device_t dev); static int32_t umidi_probe(device_t dev); static int32_t umidi_detach(device_t dev); @@ -3585,7 +3585,7 @@ umidi_stop_write(struct usb2_fifo *fifo) } static int -umidi_open(struct usb2_fifo *fifo, int fflags, struct thread *td) +umidi_open(struct usb2_fifo *fifo, int fflags) { struct umidi_chan *chan = fifo->priv_sc0; struct umidi_sub_chan *sub = umidi_sub_by_fifo(fifo); @@ -3617,7 +3617,7 @@ umidi_open(struct usb2_fifo *fifo, int fflags, struct thread *td) } static void -umidi_close(struct usb2_fifo *fifo, int fflags, struct thread *td) +umidi_close(struct usb2_fifo *fifo, int fflags) { if (fflags & FREAD) { usb2_fifo_free_buffer(fifo); @@ -3630,7 +3630,7 @@ umidi_close(struct usb2_fifo *fifo, int fflags, struct thread *td) static int umidi_ioctl(struct usb2_fifo *fifo, u_long cmd, void *data, - int fflags, struct thread *td) + int fflags) { return (ENODEV); } @@ -3684,9 +3684,6 @@ umidi_probe(device_t dev) (chan->max_cable == 0)) { chan->max_cable = UMIDI_CABLES_MAX; } - /* set interface permissions */ - usb2_set_iface_perm(sc->sc_udev, chan->iface_index, - UID_ROOT, GID_OPERATOR, 0644); for (n = 0; n < chan->max_cable; n++) { @@ -3694,7 +3691,8 @@ umidi_probe(device_t dev) error = usb2_fifo_attach(sc->sc_udev, chan, &chan->mtx, &umidi_fifo_methods, &sub->fifo, unit, n, - chan->iface_index); + chan->iface_index, + UID_ROOT, GID_OPERATOR, 0644); if (error) { goto detach; } diff --git a/sys/dev/usb/bluetooth/ubtbcmfw.c b/sys/dev/usb/bluetooth/ubtbcmfw.c index 3685f5671736..6929f2da0226 100644 --- a/sys/dev/usb/bluetooth/ubtbcmfw.c +++ b/sys/dev/usb/bluetooth/ubtbcmfw.c @@ -211,13 +211,10 @@ ubtbcmfw_attach(device_t dev) goto detach; } - /* Set interface permissions */ - usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex, - UID_ROOT, GID_OPERATOR, 0644); - error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx, &ubtbcmfw_fifo_methods, &sc->sc_fifo, - device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex); + device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex, + UID_ROOT, GID_OPERATOR, 0644); if (error != 0) { device_printf(dev, "could not attach fifo. %s\n", usb2_errstr(error)); @@ -369,7 +366,7 @@ ubtbcmfw_stop_write(struct usb2_fifo *fifo) */ static int -ubtbcmfw_open(struct usb2_fifo *fifo, int fflags, struct thread *td) +ubtbcmfw_open(struct usb2_fifo *fifo, int fflags) { struct ubtbcmfw_softc *sc = fifo->priv_sc0; struct usb2_xfer *xfer; @@ -398,7 +395,7 @@ ubtbcmfw_open(struct usb2_fifo *fifo, int fflags, struct thread *td) */ static void -ubtbcmfw_close(struct usb2_fifo *fifo, int fflags, struct thread *td) +ubtbcmfw_close(struct usb2_fifo *fifo, int fflags) { if (fflags & (FREAD | FWRITE)) usb2_fifo_free_buffer(fifo); @@ -410,7 +407,7 @@ ubtbcmfw_close(struct usb2_fifo *fifo, int fflags, struct thread *td) static int ubtbcmfw_ioctl(struct usb2_fifo *fifo, u_long cmd, void *data, - int fflags, struct thread *td) + int fflags) { struct ubtbcmfw_softc *sc = fifo->priv_sc0; int error = 0; diff --git a/sys/dev/usb/image/uscanner.c b/sys/dev/usb/image/uscanner.c index ca631b5824bb..bc4614d2d4b5 100644 --- a/sys/dev/usb/image/uscanner.c +++ b/sys/dev/usb/image/uscanner.c @@ -399,13 +399,11 @@ uscanner_attach(device_t dev) "error=%s\n", usb2_errstr(error)); goto detach; } - /* set interface permissions */ - usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex, - UID_ROOT, GID_OPERATOR, 0644); error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx, &uscanner_fifo_methods, &sc->sc_fifo, - unit, 0 - 1, uaa->info.bIfaceIndex); + unit, 0 - 1, uaa->info.bIfaceIndex, + UID_ROOT, GID_OPERATOR, 0644); if (error) { goto detach; } @@ -553,7 +551,7 @@ uscanner_write_clear_stall_callback(struct usb2_xfer *xfer) * uscanner character device opening method. */ static int -uscanner_open(struct usb2_fifo *fifo, int fflags, struct thread *td) +uscanner_open(struct usb2_fifo *fifo, int fflags) { struct uscanner_softc *sc; @@ -585,7 +583,7 @@ uscanner_open(struct usb2_fifo *fifo, int fflags, struct thread *td) } static void -uscanner_close(struct usb2_fifo *fifo, int fflags, struct thread *td) +uscanner_close(struct usb2_fifo *fifo, int fflags) { if (fflags & (FREAD | FWRITE)) { usb2_fifo_free_buffer(fifo); diff --git a/sys/dev/usb/input/uhid.c b/sys/dev/usb/input/uhid.c index 563bd9959eae..c2307f580cbc 100644 --- a/sys/dev/usb/input/uhid.c +++ b/sys/dev/usb/input/uhid.c @@ -447,7 +447,7 @@ uhid_set_report(struct uhid_softc *sc, uint8_t type, } static int -uhid_open(struct usb2_fifo *fifo, int fflags, struct thread *td) +uhid_open(struct usb2_fifo *fifo, int fflags) { struct uhid_softc *sc = fifo->priv_sc0; @@ -474,7 +474,7 @@ uhid_open(struct usb2_fifo *fifo, int fflags, struct thread *td) } static void -uhid_close(struct usb2_fifo *fifo, int fflags, struct thread *td) +uhid_close(struct usb2_fifo *fifo, int fflags) { if (fflags & (FREAD | FWRITE)) { usb2_fifo_free_buffer(fifo); @@ -483,7 +483,7 @@ uhid_close(struct usb2_fifo *fifo, int fflags, struct thread *td) static int uhid_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr, - int fflags, struct thread *td) + int fflags) { struct uhid_softc *sc = fifo->priv_sc0; struct usb2_gen_descriptor *ugd; @@ -734,13 +734,11 @@ uhid_attach(device_t dev) sc->sc_fsize); sc->sc_fsize = UHID_BSIZE; } - /* set interface permissions */ - usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex, - UID_ROOT, GID_OPERATOR, 0644); error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx, &uhid_fifo_methods, &sc->sc_fifo, - unit, 0 - 1, uaa->info.bIfaceIndex); + unit, 0 - 1, uaa->info.bIfaceIndex, + UID_ROOT, GID_OPERATOR, 0644); if (error) { goto detach; } diff --git a/sys/dev/usb/input/ums.c b/sys/dev/usb/input/ums.c index 04e258057d05..36460b400a36 100644 --- a/sys/dev/usb/input/ums.c +++ b/sys/dev/usb/input/ums.c @@ -583,13 +583,10 @@ ums_attach(device_t dev) sc->sc_status.dy = 0; sc->sc_status.dz = 0; - /* set interface permissions */ - usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex, - UID_ROOT, GID_OPERATOR, 0644); - err = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx, &ums_fifo_methods, &sc->sc_fifo, - unit, 0 - 1, uaa->info.bIfaceIndex); + unit, 0 - 1, uaa->info.bIfaceIndex, + UID_ROOT, GID_OPERATOR, 0644); if (err) { goto detach; } @@ -697,7 +694,7 @@ ums_reset_buf(struct ums_softc *sc) } static int -ums_open(struct usb2_fifo *fifo, int fflags, struct thread *td) +ums_open(struct usb2_fifo *fifo, int fflags) { struct ums_softc *sc = fifo->priv_sc0; @@ -724,7 +721,7 @@ ums_open(struct usb2_fifo *fifo, int fflags, struct thread *td) } static void -ums_close(struct usb2_fifo *fifo, int fflags, struct thread *td) +ums_close(struct usb2_fifo *fifo, int fflags) { if (fflags & FREAD) { usb2_fifo_free_buffer(fifo); @@ -732,8 +729,7 @@ ums_close(struct usb2_fifo *fifo, int fflags, struct thread *td) } static int -ums_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr, - int fflags, struct thread *td) +ums_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr, int fflags) { struct ums_softc *sc = fifo->priv_sc0; mousemode_t mode; diff --git a/sys/dev/usb/misc/ufm.c b/sys/dev/usb/misc/ufm.c index 81ce1b3c0895..7f85b4fa4485 100644 --- a/sys/dev/usb/misc/ufm.c +++ b/sys/dev/usb/misc/ufm.c @@ -139,13 +139,10 @@ ufm_attach(device_t dev) device_set_usb2_desc(dev); - /* set interface permissions */ - usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex, - UID_ROOT, GID_OPERATOR, 0644); - error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx, &ufm_fifo_methods, &sc->sc_fifo, - device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex); + device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex, + UID_ROOT, GID_OPERATOR, 0644); if (error) { goto detach; } @@ -169,7 +166,7 @@ ufm_detach(device_t dev) } static int -ufm_open(struct usb2_fifo *dev, int fflags, struct thread *td) +ufm_open(struct usb2_fifo *dev, int fflags) { if ((fflags & (FWRITE | FREAD)) != (FWRITE | FREAD)) { return (EACCES); @@ -300,7 +297,7 @@ ufm_get_stat(struct ufm_softc *sc, void *addr) static int ufm_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr, - int fflags, struct thread *td) + int fflags) { struct ufm_softc *sc = fifo->priv_sc0; int error = 0; diff --git a/sys/dev/usb/serial/ulpt.c b/sys/dev/usb/serial/ulpt.c index 36e082b3f3c3..b3008633b909 100644 --- a/sys/dev/usb/serial/ulpt.c +++ b/sys/dev/usb/serial/ulpt.c @@ -395,7 +395,7 @@ ulpt_stop_write(struct usb2_fifo *fifo) } static int -ulpt_open(struct usb2_fifo *fifo, int fflags, struct thread *td) +ulpt_open(struct usb2_fifo *fifo, int fflags) { struct ulpt_softc *sc = fifo->priv_sc0; @@ -404,11 +404,11 @@ ulpt_open(struct usb2_fifo *fifo, int fflags, struct thread *td) if (sc->sc_fflags == 0) { ulpt_reset(sc); } - return (unlpt_open(fifo, fflags, td)); + return (unlpt_open(fifo, fflags)); } static int -unlpt_open(struct usb2_fifo *fifo, int fflags, struct thread *td) +unlpt_open(struct usb2_fifo *fifo, int fflags) { struct ulpt_softc *sc = fifo->priv_sc0; @@ -446,7 +446,7 @@ unlpt_open(struct usb2_fifo *fifo, int fflags, struct thread *td) } static void -ulpt_close(struct usb2_fifo *fifo, int fflags, struct thread *td) +ulpt_close(struct usb2_fifo *fifo, int fflags) { struct ulpt_softc *sc = fifo->priv_sc0; @@ -459,7 +459,7 @@ ulpt_close(struct usb2_fifo *fifo, int fflags, struct thread *td) static int ulpt_ioctl(struct usb2_fifo *fifo, u_long cmd, void *data, - int fflags, struct thread *td) + int fflags) { return (ENODEV); } @@ -595,19 +595,17 @@ ulpt_attach(device_t dev) } #endif - /* set interface permissions */ - usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex, - UID_ROOT, GID_OPERATOR, 0644); - error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx, &ulpt_fifo_methods, &sc->sc_fifo, - unit, 0 - 1, uaa->info.bIfaceIndex); + unit, 0 - 1, uaa->info.bIfaceIndex, + UID_ROOT, GID_OPERATOR, 0644); if (error) { goto detach; } error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx, &unlpt_fifo_methods, &sc->sc_fifo_noreset, - unit, 0 - 1, uaa->info.bIfaceIndex); + unit, 0 - 1, uaa->info.bIfaceIndex, + UID_ROOT, GID_OPERATOR, 0644); if (error) { goto detach; } diff --git a/sys/dev/usb/storage/urio.c b/sys/dev/usb/storage/urio.c index 82e16d90f881..278a952bf3e7 100644 --- a/sys/dev/usb/storage/urio.c +++ b/sys/dev/usb/storage/urio.c @@ -228,13 +228,11 @@ urio_attach(device_t dev) DPRINTF("error=%s\n", usb2_errstr(error)); goto detach; } - /* set interface permissions */ - usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex, - UID_ROOT, GID_OPERATOR, 0644); error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx, &urio_fifo_methods, &sc->sc_fifo, - device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex); + device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex, + UID_ROOT, GID_OPERATOR, 0644); if (error) { goto detach; } @@ -370,7 +368,7 @@ urio_stop_write(struct usb2_fifo *fifo) } static int -urio_open(struct usb2_fifo *fifo, int fflags, struct thread *td) +urio_open(struct usb2_fifo *fifo, int fflags) { struct urio_softc *sc = fifo->priv_sc0; @@ -403,7 +401,7 @@ urio_open(struct usb2_fifo *fifo, int fflags, struct thread *td) } static void -urio_close(struct usb2_fifo *fifo, int fflags, struct thread *td) +urio_close(struct usb2_fifo *fifo, int fflags) { if (fflags & (FREAD | FWRITE)) { usb2_fifo_free_buffer(fifo); @@ -412,7 +410,7 @@ urio_close(struct usb2_fifo *fifo, int fflags, struct thread *td) static int urio_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr, - int fflags, struct thread *td) + int fflags) { struct usb2_ctl_request ur; struct RioCommand *rio_cmd; diff --git a/sys/dev/usb/usb_bus.h b/sys/dev/usb/usb_bus.h index 59287c448d4b..d2fecb94621c 100644 --- a/sys/dev/usb/usb_bus.h +++ b/sys/dev/usb/usb_bus.h @@ -69,7 +69,6 @@ struct usb2_bus { * This mutex protects the USB hardware: */ struct mtx bus_mtx; - struct usb2_perm perm; struct usb2_xfer_queue intr_q; struct usb2_callout power_wdog; /* power management */ diff --git a/sys/dev/usb/usb_core.h b/sys/dev/usb/usb_core.h index f89c22fd7a8d..62dcbd92d6ea 100644 --- a/sys/dev/usb/usb_core.h +++ b/sys/dev/usb/usb_core.h @@ -177,16 +177,6 @@ typedef void (usb2_callback_t)(struct usb2_xfer *); /* structures */ -/* - * This structure contains permissions. - */ - -struct usb2_perm { - uint32_t uid; - uint32_t gid; - uint16_t mode; -}; - /* * Common queue structure for USB transfers. */ @@ -383,25 +373,6 @@ struct usb2_attach_arg { uint8_t use_generic; /* hint for generic drivers */ }; -/* Structure used when referring an USB device */ - -struct usb2_location { - struct usb2_bus *bus; - struct usb2_device *udev; - struct usb2_interface *iface; - struct usb2_fifo *rxfifo; - struct usb2_fifo *txfifo; - uint32_t devloc; /* original devloc */ - uint16_t bus_index; /* bus index */ - uint8_t dev_index; /* device index */ - uint8_t iface_index; /* interface index */ - uint8_t fifo_index; /* FIFO index */ - uint8_t is_read; /* set if location has read access */ - uint8_t is_write; /* set if location has write access */ - uint8_t is_uref; /* set if USB refcount decr. needed */ - uint8_t is_usbfs; /* set if USB-FS is active */ -}; - /* external variables */ MALLOC_DECLARE(M_USB); @@ -449,13 +420,8 @@ uint8_t usb2_transfer_pending(struct usb2_xfer *xfer); void usb2_transfer_start(struct usb2_xfer *xfer); void usb2_transfer_stop(struct usb2_xfer *xfer); void usb2_transfer_unsetup(struct usb2_xfer **pxfer, uint16_t n_setup); -usb2_error_t usb2_ref_device(struct file *fp, struct usb2_location *ploc, - uint32_t devloc); -void usb2_unref_device(struct usb2_location *ploc); void usb2_set_parent_iface(struct usb2_device *udev, uint8_t iface_index, uint8_t parent_index); -void usb2_set_iface_perm(struct usb2_device *udev, uint8_t iface_index, - uint32_t uid, uint32_t gid, uint16_t mode); uint8_t usb2_get_bus_index(struct usb2_device *udev); uint8_t usb2_get_device_index(struct usb2_device *udev); void usb2_set_power_mode(struct usb2_device *udev, uint8_t power_mode); diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c index 87a656a3f561..6d385ede9801 100644 --- a/sys/dev/usb/usb_dev.c +++ b/sys/dev/usb/usb_dev.c @@ -72,381 +72,77 @@ SYSCTL_INT(_hw_usb2_dev, OID_AUTO, debug, CTLFLAG_RW, /* prototypes */ -static uint32_t usb2_path_convert_one(const char **); -static uint32_t usb2_path_convert(const char *); -static int usb2_check_access(int, struct usb2_perm *); -static int usb2_fifo_open(struct usb2_fifo *, struct file *, - struct thread *, int); -static void usb2_fifo_close(struct usb2_fifo *, struct thread *, int); +static int usb2_fifo_open(struct usb2_fifo *, int); +static void usb2_fifo_close(struct usb2_fifo *, int); static void usb2_dev_init(void *); static void usb2_dev_init_post(void *); static void usb2_dev_uninit(void *); static int usb2_fifo_uiomove(struct usb2_fifo *, void *, int, struct uio *); static void usb2_fifo_check_methods(struct usb2_fifo_methods *); -static void usb2_clone(void *, USB_UCRED char *, int, struct cdev **); static struct usb2_fifo *usb2_fifo_alloc(void); static struct usb2_pipe *usb2_dev_get_pipe(struct usb2_device *, uint8_t, uint8_t, uint8_t); +static void usb2_loc_fill(struct usb2_fs_privdata *, + struct usb2_cdev_privdata *); +static void usb2_close(void *); +static usb2_error_t usb2_ref_device(struct usb2_cdev_privdata *, int); +static usb2_error_t usb2_uref_location(struct usb2_cdev_privdata *); +static void usb2_unref_device(struct usb2_cdev_privdata *); -static d_fdopen_t usb2_fdopen; -static d_close_t usb2_close; +static d_open_t usb2_open; static d_ioctl_t usb2_ioctl; +static d_read_t usb2_read; +static d_write_t usb2_write; +static d_poll_t usb2_poll; -static fo_rdwr_t usb2_read_f; -static fo_rdwr_t usb2_write_f; - -#if __FreeBSD_version > 800009 -static fo_truncate_t usb2_truncate_f; - -#endif -static fo_ioctl_t usb2_ioctl_f; -static fo_poll_t usb2_poll_f; -static fo_kqfilter_t usb2_kqfilter_f; -static fo_stat_t usb2_stat_f; -static fo_close_t usb2_close_f; +static d_ioctl_t usb2_static_ioctl; static usb2_fifo_open_t usb2_fifo_dummy_open; static usb2_fifo_close_t usb2_fifo_dummy_close; static usb2_fifo_ioctl_t usb2_fifo_dummy_ioctl; static usb2_fifo_cmd_t usb2_fifo_dummy_cmd; -static struct usb2_perm usb2_perm = { - .uid = UID_ROOT, - .gid = GID_OPERATOR, - .mode = 0660, -}; - -static struct cdevsw usb2_devsw = { +/* character device structure used for devices (/dev/ugenX.Y and /dev/uXXX) */ +struct cdevsw usb2_devsw = { .d_version = D_VERSION, - .d_fdopen = usb2_fdopen, - .d_close = usb2_close, + .d_open = usb2_open, .d_ioctl = usb2_ioctl, - .d_name = "usb", + .d_name = "usbdev", .d_flags = D_TRACKCLOSE, + .d_read = usb2_read, + .d_write = usb2_write, + .d_poll = usb2_poll }; -static struct fileops usb2_ops_f = { - .fo_read = usb2_read_f, - .fo_write = usb2_write_f, -#if __FreeBSD_version > 800009 - .fo_truncate = usb2_truncate_f, -#endif - .fo_ioctl = usb2_ioctl_f, - .fo_poll = usb2_poll_f, - .fo_kqfilter = usb2_kqfilter_f, - .fo_stat = usb2_stat_f, - .fo_close = usb2_close_f, - .fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE +static struct cdev* usb2_dev = NULL; + +/* character device structure used for /dev/usb */ +struct cdevsw usb2_static_devsw = { + .d_version = D_VERSION, + .d_ioctl = usb2_static_ioctl, + .d_name = "usb" }; -static const dev_clone_fn usb2_clone_ptr = &usb2_clone; -static struct cdev *usb2_dev; -static uint32_t usb2_last_devloc = 0 - 1; -static eventhandler_tag usb2_clone_tag; -static void *usb2_old_f_data; -static struct fileops *usb2_old_f_ops; static TAILQ_HEAD(, usb2_symlink) usb2_sym_head; static struct sx usb2_sym_lock; struct mtx usb2_ref_lock; -static uint32_t -usb2_path_convert_one(const char **pp) -{ - const char *ptr; - uint32_t temp = 0; - - ptr = *pp; - - while ((*ptr >= '0') && (*ptr <= '9')) { - temp *= 10; - temp += (*ptr - '0'); - if (temp >= 1000000) { - /* catch overflow early */ - return (0 - 1); - } - ptr++; - } - - if (*ptr == '.') { - /* skip dot */ - ptr++; - } - *pp = ptr; - - return (temp); -} - /*------------------------------------------------------------------------* - * usb2_path_convert + * usb2_loc_fill * - * Path format: "/dev/usb..." - * - * Returns: Path converted into numerical format. + * This is used to fill out a usb2_cdev_privdata structure based on the + * device's address as contained in usb2_fs_privdata. *------------------------------------------------------------------------*/ -static uint32_t -usb2_path_convert(const char *path) +static void +usb2_loc_fill(struct usb2_fs_privdata* pd, struct usb2_cdev_privdata *cpd) { - uint32_t temp; - uint32_t devloc; - - devloc = 0; - - temp = usb2_path_convert_one(&path); - - if (temp >= USB_BUS_MAX) { - return (0 - 1); - } - devloc += temp; - - temp = usb2_path_convert_one(&path); - - if (temp >= USB_DEV_MAX) { - return (0 - 1); - } - devloc += (temp * USB_BUS_MAX); - - temp = usb2_path_convert_one(&path); - - if (temp >= USB_IFACE_MAX) { - return (0 - 1); - } - devloc += (temp * USB_DEV_MAX * USB_BUS_MAX); - - temp = usb2_path_convert_one(&path); - - if (temp >= ((USB_FIFO_MAX / 2) + (USB_EP_MAX / 2))) { - return (0 - 1); - } - devloc += (temp * USB_IFACE_MAX * USB_DEV_MAX * USB_BUS_MAX); - - return (devloc); -} - -/*------------------------------------------------------------------------* - * usb2_set_iface_perm - * - * This function will set the interface permissions. - *------------------------------------------------------------------------*/ -void -usb2_set_iface_perm(struct usb2_device *udev, uint8_t iface_index, - uint32_t uid, uint32_t gid, uint16_t mode) -{ - struct usb2_interface *iface; - - iface = usb2_get_iface(udev, iface_index); - if (iface && iface->idesc) { - mtx_lock(&usb2_ref_lock); - iface->perm.uid = uid; - iface->perm.gid = gid; - iface->perm.mode = mode; - mtx_unlock(&usb2_ref_lock); - - } -} - -/*------------------------------------------------------------------------* - * usb2_set_perm - * - * This function will set the permissions at the given level. - * - * Return values: - * 0: Success. - * Else: Failure. - *------------------------------------------------------------------------*/ -static int -usb2_set_perm(struct usb2_dev_perm *psrc, uint8_t level) -{ - struct usb2_location loc; - struct usb2_perm *pdst; - uint32_t devloc; - int error; - - /* check if the current thread can change USB permissions. */ - error = priv_check(curthread, PRIV_ROOT); - if (error) { - return (error); - } - /* range check device location */ - if ((psrc->bus_index >= USB_BUS_MAX) || - (psrc->dev_index >= USB_DEV_MAX) || - (psrc->iface_index >= USB_IFACE_MAX)) { - return (EINVAL); - } - if (level == 1) - devloc = USB_BUS_MAX; /* use root-HUB to access bus */ - else - devloc = 0; - switch (level) { - case 3: - devloc += psrc->iface_index * - USB_DEV_MAX * USB_BUS_MAX; - /* FALLTHROUGH */ - case 2: - devloc += psrc->dev_index * - USB_BUS_MAX; - /* FALLTHROUGH */ - case 1: - devloc += psrc->bus_index; - break; - default: - break; - } - - if ((level > 0) && (level < 4)) { - error = usb2_ref_device(NULL, &loc, devloc); - if (error) { - return (error); - } - } - switch (level) { - case 3: - if (loc.iface == NULL) { - usb2_unref_device(&loc); - return (EINVAL); - } - pdst = &loc.iface->perm; - break; - case 2: - pdst = &loc.udev->perm; - break; - case 1: - pdst = &loc.bus->perm; - break; - default: - pdst = &usb2_perm; - break; - } - - /* all permissions are protected by "usb2_ref_lock" */ - mtx_lock(&usb2_ref_lock); - pdst->uid = psrc->user_id; - pdst->gid = psrc->group_id; - pdst->mode = psrc->mode; - mtx_unlock(&usb2_ref_lock); - - if ((level > 0) && (level < 4)) { - usb2_unref_device(&loc); - } - return (0); /* success */ -} - -/*------------------------------------------------------------------------* - * usb2_get_perm - * - * This function will get the permissions at the given level. - * - * Return values: - * 0: Success. - * Else: Failure. - *------------------------------------------------------------------------*/ -static int -usb2_get_perm(struct usb2_dev_perm *pdst, uint8_t level) -{ - struct usb2_location loc; - struct usb2_perm *psrc; - uint32_t devloc; - int error; - - if ((pdst->bus_index >= USB_BUS_MAX) || - (pdst->dev_index >= USB_DEV_MAX) || - (pdst->iface_index >= USB_IFACE_MAX)) { - return (EINVAL); - } - if (level == 1) - devloc = USB_BUS_MAX; /* use root-HUB to access bus */ - else - devloc = 0; - switch (level) { - case 3: - devloc += pdst->iface_index * - USB_DEV_MAX * USB_BUS_MAX; - /* FALLTHROUGH */ - case 2: - devloc += pdst->dev_index * - USB_BUS_MAX; - /* FALLTHROUGH */ - case 1: - devloc += pdst->bus_index; - break; - default: - break; - } - - if ((level > 0) && (level < 4)) { - error = usb2_ref_device(NULL, &loc, devloc); - if (error) { - return (error); - } - } - switch (level) { - case 3: - if (loc.iface == NULL) { - usb2_unref_device(&loc); - return (EINVAL); - } - psrc = &loc.iface->perm; - break; - case 2: - psrc = &loc.udev->perm; - break; - case 1: - psrc = &loc.bus->perm; - break; - default: - psrc = &usb2_perm; - break; - } - - /* all permissions are protected by "usb2_ref_lock" */ - mtx_lock(&usb2_ref_lock); - if (psrc->mode != 0) { - pdst->user_id = psrc->uid; - pdst->group_id = psrc->gid; - pdst->mode = psrc->mode; - } else { - /* access entry at this level and location is not active */ - pdst->user_id = 0; - pdst->group_id = 0; - pdst->mode = 0; - } - mtx_unlock(&usb2_ref_lock); - - if ((level > 0) && (level < 4)) { - usb2_unref_device(&loc); - } - return (0); -} - -/*------------------------------------------------------------------------* - * usb2_check_access - * - * This function will verify the given access information. - * - * Return values: - * 0: Access granted. - * Else: No access granted. - *------------------------------------------------------------------------*/ -static int -usb2_check_access(int fflags, struct usb2_perm *puser) -{ - mode_t accmode; - - if ((fflags & (FWRITE | FREAD)) && (puser->mode != 0)) { - /* continue */ - } else { - return (EPERM); /* no access */ - } - - accmode = 0; - if (fflags & FWRITE) - accmode |= VWRITE; - if (fflags & FREAD) - accmode |= VREAD; - - return (vaccess(VCHR, puser->mode, puser->uid, - puser->gid, accmode, curthread->td_ucred, NULL)); + cpd->bus_index = pd->bus_index; + cpd->dev_index = pd->dev_index; + cpd->iface_index = pd->iface_index; + cpd->ep_addr = pd->ep_addr; + cpd->fifo_index = pd->fifo_index; } /*------------------------------------------------------------------------* @@ -461,89 +157,53 @@ usb2_check_access(int fflags, struct usb2_perm *puser) * Else: Failure. *------------------------------------------------------------------------*/ usb2_error_t -usb2_ref_device(struct file *fp, struct usb2_location *ploc, uint32_t devloc) +usb2_ref_device(struct usb2_cdev_privdata* cpd, int need_uref) { struct usb2_fifo **ppf; struct usb2_fifo *f; - int fflags; - uint8_t dev_ep_index; + int dev_ep_index; - if (fp) { - /* check if we need uref */ - ploc->is_uref = devloc ? 0 : 1; - /* get devloc - already verified */ - devloc = USB_P2U(fp->f_data); - /* get file flags */ - fflags = fp->f_flag; - } else { - /* only ref device */ - fflags = 0; - /* search for FIFO */ - ploc->is_uref = 1; - /* check "devloc" */ - if (devloc >= (USB_BUS_MAX * USB_DEV_MAX * - USB_IFACE_MAX * ((USB_EP_MAX / 2) + (USB_FIFO_MAX / 2)))) { - return (USB_ERR_INVAL); - } - } - - /* store device location */ - ploc->devloc = devloc; - ploc->bus_index = devloc % USB_BUS_MAX; - ploc->dev_index = (devloc / USB_BUS_MAX) % USB_DEV_MAX; - ploc->iface_index = (devloc / (USB_BUS_MAX * - USB_DEV_MAX)) % USB_IFACE_MAX; - ploc->fifo_index = (devloc / (USB_BUS_MAX * USB_DEV_MAX * - USB_IFACE_MAX)); + DPRINTFN(2, "usb2_ref_device, cpd=%p need uref=%d\n", cpd, need_uref); mtx_lock(&usb2_ref_lock); - ploc->bus = devclass_get_softc(usb2_devclass_ptr, ploc->bus_index); - if (ploc->bus == NULL) { - DPRINTFN(2, "no bus at %u\n", ploc->bus_index); + cpd->bus = devclass_get_softc(usb2_devclass_ptr, cpd->bus_index); + if (cpd->bus == NULL) { + DPRINTFN(2, "no bus at %u\n", cpd->bus_index); goto error; } - if (ploc->dev_index >= ploc->bus->devices_max) { - DPRINTFN(2, "invalid dev index, %u\n", ploc->dev_index); + cpd->udev = cpd->bus->devices[cpd->dev_index]; + if (cpd->udev == NULL) { + DPRINTFN(2, "no device at %u\n", cpd->dev_index); goto error; } - ploc->udev = ploc->bus->devices[ploc->dev_index]; - if (ploc->udev == NULL) { - DPRINTFN(2, "no device at %u\n", ploc->dev_index); - goto error; - } - if (ploc->udev->refcount == USB_DEV_REF_MAX) { + if (cpd->udev->refcount == USB_DEV_REF_MAX) { DPRINTFN(2, "no dev ref\n"); goto error; } /* check if we are doing an open */ - if (fp == NULL) { + dev_ep_index = cpd->ep_addr; + if (cpd->fflags == 0) { /* set defaults */ - ploc->txfifo = NULL; - ploc->rxfifo = NULL; - ploc->is_write = 0; - ploc->is_read = 0; - ploc->is_usbfs = 0; - /* NOTE: variable overloading: */ - dev_ep_index = ploc->fifo_index; + cpd->txfifo = NULL; + cpd->rxfifo = NULL; + cpd->is_write = 0; + cpd->is_read = 0; + cpd->is_usbfs = 0; } else { /* initialise "is_usbfs" flag */ - ploc->is_usbfs = 0; - dev_ep_index = 255; /* dummy */ + cpd->is_usbfs = 0; /* check for write */ - if (fflags & FWRITE) { - ppf = ploc->udev->fifo; - f = ppf[ploc->fifo_index + USB_FIFO_TX]; - ploc->txfifo = f; - ploc->is_write = 1; /* ref */ - if ((f == NULL) || - (f->refcount == USB_FIFO_REF_MAX) || - (f->curr_file != fp)) { + if (cpd->fflags & FWRITE) { + ppf = cpd->udev->fifo; + f = ppf[cpd->fifo_index + USB_FIFO_TX]; + cpd->txfifo = f; + cpd->is_write = 1; /* ref */ + if (f == NULL || f->refcount == USB_FIFO_REF_MAX) goto error; - } /* check if USB-FS is active */ if (f->fs_ep_max != 0) { - ploc->is_usbfs = 1; + cpd->is_usbfs = 1; } /* * Get real endpoint index associated with @@ -551,24 +211,21 @@ usb2_ref_device(struct file *fp, struct usb2_location *ploc, uint32_t devloc) */ dev_ep_index = f->dev_ep_index; } else { - ploc->txfifo = NULL; - ploc->is_write = 0; /* no ref */ + cpd->txfifo = NULL; + cpd->is_write = 0; /* no ref */ } /* check for read */ - if (fflags & FREAD) { - ppf = ploc->udev->fifo; - f = ppf[ploc->fifo_index + USB_FIFO_RX]; - ploc->rxfifo = f; - ploc->is_read = 1; /* ref */ - if ((f == NULL) || - (f->refcount == USB_FIFO_REF_MAX) || - (f->curr_file != fp)) { + if (cpd->fflags & FREAD) { + ppf = cpd->udev->fifo; + f = ppf[cpd->fifo_index + USB_FIFO_RX]; + cpd->rxfifo = f; + cpd->is_read = 1; /* ref */ + if (f == NULL || f->refcount == USB_FIFO_REF_MAX) goto error; - } /* check if USB-FS is active */ if (f->fs_ep_max != 0) { - ploc->is_usbfs = 1; + cpd->is_usbfs = 1; } /* * Get real endpoint index associated with @@ -576,45 +233,46 @@ usb2_ref_device(struct file *fp, struct usb2_location *ploc, uint32_t devloc) */ dev_ep_index = f->dev_ep_index; } else { - ploc->rxfifo = NULL; - ploc->is_read = 0; /* no ref */ + cpd->rxfifo = NULL; + cpd->is_read = 0; /* no ref */ } } /* check if we require an interface */ - ploc->iface = usb2_get_iface(ploc->udev, ploc->iface_index); + cpd->iface = usb2_get_iface(cpd->udev, cpd->iface_index); if (dev_ep_index != 0) { /* non control endpoint - we need an interface */ - if (ploc->iface == NULL) { + if (cpd->iface == NULL) { DPRINTFN(2, "no iface\n"); goto error; } - if (ploc->iface->idesc == NULL) { + if (cpd->iface->idesc == NULL) { DPRINTFN(2, "no idesc\n"); goto error; } } /* when everything is OK we increment the refcounts */ - if (ploc->is_write) { + if (cpd->is_write) { DPRINTFN(2, "ref write\n"); - ploc->txfifo->refcount++; + cpd->txfifo->refcount++; } - if (ploc->is_read) { + if (cpd->is_read) { DPRINTFN(2, "ref read\n"); - ploc->rxfifo->refcount++; + cpd->rxfifo->refcount++; } - if (ploc->is_uref) { + if (need_uref) { DPRINTFN(2, "ref udev - needed\n"); - ploc->udev->refcount++; + cpd->udev->refcount++; + cpd->is_uref = 1; } mtx_unlock(&usb2_ref_lock); - if (ploc->is_uref) { + if (cpd->is_uref) { /* * We are about to alter the bus-state. Apply the * required locks. */ - sx_xlock(ploc->udev->default_sx + 1); + sx_xlock(cpd->udev->default_sx + 1); mtx_lock(&Giant); /* XXX */ } return (0); @@ -636,39 +294,39 @@ usb2_ref_device(struct file *fp, struct usb2_location *ploc, uint32_t devloc) * Else: Failure. *------------------------------------------------------------------------*/ static usb2_error_t -usb2_uref_location(struct usb2_location *ploc) +usb2_uref_location(struct usb2_cdev_privdata *cpd) { /* * Check if we already got an USB reference on this location: */ - if (ploc->is_uref) { + if (cpd->is_uref) { return (0); /* success */ } mtx_lock(&usb2_ref_lock); - if (ploc->bus != devclass_get_softc(usb2_devclass_ptr, ploc->bus_index)) { - DPRINTFN(2, "bus changed at %u\n", ploc->bus_index); + if (cpd->bus != devclass_get_softc(usb2_devclass_ptr, cpd->bus_index)) { + DPRINTFN(2, "bus changed at %u\n", cpd->bus_index); goto error; } - if (ploc->udev != ploc->bus->devices[ploc->dev_index]) { - DPRINTFN(2, "device changed at %u\n", ploc->dev_index); + if (cpd->udev != cpd->bus->devices[cpd->dev_index]) { + DPRINTFN(2, "device changed at %u\n", cpd->dev_index); goto error; } - if (ploc->udev->refcount == USB_DEV_REF_MAX) { + if (cpd->udev->refcount == USB_DEV_REF_MAX) { DPRINTFN(2, "no dev ref\n"); goto error; } DPRINTFN(2, "ref udev\n"); - ploc->udev->refcount++; + cpd->udev->refcount++; mtx_unlock(&usb2_ref_lock); /* set "uref" */ - ploc->is_uref = 1; + cpd->is_uref = 1; /* * We are about to alter the bus-state. Apply the * required locks. */ - sx_xlock(ploc->udev->default_sx + 1); + sx_xlock(cpd->udev->default_sx + 1); mtx_lock(&Giant); /* XXX */ return (0); @@ -685,27 +343,30 @@ usb2_uref_location(struct usb2_location *ploc) * given USB device. *------------------------------------------------------------------------*/ void -usb2_unref_device(struct usb2_location *ploc) +usb2_unref_device(struct usb2_cdev_privdata *cpd) { - if (ploc->is_uref) { + if (cpd->is_uref) { mtx_unlock(&Giant); /* XXX */ - sx_unlock(ploc->udev->default_sx + 1); + sx_unlock(cpd->udev->default_sx + 1); } mtx_lock(&usb2_ref_lock); - if (ploc->is_read) { - if (--(ploc->rxfifo->refcount) == 0) { - usb2_cv_signal(&ploc->rxfifo->cv_drain); + if (cpd->is_read) { + if (--(cpd->rxfifo->refcount) == 0) { + usb2_cv_signal(&cpd->rxfifo->cv_drain); } + cpd->is_read = 0; } - if (ploc->is_write) { - if (--(ploc->txfifo->refcount) == 0) { - usb2_cv_signal(&ploc->txfifo->cv_drain); + if (cpd->is_write) { + if (--(cpd->txfifo->refcount) == 0) { + usb2_cv_signal(&cpd->txfifo->cv_drain); } + cpd->is_write = 0; } - if (ploc->is_uref) { - if (--(ploc->udev->refcount) == 0) { - usb2_cv_signal(ploc->udev->default_cv + 1); + if (cpd->is_uref) { + if (--(cpd->udev->refcount) == 0) { + usb2_cv_signal(cpd->udev->default_cv + 1); } + cpd->is_uref = 0; } mtx_unlock(&usb2_ref_lock); } @@ -728,28 +389,46 @@ usb2_fifo_alloc(void) * usb2_fifo_create *------------------------------------------------------------------------*/ static int -usb2_fifo_create(struct usb2_location *ploc, uint32_t *pdevloc, int fflags) +usb2_fifo_create(struct usb2_cdev_privdata *cpd) { - struct usb2_device *udev = ploc->udev; + struct usb2_device *udev = cpd->udev; struct usb2_fifo *f; struct usb2_pipe *pipe; - uint8_t iface_index = ploc->iface_index; - - /* NOTE: variable overloading: */ - uint8_t dev_ep_index = ploc->fifo_index; + uint8_t iface_index = cpd->iface_index; uint8_t n; uint8_t is_tx; uint8_t is_rx; uint8_t no_null; uint8_t is_busy; + int ep = cpd->ep_addr; - is_tx = (fflags & FWRITE) ? 1 : 0; - is_rx = (fflags & FREAD) ? 1 : 0; + is_tx = (cpd->fflags & FWRITE) ? 1 : 0; + is_rx = (cpd->fflags & FREAD) ? 1 : 0; no_null = 1; is_busy = 0; - /* search for a free FIFO slot */ + /* Preallocated FIFO */ + if (ep < 0) { + DPRINTFN(5, "Preallocated FIFO\n"); + if (is_tx) { + f = udev->fifo[cpd->fifo_index + USB_FIFO_TX]; + if (f == NULL) + return (EINVAL); + cpd->txfifo = f; + } + if (is_rx) { + f = udev->fifo[cpd->fifo_index + USB_FIFO_RX]; + if (f == NULL) + return (EINVAL); + cpd->rxfifo = f; + } + return (0); + } + KASSERT(ep >= 0 && ep <= 15, ("endpoint %d out of range", ep)); + + /* search for a free FIFO slot */ + DPRINTFN(5, "Endpoint device, searching for 0x%02x\n", ep); for (n = 0;; n += 2) { if (n == USB_FIFO_MAX) { @@ -758,6 +437,7 @@ usb2_fifo_create(struct usb2_location *ploc, uint32_t *pdevloc, int fflags) n = 0; } else { /* end of FIFOs reached */ + DPRINTFN(5, "out of FIFOs\n"); return (ENOMEM); } } @@ -765,16 +445,16 @@ usb2_fifo_create(struct usb2_location *ploc, uint32_t *pdevloc, int fflags) if (is_tx) { f = udev->fifo[n + USB_FIFO_TX]; if (f != NULL) { - if (f->dev_ep_index != dev_ep_index) { + if (f->dev_ep_index != ep) { /* wrong endpoint index */ continue; } - if ((dev_ep_index != 0) && - (f->iface_index != iface_index)) { + if (ep != 0 && + f->iface_index != iface_index) { /* wrong interface index */ continue; } - if (f->curr_file != NULL) { + if (f->opened) { /* FIFO is opened */ is_busy = 1; continue; @@ -787,16 +467,16 @@ usb2_fifo_create(struct usb2_location *ploc, uint32_t *pdevloc, int fflags) if (is_rx) { f = udev->fifo[n + USB_FIFO_RX]; if (f != NULL) { - if (f->dev_ep_index != dev_ep_index) { + if (f->dev_ep_index != ep) { /* wrong endpoint index */ continue; } - if ((dev_ep_index != 0) && - (f->iface_index != iface_index)) { + if (ep != 0 && + f->iface_index != iface_index) { /* wrong interface index */ continue; } - if (f->curr_file != NULL) { + if (f->opened) { /* FIFO is opened */ is_busy = 1; continue; @@ -809,8 +489,9 @@ usb2_fifo_create(struct usb2_location *ploc, uint32_t *pdevloc, int fflags) } if (no_null == 0) { - if (dev_ep_index >= (USB_EP_MAX / 2)) { + if (ep >= (USB_EP_MAX / 2)) { /* we don't create any endpoints in this range */ + DPRINTFN(5, "dev_ep_index out of range\n"); return (is_busy ? EBUSY : EINVAL); } } @@ -818,17 +499,20 @@ usb2_fifo_create(struct usb2_location *ploc, uint32_t *pdevloc, int fflags) if (is_tx && (udev->fifo[n + USB_FIFO_TX] == NULL)) { pipe = usb2_dev_get_pipe(udev, - iface_index, dev_ep_index, USB_FIFO_TX); + iface_index, ep, USB_FIFO_TX); + DPRINTFN(5, "dev_get_pipe(%d, 0x%x, 0x%x)\n", iface_index, ep, USB_FIFO_TX); if (pipe == NULL) { + DPRINTFN(5, "dev_get_pipe returned NULL\n"); return (EINVAL); } f = usb2_fifo_alloc(); if (f == NULL) { + DPRINTFN(5, "could not alloc tx fifo\n"); return (ENOMEM); } /* update some fields */ f->fifo_index = n + USB_FIFO_TX; - f->dev_ep_index = dev_ep_index; + f->dev_ep_index = ep; f->priv_mtx = udev->default_mtx; f->priv_sc0 = pipe; f->methods = &usb2_ugen_methods; @@ -843,17 +527,20 @@ usb2_fifo_create(struct usb2_location *ploc, uint32_t *pdevloc, int fflags) (udev->fifo[n + USB_FIFO_RX] == NULL)) { pipe = usb2_dev_get_pipe(udev, - iface_index, dev_ep_index, USB_FIFO_RX); + iface_index, ep, USB_FIFO_RX); + DPRINTFN(5, "dev_get_pipe(%d, 0x%x, 0x%x)\n", iface_index, ep, USB_FIFO_RX); if (pipe == NULL) { + DPRINTFN(5, "dev_get_pipe returned NULL\n"); return (EINVAL); } f = usb2_fifo_alloc(); if (f == NULL) { + DPRINTFN(5, "could not alloc rx fifo\n"); return (ENOMEM); } /* update some fields */ f->fifo_index = n + USB_FIFO_RX; - f->dev_ep_index = dev_ep_index; + f->dev_ep_index = ep; f->priv_mtx = udev->default_mtx; f->priv_sc0 = pipe; f->methods = &usb2_ugen_methods; @@ -864,15 +551,14 @@ usb2_fifo_create(struct usb2_location *ploc, uint32_t *pdevloc, int fflags) mtx_unlock(&usb2_ref_lock); } if (is_tx) { - ploc->txfifo = udev->fifo[n + USB_FIFO_TX]; + cpd->txfifo = udev->fifo[n + USB_FIFO_TX]; } if (is_rx) { - ploc->rxfifo = udev->fifo[n + USB_FIFO_RX]; + cpd->rxfifo = udev->fifo[n + USB_FIFO_RX]; } - /* replace endpoint index by FIFO index */ - - (*pdevloc) %= (USB_BUS_MAX * USB_DEV_MAX * USB_IFACE_MAX); - (*pdevloc) += (USB_BUS_MAX * USB_DEV_MAX * USB_IFACE_MAX) * n; + /* fill out fifo index */ + DPRINTFN(5, "fifo index = %d\n", n); + cpd->fifo_index = n; /* complete */ @@ -928,7 +614,7 @@ usb2_fifo_free(struct usb2_fifo *f) mtx_unlock(&usb2_ref_lock); /* take care of closing the device here, if any */ - usb2_fifo_close(f, curthread, 0); + usb2_fifo_close(f, 0); usb2_cv_destroy(&f->cv_io); usb2_cv_destroy(&f->cv_drain); @@ -990,8 +676,7 @@ usb2_dev_get_pipe(struct usb2_device *udev, * Else: Failure *------------------------------------------------------------------------*/ static int -usb2_fifo_open(struct usb2_fifo *f, struct file *fp, struct thread *td, - int fflags) +usb2_fifo_open(struct usb2_fifo *f, int fflags) { int err; @@ -1012,12 +697,13 @@ usb2_fifo_open(struct usb2_fifo *f, struct file *fp, struct thread *td, /* check if we are already opened */ /* we don't need any locks when checking this variable */ - if (f->curr_file) { + if (f->opened) { err = EBUSY; goto done; } + /* call open method */ - err = (f->methods->f_open) (f, fflags, td); + err = (f->methods->f_open) (f, fflags); if (err) { goto done; } @@ -1041,9 +727,9 @@ usb2_fifo_open(struct usb2_fifo *f, struct file *fp, struct thread *td, /* reset ASYNC proc flag */ f->async_p = NULL; - /* set which file we belong to */ + /* flag the fifo as opened to prevent others */ mtx_lock(&usb2_ref_lock); - f->curr_file = fp; + f->opened = 1; mtx_unlock(&usb2_ref_lock); /* reset queue */ @@ -1079,19 +765,19 @@ usb2_fifo_reset(struct usb2_fifo *f) * usb2_fifo_close *------------------------------------------------------------------------*/ static void -usb2_fifo_close(struct usb2_fifo *f, struct thread *td, int fflags) +usb2_fifo_close(struct usb2_fifo *f, int fflags) { int err; /* check if we are not opened */ - if (!f->curr_file) { + if (!f->opened) { /* nothing to do - already closed */ return; } mtx_lock(f->priv_mtx); /* clear current file flag */ - f->curr_file = NULL; + f->opened = 0; /* check if we are selected */ if (f->flag_isselect) { @@ -1149,310 +835,126 @@ usb2_fifo_close(struct usb2_fifo *f, struct thread *td, int fflags) mtx_unlock(f->priv_mtx); /* call close method */ - (f->methods->f_close) (f, fflags, td); + (f->methods->f_close) (f, fflags); DPRINTF("closed\n"); } /*------------------------------------------------------------------------* - * usb2_check_thread_perm - * - * Returns: - * 0: Has permission. - * Else: No permission. - *------------------------------------------------------------------------*/ -int -usb2_check_thread_perm(struct usb2_device *udev, struct thread *td, - int fflags, uint8_t iface_index, uint8_t ep_index) -{ - struct usb2_interface *iface; - int err; - - if (ep_index != 0) { - /* - * Non-control endpoints are always - * associated with an interface: - */ - iface = usb2_get_iface(udev, iface_index); - if (iface == NULL) { - return (EINVAL); - } - if (iface->idesc == NULL) { - return (EINVAL); - } - } else { - iface = NULL; - } - /* scan down the permissions tree */ - if ((iface != NULL) && - (usb2_check_access(fflags, &iface->perm) == 0)) { - /* we got access through the interface */ - err = 0; - } else if (udev && - (usb2_check_access(fflags, &udev->perm) == 0)) { - /* we got access through the device */ - err = 0; - } else if (udev->bus && - (usb2_check_access(fflags, &udev->bus->perm) == 0)) { - /* we got access through the USB bus */ - err = 0; - } else if (usb2_check_access(fflags, &usb2_perm) == 0) { - /* we got general access */ - err = 0; - } else { - /* no access */ - err = EPERM; - } - return (err); -} - -/*------------------------------------------------------------------------* - * usb2_fdopen - cdev callback + * usb2_open - cdev callback *------------------------------------------------------------------------*/ static int -usb2_fdopen(struct cdev *dev, int xxx_oflags, struct thread *td, - struct file *fp) +usb2_open(struct cdev *dev, int fflags, int devtype, struct thread *td) { - struct usb2_location loc; - uint32_t devloc; - int err; - int fflags; + struct usb2_fs_privdata* pd = (struct usb2_fs_privdata*)dev->si_drv1; + struct usb2_cdev_privdata *cpd; + int err, ep; - DPRINTFN(2, "oflags=0x%08x\n", xxx_oflags); - - devloc = usb2_last_devloc; - usb2_last_devloc = (0 - 1); /* reset "usb2_last_devloc" */ - - if (fp == NULL) { - DPRINTFN(2, "fp == NULL\n"); - return (ENXIO); - } - if (usb2_old_f_data != fp->f_data) { - if (usb2_old_f_data != NULL) { - DPRINTFN(0, "File data mismatch!\n"); - return (ENXIO); - } - usb2_old_f_data = fp->f_data; - } - if (usb2_old_f_ops != fp->f_ops) { - if (usb2_old_f_ops != NULL) { - DPRINTFN(0, "File ops mismatch!\n"); - return (ENXIO); - } - usb2_old_f_ops = fp->f_ops; - } - fflags = fp->f_flag; DPRINTFN(2, "fflags=0x%08x\n", fflags); - if (!(fflags & (FREAD | FWRITE))) { - /* should not happen */ + KASSERT(fflags & (FREAD|FWRITE), ("invalid open flags")); + if (((fflags & FREAD) && !(pd->mode & FREAD)) || + ((fflags & FWRITE) && !(pd->mode & FWRITE))) { + DPRINTFN(2, "access mode not supported\n"); return (EPERM); } - if (devloc == (uint32_t)(0 - 2)) { - /* tried to open "/dev/usb" */ - return (0); - } else if (devloc == (uint32_t)(0 - 1)) { - /* tried to open "/dev/usb " */ - DPRINTFN(2, "no devloc\n"); - return (ENXIO); - } - err = usb2_ref_device(NULL, &loc, devloc); + + cpd = malloc(sizeof(*cpd), M_USBDEV, M_WAITOK | M_ZERO); + ep = cpd->ep_addr = pd->ep_addr; + + usb2_loc_fill(pd, cpd); + err = usb2_ref_device(cpd, 1); if (err) { DPRINTFN(2, "cannot ref device\n"); + free(cpd, M_USBDEV); return (ENXIO); } - /* - * NOTE: Variable overloading. "usb2_fifo_create" will update - * the FIFO index. Right here we can assume that the - * "fifo_index" is the same like the endpoint number without - * direction mask, if the "fifo_index" is less than 16. - */ - err = usb2_check_thread_perm(loc.udev, td, fflags, - loc.iface_index, loc.fifo_index); + cpd->fflags = fflags; /* access mode for open lifetime */ - /* check for error */ - if (err) { - usb2_unref_device(&loc); - return (err); + /* Check if the endpoint is already open, we always allow EP0 */ + if (ep > 0) { + if ((fflags & FREAD && cpd->udev->ep_rd_opened & (1 << ep)) || + (fflags & FWRITE && cpd->udev->ep_wr_opened & (1 << ep))) { + DPRINTFN(2, "endpoint already open\n"); + usb2_unref_device(cpd); + free(cpd, M_USBDEV); + return (EBUSY); + } + if (fflags & FREAD) + cpd->udev->ep_rd_opened |= (1 << ep); + if (fflags & FWRITE) + cpd->udev->ep_wr_opened |= (1 << ep); } + /* create FIFOs, if any */ - err = usb2_fifo_create(&loc, &devloc, fflags); + err = usb2_fifo_create(cpd); /* check for error */ if (err) { - usb2_unref_device(&loc); + DPRINTFN(2, "cannot create fifo\n"); + usb2_unref_device(cpd); + free(cpd, M_USBDEV); return (err); } if (fflags & FREAD) { - err = usb2_fifo_open(loc.rxfifo, fp, td, fflags); + err = usb2_fifo_open(cpd->rxfifo, fflags); if (err) { DPRINTFN(2, "read open failed\n"); - usb2_unref_device(&loc); + usb2_unref_device(cpd); + free(cpd, M_USBDEV); return (err); } } if (fflags & FWRITE) { - err = usb2_fifo_open(loc.txfifo, fp, td, fflags); + err = usb2_fifo_open(cpd->txfifo, fflags); if (err) { DPRINTFN(2, "write open failed\n"); if (fflags & FREAD) { - usb2_fifo_close(loc.rxfifo, td, - fflags); + usb2_fifo_close(cpd->rxfifo, fflags); } - usb2_unref_device(&loc); + usb2_unref_device(cpd); + free(cpd, M_USBDEV); return (err); } } - /* - * Take over the file so that we get all the callbacks - * directly and don't have to create another device: - */ - finit(fp, fp->f_flag, DTYPE_VNODE, - ((uint8_t *)0) + devloc, &usb2_ops_f); + usb2_unref_device(cpd); + devfs_set_cdevpriv(cpd, usb2_close); - usb2_unref_device(&loc); - - DPRINTFN(2, "error=%d\n", err); - - return (err); + return (0); } /*------------------------------------------------------------------------* * usb2_close - cdev callback *------------------------------------------------------------------------*/ -static int -usb2_close(struct cdev *dev, int flag, int mode, struct thread *p) -{ - DPRINTF("\n"); - return (0); /* nothing to do */ -} - -/*------------------------------------------------------------------------* - * usb2_close - cdev callback - *------------------------------------------------------------------------*/ -static int -usb2_ioctl(struct cdev *dev, u_long cmd, caddr_t data, - int fflag, struct thread *td) -{ - union { - struct usb2_read_dir *urd; - struct usb2_dev_perm *udp; - void *data; - } u; - int err; - - u.data = data; - - err = 0; - switch (cmd) { - case USB_READ_DIR: - err = usb2_read_symlink(u.urd->urd_data, - u.urd->urd_startentry, u.urd->urd_maxlen); - break; - case USB_SET_IFACE_PERM: - err = usb2_set_perm(u.udp, 3); - break; - case USB_SET_DEVICE_PERM: - err = usb2_set_perm(u.udp, 2); - break; - case USB_SET_BUS_PERM: - err = usb2_set_perm(u.udp, 1); - break; - case USB_SET_ROOT_PERM: - err = usb2_set_perm(u.udp, 0); - break; - case USB_GET_IFACE_PERM: - err = usb2_get_perm(u.udp, 3); - break; - case USB_GET_DEVICE_PERM: - err = usb2_get_perm(u.udp, 2); - break; - case USB_GET_BUS_PERM: - err = usb2_get_perm(u.udp, 1); - break; - case USB_GET_ROOT_PERM: - err = usb2_get_perm(u.udp, 0); - break; - case USB_DEV_QUIRK_GET: - case USB_QUIRK_NAME_GET: - case USB_DEV_QUIRK_ADD: - case USB_DEV_QUIRK_REMOVE: - err = usb2_quirk_ioctl_p(cmd, data, fflag, td); - break; - case USB_GET_TEMPLATE: - *(int *)data = usb2_template; - break; - case USB_SET_TEMPLATE: - err = priv_check(curthread, PRIV_ROOT); - if (err) - break; - usb2_template = *(int *)data; - break; - default: - err = ENOTTY; - break; - } - return (err); -} - -/*------------------------------------------------------------------------* - * usb2_clone - cdev callback - * - * This function is the kernel clone callback for "/dev/usbX.Y". - * - * NOTE: This function assumes that the clone and device open - * operation is atomic. - *------------------------------------------------------------------------*/ static void -usb2_clone(void *arg, USB_UCRED char *name, int namelen, struct cdev **dev) +usb2_close(void *arg) { - enum { - USB_DNAME_LEN = sizeof(USB_DEVICE_NAME) - 1, - USB_GNAME_LEN = sizeof(USB_GENERIC_NAME) - 1, - }; + struct usb2_cdev_privdata *cpd = arg; + struct usb2_device *udev; + int err; - if (*dev) { - /* someone else has created a device */ + DPRINTFN(2, "usb2_close, cpd=%p\n", cpd); + + err = usb2_ref_device(cpd, 1); + if (err) { + free(cpd, M_USBDEV); return; } - /* reset device location */ - usb2_last_devloc = (uint32_t)(0 - 1); - /* - * Check if we are matching "usb", "ugen" or an internal - * symbolic link: - */ - if ((namelen >= USB_DNAME_LEN) && - (bcmp(name, USB_DEVICE_NAME, USB_DNAME_LEN) == 0)) { - if (namelen == USB_DNAME_LEN) { - /* USB management device location */ - usb2_last_devloc = (uint32_t)(0 - 2); - } else { - /* USB endpoint */ - usb2_last_devloc = - usb2_path_convert(name + USB_DNAME_LEN); - } - } else if ((namelen >= USB_GNAME_LEN) && - (bcmp(name, USB_GENERIC_NAME, USB_GNAME_LEN) == 0)) { - if (namelen == USB_GNAME_LEN) { - /* USB management device location */ - usb2_last_devloc = (uint32_t)(0 - 2); - } else { - /* USB endpoint */ - usb2_last_devloc = - usb2_path_convert(name + USB_GNAME_LEN); - } + udev = cpd->udev; + if (cpd->fflags & FREAD) { + usb2_fifo_close(cpd->rxfifo, cpd->fflags); + /* clear read bitmask */ + udev->ep_rd_opened &= ~(1 << cpd->ep_addr); } - if (usb2_last_devloc == (uint32_t)(0 - 1)) { - /* Search for symbolic link */ - usb2_last_devloc = - usb2_lookup_symlink(name, namelen); + if (cpd->fflags & FWRITE) { + usb2_fifo_close(cpd->txfifo, cpd->fflags); + /* clear write bitmask */ + udev->ep_wr_opened &= ~(1 << cpd->ep_addr); } - if (usb2_last_devloc == (uint32_t)(0 - 1)) { - /* invalid location */ - return; - } - dev_ref(usb2_dev); - *dev = usb2_dev; + + usb2_unref_device(cpd); + free(cpd, M_USBDEV); + return; } static void @@ -1472,24 +974,14 @@ static void usb2_dev_init_post(void *arg) { /* - * Create a dummy device so that we are visible. This device - * should never be opened. Therefore a space character is - * appended after the USB device name. - * - * NOTE: The permissions of this device is 0666, because we - * check the permissions again in the open routine against the - * real USB permissions which are not 0666. Else USB access - * will be limited to one user and one group. + * Create /dev/usb - this is needed for usbconfig(8), which + * needs a well-known device name to access. */ - usb2_dev = make_dev(&usb2_devsw, 0, UID_ROOT, GID_OPERATOR, - 0666, USB_DEVICE_NAME " "); + usb2_dev = make_dev(&usb2_static_devsw, 0, UID_ROOT, GID_OPERATOR, + 0644, USB_DEVICE_NAME); if (usb2_dev == NULL) { DPRINTFN(0, "Could not create usb bus device!\n"); } - usb2_clone_tag = EVENTHANDLER_REGISTER(dev_clone, usb2_clone_ptr, NULL, 1000); - if (usb2_clone_tag == NULL) { - DPRINTFN(0, "Registering clone handler failed!\n"); - } } SYSINIT(usb2_dev_init_post, SI_SUB_KICK_SCHEDULER, SI_ORDER_FIRST, usb2_dev_init_post, NULL); @@ -1497,13 +989,10 @@ SYSINIT(usb2_dev_init_post, SI_SUB_KICK_SCHEDULER, SI_ORDER_FIRST, usb2_dev_init static void usb2_dev_uninit(void *arg) { - if (usb2_clone_tag) { - EVENTHANDLER_DEREGISTER(dev_clone, usb2_clone_tag); - usb2_clone_tag = NULL; - } - if (usb2_dev) { + if (usb2_dev != NULL) { destroy_dev(usb2_dev); usb2_dev = NULL; + } mtx_destroy(&usb2_ref_lock); sx_destroy(&usb2_sym_lock); @@ -1511,43 +1000,6 @@ usb2_dev_uninit(void *arg) SYSUNINIT(usb2_dev_uninit, SI_SUB_KICK_SCHEDULER, SI_ORDER_ANY, usb2_dev_uninit, NULL); -static int -usb2_close_f(struct file *fp, struct thread *td) -{ - struct usb2_location loc; - int fflags; - int err; - - fflags = fp->f_flag; - - DPRINTFN(2, "fflags=%u\n", fflags); - - err = usb2_ref_device(fp, &loc, 0 /* need uref */ );; - - /* restore some file variables */ - fp->f_ops = usb2_old_f_ops; - fp->f_data = usb2_old_f_data; - - /* check for error */ - if (err) { - DPRINTFN(2, "could not ref\n"); - goto done; - } - if (fflags & FREAD) { - usb2_fifo_close(loc.rxfifo, td, fflags); - } - if (fflags & FWRITE) { - usb2_fifo_close(loc.txfifo, td, fflags); - } - usb2_unref_device(&loc); - -done: - /* call old close method */ - USB_VNOPS_FO_CLOSE(fp, td, &err); - - return (err); -} - static int usb2_ioctl_f_sub(struct usb2_fifo *f, u_long cmd, void *addr, struct thread *td) @@ -1592,20 +1044,26 @@ usb2_ioctl_f_sub(struct usb2_fifo *f, u_long cmd, void *addr, return (error); } +/*------------------------------------------------------------------------* + * usb2_ioctl - cdev callback + *------------------------------------------------------------------------*/ static int -usb2_ioctl_f(struct file *fp, u_long cmd, void *addr, - struct ucred *cred, struct thread *td) +usb2_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread* td) { - struct usb2_location loc; + struct usb2_cdev_privdata* cpd; struct usb2_fifo *f; int fflags; int err; - err = usb2_ref_device(fp, &loc, 1 /* no uref */ );; + err = devfs_get_cdevpriv((void **)&cpd); + if (err != 0) + return (err); + + err = usb2_ref_device(cpd, 1); if (err) { return (ENXIO); } - fflags = fp->f_flag; + fflags = cpd->fflags; DPRINTFN(2, "fflags=%u, cmd=0x%lx\n", fflags, cmd); @@ -1613,65 +1071,62 @@ usb2_ioctl_f(struct file *fp, u_long cmd, void *addr, err = ENOIOCTL; /* set default value */ if (fflags & FWRITE) { - f = loc.txfifo; + f = cpd->txfifo; err = usb2_ioctl_f_sub(f, cmd, addr, td); } if (fflags & FREAD) { - f = loc.rxfifo; + f = cpd->rxfifo; err = usb2_ioctl_f_sub(f, cmd, addr, td); } + KASSERT(f != NULL, ("fifo not found")); if (err == ENOIOCTL) { - err = (f->methods->f_ioctl) (f, cmd, addr, fflags, td); + err = (f->methods->f_ioctl) (f, cmd, addr, fflags); if (err == ENOIOCTL) { - if (usb2_uref_location(&loc)) { + if (usb2_uref_location(cpd)) { err = ENXIO; goto done; } - err = (f->methods->f_ioctl_post) (f, cmd, addr, fflags, td); + err = (f->methods->f_ioctl_post) (f, cmd, addr, fflags); } } if (err == ENOIOCTL) { err = ENOTTY; } done: - usb2_unref_device(&loc); + usb2_unref_device(cpd); return (err); } /* ARGSUSED */ static int -usb2_kqfilter_f(struct file *fp, struct knote *kn) +usb2_poll(struct cdev* dev, int events, struct thread* td) { - return (ENXIO); -} - -/* ARGSUSED */ -static int -usb2_poll_f(struct file *fp, int events, - struct ucred *cred, struct thread *td) -{ - struct usb2_location loc; + struct usb2_cdev_privdata* cpd; struct usb2_fifo *f; struct usb2_mbuf *m; int fflags; - int revents; + int err, revents; - revents = usb2_ref_device(fp, &loc, 1 /* no uref */ );; - if (revents) { + err = devfs_get_cdevpriv((void **)&cpd); + if (err != 0) + return (err); + + err = usb2_ref_device(cpd, 0 /* no uref */ ); + if (err) return (POLLHUP); - } - fflags = fp->f_flag; + + fflags = cpd->fflags; /* Figure out who needs service */ - + revents = 0; if ((events & (POLLOUT | POLLWRNORM)) && (fflags & FWRITE)) { - f = loc.txfifo; + f = cpd->txfifo; mtx_lock(f->priv_mtx); - if (!loc.is_usbfs) { + if (!cpd->is_usbfs) { if (f->flag_iserror) { /* we got an error */ m = (void *)1; @@ -1706,11 +1161,11 @@ usb2_poll_f(struct file *fp, int events, if ((events & (POLLIN | POLLRDNORM)) && (fflags & FREAD)) { - f = loc.rxfifo; + f = cpd->rxfifo; mtx_lock(f->priv_mtx); - if (!loc.is_usbfs) { + if (!cpd->is_usbfs) { if (f->flag_iserror) { /* we have and error */ m = (void *)1; @@ -1739,7 +1194,7 @@ usb2_poll_f(struct file *fp, int events, f->flag_isselect = 1; selrecord(td, &f->selinfo); - if (!loc.is_usbfs) { + if (!cpd->is_usbfs) { /* start reading data */ (f->methods->f_start_read) (f); } @@ -1747,16 +1202,14 @@ usb2_poll_f(struct file *fp, int events, mtx_unlock(f->priv_mtx); } - usb2_unref_device(&loc); + usb2_unref_device(cpd); return (revents); } -/* ARGSUSED */ static int -usb2_read_f(struct file *fp, struct uio *uio, struct ucred *cred, - int flags, struct thread *td) +usb2_read(struct cdev *dev, struct uio *uio, int ioflag) { - struct usb2_location loc; + struct usb2_cdev_privdata* cpd; struct usb2_fifo *f; struct usb2_mbuf *m; int fflags; @@ -1765,25 +1218,23 @@ usb2_read_f(struct file *fp, struct uio *uio, struct ucred *cred, int err; uint8_t tr_data = 0; - DPRINTFN(2, "\n"); + err = devfs_get_cdevpriv((void **)&cpd); + if (err != 0) + return (err); - fflags = fp->f_flag & (O_NONBLOCK | O_DIRECT | FREAD | FWRITE); - if (fflags & O_DIRECT) - fflags |= IO_DIRECT; - - err = usb2_ref_device(fp, &loc, 1 /* no uref */ ); + err = usb2_ref_device(cpd, 0 /* no uref */ ); if (err) { return (ENXIO); } - f = loc.rxfifo; + fflags = cpd->fflags; + + f = cpd->rxfifo; if (f == NULL) { /* should not happen */ return (EPERM); } - resid = uio->uio_resid; - if ((flags & FOF_OFFSET) == 0) - uio->uio_offset = fp->f_offset; + resid = uio->uio_resid; mtx_lock(f->priv_mtx); @@ -1793,7 +1244,7 @@ usb2_read_f(struct file *fp, struct uio *uio, struct ucred *cred, goto done; } /* check if USB-FS interface is active */ - if (loc.is_usbfs) { + if (cpd->is_usbfs) { /* * The queue is used for events that should be * retrieved using the "USB_FS_COMPLETE" ioctl. @@ -1811,7 +1262,7 @@ usb2_read_f(struct file *fp, struct uio *uio, struct ucred *cred, (f->methods->f_start_read) (f); - if (fflags & O_NONBLOCK) { + if (fflags & IO_NDELAY) { if (tr_data) { /* return length before error */ break; @@ -1871,35 +1322,15 @@ usb2_read_f(struct file *fp, struct uio *uio, struct ucred *cred, done: mtx_unlock(f->priv_mtx); - usb2_unref_device(&loc); + usb2_unref_device(cpd); - if ((flags & FOF_OFFSET) == 0) - fp->f_offset = uio->uio_offset; - fp->f_nextoff = uio->uio_offset; return (err); } static int -usb2_stat_f(struct file *fp, struct stat *sb, struct ucred *cred, struct thread *td) +usb2_write(struct cdev *dev, struct uio *uio, int ioflag) { - return (USB_VNOPS_FO_STAT(fp, sb, cred, td)); -} - -#if __FreeBSD_version > 800009 -static int -usb2_truncate_f(struct file *fp, off_t length, struct ucred *cred, struct thread *td) -{ - return (USB_VNOPS_FO_TRUNCATE(fp, length, cred, td)); -} - -#endif - -/* ARGSUSED */ -static int -usb2_write_f(struct file *fp, struct uio *uio, struct ucred *cred, - int flags, struct thread *td) -{ - struct usb2_location loc; + struct usb2_cdev_privdata* cpd; struct usb2_fifo *f; struct usb2_mbuf *m; int fflags; @@ -1910,26 +1341,24 @@ usb2_write_f(struct file *fp, struct uio *uio, struct ucred *cred, DPRINTFN(2, "\n"); - fflags = fp->f_flag & (O_NONBLOCK | O_DIRECT | - FREAD | FWRITE | O_FSYNC); - if (fflags & O_DIRECT) - fflags |= IO_DIRECT; + err = devfs_get_cdevpriv((void **)&cpd); + if (err != 0) + return (err); - err = usb2_ref_device(fp, &loc, 1 /* no uref */ ); + err = usb2_ref_device(cpd, 0 /* no uref */ ); if (err) { return (ENXIO); } - f = loc.txfifo; + fflags = cpd->fflags; + + f = cpd->txfifo; if (f == NULL) { /* should not happen */ - usb2_unref_device(&loc); + usb2_unref_device(cpd); return (EPERM); } resid = uio->uio_resid; - if ((flags & FOF_OFFSET) == 0) - uio->uio_offset = fp->f_offset; - mtx_lock(f->priv_mtx); /* check for permanent write error */ @@ -1938,7 +1367,7 @@ usb2_write_f(struct file *fp, struct uio *uio, struct ucred *cred, goto done; } /* check if USB-FS interface is active */ - if (loc.is_usbfs) { + if (cpd->is_usbfs) { /* * The queue is used for events that should be * retrieved using the "USB_FS_COMPLETE" ioctl. @@ -1956,7 +1385,7 @@ usb2_write_f(struct file *fp, struct uio *uio, struct ucred *cred, if (m == NULL) { - if (fflags & O_NONBLOCK) { + if (fflags & IO_NDELAY) { if (tr_data) { /* return length before error */ break; @@ -2006,12 +1435,43 @@ usb2_write_f(struct file *fp, struct uio *uio, struct ucred *cred, done: mtx_unlock(f->priv_mtx); - usb2_unref_device(&loc); + usb2_unref_device(cpd); - if ((flags & FOF_OFFSET) == 0) - fp->f_offset = uio->uio_offset; - fp->f_nextoff = uio->uio_offset; + return (err); +} +int +usb2_static_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, + struct thread *td) +{ + union { + struct usb2_read_dir *urd; + void* data; + } u; + int err = ENOTTY; + + u.data = data; + switch (cmd) { + case USB_READ_DIR: + err = usb2_read_symlink(u.urd->urd_data, + u.urd->urd_startentry, u.urd->urd_maxlen); + break; + case USB_DEV_QUIRK_GET: + case USB_QUIRK_NAME_GET: + case USB_DEV_QUIRK_ADD: + case USB_DEV_QUIRK_REMOVE: + err = usb2_quirk_ioctl_p(cmd, data, fflag, td); + break; + case USB_GET_TEMPLATE: + *(int *)data = usb2_template; + break; + case USB_SET_TEMPLATE: + err = priv_check(curthread, PRIV_ROOT); + if (err) + break; + usb2_template = *(int *)data; + break; + } return (err); } @@ -2081,53 +1541,20 @@ usb2_fifo_wakeup(struct usb2_fifo *f) } } -/*------------------------------------------------------------------------* - * usb2_fifo_opened - * - * Returns: - * 0: FIFO not opened. - * Else: FIFO is opened. - *------------------------------------------------------------------------*/ -uint8_t -usb2_fifo_opened(struct usb2_fifo *f) -{ - uint8_t temp; - uint8_t do_unlock; - - if (f == NULL) { - return (0); /* be NULL safe */ - } - if (mtx_owned(f->priv_mtx)) { - do_unlock = 0; - } else { - do_unlock = 1; - mtx_lock(f->priv_mtx); - } - temp = f->curr_file ? 1 : 0; - if (do_unlock) { - mtx_unlock(f->priv_mtx); - } - return (temp); -} - - static int -usb2_fifo_dummy_open(struct usb2_fifo *fifo, - int fflags, struct thread *td) +usb2_fifo_dummy_open(struct usb2_fifo *fifo, int fflags) { return (0); } static void -usb2_fifo_dummy_close(struct usb2_fifo *fifo, - int fflags, struct thread *td) +usb2_fifo_dummy_close(struct usb2_fifo *fifo, int fflags) { return; } static int -usb2_fifo_dummy_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr, - int fflags, struct thread *td) +usb2_fifo_dummy_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr, int fflags) { return (ENOIOCTL); } @@ -2181,13 +1608,13 @@ int usb2_fifo_attach(struct usb2_device *udev, void *priv_sc, struct mtx *priv_mtx, struct usb2_fifo_methods *pm, struct usb2_fifo_sc *f_sc, uint16_t unit, uint16_t subunit, - uint8_t iface_index) + uint8_t iface_index, uid_t uid, gid_t gid, int mode) { struct usb2_fifo *f_tx; struct usb2_fifo *f_rx; - char buf[32]; - char src[32]; + char devname[32]; uint8_t n; + struct usb2_fs_privdata* pd; f_sc->fp[USB_FIFO_TX] = NULL; f_sc->fp[USB_FIFO_RX] = NULL; @@ -2253,28 +1680,20 @@ usb2_fifo_attach(struct usb2_device *udev, void *priv_sc, udev->fifo[f_rx->fifo_index] = f_rx; mtx_unlock(&usb2_ref_lock); - if (snprintf(src, sizeof(src), - USB_DEVICE_NAME "%u.%u.%u.%u", - device_get_unit(udev->bus->bdev), - udev->device_index, - iface_index, - f_tx->dev_ep_index)) { - /* ignore */ - } for (n = 0; n != 4; n++) { if (pm->basename[n] == NULL) { continue; } if (subunit == 0xFFFF) { - if (snprintf(buf, sizeof(buf), + if (snprintf(devname, sizeof(devname), "%s%u%s", pm->basename[n], unit, pm->postfix[n] ? pm->postfix[n] : "")) { /* ignore */ } } else { - if (snprintf(buf, sizeof(buf), + if (snprintf(devname, sizeof(devname), "%s%u.%u%s", pm->basename[n], unit, subunit, pm->postfix[n] ? pm->postfix[n] : "")) { @@ -2287,12 +1706,28 @@ usb2_fifo_attach(struct usb2_device *udev, void *priv_sc, */ if (n & 1) { f_rx->symlink[n / 2] = - usb2_alloc_symlink(src, "%s", buf); + usb2_alloc_symlink(devname); } else { f_tx->symlink[n / 2] = - usb2_alloc_symlink(src, "%s", buf); + usb2_alloc_symlink(devname); } - printf("Symlink: %s -> %s\n", buf, src); + + /* + * Initialize device private data - this is used to find the + * actual USB device itself. + */ + pd = malloc(sizeof(struct usb2_fs_privdata), M_USBDEV, M_WAITOK | M_ZERO); + pd->bus_index = device_get_unit(udev->bus->bdev); + pd->dev_index = udev->device_index; + pd->iface_index = iface_index; + pd->ep_addr = -1; /* not an endpoint */ + pd->fifo_index = f_tx->fifo_index; + pd->mode = FREAD|FWRITE; + + /* Now, create the device itself */ + f_sc->dev = make_dev(&usb2_devsw, 0, uid, gid, mode, + devname); + f_sc->dev->si_drv1 = pd; } DPRINTFN(2, "attached %p/%p\n", f_tx, f_rx); @@ -2345,6 +1780,12 @@ usb2_fifo_free_buffer(struct usb2_fifo *f) bzero(&f->used_q, sizeof(f->used_q)); } +static void +usb2_fifo_cleanup(void* ptr) +{ + free(ptr, M_USBDEV); +} + void usb2_fifo_detach(struct usb2_fifo_sc *f_sc) { @@ -2357,6 +1798,10 @@ usb2_fifo_detach(struct usb2_fifo_sc *f_sc) f_sc->fp[USB_FIFO_TX] = NULL; f_sc->fp[USB_FIFO_RX] = NULL; + if (f_sc->dev != NULL) { + destroy_dev_sched_cb(f_sc->dev, usb2_fifo_cleanup, f_sc->dev->si_drv1); + } + DPRINTFN(2, "detached %p\n", f_sc); } @@ -2642,24 +2087,20 @@ usb2_fifo_get_data_error(struct usb2_fifo *f) * Else: Pointer to symlink entry *------------------------------------------------------------------------*/ struct usb2_symlink * -usb2_alloc_symlink(const char *target, const char *fmt,...) +usb2_alloc_symlink(const char *target) { struct usb2_symlink *ps; - va_list ap; ps = malloc(sizeof(*ps), M_USBDEV, M_WAITOK); if (ps == NULL) { return (ps); } + /* XXX no longer needed */ + strlcpy(ps->src_path, target, sizeof(ps->src_path)); + ps->src_len = strlen(ps->src_path); strlcpy(ps->dst_path, target, sizeof(ps->dst_path)); ps->dst_len = strlen(ps->dst_path); - va_start(ap, fmt); - vsnrprintf(ps->src_path, - sizeof(ps->src_path), 32, fmt, ap); - va_end(ap); - ps->src_len = strlen(ps->src_path); - sx_xlock(&usb2_sym_lock); TAILQ_INSERT_TAIL(&usb2_sym_head, ps, sym_entry); sx_unlock(&usb2_sym_lock); @@ -2682,46 +2123,6 @@ usb2_free_symlink(struct usb2_symlink *ps) free(ps, M_USBDEV); } -/*------------------------------------------------------------------------* - * usb2_lookup_symlink - * - * Return value: - * Numerical device location - *------------------------------------------------------------------------*/ -uint32_t -usb2_lookup_symlink(const char *src_ptr, uint8_t src_len) -{ - enum { - USB_DNAME_LEN = sizeof(USB_DEVICE_NAME) - 1, - }; - struct usb2_symlink *ps; - uint32_t temp; - - sx_xlock(&usb2_sym_lock); - - TAILQ_FOREACH(ps, &usb2_sym_head, sym_entry) { - - if (src_len != ps->src_len) - continue; - - if (memcmp(ps->src_path, src_ptr, src_len)) - continue; - - if (USB_DNAME_LEN > ps->dst_len) - continue; - - if (memcmp(ps->dst_path, USB_DEVICE_NAME, USB_DNAME_LEN)) - continue; - - temp = usb2_path_convert(ps->dst_path + USB_DNAME_LEN); - sx_unlock(&usb2_sym_lock); - - return (temp); - } - sx_unlock(&usb2_sym_lock); - return (0 - 1); -} - /*------------------------------------------------------------------------* * usb2_read_symlink * diff --git a/sys/dev/usb/usb_dev.h b/sys/dev/usb/usb_dev.h index 6203572cfb32..ee00852a03b4 100644 --- a/sys/dev/usb/usb_dev.h +++ b/sys/dev/usb/usb_dev.h @@ -41,9 +41,9 @@ struct usb2_fifo; struct usb2_mbuf; -typedef int (usb2_fifo_open_t)(struct usb2_fifo *fifo, int fflags, struct thread *td); -typedef void (usb2_fifo_close_t)(struct usb2_fifo *fifo, int fflags, struct thread *td); -typedef int (usb2_fifo_ioctl_t)(struct usb2_fifo *fifo, u_long cmd, void *addr, int fflags, struct thread *td); +typedef int (usb2_fifo_open_t)(struct usb2_fifo *fifo, int fflags); +typedef void (usb2_fifo_close_t)(struct usb2_fifo *fifo, int fflags); +typedef int (usb2_fifo_ioctl_t)(struct usb2_fifo *fifo, u_long cmd, void *addr, int fflags); typedef void (usb2_fifo_cmd_t)(struct usb2_fifo *fifo); typedef void (usb2_fifo_filter_t)(struct usb2_fifo *fifo, struct usb2_mbuf *m); @@ -81,6 +81,39 @@ struct usb2_fifo_methods { const char *postfix[4]; }; +/* + * Private per-device information. + */ +struct usb2_cdev_privdata { + struct usb2_bus *bus; + struct usb2_device *udev; + struct usb2_interface *iface; + struct usb2_fifo *rxfifo; + struct usb2_fifo *txfifo; + int bus_index; /* bus index */ + int dev_index; /* device index */ + int iface_index; /* interface index */ + int ep_addr; /* endpoint address */ + uint8_t fifo_index; /* FIFO index */ + uint8_t is_read; /* location has read access */ + uint8_t is_write; /* location has write access */ + uint8_t is_uref; /* USB refcount decr. needed */ + uint8_t is_usbfs; /* USB-FS is active */ + int fflags; +}; + +struct usb2_fs_privdata { + int bus_index; + int dev_index; + int iface_index; + int ep_addr; + int mode; + int fifo_index; + struct cdev *cdev; + + LIST_ENTRY(usb2_fs_privdata) pd_next; +}; + /* * Most of the fields in the "usb2_fifo" structure are used by the * generic USB access layer. @@ -99,7 +132,7 @@ struct usb2_fifo { struct usb2_xfer *xfer[2]; struct usb2_xfer **fs_xfer; struct mtx *priv_mtx; /* client data */ - struct file *curr_file; /* set if FIFO is opened by a FILE */ + int opened; /* set if FIFO is opened by a FILE */ void *priv_sc0; /* client data */ void *priv_sc1; /* client data */ void *queue_data; @@ -126,8 +159,11 @@ struct usb2_fifo { struct usb2_fifo_sc { struct usb2_fifo *fp[2]; + struct cdev* dev; }; +extern struct cdevsw usb2_devsw; + int usb2_fifo_wait(struct usb2_fifo *fifo); void usb2_fifo_signal(struct usb2_fifo *fifo); int usb2_fifo_alloc_buffer(struct usb2_fifo *f, uint32_t bufsize, @@ -136,7 +172,7 @@ void usb2_fifo_free_buffer(struct usb2_fifo *f); int usb2_fifo_attach(struct usb2_device *udev, void *priv_sc, struct mtx *priv_mtx, struct usb2_fifo_methods *pm, struct usb2_fifo_sc *f_sc, uint16_t unit, uint16_t subunit, - uint8_t iface_index); + uint8_t iface_index, uid_t uid, gid_t gid, int mode); void usb2_fifo_detach(struct usb2_fifo_sc *f_sc); uint32_t usb2_fifo_put_bytes_max(struct usb2_fifo *fifo); void usb2_fifo_put_data(struct usb2_fifo *fifo, struct usb2_page_cache *pc, @@ -155,13 +191,9 @@ void usb2_fifo_get_data_error(struct usb2_fifo *fifo); uint8_t usb2_fifo_opened(struct usb2_fifo *fifo); void usb2_fifo_free(struct usb2_fifo *f); void usb2_fifo_reset(struct usb2_fifo *f); -int usb2_check_thread_perm(struct usb2_device *udev, struct thread *td, - int fflags, uint8_t iface_index, uint8_t ep_index); void usb2_fifo_wakeup(struct usb2_fifo *f); -struct usb2_symlink *usb2_alloc_symlink(const char *target, - const char *fmt,...); +struct usb2_symlink *usb2_alloc_symlink(const char *target); void usb2_free_symlink(struct usb2_symlink *ps); -uint32_t usb2_lookup_symlink(const char *src_ptr, uint8_t src_len); int usb2_read_symlink(uint8_t *user_ptr, uint32_t startentry, uint32_t user_len); diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c index 7746c010d0a8..9e11e8ea906d 100644 --- a/sys/dev/usb/usb_device.c +++ b/sys/dev/usb/usb_device.c @@ -74,6 +74,10 @@ static usb2_error_t usb2_fill_iface_data(struct usb2_device *, uint8_t, uint8_t); static void usb2_notify_addq(const char *type, struct usb2_device *); static void usb2_fifo_free_wrap(struct usb2_device *, uint8_t, uint8_t); +static struct cdev *usb2_make_dev(struct usb2_device *, int, int, int); +static void usb2_cdev_create(struct usb2_device *); +static void usb2_cdev_free(struct usb2_device *); +static void usb2_cdev_cleanup(void *); /* This variable is global to allow easy access to it: */ @@ -274,6 +278,7 @@ static void usb2_fill_pipe_data(struct usb2_device *udev, uint8_t iface_index, struct usb2_endpoint_descriptor *edesc, struct usb2_pipe *pipe) { + bzero(pipe, sizeof(*pipe)); (udev->bus->methods->pipe_init) (udev, edesc, pipe); @@ -416,6 +421,7 @@ usb2_fill_iface_data(struct usb2_device *udev, iface->idesc = id; iface->alt_index = alt_index; iface->parent_iface_index = USB_IFACE_INDEX_ANY; + iface->ep_in_mask = iface->ep_out_mask = 0; nendpt = id->bNumEndpoints; DPRINTFN(5, "found idesc nendpt=%d\n", nendpt); @@ -439,6 +445,14 @@ usb2_fill_iface_data(struct usb2_device *udev, found: ed = (void *)desc; + /* Fill in the endpoint bitmasks */ + if (ed->bEndpointAddress & UE_DIR_IN) + iface->ep_in_mask |= + 1 << UE_GET_ADDR(ed->bEndpointAddress); + else + iface->ep_out_mask |= + 1 << UE_GET_ADDR(ed->bEndpointAddress); + /* find a free pipe */ while (pipe != pipe_end) { if (pipe->edesc == NULL) { @@ -488,7 +502,6 @@ usb2_free_iface_data(struct usb2_device *udev) iface->idesc = NULL; iface->alt_index = 0; iface->parent_iface_index = USB_IFACE_INDEX_ANY; - iface->perm.mode = 0; /* disable permissions */ iface++; } @@ -543,6 +556,7 @@ usb2_set_config_index(struct usb2_device *udev, uint8_t index) usb2_fifo_free_wrap(udev, USB_IFACE_INDEX_ANY, 0); /* free all configuration data structures */ + usb2_cdev_free(udev); usb2_free_iface_data(udev); if (index == USB_UNCONFIG_INDEX) { @@ -652,10 +666,13 @@ usb2_set_config_index(struct usb2_device *udev, uint8_t index) goto done; } } + /* create device nodes for each endpoint */ + usb2_cdev_create(udev); done: DPRINTF("error=%s\n", usb2_errstr(err)); if (err) { + usb2_cdev_free(udev); usb2_free_iface_data(udev); } if (do_unlock) { @@ -713,6 +730,7 @@ usb2_set_alt_interface_index(struct usb2_device *udev, * Free all generic FIFOs for this interface, except control * endpoint FIFOs: */ + usb2_cdev_free(udev); usb2_fifo_free_wrap(udev, iface_index, 0); err = usb2_fill_iface_data(udev, iface_index, alt_index); @@ -722,6 +740,9 @@ usb2_set_alt_interface_index(struct usb2_device *udev, err = usb2_req_set_alt_interface_no(udev, NULL, iface_index, iface->idesc->bAlternateSetting); + /* create device nodes for each endpoint */ + usb2_cdev_create(udev); + done: if (do_unlock) { sx_unlock(udev->default_sx + 1); @@ -1354,6 +1375,8 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus, usb2_cv_init(udev->default_cv, "WCTRL"); usb2_cv_init(udev->default_cv + 1, "UGONE"); + LIST_INIT(&udev->pd_list); + /* initialise our mutex */ mtx_init(udev->default_mtx, "USB device mutex", NULL, MTX_DEF); @@ -1423,6 +1446,14 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus, /* set device index */ udev->device_index = device_index; + /* Create the control endpoint device */ + udev->default_dev = usb2_make_dev(udev, 0 , 0, FREAD|FWRITE); + /* Create a link from /dev/ugenX.X to the default endpoint */ + snprintf(udev->ugen_name, sizeof(udev->ugen_name), + USB_GENERIC_NAME "%u.%u", device_get_unit(bus->bdev), + device_index); + make_dev_alias(udev->default_dev, udev->ugen_name); + if (udev->flags.usb2_mode == USB_MODE_HOST) { err = usb2_req_set_address(udev, NULL, device_index); @@ -1673,21 +1704,9 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus, usb2_bus_port_set_device(bus, parent_hub ? parent_hub->hub->ports + port_index : NULL, udev, device_index); - /* make a symlink for UGEN */ - if (snprintf((char *)scratch_ptr, scratch_size, - USB_DEVICE_NAME "%u.%u.0.0", - device_get_unit(udev->bus->bdev), - udev->device_index)) { - /* ignore */ - } - udev->ugen_symlink = - usb2_alloc_symlink((char *)scratch_ptr, "ugen%u.%u", - device_get_unit(udev->bus->bdev), - udev->device_index); - - printf("ugen%u.%u: <%s> at %s\n", - device_get_unit(udev->bus->bdev), - udev->device_index, udev->manufacturer, + /* Link and announce the ugen device name */ + udev->ugen_symlink = usb2_alloc_symlink(udev->ugen_name); + printf("%s: <%s> at %s\n", udev->ugen_name, udev->manufacturer, device_get_nameunit(udev->bus->bdev)); usb2_notify_addq("+", udev); @@ -1700,6 +1719,100 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus, return (udev); } +static struct cdev * +usb2_make_dev(struct usb2_device *udev, int iface_index, int ep, int mode) +{ + struct usb2_fs_privdata* pd; + char devname[20]; + + /* Store information to locate ourselves again later */ + pd = malloc(sizeof(struct usb2_fs_privdata), M_USBDEV, + M_WAITOK | M_ZERO); + pd->bus_index = device_get_unit(udev->bus->bdev); + pd->dev_index = udev->device_index; + pd->iface_index = iface_index; + pd->ep_addr = ep; + pd->mode = mode; + + /* Now, create the device itself */ + snprintf(devname, sizeof(devname), "%u.%u.%u.%u", + pd->bus_index, pd->dev_index, + pd->iface_index, pd->ep_addr); + pd->cdev = make_dev(&usb2_devsw, 0, UID_ROOT, + GID_OPERATOR, 0600, USB_DEVICE_DIR "/%s", devname); + pd->cdev->si_drv1 = pd; + + return (pd->cdev); +} + +static void +usb2_cdev_create(struct usb2_device *udev) +{ + struct usb2_interface *iface; + struct usb2_fs_privdata* pd; + struct cdev *dev; + uint8_t niface; + int i, ep, mode, inmode, outmode; + + KASSERT(LIST_FIRST(&udev->pd_list) == NULL, ("stale cdev entries")); + + DPRINTFN(2, "Creating device nodes\n"); + + usb2_interface_count(udev, &niface); + if (niface == 0) + return; /* nothing to do */ + + if (usb2_get_mode(udev) == USB_MODE_DEVICE) { + inmode = FWRITE; + outmode = FREAD; + } else { /* USB_MODE_HOST */ + inmode = FREAD; + outmode = FWRITE; + } + + for (i = 0; i < niface; i++) { + iface = usb2_get_iface(udev, i); + if (iface == NULL) + break; + + /* Create all available endpoints except EP0 */ + for (ep = 1; ep < 16; ep++) { + mode = 0; + mode |= iface->ep_in_mask & (1 << ep) ? inmode : 0; + mode |= iface->ep_out_mask & (1 << ep) ? outmode : 0; + if (mode == 0) + continue; /* no IN or OUT endpoint */ + + dev = usb2_make_dev(udev, i , ep, mode); + pd = dev->si_drv1; + LIST_INSERT_HEAD(&udev->pd_list, pd, pd_next); + } + } +} + +static void +usb2_cdev_free(struct usb2_device *udev) +{ + struct usb2_fs_privdata* pd; + + DPRINTFN(2, "Freeing device nodes\n"); + + while ((pd = LIST_FIRST(&udev->pd_list)) != NULL) { + KASSERT(pd->cdev->si_drv1 == pd, ("privdata corrupt")); + KASSERT(pd->ep_addr > 0, ("freeing EP0")); + + destroy_dev_sched_cb(pd->cdev, usb2_cdev_cleanup, pd); + pd->cdev = NULL; + LIST_REMOVE(pd, pd_next); + } +} + +static void +usb2_cdev_cleanup(void* arg) +{ + free(arg, M_USBDEV); +} + /*------------------------------------------------------------------------* * usb2_free_device * @@ -1708,26 +1821,16 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus, void usb2_free_device(struct usb2_device *udev) { - struct usb2_bus *bus; + struct usb2_bus *bus = udev->bus;; - if (udev == NULL) { - /* already freed */ - return; - } DPRINTFN(4, "udev=%p port=%d\n", udev, udev->port_no); usb2_notify_addq("-", udev); - bus = udev->bus; + printf("%s: <%s> at %s (disconnected)\n", udev->ugen_name, + udev->manufacturer, device_get_nameunit(bus->bdev)); - printf("ugen%u.%u: <%s> at %s (disconnected)\n", - device_get_unit(bus->bdev), - udev->device_index, udev->manufacturer, - device_get_nameunit(bus->bdev)); - - /* - * Destroy UGEN symlink, if any - */ + /* Destroy UGEN symlink, if any */ if (udev->ugen_symlink) { usb2_free_symlink(udev->ugen_symlink); udev->ugen_symlink = NULL; @@ -1759,7 +1862,10 @@ usb2_free_device(struct usb2_device *udev) /* * Free all interface related data and FIFOs, if any. */ + usb2_cdev_free(udev); usb2_free_iface_data(udev); + destroy_dev_sched_cb(udev->default_dev, usb2_cdev_cleanup, + udev->default_dev->si_drv1); /* unsetup any leftover default USB transfers */ usb2_transfer_unsetup(udev->default_xfer, USB_DEFAULT_XFER_MAX); @@ -1783,6 +1889,7 @@ usb2_free_device(struct usb2_device *udev) usb2_cv_destroy(udev->default_cv + 1); mtx_destroy(udev->default_mtx); + KASSERT(LIST_FIRST(&udev->pd_list) == NULL, ("leaked cdev entries")); /* free device */ free(udev, M_USB); @@ -2112,7 +2219,7 @@ usb2_notify_addq(const char *type, struct usb2_device *udev) if (udev->parent_hub) { snprintf(data, 1024, "%s" - "ugen%u.%u " + "%s " "vendor=0x%04x " "product=0x%04x " "devclass=0x%02x " @@ -2121,22 +2228,20 @@ usb2_notify_addq(const char *type, struct usb2_device *udev) "at " "port=%u " "on " - "ugen%u.%u\n", + "%s\n", type, - device_get_unit(udev->bus->bdev), - udev->device_index, + udev->ugen_name, UGETW(udev->ddesc.idVendor), UGETW(udev->ddesc.idProduct), udev->ddesc.bDeviceClass, udev->ddesc.bDeviceSubClass, udev->serial, udev->port_no, - device_get_unit(udev->bus->bdev), - udev->parent_hub->device_index); + udev->parent_hub->ugen_name); } else { snprintf(data, 1024, "%s" - "ugen%u.%u " + "%s " "vendor=0x%04x " "product=0x%04x " "devclass=0x%02x " @@ -2146,8 +2251,7 @@ usb2_notify_addq(const char *type, struct usb2_device *udev) "on " "%s\n", type, - device_get_unit(udev->bus->bdev), - udev->device_index, + udev->ugen_name, UGETW(udev->ddesc.idVendor), UGETW(udev->ddesc.idProduct), udev->ddesc.bDeviceClass, diff --git a/sys/dev/usb/usb_device.h b/sys/dev/usb/usb_device.h index 4c296d456725..bca3a1d32822 100644 --- a/sys/dev/usb/usb_device.h +++ b/sys/dev/usb/usb_device.h @@ -61,11 +61,12 @@ struct usb2_pipe { * The following structure defines an USB interface. */ struct usb2_interface { - struct usb2_perm perm; /* interface permissions */ struct usb2_interface_descriptor *idesc; device_t subdev; uint8_t alt_index; uint8_t parent_iface_index; + uint16_t ep_in_mask; /* bitmask of IN endpoints */ + uint16_t ep_out_mask; /* bitmask of OUT endpoints */ }; /* @@ -101,12 +102,12 @@ struct usb2_power_save { struct usb2_device { struct usb2_clear_stall_msg cs_msg[2]; /* generic clear stall * messages */ - struct usb2_perm perm; struct sx default_sx[2]; struct mtx default_mtx[1]; struct cv default_cv[2]; struct usb2_interface ifaces[USB_IFACE_MAX]; struct usb2_pipe default_pipe; /* Control Endpoint 0 */ + struct cdev *default_dev; /* Control Endpoint 0 device node */ struct usb2_pipe pipes[USB_EP_MAX]; struct usb2_power_save pwr_save;/* power save data */ @@ -120,10 +121,16 @@ struct usb2_device { struct usb2_temp_data *usb2_template_ptr; struct usb2_pipe *pipe_curr; /* current clear stall pipe */ struct usb2_fifo *fifo[USB_FIFO_MAX]; + + char ugen_name[20]; /* name of ugenX.X device */ struct usb2_symlink *ugen_symlink; /* our generic symlink */ + LIST_HEAD(,usb2_fs_privdata) pd_list; + uint32_t plugtime; /* copy of "ticks" */ + uint16_t ep_rd_opened; /* bitmask of endpoints opened */ + uint16_t ep_wr_opened; /* from the device nodes. */ uint16_t refcount; #define USB_DEV_REF_MAX 0xffff diff --git a/sys/dev/usb/usb_generic.c b/sys/dev/usb/usb_generic.c index 75b985c2c52a..49b072c342e3 100644 --- a/sys/dev/usb/usb_generic.c +++ b/sys/dev/usb/usb_generic.c @@ -149,7 +149,7 @@ ugen_transfer_setup(struct usb2_fifo *f, } static int -ugen_open(struct usb2_fifo *f, int fflags, struct thread *td) +ugen_open(struct usb2_fifo *f, int fflags) { struct usb2_pipe *pipe = f->priv_sc0; struct usb2_endpoint_descriptor *ed = pipe->edesc; @@ -183,7 +183,7 @@ ugen_open(struct usb2_fifo *f, int fflags, struct thread *td) } static void -ugen_close(struct usb2_fifo *f, int fflags, struct thread *td) +ugen_close(struct usb2_fifo *f, int fflags) { DPRINTFN(6, "flag=0x%x\n", fflags); @@ -872,10 +872,6 @@ ugen_check_request(struct usb2_device *udev, struct usb2_device_request *req) if (pipe == NULL) { return (EINVAL); } - if (usb2_check_thread_perm(udev, curthread, FREAD | FWRITE, - pipe->iface_index, req->wIndex[0] & UE_ADDR)) { - return (EPERM); - } if ((req->bRequest == UR_CLEAR_FEATURE) && (UGETW(req->wValue) == UF_ENDPOINT_HALT)) { usb2_clear_data_toggle(udev, pipe); @@ -1367,8 +1363,7 @@ ugen_fifo_in_use(struct usb2_fifo *f, int fflags) } static int -ugen_ioctl(struct usb2_fifo *f, u_long cmd, void *addr, int fflags, - struct thread *td) +ugen_ioctl(struct usb2_fifo *f, u_long cmd, void *addr, int fflags) { struct usb2_config usb2_config[1]; struct usb2_device_request req; @@ -1458,11 +1453,6 @@ ugen_ioctl(struct usb2_fifo *f, u_long cmd, void *addr, int fflags, } iface_index = pipe->iface_index; - error = usb2_check_thread_perm(f->udev, curthread, fflags, - iface_index, u.popen->ep_no); - if (error) { - break; - } bzero(usb2_config, sizeof(usb2_config)); usb2_config[0].type = ed->bmAttributes & UE_XFERTYPE; @@ -1948,8 +1938,7 @@ ugen_iface_ioctl(struct usb2_fifo *f, u_long cmd, void *addr, int fflags) } static int -ugen_ioctl_post(struct usb2_fifo *f, u_long cmd, void *addr, int fflags, - struct thread *td) +ugen_ioctl_post(struct usb2_fifo *f, u_long cmd, void *addr, int fflags) { union { struct usb2_interface_descriptor *idesc; diff --git a/sys/dev/usb/usb_ioctl.h b/sys/dev/usb/usb_ioctl.h index 73f77964e110..81e2c466dec7 100644 --- a/sys/dev/usb/usb_ioctl.h +++ b/sys/dev/usb/usb_ioctl.h @@ -36,7 +36,8 @@ #include #include -#define USB_DEVICE_NAME "usb" +#define USB_DEVICE_NAME "usbctl" +#define USB_DEVICE_DIR "usb" #define USB_GENERIC_NAME "ugen" struct usb2_read_dir { @@ -180,18 +181,6 @@ struct usb2_fs_clear_stall_sync { uint8_t ep_index; }; -struct usb2_dev_perm { - /* Access information */ - uint32_t user_id; - uint32_t group_id; - uint16_t mode; - - /* Device location */ - uint16_t bus_index; - uint16_t dev_index; - uint16_t iface_index; -}; - struct usb2_gen_quirk { uint16_t index; /* Quirk Index */ uint16_t vid; /* Vendor ID */ @@ -248,14 +237,7 @@ struct usb2_gen_quirk { #define USB_IFACE_DRIVER_DETACH _IOW ('U', 125, int) #define USB_GET_PLUGTIME _IOR ('U', 126, uint32_t) #define USB_READ_DIR _IOW ('U', 127, struct usb2_read_dir) -#define USB_SET_ROOT_PERM _IOW ('U', 128, struct usb2_dev_perm) -#define USB_SET_BUS_PERM _IOW ('U', 129, struct usb2_dev_perm) -#define USB_SET_DEVICE_PERM _IOW ('U', 130, struct usb2_dev_perm) -#define USB_SET_IFACE_PERM _IOW ('U', 131, struct usb2_dev_perm) -#define USB_GET_ROOT_PERM _IOWR('U', 132, struct usb2_dev_perm) -#define USB_GET_BUS_PERM _IOWR('U', 133, struct usb2_dev_perm) -#define USB_GET_DEVICE_PERM _IOWR('U', 134, struct usb2_dev_perm) -#define USB_GET_IFACE_PERM _IOWR('U', 135, struct usb2_dev_perm) +/* 128 - 135 unused */ #define USB_SET_TX_FORCE_SHORT _IOW ('U', 136, int) #define USB_SET_TX_TIMEOUT _IOW ('U', 137, int) #define USB_GET_TX_FRAME_SIZE _IOR ('U', 138, int) diff --git a/sys/sys/param.h b/sys/sys/param.h index 3676c1e4c354..cb11672704fe 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -57,7 +57,7 @@ * is created, otherwise 1. */ #undef __FreeBSD_version -#define __FreeBSD_version 800065 /* Master, propagated to newvers */ +#define __FreeBSD_version 800066 /* Master, propagated to newvers */ #ifndef LOCORE #include diff --git a/usr.sbin/usbconfig/dump.c b/usr.sbin/usbconfig/dump.c index 01c55d29cf43..6a2fd026062c 100644 --- a/usr.sbin/usbconfig/dump.c +++ b/usr.sbin/usbconfig/dump.c @@ -262,107 +262,6 @@ dump_be_dev_quirks(struct libusb20_backend *pbe) return; } -void -dump_be_access(struct libusb20_backend *pbe) -{ - struct group *gr; - struct passwd *pw; - const char *owner; - const char *group; - uid_t uid; - gid_t gid; - mode_t mode; - - if (libusb20_be_get_owner(pbe, &uid, &gid)) { - err(1, "could not get owner"); - } - if (libusb20_be_get_perm(pbe, &mode)) { - err(1, "could not get permission"); - } - owner = (pw = getpwuid(uid)) ? pw->pw_name : "UNKNOWN"; - group = (gr = getgrgid(gid)) ? gr->gr_name : "UNKNOWN"; - - if (mode || 1) { - printf("Global Access: %s:%s 0%o\n", owner, group, mode); - } else { - printf("Global Access: \n"); - } - return; -} - -void -dump_device_access(struct libusb20_device *pdev, uint8_t iface) -{ - struct group *gr; - struct passwd *pw; - const char *owner; - const char *group; - uid_t uid; - gid_t gid; - mode_t mode; - - if (libusb20_dev_get_owner(pdev, &uid, &gid)) { - err(1, "could not get owner"); - } - if (libusb20_dev_get_perm(pdev, &mode)) { - err(1, "could not get permission"); - } - if (mode) { - owner = (pw = getpwuid(uid)) ? pw->pw_name : "UNKNOWN"; - group = (gr = getgrgid(gid)) ? gr->gr_name : "UNKNOWN"; - - printf(" " "Device Access: %s:%s 0%o\n", owner, group, mode); - - } else { - printf(" " "Device Access: \n"); - } - - if (iface == 0xFF) { - for (iface = 0; iface != 0xFF; iface++) { - if (dump_device_iface_access(pdev, iface)) { - break; - } - } - } else { - if (dump_device_iface_access(pdev, iface)) { - err(1, "could not get interface access info"); - } - } - return; -} - -int -dump_device_iface_access(struct libusb20_device *pdev, uint8_t iface) -{ - struct group *gr; - struct passwd *pw; - const char *owner; - const char *group; - uid_t uid; - gid_t gid; - mode_t mode; - int error; - - if ((error = libusb20_dev_get_iface_owner(pdev, iface, &uid, &gid))) { - return (error); - } - if ((error = libusb20_dev_get_iface_perm(pdev, iface, &mode))) { - return (error); - } - if (mode) { - - owner = (pw = getpwuid(uid)) ? pw->pw_name : "UNKNOWN"; - group = (gr = getgrgid(gid)) ? gr->gr_name : "UNKNOWN"; - - printf(" " "Interface %u Access: %s:%s 0%o\n", - iface, owner, group, mode); - } else { - printf(" " "Interface %u Access: \n", iface); - } - - return (0); -} - void dump_device_desc(struct libusb20_device *pdev) { diff --git a/usr.sbin/usbconfig/dump.h b/usr.sbin/usbconfig/dump.h index 87e9a4d4332d..7fafdfd34dbf 100644 --- a/usr.sbin/usbconfig/dump.h +++ b/usr.sbin/usbconfig/dump.h @@ -28,10 +28,7 @@ const char *dump_mode(uint8_t value); const char *dump_speed(uint8_t value); const char *dump_power_mode(uint8_t value); void dump_device_info(struct libusb20_device *pdev, uint8_t show_drv); -void dump_be_access(struct libusb20_backend *pbe); void dump_be_quirk_names(struct libusb20_backend *pbe); void dump_be_dev_quirks(struct libusb20_backend *pbe); -void dump_device_access(struct libusb20_device *pdev, uint8_t iface); -int dump_device_iface_access(struct libusb20_device *pdev, uint8_t iface); void dump_device_desc(struct libusb20_device *pdev); void dump_config(struct libusb20_device *pdev, uint8_t all_cfg); diff --git a/usr.sbin/usbconfig/usbconfig.c b/usr.sbin/usbconfig/usbconfig.c index 8a4ac1da4c3c..5227544ec840 100644 --- a/usr.sbin/usbconfig/usbconfig.c +++ b/usr.sbin/usbconfig/usbconfig.c @@ -64,8 +64,6 @@ struct options { uint8_t got_iface:1; uint8_t got_set_config:1; uint8_t got_set_alt:1; - uint8_t got_set_owner:1; - uint8_t got_set_perm:1; uint8_t got_set_template:1; uint8_t got_get_template:1; uint8_t got_suspend:1; @@ -80,7 +78,6 @@ struct options { uint8_t got_dump_curr_config:1; uint8_t got_dump_all_config:1; uint8_t got_dump_info:1; - uint8_t got_dump_access:1; uint8_t got_show_iface_driver:1; uint8_t got_remove_device_quirk:1; uint8_t got_add_device_quirk:1; @@ -100,8 +97,6 @@ enum { T_IFACE, T_SET_CONFIG, T_SET_ALT, - T_SET_OWNER, - T_SET_PERM, T_SET_TEMPLATE, T_GET_TEMPLATE, T_ADD_DEVICE_QUIRK, @@ -113,7 +108,6 @@ enum { T_DUMP_CURR_CONFIG_DESC, T_DUMP_ALL_CONFIG_DESC, T_DUMP_STRING, - T_DUMP_ACCESS, T_DUMP_INFO, T_SUSPEND, T_RESUME, @@ -133,8 +127,6 @@ static const struct token token[] = { {"-i", T_IFACE, 1}, {"set_config", T_SET_CONFIG, 1}, {"set_alt", T_SET_ALT, 1}, - {"set_owner", T_SET_OWNER, 1}, - {"set_perm", T_SET_PERM, 1}, {"set_template", T_SET_TEMPLATE, 1}, {"get_template", T_GET_TEMPLATE, 0}, {"add_dev_quirk_vplh", T_ADD_DEVICE_QUIRK, 5}, @@ -145,7 +137,6 @@ static const struct token token[] = { {"dump_curr_config_desc", T_DUMP_CURR_CONFIG_DESC, 0}, {"dump_all_config_desc", T_DUMP_ALL_CONFIG_DESC, 0}, {"dump_string", T_DUMP_STRING, 1}, - {"dump_access", T_DUMP_ACCESS, 0}, {"dump_info", T_DUMP_INFO, 0}, {"show_ifdrv", T_SHOW_IFACE_DRIVER, 0}, {"suspend", T_SUSPEND, 0}, @@ -238,43 +229,19 @@ num_id(const char *name, const char *type) return (val); } -static gid_t -a_gid(const char *s) +static int +get_int(const char *s) { - struct group *gr; - - if (*s == '\0') { - /* empty group ID */ - return ((gid_t)-1); - } - return ((gr = getgrnam(s)) ? gr->gr_gid : num_id(s, "group")); -} - -static uid_t -a_uid(const char *s) -{ - struct passwd *pw; - - if (*s == '\0') { - /* empty user ID */ - return ((uid_t)-1); - } - return ((pw = getpwnam(s)) ? pw->pw_uid : num_id(s, "user")); -} - -static mode_t -a_mode(const char *s) -{ - uint16_t val; + int val; char *ep; errno = 0; - val = strtoul(s, &ep, 8); + val = strtoul(s, &ep, 0); if (errno) { err(1, "%s", s); } if (*ep != '\0') { - errx(1, "illegal permissions: %s", s); + errx(1, "illegal number: %s", s); } return val; } @@ -288,8 +255,6 @@ usage(void) "commands:" "\n" " set_config " "\n" " set_alt " "\n" - " set_owner " "\n" - " set_perm " "\n" " set_template