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 static 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
)
106 size_t grant_size
= 0;
107 void *buf
= serialize_dev(dev
, &grant_size
);
110 panic("out of memory");
113 cpf_grant_direct(devman_ep
,(vir_bytes
) buf
,
114 grant_size
, CPF_READ
);
116 /* prepare message */
117 msg
.m_type
= DEVMAN_ADD_DEV
;
118 msg
.DEVMAN_GRANT_ID
= gid
;
119 msg
.DEVMAN_GRANT_SIZE
= grant_size
;
122 res
= ipc_sendrec(devman_ep
, &msg
);
125 panic("devman_add_device: could not talk to devman: %d", res
);
128 if (msg
.m_type
!= DEVMAN_REPLY
) {
129 panic("devman_add_device: got illegal response from devman: %d",
133 if (msg
.DEVMAN_RESULT
!= 0) {
134 panic("devman_add_device: could add device: %ld",
138 /* store given dev_id to dev */
139 dev
->dev_id
= msg
.DEVMAN_DEVICE_ID
;
145 /* put device in list */
146 TAILQ_INSERT_HEAD(&dev_list
, dev
, dev_list
);
151 /****************************************************************************
152 * devman_del_device *
153 ***************************************************************************/
154 int devman_del_device(struct devman_dev
*dev
)
159 msg
.m_type
= DEVMAN_DEL_DEV
;
160 msg
.DEVMAN_DEVICE_ID
= dev
->dev_id
;
162 res
= ipc_sendrec(devman_ep
, &msg
);
165 panic("devman_del_device: could not talk to devman: %d", res
);
168 if (msg
.m_type
!= DEVMAN_REPLY
) {
169 panic("devman_del_device: got illegal response from devman: %d",
173 if (msg
.DEVMAN_RESULT
!= 0) {
174 panic("devman_del_device: could delete device: %ld",
178 /* remove the device from list */
179 TAILQ_REMOVE(&dev_list
, dev
, dev_list
);
185 /****************************************************************************
187 ***************************************************************************/
188 int devman_init(void)
192 /* get the endpoint of the HCD */
193 res
= ds_retrieve_label_endpt("devman", &devman_ep
);
196 panic("usb_init: ds_retrieve_label_endpt failed for 'devman': %d", res
);
199 TAILQ_INIT(&dev_list
);
204 /****************************************************************************
206 ***************************************************************************/
207 static void do_bind(message
*m
)
209 struct devman_dev
*dev
;
213 TAILQ_FOREACH(dev
, &dev_list
, dev_list
) {
214 if (dev
->dev_id
== m
->DEVMAN_DEVICE_ID
) {
216 res
= dev
->bind_cb(dev
->data
, m
->DEVMAN_ENDPOINT
);
217 m
->m_type
= DEVMAN_REPLY
;
218 m
->DEVMAN_RESULT
= res
;
219 ipc_send(devman_ep
, m
);
224 m
->m_type
= DEVMAN_REPLY
;
225 m
->DEVMAN_RESULT
= ENODEV
;
226 ipc_send(devman_ep
, m
);
230 /****************************************************************************
232 ***************************************************************************/
233 static void do_unbind(message
*m
)
235 struct devman_dev
*dev
;
239 TAILQ_FOREACH(dev
, &dev_list
, dev_list
) {
240 if (dev
->dev_id
== m
->DEVMAN_DEVICE_ID
) {
241 if (dev
->unbind_cb
) {
242 res
= dev
->unbind_cb(dev
->data
, m
->DEVMAN_ENDPOINT
);
243 m
->m_type
= DEVMAN_REPLY
;
244 m
->DEVMAN_RESULT
= res
;
245 ipc_send(devman_ep
, m
);
250 m
->m_type
= DEVMAN_REPLY
;
251 m
->DEVMAN_RESULT
= ENODEV
;
252 ipc_send(devman_ep
, m
);
255 /****************************************************************************
256 * devman_handle_msg *
257 ***************************************************************************/
258 int devman_handle_msg(message
*m
)
260 /* make sure msg comes from devman server */
261 if (m
->m_source
!= devman_ep
) {
262 /* we don't honor requests from others by answering them */