1 /* ----------------------------------------------------------------------------
2 * Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved.
3 * Description: LiteOS USB Driver Composite Devices
4 * Author: Yannik Li
5 * Create: 2021-02-21
6 * Redistribution and use in source and binary forms, with or without modification,
7 * are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
14 * to endorse or promote products derived from this software without specific prior written
15 * permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * --------------------------------------------------------------------------- */
28 /* ----------------------------------------------------------------------------
29 * Notice of Export Control Law
30 * ===============================================
31 * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
32 * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
33 * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
34 * applicable export control laws and regulations.
35 * --------------------------------------------------------------------------- */
36 #include "obj_ref.h"
37 #include "usb_obj.h"
38 #include "f_common.h"
39 #include <linux/spinlock.h>
40
41 #ifdef __cplusplus
42 #if __cplusplus
43 //extern "C" {
44 #endif /* __cplusplus */
45 #endif /* __cplusplus */
46
usbobj_init(struct usb_obj * obj,const char * name,void (* release)(struct usb_obj * obj))47 int usbobj_init(struct usb_obj *obj, const char *name,
48 void (*release)(struct usb_obj *obj))
49 {
50 if (!obj)
51 {
52 return -1;
53 }
54
55 obj->name = name;
56 obj->parent = NULL;
57 objref_init(&obj->ref, 1);
58 INIT_LIST_HEAD(&obj->entry);
59 INIT_LIST_HEAD(&obj->children);
60 INIT_LIST_HEAD(&obj->objres_head);
61 spin_lock_init(&obj->objres_lock);
62 spin_lock_init(&obj->lock);
63 obj->release = release;
64
65 return 0;
66 }
67
usbobj_add(struct usb_obj * obj,struct usb_obj * parent)68 int usbobj_add(struct usb_obj *obj, struct usb_obj *parent)
69 {
70 uint32_t flags;
71
72 if (!obj || !parent)
73 {
74 return -1;
75 }
76
77 usbobj_get(parent);
78 spin_lock_irqsave(&parent->lock, flags);
79 list_add_tail(&obj->entry, &parent->children);
80 obj->parent = parent;
81 spin_unlock_irqrestore(&parent->lock, flags);
82
83 return 0;
84 }
85
usbobj_remove(struct usb_obj * obj)86 int usbobj_remove(struct usb_obj *obj)
87 {
88 struct usb_obj *parent;
89 uint32_t flags;
90
91 if (!obj || !obj->parent)
92 {
93 return -1;
94 }
95
96 parent = obj->parent;
97 spin_lock_irqsave(&parent->lock, flags);
98 list_del_init(&obj->entry);
99 spin_unlock_irqrestore(&parent->lock, flags);
100 obj->parent = NULL;
101
102 return 0;
103 }
104
usbobj_find(struct usb_obj * obj,usbobj_match_t match,void * match_data)105 struct usb_obj *usbobj_find(struct usb_obj *obj, usbobj_match_t match, void *match_data)
106 {
107 struct usb_obj *child;
108 bool found = false;
109 uint32_t flags;
110
111 if (!obj)
112 {
113 return NULL;
114 }
115
116 spin_lock_irqsave(&obj->lock, flags);
117 list_for_each_entry(child, &obj->children, entry)
118 {
119 if (match(child, match_data))
120 {
121 found = true;
122 break;
123 }
124 }
125 spin_unlock_irqrestore(&obj->lock, flags);
126
127 return found ? child : NULL;
128 }
129
usbobj_get(struct usb_obj * obj)130 void usbobj_get(struct usb_obj *obj)
131 {
132 if (obj)
133 {
134 objref_get(&obj->ref);
135 }
136 }
137
usbobj_release_child(struct usb_obj * obj,void * data)138 static void usbobj_release_child(struct usb_obj *obj, void *data)
139 {
140 (void)data;
141 usbobj_put(obj);
142 }
143
usbobj_release(struct obj_ref * ref)144 static void usbobj_release(struct obj_ref *ref)
145 {
146 struct usb_obj *obj = container_of(ref, struct usb_obj, ref);
147 struct usb_obj *parent = obj->parent;
148 uint32_t flags;
149
150 if (parent)
151 {
152 spin_lock_irqsave(&parent->lock, flags);
153 list_del_init(&obj->entry);
154 spin_unlock_irqrestore(&parent->lock, flags);
155 }
156
157 usbobj_for_each_child(obj, NULL, NULL, usbobj_release_child, NULL);
158
159 objres_release_all(obj);
160 if (obj->release)
161 {
162 obj->release(obj);
163 }
164
165 if (parent)
166 {
167 usbobj_put(parent);
168 }
169 }
170
usbobj_put(struct usb_obj * obj)171 void usbobj_put(struct usb_obj *obj)
172 {
173 if (obj)
174 {
175 (void)objref_put(&obj->ref, usbobj_release);
176 }
177 }
178
usbobj_for_each_child(struct usb_obj * obj,usbobj_match_t match,void * match_data,void (* fn)(struct usb_obj *,void *),void * data)179 void usbobj_for_each_child(struct usb_obj *obj,
180 usbobj_match_t match, void *match_data,
181 void (*fn)(struct usb_obj *, void *),
182 void *data)
183 {
184 struct usb_obj *child, *tmp;
185 uint32_t flags;
186
187 if (!obj || !fn)
188 {
189 return;
190 }
191
192 spin_lock_irqsave(&obj->lock, flags);
193 list_for_each_entry_safe(child, tmp, &obj->children, entry)
194 {
195 if (match && !match(child, match_data))
196 {
197 continue;
198 }
199 fn(child, data);
200 }
201 spin_unlock_irqrestore(&obj->lock, flags);
202 }
203
204 #ifdef __cplusplus
205 #if __cplusplus
206 //}
207 #endif /* __cplusplus */
208 #endif /* __cplusplus */
209