xref: /minix3/minix/lib/libddekit/src/usb_server.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1433d6423SLionel Sambuc #include "common.h"
2433d6423SLionel Sambuc 
3433d6423SLionel Sambuc #include <ddekit/minix/msg_queue.h>
4433d6423SLionel Sambuc #include <ddekit/panic.h>
5433d6423SLionel Sambuc #include <ddekit/printf.h>
6433d6423SLionel Sambuc #include <ddekit/usb.h>
7433d6423SLionel Sambuc #include <minix/safecopies.h>
8433d6423SLionel Sambuc #include <minix/usb.h>
9433d6423SLionel Sambuc #include <minix/usb_ch9.h>
10433d6423SLionel Sambuc #include <minix/devman.h>
11433d6423SLionel Sambuc 
12433d6423SLionel Sambuc #define MAX_URBS    10
13433d6423SLionel Sambuc 
14433d6423SLionel Sambuc #define DRIVER_UNUSED 0
15433d6423SLionel Sambuc #define DRIVER_ACTIVE 1
16433d6423SLionel Sambuc #define DRIVER_BOUND  2
17433d6423SLionel Sambuc 
18433d6423SLionel Sambuc #if 0
19433d6423SLionel Sambuc #define DEBUG_MSG(fmt, ...) ddekit_printf("%s : "fmt"\n", __func__, ##__VA_ARGS__ )
20433d6423SLionel Sambuc #else
21433d6423SLionel Sambuc #define DEBUG_MSG(fmt, ...)
22433d6423SLionel Sambuc #endif
23433d6423SLionel Sambuc 
24433d6423SLionel Sambuc #undef DDEBUG
25433d6423SLionel Sambuc #define DDEBUG 0
26433d6423SLionel Sambuc #include "debug.h"
27433d6423SLionel Sambuc 
28433d6423SLionel Sambuc #define MAX_DEVS 256
29433d6423SLionel Sambuc #define MAX_DRIVERS 256
30433d6423SLionel Sambuc #define OK 0
31433d6423SLionel Sambuc 
32433d6423SLionel Sambuc #define INVAL_DEV (-1)
33433d6423SLionel Sambuc 
34433d6423SLionel Sambuc struct my_context {
35433d6423SLionel Sambuc 	unsigned urb_id;
36433d6423SLionel Sambuc 	struct ddekit_usb_urb *d_urb;
37433d6423SLionel Sambuc 	struct usb_urb *mx_urb;
38433d6423SLionel Sambuc 	struct minix_usb_driver *drv;
39433d6423SLionel Sambuc 	gid_t gid;
40433d6423SLionel Sambuc };
41433d6423SLionel Sambuc 
42433d6423SLionel Sambuc struct minix_usb_driver {
43433d6423SLionel Sambuc 	endpoint_t ep;                       /* address of the client */
44433d6423SLionel Sambuc 
45433d6423SLionel Sambuc 	int status;                          /* In what state is the client? */
46433d6423SLionel Sambuc 
47433d6423SLionel Sambuc 	int dev;                          /* which device is this driver handling */
48433d6423SLionel Sambuc 	unsigned interfaces;                 /* which interfaces of the device the
49433d6423SLionel Sambuc 	                                        driver is handling */
50433d6423SLionel Sambuc 
51433d6423SLionel Sambuc 	struct ddekit_usb_urb *urbs[MAX_URBS]; /* pending urbs */
52433d6423SLionel Sambuc 
53433d6423SLionel Sambuc 	unsigned long urb_id;			     /* generation of driver_local urb_ids */
54433d6423SLionel Sambuc };
55433d6423SLionel Sambuc 
56433d6423SLionel Sambuc struct minix_usb_device {
57433d6423SLionel Sambuc 	struct ddekit_usb_dev *dev;
58433d6423SLionel Sambuc 	unsigned int interfaces;
59433d6423SLionel Sambuc };
60433d6423SLionel Sambuc 
61433d6423SLionel Sambuc static struct minix_usb_driver *find_driver(endpoint_t ep);
62433d6423SLionel Sambuc static struct minix_usb_driver *find_unused_driver(void);
63433d6423SLionel Sambuc static int add_to_pending_urbs(struct minix_usb_driver *drv, struct
64433d6423SLionel Sambuc 	ddekit_usb_urb *urb);
65433d6423SLionel Sambuc static int remove_from_pending_urbs(struct minix_usb_driver *drv,
66433d6423SLionel Sambuc 	struct ddekit_usb_urb *urb);
67433d6423SLionel Sambuc static struct ddekit_usb_urb * find_pending_urb(struct minix_usb_driver
68433d6423SLionel Sambuc 	*drv, unsigned urb_id);
69433d6423SLionel Sambuc static void register_driver(message *msg);
70433d6423SLionel Sambuc static struct ddekit_usb_urb *ddekit_usb_urb_from_mx_urb(struct usb_urb
71433d6423SLionel Sambuc 	*mx_urb);
72433d6423SLionel Sambuc static void submit_urb(message *msg);
73433d6423SLionel Sambuc static void cancle_urb(message *msg);
742d64210cSWojciech Zajac static void get_info(message *msg);
75433d6423SLionel Sambuc static void completion_callback(void *priv);
76433d6423SLionel Sambuc 
77433d6423SLionel Sambuc static void prepare_devman_usbdev(struct ddekit_usb_dev * dev, int
78433d6423SLionel Sambuc 	dev_id, unsigned int interfaces, struct devman_usb_dev *dudev);
79433d6423SLionel Sambuc static void device_disconnect_callback(struct ddekit_usb_dev * dev);
80433d6423SLionel Sambuc static int add_acl(int dev_id, unsigned interfaces, endpoint_t ep);
81433d6423SLionel Sambuc static int del_acl(int dev_id, unsigned interaces, endpoint_t ep);
82433d6423SLionel Sambuc static int handle_msg(message *msg);
83433d6423SLionel Sambuc static void _ddekit_usb_thread();
84433d6423SLionel Sambuc static void device_connect_callback(struct ddekit_usb_dev * dev,
85433d6423SLionel Sambuc 	unsigned int interfaces);
86433d6423SLionel Sambuc 
87433d6423SLionel Sambuc char *_ddekit_usb_get_manufacturer(struct ddekit_usb_dev *ddev);
88433d6423SLionel Sambuc char *_ddekit_usb_get_product(struct ddekit_usb_dev *ddev);
89433d6423SLionel Sambuc char *_ddekit_usb_get_serial(struct ddekit_usb_dev *ddev);
90433d6423SLionel Sambuc usb_device_descriptor_t *_ddekit_usb_get_device_desc(struct
91433d6423SLionel Sambuc 	ddekit_usb_dev *ddev);
92433d6423SLionel Sambuc usb_interface_descriptor_t *_ddekit_usb_get_interface_desc(struct
93433d6423SLionel Sambuc 	ddekit_usb_dev *ddev, int inum);
94433d6423SLionel Sambuc 
95433d6423SLionel Sambuc 
96433d6423SLionel Sambuc static ddekit_usb_malloc_fn my_malloc;
97433d6423SLionel Sambuc static ddekit_usb_free_fn my_free;
98433d6423SLionel Sambuc static struct minix_usb_driver gbl_drivers[MAX_DRIVERS];
99433d6423SLionel Sambuc static struct minix_usb_device _devices[MAX_DEVS];
100433d6423SLionel Sambuc 
101433d6423SLionel Sambuc static struct ddekit_usb_driver my_driver = {
102433d6423SLionel Sambuc 	.completion = completion_callback,
103433d6423SLionel Sambuc 	.connect    = device_connect_callback,
104433d6423SLionel Sambuc 	.disconnect = device_disconnect_callback,
105433d6423SLionel Sambuc };
106433d6423SLionel Sambuc 
107433d6423SLionel Sambuc 
108433d6423SLionel Sambuc /*****************************************************************************
109433d6423SLionel Sambuc  *         find_driver                                                       *
110433d6423SLionel Sambuc  ****************************************************************************/
find_driver(endpoint_t ep)111433d6423SLionel Sambuc static struct minix_usb_driver *find_driver(endpoint_t ep)
112433d6423SLionel Sambuc {
113433d6423SLionel Sambuc 	int i;
114433d6423SLionel Sambuc 	for (i = 0; i < MAX_DRIVERS; i++ ){
115433d6423SLionel Sambuc 		if (gbl_drivers[i].ep == ep) {
116433d6423SLionel Sambuc 			return &gbl_drivers[i];
117433d6423SLionel Sambuc 		}
118433d6423SLionel Sambuc 	}
119433d6423SLionel Sambuc 	return NULL;
120433d6423SLionel Sambuc }
121433d6423SLionel Sambuc 
122433d6423SLionel Sambuc /*****************************************************************************
123433d6423SLionel Sambuc  *         find_unused_driver                                                *
124433d6423SLionel Sambuc  ****************************************************************************/
find_unused_driver()125433d6423SLionel Sambuc static struct minix_usb_driver *find_unused_driver()
126433d6423SLionel Sambuc {
127433d6423SLionel Sambuc 	int i;
128433d6423SLionel Sambuc 	for (i = 0; i < MAX_DRIVERS; i++ ){
129433d6423SLionel Sambuc 		if (gbl_drivers[i].status == DRIVER_UNUSED) {
130433d6423SLionel Sambuc 			return &gbl_drivers[i];
131433d6423SLionel Sambuc 		}
132433d6423SLionel Sambuc 	}
133433d6423SLionel Sambuc 	return NULL;
134433d6423SLionel Sambuc }
135433d6423SLionel Sambuc 
136433d6423SLionel Sambuc /*****************************************************************************
137433d6423SLionel Sambuc  *         add_to_pending_urbs                                               *
138433d6423SLionel Sambuc  ****************************************************************************/
add_to_pending_urbs(struct minix_usb_driver * drv,struct ddekit_usb_urb * urb)139433d6423SLionel Sambuc static int add_to_pending_urbs(struct minix_usb_driver *drv,
140433d6423SLionel Sambuc                                struct ddekit_usb_urb *urb)
141433d6423SLionel Sambuc {
142433d6423SLionel Sambuc 	int i;
143433d6423SLionel Sambuc 
144433d6423SLionel Sambuc 	for (i = 0; i < MAX_URBS; i++) {
145433d6423SLionel Sambuc 		if (drv->urbs[i] == NULL) {
146433d6423SLionel Sambuc 			drv->urbs[i] = urb;
147433d6423SLionel Sambuc 			return 0;
148433d6423SLionel Sambuc 		}
149433d6423SLionel Sambuc 	}
150433d6423SLionel Sambuc 
151433d6423SLionel Sambuc 	return -1;
152433d6423SLionel Sambuc }
153433d6423SLionel Sambuc 
154433d6423SLionel Sambuc /*****************************************************************************
155433d6423SLionel Sambuc  *         remove_from_pending_urbs                                          *
156433d6423SLionel Sambuc  ****************************************************************************/
remove_from_pending_urbs(struct minix_usb_driver * drv,struct ddekit_usb_urb * urb)157433d6423SLionel Sambuc static int remove_from_pending_urbs(struct minix_usb_driver *drv,
158433d6423SLionel Sambuc                                struct ddekit_usb_urb *urb)
159433d6423SLionel Sambuc {
160433d6423SLionel Sambuc 	int i;
161433d6423SLionel Sambuc 
162433d6423SLionel Sambuc 	for (i = 0; i < MAX_URBS; i++) {
163433d6423SLionel Sambuc 		if (drv->urbs[i] == urb) {
164433d6423SLionel Sambuc 			drv->urbs[i] = NULL;
165433d6423SLionel Sambuc 			return 0;
166433d6423SLionel Sambuc 		}
167433d6423SLionel Sambuc 	}
168433d6423SLionel Sambuc 
169433d6423SLionel Sambuc 	return -1;
170433d6423SLionel Sambuc }
171433d6423SLionel Sambuc 
172433d6423SLionel Sambuc /*****************************************************************************
173433d6423SLionel Sambuc  *         find_pending_urb                                                  *
174433d6423SLionel Sambuc  ****************************************************************************/
find_pending_urb(struct minix_usb_driver * drv,unsigned urb_id)175433d6423SLionel Sambuc static struct ddekit_usb_urb * find_pending_urb(struct minix_usb_driver *drv,
176433d6423SLionel Sambuc                                                 unsigned urb_id)
177433d6423SLionel Sambuc {
178433d6423SLionel Sambuc 	int i;
179433d6423SLionel Sambuc 
180433d6423SLionel Sambuc 	for (i = 0; i < MAX_URBS; i++) {
181433d6423SLionel Sambuc 		if (((struct my_context*)drv->urbs[i]->priv)->urb_id == urb_id) {
182433d6423SLionel Sambuc 				return drv->urbs[i];
183433d6423SLionel Sambuc 		}
184433d6423SLionel Sambuc 	}
185433d6423SLionel Sambuc 
186433d6423SLionel Sambuc 	return NULL;
187433d6423SLionel Sambuc }
188433d6423SLionel Sambuc 
189433d6423SLionel Sambuc /*****************************************************************************
190433d6423SLionel Sambuc  *         register_driver                                                   *
191433d6423SLionel Sambuc  ****************************************************************************/
register_driver(message * msg)192433d6423SLionel Sambuc static void register_driver(message *msg)
193433d6423SLionel Sambuc {
194433d6423SLionel Sambuc 	endpoint_t ep = msg->m_source;
195433d6423SLionel Sambuc 	struct minix_usb_driver *drv;
196433d6423SLionel Sambuc 
197433d6423SLionel Sambuc 	msg->m_type=USB_REPLY;
198433d6423SLionel Sambuc 
199433d6423SLionel Sambuc 	if ( (drv = find_driver(ep)) != NULL) {
200433d6423SLionel Sambuc 		msg->m_type = USB_REPLY;
201433d6423SLionel Sambuc 		msg->USB_RESULT = OK;
202433d6423SLionel Sambuc 		ipc_send(ep,msg);
203433d6423SLionel Sambuc 	} else {
204433d6423SLionel Sambuc 		msg->m_type = USB_REPLY;
205433d6423SLionel Sambuc 		msg->USB_RESULT = EPERM;
206433d6423SLionel Sambuc 		ipc_send(ep,msg);
207433d6423SLionel Sambuc 		return;
208433d6423SLionel Sambuc 	}
209433d6423SLionel Sambuc 
210433d6423SLionel Sambuc 	DEBUG_MSG("DRIVER %d registered \n"
211433d6423SLionel Sambuc 	              "Announcing device %d, interfaces 0x%x\n",
212433d6423SLionel Sambuc 				  ep,
213433d6423SLionel Sambuc 				  drv->dev,
214433d6423SLionel Sambuc 				  drv->interfaces);
215433d6423SLionel Sambuc 
216433d6423SLionel Sambuc 	/* hand out the device */
217433d6423SLionel Sambuc 	msg->m_type = USB_ANNOUCE_DEV;
218433d6423SLionel Sambuc 	msg->USB_DEV_ID     = drv->dev;
219433d6423SLionel Sambuc 	msg->USB_INTERFACES = drv->interfaces;
220433d6423SLionel Sambuc 	ipc_send(ep, msg);
221433d6423SLionel Sambuc }
222433d6423SLionel Sambuc 
223433d6423SLionel Sambuc /*****************************************************************************
224433d6423SLionel Sambuc  *         deregister_driver                                                 *
225433d6423SLionel Sambuc  ****************************************************************************/
deregister_driver(message * msg)226433d6423SLionel Sambuc static void deregister_driver(message *msg)
227433d6423SLionel Sambuc {
228433d6423SLionel Sambuc 	endpoint_t ep = msg->m_source;
229433d6423SLionel Sambuc 
230433d6423SLionel Sambuc 	struct minix_usb_driver *drv;
231433d6423SLionel Sambuc 
232433d6423SLionel Sambuc 	msg->m_type=USB_REPLY;
233433d6423SLionel Sambuc 
234433d6423SLionel Sambuc 	if ( (drv = find_driver(ep)) == NULL) {
235433d6423SLionel Sambuc 		DEBUG_MSG("Non-registered driver tries to unregister.");
236433d6423SLionel Sambuc 		return;
237433d6423SLionel Sambuc 	} else {
238433d6423SLionel Sambuc 		/* do not accept requests for this client anymore! */
239433d6423SLionel Sambuc 		drv->status = DRIVER_UNUSED;
240433d6423SLionel Sambuc 
241433d6423SLionel Sambuc 		msg->USB_RESULT = 0;
242433d6423SLionel Sambuc 		asynsend3(ep, msg, AMF_NOREPLY);
243433d6423SLionel Sambuc 	}
244433d6423SLionel Sambuc }
245433d6423SLionel Sambuc 
246433d6423SLionel Sambuc /*****************************************************************************
247433d6423SLionel Sambuc  *         ddekit_usb_urb_from_mx_urb                                        *
248433d6423SLionel Sambuc  ****************************************************************************/
ddekit_usb_urb_from_mx_urb(struct usb_urb * mx_urb)249433d6423SLionel Sambuc static struct ddekit_usb_urb *ddekit_usb_urb_from_mx_urb(struct usb_urb *mx_urb)
250433d6423SLionel Sambuc {
251433d6423SLionel Sambuc 	/*
252433d6423SLionel Sambuc 	 * A helper function that generates (allocates and initializes)
253433d6423SLionel Sambuc 	 * a ddekit_usb_urb.
254433d6423SLionel Sambuc 	 */
255433d6423SLionel Sambuc 
256433d6423SLionel Sambuc 	struct ddekit_usb_urb *d_urb = (struct ddekit_usb_urb *)
257433d6423SLionel Sambuc 		my_malloc(sizeof(struct ddekit_usb_urb));
258433d6423SLionel Sambuc 
259433d6423SLionel Sambuc 	if (d_urb == NULL) {
260433d6423SLionel Sambuc 		return NULL;
261433d6423SLionel Sambuc 	}
262433d6423SLionel Sambuc 
263433d6423SLionel Sambuc 	d_urb->type           = mx_urb->type;
264433d6423SLionel Sambuc 	d_urb->direction      = mx_urb->direction;
265433d6423SLionel Sambuc 	d_urb->transfer_flags = mx_urb->transfer_flags;
266433d6423SLionel Sambuc 	d_urb->size           = mx_urb->size;
267433d6423SLionel Sambuc 	d_urb->data           = mx_urb->buffer;
268433d6423SLionel Sambuc 	d_urb->interval       = mx_urb->interval;
269433d6423SLionel Sambuc 	d_urb->endpoint       = mx_urb->endpoint;
270433d6423SLionel Sambuc 
271433d6423SLionel Sambuc 	if (d_urb->type == USB_TRANSFER_CTL) {
272433d6423SLionel Sambuc 		d_urb->setup_packet = mx_urb->setup_packet;
273433d6423SLionel Sambuc 	}
274433d6423SLionel Sambuc 	DEBUG_MSG("setup_package at %p", d_urb->setup_packet);
275433d6423SLionel Sambuc 
276433d6423SLionel Sambuc 	if (d_urb->type == USB_TRANSFER_ISO) {
277433d6423SLionel Sambuc 		d_urb->iso_desc  = (struct ddekit_usb_iso_packet_desc *)
278433d6423SLionel Sambuc 		    mx_urb->buffer + mx_urb->iso_desc_offset;
279433d6423SLionel Sambuc 		d_urb->number_of_packets = mx_urb->number_of_packets;
280433d6423SLionel Sambuc 	}
281433d6423SLionel Sambuc 
282433d6423SLionel Sambuc 	return d_urb;
283433d6423SLionel Sambuc }
284433d6423SLionel Sambuc 
285433d6423SLionel Sambuc /*****************************************************************************
286433d6423SLionel Sambuc  *         submit_urb                                                        *
287433d6423SLionel Sambuc  ****************************************************************************/
submit_urb(message * msg)288433d6423SLionel Sambuc static void submit_urb(message *msg)
289433d6423SLionel Sambuc {
290433d6423SLionel Sambuc 	/*
291433d6423SLionel Sambuc 	 * submit_urb
292433d6423SLionel Sambuc 	 *
293433d6423SLionel Sambuc 	 * Handles a submit_urb from a minix USB device driver. It copies the
294433d6423SLionel Sambuc 	 * usb_urb structure containing the buffers and generates and tries to
295433d6423SLionel Sambuc 	 * submit a ddekit_usb_urb. The reference to the ddekit_usb_urb is stored
296433d6423SLionel Sambuc 	 * in the driver structure in order to be able to cancle the URB on the
297433d6423SLionel Sambuc 	 * clients request.
298433d6423SLionel Sambuc 	 */
299433d6423SLionel Sambuc 	endpoint_t ep = msg->m_source;
300433d6423SLionel Sambuc 	struct minix_usb_driver *drv;
301433d6423SLionel Sambuc 
302433d6423SLionel Sambuc 	/* find driver */
303433d6423SLionel Sambuc 	if ( (drv = find_driver(ep)) == NULL) {
304433d6423SLionel Sambuc 		DEBUG_MSG("Non-registered driver tries to send URB.");
305433d6423SLionel Sambuc 		return;
306433d6423SLionel Sambuc 	} else {
307433d6423SLionel Sambuc 
308433d6423SLionel Sambuc 		int res;
309*0a6a1f1dSLionel Sambuc 		struct my_context *ctx = NULL;
310*0a6a1f1dSLionel Sambuc 		struct ddekit_usb_urb *d_urb = NULL;
311433d6423SLionel Sambuc 
312433d6423SLionel Sambuc 		struct usb_urb *mx_urb  = (struct usb_urb*)
313433d6423SLionel Sambuc 		    my_malloc(msg->USB_GRANT_SIZE+sizeof(void *));
314433d6423SLionel Sambuc 
315433d6423SLionel Sambuc 		if (mx_urb == NULL) {
316433d6423SLionel Sambuc 			DEBUG_MSG("Can't allocat mem for mx_urb.");
317433d6423SLionel Sambuc 			res = ENOMEM;
318433d6423SLionel Sambuc 			goto out;
319433d6423SLionel Sambuc 		}
320433d6423SLionel Sambuc 
321433d6423SLionel Sambuc 		/* copy in URB */
322433d6423SLionel Sambuc 		res = sys_safecopyfrom(ep, msg->USB_GRANT_ID, 0,
323433d6423SLionel Sambuc 		    (vir_bytes) &mx_urb->dev_id, msg->USB_GRANT_SIZE);
324433d6423SLionel Sambuc 
325433d6423SLionel Sambuc 		if (res != 0) {
326433d6423SLionel Sambuc 			DEBUG_MSG("sys_safecopyfrom failed ");
327433d6423SLionel Sambuc 			my_free(mx_urb);
328433d6423SLionel Sambuc 			res = EINVAL;
329433d6423SLionel Sambuc 			goto out;
330433d6423SLionel Sambuc 		}
331433d6423SLionel Sambuc 
332433d6423SLionel Sambuc 		DEBUG_MSG("URB type: %d", mx_urb->type);
333433d6423SLionel Sambuc 		/* check if urb is valid */
334dc007724SJacob Adams 		if (mx_urb->dev_id >= MAX_DEVS || mx_urb->dev_id < 0) {
335433d6423SLionel Sambuc 			DEBUG_MSG("Bogus device ID.");
336433d6423SLionel Sambuc 			res = EINVAL;
337433d6423SLionel Sambuc 			goto out;
338433d6423SLionel Sambuc 		}
339433d6423SLionel Sambuc 
340433d6423SLionel Sambuc 		/* create ddekit_usb_urb */
341*0a6a1f1dSLionel Sambuc 		d_urb = ddekit_usb_urb_from_mx_urb(mx_urb);
342433d6423SLionel Sambuc 		d_urb->dev = _devices[drv->dev].dev;
343433d6423SLionel Sambuc 		/* submit urb */
344433d6423SLionel Sambuc 
345433d6423SLionel Sambuc 		if (!d_urb) {
346433d6423SLionel Sambuc 			res = ENOMEM;
347433d6423SLionel Sambuc 			goto out;
348433d6423SLionel Sambuc 		}
349433d6423SLionel Sambuc 
350*0a6a1f1dSLionel Sambuc 		ctx = my_malloc(sizeof(struct my_context));
351433d6423SLionel Sambuc 
352433d6423SLionel Sambuc 		if(!ctx) {
353433d6423SLionel Sambuc 			res = ENOMEM;
354433d6423SLionel Sambuc 			goto out;
355433d6423SLionel Sambuc 		}
356433d6423SLionel Sambuc 
357433d6423SLionel Sambuc 		ctx->drv       = drv;
358433d6423SLionel Sambuc 		ctx->urb_id    = drv->urb_id++;
359433d6423SLionel Sambuc 		mx_urb->urb_id = ctx->urb_id;
360433d6423SLionel Sambuc 		ctx->mx_urb    = mx_urb;
361433d6423SLionel Sambuc 		ctx->d_urb     = d_urb;
362433d6423SLionel Sambuc 		ctx->gid       = msg->USB_GRANT_ID;
363433d6423SLionel Sambuc 
364433d6423SLionel Sambuc 		DEBUG_MSG("ctx: %p, urb_id: %d, d_urb: %p, mx_urb: %p, drv: %d, gid: %d ",
365433d6423SLionel Sambuc 		    ctx, ctx->urb_id, ctx->d_urb, ctx->mx_urb, ctx->drv, ctx->gid);
366433d6423SLionel Sambuc 
367433d6423SLionel Sambuc 		d_urb->priv = ctx;
368433d6423SLionel Sambuc 
369433d6423SLionel Sambuc 		res = add_to_pending_urbs(drv, d_urb);
370433d6423SLionel Sambuc 
371433d6423SLionel Sambuc 		if (res == 0) {
372433d6423SLionel Sambuc 			DEBUG_MSG("submitting urb...");
373433d6423SLionel Sambuc 			res = ddekit_usb_submit_urb(d_urb);
374433d6423SLionel Sambuc 			if(res) {
375433d6423SLionel Sambuc 				DEBUG_MSG("submitting urb failed (err: %d)", res);
376433d6423SLionel Sambuc 				remove_from_pending_urbs(drv, d_urb);
377433d6423SLionel Sambuc 			}
378433d6423SLionel Sambuc 		}
379433d6423SLionel Sambuc 
380433d6423SLionel Sambuc out:
381433d6423SLionel Sambuc 		/* reply */
382433d6423SLionel Sambuc 		msg->m_type     = USB_REPLY;
383433d6423SLionel Sambuc 		msg->USB_URB_ID = mx_urb->urb_id;
384433d6423SLionel Sambuc 		msg->USB_RESULT = res;
385433d6423SLionel Sambuc 
386433d6423SLionel Sambuc 		if(res != 0) {
387433d6423SLionel Sambuc 
388433d6423SLionel Sambuc 			if (mx_urb != NULL) {
389433d6423SLionel Sambuc 				my_free(mx_urb);
390433d6423SLionel Sambuc 			}
391433d6423SLionel Sambuc 			if (ctx != NULL) {
392433d6423SLionel Sambuc 				my_free(ctx);
393433d6423SLionel Sambuc 			}
394433d6423SLionel Sambuc 
395433d6423SLionel Sambuc 			if (d_urb != NULL) {
396433d6423SLionel Sambuc 				my_free(d_urb);
397433d6423SLionel Sambuc 			}
398433d6423SLionel Sambuc 
399433d6423SLionel Sambuc 		}
400433d6423SLionel Sambuc 
401433d6423SLionel Sambuc 		/* send reply */
402433d6423SLionel Sambuc 		ipc_send(ep, msg);
403433d6423SLionel Sambuc 	}
404433d6423SLionel Sambuc }
405433d6423SLionel Sambuc 
406433d6423SLionel Sambuc 
407433d6423SLionel Sambuc /*
408433d6423SLionel Sambuc  * cancle_urb
409433d6423SLionel Sambuc  *
410433d6423SLionel Sambuc  * Cancels the submission of an URB identified by a URB_id
411433d6423SLionel Sambuc  */
412433d6423SLionel Sambuc /*****************************************************************************
413433d6423SLionel Sambuc  *         cancle_urb                                                        *
414433d6423SLionel Sambuc  ****************************************************************************/
cancle_urb(message * msg)415433d6423SLionel Sambuc static void cancle_urb(message *msg)
416433d6423SLionel Sambuc {
417433d6423SLionel Sambuc 	endpoint_t ep = msg->m_source;
418433d6423SLionel Sambuc 
419433d6423SLionel Sambuc 	struct minix_usb_driver *drv;
420433d6423SLionel Sambuc 
421433d6423SLionel Sambuc 	msg->USB_RESULT = -1;
422433d6423SLionel Sambuc 	msg->m_type = USB_REPLY;
423433d6423SLionel Sambuc 
424433d6423SLionel Sambuc 	/* find driver */
425433d6423SLionel Sambuc 	if ( (drv = find_driver(ep)) == NULL) {
426433d6423SLionel Sambuc 		DEBUG_MSG("Non-registered driver tries to cancel URB.");
427433d6423SLionel Sambuc 		return;
428433d6423SLionel Sambuc 	} else {
429433d6423SLionel Sambuc 		struct ddekit_usb_urb *d_urb = NULL;
430433d6423SLionel Sambuc 
431433d6423SLionel Sambuc 		d_urb = find_pending_urb(drv, msg->USB_URB_ID);
432433d6423SLionel Sambuc 
433433d6423SLionel Sambuc 		if (d_urb != NULL) {
434433d6423SLionel Sambuc 			ddekit_usb_cancle_urb(d_urb);
435433d6423SLionel Sambuc 			msg->USB_RESULT = 0;
436433d6423SLionel Sambuc 		} else {
437433d6423SLionel Sambuc 			DEBUG_MSG("No URB to cancle");
438433d6423SLionel Sambuc 			msg->USB_RESULT = ENODEV;
439433d6423SLionel Sambuc 		}
440433d6423SLionel Sambuc 	}
441433d6423SLionel Sambuc 
442433d6423SLionel Sambuc 	ipc_send(ep, msg);
443433d6423SLionel Sambuc }
444433d6423SLionel Sambuc 
445433d6423SLionel Sambuc 
446433d6423SLionel Sambuc /*****************************************************************************
4472d64210cSWojciech Zajac  *         get_info                                                          *
4482d64210cSWojciech Zajac  *****************************************************************************/
4492d64210cSWojciech Zajac static void
get_info(message * msg)4502d64210cSWojciech Zajac get_info(message * msg)
4512d64210cSWojciech Zajac {
4522d64210cSWojciech Zajac 	struct minix_usb_driver * drv;
4532d64210cSWojciech Zajac 	endpoint_t ep;
4542d64210cSWojciech Zajac 	long info_type;
4552d64210cSWojciech Zajac 	long info_value;
4562d64210cSWojciech Zajac 
4572d64210cSWojciech Zajac 	/* Read */
4582d64210cSWojciech Zajac 	ep		= msg->m_source;
4592d64210cSWojciech Zajac 	info_type	= msg->USB_INFO_TYPE;
4602d64210cSWojciech Zajac 	info_value	= msg->USB_INFO_VALUE;
4612d64210cSWojciech Zajac 
4622d64210cSWojciech Zajac 	/* Reuse as reply */
4632d64210cSWojciech Zajac 	msg->m_type	= USB_REPLY;
4642d64210cSWojciech Zajac 	msg->USB_RESULT	= -1;
4652d64210cSWojciech Zajac 
4662d64210cSWojciech Zajac 	/* Try and find driver first */
4672d64210cSWojciech Zajac 	if (NULL == (drv = find_driver(ep)))
4682d64210cSWojciech Zajac 		ddekit_printf("Non-registered driver tries to send info");
4692d64210cSWojciech Zajac 	else
4702d64210cSWojciech Zajac 		/* Route info to device */
4712d64210cSWojciech Zajac 		msg->USB_RESULT = ddekit_usb_info(_devices[drv->dev].dev,
4722d64210cSWojciech Zajac 						info_type, info_value);
4732d64210cSWojciech Zajac 
4742d64210cSWojciech Zajac 	/* Reply */
4752d64210cSWojciech Zajac 	ipc_send(ep, msg);
4762d64210cSWojciech Zajac }
4772d64210cSWojciech Zajac 
4782d64210cSWojciech Zajac 
4792d64210cSWojciech Zajac /*****************************************************************************
480433d6423SLionel Sambuc  *         completion_callback                                               *
481433d6423SLionel Sambuc  ****************************************************************************/
completion_callback(void * priv)482433d6423SLionel Sambuc static void completion_callback(void *priv)
483433d6423SLionel Sambuc {
484433d6423SLionel Sambuc 	/*
485433d6423SLionel Sambuc 	 * completion_callback
486433d6423SLionel Sambuc 	 *
487433d6423SLionel Sambuc 	 * This is called by the DDE side. Here the data is copied back to
488433d6423SLionel Sambuc 	 * the driver and a message is send to inform the driver about the
489433d6423SLionel Sambuc 	 * completion.
490433d6423SLionel Sambuc 	 */
491433d6423SLionel Sambuc 	message msg;
492433d6423SLionel Sambuc 	int res;
493433d6423SLionel Sambuc 	struct my_context *ctx       = (struct my_context *)priv;
494433d6423SLionel Sambuc 	struct usb_urb *mx_urb       = ctx->mx_urb;
495433d6423SLionel Sambuc 	struct ddekit_usb_urb *d_urb = ctx->d_urb;
496433d6423SLionel Sambuc 	struct minix_usb_driver *drv = ctx->drv;
497433d6423SLionel Sambuc 
498433d6423SLionel Sambuc 	DEBUG_MSG("ctx: %p, urb_id: %d, d_urb: %p, mx_urb: %p, drv: %d, gid: %d ",
499433d6423SLionel Sambuc 		    ctx, ctx->urb_id, ctx->d_urb, ctx->mx_urb, ctx->drv, ctx->gid);
500433d6423SLionel Sambuc 
501433d6423SLionel Sambuc 	/* update data in minix URB */
502433d6423SLionel Sambuc 	mx_urb->status          = d_urb->status;
503433d6423SLionel Sambuc 	mx_urb->actual_length   = d_urb->actual_length;
504433d6423SLionel Sambuc 	mx_urb->error_count     = d_urb->error_count;
505433d6423SLionel Sambuc 	mx_urb->transfer_flags  = d_urb->transfer_flags;
506433d6423SLionel Sambuc 
507433d6423SLionel Sambuc 	remove_from_pending_urbs(drv, d_urb);
508433d6423SLionel Sambuc 
509433d6423SLionel Sambuc 	/* copy out URB */
510433d6423SLionel Sambuc 	res = sys_safecopyto(drv->ep, ctx->gid, 0,
511433d6423SLionel Sambuc 	    (vir_bytes) ((char*)mx_urb) + sizeof(void*),
512433d6423SLionel Sambuc 		mx_urb->urb_size - sizeof(void*));
513433d6423SLionel Sambuc 
514433d6423SLionel Sambuc 	if (res != 0) {
515433d6423SLionel Sambuc 		DEBUG_MSG("Copy out failed: %d", res);
516433d6423SLionel Sambuc 		DEBUG_MSG(" URB ID: %d, Grant-ID: %d, Grant-size: %d", ctx->urb_id,
517433d6423SLionel Sambuc 		            ctx->gid, mx_urb->urb_size);
518433d6423SLionel Sambuc 	}
519433d6423SLionel Sambuc 
520433d6423SLionel Sambuc 	/* send message to client */
521433d6423SLionel Sambuc 	msg.m_type     = USB_COMPLETE_URB;
522433d6423SLionel Sambuc 	msg.USB_URB_ID = ctx->urb_id;
523433d6423SLionel Sambuc 	asynsend3(drv->ep, &msg, AMF_NOREPLY);
524433d6423SLionel Sambuc 
525433d6423SLionel Sambuc 	/* free stuff */
526433d6423SLionel Sambuc 	my_free(ctx);
527433d6423SLionel Sambuc 	my_free(mx_urb);
528433d6423SLionel Sambuc 	my_free(d_urb);
529433d6423SLionel Sambuc }
530433d6423SLionel Sambuc 
531433d6423SLionel Sambuc 
532433d6423SLionel Sambuc /*****************************************************************************
533433d6423SLionel Sambuc  *         prepare_devman_usbdev                                             *
534433d6423SLionel Sambuc  ****************************************************************************/
prepare_devman_usbdev(struct ddekit_usb_dev * dev,int dev_id,unsigned int interfaces,struct devman_usb_dev * dudev)535433d6423SLionel Sambuc static void prepare_devman_usbdev
536433d6423SLionel Sambuc (struct ddekit_usb_dev * dev, int dev_id, unsigned int interfaces,
537433d6423SLionel Sambuc  struct devman_usb_dev *dudev)
538433d6423SLionel Sambuc {
539433d6423SLionel Sambuc 	int j;
540433d6423SLionel Sambuc 	int intf_count;
541433d6423SLionel Sambuc 	/*
542433d6423SLionel Sambuc 	 * currently this is only implemented by stub driver
543433d6423SLionel Sambuc 	 */
544433d6423SLionel Sambuc 
545433d6423SLionel Sambuc 	usb_device_descriptor_t *desc = _ddekit_usb_get_device_desc(dev);
546433d6423SLionel Sambuc 
547433d6423SLionel Sambuc 	dudev->manufacturer = _ddekit_usb_get_manufacturer(dev);
548433d6423SLionel Sambuc 	dudev->product = _ddekit_usb_get_product(dev);
549433d6423SLionel Sambuc 	dudev->serial = _ddekit_usb_get_serial(dev);
550433d6423SLionel Sambuc 
551433d6423SLionel Sambuc 	dudev->desc = desc;
552433d6423SLionel Sambuc 
553433d6423SLionel Sambuc 	intf_count = 0;
554433d6423SLionel Sambuc 
555433d6423SLionel Sambuc 	for (j=0; j < 32; j++) {
556433d6423SLionel Sambuc 		if (interfaces & (1 << j)) {
557433d6423SLionel Sambuc 				dudev->interfaces[intf_count++].desc =
558433d6423SLionel Sambuc 				   _ddekit_usb_get_interface_desc(dev, j);
559433d6423SLionel Sambuc 		}
560433d6423SLionel Sambuc 	}
561433d6423SLionel Sambuc 
562433d6423SLionel Sambuc 	dudev->intf_count = intf_count;
563433d6423SLionel Sambuc 	dudev->dev_id     = dev_id;
564433d6423SLionel Sambuc }
565433d6423SLionel Sambuc 
566433d6423SLionel Sambuc /*****************************************************************************
567433d6423SLionel Sambuc  *         device_connect_callback                                           *
568433d6423SLionel Sambuc  ****************************************************************************/
569433d6423SLionel Sambuc static void
device_connect_callback(struct ddekit_usb_dev * dev,unsigned int interfaces)570433d6423SLionel Sambuc device_connect_callback
571433d6423SLionel Sambuc (struct ddekit_usb_dev * dev, unsigned int interfaces) {
572433d6423SLionel Sambuc 
573433d6423SLionel Sambuc 	int i, res;
574433d6423SLionel Sambuc 
575433d6423SLionel Sambuc 	/* add to device list */
576433d6423SLionel Sambuc 	for (i=0; i < MAX_DEVS; i++) {
577433d6423SLionel Sambuc 		if (_devices[i].dev == NULL)
578433d6423SLionel Sambuc 			break;
579433d6423SLionel Sambuc 	}
580433d6423SLionel Sambuc 
581433d6423SLionel Sambuc 	if (i >= MAX_DEVS) {
582433d6423SLionel Sambuc 		DEBUG_MSG("Too much devices...");
583433d6423SLionel Sambuc 	} else {
584433d6423SLionel Sambuc 		_devices[i].dev = dev;
585433d6423SLionel Sambuc 		_devices[i].interfaces = (1 << interfaces);
586433d6423SLionel Sambuc 	}
587433d6423SLionel Sambuc 
588433d6423SLionel Sambuc 	struct devman_usb_dev *dudev;
589433d6423SLionel Sambuc 
590433d6423SLionel Sambuc 	dudev = devman_usb_device_new(i);
591433d6423SLionel Sambuc 
592433d6423SLionel Sambuc 	prepare_devman_usbdev(dev, i, interfaces, dudev);
593433d6423SLionel Sambuc 
594433d6423SLionel Sambuc 	if (dudev == NULL) {
595433d6423SLionel Sambuc 		/* TODO: ERROR */
596433d6423SLionel Sambuc 		printf("ERROR: !");
597433d6423SLionel Sambuc 	}
598433d6423SLionel Sambuc 
599433d6423SLionel Sambuc 	ddekit_usb_dev_set_data(dev, dudev);
600433d6423SLionel Sambuc 
601433d6423SLionel Sambuc 	res = devman_usb_device_add(dudev);
602433d6423SLionel Sambuc 
603433d6423SLionel Sambuc 	if (res != 0) {
604433d6423SLionel Sambuc 		/* TODO: Error*/
605433d6423SLionel Sambuc 		printf("ERROR!");
606433d6423SLionel Sambuc 	}
607433d6423SLionel Sambuc }
608433d6423SLionel Sambuc 
609433d6423SLionel Sambuc /*****************************************************************************
610433d6423SLionel Sambuc  *         device_disconnect_callback                                        *
611433d6423SLionel Sambuc  ****************************************************************************/
device_disconnect_callback(struct ddekit_usb_dev * dev)612433d6423SLionel Sambuc static void device_disconnect_callback(struct ddekit_usb_dev * dev)
613433d6423SLionel Sambuc {
614433d6423SLionel Sambuc 	int i;
615433d6423SLionel Sambuc 
616433d6423SLionel Sambuc 	/* remove ACL entry */
617433d6423SLionel Sambuc 	for (i = 0; i< MAX_DRIVERS; i++) {
618433d6423SLionel Sambuc 		if (gbl_drivers[i].dev != INVAL_DEV
619433d6423SLionel Sambuc 			&& _devices[gbl_drivers[i].dev].dev == dev) {
620433d6423SLionel Sambuc 			struct minix_usb_driver *drv = &gbl_drivers[i];
621433d6423SLionel Sambuc 			drv->ep     = 0;
622433d6423SLionel Sambuc 			drv->status = DRIVER_UNUSED;
623433d6423SLionel Sambuc 			drv->dev    = INVAL_DEV;
624433d6423SLionel Sambuc 		}
625433d6423SLionel Sambuc 	}
626433d6423SLionel Sambuc 
627433d6423SLionel Sambuc 	for (i=0; i < MAX_DEVS; i++) {
628433d6423SLionel Sambuc 		if (_devices[i].dev == dev) {
629433d6423SLionel Sambuc 			_devices[i].dev = NULL;
630433d6423SLionel Sambuc 			_devices[i].interfaces = 0;
631433d6423SLionel Sambuc 		}
632433d6423SLionel Sambuc 	}
633433d6423SLionel Sambuc 
634433d6423SLionel Sambuc 
635433d6423SLionel Sambuc 	/* get the devman device */
636433d6423SLionel Sambuc 	struct devman_usb_dev * dudev = NULL;
637433d6423SLionel Sambuc 
638433d6423SLionel Sambuc 	dudev = ddekit_usb_dev_get_data(dev);
639433d6423SLionel Sambuc 
640433d6423SLionel Sambuc 	if (dudev == NULL) {
641433d6423SLionel Sambuc 		/* TODO: error */
642433d6423SLionel Sambuc 	}
643433d6423SLionel Sambuc 
644433d6423SLionel Sambuc 	devman_usb_device_remove(dudev);
645433d6423SLionel Sambuc 
646433d6423SLionel Sambuc 	/* free the devman dev */
647433d6423SLionel Sambuc 	devman_usb_device_delete(dudev);
648433d6423SLionel Sambuc }
649433d6423SLionel Sambuc 
650433d6423SLionel Sambuc 
651433d6423SLionel Sambuc /*****************************************************************************
652433d6423SLionel Sambuc  *         add_acl                                                           *
653433d6423SLionel Sambuc  ****************************************************************************/
add_acl(int dev_id,unsigned interfaces,endpoint_t ep)654433d6423SLionel Sambuc static int add_acl(int dev_id, unsigned interfaces, endpoint_t ep)
655433d6423SLionel Sambuc {
656433d6423SLionel Sambuc 	/*
657433d6423SLionel Sambuc 	 * This functions binds a specific USB interface to a client.
658433d6423SLionel Sambuc 	 */
659433d6423SLionel Sambuc 	int i;
660433d6423SLionel Sambuc 	struct minix_usb_driver *drv;
661433d6423SLionel Sambuc 
662433d6423SLionel Sambuc 	if (_devices[dev_id].dev == NULL) {
663433d6423SLionel Sambuc 		/* if no device with that ID */
664433d6423SLionel Sambuc 		return  ENODEV;
665433d6423SLionel Sambuc 	}
666433d6423SLionel Sambuc 
667433d6423SLionel Sambuc 	/* is the device allready given to a client*/
668433d6423SLionel Sambuc 	for (i = 0; i< MAX_DRIVERS; i++) {
669433d6423SLionel Sambuc 		if (gbl_drivers[i].status != DRIVER_UNUSED &&
670433d6423SLionel Sambuc 			gbl_drivers[i].dev == dev_id) {
671433d6423SLionel Sambuc 			printf("devid: %d\n", dev_id);
672433d6423SLionel Sambuc 			return EBUSY;
673433d6423SLionel Sambuc 		}
674433d6423SLionel Sambuc 	}
675433d6423SLionel Sambuc 
676433d6423SLionel Sambuc 	/* bind device to client */
677433d6423SLionel Sambuc 	drv = find_unused_driver();
678433d6423SLionel Sambuc 
679433d6423SLionel Sambuc 	if (drv == NULL) {
680433d6423SLionel Sambuc 		return ENOMEM;
681433d6423SLionel Sambuc 	}
682433d6423SLionel Sambuc 
683433d6423SLionel Sambuc 	drv->status     = DRIVER_BOUND;
684433d6423SLionel Sambuc 	drv->dev        = dev_id;
685433d6423SLionel Sambuc 	drv->interfaces = 1 << interfaces;
686433d6423SLionel Sambuc 	drv->ep         = ep;
687433d6423SLionel Sambuc 	drv->urb_id     = 0;
688433d6423SLionel Sambuc 
689433d6423SLionel Sambuc 	return OK;
690433d6423SLionel Sambuc }
691433d6423SLionel Sambuc 
692433d6423SLionel Sambuc /*****************************************************************************
693433d6423SLionel Sambuc  *         del_acl                                                           *
694433d6423SLionel Sambuc  ****************************************************************************/
del_acl(int dev_id,unsigned interfaces,endpoint_t ep)695433d6423SLionel Sambuc static int del_acl(int dev_id, unsigned interfaces, endpoint_t ep)
696433d6423SLionel Sambuc {
697433d6423SLionel Sambuc 	struct minix_usb_driver *drv;
698433d6423SLionel Sambuc 	int dev, withdraw = 0;
699433d6423SLionel Sambuc 	message msg;
700433d6423SLionel Sambuc 
701433d6423SLionel Sambuc 	/* find driver */
702433d6423SLionel Sambuc 	drv = find_driver(ep);
703433d6423SLionel Sambuc 
704433d6423SLionel Sambuc 	if (drv == NULL) {
705433d6423SLionel Sambuc 		return  ENOENT;
706433d6423SLionel Sambuc 	}
707433d6423SLionel Sambuc 
708433d6423SLionel Sambuc 	dev = drv->dev;
709433d6423SLionel Sambuc 
710433d6423SLionel Sambuc 	if (drv->status == DRIVER_ACTIVE) {
711433d6423SLionel Sambuc 		withdraw = 1;
712433d6423SLionel Sambuc 	}
713433d6423SLionel Sambuc 
714433d6423SLionel Sambuc 	drv->ep    = 0;
715433d6423SLionel Sambuc 	drv->status = DRIVER_UNUSED;
716433d6423SLionel Sambuc 	drv->dev   = INVAL_DEV;
717433d6423SLionel Sambuc 
718433d6423SLionel Sambuc 	if (withdraw) {
719433d6423SLionel Sambuc 		msg.m_type     = USB_WITHDRAW_DEV;
720433d6423SLionel Sambuc 		msg.USB_DEV_ID = dev;
721433d6423SLionel Sambuc 		asynsend3(ep, &msg, AMF_NOREPLY);
722433d6423SLionel Sambuc 	}
723433d6423SLionel Sambuc 
724433d6423SLionel Sambuc 	return 0;
725433d6423SLionel Sambuc }
726433d6423SLionel Sambuc 
727433d6423SLionel Sambuc /*****************************************************************************
728433d6423SLionel Sambuc  *         handle_msg                                                        *
729433d6423SLionel Sambuc  ****************************************************************************/
handle_msg(message * msg)730433d6423SLionel Sambuc static int handle_msg(message *msg)
731433d6423SLionel Sambuc {
732433d6423SLionel Sambuc 	/*
733433d6423SLionel Sambuc 	 * handle_msg
734433d6423SLionel Sambuc 	 *
735433d6423SLionel Sambuc 	 * The dispatcher for USB related messages.
736433d6423SLionel Sambuc 	 */
737433d6423SLionel Sambuc 
738433d6423SLionel Sambuc 	switch(msg->m_type) {
739433d6423SLionel Sambuc 		case USB_RQ_INIT:
740433d6423SLionel Sambuc 			register_driver(msg);
741433d6423SLionel Sambuc 			return 1;
742433d6423SLionel Sambuc 		case USB_RQ_DEINIT:
743433d6423SLionel Sambuc 			deregister_driver(msg);
744433d6423SLionel Sambuc 			return 1;
745433d6423SLionel Sambuc 		case USB_RQ_SEND_URB:
746433d6423SLionel Sambuc 			submit_urb(msg);
747433d6423SLionel Sambuc 			return 1;
748433d6423SLionel Sambuc 		case USB_RQ_CANCEL_URB:
749433d6423SLionel Sambuc 			cancle_urb(msg);
750433d6423SLionel Sambuc 			return 1;
7512d64210cSWojciech Zajac 		case USB_RQ_SEND_INFO:
7522d64210cSWojciech Zajac 			get_info(msg);
7532d64210cSWojciech Zajac 			return 1;
754433d6423SLionel Sambuc 		default:
755433d6423SLionel Sambuc 			return 0;
756433d6423SLionel Sambuc 	}
757433d6423SLionel Sambuc }
758433d6423SLionel Sambuc 
759433d6423SLionel Sambuc /*****************************************************************************
760433d6423SLionel Sambuc  *         devman_tread                                                      *
761433d6423SLionel Sambuc  ****************************************************************************/
devman_thread(void * unused)762433d6423SLionel Sambuc static void devman_thread(void *unused)
763433d6423SLionel Sambuc {
764433d6423SLionel Sambuc 	struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(DEVMAN_BASE,
765433d6423SLionel Sambuc 	    DEVMAN_BASE + 0xff);
766433d6423SLionel Sambuc 	int ipc_status;
767433d6423SLionel Sambuc 	message m;
768433d6423SLionel Sambuc 	while (1) {
769433d6423SLionel Sambuc 		ddekit_minix_rcv(mq, &m, &ipc_status);
770433d6423SLionel Sambuc 		devman_handle_msg(&m);
771433d6423SLionel Sambuc 	}
772433d6423SLionel Sambuc }
773433d6423SLionel Sambuc 
774433d6423SLionel Sambuc /*****************************************************************************
775433d6423SLionel Sambuc  *         _ddekit_usb_thread                                                *
776433d6423SLionel Sambuc  ****************************************************************************/
_ddekit_usb_thread(void * unused)777433d6423SLionel Sambuc static void _ddekit_usb_thread(void * unused)
778433d6423SLionel Sambuc {
779433d6423SLionel Sambuc 	struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(USB_BASE,
780433d6423SLionel Sambuc 	    USB_BASE + 0xff);
781433d6423SLionel Sambuc 
782433d6423SLionel Sambuc 	message m;
783433d6423SLionel Sambuc 	int ipc_status;
784433d6423SLionel Sambuc 
785433d6423SLionel Sambuc 	/* create devman thread */
786*0a6a1f1dSLionel Sambuc 	ddekit_thread_t * __unused dmth;
787433d6423SLionel Sambuc 
788433d6423SLionel Sambuc 	dmth = ddekit_thread_create(devman_thread, NULL, "devman_thread");
789433d6423SLionel Sambuc 
790433d6423SLionel Sambuc 	while (1) {
791433d6423SLionel Sambuc 		ddekit_minix_rcv(mq, &m, &ipc_status);
792433d6423SLionel Sambuc 		handle_msg(&m);
793433d6423SLionel Sambuc 	}
794433d6423SLionel Sambuc }
795433d6423SLionel Sambuc 
796433d6423SLionel Sambuc 
797433d6423SLionel Sambuc /*****************************************************************************
798433d6423SLionel Sambuc  *         bind_cb                                                           *
799433d6423SLionel Sambuc  ****************************************************************************/
bind_cb(struct devman_usb_bind_cb_data * data,endpoint_t ep)800433d6423SLionel Sambuc static int bind_cb (struct devman_usb_bind_cb_data *data, endpoint_t ep)
801433d6423SLionel Sambuc {
802433d6423SLionel Sambuc 	if(data) {
803433d6423SLionel Sambuc 		return add_acl(data->dev_id, data->interface, ep);
804433d6423SLionel Sambuc 	} else {
805433d6423SLionel Sambuc 		printf("warning: missing cb_data!\n");
806433d6423SLionel Sambuc 		return EINVAL;
807433d6423SLionel Sambuc 	}
808433d6423SLionel Sambuc }
809433d6423SLionel Sambuc 
810433d6423SLionel Sambuc /*****************************************************************************
811433d6423SLionel Sambuc  *         unbind_cb                                                         *
812433d6423SLionel Sambuc  ****************************************************************************/
unbind_cb(struct devman_usb_bind_cb_data * data,endpoint_t ep)813433d6423SLionel Sambuc static int unbind_cb (struct devman_usb_bind_cb_data *data, endpoint_t ep)
814433d6423SLionel Sambuc {
815433d6423SLionel Sambuc 	if(data) {
816433d6423SLionel Sambuc 		return del_acl(data->dev_id, data->interface, ep);
817433d6423SLionel Sambuc 	} else {
818433d6423SLionel Sambuc 		printf("warning: missing cb_data!\n");
819433d6423SLionel Sambuc 		return EINVAL;
820433d6423SLionel Sambuc 	}
821433d6423SLionel Sambuc }
822433d6423SLionel Sambuc 
823433d6423SLionel Sambuc /*****************************************************************************
824433d6423SLionel Sambuc  *         ddekit_usb_server_init                                            *
825433d6423SLionel Sambuc  ****************************************************************************/
ddekit_usb_server_init()826433d6423SLionel Sambuc void ddekit_usb_server_init()
827433d6423SLionel Sambuc {
828433d6423SLionel Sambuc 	int i;
829433d6423SLionel Sambuc 	/*
830433d6423SLionel Sambuc 	 * this function has to be called inside the context of an dedicated
831433d6423SLionel Sambuc 	 * DDELinux thread
832433d6423SLionel Sambuc 	 */
833433d6423SLionel Sambuc 	devman_usb_init(bind_cb, unbind_cb);
834433d6423SLionel Sambuc 	ddekit_usb_init(&my_driver, &my_malloc, &my_free);
835433d6423SLionel Sambuc 	for (i = 0; i< MAX_DRIVERS; i++) {
836433d6423SLionel Sambuc 		gbl_drivers[i].dev = DRIVER_UNUSED;
837433d6423SLionel Sambuc 		gbl_drivers[i].dev = INVAL_DEV;
838433d6423SLionel Sambuc 	}
839433d6423SLionel Sambuc 	_ddekit_usb_thread(NULL);
840433d6423SLionel Sambuc 
841433d6423SLionel Sambuc }
842