]> Zhao Yanbai Git Server - minix.git/commitdiff
added libusb, a IPC abstraction lib for USB stuff
authorDirk Vogt <dirk@minix3.org>
Tue, 22 Feb 2011 10:23:38 +0000 (10:23 +0000)
committerDirk Vogt <dirk@minix3.org>
Tue, 22 Feb 2011 10:23:38 +0000 (10:23 +0000)
include/Makefile
include/minix/usb.h [new file with mode: 0644]
lib/Makefile
lib/libusb/Makefile [new file with mode: 0644]
lib/libusb/usb.c [new file with mode: 0644]
share/mk/bsd.prog.mk

index df0469992a337028afdf5e55305a3a76ceba8d5c..fdc087331d23b810788ecfbd20e8d9a2910af6ed 100644 (file)
@@ -27,7 +27,7 @@ INCS+=        minix/a.out.h minix/cdrom.h minix/cpufeature.h \
        minix/vfsif.h minix/vtreefs.h \
        minix/compiler-ack.h minix/sha2.h minix/sha1.h minix/md5.h \
        minix/audio_fw.h minix/hash.h minix/input.h \
-       minix/usb_ch9.h 
+       minix/usb.h minix/usb_ch9.h 
        
 INCS+= net/hton.h net/if.h net/ioctl.h net/netlib.h
 INCS+= netinet/if_ether.h netinet/in.h netinet/tcp.h
diff --git a/include/minix/usb.h b/include/minix/usb.h
new file mode 100644 (file)
index 0000000..cd5b669
--- /dev/null
@@ -0,0 +1,155 @@
+#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 */
index a0a2561e98379e3b77e6f81959cc5007bb26706f..b669093717b4baf25a2043a907ac5b32356e33e9 100644 (file)
@@ -2,7 +2,7 @@
 
 SUBDIR= csu libc libcurses libdriver libnetdriver libedit libm libsys \
        libtimers libutil libbz2 libl libhgfs libz libfetch libarchive \
-       libvtreefs libaudiodriver libmthread libexec
+       libvtreefs libaudiodriver libmthread libexec libusb 
 
 .if ${COMPILER_TYPE} == "ack"
 SUBDIR+= ack/libd ack/libe ack/libfp ack/liby
diff --git a/lib/libusb/Makefile b/lib/libusb/Makefile
new file mode 100644 (file)
index 0000000..b8709a2
--- /dev/null
@@ -0,0 +1,7 @@
+# Makefile for libdriver
+
+LIB = usb      
+
+SRCS = usb.c
+
+.include <bsd.lib.mk>
diff --git a/lib/libusb/usb.c b/lib/libusb/usb.c
new file mode 100644 (file)
index 0000000..2f550ec
--- /dev/null
@@ -0,0 +1,224 @@
+#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");
+       }
+}
+
index 820feb52df0335340ee45d92805eaca738bebd0e..d98ce8cd5ff5b7eb7c054d06decbab739c34ae14 100644 (file)
@@ -59,7 +59,7 @@ MKDEP_SUFFIXES?=      .o .ln
 #      rumpfs_tmpfs rumpfs_udf rumpfs_ufs
 .for _lib in \
        c curses driver netdriver edit end m sys timers util bz2 l hgfs \
-       audiodriver exec
+       audiodriver exec usb 
 .ifndef LIB${_lib:tu}
 LIB${_lib:tu}= ${DESTDIR}/usr/lib/lib${_lib}.a
 .if ${COMPILER_TYPE} == "ack"