Root/
1 | /********************************************************************* |
2 | * |
3 | * Filename: irias_object.c |
4 | * Version: 0.3 |
5 | * Description: IAS object database and functions |
6 | * Status: Experimental. |
7 | * Author: Dag Brattli <dagb@cs.uit.no> |
8 | * Created at: Thu Oct 1 22:50:04 1998 |
9 | * Modified at: Wed Dec 15 11:23:16 1999 |
10 | * Modified by: Dag Brattli <dagb@cs.uit.no> |
11 | * |
12 | * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. |
13 | * |
14 | * This program is free software; you can redistribute it and/or |
15 | * modify it under the terms of the GNU General Public License as |
16 | * published by the Free Software Foundation; either version 2 of |
17 | * the License, or (at your option) any later version. |
18 | * |
19 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
20 | * provide warranty for any of this software. This material is |
21 | * provided "AS-IS" and at no charge. |
22 | * |
23 | ********************************************************************/ |
24 | |
25 | #include <linux/slab.h> |
26 | #include <linux/string.h> |
27 | #include <linux/socket.h> |
28 | #include <linux/module.h> |
29 | |
30 | #include <net/irda/irda.h> |
31 | #include <net/irda/irias_object.h> |
32 | |
33 | hashbin_t *irias_objects; |
34 | |
35 | /* |
36 | * Used when a missing value needs to be returned |
37 | */ |
38 | struct ias_value irias_missing = { IAS_MISSING, 0, 0, 0, {0}}; |
39 | |
40 | |
41 | /* |
42 | * Function ias_new_object (name, id) |
43 | * |
44 | * Create a new IAS object |
45 | * |
46 | */ |
47 | struct ias_object *irias_new_object( char *name, int id) |
48 | { |
49 | struct ias_object *obj; |
50 | |
51 | IRDA_DEBUG( 4, "%s()\n", __func__); |
52 | |
53 | obj = kzalloc(sizeof(struct ias_object), GFP_ATOMIC); |
54 | if (obj == NULL) { |
55 | IRDA_WARNING("%s(), Unable to allocate object!\n", |
56 | __func__); |
57 | return NULL; |
58 | } |
59 | |
60 | obj->magic = IAS_OBJECT_MAGIC; |
61 | obj->name = kstrndup(name, IAS_MAX_CLASSNAME, GFP_ATOMIC); |
62 | if (!obj->name) { |
63 | IRDA_WARNING("%s(), Unable to allocate name!\n", |
64 | __func__); |
65 | kfree(obj); |
66 | return NULL; |
67 | } |
68 | obj->id = id; |
69 | |
70 | /* Locking notes : the attrib spinlock has lower precendence |
71 | * than the objects spinlock. Never grap the objects spinlock |
72 | * while holding any attrib spinlock (risk of deadlock). Jean II */ |
73 | obj->attribs = hashbin_new(HB_LOCK); |
74 | |
75 | if (obj->attribs == NULL) { |
76 | IRDA_WARNING("%s(), Unable to allocate attribs!\n", |
77 | __func__); |
78 | kfree(obj->name); |
79 | kfree(obj); |
80 | return NULL; |
81 | } |
82 | |
83 | return obj; |
84 | } |
85 | EXPORT_SYMBOL(irias_new_object); |
86 | |
87 | /* |
88 | * Function irias_delete_attrib (attrib) |
89 | * |
90 | * Delete given attribute and deallocate all its memory |
91 | * |
92 | */ |
93 | static void __irias_delete_attrib(struct ias_attrib *attrib) |
94 | { |
95 | IRDA_ASSERT(attrib != NULL, return;); |
96 | IRDA_ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return;); |
97 | |
98 | kfree(attrib->name); |
99 | |
100 | irias_delete_value(attrib->value); |
101 | attrib->magic = ~IAS_ATTRIB_MAGIC; |
102 | |
103 | kfree(attrib); |
104 | } |
105 | |
106 | void __irias_delete_object(struct ias_object *obj) |
107 | { |
108 | IRDA_ASSERT(obj != NULL, return;); |
109 | IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;); |
110 | |
111 | kfree(obj->name); |
112 | |
113 | hashbin_delete(obj->attribs, (FREE_FUNC) __irias_delete_attrib); |
114 | |
115 | obj->magic = ~IAS_OBJECT_MAGIC; |
116 | |
117 | kfree(obj); |
118 | } |
119 | |
120 | /* |
121 | * Function irias_delete_object (obj) |
122 | * |
123 | * Remove object from hashbin and deallocate all attributes associated with |
124 | * with this object and the object itself |
125 | * |
126 | */ |
127 | int irias_delete_object(struct ias_object *obj) |
128 | { |
129 | struct ias_object *node; |
130 | |
131 | IRDA_ASSERT(obj != NULL, return -1;); |
132 | IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -1;); |
133 | |
134 | /* Remove from list */ |
135 | node = hashbin_remove_this(irias_objects, (irda_queue_t *) obj); |
136 | if (!node) |
137 | IRDA_DEBUG( 0, "%s(), object already removed!\n", |
138 | __func__); |
139 | |
140 | /* Destroy */ |
141 | __irias_delete_object(obj); |
142 | |
143 | return 0; |
144 | } |
145 | EXPORT_SYMBOL(irias_delete_object); |
146 | |
147 | /* |
148 | * Function irias_delete_attrib (obj) |
149 | * |
150 | * Remove attribute from hashbin and, if it was the last attribute of |
151 | * the object, remove the object as well. |
152 | * |
153 | */ |
154 | int irias_delete_attrib(struct ias_object *obj, struct ias_attrib *attrib, |
155 | int cleanobject) |
156 | { |
157 | struct ias_attrib *node; |
158 | |
159 | IRDA_ASSERT(obj != NULL, return -1;); |
160 | IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -1;); |
161 | IRDA_ASSERT(attrib != NULL, return -1;); |
162 | |
163 | /* Remove attribute from object */ |
164 | node = hashbin_remove_this(obj->attribs, (irda_queue_t *) attrib); |
165 | if (!node) |
166 | return 0; /* Already removed or non-existent */ |
167 | |
168 | /* Deallocate attribute */ |
169 | __irias_delete_attrib(node); |
170 | |
171 | /* Check if object has still some attributes, destroy it if none. |
172 | * At first glance, this look dangerous, as the kernel reference |
173 | * various IAS objects. However, we only use this function on |
174 | * user attributes, not kernel attributes, so there is no risk |
175 | * of deleting a kernel object this way. Jean II */ |
176 | node = (struct ias_attrib *) hashbin_get_first(obj->attribs); |
177 | if (cleanobject && !node) |
178 | irias_delete_object(obj); |
179 | |
180 | return 0; |
181 | } |
182 | |
183 | /* |
184 | * Function irias_insert_object (obj) |
185 | * |
186 | * Insert an object into the LM-IAS database |
187 | * |
188 | */ |
189 | void irias_insert_object(struct ias_object *obj) |
190 | { |
191 | IRDA_ASSERT(obj != NULL, return;); |
192 | IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;); |
193 | |
194 | hashbin_insert(irias_objects, (irda_queue_t *) obj, 0, obj->name); |
195 | } |
196 | EXPORT_SYMBOL(irias_insert_object); |
197 | |
198 | /* |
199 | * Function irias_find_object (name) |
200 | * |
201 | * Find object with given name |
202 | * |
203 | */ |
204 | struct ias_object *irias_find_object(char *name) |
205 | { |
206 | IRDA_ASSERT(name != NULL, return NULL;); |
207 | |
208 | /* Unsafe (locking), object might change */ |
209 | return hashbin_lock_find(irias_objects, 0, name); |
210 | } |
211 | EXPORT_SYMBOL(irias_find_object); |
212 | |
213 | /* |
214 | * Function irias_find_attrib (obj, name) |
215 | * |
216 | * Find named attribute in object |
217 | * |
218 | */ |
219 | struct ias_attrib *irias_find_attrib(struct ias_object *obj, char *name) |
220 | { |
221 | struct ias_attrib *attrib; |
222 | |
223 | IRDA_ASSERT(obj != NULL, return NULL;); |
224 | IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return NULL;); |
225 | IRDA_ASSERT(name != NULL, return NULL;); |
226 | |
227 | attrib = hashbin_lock_find(obj->attribs, 0, name); |
228 | if (attrib == NULL) |
229 | return NULL; |
230 | |
231 | /* Unsafe (locking), attrib might change */ |
232 | return attrib; |
233 | } |
234 | |
235 | /* |
236 | * Function irias_add_attribute (obj, attrib) |
237 | * |
238 | * Add attribute to object |
239 | * |
240 | */ |
241 | static void irias_add_attrib(struct ias_object *obj, struct ias_attrib *attrib, |
242 | int owner) |
243 | { |
244 | IRDA_ASSERT(obj != NULL, return;); |
245 | IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;); |
246 | |
247 | IRDA_ASSERT(attrib != NULL, return;); |
248 | IRDA_ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return;); |
249 | |
250 | /* Set if attrib is owned by kernel or user space */ |
251 | attrib->value->owner = owner; |
252 | |
253 | hashbin_insert(obj->attribs, (irda_queue_t *) attrib, 0, attrib->name); |
254 | } |
255 | |
256 | /* |
257 | * Function irias_object_change_attribute (obj_name, attrib_name, new_value) |
258 | * |
259 | * Change the value of an objects attribute. |
260 | * |
261 | */ |
262 | int irias_object_change_attribute(char *obj_name, char *attrib_name, |
263 | struct ias_value *new_value) |
264 | { |
265 | struct ias_object *obj; |
266 | struct ias_attrib *attrib; |
267 | unsigned long flags; |
268 | |
269 | /* Find object */ |
270 | obj = hashbin_lock_find(irias_objects, 0, obj_name); |
271 | if (obj == NULL) { |
272 | IRDA_WARNING("%s: Unable to find object: %s\n", __func__, |
273 | obj_name); |
274 | return -1; |
275 | } |
276 | |
277 | /* Slightly unsafe (obj might get removed under us) */ |
278 | spin_lock_irqsave(&obj->attribs->hb_spinlock, flags); |
279 | |
280 | /* Find attribute */ |
281 | attrib = hashbin_find(obj->attribs, 0, attrib_name); |
282 | if (attrib == NULL) { |
283 | IRDA_WARNING("%s: Unable to find attribute: %s\n", |
284 | __func__, attrib_name); |
285 | spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags); |
286 | return -1; |
287 | } |
288 | |
289 | if ( attrib->value->type != new_value->type) { |
290 | IRDA_DEBUG( 0, "%s(), changing value type not allowed!\n", |
291 | __func__); |
292 | spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags); |
293 | return -1; |
294 | } |
295 | |
296 | /* Delete old value */ |
297 | irias_delete_value(attrib->value); |
298 | |
299 | /* Insert new value */ |
300 | attrib->value = new_value; |
301 | |
302 | /* Success */ |
303 | spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags); |
304 | return 0; |
305 | } |
306 | EXPORT_SYMBOL(irias_object_change_attribute); |
307 | |
308 | /* |
309 | * Function irias_object_add_integer_attrib (obj, name, value) |
310 | * |
311 | * Add an integer attribute to an LM-IAS object |
312 | * |
313 | */ |
314 | void irias_add_integer_attrib(struct ias_object *obj, char *name, int value, |
315 | int owner) |
316 | { |
317 | struct ias_attrib *attrib; |
318 | |
319 | IRDA_ASSERT(obj != NULL, return;); |
320 | IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;); |
321 | IRDA_ASSERT(name != NULL, return;); |
322 | |
323 | attrib = kzalloc(sizeof(struct ias_attrib), GFP_ATOMIC); |
324 | if (attrib == NULL) { |
325 | IRDA_WARNING("%s: Unable to allocate attribute!\n", |
326 | __func__); |
327 | return; |
328 | } |
329 | |
330 | attrib->magic = IAS_ATTRIB_MAGIC; |
331 | attrib->name = kstrndup(name, IAS_MAX_ATTRIBNAME, GFP_ATOMIC); |
332 | |
333 | /* Insert value */ |
334 | attrib->value = irias_new_integer_value(value); |
335 | if (!attrib->name || !attrib->value) { |
336 | IRDA_WARNING("%s: Unable to allocate attribute!\n", |
337 | __func__); |
338 | if (attrib->value) |
339 | irias_delete_value(attrib->value); |
340 | kfree(attrib->name); |
341 | kfree(attrib); |
342 | return; |
343 | } |
344 | |
345 | irias_add_attrib(obj, attrib, owner); |
346 | } |
347 | EXPORT_SYMBOL(irias_add_integer_attrib); |
348 | |
349 | /* |
350 | * Function irias_add_octseq_attrib (obj, name, octet_seq, len) |
351 | * |
352 | * Add a octet sequence attribute to an LM-IAS object |
353 | * |
354 | */ |
355 | |
356 | void irias_add_octseq_attrib(struct ias_object *obj, char *name, __u8 *octets, |
357 | int len, int owner) |
358 | { |
359 | struct ias_attrib *attrib; |
360 | |
361 | IRDA_ASSERT(obj != NULL, return;); |
362 | IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;); |
363 | |
364 | IRDA_ASSERT(name != NULL, return;); |
365 | IRDA_ASSERT(octets != NULL, return;); |
366 | |
367 | attrib = kzalloc(sizeof(struct ias_attrib), GFP_ATOMIC); |
368 | if (attrib == NULL) { |
369 | IRDA_WARNING("%s: Unable to allocate attribute!\n", |
370 | __func__); |
371 | return; |
372 | } |
373 | |
374 | attrib->magic = IAS_ATTRIB_MAGIC; |
375 | attrib->name = kstrndup(name, IAS_MAX_ATTRIBNAME, GFP_ATOMIC); |
376 | |
377 | attrib->value = irias_new_octseq_value( octets, len); |
378 | if (!attrib->name || !attrib->value) { |
379 | IRDA_WARNING("%s: Unable to allocate attribute!\n", |
380 | __func__); |
381 | if (attrib->value) |
382 | irias_delete_value(attrib->value); |
383 | kfree(attrib->name); |
384 | kfree(attrib); |
385 | return; |
386 | } |
387 | |
388 | irias_add_attrib(obj, attrib, owner); |
389 | } |
390 | EXPORT_SYMBOL(irias_add_octseq_attrib); |
391 | |
392 | /* |
393 | * Function irias_object_add_string_attrib (obj, string) |
394 | * |
395 | * Add a string attribute to an LM-IAS object |
396 | * |
397 | */ |
398 | void irias_add_string_attrib(struct ias_object *obj, char *name, char *value, |
399 | int owner) |
400 | { |
401 | struct ias_attrib *attrib; |
402 | |
403 | IRDA_ASSERT(obj != NULL, return;); |
404 | IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;); |
405 | |
406 | IRDA_ASSERT(name != NULL, return;); |
407 | IRDA_ASSERT(value != NULL, return;); |
408 | |
409 | attrib = kzalloc(sizeof( struct ias_attrib), GFP_ATOMIC); |
410 | if (attrib == NULL) { |
411 | IRDA_WARNING("%s: Unable to allocate attribute!\n", |
412 | __func__); |
413 | return; |
414 | } |
415 | |
416 | attrib->magic = IAS_ATTRIB_MAGIC; |
417 | attrib->name = kstrndup(name, IAS_MAX_ATTRIBNAME, GFP_ATOMIC); |
418 | |
419 | attrib->value = irias_new_string_value(value); |
420 | if (!attrib->name || !attrib->value) { |
421 | IRDA_WARNING("%s: Unable to allocate attribute!\n", |
422 | __func__); |
423 | if (attrib->value) |
424 | irias_delete_value(attrib->value); |
425 | kfree(attrib->name); |
426 | kfree(attrib); |
427 | return; |
428 | } |
429 | |
430 | irias_add_attrib(obj, attrib, owner); |
431 | } |
432 | EXPORT_SYMBOL(irias_add_string_attrib); |
433 | |
434 | /* |
435 | * Function irias_new_integer_value (integer) |
436 | * |
437 | * Create new IAS integer value |
438 | * |
439 | */ |
440 | struct ias_value *irias_new_integer_value(int integer) |
441 | { |
442 | struct ias_value *value; |
443 | |
444 | value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC); |
445 | if (value == NULL) { |
446 | IRDA_WARNING("%s: Unable to kmalloc!\n", __func__); |
447 | return NULL; |
448 | } |
449 | |
450 | value->type = IAS_INTEGER; |
451 | value->len = 4; |
452 | value->t.integer = integer; |
453 | |
454 | return value; |
455 | } |
456 | EXPORT_SYMBOL(irias_new_integer_value); |
457 | |
458 | /* |
459 | * Function irias_new_string_value (string) |
460 | * |
461 | * Create new IAS string value |
462 | * |
463 | * Per IrLMP 1.1, 4.3.3.2, strings are up to 256 chars - Jean II |
464 | */ |
465 | struct ias_value *irias_new_string_value(char *string) |
466 | { |
467 | struct ias_value *value; |
468 | |
469 | value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC); |
470 | if (value == NULL) { |
471 | IRDA_WARNING("%s: Unable to kmalloc!\n", __func__); |
472 | return NULL; |
473 | } |
474 | |
475 | value->type = IAS_STRING; |
476 | value->charset = CS_ASCII; |
477 | value->t.string = kstrndup(string, IAS_MAX_STRING, GFP_ATOMIC); |
478 | if (!value->t.string) { |
479 | IRDA_WARNING("%s: Unable to kmalloc!\n", __func__); |
480 | kfree(value); |
481 | return NULL; |
482 | } |
483 | |
484 | value->len = strlen(value->t.string); |
485 | |
486 | return value; |
487 | } |
488 | |
489 | /* |
490 | * Function irias_new_octseq_value (octets, len) |
491 | * |
492 | * Create new IAS octet-sequence value |
493 | * |
494 | * Per IrLMP 1.1, 4.3.3.2, octet-sequence are up to 1024 bytes - Jean II |
495 | */ |
496 | struct ias_value *irias_new_octseq_value(__u8 *octseq , int len) |
497 | { |
498 | struct ias_value *value; |
499 | |
500 | value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC); |
501 | if (value == NULL) { |
502 | IRDA_WARNING("%s: Unable to kmalloc!\n", __func__); |
503 | return NULL; |
504 | } |
505 | |
506 | value->type = IAS_OCT_SEQ; |
507 | /* Check length */ |
508 | if(len > IAS_MAX_OCTET_STRING) |
509 | len = IAS_MAX_OCTET_STRING; |
510 | value->len = len; |
511 | |
512 | value->t.oct_seq = kmemdup(octseq, len, GFP_ATOMIC); |
513 | if (value->t.oct_seq == NULL){ |
514 | IRDA_WARNING("%s: Unable to kmalloc!\n", __func__); |
515 | kfree(value); |
516 | return NULL; |
517 | } |
518 | return value; |
519 | } |
520 | |
521 | struct ias_value *irias_new_missing_value(void) |
522 | { |
523 | struct ias_value *value; |
524 | |
525 | value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC); |
526 | if (value == NULL) { |
527 | IRDA_WARNING("%s: Unable to kmalloc!\n", __func__); |
528 | return NULL; |
529 | } |
530 | |
531 | value->type = IAS_MISSING; |
532 | |
533 | return value; |
534 | } |
535 | |
536 | /* |
537 | * Function irias_delete_value (value) |
538 | * |
539 | * Delete IAS value |
540 | * |
541 | */ |
542 | void irias_delete_value(struct ias_value *value) |
543 | { |
544 | IRDA_DEBUG(4, "%s()\n", __func__); |
545 | |
546 | IRDA_ASSERT(value != NULL, return;); |
547 | |
548 | switch (value->type) { |
549 | case IAS_INTEGER: /* Fallthrough */ |
550 | case IAS_MISSING: |
551 | /* No need to deallocate */ |
552 | break; |
553 | case IAS_STRING: |
554 | /* Deallocate string */ |
555 | kfree(value->t.string); |
556 | break; |
557 | case IAS_OCT_SEQ: |
558 | /* Deallocate byte stream */ |
559 | kfree(value->t.oct_seq); |
560 | break; |
561 | default: |
562 | IRDA_DEBUG(0, "%s(), Unknown value type!\n", __func__); |
563 | break; |
564 | } |
565 | kfree(value); |
566 | } |
567 | EXPORT_SYMBOL(irias_delete_value); |
568 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9