xref: /minix3/minix/lib/libddekit/src/usb_server.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc #include "common.h"
2*433d6423SLionel Sambuc 
3*433d6423SLionel Sambuc #include <ddekit/minix/msg_queue.h>
4*433d6423SLionel Sambuc #include <ddekit/panic.h>
5*433d6423SLionel Sambuc #include <ddekit/printf.h>
6*433d6423SLionel Sambuc #include <ddekit/usb.h>
7*433d6423SLionel Sambuc #include <minix/safecopies.h>
8*433d6423SLionel Sambuc #include <minix/usb.h>
9*433d6423SLionel Sambuc #include <minix/usb_ch9.h>
10*433d6423SLionel Sambuc #include <minix/devman.h>
11*433d6423SLionel Sambuc 
12*433d6423SLionel Sambuc #define MAX_URBS    10
13*433d6423SLionel Sambuc 
14*433d6423SLionel Sambuc #define DRIVER_UNUSED 0
15*433d6423SLionel Sambuc #define DRIVER_ACTIVE 1
16*433d6423SLionel Sambuc #define DRIVER_BOUND  2
17*433d6423SLionel Sambuc 
18*433d6423SLionel Sambuc #if 0
19*433d6423SLionel Sambuc #define DEBUG_MSG(fmt, ...) ddekit_printf("%s : "fmt"\n", __func__, ##__VA_ARGS__ )
20*433d6423SLionel Sambuc #else
21*433d6423SLionel Sambuc #define DEBUG_MSG(fmt, ...)
22*433d6423SLionel Sambuc #endif
23*433d6423SLionel Sambuc 
24*433d6423SLionel Sambuc #undef DDEBUG
25*433d6423SLionel Sambuc #define DDEBUG 0
26*433d6423SLionel Sambuc #include "debug.h"
27*433d6423SLionel Sambuc 
28*433d6423SLionel Sambuc #define MAX_DEVS 256
29*433d6423SLionel Sambuc #define MAX_DRIVERS 256
30*433d6423SLionel Sambuc #define OK 0
31*433d6423SLionel Sambuc 
32*433d6423SLionel Sambuc #define INVAL_DEV (-1)
33*433d6423SLionel Sambuc 
34*433d6423SLionel Sambuc struct my_context {
35*433d6423SLionel Sambuc 	unsigned urb_id;
36*433d6423SLionel Sambuc 	struct ddekit_usb_urb *d_urb;
37*433d6423SLionel Sambuc 	struct usb_urb *mx_urb;
38*433d6423SLionel Sambuc 	struct minix_usb_driver *drv;
39*433d6423SLionel Sambuc 	gid_t gid;
40*433d6423SLionel Sambuc };
41*433d6423SLionel Sambuc 
42*433d6423SLionel Sambuc struct minix_usb_driver {
43*433d6423SLionel Sambuc 	endpoint_t ep;                       /* address of the client */
44*433d6423SLionel Sambuc 
45*433d6423SLionel Sambuc 	int status;                          /* In what state is the client? */
46*433d6423SLionel Sambuc 
47*433d6423SLionel Sambuc 	int dev;                          /* which device is this driver handling */
48*433d6423SLionel Sambuc 	unsigned interfaces;                 /* which interfaces of the device the
49*433d6423SLionel Sambuc 	                                        driver is handling */
50*433d6423SLionel Sambuc 
51*433d6423SLionel Sambuc 	struct ddekit_usb_urb *urbs[MAX_URBS]; /* pending urbs */
52*433d6423SLionel Sambuc 
53*433d6423SLionel Sambuc 	unsigned long urb_id;			     /* generation of driver_local urb_ids */
54*433d6423SLionel Sambuc };
55*433d6423SLionel Sambuc 
56*433d6423SLionel Sambuc struct minix_usb_device {
57*433d6423SLionel Sambuc 	struct ddekit_usb_dev *dev;
58*433d6423SLionel Sambuc 	unsigned int interfaces;
59*433d6423SLionel Sambuc };
60*433d6423SLionel Sambuc 
61*433d6423SLionel Sambuc static struct minix_usb_driver *find_driver(endpoint_t ep);
62*433d6423SLionel Sambuc static struct minix_usb_driver *find_unused_driver(void);
63*433d6423SLionel Sambuc static int add_to_pending_urbs(struct minix_usb_driver *drv, struct
64*433d6423SLionel Sambuc 	ddekit_usb_urb *urb);
65*433d6423SLionel Sambuc static int remove_from_pending_urbs(struct minix_usb_driver *drv,
66*433d6423SLionel Sambuc 	struct ddekit_usb_urb *urb);
67*433d6423SLionel Sambuc static struct ddekit_usb_urb * find_pending_urb(struct minix_usb_driver
68*433d6423SLionel Sambuc 	*drv, unsigned urb_id);
69*433d6423SLionel Sambuc static void register_driver(message *msg);
70*433d6423SLionel Sambuc static struct ddekit_usb_urb *ddekit_usb_urb_from_mx_urb(struct usb_urb
71*433d6423SLionel Sambuc 	*mx_urb);
72*433d6423SLionel Sambuc static void submit_urb(message *msg);
73*433d6423SLionel Sambuc static void cancle_urb(message *msg);
74*433d6423SLionel Sambuc static void completion_callback(void *priv);
75*433d6423SLionel Sambuc 
76*433d6423SLionel Sambuc static void prepare_devman_usbdev(struct ddekit_usb_dev * dev, int
77*433d6423SLionel Sambuc 	dev_id, unsigned int interfaces, struct devman_usb_dev *dudev);
78*433d6423SLionel Sambuc static void device_disconnect_callback(struct ddekit_usb_dev * dev);
79*433d6423SLionel Sambuc static int add_acl(int dev_id, unsigned interfaces, endpoint_t ep);
80*433d6423SLionel Sambuc static int del_acl(int dev_id, unsigned interaces, endpoint_t ep);
81*433d6423SLionel Sambuc static int handle_msg(message *msg);
82*433d6423SLionel Sambuc static void _ddekit_usb_thread();
83*433d6423SLionel Sambuc static void device_connect_callback(struct ddekit_usb_dev * dev,
84*433d6423SLionel Sambuc 	unsigned int interfaces);
85*433d6423SLionel Sambuc 
86*433d6423SLionel Sambuc char *_ddekit_usb_get_manufacturer(struct ddekit_usb_dev *ddev);
87*433d6423SLionel Sambuc char *_ddekit_usb_get_product(struct ddekit_usb_dev *ddev);
88*433d6423SLionel Sambuc char *_ddekit_usb_get_serial(struct ddekit_usb_dev *ddev);
89*433d6423SLionel Sambuc usb_device_descriptor_t *_ddekit_usb_get_device_desc(struct
90*433d6423SLionel Sambuc 	ddekit_usb_dev *ddev);
91*433d6423SLionel Sambuc usb_interface_descriptor_t *_ddekit_usb_get_interface_desc(struct
92*433d6423SLionel Sambuc 	ddekit_usb_dev *ddev, int inum);
93*433d6423SLionel Sambuc 
94*433d6423SLionel Sambuc 
95*433d6423SLionel Sambuc static ddekit_usb_malloc_fn my_malloc;
96*433d6423SLionel Sambuc static ddekit_usb_free_fn my_free;
97*433d6423SLionel Sambuc static struct minix_usb_driver gbl_drivers[MAX_DRIVERS];
98*433d6423SLionel Sambuc static struct minix_usb_device _devices[MAX_DEVS];
99*433d6423SLionel Sambuc 
100*433d6423SLionel Sambuc static struct ddekit_usb_driver my_driver = {
101*433d6423SLionel Sambuc 	.completion = completion_callback,
102*433d6423SLionel Sambuc 	.connect    = device_connect_callback,
103*433d6423SLionel Sambuc 	.disconnect = device_disconnect_callback,
104*433d6423SLionel Sambuc };
105*433d6423SLionel Sambuc 
106*433d6423SLionel Sambuc 
107*433d6423SLionel Sambuc /*****************************************************************************
108*433d6423SLionel Sambuc  *         find_driver                                                       *
109*433d6423SLionel Sambuc  ****************************************************************************/
110*433d6423SLionel Sambuc static struct minix_usb_driver *find_driver(endpoint_t ep)
111*433d6423SLionel Sambuc {
112*433d6423SLionel Sambuc 	int i;
113*433d6423SLionel Sambuc 	for (i = 0; i < MAX_DRIVERS; i++ ){
114*433d6423SLionel Sambuc 		if (gbl_drivers[i].ep == ep) {
115*433d6423SLionel Sambuc 			return &gbl_drivers[i];
116*433d6423SLionel Sambuc 		}
117*433d6423SLionel Sambuc 	}
118*433d6423SLionel Sambuc 	return NULL;
119*433d6423SLionel Sambuc }
120*433d6423SLionel Sambuc 
121*433d6423SLionel Sambuc /*****************************************************************************
122*433d6423SLionel Sambuc  *         find_unused_driver                                                *
123*433d6423SLionel Sambuc  ****************************************************************************/
124*433d6423SLionel Sambuc static struct minix_usb_driver *find_unused_driver()
125*433d6423SLionel Sambuc {
126*433d6423SLionel Sambuc 	int i;
127*433d6423SLionel Sambuc 	for (i = 0; i < MAX_DRIVERS; i++ ){
128*433d6423SLionel Sambuc 		if (gbl_drivers[i].status == DRIVER_UNUSED) {
129*433d6423SLionel Sambuc 			return &gbl_drivers[i];
130*433d6423SLionel Sambuc 		}
131*433d6423SLionel Sambuc 	}
132*433d6423SLionel Sambuc 	return NULL;
133*433d6423SLionel Sambuc }
134*433d6423SLionel Sambuc 
135*433d6423SLionel Sambuc /*****************************************************************************
136*433d6423SLionel Sambuc  *         add_to_pending_urbs                                               *
137*433d6423SLionel Sambuc  ****************************************************************************/
138*433d6423SLionel Sambuc static int add_to_pending_urbs(struct minix_usb_driver *drv,
139*433d6423SLionel Sambuc                                struct ddekit_usb_urb *urb)
140*433d6423SLionel Sambuc {
141*433d6423SLionel Sambuc 	int i;
142*433d6423SLionel Sambuc 
143*433d6423SLionel Sambuc 	for (i = 0; i < MAX_URBS; i++) {
144*433d6423SLionel Sambuc 		if (drv->urbs[i] == NULL) {
145*433d6423SLionel Sambuc 			drv->urbs[i] = urb;
146*433d6423SLionel Sambuc 			return 0;
147*433d6423SLionel Sambuc 		}
148*433d6423SLionel Sambuc 	}
149*433d6423SLionel Sambuc 
150*433d6423SLionel Sambuc 	return -1;
151*433d6423SLionel Sambuc }
152*433d6423SLionel Sambuc 
153*433d6423SLionel Sambuc /*****************************************************************************
154*433d6423SLionel Sambuc  *         remove_from_pending_urbs                                          *
155*433d6423SLionel Sambuc  ****************************************************************************/
156*433d6423SLionel Sambuc static int remove_from_pending_urbs(struct minix_usb_driver *drv,
157*433d6423SLionel Sambuc                                struct ddekit_usb_urb *urb)
158*433d6423SLionel Sambuc {
159*433d6423SLionel Sambuc 	int i;
160*433d6423SLionel Sambuc 
161*433d6423SLionel Sambuc 	for (i = 0; i < MAX_URBS; i++) {
162*433d6423SLionel Sambuc 		if (drv->urbs[i] == urb) {
163*433d6423SLionel Sambuc 			drv->urbs[i] = NULL;
164*433d6423SLionel Sambuc 			return 0;
165*433d6423SLionel Sambuc 		}
166*433d6423SLionel Sambuc 	}
167*433d6423SLionel Sambuc 
168*433d6423SLionel Sambuc 	return -1;
169*433d6423SLionel Sambuc }
170*433d6423SLionel Sambuc 
171*433d6423SLionel Sambuc /*****************************************************************************
172*433d6423SLionel Sambuc  *         find_pending_urb                                                  *
173*433d6423SLionel Sambuc  ****************************************************************************/
174*433d6423SLionel Sambuc static struct ddekit_usb_urb * find_pending_urb(struct minix_usb_driver *drv,
175*433d6423SLionel Sambuc                                                 unsigned urb_id)
176*433d6423SLionel Sambuc {
177*433d6423SLionel Sambuc 	int i;
178*433d6423SLionel Sambuc 
179*433d6423SLionel Sambuc 	for (i = 0; i < MAX_URBS; i++) {
180*433d6423SLionel Sambuc 		if (((struct my_context*)drv->urbs[i]->priv)->urb_id == urb_id) {
181*433d6423SLionel Sambuc 				return drv->urbs[i];
182*433d6423SLionel Sambuc 		}
183*433d6423SLionel Sambuc 	}
184*433d6423SLionel Sambuc 
185*433d6423SLionel Sambuc 	return NULL;
186*433d6423SLionel Sambuc }
187*433d6423SLionel Sambuc 
188*433d6423SLionel Sambuc /*****************************************************************************
189*433d6423SLionel Sambuc  *         register_driver                                                   *
190*433d6423SLionel Sambuc  ****************************************************************************/
191*433d6423SLionel Sambuc static void register_driver(message *msg)
192*433d6423SLionel Sambuc {
193*433d6423SLionel Sambuc 	endpoint_t ep = msg->m_source;
194*433d6423SLionel Sambuc 	struct minix_usb_driver *drv;
195*433d6423SLionel Sambuc 
196*433d6423SLionel Sambuc 	msg->m_type=USB_REPLY;
197*433d6423SLionel Sambuc 
198*433d6423SLionel Sambuc 	if ( (drv = find_driver(ep)) != NULL) {
199*433d6423SLionel Sambuc 		msg->m_type = USB_REPLY;
200*433d6423SLionel Sambuc 		msg->USB_RESULT = OK;
201*433d6423SLionel Sambuc 		ipc_send(ep,msg);
202*433d6423SLionel Sambuc 	} else {
203*433d6423SLionel Sambuc 		msg->m_type = USB_REPLY;
204*433d6423SLionel Sambuc 		msg->USB_RESULT = EPERM;
205*433d6423SLionel Sambuc 		ipc_send(ep,msg);
206*433d6423SLionel Sambuc 		return;
207*433d6423SLionel Sambuc 	}
208*433d6423SLionel Sambuc 
209*433d6423SLionel Sambuc 	DEBUG_MSG("DRIVER %d registered \n"
210*433d6423SLionel Sambuc 	              "Announcing device %d, interfaces 0x%x\n",
211*433d6423SLionel Sambuc 				  ep,
212*433d6423SLionel Sambuc 				  drv->dev,
213*433d6423SLionel Sambuc 				  drv->interfaces);
214*433d6423SLionel Sambuc 
215*433d6423SLionel Sambuc 	/* hand out the device */
216*433d6423SLionel Sambuc 	msg->m_type = USB_ANNOUCE_DEV;
217*433d6423SLionel Sambuc 	msg->USB_DEV_ID     = drv->dev;
218*433d6423SLionel Sambuc 	msg->USB_INTERFACES = drv->interfaces;
219*433d6423SLionel Sambuc 	ipc_send(ep, msg);
220*433d6423SLionel Sambuc }
221*433d6423SLionel Sambuc 
222*433d6423SLionel Sambuc /*****************************************************************************
223*433d6423SLionel Sambuc  *         deregister_driver                                                 *
224*433d6423SLionel Sambuc  ****************************************************************************/
225*433d6423SLionel Sambuc static void deregister_driver(message *msg)
226*433d6423SLionel Sambuc {
227*433d6423SLionel Sambuc 	endpoint_t ep = msg->m_source;
228*433d6423SLionel Sambuc 
229*433d6423SLionel Sambuc 	struct minix_usb_driver *drv;
230*433d6423SLionel Sambuc 
231*433d6423SLionel Sambuc 	msg->m_type=USB_REPLY;
232*433d6423SLionel Sambuc 
233*433d6423SLionel Sambuc 	if ( (drv = find_driver(ep)) == NULL) {
234*433d6423SLionel Sambuc 		DEBUG_MSG("Non-registered driver tries to unregister.");
235*433d6423SLionel Sambuc 		return;
236*433d6423SLionel Sambuc 	} else {
237*433d6423SLionel Sambuc 		/* do not accept requests for this client anymore! */
238*433d6423SLionel Sambuc 		drv->status = DRIVER_UNUSED;
239*433d6423SLionel Sambuc 
240*433d6423SLionel Sambuc 		msg->USB_RESULT = 0;
241*433d6423SLionel Sambuc 		asynsend3(ep, msg, AMF_NOREPLY);
242*433d6423SLionel Sambuc 	}
243*433d6423SLionel Sambuc }
244*433d6423SLionel Sambuc 
245*433d6423SLionel Sambuc /*****************************************************************************
246*433d6423SLionel Sambuc  *         ddekit_usb_urb_from_mx_urb                                        *
247*433d6423SLionel Sambuc  ****************************************************************************/
248*433d6423SLionel Sambuc static struct ddekit_usb_urb *ddekit_usb_urb_from_mx_urb(struct usb_urb *mx_urb)
249*433d6423SLionel Sambuc {
250*433d6423SLionel Sambuc 	/*
251*433d6423SLionel Sambuc 	 * A helper function that generates (allocates and initializes)
252*433d6423SLionel Sambuc 	 * a ddekit_usb_urb.
253*433d6423SLionel Sambuc 	 */
254*433d6423SLionel Sambuc 
255*433d6423SLionel Sambuc 	struct ddekit_usb_urb *d_urb = (struct ddekit_usb_urb *)
256*433d6423SLionel Sambuc 		my_malloc(sizeof(struct ddekit_usb_urb));
257*433d6423SLionel Sambuc 
258*433d6423SLionel Sambuc 	if (d_urb == NULL) {
259*433d6423SLionel Sambuc 		return NULL;
260*433d6423SLionel Sambuc 	}
261*433d6423SLionel Sambuc 
262*433d6423SLionel Sambuc 	d_urb->type           = mx_urb->type;
263*433d6423SLionel Sambuc 	d_urb->direction      = mx_urb->direction;
264*433d6423SLionel Sambuc 	d_urb->transfer_flags = mx_urb->transfer_flags;
265*433d6423SLionel Sambuc 	d_urb->size           = mx_urb->size;
266*433d6423SLionel Sambuc 	d_urb->data           = mx_urb->buffer;
267*433d6423SLionel Sambuc 	d_urb->interval       = mx_urb->interval;
268*433d6423SLionel Sambuc 	d_urb->endpoint       = mx_urb->endpoint;
269*433d6423SLionel Sambuc 
270*433d6423SLionel Sambuc 	if (d_urb->type == USB_TRANSFER_CTL) {
271*433d6423SLionel Sambuc 		d_urb->setup_packet = mx_urb->setup_packet;
272*433d6423SLionel Sambuc 	}
273*433d6423SLionel Sambuc 	DEBUG_MSG("setup_package at %p", d_urb->setup_packet);
274*433d6423SLionel Sambuc 
275*433d6423SLionel Sambuc 	if (d_urb->type == USB_TRANSFER_ISO) {
276*433d6423SLionel Sambuc 		d_urb->iso_desc  = (struct ddekit_usb_iso_packet_desc *)
277*433d6423SLionel Sambuc 		    mx_urb->buffer + mx_urb->iso_desc_offset;
278*433d6423SLionel Sambuc 		d_urb->number_of_packets = mx_urb->number_of_packets;
279*433d6423SLionel Sambuc 	}
280*433d6423SLionel Sambuc 
281*433d6423SLionel Sambuc 	return d_urb;
282*433d6423SLionel Sambuc }
283*433d6423SLionel Sambuc 
284*433d6423SLionel Sambuc /*****************************************************************************
285*433d6423SLionel Sambuc  *         submit_urb                                                        *
286*433d6423SLionel Sambuc  ****************************************************************************/
287*433d6423SLionel Sambuc static void submit_urb(message *msg)
288*433d6423SLionel Sambuc {
289*433d6423SLionel Sambuc 	/*
290*433d6423SLionel Sambuc 	 * submit_urb
291*433d6423SLionel Sambuc 	 *
292*433d6423SLionel Sambuc 	 * Handles a submit_urb from a minix USB device driver. It copies the
293*433d6423SLionel Sambuc 	 * usb_urb structure containing the buffers and generates and tries to
294*433d6423SLionel Sambuc 	 * submit a ddekit_usb_urb. The reference to the ddekit_usb_urb is stored
295*433d6423SLionel Sambuc 	 * in the driver structure in order to be able to cancle the URB on the
296*433d6423SLionel Sambuc 	 * clients request.
297*433d6423SLionel Sambuc 	 */
298*433d6423SLionel Sambuc 	endpoint_t ep = msg->m_source;
299*433d6423SLionel Sambuc 	struct minix_usb_driver *drv;
300*433d6423SLionel Sambuc 
301*433d6423SLionel Sambuc 	/* find driver */
302*433d6423SLionel Sambuc 	if ( (drv = find_driver(ep)) == NULL) {
303*433d6423SLionel Sambuc 		DEBUG_MSG("Non-registered driver tries to send URB.");
304*433d6423SLionel Sambuc 		return;
305*433d6423SLionel Sambuc 	} else {
306*433d6423SLionel Sambuc 
307*433d6423SLionel Sambuc 		int res;
308*433d6423SLionel Sambuc 
309*433d6423SLionel Sambuc 		struct usb_urb *mx_urb  = (struct usb_urb*)
310*433d6423SLionel Sambuc 		    my_malloc(msg->USB_GRANT_SIZE+sizeof(void *));
311*433d6423SLionel Sambuc 
312*433d6423SLionel Sambuc 		if (mx_urb == NULL) {
313*433d6423SLionel Sambuc 			DEBUG_MSG("Can't allocat mem for mx_urb.");
314*433d6423SLionel Sambuc 			res = ENOMEM;
315*433d6423SLionel Sambuc 			goto out;
316*433d6423SLionel Sambuc 		}
317*433d6423SLionel Sambuc 
318*433d6423SLionel Sambuc 		/* copy in URB */
319*433d6423SLionel Sambuc 		res = sys_safecopyfrom(ep, msg->USB_GRANT_ID, 0,
320*433d6423SLionel Sambuc 		    (vir_bytes) &mx_urb->dev_id, msg->USB_GRANT_SIZE);
321*433d6423SLionel Sambuc 
322*433d6423SLionel Sambuc 		if (res != 0) {
323*433d6423SLionel Sambuc 			DEBUG_MSG("sys_safecopyfrom failed ");
324*433d6423SLionel Sambuc 			my_free(mx_urb);
325*433d6423SLionel Sambuc 			res = EINVAL;
326*433d6423SLionel Sambuc 			goto out;
327*433d6423SLionel Sambuc 		}
328*433d6423SLionel Sambuc 
329*433d6423SLionel Sambuc 		DEBUG_MSG("URB type: %d", mx_urb->type);
330*433d6423SLionel Sambuc 		/* check if urb is valid */
331*433d6423SLionel Sambuc 		if (mx_urb->dev_id >= MAX_DEVS && mx_urb->dev_id < 0) {
332*433d6423SLionel Sambuc 			DEBUG_MSG("Bogus device ID.");
333*433d6423SLionel Sambuc 			res = EINVAL;
334*433d6423SLionel Sambuc 			goto out;
335*433d6423SLionel Sambuc 		}
336*433d6423SLionel Sambuc 
337*433d6423SLionel Sambuc 		/* create ddekit_usb_urb */
338*433d6423SLionel Sambuc 		struct ddekit_usb_urb *d_urb = ddekit_usb_urb_from_mx_urb(mx_urb);
339*433d6423SLionel Sambuc 		d_urb->dev = _devices[drv->dev].dev;
340*433d6423SLionel Sambuc 		/* submit urb */
341*433d6423SLionel Sambuc 
342*433d6423SLionel Sambuc 		if (!d_urb) {
343*433d6423SLionel Sambuc 			res = ENOMEM;
344*433d6423SLionel Sambuc 			goto out;
345*433d6423SLionel Sambuc 		}
346*433d6423SLionel Sambuc 
347*433d6423SLionel Sambuc 		struct my_context *ctx = (struct my_context *)
348*433d6423SLionel Sambuc 		    my_malloc(sizeof(struct my_context));
349*433d6423SLionel Sambuc 
350*433d6423SLionel Sambuc 		if(!ctx) {
351*433d6423SLionel Sambuc 			res = ENOMEM;
352*433d6423SLionel Sambuc 			goto out;
353*433d6423SLionel Sambuc 		}
354*433d6423SLionel Sambuc 
355*433d6423SLionel Sambuc 		ctx->drv       = drv;
356*433d6423SLionel Sambuc 		ctx->urb_id    = drv->urb_id++;
357*433d6423SLionel Sambuc 		mx_urb->urb_id = ctx->urb_id;
358*433d6423SLionel Sambuc 		ctx->mx_urb    = mx_urb;
359*433d6423SLionel Sambuc 		ctx->d_urb     = d_urb;
360*433d6423SLionel Sambuc 		ctx->gid       = msg->USB_GRANT_ID;
361*433d6423SLionel Sambuc 
362*433d6423SLionel Sambuc 		DEBUG_MSG("ctx: %p, urb_id: %d, d_urb: %p, mx_urb: %p, drv: %d, gid: %d ",
363*433d6423SLionel Sambuc 		    ctx, ctx->urb_id, ctx->d_urb, ctx->mx_urb, ctx->drv, ctx->gid);
364*433d6423SLionel Sambuc 
365*433d6423SLionel Sambuc 		d_urb->priv = ctx;
366*433d6423SLionel Sambuc 
367*433d6423SLionel Sambuc 		res = add_to_pending_urbs(drv, d_urb);
368*433d6423SLionel Sambuc 
369*433d6423SLionel Sambuc 		if (res == 0) {
370*433d6423SLionel Sambuc 			DEBUG_MSG("submitting urb...");
371*433d6423SLionel Sambuc 			res = ddekit_usb_submit_urb(d_urb);
372*433d6423SLionel Sambuc 			if(res) {
373*433d6423SLionel Sambuc 				DEBUG_MSG("submitting urb failed (err: %d)", res);
374*433d6423SLionel Sambuc 				remove_from_pending_urbs(drv, d_urb);
375*433d6423SLionel Sambuc 			}
376*433d6423SLionel Sambuc 		}
377*433d6423SLionel Sambuc 
378*433d6423SLionel Sambuc out:
379*433d6423SLionel Sambuc 		/* reply */
380*433d6423SLionel Sambuc 		msg->m_type     = USB_REPLY;
381*433d6423SLionel Sambuc 		msg->USB_URB_ID = mx_urb->urb_id;
382*433d6423SLionel Sambuc 		msg->USB_RESULT = res;
383*433d6423SLionel Sambuc 
384*433d6423SLionel Sambuc 		if(res != 0) {
385*433d6423SLionel Sambuc 
386*433d6423SLionel Sambuc 			if (mx_urb != NULL) {
387*433d6423SLionel Sambuc 				my_free(mx_urb);
388*433d6423SLionel Sambuc 			}
389*433d6423SLionel Sambuc 			if (ctx != NULL) {
390*433d6423SLionel Sambuc 				my_free(ctx);
391*433d6423SLionel Sambuc 			}
392*433d6423SLionel Sambuc 
393*433d6423SLionel Sambuc 			if (d_urb != NULL) {
394*433d6423SLionel Sambuc 				my_free(d_urb);
395*433d6423SLionel Sambuc 			}
396*433d6423SLionel Sambuc 
397*433d6423SLionel Sambuc 		}
398*433d6423SLionel Sambuc 
399*433d6423SLionel Sambuc 		/* send reply */
400*433d6423SLionel Sambuc 		ipc_send(ep, msg);
401*433d6423SLionel Sambuc 	}
402*433d6423SLionel Sambuc }
403*433d6423SLionel Sambuc 
404*433d6423SLionel Sambuc 
405*433d6423SLionel Sambuc /*
406*433d6423SLionel Sambuc  * cancle_urb
407*433d6423SLionel Sambuc  *
408*433d6423SLionel Sambuc  * Cancels the submission of an URB identified by a URB_id
409*433d6423SLionel Sambuc  */
410*433d6423SLionel Sambuc /*****************************************************************************
411*433d6423SLionel Sambuc  *         cancle_urb                                                        *
412*433d6423SLionel Sambuc  ****************************************************************************/
413*433d6423SLionel Sambuc static void cancle_urb(message *msg)
414*433d6423SLionel Sambuc {
415*433d6423SLionel Sambuc 	endpoint_t ep = msg->m_source;
416*433d6423SLionel Sambuc 
417*433d6423SLionel Sambuc 	struct minix_usb_driver *drv;
418*433d6423SLionel Sambuc 
419*433d6423SLionel Sambuc 	msg->USB_RESULT = -1;
420*433d6423SLionel Sambuc 	msg->m_type = USB_REPLY;
421*433d6423SLionel Sambuc 
422*433d6423SLionel Sambuc 	/* find driver */
423*433d6423SLionel Sambuc 	if ( (drv = find_driver(ep)) == NULL) {
424*433d6423SLionel Sambuc 		DEBUG_MSG("Non-registered driver tries to cancel URB.");
425*433d6423SLionel Sambuc 		return;
426*433d6423SLionel Sambuc 	} else {
427*433d6423SLionel Sambuc 		struct ddekit_usb_urb *d_urb = NULL;
428*433d6423SLionel Sambuc 
429*433d6423SLionel Sambuc 		d_urb = find_pending_urb(drv, msg->USB_URB_ID);
430*433d6423SLionel Sambuc 
431*433d6423SLionel Sambuc 		if (d_urb != NULL) {
432*433d6423SLionel Sambuc 			ddekit_usb_cancle_urb(d_urb);
433*433d6423SLionel Sambuc 			msg->USB_RESULT = 0;
434*433d6423SLionel Sambuc 		} else {
435*433d6423SLionel Sambuc 			DEBUG_MSG("No URB to cancle");
436*433d6423SLionel Sambuc 			msg->USB_RESULT = ENODEV;
437*433d6423SLionel Sambuc 		}
438*433d6423SLionel Sambuc 	}
439*433d6423SLionel Sambuc 
440*433d6423SLionel Sambuc 	ipc_send(ep, msg);
441*433d6423SLionel Sambuc }
442*433d6423SLionel Sambuc 
443*433d6423SLionel Sambuc 
444*433d6423SLionel Sambuc /*****************************************************************************
445*433d6423SLionel Sambuc  *         completion_callback                                               *
446*433d6423SLionel Sambuc  ****************************************************************************/
447*433d6423SLionel Sambuc static void completion_callback(void *priv)
448*433d6423SLionel Sambuc {
449*433d6423SLionel Sambuc 	/*
450*433d6423SLionel Sambuc 	 * completion_callback
451*433d6423SLionel Sambuc 	 *
452*433d6423SLionel Sambuc 	 * This is called by the DDE side. Here the data is copied back to
453*433d6423SLionel Sambuc 	 * the driver and a message is send to inform the driver about the
454*433d6423SLionel Sambuc 	 * completion.
455*433d6423SLionel Sambuc 	 */
456*433d6423SLionel Sambuc 	message msg;
457*433d6423SLionel Sambuc 	int res;
458*433d6423SLionel Sambuc 	struct my_context *ctx       = (struct my_context *)priv;
459*433d6423SLionel Sambuc 	struct usb_urb *mx_urb       = ctx->mx_urb;
460*433d6423SLionel Sambuc 	struct ddekit_usb_urb *d_urb = ctx->d_urb;
461*433d6423SLionel Sambuc 	struct minix_usb_driver *drv = ctx->drv;
462*433d6423SLionel Sambuc 
463*433d6423SLionel Sambuc 	DEBUG_MSG("ctx: %p, urb_id: %d, d_urb: %p, mx_urb: %p, drv: %d, gid: %d ",
464*433d6423SLionel Sambuc 		    ctx, ctx->urb_id, ctx->d_urb, ctx->mx_urb, ctx->drv, ctx->gid);
465*433d6423SLionel Sambuc 
466*433d6423SLionel Sambuc 	/* update data in minix URB */
467*433d6423SLionel Sambuc 	mx_urb->status          = d_urb->status;
468*433d6423SLionel Sambuc 	mx_urb->actual_length   = d_urb->actual_length;
469*433d6423SLionel Sambuc 	mx_urb->error_count     = d_urb->error_count;
470*433d6423SLionel Sambuc 	mx_urb->transfer_flags  = d_urb->transfer_flags;
471*433d6423SLionel Sambuc 
472*433d6423SLionel Sambuc 	remove_from_pending_urbs(drv, d_urb);
473*433d6423SLionel Sambuc 
474*433d6423SLionel Sambuc 	/* copy out URB */
475*433d6423SLionel Sambuc 	res = sys_safecopyto(drv->ep, ctx->gid, 0,
476*433d6423SLionel Sambuc 	    (vir_bytes) ((char*)mx_urb) + sizeof(void*),
477*433d6423SLionel Sambuc 		mx_urb->urb_size - sizeof(void*));
478*433d6423SLionel Sambuc 
479*433d6423SLionel Sambuc 	if (res != 0) {
480*433d6423SLionel Sambuc 		DEBUG_MSG("Copy out failed: %d", res);
481*433d6423SLionel Sambuc 		DEBUG_MSG(" URB ID: %d, Grant-ID: %d, Grant-size: %d", ctx->urb_id,
482*433d6423SLionel Sambuc 		            ctx->gid, mx_urb->urb_size);
483*433d6423SLionel Sambuc 	}
484*433d6423SLionel Sambuc 
485*433d6423SLionel Sambuc 	/* send message to client */
486*433d6423SLionel Sambuc 	msg.m_type     = USB_COMPLETE_URB;
487*433d6423SLionel Sambuc 	msg.USB_URB_ID = ctx->urb_id;
488*433d6423SLionel Sambuc 	asynsend3(drv->ep, &msg, AMF_NOREPLY);
489*433d6423SLionel Sambuc 
490*433d6423SLionel Sambuc 	/* free stuff */
491*433d6423SLionel Sambuc 	my_free(ctx);
492*433d6423SLionel Sambuc 	my_free(mx_urb);
493*433d6423SLionel Sambuc 	my_free(d_urb);
494*433d6423SLionel Sambuc }
495*433d6423SLionel Sambuc 
496*433d6423SLionel Sambuc 
497*433d6423SLionel Sambuc /*****************************************************************************
498*433d6423SLionel Sambuc  *         prepare_devman_usbdev                                             *
499*433d6423SLionel Sambuc  ****************************************************************************/
500*433d6423SLionel Sambuc static void prepare_devman_usbdev
501*433d6423SLionel Sambuc (struct ddekit_usb_dev * dev, int dev_id, unsigned int interfaces,
502*433d6423SLionel Sambuc  struct devman_usb_dev *dudev)
503*433d6423SLionel Sambuc {
504*433d6423SLionel Sambuc 	int j;
505*433d6423SLionel Sambuc 	int intf_count;
506*433d6423SLionel Sambuc 	/*
507*433d6423SLionel Sambuc 	 * currently this is only implemented by stub driver
508*433d6423SLionel Sambuc 	 */
509*433d6423SLionel Sambuc 
510*433d6423SLionel Sambuc 	usb_device_descriptor_t *desc = _ddekit_usb_get_device_desc(dev);
511*433d6423SLionel Sambuc 
512*433d6423SLionel Sambuc 	dudev->manufacturer = _ddekit_usb_get_manufacturer(dev);
513*433d6423SLionel Sambuc 	dudev->product = _ddekit_usb_get_product(dev);
514*433d6423SLionel Sambuc 	dudev->serial = _ddekit_usb_get_serial(dev);
515*433d6423SLionel Sambuc 
516*433d6423SLionel Sambuc 	dudev->desc = desc;
517*433d6423SLionel Sambuc 
518*433d6423SLionel Sambuc 	intf_count = 0;
519*433d6423SLionel Sambuc 
520*433d6423SLionel Sambuc 	for (j=0; j < 32; j++) {
521*433d6423SLionel Sambuc 		if (interfaces & (1 << j)) {
522*433d6423SLionel Sambuc 				dudev->interfaces[intf_count++].desc =
523*433d6423SLionel Sambuc 				   _ddekit_usb_get_interface_desc(dev, j);
524*433d6423SLionel Sambuc 		}
525*433d6423SLionel Sambuc 	}
526*433d6423SLionel Sambuc 
527*433d6423SLionel Sambuc 	dudev->intf_count = intf_count;
528*433d6423SLionel Sambuc 	dudev->dev_id     = dev_id;
529*433d6423SLionel Sambuc }
530*433d6423SLionel Sambuc 
531*433d6423SLionel Sambuc /*****************************************************************************
532*433d6423SLionel Sambuc  *         device_connect_callback                                           *
533*433d6423SLionel Sambuc  ****************************************************************************/
534*433d6423SLionel Sambuc static void
535*433d6423SLionel Sambuc device_connect_callback
536*433d6423SLionel Sambuc (struct ddekit_usb_dev * dev, unsigned int interfaces) {
537*433d6423SLionel Sambuc 
538*433d6423SLionel Sambuc 	int i, res;
539*433d6423SLionel Sambuc 
540*433d6423SLionel Sambuc 	/* add to device list */
541*433d6423SLionel Sambuc 	for (i=0; i < MAX_DEVS; i++) {
542*433d6423SLionel Sambuc 		if (_devices[i].dev == NULL)
543*433d6423SLionel Sambuc 			break;
544*433d6423SLionel Sambuc 	}
545*433d6423SLionel Sambuc 
546*433d6423SLionel Sambuc 	if (i >= MAX_DEVS) {
547*433d6423SLionel Sambuc 		DEBUG_MSG("Too much devices...");
548*433d6423SLionel Sambuc 	} else {
549*433d6423SLionel Sambuc 		_devices[i].dev = dev;
550*433d6423SLionel Sambuc 		_devices[i].interfaces = (1 << interfaces);
551*433d6423SLionel Sambuc 	}
552*433d6423SLionel Sambuc 
553*433d6423SLionel Sambuc 	struct devman_usb_dev *dudev;
554*433d6423SLionel Sambuc 
555*433d6423SLionel Sambuc 	dudev = devman_usb_device_new(i);
556*433d6423SLionel Sambuc 
557*433d6423SLionel Sambuc 	prepare_devman_usbdev(dev, i, interfaces, dudev);
558*433d6423SLionel Sambuc 
559*433d6423SLionel Sambuc 	if (dudev == NULL) {
560*433d6423SLionel Sambuc 		/* TODO: ERROR */
561*433d6423SLionel Sambuc 		printf("ERROR: !");
562*433d6423SLionel Sambuc 	}
563*433d6423SLionel Sambuc 
564*433d6423SLionel Sambuc 	ddekit_usb_dev_set_data(dev, dudev);
565*433d6423SLionel Sambuc 
566*433d6423SLionel Sambuc 	res = devman_usb_device_add(dudev);
567*433d6423SLionel Sambuc 
568*433d6423SLionel Sambuc 	if (res != 0) {
569*433d6423SLionel Sambuc 		/* TODO: Error*/
570*433d6423SLionel Sambuc 		printf("ERROR!");
571*433d6423SLionel Sambuc 	}
572*433d6423SLionel Sambuc }
573*433d6423SLionel Sambuc 
574*433d6423SLionel Sambuc /*****************************************************************************
575*433d6423SLionel Sambuc  *         device_disconnect_callback                                        *
576*433d6423SLionel Sambuc  ****************************************************************************/
577*433d6423SLionel Sambuc static void device_disconnect_callback(struct ddekit_usb_dev * dev)
578*433d6423SLionel Sambuc {
579*433d6423SLionel Sambuc 	int i;
580*433d6423SLionel Sambuc 
581*433d6423SLionel Sambuc 	/* remove ACL entry */
582*433d6423SLionel Sambuc 	for (i = 0; i< MAX_DRIVERS; i++) {
583*433d6423SLionel Sambuc 		if (gbl_drivers[i].dev != INVAL_DEV
584*433d6423SLionel Sambuc 			&& _devices[gbl_drivers[i].dev].dev == dev) {
585*433d6423SLionel Sambuc 			struct minix_usb_driver *drv = &gbl_drivers[i];
586*433d6423SLionel Sambuc 			drv->ep     = 0;
587*433d6423SLionel Sambuc 			drv->status = DRIVER_UNUSED;
588*433d6423SLionel Sambuc 			drv->dev    = INVAL_DEV;
589*433d6423SLionel Sambuc 		}
590*433d6423SLionel Sambuc 	}
591*433d6423SLionel Sambuc 
592*433d6423SLionel Sambuc 	for (i=0; i < MAX_DEVS; i++) {
593*433d6423SLionel Sambuc 		if (_devices[i].dev == dev) {
594*433d6423SLionel Sambuc 			_devices[i].dev = NULL;
595*433d6423SLionel Sambuc 			_devices[i].interfaces = 0;
596*433d6423SLionel Sambuc 		}
597*433d6423SLionel Sambuc 	}
598*433d6423SLionel Sambuc 
599*433d6423SLionel Sambuc 
600*433d6423SLionel Sambuc 	/* get the devman device */
601*433d6423SLionel Sambuc 	struct devman_usb_dev * dudev = NULL;
602*433d6423SLionel Sambuc 
603*433d6423SLionel Sambuc 	dudev = ddekit_usb_dev_get_data(dev);
604*433d6423SLionel Sambuc 
605*433d6423SLionel Sambuc 	if (dudev == NULL) {
606*433d6423SLionel Sambuc 		/* TODO: error */
607*433d6423SLionel Sambuc 	}
608*433d6423SLionel Sambuc 
609*433d6423SLionel Sambuc 	devman_usb_device_remove(dudev);
610*433d6423SLionel Sambuc 
611*433d6423SLionel Sambuc 	/* free the devman dev */
612*433d6423SLionel Sambuc 	devman_usb_device_delete(dudev);
613*433d6423SLionel Sambuc }
614*433d6423SLionel Sambuc 
615*433d6423SLionel Sambuc 
616*433d6423SLionel Sambuc /*****************************************************************************
617*433d6423SLionel Sambuc  *         add_acl                                                           *
618*433d6423SLionel Sambuc  ****************************************************************************/
619*433d6423SLionel Sambuc static int add_acl(int dev_id, unsigned interfaces, endpoint_t ep)
620*433d6423SLionel Sambuc {
621*433d6423SLionel Sambuc 	/*
622*433d6423SLionel Sambuc 	 * This functions binds a specific USB interface to a client.
623*433d6423SLionel Sambuc 	 */
624*433d6423SLionel Sambuc 	int i;
625*433d6423SLionel Sambuc 	struct minix_usb_driver *drv;
626*433d6423SLionel Sambuc 
627*433d6423SLionel Sambuc 	if (_devices[dev_id].dev == NULL) {
628*433d6423SLionel Sambuc 		/* if no device with that ID */
629*433d6423SLionel Sambuc 		return  ENODEV;
630*433d6423SLionel Sambuc 	}
631*433d6423SLionel Sambuc 
632*433d6423SLionel Sambuc 	/* is the device allready given to a client*/
633*433d6423SLionel Sambuc 	for (i = 0; i< MAX_DRIVERS; i++) {
634*433d6423SLionel Sambuc 		if (gbl_drivers[i].status != DRIVER_UNUSED &&
635*433d6423SLionel Sambuc 			gbl_drivers[i].dev == dev_id) {
636*433d6423SLionel Sambuc 			printf("devid: %d\n", dev_id);
637*433d6423SLionel Sambuc 			return EBUSY;
638*433d6423SLionel Sambuc 		}
639*433d6423SLionel Sambuc 	}
640*433d6423SLionel Sambuc 
641*433d6423SLionel Sambuc 	/* bind device to client */
642*433d6423SLionel Sambuc 	drv = find_unused_driver();
643*433d6423SLionel Sambuc 
644*433d6423SLionel Sambuc 	if (drv == NULL) {
645*433d6423SLionel Sambuc 		return ENOMEM;
646*433d6423SLionel Sambuc 	}
647*433d6423SLionel Sambuc 
648*433d6423SLionel Sambuc 	drv->status     = DRIVER_BOUND;
649*433d6423SLionel Sambuc 	drv->dev        = dev_id;
650*433d6423SLionel Sambuc 	drv->interfaces = 1 << interfaces;
651*433d6423SLionel Sambuc 	drv->ep         = ep;
652*433d6423SLionel Sambuc 	drv->urb_id     = 0;
653*433d6423SLionel Sambuc 
654*433d6423SLionel Sambuc 	return OK;
655*433d6423SLionel Sambuc }
656*433d6423SLionel Sambuc 
657*433d6423SLionel Sambuc /*****************************************************************************
658*433d6423SLionel Sambuc  *         del_acl                                                           *
659*433d6423SLionel Sambuc  ****************************************************************************/
660*433d6423SLionel Sambuc static int del_acl(int dev_id, unsigned interfaces, endpoint_t ep)
661*433d6423SLionel Sambuc {
662*433d6423SLionel Sambuc 	struct minix_usb_driver *drv;
663*433d6423SLionel Sambuc 	int dev, withdraw = 0;
664*433d6423SLionel Sambuc 	message msg;
665*433d6423SLionel Sambuc 
666*433d6423SLionel Sambuc 	/* find driver */
667*433d6423SLionel Sambuc 	drv = find_driver(ep);
668*433d6423SLionel Sambuc 
669*433d6423SLionel Sambuc 	if (drv == NULL) {
670*433d6423SLionel Sambuc 		return  ENOENT;
671*433d6423SLionel Sambuc 	}
672*433d6423SLionel Sambuc 
673*433d6423SLionel Sambuc 	dev = drv->dev;
674*433d6423SLionel Sambuc 
675*433d6423SLionel Sambuc 	if (drv->status == DRIVER_ACTIVE) {
676*433d6423SLionel Sambuc 		withdraw = 1;
677*433d6423SLionel Sambuc 	}
678*433d6423SLionel Sambuc 
679*433d6423SLionel Sambuc 	drv->ep    = 0;
680*433d6423SLionel Sambuc 	drv->status = DRIVER_UNUSED;
681*433d6423SLionel Sambuc 	drv->dev   = INVAL_DEV;
682*433d6423SLionel Sambuc 
683*433d6423SLionel Sambuc 	if (withdraw) {
684*433d6423SLionel Sambuc 		msg.m_type     = USB_WITHDRAW_DEV;
685*433d6423SLionel Sambuc 		msg.USB_DEV_ID = dev;
686*433d6423SLionel Sambuc 		asynsend3(ep, &msg, AMF_NOREPLY);
687*433d6423SLionel Sambuc 	}
688*433d6423SLionel Sambuc 
689*433d6423SLionel Sambuc 	return 0;
690*433d6423SLionel Sambuc }
691*433d6423SLionel Sambuc 
692*433d6423SLionel Sambuc /*****************************************************************************
693*433d6423SLionel Sambuc  *         handle_msg                                                        *
694*433d6423SLionel Sambuc  ****************************************************************************/
695*433d6423SLionel Sambuc static int handle_msg(message *msg)
696*433d6423SLionel Sambuc {
697*433d6423SLionel Sambuc 	/*
698*433d6423SLionel Sambuc 	 * handle_msg
699*433d6423SLionel Sambuc 	 *
700*433d6423SLionel Sambuc 	 * The dispatcher for USB related messages.
701*433d6423SLionel Sambuc 	 */
702*433d6423SLionel Sambuc 
703*433d6423SLionel Sambuc 	switch(msg->m_type) {
704*433d6423SLionel Sambuc 		case USB_RQ_INIT:
705*433d6423SLionel Sambuc 			register_driver(msg);
706*433d6423SLionel Sambuc 			return 1;
707*433d6423SLionel Sambuc 		case USB_RQ_DEINIT:
708*433d6423SLionel Sambuc 			deregister_driver(msg);
709*433d6423SLionel Sambuc 			return 1;
710*433d6423SLionel Sambuc 		case USB_RQ_SEND_URB:
711*433d6423SLionel Sambuc 			submit_urb(msg);
712*433d6423SLionel Sambuc 			return 1;
713*433d6423SLionel Sambuc 		case USB_RQ_CANCEL_URB:
714*433d6423SLionel Sambuc 			cancle_urb(msg);
715*433d6423SLionel Sambuc 			return 1;
716*433d6423SLionel Sambuc 		default:
717*433d6423SLionel Sambuc 			return 0;
718*433d6423SLionel Sambuc 	}
719*433d6423SLionel Sambuc }
720*433d6423SLionel Sambuc 
721*433d6423SLionel Sambuc /*****************************************************************************
722*433d6423SLionel Sambuc  *         devman_tread                                                      *
723*433d6423SLionel Sambuc  ****************************************************************************/
724*433d6423SLionel Sambuc static void devman_thread(void *unused)
725*433d6423SLionel Sambuc {
726*433d6423SLionel Sambuc 	struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(DEVMAN_BASE,
727*433d6423SLionel Sambuc 	    DEVMAN_BASE + 0xff);
728*433d6423SLionel Sambuc 	int ipc_status;
729*433d6423SLionel Sambuc 	message m;
730*433d6423SLionel Sambuc 	while (1) {
731*433d6423SLionel Sambuc 		ddekit_minix_rcv(mq, &m, &ipc_status);
732*433d6423SLionel Sambuc 		devman_handle_msg(&m);
733*433d6423SLionel Sambuc 	}
734*433d6423SLionel Sambuc }
735*433d6423SLionel Sambuc 
736*433d6423SLionel Sambuc /*****************************************************************************
737*433d6423SLionel Sambuc  *         _ddekit_usb_thread                                                *
738*433d6423SLionel Sambuc  ****************************************************************************/
739*433d6423SLionel Sambuc static void _ddekit_usb_thread(void * unused)
740*433d6423SLionel Sambuc {
741*433d6423SLionel Sambuc 	struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(USB_BASE,
742*433d6423SLionel Sambuc 	    USB_BASE + 0xff);
743*433d6423SLionel Sambuc 
744*433d6423SLionel Sambuc 	message m;
745*433d6423SLionel Sambuc 	int ipc_status;
746*433d6423SLionel Sambuc 
747*433d6423SLionel Sambuc 	/* create devman thread */
748*433d6423SLionel Sambuc 	ddekit_thread_t * dmth;
749*433d6423SLionel Sambuc 
750*433d6423SLionel Sambuc 	dmth = ddekit_thread_create(devman_thread, NULL, "devman_thread");
751*433d6423SLionel Sambuc 
752*433d6423SLionel Sambuc 	while (1) {
753*433d6423SLionel Sambuc 		ddekit_minix_rcv(mq, &m, &ipc_status);
754*433d6423SLionel Sambuc 		handle_msg(&m);
755*433d6423SLionel Sambuc 	}
756*433d6423SLionel Sambuc }
757*433d6423SLionel Sambuc 
758*433d6423SLionel Sambuc 
759*433d6423SLionel Sambuc /*****************************************************************************
760*433d6423SLionel Sambuc  *         bind_cb                                                           *
761*433d6423SLionel Sambuc  ****************************************************************************/
762*433d6423SLionel Sambuc static int bind_cb (struct devman_usb_bind_cb_data *data, endpoint_t ep)
763*433d6423SLionel Sambuc {
764*433d6423SLionel Sambuc 	if(data) {
765*433d6423SLionel Sambuc 		return add_acl(data->dev_id, data->interface, ep);
766*433d6423SLionel Sambuc 	} else {
767*433d6423SLionel Sambuc 		printf("warning: missing cb_data!\n");
768*433d6423SLionel Sambuc 		return EINVAL;
769*433d6423SLionel Sambuc 	}
770*433d6423SLionel Sambuc }
771*433d6423SLionel Sambuc 
772*433d6423SLionel Sambuc /*****************************************************************************
773*433d6423SLionel Sambuc  *         unbind_cb                                                         *
774*433d6423SLionel Sambuc  ****************************************************************************/
775*433d6423SLionel Sambuc static int unbind_cb (struct devman_usb_bind_cb_data *data, endpoint_t ep)
776*433d6423SLionel Sambuc {
777*433d6423SLionel Sambuc 	if(data) {
778*433d6423SLionel Sambuc 		return del_acl(data->dev_id, data->interface, ep);
779*433d6423SLionel Sambuc 	} else {
780*433d6423SLionel Sambuc 		printf("warning: missing cb_data!\n");
781*433d6423SLionel Sambuc 		return EINVAL;
782*433d6423SLionel Sambuc 	}
783*433d6423SLionel Sambuc }
784*433d6423SLionel Sambuc 
785*433d6423SLionel Sambuc /*****************************************************************************
786*433d6423SLionel Sambuc  *         ddekit_usb_server_init                                            *
787*433d6423SLionel Sambuc  ****************************************************************************/
788*433d6423SLionel Sambuc void ddekit_usb_server_init()
789*433d6423SLionel Sambuc {
790*433d6423SLionel Sambuc 	int i;
791*433d6423SLionel Sambuc 	/*
792*433d6423SLionel Sambuc 	 * this function has to be called inside the context of an dedicated
793*433d6423SLionel Sambuc 	 * DDELinux thread
794*433d6423SLionel Sambuc 	 */
795*433d6423SLionel Sambuc 	devman_usb_init(bind_cb, unbind_cb);
796*433d6423SLionel Sambuc 	ddekit_usb_init(&my_driver, &my_malloc, &my_free);
797*433d6423SLionel Sambuc 	for (i = 0; i< MAX_DRIVERS; i++) {
798*433d6423SLionel Sambuc 		gbl_drivers[i].dev = DRIVER_UNUSED;
799*433d6423SLionel Sambuc 		gbl_drivers[i].dev = INVAL_DEV;
800*433d6423SLionel Sambuc 	}
801*433d6423SLionel Sambuc 	_ddekit_usb_thread(NULL);
802*433d6423SLionel Sambuc 
803*433d6423SLionel Sambuc }
804