7 #include <minix/const.h>
8 #include <minix/devman.h>
9 #include <minix/safecopies.h>
10 #include <minix/sysutil.h>
15 static endpoint_t devman_ep
;
17 static int save_string(char *buffer
, char *src
, size_t *offset
);
19 static TAILQ_HEAD(devlist_head
, devman_dev
) dev_list
;
21 /****************************************************************************
23 ***************************************************************************/
24 static int save_string(char *buffer
, char *src
, size_t *offset
)
26 unsigned old_offset
= *offset
;
27 size_t len
= strlen(src
) + 1;
28 memcpy(buffer
+ *offset
, src
, len
);
33 /****************************************************************************
35 ***************************************************************************/
36 void *serialize_dev(struct devman_dev
*dev
, size_t *overall_size
)
38 /* determine size of serialized version of dev */
41 size_t string_buffer_offset
;
43 size_t size
= sizeof(struct devman_device_info
);
44 size_t strings_size
= strlen(dev
->name
) + 1;
45 struct devman_device_info
* serialized_dev
;
46 struct devman_device_info_entry
*entry
;
47 struct devman_static_attribute
*attribute
;
49 TAILQ_FOREACH(attribute
, &dev
->attrs
, list
) {
50 strings_size
+= strlen(attribute
->name
) + 1;
51 strings_size
+= strlen(attribute
->data
) + 1;
52 size
+= sizeof(struct devman_device_info_entry
);
56 buffer
= malloc(size
+ strings_size
);
62 string_buffer
= buffer
;
63 string_buffer_offset
= size
; /* strings start after
64 devman_device_info and
65 devman_device_info_entries */
67 /* serialize device */
68 serialized_dev
= (struct devman_device_info
*) buffer
;
70 serialized_dev
->count
= count
;
71 serialized_dev
->parent_dev_id
= dev
->parent_dev_id
;
72 serialized_dev
->name_offset
=
73 save_string(string_buffer
, dev
->name
, &string_buffer_offset
);
76 save_string(string_buffer
, dev
->bus
, &string_buffer_offset
);
79 /* serialize entries */
81 (struct devman_device_info_entry
*)
82 (buffer
+ sizeof(struct devman_device_info
));
84 TAILQ_FOREACH(attribute
, &dev
->attrs
, list
) {
85 entry
->type
= 0; /* TODO: use macro */
87 save_string(string_buffer
, attribute
->name
, &string_buffer_offset
);
89 save_string(string_buffer
, attribute
->data
, &string_buffer_offset
);
93 *overall_size
= size
+ strings_size
;
99 /****************************************************************************
100 * devman_add_device *
101 ***************************************************************************/
102 int devman_add_device(struct devman_dev
*dev
)
107 void *buf
= serialize_dev(dev
, &grant_size
);
110 cpf_grant_direct(devman_ep
,(vir_bytes
) buf
,
111 grant_size
, CPF_READ
);
113 /* prepare message */
114 msg
.m_type
= DEVMAN_ADD_DEV
;
115 msg
.DEVMAN_GRANT_ID
= gid
;
116 msg
.DEVMAN_GRANT_SIZE
= grant_size
;
119 res
= sendrec(devman_ep
, &msg
);
122 panic("devman_add_device: could not talk to devman: %d", res
);
125 if (msg
.m_type
!= DEVMAN_REPLY
) {
126 panic("devman_add_device: got illegal response from devman: %d",
130 if (msg
.DEVMAN_RESULT
!= 0) {
131 panic("devman_add_device: could add device: %d",
135 /* store given dev_id to dev */
136 dev
->dev_id
= msg
.DEVMAN_DEVICE_ID
;
142 /* put device in list */
143 TAILQ_INSERT_HEAD(&dev_list
, dev
, dev_list
);
148 /****************************************************************************
149 * devman_del_device *
150 ***************************************************************************/
151 int devman_del_device(struct devman_dev
*dev
)
156 msg
.m_type
= DEVMAN_DEL_DEV
;
157 msg
.DEVMAN_DEVICE_ID
= dev
->dev_id
;
159 res
= sendrec(devman_ep
, &msg
);
162 panic("devman_del_device: could not talk to devman: %d", res
);
165 if (msg
.m_type
!= DEVMAN_REPLY
) {
166 panic("devman_del_device: got illegal response from devman: %d",
170 if (msg
.DEVMAN_RESULT
!= 0) {
171 panic("devman_del_device: could delete device: %d",
175 /* remove the device from list */
176 TAILQ_REMOVE(&dev_list
, dev
, dev_list
);
182 /****************************************************************************
184 ***************************************************************************/
185 endpoint_t
devman_get_ep()
190 /****************************************************************************
192 ***************************************************************************/
197 /* get the endpoint of the HCD */
198 res
= ds_retrieve_label_endpt("devman", &devman_ep
);
201 panic("usb_init: ds_retrieve_label_endpt failed for 'devman': %d", res
);
204 TAILQ_INIT(&dev_list
);
209 /****************************************************************************
211 ***************************************************************************/
212 static void do_bind(message
*m
)
214 struct devman_dev
*dev
;
218 TAILQ_FOREACH(dev
, &dev_list
, dev_list
) {
219 if (dev
->dev_id
== m
->DEVMAN_DEVICE_ID
) {
221 res
= dev
->bind_cb(dev
->data
, m
->DEVMAN_ENDPOINT
);
222 m
->m_type
= DEVMAN_REPLY
;
223 m
->DEVMAN_RESULT
= res
;
229 m
->m_type
= DEVMAN_REPLY
;
230 m
->DEVMAN_RESULT
= ENODEV
;
235 /****************************************************************************
237 ***************************************************************************/
238 static void do_unbind(message
*m
)
240 struct devman_dev
*dev
;
244 TAILQ_FOREACH(dev
, &dev_list
, dev_list
) {
245 if (dev
->dev_id
== m
->DEVMAN_DEVICE_ID
) {
246 if (dev
->unbind_cb
) {
247 res
= dev
->unbind_cb(dev
->data
, m
->DEVMAN_ENDPOINT
);
248 m
->m_type
= DEVMAN_REPLY
;
249 m
->DEVMAN_RESULT
= res
;
255 m
->m_type
= DEVMAN_REPLY
;
256 m
->DEVMAN_RESULT
= ENODEV
;
260 /****************************************************************************
261 * devman_handle_msg *
262 ***************************************************************************/
263 int devman_handle_msg(message
*m
)
265 /* make sure msg comes from devman server */
266 if (m
->m_source
!= devman_ep
) {
267 /* we don't honor requests from others by answering them */