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 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 /*****************************************************************************
110 ****************************************************************************/
111 static struct minix_usb_driver
*find_driver(endpoint_t ep
)
114 for (i
= 0; i
< MAX_DRIVERS
; i
++ ){
115 if (gbl_drivers
[i
].ep
== ep
) {
116 return &gbl_drivers
[i
];
122 /*****************************************************************************
123 * find_unused_driver *
124 ****************************************************************************/
125 static struct minix_usb_driver
*find_unused_driver()
128 for (i
= 0; i
< MAX_DRIVERS
; i
++ ){
129 if (gbl_drivers
[i
].status
== DRIVER_UNUSED
) {
130 return &gbl_drivers
[i
];
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
)
144 for (i
= 0; i
< MAX_URBS
; i
++) {
145 if (drv
->urbs
[i
] == NULL
) {
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
)
162 for (i
= 0; i
< MAX_URBS
; i
++) {
163 if (drv
->urbs
[i
] == urb
) {
172 /*****************************************************************************
174 ****************************************************************************/
175 static struct ddekit_usb_urb
* find_pending_urb(struct minix_usb_driver
*drv
,
180 for (i
= 0; i
< MAX_URBS
; i
++) {
181 if (((struct my_context
*)drv
->urbs
[i
]->priv
)->urb_id
== urb_id
) {
189 /*****************************************************************************
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
;
204 msg
->m_type
= USB_REPLY
;
205 msg
->USB_RESULT
= EPERM
;
210 DEBUG_MSG("DRIVER %d registered \n"
211 "Announcing device %d, interfaces 0x%x\n",
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
;
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.");
238 /* do not accept requests for this client anymore! */
239 drv
->status
= DRIVER_UNUSED
;
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)
256 struct ddekit_usb_urb
*d_urb
= (struct ddekit_usb_urb
*)
257 my_malloc(sizeof(struct ddekit_usb_urb
));
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
;
285 /*****************************************************************************
287 ****************************************************************************/
288 static void submit_urb(message
*msg
)
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
299 endpoint_t ep
= msg
->m_source
;
300 struct minix_usb_driver
*drv
;
303 if ( (drv
= find_driver(ep
)) == NULL
) {
304 DEBUG_MSG("Non-registered driver tries to send URB.");
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.");
322 res
= sys_safecopyfrom(ep
, msg
->USB_GRANT_ID
, 0,
323 (vir_bytes
) &mx_urb
->dev_id
, msg
->USB_GRANT_SIZE
);
326 DEBUG_MSG("sys_safecopyfrom failed ");
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.");
340 /* create ddekit_usb_urb */
341 d_urb
= ddekit_usb_urb_from_mx_urb(mx_urb
);
342 d_urb
->dev
= _devices
[drv
->dev
].dev
;
350 ctx
= my_malloc(sizeof(struct my_context
));
358 ctx
->urb_id
= drv
->urb_id
++;
359 mx_urb
->urb_id
= ctx
->urb_id
;
360 ctx
->mx_urb
= mx_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
);
369 res
= add_to_pending_urbs(drv
, d_urb
);
372 DEBUG_MSG("submitting urb...");
373 res
= ddekit_usb_submit_urb(d_urb
);
375 DEBUG_MSG("submitting urb failed (err: %d)", res
);
376 remove_from_pending_urbs(drv
, d_urb
);
382 msg
->m_type
= USB_REPLY
;
383 msg
->USB_URB_ID
= mx_urb
->urb_id
;
384 msg
->USB_RESULT
= res
;
388 if (mx_urb
!= NULL
) {
410 * Cancels the submission of an URB identified by a URB_id
412 /*****************************************************************************
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
;
425 if ( (drv
= find_driver(ep
)) == NULL
) {
426 DEBUG_MSG("Non-registered driver tries to cancel URB.");
429 struct ddekit_usb_urb
*d_urb
= NULL
;
431 d_urb
= find_pending_urb(drv
, msg
->USB_URB_ID
);
434 ddekit_usb_cancle_urb(d_urb
);
437 DEBUG_MSG("No URB to cancle");
438 msg
->USB_RESULT
= ENODEV
;
446 /*****************************************************************************
448 *****************************************************************************/
450 get_info(message
* msg
)
452 struct minix_usb_driver
* drv
;
459 info_type
= msg
->USB_INFO_TYPE
;
460 info_value
= msg
->USB_INFO_VALUE
;
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");
470 /* Route info to device */
471 msg
->USB_RESULT
= ddekit_usb_info(_devices
[drv
->dev
].dev
,
472 info_type
, info_value
);
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
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
);
510 res
= sys_safecopyto(drv
->ep
, ctx
->gid
, 0,
511 (vir_bytes
) ((char*)mx_urb
) + sizeof(void*),
512 mx_urb
->urb_size
- sizeof(void*));
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
);
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
)
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
);
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 ****************************************************************************/
570 device_connect_callback
571 (struct ddekit_usb_dev
* dev
, unsigned int interfaces
) {
575 /* add to device list */
576 for (i
=0; i
< MAX_DEVS
; i
++) {
577 if (_devices
[i
].dev
== NULL
)
582 DEBUG_MSG("Too much devices...");
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
);
599 ddekit_usb_dev_set_data(dev
, dudev
);
601 res
= devman_usb_device_add(dudev
);
609 /*****************************************************************************
610 * device_disconnect_callback *
611 ****************************************************************************/
612 static void device_disconnect_callback(struct ddekit_usb_dev
* dev
)
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
];
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
);
644 devman_usb_device_remove(dudev
);
646 /* free the devman dev */
647 devman_usb_device_delete(dudev
);
651 /*****************************************************************************
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.
660 struct minix_usb_driver
*drv
;
662 if (_devices
[dev_id
].dev
== NULL
) {
663 /* if no device with that ID */
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
);
676 /* bind device to client */
677 drv
= find_unused_driver();
683 drv
->status
= DRIVER_BOUND
;
685 drv
->interfaces
= 1 << interfaces
;
692 /*****************************************************************************
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;
702 drv
= find_driver(ep
);
710 if (drv
->status
== DRIVER_ACTIVE
) {
715 drv
->status
= DRIVER_UNUSED
;
716 drv
->dev
= INVAL_DEV
;
719 msg
.m_type
= USB_WITHDRAW_DEV
;
720 msg
.USB_DEV_ID
= dev
;
721 asynsend3(ep
, &msg
, AMF_NOREPLY
);
727 /*****************************************************************************
729 ****************************************************************************/
730 static int handle_msg(message
*msg
)
735 * The dispatcher for USB related messages.
738 switch(msg
->m_type
) {
740 register_driver(msg
);
743 deregister_driver(msg
);
745 case USB_RQ_SEND_URB
:
748 case USB_RQ_CANCEL_URB
:
751 case USB_RQ_SEND_INFO
:
759 /*****************************************************************************
761 ****************************************************************************/
762 static void devman_thread(void *unused
)
764 struct ddekit_minix_msg_q
*mq
= ddekit_minix_create_msg_q(DEVMAN_BASE
,
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
,
785 /* create devman thread */
786 ddekit_thread_t
* __unused dmth
;
788 dmth
= ddekit_thread_create(devman_thread
, NULL
, "devman_thread");
791 ddekit_minix_rcv(mq
, &m
, &ipc_status
);
797 /*****************************************************************************
799 ****************************************************************************/
800 static int bind_cb (struct devman_usb_bind_cb_data
*data
, endpoint_t ep
)
803 return add_acl(data
->dev_id
, data
->interface
, ep
);
805 printf("warning: missing cb_data!\n");
810 /*****************************************************************************
812 ****************************************************************************/
813 static int unbind_cb (struct devman_usb_bind_cb_data
*data
, endpoint_t ep
)
816 return del_acl(data
->dev_id
, data
->interface
, ep
);
818 printf("warning: missing cb_data!\n");
823 /*****************************************************************************
824 * ddekit_usb_server_init *
825 ****************************************************************************/
826 void ddekit_usb_server_init()
830 * this function has to be called inside the context of an dedicated
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
);