From: Dirk Vogt Date: Tue, 22 Feb 2011 10:23:38 +0000 (+0000) Subject: added libusb, a IPC abstraction lib for USB stuff X-Git-Tag: v3.2.0~649 X-Git-Url: http://zhaoyanbai.com/repos/man.delv.html?a=commitdiff_plain;h=083d30afbbfc5af8f0b75bc72f566b66e51ee17c;p=minix.git added libusb, a IPC abstraction lib for USB stuff --- diff --git a/include/Makefile b/include/Makefile index df0469992..fdc087331 100644 --- a/include/Makefile +++ b/include/Makefile @@ -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 index 000000000..cd5b6690c --- /dev/null +++ b/include/minix/usb.h @@ -0,0 +1,155 @@ +#ifndef _MINIX_USB_H +#define _MINIX_USB_H + +#include +#include +#include +#include + +#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 */ diff --git a/lib/Makefile b/lib/Makefile index a0a2561e9..b66909371 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -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 index 000000000..b8709a2fc --- /dev/null +++ b/lib/libusb/Makefile @@ -0,0 +1,7 @@ +# Makefile for libdriver + +LIB = usb + +SRCS = usb.c + +.include diff --git a/lib/libusb/usb.c b/lib/libusb/usb.c new file mode 100644 index 000000000..2f550ecbc --- /dev/null +++ b/lib/libusb/usb.c @@ -0,0 +1,224 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +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"); + } +} + diff --git a/share/mk/bsd.prog.mk b/share/mk/bsd.prog.mk index 820feb52d..d98ce8cd5 100644 --- a/share/mk/bsd.prog.mk +++ b/share/mk/bsd.prog.mk @@ -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"