static void uhid_close(struct usb_fifo *fifo, int fflags) { if (fflags & (FREAD | FWRITE)) { usb_fifo_free_buffer(fifo); } }
int ugen_fs_uninit(struct usb_fifo *f) { if (f->fs_xfer == NULL) { return (EINVAL); } usbd_transfer_unsetup(f->fs_xfer, f->fs_ep_max); free(f->fs_xfer, M_USB); f->fs_xfer = NULL; f->fs_ep_max = 0; f->fs_ep_ptr = NULL; f->flag_iscomplete = 0; usb_fifo_free_buffer(f); return (0); }
static void ugen_close(struct usb_fifo *f, int fflags) { DPRINTFN(6, "flag=0x%x\n", fflags); /* cleanup */ mtx_lock(f->priv_mtx); usbd_transfer_stop(f->xfer[0]); usbd_transfer_stop(f->xfer[1]); mtx_unlock(f->priv_mtx); usbd_transfer_unsetup(f->xfer, 2); usb_fifo_free_buffer(f); if (ugen_fs_uninit(f)) { /* ignore any errors - we are closing */ DPRINTFN(6, "no FIFOs\n"); } }
static int ugen_ioctl_post(struct usb_fifo *f, u_long cmd, void *addr, int fflags) { union { struct usb_interface_descriptor *idesc; struct usb_alt_interface *ai; struct usb_device_descriptor *ddesc; struct usb_config_descriptor *cdesc; struct usb_device_stats *stat; struct usb_fs_init *pinit; struct usb_fs_uninit *puninit; uint32_t *ptime; void *addr; int *pint; } u; struct usb_device_descriptor *dtemp; struct usb_config_descriptor *ctemp; struct usb_interface *iface; int error = 0; uint8_t n; u.addr = addr; DPRINTFN(6, "cmd=0x%08lx\n", cmd); switch (cmd) { case USB_DISCOVER: usb_needs_explore_all(); break; case USB_SETDEBUG: if (!(fflags & FWRITE)) { error = EPERM; break; } usb_debug = *(int *)addr; break; case USB_GET_CONFIG: *(int *)addr = f->udev->curr_config_index; break; case USB_SET_CONFIG: if (!(fflags & FWRITE)) { error = EPERM; break; } error = ugen_set_config(f, *(int *)addr); break; case USB_GET_ALTINTERFACE: iface = usbd_get_iface(f->udev, u.ai->uai_interface_index); if (iface && iface->idesc) { u.ai->uai_alt_index = iface->alt_index; } else { error = EINVAL; } break; case USB_SET_ALTINTERFACE: if (!(fflags & FWRITE)) { error = EPERM; break; } error = ugen_set_interface(f, u.ai->uai_interface_index, u.ai->uai_alt_index); break; case USB_GET_DEVICE_DESC: dtemp = usbd_get_device_descriptor(f->udev); if (!dtemp) { error = EIO; break; } *u.ddesc = *dtemp; break; case USB_GET_CONFIG_DESC: ctemp = usbd_get_config_descriptor(f->udev); if (!ctemp) { error = EIO; break; } *u.cdesc = *ctemp; break; case USB_GET_FULL_DESC: error = ugen_get_cdesc(f, addr); break; case USB_GET_STRING_DESC: error = ugen_get_sdesc(f, addr); break; case USB_GET_IFACE_DRIVER: error = ugen_get_iface_driver(f, addr); break; case USB_REQUEST: case USB_DO_REQUEST: if (!(fflags & FWRITE)) { error = EPERM; break; } error = ugen_do_request(f, addr); break; case USB_DEVICEINFO: case USB_GET_DEVICEINFO: error = usb_gen_fill_deviceinfo(f, addr); break; case USB_DEVICESTATS: for (n = 0; n != 4; n++) { u.stat->uds_requests_fail[n] = f->udev->bus->stats_err.uds_requests[n]; u.stat->uds_requests_ok[n] = f->udev->bus->stats_ok.uds_requests[n]; } break; case USB_DEVICEENUMERATE: error = ugen_re_enumerate(f); break; case USB_GET_PLUGTIME: *u.ptime = f->udev->plugtime; break; case USB_CLAIM_INTERFACE: case USB_RELEASE_INTERFACE: /* TODO */ break; case USB_IFACE_DRIVER_ACTIVE: /* TODO */ *u.pint = 0; break; case USB_IFACE_DRIVER_DETACH: /* TODO */ error = priv_check(curthread, PRIV_DRIVER); if (error) { break; } error = EINVAL; break; case USB_SET_POWER_MODE: error = ugen_set_power_mode(f, *u.pint); break; case USB_GET_POWER_MODE: *u.pint = ugen_get_power_mode(f); break; case USB_SET_PORT_ENABLE: error = ugen_do_port_feature(f, *u.pint, 1, UHF_PORT_ENABLE); break; case USB_SET_PORT_DISABLE: error = ugen_do_port_feature(f, *u.pint, 0, UHF_PORT_ENABLE); break; case USB_FS_INIT: /* verify input parameters */ if (u.pinit->pEndpoints == NULL) { error = EINVAL; break; } if (u.pinit->ep_index_max > 127) { error = EINVAL; break; } if (u.pinit->ep_index_max == 0) { error = EINVAL; break; } if (f->fs_xfer != NULL) { error = EBUSY; break; } if (f->dev_ep_index != 0) { error = EINVAL; break; } if (ugen_fifo_in_use(f, fflags)) { error = EBUSY; break; } error = usb_fifo_alloc_buffer(f, 1, u.pinit->ep_index_max); if (error) { break; } f->fs_xfer = malloc(sizeof(f->fs_xfer[0]) * u.pinit->ep_index_max, M_USB, M_WAITOK | M_ZERO); if (f->fs_xfer == NULL) { usb_fifo_free_buffer(f); error = ENOMEM; break; } f->fs_ep_max = u.pinit->ep_index_max; f->fs_ep_ptr = u.pinit->pEndpoints; break; case USB_FS_UNINIT: if (u.puninit->dummy != 0) { error = EINVAL; break; } error = ugen_fs_uninit(f); break; default: mtx_lock(f->priv_mtx); error = ugen_iface_ioctl(f, cmd, addr, fflags); mtx_unlock(f->priv_mtx); break; } DPRINTFN(6, "error=%d\n", error); return (error); }