added libusb, a IPC abstraction lib for USB stuff
This commit is contained in:
parent
dc75514afc
commit
083d30afbb
@ -27,7 +27,7 @@ INCS+= minix/a.out.h minix/cdrom.h minix/cpufeature.h \
|
|||||||
minix/vfsif.h minix/vtreefs.h \
|
minix/vfsif.h minix/vtreefs.h \
|
||||||
minix/compiler-ack.h minix/sha2.h minix/sha1.h minix/md5.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/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+= net/hton.h net/if.h net/ioctl.h net/netlib.h
|
||||||
INCS+= netinet/if_ether.h netinet/in.h netinet/tcp.h
|
INCS+= netinet/if_ether.h netinet/in.h netinet/tcp.h
|
||||||
|
155
include/minix/usb.h
Normal file
155
include/minix/usb.h
Normal file
@ -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 */
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
SUBDIR= csu libc libcurses libdriver libnetdriver libedit libm libsys \
|
SUBDIR= csu libc libcurses libdriver libnetdriver libedit libm libsys \
|
||||||
libtimers libutil libbz2 libl libhgfs libz libfetch libarchive \
|
libtimers libutil libbz2 libl libhgfs libz libfetch libarchive \
|
||||||
libvtreefs libaudiodriver libmthread libexec
|
libvtreefs libaudiodriver libmthread libexec libusb
|
||||||
|
|
||||||
.if ${COMPILER_TYPE} == "ack"
|
.if ${COMPILER_TYPE} == "ack"
|
||||||
SUBDIR+= ack/libd ack/libe ack/libfp ack/liby
|
SUBDIR+= ack/libd ack/libe ack/libfp ack/liby
|
||||||
|
7
lib/libusb/Makefile
Normal file
7
lib/libusb/Makefile
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# Makefile for libdriver
|
||||||
|
|
||||||
|
LIB = usb
|
||||||
|
|
||||||
|
SRCS = usb.c
|
||||||
|
|
||||||
|
.include <bsd.lib.mk>
|
224
lib/libusb/usb.c
Normal file
224
lib/libusb/usb.c
Normal file
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -59,7 +59,7 @@ MKDEP_SUFFIXES?= .o .ln
|
|||||||
# rumpfs_tmpfs rumpfs_udf rumpfs_ufs
|
# rumpfs_tmpfs rumpfs_udf rumpfs_ufs
|
||||||
.for _lib in \
|
.for _lib in \
|
||||||
c curses driver netdriver edit end m sys timers util bz2 l hgfs \
|
c curses driver netdriver edit end m sys timers util bz2 l hgfs \
|
||||||
audiodriver exec
|
audiodriver exec usb
|
||||||
.ifndef LIB${_lib:tu}
|
.ifndef LIB${_lib:tu}
|
||||||
LIB${_lib:tu}= ${DESTDIR}/usr/lib/lib${_lib}.a
|
LIB${_lib:tu}= ${DESTDIR}/usr/lib/lib${_lib}.a
|
||||||
.if ${COMPILER_TYPE} == "ack"
|
.if ${COMPILER_TYPE} == "ack"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user