Remove building with NOCRYPTO option
[minix.git] / minix / lib / libddekit / src / usb_server.c
blob2fb87eb5ba26e3ca1ae7cbe7ddb9f278df1e0d4a
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 get_info(message *msg);
75 static void completion_callback(void *priv);
77 static void prepare_devman_usbdev(struct ddekit_usb_dev * dev, int
78 dev_id, unsigned int interfaces, struct devman_usb_dev *dudev);
79 static void device_disconnect_callback(struct ddekit_usb_dev * dev);
80 static int add_acl(int dev_id, unsigned interfaces, endpoint_t ep);
81 static int del_acl(int dev_id, unsigned interaces, endpoint_t ep);
82 static int handle_msg(message *msg);
83 static void _ddekit_usb_thread();
84 static void device_connect_callback(struct ddekit_usb_dev * dev,
85 unsigned int interfaces);
87 char *_ddekit_usb_get_manufacturer(struct ddekit_usb_dev *ddev);
88 char *_ddekit_usb_get_product(struct ddekit_usb_dev *ddev);
89 char *_ddekit_usb_get_serial(struct ddekit_usb_dev *ddev);
90 usb_device_descriptor_t *_ddekit_usb_get_device_desc(struct
91 ddekit_usb_dev *ddev);
92 usb_interface_descriptor_t *_ddekit_usb_get_interface_desc(struct
93 ddekit_usb_dev *ddev, int inum);
96 static ddekit_usb_malloc_fn my_malloc;
97 static ddekit_usb_free_fn my_free;
98 static struct minix_usb_driver gbl_drivers[MAX_DRIVERS];
99 static struct minix_usb_device _devices[MAX_DEVS];
101 static struct ddekit_usb_driver my_driver = {
102 .completion = completion_callback,
103 .connect = device_connect_callback,
104 .disconnect = device_disconnect_callback,
108 /*****************************************************************************
109 * find_driver *
110 ****************************************************************************/
111 static struct minix_usb_driver *find_driver(endpoint_t ep)
113 int i;
114 for (i = 0; i < MAX_DRIVERS; i++ ){
115 if (gbl_drivers[i].ep == ep) {
116 return &gbl_drivers[i];
119 return NULL;
122 /*****************************************************************************
123 * find_unused_driver *
124 ****************************************************************************/
125 static struct minix_usb_driver *find_unused_driver()
127 int i;
128 for (i = 0; i < MAX_DRIVERS; i++ ){
129 if (gbl_drivers[i].status == DRIVER_UNUSED) {
130 return &gbl_drivers[i];
133 return NULL;
136 /*****************************************************************************
137 * add_to_pending_urbs *
138 ****************************************************************************/
139 static int add_to_pending_urbs(struct minix_usb_driver *drv,
140 struct ddekit_usb_urb *urb)
142 int i;
144 for (i = 0; i < MAX_URBS; i++) {
145 if (drv->urbs[i] == NULL) {
146 drv->urbs[i] = urb;
147 return 0;
151 return -1;
154 /*****************************************************************************
155 * remove_from_pending_urbs *
156 ****************************************************************************/
157 static int remove_from_pending_urbs(struct minix_usb_driver *drv,
158 struct ddekit_usb_urb *urb)
160 int i;
162 for (i = 0; i < MAX_URBS; i++) {
163 if (drv->urbs[i] == urb) {
164 drv->urbs[i] = NULL;
165 return 0;
169 return -1;
172 /*****************************************************************************
173 * find_pending_urb *
174 ****************************************************************************/
175 static struct ddekit_usb_urb * find_pending_urb(struct minix_usb_driver *drv,
176 unsigned urb_id)
178 int i;
180 for (i = 0; i < MAX_URBS; i++) {
181 if (((struct my_context*)drv->urbs[i]->priv)->urb_id == urb_id) {
182 return drv->urbs[i];
186 return NULL;
189 /*****************************************************************************
190 * register_driver *
191 ****************************************************************************/
192 static void register_driver(message *msg)
194 endpoint_t ep = msg->m_source;
195 struct minix_usb_driver *drv;
197 msg->m_type=USB_REPLY;
199 if ( (drv = find_driver(ep)) != NULL) {
200 msg->m_type = USB_REPLY;
201 msg->USB_RESULT = OK;
202 ipc_send(ep,msg);
203 } else {
204 msg->m_type = USB_REPLY;
205 msg->USB_RESULT = EPERM;
206 ipc_send(ep,msg);
207 return;
210 DEBUG_MSG("DRIVER %d registered \n"
211 "Announcing device %d, interfaces 0x%x\n",
213 drv->dev,
214 drv->interfaces);
216 /* hand out the device */
217 msg->m_type = USB_ANNOUCE_DEV;
218 msg->USB_DEV_ID = drv->dev;
219 msg->USB_INTERFACES = drv->interfaces;
220 ipc_send(ep, msg);
223 /*****************************************************************************
224 * deregister_driver *
225 ****************************************************************************/
226 static void deregister_driver(message *msg)
228 endpoint_t ep = msg->m_source;
230 struct minix_usb_driver *drv;
232 msg->m_type=USB_REPLY;
234 if ( (drv = find_driver(ep)) == NULL) {
235 DEBUG_MSG("Non-registered driver tries to unregister.");
236 return;
237 } else {
238 /* do not accept requests for this client anymore! */
239 drv->status = DRIVER_UNUSED;
241 msg->USB_RESULT = 0;
242 asynsend3(ep, msg, AMF_NOREPLY);
246 /*****************************************************************************
247 * ddekit_usb_urb_from_mx_urb *
248 ****************************************************************************/
249 static struct ddekit_usb_urb *ddekit_usb_urb_from_mx_urb(struct usb_urb *mx_urb)
252 * A helper function that generates (allocates and initializes)
253 * a ddekit_usb_urb.
256 struct ddekit_usb_urb *d_urb = (struct ddekit_usb_urb *)
257 my_malloc(sizeof(struct ddekit_usb_urb));
259 if (d_urb == NULL) {
260 return NULL;
263 d_urb->type = mx_urb->type;
264 d_urb->direction = mx_urb->direction;
265 d_urb->transfer_flags = mx_urb->transfer_flags;
266 d_urb->size = mx_urb->size;
267 d_urb->data = mx_urb->buffer;
268 d_urb->interval = mx_urb->interval;
269 d_urb->endpoint = mx_urb->endpoint;
271 if (d_urb->type == USB_TRANSFER_CTL) {
272 d_urb->setup_packet = mx_urb->setup_packet;
274 DEBUG_MSG("setup_package at %p", d_urb->setup_packet);
276 if (d_urb->type == USB_TRANSFER_ISO) {
277 d_urb->iso_desc = (struct ddekit_usb_iso_packet_desc *)
278 mx_urb->buffer + mx_urb->iso_desc_offset;
279 d_urb->number_of_packets = mx_urb->number_of_packets;
282 return d_urb;
285 /*****************************************************************************
286 * submit_urb *
287 ****************************************************************************/
288 static void submit_urb(message *msg)
291 * submit_urb
293 * Handles a submit_urb from a minix USB device driver. It copies the
294 * usb_urb structure containing the buffers and generates and tries to
295 * submit a ddekit_usb_urb. The reference to the ddekit_usb_urb is stored
296 * in the driver structure in order to be able to cancle the URB on the
297 * clients request.
299 endpoint_t ep = msg->m_source;
300 struct minix_usb_driver *drv;
302 /* find driver */
303 if ( (drv = find_driver(ep)) == NULL) {
304 DEBUG_MSG("Non-registered driver tries to send URB.");
305 return;
306 } else {
308 int res;
309 struct my_context *ctx = NULL;
310 struct ddekit_usb_urb *d_urb = NULL;
312 struct usb_urb *mx_urb = (struct usb_urb*)
313 my_malloc(msg->USB_GRANT_SIZE+sizeof(void *));
315 if (mx_urb == NULL) {
316 DEBUG_MSG("Can't allocat mem for mx_urb.");
317 res = ENOMEM;
318 goto out;
321 /* copy in URB */
322 res = sys_safecopyfrom(ep, msg->USB_GRANT_ID, 0,
323 (vir_bytes) &mx_urb->dev_id, msg->USB_GRANT_SIZE);
325 if (res != 0) {
326 DEBUG_MSG("sys_safecopyfrom failed ");
327 my_free(mx_urb);
328 res = EINVAL;
329 goto out;
332 DEBUG_MSG("URB type: %d", mx_urb->type);
333 /* check if urb is valid */
334 if (mx_urb->dev_id >= MAX_DEVS || mx_urb->dev_id < 0) {
335 DEBUG_MSG("Bogus device ID.");
336 res = EINVAL;
337 goto out;
340 /* create ddekit_usb_urb */
341 d_urb = ddekit_usb_urb_from_mx_urb(mx_urb);
342 d_urb->dev = _devices[drv->dev].dev;
343 /* submit urb */
345 if (!d_urb) {
346 res = ENOMEM;
347 goto out;
350 ctx = my_malloc(sizeof(struct my_context));
352 if(!ctx) {
353 res = ENOMEM;
354 goto out;
357 ctx->drv = drv;
358 ctx->urb_id = drv->urb_id++;
359 mx_urb->urb_id = ctx->urb_id;
360 ctx->mx_urb = mx_urb;
361 ctx->d_urb = d_urb;
362 ctx->gid = msg->USB_GRANT_ID;
364 DEBUG_MSG("ctx: %p, urb_id: %d, d_urb: %p, mx_urb: %p, drv: %d, gid: %d ",
365 ctx, ctx->urb_id, ctx->d_urb, ctx->mx_urb, ctx->drv, ctx->gid);
367 d_urb->priv = ctx;
369 res = add_to_pending_urbs(drv, d_urb);
371 if (res == 0) {
372 DEBUG_MSG("submitting urb...");
373 res = ddekit_usb_submit_urb(d_urb);
374 if(res) {
375 DEBUG_MSG("submitting urb failed (err: %d)", res);
376 remove_from_pending_urbs(drv, d_urb);
380 out:
381 /* reply */
382 msg->m_type = USB_REPLY;
383 msg->USB_URB_ID = mx_urb->urb_id;
384 msg->USB_RESULT = res;
386 if(res != 0) {
388 if (mx_urb != NULL) {
389 my_free(mx_urb);
391 if (ctx != NULL) {
392 my_free(ctx);
395 if (d_urb != NULL) {
396 my_free(d_urb);
401 /* send reply */
402 ipc_send(ep, msg);
408 * cancle_urb
410 * Cancels the submission of an URB identified by a URB_id
412 /*****************************************************************************
413 * cancle_urb *
414 ****************************************************************************/
415 static void cancle_urb(message *msg)
417 endpoint_t ep = msg->m_source;
419 struct minix_usb_driver *drv;
421 msg->USB_RESULT = -1;
422 msg->m_type = USB_REPLY;
424 /* find driver */
425 if ( (drv = find_driver(ep)) == NULL) {
426 DEBUG_MSG("Non-registered driver tries to cancel URB.");
427 return;
428 } else {
429 struct ddekit_usb_urb *d_urb = NULL;
431 d_urb = find_pending_urb(drv, msg->USB_URB_ID);
433 if (d_urb != NULL) {
434 ddekit_usb_cancle_urb(d_urb);
435 msg->USB_RESULT = 0;
436 } else {
437 DEBUG_MSG("No URB to cancle");
438 msg->USB_RESULT = ENODEV;
442 ipc_send(ep, msg);
446 /*****************************************************************************
447 * get_info *
448 *****************************************************************************/
449 static void
450 get_info(message * msg)
452 struct minix_usb_driver * drv;
453 endpoint_t ep;
454 long info_type;
455 long info_value;
457 /* Read */
458 ep = msg->m_source;
459 info_type = msg->USB_INFO_TYPE;
460 info_value = msg->USB_INFO_VALUE;
462 /* Reuse as reply */
463 msg->m_type = USB_REPLY;
464 msg->USB_RESULT = -1;
466 /* Try and find driver first */
467 if (NULL == (drv = find_driver(ep)))
468 ddekit_printf("Non-registered driver tries to send info");
469 else
470 /* Route info to device */
471 msg->USB_RESULT = ddekit_usb_info(_devices[drv->dev].dev,
472 info_type, info_value);
474 /* Reply */
475 ipc_send(ep, msg);
479 /*****************************************************************************
480 * completion_callback *
481 ****************************************************************************/
482 static void completion_callback(void *priv)
485 * completion_callback
487 * This is called by the DDE side. Here the data is copied back to
488 * the driver and a message is send to inform the driver about the
489 * completion.
491 message msg;
492 int res;
493 struct my_context *ctx = (struct my_context *)priv;
494 struct usb_urb *mx_urb = ctx->mx_urb;
495 struct ddekit_usb_urb *d_urb = ctx->d_urb;
496 struct minix_usb_driver *drv = ctx->drv;
498 DEBUG_MSG("ctx: %p, urb_id: %d, d_urb: %p, mx_urb: %p, drv: %d, gid: %d ",
499 ctx, ctx->urb_id, ctx->d_urb, ctx->mx_urb, ctx->drv, ctx->gid);
501 /* update data in minix URB */
502 mx_urb->status = d_urb->status;
503 mx_urb->actual_length = d_urb->actual_length;
504 mx_urb->error_count = d_urb->error_count;
505 mx_urb->transfer_flags = d_urb->transfer_flags;
507 remove_from_pending_urbs(drv, d_urb);
509 /* copy out URB */
510 res = sys_safecopyto(drv->ep, ctx->gid, 0,
511 (vir_bytes) ((char*)mx_urb) + sizeof(void*),
512 mx_urb->urb_size - sizeof(void*));
514 if (res != 0) {
515 DEBUG_MSG("Copy out failed: %d", res);
516 DEBUG_MSG(" URB ID: %d, Grant-ID: %d, Grant-size: %d", ctx->urb_id,
517 ctx->gid, mx_urb->urb_size);
520 /* send message to client */
521 msg.m_type = USB_COMPLETE_URB;
522 msg.USB_URB_ID = ctx->urb_id;
523 asynsend3(drv->ep, &msg, AMF_NOREPLY);
525 /* free stuff */
526 my_free(ctx);
527 my_free(mx_urb);
528 my_free(d_urb);
532 /*****************************************************************************
533 * prepare_devman_usbdev *
534 ****************************************************************************/
535 static void prepare_devman_usbdev
536 (struct ddekit_usb_dev * dev, int dev_id, unsigned int interfaces,
537 struct devman_usb_dev *dudev)
539 int j;
540 int intf_count;
542 * currently this is only implemented by stub driver
545 usb_device_descriptor_t *desc = _ddekit_usb_get_device_desc(dev);
547 dudev->manufacturer = _ddekit_usb_get_manufacturer(dev);
548 dudev->product = _ddekit_usb_get_product(dev);
549 dudev->serial = _ddekit_usb_get_serial(dev);
551 dudev->desc = desc;
553 intf_count = 0;
555 for (j=0; j < 32; j++) {
556 if (interfaces & (1 << j)) {
557 dudev->interfaces[intf_count++].desc =
558 _ddekit_usb_get_interface_desc(dev, j);
562 dudev->intf_count = intf_count;
563 dudev->dev_id = dev_id;
566 /*****************************************************************************
567 * device_connect_callback *
568 ****************************************************************************/
569 static void
570 device_connect_callback
571 (struct ddekit_usb_dev * dev, unsigned int interfaces) {
573 int i, res;
575 /* add to device list */
576 for (i=0; i < MAX_DEVS; i++) {
577 if (_devices[i].dev == NULL)
578 break;
581 if (i >= MAX_DEVS) {
582 DEBUG_MSG("Too much devices...");
583 } else {
584 _devices[i].dev = dev;
585 _devices[i].interfaces = (1 << interfaces);
588 struct devman_usb_dev *dudev;
590 dudev = devman_usb_device_new(i);
592 prepare_devman_usbdev(dev, i, interfaces, dudev);
594 if (dudev == NULL) {
595 /* TODO: ERROR */
596 printf("ERROR: !");
599 ddekit_usb_dev_set_data(dev, dudev);
601 res = devman_usb_device_add(dudev);
603 if (res != 0) {
604 /* TODO: Error*/
605 printf("ERROR!");
609 /*****************************************************************************
610 * device_disconnect_callback *
611 ****************************************************************************/
612 static void device_disconnect_callback(struct ddekit_usb_dev * dev)
614 int i;
616 /* remove ACL entry */
617 for (i = 0; i< MAX_DRIVERS; i++) {
618 if (gbl_drivers[i].dev != INVAL_DEV
619 && _devices[gbl_drivers[i].dev].dev == dev) {
620 struct minix_usb_driver *drv = &gbl_drivers[i];
621 drv->ep = 0;
622 drv->status = DRIVER_UNUSED;
623 drv->dev = INVAL_DEV;
627 for (i=0; i < MAX_DEVS; i++) {
628 if (_devices[i].dev == dev) {
629 _devices[i].dev = NULL;
630 _devices[i].interfaces = 0;
635 /* get the devman device */
636 struct devman_usb_dev * dudev = NULL;
638 dudev = ddekit_usb_dev_get_data(dev);
640 if (dudev == NULL) {
641 /* TODO: error */
644 devman_usb_device_remove(dudev);
646 /* free the devman dev */
647 devman_usb_device_delete(dudev);
651 /*****************************************************************************
652 * add_acl *
653 ****************************************************************************/
654 static int add_acl(int dev_id, unsigned interfaces, endpoint_t ep)
657 * This functions binds a specific USB interface to a client.
659 int i;
660 struct minix_usb_driver *drv;
662 if (_devices[dev_id].dev == NULL) {
663 /* if no device with that ID */
664 return ENODEV;
667 /* is the device allready given to a client*/
668 for (i = 0; i< MAX_DRIVERS; i++) {
669 if (gbl_drivers[i].status != DRIVER_UNUSED &&
670 gbl_drivers[i].dev == dev_id) {
671 printf("devid: %d\n", dev_id);
672 return EBUSY;
676 /* bind device to client */
677 drv = find_unused_driver();
679 if (drv == NULL) {
680 return ENOMEM;
683 drv->status = DRIVER_BOUND;
684 drv->dev = dev_id;
685 drv->interfaces = 1 << interfaces;
686 drv->ep = ep;
687 drv->urb_id = 0;
689 return OK;
692 /*****************************************************************************
693 * del_acl *
694 ****************************************************************************/
695 static int del_acl(int dev_id, unsigned interfaces, endpoint_t ep)
697 struct minix_usb_driver *drv;
698 int dev, withdraw = 0;
699 message msg;
701 /* find driver */
702 drv = find_driver(ep);
704 if (drv == NULL) {
705 return ENOENT;
708 dev = drv->dev;
710 if (drv->status == DRIVER_ACTIVE) {
711 withdraw = 1;
714 drv->ep = 0;
715 drv->status = DRIVER_UNUSED;
716 drv->dev = INVAL_DEV;
718 if (withdraw) {
719 msg.m_type = USB_WITHDRAW_DEV;
720 msg.USB_DEV_ID = dev;
721 asynsend3(ep, &msg, AMF_NOREPLY);
724 return 0;
727 /*****************************************************************************
728 * handle_msg *
729 ****************************************************************************/
730 static int handle_msg(message *msg)
733 * handle_msg
735 * The dispatcher for USB related messages.
738 switch(msg->m_type) {
739 case USB_RQ_INIT:
740 register_driver(msg);
741 return 1;
742 case USB_RQ_DEINIT:
743 deregister_driver(msg);
744 return 1;
745 case USB_RQ_SEND_URB:
746 submit_urb(msg);
747 return 1;
748 case USB_RQ_CANCEL_URB:
749 cancle_urb(msg);
750 return 1;
751 case USB_RQ_SEND_INFO:
752 get_info(msg);
753 return 1;
754 default:
755 return 0;
759 /*****************************************************************************
760 * devman_tread *
761 ****************************************************************************/
762 static void devman_thread(void *unused)
764 struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(DEVMAN_BASE,
765 DEVMAN_BASE + 0xff);
766 int ipc_status;
767 message m;
768 while (1) {
769 ddekit_minix_rcv(mq, &m, &ipc_status);
770 devman_handle_msg(&m);
774 /*****************************************************************************
775 * _ddekit_usb_thread *
776 ****************************************************************************/
777 static void _ddekit_usb_thread(void * unused)
779 struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(USB_BASE,
780 USB_BASE + 0xff);
782 message m;
783 int ipc_status;
785 /* create devman thread */
786 ddekit_thread_t * __unused dmth;
788 dmth = ddekit_thread_create(devman_thread, NULL, "devman_thread");
790 while (1) {
791 ddekit_minix_rcv(mq, &m, &ipc_status);
792 handle_msg(&m);
797 /*****************************************************************************
798 * bind_cb *
799 ****************************************************************************/
800 static int bind_cb (struct devman_usb_bind_cb_data *data, endpoint_t ep)
802 if(data) {
803 return add_acl(data->dev_id, data->interface, ep);
804 } else {
805 printf("warning: missing cb_data!\n");
806 return EINVAL;
810 /*****************************************************************************
811 * unbind_cb *
812 ****************************************************************************/
813 static int unbind_cb (struct devman_usb_bind_cb_data *data, endpoint_t ep)
815 if(data) {
816 return del_acl(data->dev_id, data->interface, ep);
817 } else {
818 printf("warning: missing cb_data!\n");
819 return EINVAL;
823 /*****************************************************************************
824 * ddekit_usb_server_init *
825 ****************************************************************************/
826 void ddekit_usb_server_init()
828 int i;
830 * this function has to be called inside the context of an dedicated
831 * DDELinux thread
833 devman_usb_init(bind_cb, unbind_cb);
834 ddekit_usb_init(&my_driver, &my_malloc, &my_free);
835 for (i = 0; i< MAX_DRIVERS; i++) {
836 gbl_drivers[i].dev = DRIVER_UNUSED;
837 gbl_drivers[i].dev = INVAL_DEV;
839 _ddekit_usb_thread(NULL);