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 15 static 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 28 int 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 43 static 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 59 int pnp_device_attach(struct pnp_dev *pnp_dev) 60 { 61 spin_lock(&pnp_lock); 62 if (pnp_dev->status != PNP_READY) { 63 spin_unlock(&pnp_lock); 64 return -EBUSY; 65 } 66 pnp_dev->status = PNP_ATTACHED; 67 spin_unlock(&pnp_lock); 68 return 0; 69 } 70 71 void pnp_device_detach(struct pnp_dev *pnp_dev) 72 { 73 spin_lock(&pnp_lock); 74 if (pnp_dev->status == PNP_ATTACHED) 75 pnp_dev->status = PNP_READY; 76 spin_unlock(&pnp_lock); 77 pnp_disable_dev(pnp_dev); 78 } 79 80 static 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 pnp_dbg("match found with the PnP device '%s' and the driver '%s'", 90 dev->bus_id, pnp_drv->name); 91 92 error = pnp_device_attach(pnp_dev); 93 if (error < 0) 94 return error; 95 96 if (pnp_dev->active == 0) { 97 if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) { 98 error = pnp_activate_dev(pnp_dev); 99 if (error < 0) 100 return error; 101 } 102 } else if ((pnp_drv->flags & PNP_DRIVER_RES_DISABLE) 103 == PNP_DRIVER_RES_DISABLE) { 104 error = pnp_disable_dev(pnp_dev); 105 if (error < 0) 106 return error; 107 } 108 error = 0; 109 if (pnp_drv->probe) { 110 dev_id = match_device(pnp_drv, pnp_dev); 111 if (dev_id != NULL) 112 error = pnp_drv->probe(pnp_dev, dev_id); 113 } 114 if (error >= 0) { 115 pnp_dev->driver = pnp_drv; 116 error = 0; 117 } else 118 goto fail; 119 return error; 120 121 fail: 122 pnp_device_detach(pnp_dev); 123 return error; 124 } 125 126 static int pnp_device_remove(struct device *dev) 127 { 128 struct pnp_dev *pnp_dev = to_pnp_dev(dev); 129 struct pnp_driver *drv = pnp_dev->driver; 130 131 if (drv) { 132 if (drv->remove) 133 drv->remove(pnp_dev); 134 pnp_dev->driver = NULL; 135 } 136 pnp_device_detach(pnp_dev); 137 return 0; 138 } 139 140 static int pnp_bus_match(struct device *dev, struct device_driver *drv) 141 { 142 struct pnp_dev *pnp_dev = to_pnp_dev(dev); 143 struct pnp_driver *pnp_drv = to_pnp_driver(drv); 144 145 if (match_device(pnp_drv, pnp_dev) == NULL) 146 return 0; 147 return 1; 148 } 149 150 static int pnp_bus_suspend(struct device *dev, pm_message_t state) 151 { 152 struct pnp_dev *pnp_dev = to_pnp_dev(dev); 153 struct pnp_driver *pnp_drv = pnp_dev->driver; 154 int error; 155 156 if (!pnp_drv) 157 return 0; 158 159 if (pnp_drv->suspend) { 160 error = pnp_drv->suspend(pnp_dev, state); 161 if (error) 162 return error; 163 } 164 165 if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE) && 166 pnp_can_disable(pnp_dev)) { 167 error = pnp_stop_dev(pnp_dev); 168 if (error) 169 return error; 170 } 171 172 if (pnp_dev->protocol && pnp_dev->protocol->suspend) 173 pnp_dev->protocol->suspend(pnp_dev, state); 174 return 0; 175 } 176 177 static int pnp_bus_resume(struct device *dev) 178 { 179 struct pnp_dev *pnp_dev = to_pnp_dev(dev); 180 struct pnp_driver *pnp_drv = pnp_dev->driver; 181 int error; 182 183 if (!pnp_drv) 184 return 0; 185 186 if (pnp_dev->protocol && pnp_dev->protocol->resume) 187 pnp_dev->protocol->resume(pnp_dev); 188 189 if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) { 190 error = pnp_start_dev(pnp_dev); 191 if (error) 192 return error; 193 } 194 195 if (pnp_drv->resume) 196 return pnp_drv->resume(pnp_dev); 197 198 return 0; 199 } 200 201 struct bus_type pnp_bus_type = { 202 .name = "pnp", 203 .match = pnp_bus_match, 204 .probe = pnp_device_probe, 205 .remove = pnp_device_remove, 206 .suspend = pnp_bus_suspend, 207 .resume = pnp_bus_resume, 208 }; 209 210 int pnp_register_driver(struct pnp_driver *drv) 211 { 212 pnp_dbg("the driver '%s' has been registered", drv->name); 213 214 drv->driver.name = drv->name; 215 drv->driver.bus = &pnp_bus_type; 216 217 return driver_register(&drv->driver); 218 } 219 220 void pnp_unregister_driver(struct pnp_driver *drv) 221 { 222 driver_unregister(&drv->driver); 223 pnp_dbg("the driver '%s' has been unregistered", drv->name); 224 } 225 226 /** 227 * pnp_add_id - adds an EISA id to the specified device 228 * @id: pointer to a pnp_id structure 229 * @dev: pointer to the desired device 230 */ 231 int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev) 232 { 233 struct pnp_id *ptr; 234 235 id->next = NULL; 236 ptr = dev->id; 237 while (ptr && ptr->next) 238 ptr = ptr->next; 239 if (ptr) 240 ptr->next = id; 241 else 242 dev->id = id; 243 return 0; 244 } 245 246 EXPORT_SYMBOL(pnp_register_driver); 247 EXPORT_SYMBOL(pnp_unregister_driver); 248 EXPORT_SYMBOL(pnp_device_attach); 249 EXPORT_SYMBOL(pnp_device_detach); 250