1/* 2 * driver.c - device id matching, driver model, etc. 3 * 4 * Copyright 2002 Adam Belay <ambx1@neo.rr.com> 5 */ 6 7#include <linux/string.h> 8#include <linux/list.h> 9#include <linux/module.h> 10#include <linux/ctype.h> 11#include <linux/slab.h> 12#include <linux/pnp.h> 13#include "base.h" 14 15static int compare_func(const char *ida, const char *idb) 16{ 17 int i; 18 19 /* we only need to compare the last 4 chars */ 20 for (i = 3; i < 7; i++) { 21 if (ida[i] != 'X' && 22 idb[i] != 'X' && toupper(ida[i]) != toupper(idb[i])) 23 return 0; 24 } 25 return 1; 26} 27 28int compare_pnp_id(struct pnp_id *pos, const char *id) 29{ 30 if (!pos || !id || (strlen(id) != 7)) 31 return 0; 32 if (memcmp(id, "ANYDEVS", 7) == 0) 33 return 1; 34 while (pos) { 35 if (memcmp(pos->id, id, 3) == 0) 36 if (compare_func(pos->id, id) == 1) 37 return 1; 38 pos = pos->next; 39 } 40 return 0; 41} 42 43static const struct pnp_device_id *match_device(struct pnp_driver *drv, 44 struct pnp_dev *dev) 45{ 46 const struct pnp_device_id *drv_id = drv->id_table; 47 48 if (!drv_id) 49 return NULL; 50 51 while (*drv_id->id) { 52 if (compare_pnp_id(dev->id, drv_id->id)) 53 return drv_id; 54 drv_id++; 55 } 56 return NULL; 57} 58 59int pnp_device_attach(struct pnp_dev *pnp_dev) 60{ 61 mutex_lock(&pnp_lock); 62 if (pnp_dev->status != PNP_READY) { 63 mutex_unlock(&pnp_lock); 64 return -EBUSY; 65 } 66 pnp_dev->status = PNP_ATTACHED; 67 mutex_unlock(&pnp_lock); 68 return 0; 69} 70 71void pnp_device_detach(struct pnp_dev *pnp_dev) 72{ 73 mutex_lock(&pnp_lock); 74 if (pnp_dev->status == PNP_ATTACHED) 75 pnp_dev->status = PNP_READY; 76 mutex_unlock(&pnp_lock); 77 pnp_disable_dev(pnp_dev); 78} 79 80static int pnp_device_probe(struct device *dev) 81{ 82 int error; 83 struct pnp_driver *pnp_drv; 84 struct pnp_dev *pnp_dev; 85 const struct pnp_device_id *dev_id = NULL; 86 pnp_dev = to_pnp_dev(dev); 87 pnp_drv = to_pnp_driver(dev->driver); 88 89 error = pnp_device_attach(pnp_dev); 90 if (error < 0) 91 return error; 92 93 if (pnp_dev->active == 0) { 94 if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) { 95 error = pnp_activate_dev(pnp_dev); 96 if (error < 0) 97 return error; 98 } 99 } else if ((pnp_drv->flags & PNP_DRIVER_RES_DISABLE) 100 == PNP_DRIVER_RES_DISABLE) { 101 error = pnp_disable_dev(pnp_dev); 102 if (error < 0) 103 return error; 104 } 105 error = 0; 106 if (pnp_drv->probe) { 107 dev_id = match_device(pnp_drv, pnp_dev); 108 if (dev_id != NULL) 109 error = pnp_drv->probe(pnp_dev, dev_id); 110 } 111 if (error >= 0) { 112 pnp_dev->driver = pnp_drv; 113 error = 0; 114 } else 115 goto fail; 116 117 return error; 118 119fail: 120 pnp_device_detach(pnp_dev); 121 return error; 122} 123 124static int pnp_device_remove(struct device *dev) 125{ 126 struct pnp_dev *pnp_dev = to_pnp_dev(dev); 127 struct pnp_driver *drv = pnp_dev->driver; 128 129 if (drv) { 130 if (drv->remove) 131 drv->remove(pnp_dev); 132 pnp_dev->driver = NULL; 133 } 134 pnp_device_detach(pnp_dev); 135 return 0; 136} 137 138static void pnp_device_shutdown(struct device *dev) 139{ 140 struct pnp_dev *pnp_dev = to_pnp_dev(dev); 141 struct pnp_driver *drv = pnp_dev->driver; 142 143 if (drv && drv->shutdown) 144 drv->shutdown(pnp_dev); 145} 146 147static int pnp_bus_match(struct device *dev, struct device_driver *drv) 148{ 149 struct pnp_dev *pnp_dev = to_pnp_dev(dev); 150 struct pnp_driver *pnp_drv = to_pnp_driver(drv); 151 152 if (match_device(pnp_drv, pnp_dev) == NULL) 153 return 0; 154 return 1; 155} 156 157static int __pnp_bus_suspend(struct device *dev, pm_message_t state) 158{ 159 struct pnp_dev *pnp_dev = to_pnp_dev(dev); 160 struct pnp_driver *pnp_drv = pnp_dev->driver; 161 int error; 162 163 if (!pnp_drv) 164 return 0; 165 166 if (pnp_drv->driver.pm && pnp_drv->driver.pm->suspend) { 167 error = pnp_drv->driver.pm->suspend(dev); 168 suspend_report_result(pnp_drv->driver.pm->suspend, error); 169 if (error) 170 return error; 171 } 172 173 if (pnp_drv->suspend) { 174 error = pnp_drv->suspend(pnp_dev, state); 175 if (error) 176 return error; 177 } 178 179 if (pnp_can_disable(pnp_dev)) { 180 error = pnp_stop_dev(pnp_dev); 181 if (error) 182 return error; 183 } 184 185 if (pnp_can_suspend(pnp_dev)) 186 pnp_dev->protocol->suspend(pnp_dev, state); 187 return 0; 188} 189 190static int pnp_bus_suspend(struct device *dev) 191{ 192 return __pnp_bus_suspend(dev, PMSG_SUSPEND); 193} 194 195static int pnp_bus_freeze(struct device *dev) 196{ 197 return __pnp_bus_suspend(dev, PMSG_FREEZE); 198} 199 200static int pnp_bus_poweroff(struct device *dev) 201{ 202 return __pnp_bus_suspend(dev, PMSG_HIBERNATE); 203} 204 205static int pnp_bus_resume(struct device *dev) 206{ 207 struct pnp_dev *pnp_dev = to_pnp_dev(dev); 208 struct pnp_driver *pnp_drv = pnp_dev->driver; 209 int error; 210 211 if (!pnp_drv) 212 return 0; 213 214 if (pnp_dev->protocol->resume) { 215 error = pnp_dev->protocol->resume(pnp_dev); 216 if (error) 217 return error; 218 } 219 220 if (pnp_can_write(pnp_dev)) { 221 error = pnp_start_dev(pnp_dev); 222 if (error) 223 return error; 224 } 225 226 if (pnp_drv->driver.pm && pnp_drv->driver.pm->resume) { 227 error = pnp_drv->driver.pm->resume(dev); 228 if (error) 229 return error; 230 } 231 232 if (pnp_drv->resume) { 233 error = pnp_drv->resume(pnp_dev); 234 if (error) 235 return error; 236 } 237 238 return 0; 239} 240 241static const struct dev_pm_ops pnp_bus_dev_pm_ops = { 242 /* Suspend callbacks */ 243 .suspend = pnp_bus_suspend, 244 .resume = pnp_bus_resume, 245 /* Hibernate callbacks */ 246 .freeze = pnp_bus_freeze, 247 .thaw = pnp_bus_resume, 248 .poweroff = pnp_bus_poweroff, 249 .restore = pnp_bus_resume, 250}; 251 252struct bus_type pnp_bus_type = { 253 .name = "pnp", 254 .match = pnp_bus_match, 255 .probe = pnp_device_probe, 256 .remove = pnp_device_remove, 257 .shutdown = pnp_device_shutdown, 258 .pm = &pnp_bus_dev_pm_ops, 259 .dev_groups = pnp_dev_groups, 260}; 261 262int pnp_register_driver(struct pnp_driver *drv) 263{ 264 drv->driver.name = drv->name; 265 drv->driver.bus = &pnp_bus_type; 266 267 return driver_register(&drv->driver); 268} 269 270void pnp_unregister_driver(struct pnp_driver *drv) 271{ 272 driver_unregister(&drv->driver); 273} 274 275/** 276 * pnp_add_id - adds an EISA id to the specified device 277 * @dev: pointer to the desired device 278 * @id: pointer to an EISA id string 279 */ 280struct pnp_id *pnp_add_id(struct pnp_dev *dev, const char *id) 281{ 282 struct pnp_id *dev_id, *ptr; 283 284 dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); 285 if (!dev_id) 286 return NULL; 287 288 dev_id->id[0] = id[0]; 289 dev_id->id[1] = id[1]; 290 dev_id->id[2] = id[2]; 291 dev_id->id[3] = tolower(id[3]); 292 dev_id->id[4] = tolower(id[4]); 293 dev_id->id[5] = tolower(id[5]); 294 dev_id->id[6] = tolower(id[6]); 295 dev_id->id[7] = '\0'; 296 297 dev_id->next = NULL; 298 ptr = dev->id; 299 while (ptr && ptr->next) 300 ptr = ptr->next; 301 if (ptr) 302 ptr->next = dev_id; 303 else 304 dev->id = dev_id; 305 306 return dev_id; 307} 308 309EXPORT_SYMBOL(pnp_register_driver); 310EXPORT_SYMBOL(pnp_unregister_driver); 311EXPORT_SYMBOL(pnp_device_attach); 312EXPORT_SYMBOL(pnp_device_detach); 313