--- /dev/null
+#ifndef _MINIX_USB_H
+#define _MINIX_USB_H
+
+#include <minix/com.h>
+#include <minix/ipc.h>
+#include <minix/types.h>
+#include <stdio.h>
+
+#define USB_URBSIZE(data_size, iso_count) \
+ (data_size + sizeof(struct usb_urb) + iso_count * \
+ sizeof(struct usb_iso_packet_desc))
+
+#define USB_PREPARE_URB(urb, data_size, iso_count) \
+ do { \
+ if(iso_count)\
+ urb->iso_data.iso_desc = data_size;\
+ urb->urb_size = data_size+sizeof(struct usb_urb)+iso_count * \
+ sizeof(struct usb_iso_packet_desc); \
+ } while (0)
+
+
+struct usb_urb;
+
+struct usb_driver {
+ void (*urb_completion)(struct usb_urb *urb);
+ void (*connect_device)(unsigned dev_id, unsigned int interfaces);
+ void (*disconnect_device)(unsigned dev_id);
+};
+
+struct usb_device_id {
+ u16_t idVendor;
+ u16_t idProduct;
+ u32_t bcdDevice;
+
+ u8_t bDeviceClass;
+ u8_t bDeviceSubClass;
+ u8_t bDeviceProtocol;
+
+ u8_t bInterfaceClass;
+ u8_t bInterfaceSubClass;
+ u8_t bInterfaceProtocol;
+};
+
+struct usb_iso_packet_desc {
+ unsigned int offset;
+ unsigned int length; /* expected length */
+ unsigned int actual_length;
+ unsigned int status;
+};
+
+/** isochronous transfer */
+#define USB_TRANSFER_ISO 0
+/** interrupt transfer */
+#define USB_TRANSFER_INT 1
+/** control transfer */
+#define USB_TRANSFER_CTL 2
+/** bulk transfer */
+#define USB_TRANSFER_BLK 3
+
+#define USB_IN 0
+#define USB_OUT 1
+
+#define USB_INVALID_URB_ID 0
+
+struct usb_urb {
+ /* private */
+ struct usb_urb *next;
+
+ /** ID identifying the device on HCD side */
+ int dev_id;
+ int type;
+ int endpoint;
+ int direction;
+ int status;
+ int error_count;
+ size_t size;
+ size_t actual_length;
+ void *priv;
+ int interval;
+
+ unsigned long transfer_flags;
+
+
+ /* housekeeping information needed by usb library */
+ unsigned urb_id;
+ size_t urb_size;
+ cp_grant_id_t gid;
+
+ size_t iso_desc_offset;
+ int number_of_packets;
+ int start_frame;
+ char setup_packet[8];
+
+ /* data allways starts here */
+ char buffer[1];
+};
+
+struct usb_ctrlrequest {
+ u8_t bRequestType;
+ u8_t bRequest;
+ u16_t wValue;
+ u16_t wIndex;
+ u16_t wLength;
+} __attribute__ ((packed));
+
+#ifdef DEBUG
+static void dump_urb(struct usb_urb *urb) {
+ printf("================\n");
+ printf("DUMP: urb (0x%p)\n", urb);
+ printf("================\n");
+ printf("= dev_id: %d\n", urb->dev_id);
+ printf("= type: %d\n", urb->type);
+ printf("= endpoint: %d\n", urb->endpoint);
+ printf("= direction: %d\n", urb->direction);
+ printf("= status: %d\n", urb->status);
+ printf("= error_count: %d\n", urb->error_count);
+ printf("= size: %d\n", urb->size);
+ printf("= actual_length: %d\n", urb->actual_length);
+ printf("= interval %d\n", urb->interval);
+ printf("= transfer_flags %x\n", urb->transfer_flags);
+ printf("= urb_id = %d\n", urb->urb_id);
+ printf("= urb_size = 0x%x\n", urb->urb_size);
+ printf("= setup_packet: \n");
+ printf("= bRequestType: 0x%x \n",
+ ((struct usb_ctrlrequest *)urb->setup_packet)->bRequestType);
+ printf("= bRequest 0x%x \n",
+ ((struct usb_ctrlrequest *)urb->setup_packet)->bRequest);
+ printf("= wValue: 0x%x \n",
+ ((struct usb_ctrlrequest *)urb->setup_packet)->wValue);
+ printf("= wIndex: 0x%x \n",
+ ((struct usb_ctrlrequest *)urb->setup_packet)->wIndex);
+ printf("= wLength: 0x%x \n",
+ ((struct usb_ctrlrequest *)urb->setup_packet)->wLength);
+ printf("===============\n");
+}
+#else
+#define dumb_urb(x)
+#endif
+
+/** Submit a URB */
+int usb_send_urb(struct usb_urb* urb);
+
+/** Cancels an URB */
+int usb_cancle_urb(struct usb_urb* urb);
+
+/** Gets the USB device ID of an USB device **/
+int usb_get_device_id(int dev_id, struct usb_device_id *usb_device_id);
+
+/* this initializes a session with the HCD */
+int usb_init(char *name);
+
+/** This functions handles a message from the HCD */
+int usb_handle_msg(struct usb_driver *ubd, message *msg);
+
+#endif /* _MINIX_USB_H */
--- /dev/null
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/usb.h>
+#include <minix/com.h>
+#include <minix/safecopies.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+PRIVATE struct usb_urb * pending_urbs = NULL;
+PRIVATE endpoint_t hcd_ep;
+
+FORWARD _PROTOTYPE( void _usb_urb_complete,
+ (struct usb_driver *ud, long urb_id));
+
+/*****************************************************************************
+ * usb_send_urb *
+ ****************************************************************************/
+PUBLIC int usb_send_urb(struct usb_urb* urb)
+{
+ message msg;
+ int res;
+ cp_grant_id_t gid;
+ if (urb == NULL) {
+ return EINVAL;
+ }
+
+ if (hcd_ep == 0) {
+ return EINVAL;
+ }
+
+ /* setup grant */
+ gid = cpf_grant_direct(hcd_ep,(vir_bytes) &urb->dev_id,
+ urb->urb_size - sizeof(void*),CPF_WRITE|CPF_READ);
+
+ if (gid == -1) {
+ printf("usb_send_urb: grant failed: "
+ "cpf_grant_direct(%d,%p,%d)\n", hcd_ep, urb, urb->urb_size);
+ return EINVAL;
+ }
+
+ urb->gid = gid;
+
+ /* prepare message */
+ msg.m_type = USB_RQ_SEND_URB;
+ msg.USB_GRANT_ID = gid;
+ msg.USB_GRANT_SIZE = urb->urb_size-sizeof(void*);
+
+ /* send message */
+ res = sendrec(hcd_ep, &msg);
+
+ if (res != 0) {
+ panic("usb_send_urb: could not talk to hcd: %d", res);
+ }
+
+ if (msg.m_type != USB_REPLY) {
+ panic("usb_send_urb: got illegal response from hcd: %d", msg.m_type);
+ }
+
+ if (msg.USB_RESULT != 0) {
+ panic("usb_send_urb: hcd could not enqueue URB: %d", msg.USB_RESULT);
+ }
+
+ /* everything ok, add urb to pending_urbs */
+ urb->urb_id = msg.USB_URB_ID;
+ urb->next = pending_urbs;
+ pending_urbs = urb;
+
+ /* done. */
+
+ /* (The HCD will send us a message when the URB is completed.) */
+
+ return res;
+}
+
+/*****************************************************************************
+ * usb_cancle_urb *
+ ****************************************************************************/
+PUBLIC int usb_cancle_urb(struct usb_urb* urb)
+{
+ int res;
+ message msg;
+
+ if (urb == NULL) {
+ panic("usb_send_urb: urb == NULL!");
+ }
+
+ if (urb->urb_id == USB_INVALID_URB_ID) {
+ return EINVAL;
+ }
+
+ /* prepare message */
+ msg.m_type = USB_RQ_CANCEL_URB;
+ msg.USB_URB_ID = urb->urb_id;
+
+ /* send message */
+ res = sendrec(hcd_ep, &msg);
+
+ if (res != 0) {
+ panic("usb_cancle_urb: could not talk to hcd: %d", res);
+ }
+
+ if (msg.m_type != USB_REPLY) {
+ panic("usb_cancle_urb: got illegal response from hcd: %d", msg.m_type);
+ }
+
+ if (msg.USB_RESULT != 0) {
+ panic("usb_cancle_urb: got illegal response from hcd: %d", msg.m_type);
+ }
+
+ res = msg.USB_RESULT;
+
+ /* done. */
+ return res;
+}
+
+/*****************************************************************************
+ * usb_init *
+ ****************************************************************************/
+PUBLIC int usb_init(char *name)
+{
+ int res;
+ message msg;
+
+ /* get the endpoint of the HCD */
+ res = ds_retrieve_label_endpt("usbd", &hcd_ep);
+
+ if (res != 0) {
+ panic("usb_init: ds_retrieve_label_endpt failed for 'usb': %d", res);
+ }
+
+ msg.m_type = USB_RQ_INIT;
+
+ strncpy(msg.USB_RB_INIT_NAME, name, M3_LONG_STRING);
+
+ res = sendrec(hcd_ep, &msg);
+
+ if (res != 0) {
+ panic("usb_init: can't talk to USB: %d", res);
+ }
+
+ if (msg.m_type != USB_REPLY) {
+ panic("usb_init: bad reply from USB: %d", msg.m_type);
+ }
+
+ if (msg.USB_RESULT != 0 ) {
+ panic("usb_init: init failed: %d", msg.USB_RESULT);
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * _usb_urb_complete *
+ ****************************************************************************/
+PRIVATE void _usb_urb_complete(struct usb_driver *ud, long urb_id)
+{
+ /* find the corresponding URB in the urb_pending list. */
+ struct usb_urb * urb = NULL;
+ if (pending_urbs != NULL) {
+ if (pending_urbs->urb_id == urb_id) {
+ urb = pending_urbs;
+ pending_urbs = urb->next;
+ } else {
+ struct usb_urb *u = pending_urbs;
+ while (u->next) {
+ if (u->next->urb_id == urb_id) {
+ urb = u->next;
+ u->next = u->next->next;
+ urb->next = NULL;
+ break;
+ }
+ u = u->next;
+ }
+ }
+ }
+
+ /* Did we find a URB? */
+ if (urb != NULL) {
+ /* revoke grant */
+ cpf_revoke(urb->gid);
+ /* call completion handler */
+#if 0
+ dump_urb(urb);
+#endif
+ ud->urb_completion(urb);
+ } else {
+ printf("WARN: _usb_urb_complete: did not find URB with ID %d", urb_id);
+ }
+}
+
+/*****************************************************************************
+ * usb_handle_msg *
+ ****************************************************************************/
+PUBLIC int usb_handle_msg(struct usb_driver *ud, message *msg)
+{
+ /*
+ * we expect kind of messages:
+ * - new usb device
+ * - removed device
+ * - URB completed
+ *
+ * NOTE: the hcd driver doesn't expect replies for these messages.
+ */
+
+ if (!ud) {
+ return -1;
+ }
+
+ switch(msg->m_type) {
+ case USB_COMPLETE_URB:
+ _usb_urb_complete(ud, msg->USB_URB_ID);
+ return 0;
+ case USB_ANNOUCE_DEV:
+ ud->connect_device(msg->USB_DEV_ID, msg->USB_INTERFACES);
+ return 0;
+ case USB_WITHDRAW_DEV:
+ ud->disconnect_device(msg->USB_DEV_ID);
+ return 0;
+ default:
+ panic("usb_handle_msg: bogus message from USB");
+ }
+}
+