devctl.c revision 306533
1/*- 2 * Copyright (c) 2014 John Baldwin <jhb@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: stable/11/lib/libdevctl/devctl.c 306533 2016-09-30 22:05:47Z jhb $"); 29 30#include <sys/types.h> 31#include <sys/bus.h> 32#include <errno.h> 33#include <fcntl.h> 34#include <string.h> 35#include "devctl.h" 36 37static int 38devctl_request(u_long cmd, struct devreq *req) 39{ 40 static int devctl2_fd = -1; 41 42 if (devctl2_fd == -1) { 43 devctl2_fd = open("/dev/devctl2", O_RDONLY); 44 if (devctl2_fd == -1) 45 return (-1); 46 } 47 return (ioctl(devctl2_fd, cmd, req)); 48} 49 50static int 51devctl_simple_request(u_long cmd, const char *name, int flags) 52{ 53 struct devreq req; 54 55 memset(&req, 0, sizeof(req)); 56 if (strlcpy(req.dr_name, name, sizeof(req.dr_name)) >= 57 sizeof(req.dr_name)) { 58 errno = EINVAL; 59 return (-1); 60 } 61 req.dr_flags = flags; 62 return (devctl_request(cmd, &req)); 63} 64 65int 66devctl_attach(const char *device) 67{ 68 69 return (devctl_simple_request(DEV_ATTACH, device, 0)); 70} 71 72int 73devctl_detach(const char *device, bool force) 74{ 75 76 return (devctl_simple_request(DEV_DETACH, device, force ? 77 DEVF_FORCE_DETACH : 0)); 78} 79 80int 81devctl_enable(const char *device) 82{ 83 84 return (devctl_simple_request(DEV_ENABLE, device, 0)); 85} 86 87int 88devctl_disable(const char *device, bool force_detach) 89{ 90 91 return (devctl_simple_request(DEV_DISABLE, device, force_detach ? 92 DEVF_FORCE_DETACH : 0)); 93} 94 95int 96devctl_suspend(const char *device) 97{ 98 99 return (devctl_simple_request(DEV_SUSPEND, device, 0)); 100} 101 102int 103devctl_resume(const char *device) 104{ 105 106 return (devctl_simple_request(DEV_RESUME, device, 0)); 107} 108 109int 110devctl_set_driver(const char *device, const char *driver, bool force) 111{ 112 struct devreq req; 113 114 memset(&req, 0, sizeof(req)); 115 if (strlcpy(req.dr_name, device, sizeof(req.dr_name)) >= 116 sizeof(req.dr_name)) { 117 errno = EINVAL; 118 return (-1); 119 } 120 req.dr_data = __DECONST(char *, driver); 121 if (force) 122 req.dr_flags |= DEVF_SET_DRIVER_DETACH; 123 return (devctl_request(DEV_SET_DRIVER, &req)); 124} 125 126int 127devctl_clear_driver(const char *device, bool force) 128{ 129 130 return (devctl_simple_request(DEV_CLEAR_DRIVER, device, force ? 131 DEVF_CLEAR_DRIVER_DETACH : 0)); 132} 133 134int 135devctl_rescan(const char *device) 136{ 137 138 return (devctl_simple_request(DEV_RESCAN, device, 0)); 139} 140 141int 142devctl_delete(const char *device, bool force) 143{ 144 145 return (devctl_simple_request(DEV_DELETE, device, force ? 146 DEVF_FORCE_DELETE : 0)); 147} 148