diff --git a/sys/compat/linsysfs/linsysfs.h b/sys/compat/linsysfs/linsysfs.h --- a/sys/compat/linsysfs/linsysfs.h +++ b/sys/compat/linsysfs/linsysfs.h @@ -28,11 +28,23 @@ #ifndef _COMPAT_LINSYSFS_LINSYSFS_H_ #define _COMPAT_LINSYSFS_LINSYSFS_H_ +#include "usbdevs.h" +#include +#include +#include + MALLOC_DECLARE(M_LINSYSFS); extern struct pfs_node *net; +extern struct pfs_node *tty, *platform; + +struct pfs_node *linsysfs_find_uhub(device_t dev); +void linsysfs_usb_create_nodes(struct pfs_node *dir, struct usb_device *udev); void linsysfs_net_init(void); void linsysfs_net_uninit(void); +void linsysfs_tty_init(void); +void linsysfs_tty_uninit(void); + #endif /* _COMPAT_LINSYSFS_LINSYSFS_H_ */ diff --git a/sys/compat/linsysfs/linsysfs.c b/sys/compat/linsysfs/linsysfs.c --- a/sys/compat/linsysfs/linsysfs.c +++ b/sys/compat/linsysfs/linsysfs.c @@ -36,10 +36,22 @@ #include #include #include +#include +#include #include #include +#include "usbdevs.h" +#include +#include +#include +#include +#include +#include +#include +#include + #include #include @@ -53,10 +65,26 @@ char *name; }; -TAILQ_HEAD(,scsi_host_queue) scsi_host_q; +static TAILQ_HEAD(,scsi_host_queue) scsi_host_q = TAILQ_HEAD_INITIALIZER(scsi_host_q); static int host_number = 0; +/* + * Mapping of uhub devices to sysfs nodes. + * We shouldn't have to sync access, since they + * are created only in linsysfs_init() and + * thereafter only queried via linsysfs_find_uhub(). + */ +struct uhub_queue { + TAILQ_ENTRY(uhub_queue) uhub_next; + device_t dev; + struct pfs_node *dir; +}; + +static TAILQ_HEAD(,uhub_queue) uhub_q = TAILQ_HEAD_INITIALIZER(uhub_q); + +static int usb_number = 0; + static int atoi(const char *str) { @@ -251,6 +279,106 @@ return (0); } +struct pfs_node * +linsysfs_find_uhub(device_t dev) +{ + struct uhub_queue *uhub; + + TAILQ_FOREACH(uhub, &uhub_q, uhub_next) { + if (uhub->dev == dev) + return (uhub->dir); + } + + return (NULL); +} + +/* + * USB device fillers + */ +static int +linsysfs_usb_busnum(PFS_FILL_ARGS) +{ + struct usb_device *udev = pn->pn_data; + sbuf_printf(sb, "%d\n", device_get_unit(udev->bus->bdev)); + return (0); +} + +static int +linsysfs_usb_devnum(PFS_FILL_ARGS) +{ + /* + * With USB_HAVE_COMPAT_LINUX there is also udev->devnum, + * which is the same as device_get_unit(dev). + */ + struct usb_device *udev = pn->pn_data; + sbuf_printf(sb, "%d\n", udev->device_index); + return (0); +} + +static int +linsysfs_fill_uword(PFS_FILL_ARGS) +{ + uWord *word = pn->pn_data; + sbuf_printf(sb, "%04x\n", UGETW(*word)); + return (0); +} + +static int +linsysfs_fill_string(PFS_FILL_ARGS) +{ + const char *str = pn->pn_data; + sbuf_printf(sb, "%s\n", str); + return (0); +} + +void +linsysfs_usb_create_nodes(struct pfs_node *dir, struct usb_device *udev) +{ + struct pfs_node *cur_file; + + cur_file = pfs_create_file(dir, "idVendor", + &linsysfs_fill_uword, + NULL, NULL, NULL, PFS_RD); + cur_file->pn_data = (void*)&udev->ddesc.idVendor; + cur_file = pfs_create_file(dir, "idProduct", + &linsysfs_fill_uword, + NULL, NULL, NULL, PFS_RD); + cur_file->pn_data = (void*)&udev->ddesc.idProduct; + cur_file = pfs_create_file(dir, "bcdDevice", + &linsysfs_fill_uword, + NULL, NULL, NULL, PFS_RD); + cur_file->pn_data = (void*)&udev->ddesc.bcdDevice; + if (udev->bus != NULL) { + cur_file = pfs_create_file(dir, "busnum", + &linsysfs_usb_busnum, + NULL, NULL, NULL, PFS_RD); + cur_file->pn_data = (void*)udev; + } + cur_file = pfs_create_file(dir, "devnum", + &linsysfs_usb_devnum, + NULL, NULL, NULL, PFS_RD); + cur_file->pn_data = (void*)udev; + if (udev->product) { + cur_file = pfs_create_file(dir, "product", + &linsysfs_fill_string, + NULL, NULL, NULL, PFS_RD); + cur_file->pn_data = (void*)udev->product; + } + if (udev->manufacturer) { + cur_file = pfs_create_file(dir, "manufacturer", + &linsysfs_fill_string, + NULL, NULL, NULL, PFS_RD); + cur_file->pn_data = (void*)udev->manufacturer; + } + if (udev->serial) { + cur_file = pfs_create_file(dir, "serial", + &linsysfs_fill_string, + NULL, NULL, NULL, PFS_RD); + cur_file->pn_data = (void*)udev->serial; + } + /* FIXME: add some more nodes */ +} + #undef PCI_DEV #define PCI_DEV "pci" #define DRMN_DEV "drmn" @@ -329,6 +457,11 @@ /* libdrm just checks that the link ends in "/pci" */ cur_file->pn_data = "/sys/bus/pci"; +#if 0 + log(LOG_DEBUG, "baseclass=%d, subclass=%d\n", + dinfo->cfg.baseclass, dinfo->cfg.subclass); +#endif + if (dinfo->cfg.baseclass == PCIC_STORAGE) { /* DJA only make this if needed */ sprintf(host, "host%d", host_number++); @@ -362,6 +495,10 @@ } free(device, M_TEMP); free(host, M_TEMP); + } else { +#if 0 + log(LOG_DEBUG, "Unhandled parent devclass: %s\n", name); +#endif } } @@ -396,7 +533,30 @@ NULL, NULL, PFS_RD); cur_file->pn_data = (void*)dir; } + } else if (name != NULL && strcmp(name, "uhub") == 0) { + struct uhub_softc *sc = device_get_softc(dev); + if (sc != NULL && sc->sc_udev != NULL) { + char name[MAXPATHLEN]; + snprintf(name, sizeof(name), "usb%d", usb_number++); + sub_dir = pfs_create_dir(dir, name, + NULL, NULL, NULL, 0); + linsysfs_usb_create_nodes(sub_dir, sc->sc_udev); + + struct uhub_queue *uhub = malloc(sizeof(struct uhub_queue), + M_DEVBUF, M_NOWAIT); + uhub->dev = dev; + uhub->dir = sub_dir; + TAILQ_INSERT_TAIL(&uhub_q, uhub, uhub_next); + } + } else { +#if 0 + log(LOG_DEBUG, "Unhandled devclass: %s\n", name); +#endif } + } else { +#if 0 + log(LOG_DEBUG, "Device without parent: %s\n", device_get_name(dev)); +#endif } error = device_get_children(dev, &children, &nchildren); @@ -480,8 +640,6 @@ devclass_t devclass; device_t dev; - TAILQ_INIT(&scsi_host_q); - root = pi->pi_root; /* /sys/bus/... */ @@ -496,6 +654,9 @@ /* /sys/class/net/.. */ net = pfs_create_dir(class, "net", NULL, NULL, NULL, 0); + /* /sys/class/tty/... */ + tty = pfs_create_dir(class, "tty", NULL, NULL, NULL, 0); + /* /sys/dev/... */ devdir = pfs_create_dir(root, "dev", NULL, NULL, NULL, 0); chardev = pfs_create_dir(devdir, "char", NULL, NULL, NULL, 0); @@ -527,12 +688,16 @@ linsysfs_listcpus(cpu); + /* /sys/devices/platform */ + platform = pfs_create_dir(dir, "platform", NULL, NULL, NULL, 0); + /* /sys/kernel */ kernel = pfs_create_dir(root, "kernel", NULL, NULL, NULL, 0); /* /sys/kernel/debug, mountpoint for lindebugfs. */ pfs_create_dir(kernel, "debug", NULL, NULL, NULL, 0); linsysfs_net_init(); + linsysfs_tty_init(); return (0); } @@ -552,7 +717,15 @@ free(scsi_host, M_TEMP); } + struct uhub_queue *uhub, *uhub_tmp; + + TAILQ_FOREACH_SAFE(uhub, &uhub_q, uhub_next, uhub_tmp) { + TAILQ_REMOVE(&uhub_q, uhub, uhub_next); + free(uhub, M_TEMP); + } + linsysfs_net_uninit(); + linsysfs_tty_uninit(); return (0); } diff --git a/sys/compat/linsysfs/linsysfs_tty.c b/sys/compat/linsysfs/linsysfs_tty.c new file mode 100644 --- /dev/null +++ b/sys/compat/linsysfs/linsysfs_tty.c @@ -0,0 +1,435 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Robin Haberkorn + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +struct pfs_node *tty, *platform; +static eventhandler_tag tty_attach_tag, tty_detach_tag; + +static uint32_t tty_latch_count = 0; +static struct mtx tty_latch_mtx; +MTX_SYSINIT(tty_latch_mtx, &tty_latch_mtx, "lsftty", MTX_DEF); + +struct tty_nodes_queue { + TAILQ_ENTRY(tty_nodes_queue) tty_nodes_next; + device_t dev; + struct pfs_node *dir; + struct pfs_node *link; +}; +static TAILQ_HEAD(,tty_nodes_queue) tty_nodes_q = TAILQ_HEAD_INITIALIZER(tty_nodes_q); + +/* + * NOTE: "pts" devices are handled differently. + * In particular they don't expose their software context (softc), + * so it's not straight forward to get their /dev name. + */ +static const char *linsysfs_tty_devclasses[] = {"uart", "umodem", "uftdi", NULL}; + +/* + * FIXME: Why is this used instead of a plain mtx_lock() and mtx_unlock()? + */ +static void +linsysfs_tty_latch_hold(void) +{ + mtx_lock(&tty_latch_mtx); + if (tty_latch_count++ > 0) + mtx_sleep(&tty_latch_count, &tty_latch_mtx, PDROP, "lsftty", 0); + else + mtx_unlock(&tty_latch_mtx); +} + +static void +linsysfs_tty_latch_rele(void) +{ + mtx_lock(&tty_latch_mtx); + if (--tty_latch_count > 0) + wakeup_one(&tty_latch_count); + mtx_unlock(&tty_latch_mtx); +} + +/* + * Get the device name as used under /dev. + */ +static struct tty * +linsysfs_tty_get(device_t dev) +{ + const char *class_name = device_get_name(dev); + if (class_name == NULL) + return (NULL); + + if (strcmp(class_name, "uart") == 0) { + /* should be ttyuX */ + struct uart_softc *sc = device_get_softc(dev); + if (sc != NULL /*&& sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE*/) + return (sc->sc_u.u_tty.tp); + } else if (strcmp(class_name, "uftdi") == 0) { + /* should be ttyUX */ + struct uftdi_softc *sc = device_get_softc(dev); + return (sc->sc_ucom.sc_tty); + } else if (strcmp(class_name, "umodem") == 0) { + /* should be ttyUX */ + struct umodem_softc *sc = device_get_softc(dev); + return (sc->sc_ucom.sc_tty); +#if 0 + } else if (strcmp(class_name, "uftdi") == 0 || + strcmp(class_name, "umodem") == 0) { + /* + * NOTE: This depends on the layout of private softc structures. + * On the other hand it should work with drivers like u3g as well. + */ + struct ucom_super_softc *sc = device_get_softc(dev); + struct ucom_softc *uc = (struct ucom_softc *)(sc + 1); + return (uc->sc_tty); +#endif + } + + return (NULL); +} + +static int +linsysfs_tty_dev(PFS_FILL_ARGS) +{ + device_t dev = pn->pn_data; + + struct tty *tp = linsysfs_tty_get(dev); + if (tp == NULL) + return (0); + dev_t devn = tty_udev(tp); + + sbuf_printf(sb, "%d:%d\n", + linux_encode_major(devn), linux_encode_minor(devn)); + return (0); +} + +static int +linsysfs_tty_device(PFS_FILL_ARGS) +{ + struct pfs_node *device = pn->pn_data; + + /* + * Either /sys/platform/DRIVER or + * /sys/devices/pci.../X/usbX/X-Y/ttyUX. + */ + sbuf_printf(sb, "../../../%s", device->pn_name); + return (0); +} + +static int +linsysfs_tty_subsystem(PFS_FILL_ARGS) +{ + char buf[MAXPATHLEN] = ""; + + for (struct pfs_node *cur = pn->pn_data; + cur->pn_parent != NULL; cur = cur->pn_parent) + strcat(buf, "../"); + + sbuf_printf(sb, "%sclass/tty", buf); + return (0); +} + +static int +linsysfs_tty_uevent(PFS_FILL_ARGS) +{ + device_t dev = pn->pn_data; + + struct tty *tp = linsysfs_tty_get(dev); + if (tp == NULL) + return (0); + dev_t devn = tty_udev(tp); + + sbuf_printf(sb, "MAJOR=%d\nMINOR=%d\nDEVNAME=%s\n", + linux_encode_major(devn), linux_encode_minor(devn), tty_devname(tp)); + + return (0); +} + +static int +linsysfs_tty_class(PFS_FILL_ARGS) +{ + struct pfs_node *cur = pn->pn_data; + + char *temp, *path; + + temp = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); + path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); + path[0] = '\0'; + + do { + snprintf(temp, MAXPATHLEN, "%s/%s", cur->pn_name, path); + strlcpy(path, temp, MAXPATHLEN); + cur = cur->pn_parent; + } while (cur->pn_parent != NULL); + + path[strlen(path) - 1] = '\0'; /* remove extra slash */ + /* path will always be unter /sys/devices */ + sbuf_printf(sb, "../../%s", path); + + free(temp, M_TEMP); + free(path, M_TEMP); + return (0); +} + +static void +linsysfs_tty_add(device_t dev) +{ + struct tty_nodes_queue *nq; + struct pfs_node *cur_file; + struct pfs_node *per_dev_entry = NULL; + struct pfs_node *parent_entry = NULL; + struct pfs_node *ttydir, *tty_entry, *tty_link; + const char *class_name = device_get_name(dev); + + struct tty *tp = linsysfs_tty_get(dev); + if (tp == NULL) { +#if 0 + log(LOG_DEBUG, "Cannot get device name of %s\n", + device_get_nameunit(dev)); +#endif + return; + } + + device_t parent_dev = device_get_parent(dev); + if (parent_dev != NULL) { + struct pfs_node *uhub = linsysfs_find_uhub(parent_dev); + if (uhub != NULL) { + struct usb_device *udev = NULL; + + if (strcmp(class_name, "uftdi") == 0) { + struct uftdi_softc *sc = device_get_softc(dev); + udev = sc != NULL ? sc->sc_udev : NULL; + } else if (strcmp(class_name, "umodem") == 0) { + struct umodem_softc *sc = device_get_softc(dev); + udev = sc != NULL ? sc->sc_udev : NULL; + } + + if (udev != NULL && udev->bus != NULL) { + char name[MAXPATHLEN]; + snprintf(name, sizeof(name), "%d-%d", + device_get_unit(udev->bus->bdev), + udev->device_index); + /* /sys/devices/pci/X/X/usbX/X-Y */ + parent_entry = pfs_create_dir(uhub, name, + NULL, NULL, NULL, 0); + linsysfs_usb_create_nodes(parent_entry, udev); + + /* /sys/devices/pci/X/X/usbX/X-Y/ttyX */ + parent_entry = pfs_create_dir(parent_entry, tty_devname(tp), + NULL, NULL, NULL, 0); + /* FIXME: fill these nodes */ + + per_dev_entry = parent_entry; + } + } + } + + /* + * If the TTY node is not located under a per-USB node, + * we create a generic per-driver entry under /sys/platform. + * + * These cannot be initialized in linsysfs_tty_init(). + * 1.) There could be asynchronous events before they are created. + * 2.) Modules could be loaded only afterwards. + */ + if (parent_entry == NULL) + parent_entry = pfs_find_node(platform, class_name); + if (parent_entry == NULL) + /* /sys/devices/platform/CLASS */ + parent_entry = pfs_create_dir(platform, class_name, + NULL, NULL, NULL, 0); + MPASS(parent_entry != NULL); + + /* PARENT/tty */ + ttydir = pfs_find_node(parent_entry, "tty"); + if (ttydir == NULL) + ttydir = pfs_create_dir(parent_entry, "tty", + NULL, NULL, NULL, 0); + /* FIXME: Fill the rest of the platform structure */ + + tty_entry = pfs_find_node(ttydir, tty_devname(tp)); + if (tty_entry == NULL) { + /* PARENT/tty/ttyX */ + tty_entry = pfs_create_dir(ttydir, tty_devname(tp), + NULL, NULL, NULL, 0); + /* FIXME: Add "active"? */ + cur_file = pfs_create_file(tty_entry, "dev", &linsysfs_tty_dev, + NULL, NULL, NULL, PFS_RD); + cur_file->pn_data = (void *)dev; + cur_file = pfs_create_link(tty_entry, "device", &linsysfs_tty_device, + NULL, NULL, NULL, 0); + cur_file->pn_data = (void *)parent_entry; + /* FIXME: Fill power? */ + cur_file = pfs_create_dir(tty_entry, "power", + NULL, NULL, NULL, 0); + cur_file = pfs_create_link(tty_entry, "subsystem", &linsysfs_tty_subsystem, + NULL, NULL, NULL, 0); + cur_file->pn_data = (void *)tty_entry; + cur_file = pfs_create_file(tty_entry, "uevent", &linsysfs_tty_uevent, + NULL, NULL, NULL, PFS_RD); + cur_file->pn_data = (void *)dev; + if (per_dev_entry == NULL) + per_dev_entry = tty_entry; + + /* /sys/class/tty/ttyX -> PARENT/tty/ttyX */ + tty_link = pfs_create_link(tty, tty_devname(tp), &linsysfs_tty_class, + NULL, NULL, NULL, 0); + tty_link->pn_data = (void *)tty_entry; + } + /* + * There is a small time window between registering the device_attach + * eventhandler and creating the initial list of TTY devices. + * If a device is attached in the meantime, it might already + * exist in tty_nodes_q. + */ + TAILQ_FOREACH(nq, &tty_nodes_q, tty_nodes_next) { + if (nq->dev == dev) + return; + } + MPASS(tty_link != NULL && per_dev_entry != NULL); + nq = malloc(sizeof(*nq), M_LINSYSFS, M_WAITOK); + nq->dev = dev; + nq->dir = per_dev_entry; + nq->link = tty_link; + TAILQ_INSERT_TAIL(&tty_nodes_q, nq, tty_nodes_next); +} + +static void +linsysfs_tty_delete(device_t dev) +{ + struct tty_nodes_queue *nq, *nq_tmp; + + TAILQ_FOREACH_SAFE(nq, &tty_nodes_q, tty_nodes_next, nq_tmp) { + if (nq->dev == dev) { + TAILQ_REMOVE(&tty_nodes_q, nq, tty_nodes_next); + pfs_destroy(nq->link); + pfs_destroy(nq->dir); + free(nq, M_LINSYSFS); + break; + } + } +} + +static void +linsysfs_tty_attach(void *arg __unused, device_t dev) +{ + linsysfs_tty_latch_hold(); + linsysfs_tty_add(dev); + linsysfs_tty_latch_rele(); +} + +static void +linsysfs_tty_detach(void *arg __unused, device_t dev) +{ + linsysfs_tty_latch_hold(); + linsysfs_tty_delete(dev); + linsysfs_tty_latch_rele(); +} + +void +linsysfs_tty_init(void) +{ + MPASS(tty != NULL && platform != NULL); + + tty_attach_tag = EVENTHANDLER_REGISTER(device_attach, + linsysfs_tty_attach, NULL, EVENTHANDLER_PRI_ANY); + tty_detach_tag = EVENTHANDLER_REGISTER(device_detach, + linsysfs_tty_detach, NULL, EVENTHANDLER_PRI_ANY); + + /* + * If a TTY device is attached only now, it might end + * up in tty_nodes_q and the event might still be dispatched. + */ + for (const char **p = linsysfs_tty_devclasses; *p != NULL; p++) { + device_t *devices; + int devices_count; + devclass_t class = devclass_find(*p); + if (class == NULL || + devclass_get_devices(class, &devices, &devices_count) != 0) + continue; + + for (int i = 0; i < devices_count; i++) + linsysfs_tty_attach(NULL, devices[i]); + + free(devices, M_TEMP); + } +} + +void +linsysfs_tty_uninit(void) +{ + struct tty_nodes_queue *nq, *nq_tmp; + + EVENTHANDLER_DEREGISTER(device_attach, tty_attach_tag); + EVENTHANDLER_DEREGISTER(device_detach, tty_detach_tag); + + linsysfs_tty_latch_hold(); + TAILQ_FOREACH_SAFE(nq, &tty_nodes_q, tty_nodes_next, nq_tmp) { + TAILQ_REMOVE(&tty_nodes_q, nq, tty_nodes_next); + free(nq, M_LINSYSFS); + } + linsysfs_tty_latch_rele(); +} diff --git a/sys/dev/usb/serial/uftdi.h b/sys/dev/usb/serial/uftdi.h new file mode 100644 --- /dev/null +++ b/sys/dev/usb/serial/uftdi.h @@ -0,0 +1,62 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _UFTDI_H_ +#define _UFTDI_H_ + +#include +#include + +enum { + UFTDI_BULK_DT_WR, + UFTDI_BULK_DT_RD, + UFTDI_N_TRANSFER, +}; + +struct uftdi_softc { + struct ucom_super_softc sc_super_ucom; + struct ucom_softc sc_ucom; + + struct usb_device *sc_udev; + struct usb_xfer *sc_xfer[UFTDI_N_TRANSFER]; + device_t sc_dev; + struct mtx sc_mtx; + + uint32_t sc_unit; + + uint16_t sc_last_lcr; + uint16_t sc_bcdDevice; + + uint8_t sc_devtype; + uint8_t sc_devflags; + uint8_t sc_hdrlen; + uint8_t sc_msr; + uint8_t sc_lsr; + uint8_t sc_bitmode; +}; + +#endif /* _UFTDI_H_ */ diff --git a/sys/dev/usb/serial/uftdi.c b/sys/dev/usb/serial/uftdi.c --- a/sys/dev/usb/serial/uftdi.c +++ b/sys/dev/usb/serial/uftdi.c @@ -80,6 +80,7 @@ #include #include +#include #include static SYSCTL_NODE(_hw_usb, OID_AUTO, uftdi, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, @@ -122,12 +123,6 @@ #define UFTDI_OBUFSIZE 2048 #define UFTDI_OPKTSIZE 64 -enum { - UFTDI_BULK_DT_WR, - UFTDI_BULK_DT_RD, - UFTDI_N_TRANSFER, -}; - enum { DEVT_SIO, DEVT_232A, @@ -143,28 +138,6 @@ #define DEVF_BAUDBITS_HINDEX 0x01 /* Baud bits in high byte of index. */ #define DEVF_BAUDCLK_12M 0X02 /* Base baud clock is 12MHz. */ -struct uftdi_softc { - struct ucom_super_softc sc_super_ucom; - struct ucom_softc sc_ucom; - - struct usb_device *sc_udev; - struct usb_xfer *sc_xfer[UFTDI_N_TRANSFER]; - device_t sc_dev; - struct mtx sc_mtx; - - uint32_t sc_unit; - - uint16_t sc_last_lcr; - uint16_t sc_bcdDevice; - - uint8_t sc_devtype; - uint8_t sc_devflags; - uint8_t sc_hdrlen; - uint8_t sc_msr; - uint8_t sc_lsr; - uint8_t sc_bitmode; -}; - struct uftdi_param_config { uint16_t baud_lobits; uint16_t baud_hibits; diff --git a/sys/dev/usb/serial/umodem.h b/sys/dev/usb/serial/umodem.h new file mode 100644 --- /dev/null +++ b/sys/dev/usb/serial/umodem.h @@ -0,0 +1,93 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2003 M. Warner Losh + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Lennart Augustsson (lennart@augustsson.net) at + * Carlstedt Research & Technology. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _UMODEM_H_ +#define _UMODEM_H_ + +#include +#include + +enum { + UMODEM_BULK_WR, + UMODEM_BULK_RD, + UMODEM_INTR_WR, + UMODEM_INTR_RD, + UMODEM_N_TRANSFER, +}; + +struct umodem_softc { + struct ucom_super_softc sc_super_ucom; + struct ucom_softc sc_ucom; + + struct usb_xfer *sc_xfer[UMODEM_N_TRANSFER]; + struct usb_device *sc_udev; + struct mtx sc_mtx; + + uint16_t sc_line; + + uint8_t sc_lsr; /* local status register */ + uint8_t sc_msr; /* modem status register */ + uint8_t sc_ctrl_iface_no; + uint8_t sc_data_iface_no; + uint8_t sc_iface_index[2]; + uint8_t sc_cm_over_data; + uint8_t sc_cm_cap; /* CM capabilities */ + uint8_t sc_acm_cap; /* ACM capabilities */ + uint8_t sc_line_coding[32]; /* used in USB device mode */ + uint8_t sc_abstract_state[32]; /* used in USB device mode */ +}; + +#endif /* _UMODEM_H_ */ diff --git a/sys/dev/usb/serial/umodem.c b/sys/dev/usb/serial/umodem.c --- a/sys/dev/usb/serial/umodem.c +++ b/sys/dev/usb/serial/umodem.c @@ -107,6 +107,7 @@ #include #include +#include #ifdef USB_DEBUG static int umodem_debug = 0; @@ -162,38 +163,8 @@ */ #define UMODEM_BUF_SIZE 1024 -enum { - UMODEM_BULK_WR, - UMODEM_BULK_RD, - UMODEM_INTR_WR, - UMODEM_INTR_RD, - UMODEM_N_TRANSFER, -}; - #define UMODEM_MODVER 1 /* module version */ -struct umodem_softc { - struct ucom_super_softc sc_super_ucom; - struct ucom_softc sc_ucom; - - struct usb_xfer *sc_xfer[UMODEM_N_TRANSFER]; - struct usb_device *sc_udev; - struct mtx sc_mtx; - - uint16_t sc_line; - - uint8_t sc_lsr; /* local status register */ - uint8_t sc_msr; /* modem status register */ - uint8_t sc_ctrl_iface_no; - uint8_t sc_data_iface_no; - uint8_t sc_iface_index[2]; - uint8_t sc_cm_over_data; - uint8_t sc_cm_cap; /* CM capabilities */ - uint8_t sc_acm_cap; /* ACM capabilities */ - uint8_t sc_line_coding[32]; /* used in USB device mode */ - uint8_t sc_abstract_state[32]; /* used in USB device mode */ -}; - static device_probe_t umodem_probe; static device_attach_t umodem_attach; static device_detach_t umodem_detach; diff --git a/sys/dev/usb/usb_hub.h b/sys/dev/usb/usb_hub.h --- a/sys/dev/usb/usb_hub.h +++ b/sys/dev/usb/usb_hub.h @@ -62,6 +62,38 @@ #endif }; +enum { + UHUB_INTR_TRANSFER, +#if USB_HAVE_TT_SUPPORT + UHUB_RESET_TT_TRANSFER, +#endif + UHUB_N_TRANSFER, +}; + +struct uhub_current_state { + uint16_t port_change; + uint16_t port_status; +}; + +struct uhub_softc { + struct uhub_current_state sc_st; /* current state */ +#if (USB_HAVE_FIXED_PORT != 0) + struct usb_hub sc_hub; +#endif + device_t sc_dev; /* base device */ + struct mtx sc_mtx; /* our mutex */ + struct usb_device *sc_udev; /* USB device */ + struct usb_xfer *sc_xfer[UHUB_N_TRANSFER]; /* interrupt xfer */ +#if USB_HAVE_DISABLE_ENUM + int sc_disable_enumeration; + int sc_disable_port_power; +#endif + uint8_t sc_usb_port_errors; /* error counter */ +#define UHUB_USB_PORT_ERRORS_MAX 4 + uint8_t sc_flags; +#define UHUB_FLAG_DID_EXPLORE 0x01 +}; + /* function prototypes */ void usb_hs_bandwidth_alloc(struct usb_xfer *xfer); diff --git a/sys/dev/usb/usb_hub_private.h b/sys/dev/usb/usb_hub_private.h --- a/sys/dev/usb/usb_hub_private.h +++ b/sys/dev/usb/usb_hub_private.h @@ -35,37 +35,6 @@ #define USB_HUB_PRIVATE_H_ #define UHUB_INTR_INTERVAL 250 /* ms */ -enum { - UHUB_INTR_TRANSFER, -#if USB_HAVE_TT_SUPPORT - UHUB_RESET_TT_TRANSFER, -#endif - UHUB_N_TRANSFER, -}; - -struct uhub_current_state { - uint16_t port_change; - uint16_t port_status; -}; - -struct uhub_softc { - struct uhub_current_state sc_st; /* current state */ -#if (USB_HAVE_FIXED_PORT != 0) - struct usb_hub sc_hub; -#endif - device_t sc_dev; /* base device */ - struct mtx sc_mtx; /* our mutex */ - struct usb_device *sc_udev; /* USB device */ - struct usb_xfer *sc_xfer[UHUB_N_TRANSFER]; /* interrupt xfer */ -#if USB_HAVE_DISABLE_ENUM - int sc_disable_enumeration; - int sc_disable_port_power; -#endif - uint8_t sc_usb_port_errors; /* error counter */ -#define UHUB_USB_PORT_ERRORS_MAX 4 - uint8_t sc_flags; -#define UHUB_FLAG_DID_EXPLORE 0x01 -}; struct hub_result { struct usb_device *udev; uint8_t portno; diff --git a/sys/modules/linsysfs/Makefile b/sys/modules/linsysfs/Makefile --- a/sys/modules/linsysfs/Makefile +++ b/sys/modules/linsysfs/Makefile @@ -4,7 +4,7 @@ KMOD= linsysfs SRCS= vnode_if.h \ device_if.h bus_if.h pci_if.h \ - linsysfs.c linsysfs_net.c + linsysfs.c linsysfs_net.c linsysfs_tty.c .if !defined(KERNBUILDDIR) .warning Building Linuxulator outside of a kernel does not make sense