Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
driver.c
Go to the documentation of this file.
1 /*
2  * driver.c - device id matching, driver model, etc.
3  *
4  * Copyright 2002 Adam Belay <[email protected]>
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 
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 
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  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)
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 
119 fail:
120  pnp_device_detach(pnp_dev);
121  return error;
122 }
123 
124 static 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 
138 static 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 
147 static 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 
157 static 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->suspend) {
167  error = pnp_drv->suspend(pnp_dev, state);
168  if (error)
169  return error;
170  }
171 
172  if (pnp_can_disable(pnp_dev)) {
173  error = pnp_stop_dev(pnp_dev);
174  if (error)
175  return error;
176  }
177 
178  if (pnp_dev->protocol->suspend)
179  pnp_dev->protocol->suspend(pnp_dev, state);
180  return 0;
181 }
182 
183 static int pnp_bus_resume(struct device *dev)
184 {
185  struct pnp_dev *pnp_dev = to_pnp_dev(dev);
186  struct pnp_driver *pnp_drv = pnp_dev->driver;
187  int error;
188 
189  if (!pnp_drv)
190  return 0;
191 
192  if (pnp_dev->protocol->resume) {
193  error = pnp_dev->protocol->resume(pnp_dev);
194  if (error)
195  return error;
196  }
197 
198  if (pnp_can_write(pnp_dev)) {
199  error = pnp_start_dev(pnp_dev);
200  if (error)
201  return error;
202  }
203 
204  if (pnp_drv->resume) {
205  error = pnp_drv->resume(pnp_dev);
206  if (error)
207  return error;
208  }
209 
210  return 0;
211 }
212 
214  .name = "pnp",
215  .match = pnp_bus_match,
216  .probe = pnp_device_probe,
217  .remove = pnp_device_remove,
218  .shutdown = pnp_device_shutdown,
219  .suspend = pnp_bus_suspend,
220  .resume = pnp_bus_resume,
221  .dev_attrs = pnp_interface_attrs,
222 };
223 
225 {
226  drv->driver.name = drv->name;
227  drv->driver.bus = &pnp_bus_type;
228 
229  return driver_register(&drv->driver);
230 }
231 
233 {
234  driver_unregister(&drv->driver);
235 }
236 
242 struct pnp_id *pnp_add_id(struct pnp_dev *dev, const char *id)
243 {
244  struct pnp_id *dev_id, *ptr;
245 
246  dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
247  if (!dev_id)
248  return NULL;
249 
250  dev_id->id[0] = id[0];
251  dev_id->id[1] = id[1];
252  dev_id->id[2] = id[2];
253  dev_id->id[3] = tolower(id[3]);
254  dev_id->id[4] = tolower(id[4]);
255  dev_id->id[5] = tolower(id[5]);
256  dev_id->id[6] = tolower(id[6]);
257  dev_id->id[7] = '\0';
258 
259  dev_id->next = NULL;
260  ptr = dev->id;
261  while (ptr && ptr->next)
262  ptr = ptr->next;
263  if (ptr)
264  ptr->next = dev_id;
265  else
266  dev->id = dev_id;
267 
268  return dev_id;
269 }
270