pkgin_all: script to auto-install all packages
[minix.git] / lib / libddekit / src / usb_server.c
blob88bfdaa77f8db521d1dde8e25ed9a794c4be208b
1 #include "common.h"
3 #include <ddekit/minix/msg_queue.h>
4 #include <ddekit/panic.h>
5 #include <ddekit/printf.h>
6 #include <ddekit/usb.h>
7 #include <minix/safecopies.h>
8 #include <minix/usb.h>
9 #include <minix/usb_ch9.h>
10 #include <minix/devman.h>
12 #define MAX_URBS 10
14 #define DRIVER_UNUSED 0
15 #define DRIVER_ACTIVE 1
16 #define DRIVER_BOUND 2
18 #if 0
19 #define DEBUG_MSG(fmt, ...) ddekit_printf("%s : "fmt"\n", __func__, ##__VA_ARGS__ )
20 #else
21 #define DEBUG_MSG(fmt, ...)
22 #endif
24 #undef DDEBUG
25 #define DDEBUG 0
26 #include "debug.h"
28 #define MAX_DEVS 256
29 #define MAX_DRIVERS 256
30 #define OK 0
32 #define INVAL_DEV (-1)
34 struct my_context {
35 unsigned urb_id;
36 struct ddekit_usb_urb *d_urb;
37 struct usb_urb *mx_urb;
38 struct minix_usb_driver *drv;
39 gid_t gid;
42 struct minix_usb_driver {
43 endpoint_t ep; /* address of the client */
45 int status; /* In what state is the client? */
47 int dev; /* which device is this driver handling */
48 unsigned interfaces; /* which interfaces of the device the
49 driver is handling */
51 struct ddekit_usb_urb *urbs[MAX_URBS]; /* pending urbs */
53 unsigned long urb_id; /* generation of driver_local urb_ids */
56 struct minix_usb_device {
57 struct ddekit_usb_dev *dev;
58 unsigned int interfaces;
61 static struct minix_usb_driver *find_driver(endpoint_t ep);
62 static struct minix_usb_driver *find_unused_driver(void);
63 static int add_to_pending_urbs(struct minix_usb_driver *drv, struct
64 ddekit_usb_urb *urb);
65 static int remove_from_pending_urbs(struct minix_usb_driver *drv,
66 struct ddekit_usb_urb *urb);
67 static struct ddekit_usb_urb * find_pending_urb(struct minix_usb_driver
68 *drv, unsigned urb_id);
69 static void register_driver(message *msg);
70 static struct ddekit_usb_urb *ddekit_usb_urb_from_mx_urb(struct usb_urb
71 *mx_urb);
72 static void submit_urb(message *msg);
73 static void cancle_urb(message *msg);
74 static void completion_callback(void *priv);
76 static void prepare_devman_usbdev(struct ddekit_usb_dev * dev, int
77 dev_id, unsigned int interfaces, struct devman_usb_dev *dudev);
78 static void device_disconnect_callback(struct ddekit_usb_dev * dev);
79 static int add_acl(int dev_id, unsigned interfaces, endpoint_t ep);
80 static int del_acl(int dev_id, unsigned interaces, endpoint_t ep);
81 static int handle_msg(message *msg);
82 static void _ddekit_usb_thread();
83 static void device_connect_callback(struct ddekit_usb_dev * dev,
84 unsigned int interfaces);
86 char *_ddekit_usb_get_manufacturer(struct ddekit_usb_dev *ddev);
87 char *_ddekit_usb_get_product(struct ddekit_usb_dev *ddev);
88 char *_ddekit_usb_get_serial(struct ddekit_usb_dev *ddev);
89 usb_device_descriptor_t *_ddekit_usb_get_device_desc(struct
90 ddekit_usb_dev *ddev);
91 usb_interface_descriptor_t *_ddekit_usb_get_interface_desc(struct
92 ddekit_usb_dev *ddev, int inum);
95 static ddekit_usb_malloc_fn my_malloc;
96 static ddekit_usb_free_fn my_free;
97 static struct minix_usb_driver gbl_drivers[MAX_DRIVERS];
98 static struct minix_usb_device _devices[MAX_DEVS];
100 static struct ddekit_usb_driver my_driver = {
101 .completion = completion_callback,
102 .connect = device_connect_callback,
103 .disconnect = device_disconnect_callback,
107 /*****************************************************************************
108 * find_driver *
109 ****************************************************************************/
110 static struct minix_usb_driver *find_driver(endpoint_t ep)
112 int i;
113 for (i = 0; i < MAX_DRIVERS; i++ ){
114 if (gbl_drivers[i].ep == ep) {
115 return &gbl_drivers[i];
118 return NULL;
121 /*****************************************************************************
122 * find_unused_driver *
123 ****************************************************************************/
124 static struct minix_usb_driver *find_unused_driver()
126 int i;
127 for (i = 0; i < MAX_DRIVERS; i++ ){
128 if (gbl_drivers[i].status == DRIVER_UNUSED) {
129 return &gbl_drivers[i];
132 return NULL;
135 /*****************************************************************************
136 * add_to_pending_urbs *
137 ****************************************************************************/
138 static int add_to_pending_urbs(struct minix_usb_driver *drv,
139 struct ddekit_usb_urb *urb)
141 int i;
143 for (i = 0; i < MAX_URBS; i++) {
144 if (drv->urbs[i] == NULL) {
145 drv->urbs[i] = urb;
146 return 0;
150 return -1;
153 /*****************************************************************************
154 * remove_from_pending_urbs *
155 ****************************************************************************/
156 static int remove_from_pending_urbs(struct minix_usb_driver *drv,
157 struct ddekit_usb_urb *urb)
159 int i;
161 for (i = 0; i < MAX_URBS; i++) {
162 if (drv->urbs[i] == urb) {
163 drv->urbs[i] = NULL;
164 return 0;
168 return -1;
171 /*****************************************************************************
172 * find_pending_urb *
173 ****************************************************************************/
174 static struct ddekit_usb_urb * find_pending_urb(struct minix_usb_driver *drv,
175 unsigned urb_id)
177 int i;
179 for (i = 0; i < MAX_URBS; i++) {
180 if (((struct my_context*)drv->urbs[i]->priv)->urb_id == urb_id) {
181 return drv->urbs[i];
185 return NULL;
188 /*****************************************************************************
189 * register_driver *
190 ****************************************************************************/
191 static void register_driver(message *msg)
193 endpoint_t ep = msg->m_source;
194 struct minix_usb_driver *drv;
196 msg->m_type=USB_REPLY;
198 if ( (drv = find_driver(ep)) != NULL) {
199 msg->m_type = USB_REPLY;
200 msg->USB_RESULT = OK;
201 send(ep,msg);
202 } else {
203 msg->m_type = USB_REPLY;
204 msg->USB_RESULT = EPERM;
205 send(ep,msg);
206 return;
209 DEBUG_MSG("DRIVER %d registered \n"
210 "Announcing device %d, interfaces 0x%x\n",
212 drv->dev,
213 drv->interfaces);
215 /* hand out the device */
216 msg->m_type = USB_ANNOUCE_DEV;
217 msg->USB_DEV_ID = drv->dev;
218 msg->USB_INTERFACES = drv->interfaces;
219 send(ep, msg);
222 /*****************************************************************************
223 * deregister_driver *
224 ****************************************************************************/
225 static void deregister_driver(message *msg)
227 endpoint_t ep = msg->m_source;
229 struct minix_usb_driver *drv;
231 msg->m_type=USB_REPLY;
233 if ( (drv = find_driver(ep)) == NULL) {
234 DEBUG_MSG("Non-registered driver tries to unregister.");
235 return;
236 } else {
237 /* do not accept requests for this client anymore! */
238 drv->status = DRIVER_UNUSED;
240 msg->USB_RESULT = 0;
241 asynsend3(ep, msg, AMF_NOREPLY);
245 /*****************************************************************************
246 * ddekit_usb_urb_from_mx_urb *
247 ****************************************************************************/
248 static struct ddekit_usb_urb *ddekit_usb_urb_from_mx_urb(struct usb_urb *mx_urb)
251 * A helper function that generates (allocates and initializes)
252 * a ddekit_usb_urb.
255 struct ddekit_usb_urb *d_urb = (struct ddekit_usb_urb *)
256 my_malloc(sizeof(struct ddekit_usb_urb));
258 if (d_urb == NULL) {
259 return NULL;
262 d_urb->type = mx_urb->type;
263 d_urb->direction = mx_urb->direction;
264 d_urb->transfer_flags = mx_urb->transfer_flags;
265 d_urb->size = mx_urb->size;
266 d_urb->data = mx_urb->buffer;
267 d_urb->interval = mx_urb->interval;
268 d_urb->endpoint = mx_urb->endpoint;
270 if (d_urb->type == USB_TRANSFER_CTL) {
271 d_urb->setup_packet = mx_urb->setup_packet;
273 DEBUG_MSG("setup_package at %p", d_urb->setup_packet);
275 if (d_urb->type == USB_TRANSFER_ISO) {
276 d_urb->iso_desc = (struct ddekit_usb_iso_packet_desc *)
277 mx_urb->buffer + mx_urb->iso_desc_offset;
278 d_urb->number_of_packets = mx_urb->number_of_packets;
281 return d_urb;
284 /*****************************************************************************
285 * submit_urb *
286 ****************************************************************************/
287 static void submit_urb(message *msg)
290 * submit_urb
292 * Handles a submit_urb from a minix USB device driver. It copies the
293 * usb_urb structure containing the buffers and generates and tries to
294 * submit a ddekit_usb_urb. The reference to the ddekit_usb_urb is stored
295 * in the driver structure in order to be able to cancle the URB on the
296 * clients request.
298 endpoint_t ep = msg->m_source;
299 struct minix_usb_driver *drv;
301 /* find driver */
302 if ( (drv = find_driver(ep)) == NULL) {
303 DEBUG_MSG("Non-registered driver tries to send URB.");
304 return;
305 } else {
307 int res;
309 struct usb_urb *mx_urb = (struct usb_urb*)
310 my_malloc(msg->USB_GRANT_SIZE+sizeof(void *));
312 if (mx_urb == NULL) {
313 DEBUG_MSG("Can't allocat mem for mx_urb.");
314 res = ENOMEM;
315 goto out;
318 /* copy in URB */
319 res = sys_safecopyfrom(ep, msg->USB_GRANT_ID, 0,
320 (vir_bytes) &mx_urb->dev_id, msg->USB_GRANT_SIZE);
322 if (res != 0) {
323 DEBUG_MSG("sys_safecopyfrom failed ");
324 my_free(mx_urb);
325 res = EINVAL;
326 goto out;
329 DEBUG_MSG("URB type: %d", mx_urb->type);
330 /* check if urb is valid */
331 if (mx_urb->dev_id >= MAX_DEVS && mx_urb->dev_id < 0) {
332 DEBUG_MSG("Bogus device ID.");
333 res = EINVAL;
334 goto out;
337 /* create ddekit_usb_urb */
338 struct ddekit_usb_urb *d_urb = ddekit_usb_urb_from_mx_urb(mx_urb);
339 d_urb->dev = _devices[drv->dev].dev;
340 /* submit urb */
342 if (!d_urb) {
343 res = ENOMEM;
344 goto out;
347 struct my_context *ctx = (struct my_context *)
348 my_malloc(sizeof(struct my_context));
350 if(!ctx) {
351 res = ENOMEM;
352 goto out;
355 ctx->drv = drv;
356 ctx->urb_id = drv->urb_id++;
357 mx_urb->urb_id = ctx->urb_id;
358 ctx->mx_urb = mx_urb;
359 ctx->d_urb = d_urb;
360 ctx->gid = msg->USB_GRANT_ID;
362 DEBUG_MSG("ctx: %p, urb_id: %d, d_urb: %p, mx_urb: %p, drv: %d, gid: %d ",
363 ctx, ctx->urb_id, ctx->d_urb, ctx->mx_urb, ctx->drv, ctx->gid);
365 d_urb->priv = ctx;
367 res = add_to_pending_urbs(drv, d_urb);
369 if (res == 0) {
370 DEBUG_MSG("submitting urb...");
371 res = ddekit_usb_submit_urb(d_urb);
372 if(res) {
373 DEBUG_MSG("submitting urb failed (err: %d)", res);
374 remove_from_pending_urbs(drv, d_urb);
378 out:
379 /* reply */
380 msg->m_type = USB_REPLY;
381 msg->USB_URB_ID = mx_urb->urb_id;
382 msg->USB_RESULT = res;
384 if(res != 0) {
386 if (mx_urb != NULL) {
387 my_free(mx_urb);
389 if (ctx != NULL) {
390 my_free(ctx);
393 if (d_urb != NULL) {
394 my_free(d_urb);
399 /* send reply */
400 send(ep, msg);
406 * cancle_urb
408 * Cancels the submission of an URB identified by a URB_id
410 /*****************************************************************************
411 * cancle_urb *
412 ****************************************************************************/
413 static void cancle_urb(message *msg)
415 endpoint_t ep = msg->m_source;
417 struct minix_usb_driver *drv;
419 msg->USB_RESULT = -1;
420 msg->m_type = USB_REPLY;
422 /* find driver */
423 if ( (drv = find_driver(ep)) == NULL) {
424 DEBUG_MSG("Non-registered driver tries to cancel URB.");
425 return;
426 } else {
427 struct ddekit_usb_urb *d_urb = NULL;
429 d_urb = find_pending_urb(drv, msg->USB_URB_ID);
431 if (d_urb != NULL) {
432 ddekit_usb_cancle_urb(d_urb);
433 msg->USB_RESULT = 0;
434 } else {
435 DEBUG_MSG("No URB to cancle");
436 msg->USB_RESULT = ENODEV;
440 send(ep, msg);
444 /*****************************************************************************
445 * completion_callback *
446 ****************************************************************************/
447 static void completion_callback(void *priv)
450 * completion_callback
452 * This is called by the DDE side. Here the data is copied back to
453 * the driver and a message is send to inform the driver about the
454 * completion.
456 message msg;
457 int res;
458 struct my_context *ctx = (struct my_context *)priv;
459 struct usb_urb *mx_urb = ctx->mx_urb;
460 struct ddekit_usb_urb *d_urb = ctx->d_urb;
461 struct minix_usb_driver *drv = ctx->drv;
463 DEBUG_MSG("ctx: %p, urb_id: %d, d_urb: %p, mx_urb: %p, drv: %d, gid: %d ",
464 ctx, ctx->urb_id, ctx->d_urb, ctx->mx_urb, ctx->drv, ctx->gid);
466 /* update data in minix URB */
467 mx_urb->status = d_urb->status;
468 mx_urb->actual_length = d_urb->actual_length;
469 mx_urb->error_count = d_urb->error_count;
470 mx_urb->transfer_flags = d_urb->transfer_flags;
472 remove_from_pending_urbs(drv, d_urb);
474 /* copy out URB */
475 res = sys_safecopyto(drv->ep, ctx->gid, 0,
476 (vir_bytes) ((char*)mx_urb) + sizeof(void*),
477 mx_urb->urb_size - sizeof(void*));
479 if (res != 0) {
480 DEBUG_MSG("Copy out failed: %d", res);
481 DEBUG_MSG(" URB ID: %d, Grant-ID: %d, Grant-size: %d", ctx->urb_id,
482 ctx->gid, mx_urb->urb_size);
485 /* send message to client */
486 msg.m_type = USB_COMPLETE_URB;
487 msg.USB_URB_ID = ctx->urb_id;
488 asynsend3(drv->ep, &msg, AMF_NOREPLY);
490 /* free stuff */
491 my_free(ctx);
492 my_free(mx_urb);
493 my_free(d_urb);
497 /*****************************************************************************
498 * prepare_devman_usbdev *
499 ****************************************************************************/
500 static void prepare_devman_usbdev
501 (struct ddekit_usb_dev * dev, int dev_id, unsigned int interfaces,
502 struct devman_usb_dev *dudev)
504 int j;
505 int intf_count;
507 * currently this is only implemented by stub driver
510 usb_device_descriptor_t *desc = _ddekit_usb_get_device_desc(dev);
512 dudev->manufacturer = _ddekit_usb_get_manufacturer(dev);
513 dudev->product = _ddekit_usb_get_product(dev);
514 dudev->serial = _ddekit_usb_get_serial(dev);
516 dudev->desc = desc;
518 intf_count = 0;
520 for (j=0; j < 32; j++) {
521 if (interfaces & (1 << j)) {
522 dudev->interfaces[intf_count++].desc =
523 _ddekit_usb_get_interface_desc(dev, j);
527 dudev->intf_count = intf_count;
528 dudev->dev_id = dev_id;
531 /*****************************************************************************
532 * device_connect_callback *
533 ****************************************************************************/
534 static void
535 device_connect_callback
536 (struct ddekit_usb_dev * dev, unsigned int interfaces) {
538 int i, res;
540 /* add to device list */
541 for (i=0; i < MAX_DEVS; i++) {
542 if (_devices[i].dev == NULL)
543 break;
546 if (i >= MAX_DEVS) {
547 DEBUG_MSG("Too much devices...");
548 } else {
549 _devices[i].dev = dev;
550 _devices[i].interfaces = (1 << interfaces);
553 struct devman_usb_dev *dudev;
555 dudev = devman_usb_device_new(i);
557 prepare_devman_usbdev(dev, i, interfaces, dudev);
559 if (dudev == NULL) {
560 /* TODO: ERROR */
561 printf("ERROR: !");
564 ddekit_usb_dev_set_data(dev, dudev);
566 res = devman_usb_device_add(dudev);
568 if (res != 0) {
569 /* TODO: Error*/
570 printf("ERROR!");
574 /*****************************************************************************
575 * device_disconnect_callback *
576 ****************************************************************************/
577 static void device_disconnect_callback(struct ddekit_usb_dev * dev)
579 int i;
581 /* remove ACL entry */
582 for (i = 0; i< MAX_DRIVERS; i++) {
583 if (gbl_drivers[i].dev != INVAL_DEV
584 && _devices[gbl_drivers[i].dev].dev == dev) {
585 struct minix_usb_driver *drv = &gbl_drivers[i];
586 drv->ep = 0;
587 drv->status = DRIVER_UNUSED;
588 drv->dev = INVAL_DEV;
592 for (i=0; i < MAX_DEVS; i++) {
593 if (_devices[i].dev == dev) {
594 _devices[i].dev = NULL;
595 _devices[i].interfaces = 0;
600 /* get the devman device */
601 struct devman_usb_dev * dudev = NULL;
603 dudev = ddekit_usb_dev_get_data(dev);
605 if (dudev == NULL) {
606 /* TODO: error */
609 devman_usb_device_remove(dudev);
611 /* free the devman dev */
612 devman_usb_device_delete(dudev);
616 /*****************************************************************************
617 * add_acl *
618 ****************************************************************************/
619 static int add_acl(int dev_id, unsigned interfaces, endpoint_t ep)
622 * This functions binds a specific USB interface to a client.
624 int i;
625 struct minix_usb_driver *drv;
627 if (_devices[dev_id].dev == NULL) {
628 /* if no device with that ID */
629 return ENODEV;
632 /* is the device allready given to a client*/
633 for (i = 0; i< MAX_DRIVERS; i++) {
634 if (gbl_drivers[i].status != DRIVER_UNUSED &&
635 gbl_drivers[i].dev == dev_id) {
636 printf("devid: %d\n", dev_id);
637 return EBUSY;
641 /* bind device to client */
642 drv = find_unused_driver();
644 if (drv == NULL) {
645 return ENOMEM;
648 drv->status = DRIVER_BOUND;
649 drv->dev = dev_id;
650 drv->interfaces = 1 << interfaces;
651 drv->ep = ep;
652 drv->urb_id = 0;
654 return OK;
657 /*****************************************************************************
658 * del_acl *
659 ****************************************************************************/
660 static int del_acl(int dev_id, unsigned interfaces, endpoint_t ep)
662 struct minix_usb_driver *drv;
663 int dev, withdraw = 0;
664 message msg;
666 /* find driver */
667 drv = find_driver(ep);
669 if (drv == NULL) {
670 return ENOENT;
673 dev = drv->dev;
675 if (drv->status == DRIVER_ACTIVE) {
676 withdraw = 1;
679 drv->ep = 0;
680 drv->status = DRIVER_UNUSED;
681 drv->dev = INVAL_DEV;
683 if (withdraw) {
684 msg.m_type = USB_WITHDRAW_DEV;
685 msg.USB_DEV_ID = dev;
686 asynsend3(ep, &msg, AMF_NOREPLY);
689 return 0;
692 /*****************************************************************************
693 * handle_msg *
694 ****************************************************************************/
695 static int handle_msg(message *msg)
698 * handle_msg
700 * The dispatcher for USB related messages.
703 switch(msg->m_type) {
704 case USB_RQ_INIT:
705 register_driver(msg);
706 return 1;
707 case USB_RQ_DEINIT:
708 deregister_driver(msg);
709 return 1;
710 case USB_RQ_SEND_URB:
711 submit_urb(msg);
712 return 1;
713 case USB_RQ_CANCEL_URB:
714 cancle_urb(msg);
715 return 1;
716 default:
717 return 0;
721 /*****************************************************************************
722 * devman_tread *
723 ****************************************************************************/
724 static void devman_thread(void *unused)
726 struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(DEVMAN_BASE,
727 DEVMAN_BASE + 0xff);
728 int ipc_status;
729 message m;
730 while (1) {
731 ddekit_minix_rcv(mq, &m, &ipc_status);
732 devman_handle_msg(&m);
736 /*****************************************************************************
737 * _ddekit_usb_thread *
738 ****************************************************************************/
739 static void _ddekit_usb_thread(void * unused)
741 struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(USB_BASE,
742 USB_BASE + 0xff);
744 message m;
745 int ipc_status;
747 /* create devman thread */
748 ddekit_thread_t * dmth;
750 dmth = ddekit_thread_create(devman_thread, NULL, "devman_thread");
752 while (1) {
753 ddekit_minix_rcv(mq, &m, &ipc_status);
754 handle_msg(&m);
759 /*****************************************************************************
760 * bind_cb *
761 ****************************************************************************/
762 static int bind_cb (struct devman_usb_bind_cb_data *data, endpoint_t ep)
764 if(data) {
765 return add_acl(data->dev_id, data->interface, ep);
766 } else {
767 printf("warning: missing cb_data!\n");
768 return EINVAL;
772 /*****************************************************************************
773 * unbind_cb *
774 ****************************************************************************/
775 static int unbind_cb (struct devman_usb_bind_cb_data *data, endpoint_t ep)
777 if(data) {
778 return del_acl(data->dev_id, data->interface, ep);
779 } else {
780 printf("warning: missing cb_data!\n");
781 return EINVAL;
785 /*****************************************************************************
786 * ddekit_usb_server_init *
787 ****************************************************************************/
788 void ddekit_usb_server_init()
790 int i;
792 * this function has to be called inside the context of an dedicated
793 * DDELinux thread
795 devman_usb_init(bind_cb, unbind_cb);
796 ddekit_usb_init(&my_driver, &my_malloc, &my_free);
797 for (i = 0; i< MAX_DRIVERS; i++) {
798 gbl_drivers[i].dev = DRIVER_UNUSED;
799 gbl_drivers[i].dev = INVAL_DEV;
801 _ddekit_usb_thread(NULL);