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>
9 #include <minix/usb_ch9.h>
10 #include <minix/devman.h>
14 #define DRIVER_UNUSED 0
15 #define DRIVER_ACTIVE 1
16 #define DRIVER_BOUND 2
19 #define DEBUG_MSG(fmt, ...) ddekit_printf("%s : "fmt"\n", __func__, ##__VA_ARGS__ )
21 #define DEBUG_MSG(fmt, ...)
29 #define MAX_DRIVERS 256
32 #define INVAL_DEV (-1)
36 struct ddekit_usb_urb
*d_urb
;
37 struct usb_urb
*mx_urb
;
38 struct minix_usb_driver
*drv
;
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
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
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
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 /*****************************************************************************
109 ****************************************************************************/
110 static struct minix_usb_driver
*find_driver(endpoint_t ep
)
113 for (i
= 0; i
< MAX_DRIVERS
; i
++ ){
114 if (gbl_drivers
[i
].ep
== ep
) {
115 return &gbl_drivers
[i
];
121 /*****************************************************************************
122 * find_unused_driver *
123 ****************************************************************************/
124 static struct minix_usb_driver
*find_unused_driver()
127 for (i
= 0; i
< MAX_DRIVERS
; i
++ ){
128 if (gbl_drivers
[i
].status
== DRIVER_UNUSED
) {
129 return &gbl_drivers
[i
];
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
)
143 for (i
= 0; i
< MAX_URBS
; i
++) {
144 if (drv
->urbs
[i
] == NULL
) {
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
)
161 for (i
= 0; i
< MAX_URBS
; i
++) {
162 if (drv
->urbs
[i
] == urb
) {
171 /*****************************************************************************
173 ****************************************************************************/
174 static struct ddekit_usb_urb
* find_pending_urb(struct minix_usb_driver
*drv
,
179 for (i
= 0; i
< MAX_URBS
; i
++) {
180 if (((struct my_context
*)drv
->urbs
[i
]->priv
)->urb_id
== urb_id
) {
188 /*****************************************************************************
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
;
203 msg
->m_type
= USB_REPLY
;
204 msg
->USB_RESULT
= EPERM
;
209 DEBUG_MSG("DRIVER %d registered \n"
210 "Announcing device %d, interfaces 0x%x\n",
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
;
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.");
237 /* do not accept requests for this client anymore! */
238 drv
->status
= DRIVER_UNUSED
;
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)
255 struct ddekit_usb_urb
*d_urb
= (struct ddekit_usb_urb
*)
256 my_malloc(sizeof(struct ddekit_usb_urb
));
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
;
284 /*****************************************************************************
286 ****************************************************************************/
287 static void submit_urb(message
*msg
)
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
298 endpoint_t ep
= msg
->m_source
;
299 struct minix_usb_driver
*drv
;
302 if ( (drv
= find_driver(ep
)) == NULL
) {
303 DEBUG_MSG("Non-registered driver tries to send URB.");
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.");
319 res
= sys_safecopyfrom(ep
, msg
->USB_GRANT_ID
, 0,
320 (vir_bytes
) &mx_urb
->dev_id
, msg
->USB_GRANT_SIZE
);
323 DEBUG_MSG("sys_safecopyfrom failed ");
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.");
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
;
347 struct my_context
*ctx
= (struct my_context
*)
348 my_malloc(sizeof(struct my_context
));
356 ctx
->urb_id
= drv
->urb_id
++;
357 mx_urb
->urb_id
= ctx
->urb_id
;
358 ctx
->mx_urb
= mx_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
);
367 res
= add_to_pending_urbs(drv
, d_urb
);
370 DEBUG_MSG("submitting urb...");
371 res
= ddekit_usb_submit_urb(d_urb
);
373 DEBUG_MSG("submitting urb failed (err: %d)", res
);
374 remove_from_pending_urbs(drv
, d_urb
);
380 msg
->m_type
= USB_REPLY
;
381 msg
->USB_URB_ID
= mx_urb
->urb_id
;
382 msg
->USB_RESULT
= res
;
386 if (mx_urb
!= NULL
) {
408 * Cancels the submission of an URB identified by a URB_id
410 /*****************************************************************************
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
;
423 if ( (drv
= find_driver(ep
)) == NULL
) {
424 DEBUG_MSG("Non-registered driver tries to cancel URB.");
427 struct ddekit_usb_urb
*d_urb
= NULL
;
429 d_urb
= find_pending_urb(drv
, msg
->USB_URB_ID
);
432 ddekit_usb_cancle_urb(d_urb
);
435 DEBUG_MSG("No URB to cancle");
436 msg
->USB_RESULT
= ENODEV
;
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
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
);
475 res
= sys_safecopyto(drv
->ep
, ctx
->gid
, 0,
476 (vir_bytes
) ((char*)mx_urb
) + sizeof(void*),
477 mx_urb
->urb_size
- sizeof(void*));
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
);
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
)
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
);
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 ****************************************************************************/
535 device_connect_callback
536 (struct ddekit_usb_dev
* dev
, unsigned int interfaces
) {
540 /* add to device list */
541 for (i
=0; i
< MAX_DEVS
; i
++) {
542 if (_devices
[i
].dev
== NULL
)
547 DEBUG_MSG("Too much devices...");
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
);
564 ddekit_usb_dev_set_data(dev
, dudev
);
566 res
= devman_usb_device_add(dudev
);
574 /*****************************************************************************
575 * device_disconnect_callback *
576 ****************************************************************************/
577 static void device_disconnect_callback(struct ddekit_usb_dev
* dev
)
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
];
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
);
609 devman_usb_device_remove(dudev
);
611 /* free the devman dev */
612 devman_usb_device_delete(dudev
);
616 /*****************************************************************************
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.
625 struct minix_usb_driver
*drv
;
627 if (_devices
[dev_id
].dev
== NULL
) {
628 /* if no device with that ID */
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
);
641 /* bind device to client */
642 drv
= find_unused_driver();
648 drv
->status
= DRIVER_BOUND
;
650 drv
->interfaces
= 1 << interfaces
;
657 /*****************************************************************************
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;
667 drv
= find_driver(ep
);
675 if (drv
->status
== DRIVER_ACTIVE
) {
680 drv
->status
= DRIVER_UNUSED
;
681 drv
->dev
= INVAL_DEV
;
684 msg
.m_type
= USB_WITHDRAW_DEV
;
685 msg
.USB_DEV_ID
= dev
;
686 asynsend3(ep
, &msg
, AMF_NOREPLY
);
692 /*****************************************************************************
694 ****************************************************************************/
695 static int handle_msg(message
*msg
)
700 * The dispatcher for USB related messages.
703 switch(msg
->m_type
) {
705 register_driver(msg
);
708 deregister_driver(msg
);
710 case USB_RQ_SEND_URB
:
713 case USB_RQ_CANCEL_URB
:
721 /*****************************************************************************
723 ****************************************************************************/
724 static void devman_thread(void *unused
)
726 struct ddekit_minix_msg_q
*mq
= ddekit_minix_create_msg_q(DEVMAN_BASE
,
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
,
747 /* create devman thread */
748 ddekit_thread_t
* dmth
;
750 dmth
= ddekit_thread_create(devman_thread
, NULL
, "devman_thread");
753 ddekit_minix_rcv(mq
, &m
, &ipc_status
);
759 /*****************************************************************************
761 ****************************************************************************/
762 static int bind_cb (struct devman_usb_bind_cb_data
*data
, endpoint_t ep
)
765 return add_acl(data
->dev_id
, data
->interface
, ep
);
767 printf("warning: missing cb_data!\n");
772 /*****************************************************************************
774 ****************************************************************************/
775 static int unbind_cb (struct devman_usb_bind_cb_data
*data
, endpoint_t ep
)
778 return del_acl(data
->dev_id
, data
->interface
, ep
);
780 printf("warning: missing cb_data!\n");
785 /*****************************************************************************
786 * ddekit_usb_server_init *
787 ****************************************************************************/
788 void ddekit_usb_server_init()
792 * this function has to be called inside the context of an dedicated
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
);