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