225 lines
6.5 KiB
C
225 lines
6.5 KiB
C
|
/*
|
||
|
* This file is part of the libpayload project.
|
||
|
*
|
||
|
* Copyright (C) 2008 coresystems GmbH
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions
|
||
|
* are met:
|
||
|
* 1. Redistributions of source code must retain the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer.
|
||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer in the
|
||
|
* documentation and/or other materials provided with the distribution.
|
||
|
* 3. The name of the author may not be used to endorse or promote products
|
||
|
* derived from this software without specific prior written permission.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||
|
* SUCH DAMAGE.
|
||
|
*/
|
||
|
|
||
|
#ifndef __USB_H
|
||
|
#define __USB_H
|
||
|
#include <libpayload.h>
|
||
|
#include <pci.h>
|
||
|
|
||
|
typedef enum { host_to_device = 0, device_to_host = 1 } dev_req_dir;
|
||
|
typedef enum { standard_type = 0, class_type = 1, vendor_type =
|
||
|
2, reserved_type = 3
|
||
|
} dev_req_type;
|
||
|
typedef enum { dev_recp = 0, iface_recp = 1, endp_recp = 2, other_recp = 3
|
||
|
} dev_req_recp;
|
||
|
|
||
|
typedef enum {
|
||
|
GET_STATUS = 0,
|
||
|
CLEAR_FEATURE = 1,
|
||
|
SET_FEATURE = 3,
|
||
|
SET_ADDRESS = 5,
|
||
|
GET_DESCRIPTOR = 6,
|
||
|
SET_DESCRIPTOR = 7,
|
||
|
GET_CONFIGURATION = 8,
|
||
|
SET_CONFIGURATION = 9,
|
||
|
GET_INTERFACE = 10,
|
||
|
SET_INTERFACE = 11,
|
||
|
SYNCH_FRAME = 12
|
||
|
} bRequest_Codes;
|
||
|
|
||
|
typedef enum {
|
||
|
ENDPOINT_HALT = 0,
|
||
|
DEVICE_REMOTE_WAKEUP = 1,
|
||
|
TEST_MODE = 2
|
||
|
} feature_selectors;
|
||
|
|
||
|
typedef struct {
|
||
|
union {
|
||
|
struct {
|
||
|
dev_req_recp req_recp:5;
|
||
|
dev_req_type req_type:2;
|
||
|
dev_req_dir data_dir:1;
|
||
|
} __attribute__ ((packed));
|
||
|
unsigned char bmRequestType;
|
||
|
} __attribute__ ((packed));
|
||
|
unsigned char bRequest;
|
||
|
unsigned short wValue;
|
||
|
unsigned short wIndex;
|
||
|
unsigned short wLength;
|
||
|
} __attribute__ ((packed)) dev_req_t;
|
||
|
|
||
|
struct usbdev_hc;
|
||
|
typedef struct usbdev_hc hci_t;
|
||
|
|
||
|
struct usbdev;
|
||
|
typedef struct usbdev usbdev_t;
|
||
|
|
||
|
typedef enum { SETUP = 0x2d, IN = 0x69, OUT = 0xe1 } pid_t;
|
||
|
typedef enum { CONTROL = 0, ISOCHRONOUS = 1, BULK = 2, INTERRUPT = 3
|
||
|
} endpoint_type;
|
||
|
|
||
|
typedef struct {
|
||
|
usbdev_t *dev;
|
||
|
int endpoint;
|
||
|
pid_t direction;
|
||
|
int toggle;
|
||
|
int maxpacketsize;
|
||
|
endpoint_type type;
|
||
|
} endpoint_t;
|
||
|
|
||
|
|
||
|
struct usbdev {
|
||
|
hci_t *controller;
|
||
|
endpoint_t endpoints[32];
|
||
|
int num_endp;
|
||
|
int address; // usb address
|
||
|
int hub; // hub, device is attached to
|
||
|
int port; // port where device is attached
|
||
|
int lowspeed; // 1 if lowspeed device
|
||
|
void *data;
|
||
|
u8 *descriptor;
|
||
|
u8 *configuration;
|
||
|
void (*init) (usbdev_t *dev);
|
||
|
void (*destroy) (usbdev_t *dev);
|
||
|
void (*poll) (usbdev_t *dev);
|
||
|
};
|
||
|
|
||
|
struct usbdev_hc {
|
||
|
struct usbdev_hc *next;
|
||
|
pcidev_t bus_address;
|
||
|
u32 reg_base;
|
||
|
usbdev_t devices[128]; // dev 0 is root hub, 127 is last addressable
|
||
|
void (*start) (hci_t *controller);
|
||
|
void (*stop) (hci_t *controller);
|
||
|
void (*reset) (hci_t *controller);
|
||
|
void (*shutdown) (hci_t *controller);
|
||
|
int (*packet) (usbdev_t *dev, int endp, int pid, int toggle,
|
||
|
int length, u8 *data);
|
||
|
int (*bulk) (endpoint_t *ep, int size, u8 *data, int finalize);
|
||
|
int (*control) (usbdev_t *dev, pid_t pid, int dr_length,
|
||
|
void *devreq, int data_length, u8 *data);
|
||
|
void *instance;
|
||
|
};
|
||
|
|
||
|
typedef struct {
|
||
|
unsigned char bDescLength;
|
||
|
unsigned char bDescriptorType;
|
||
|
unsigned char bNbrPorts;
|
||
|
union {
|
||
|
struct {
|
||
|
unsigned long logicalPowerSwitchingMode:2;
|
||
|
unsigned long isCompoundDevice:1;
|
||
|
unsigned long overcurrentProtectionMode:2;
|
||
|
unsigned long ttThinkTime:2;
|
||
|
unsigned long arePortIndicatorsSupported:1;
|
||
|
unsigned long:8;
|
||
|
} __attribute__ ((packed));
|
||
|
unsigned short wHubCharacteristics;
|
||
|
} __attribute__ ((packed));
|
||
|
unsigned char bPowerOn2PwrGood;
|
||
|
unsigned char bHubContrCurrent;
|
||
|
char DeviceRemovable[];
|
||
|
} __attribute__ ((packed)) hub_descriptor_t;
|
||
|
|
||
|
typedef struct {
|
||
|
unsigned char bLength;
|
||
|
unsigned char bDescriptorType;
|
||
|
unsigned short bcdUSB;
|
||
|
unsigned char bDeviceClass;
|
||
|
unsigned char bDeviceSubClass;
|
||
|
unsigned char bDeviceProtocol;
|
||
|
unsigned char bMaxPacketSize0;
|
||
|
unsigned short idVendor;
|
||
|
unsigned short idProduct;
|
||
|
unsigned short bcdDevice;
|
||
|
unsigned char iManufacturer;
|
||
|
unsigned char iProduct;
|
||
|
unsigned char iSerialNumber;
|
||
|
unsigned char bNumConfigurations;
|
||
|
} __attribute__ ((packed)) device_descriptor_t;
|
||
|
|
||
|
typedef struct {
|
||
|
unsigned char bLength;
|
||
|
unsigned char bDescriptorType;
|
||
|
unsigned short wTotalLength;
|
||
|
unsigned char bNumInterfaces;
|
||
|
unsigned char bConfigurationValue;
|
||
|
unsigned char iConfiguration;
|
||
|
unsigned char bmAttributes;
|
||
|
unsigned char bMaxPower;
|
||
|
} __attribute__ ((packed)) configuration_descriptor_t;
|
||
|
|
||
|
typedef struct {
|
||
|
unsigned char bLength;
|
||
|
unsigned char bDescriptorType;
|
||
|
unsigned char bInterfaceNumber;
|
||
|
unsigned char bAlternateSetting;
|
||
|
unsigned char bNumEndpoints;
|
||
|
unsigned char bInterfaceClass;
|
||
|
unsigned char bInterfaceSubClass;
|
||
|
unsigned char bInterfaceProtocol;
|
||
|
unsigned char iInterface;
|
||
|
} __attribute__ ((packed)) interface_descriptor_t;
|
||
|
|
||
|
typedef struct {
|
||
|
unsigned char bLength;
|
||
|
unsigned char bDescriptorType;
|
||
|
unsigned char bEndpointAddress;
|
||
|
unsigned char bmAttributes;
|
||
|
unsigned short wMaxPacketSize;
|
||
|
unsigned char bInterval;
|
||
|
} __attribute__ ((packed)) endpoint_descriptor_t;
|
||
|
|
||
|
hci_t *new_controller (void);
|
||
|
void detach_controller (hci_t *controller);
|
||
|
void usb_poll (void);
|
||
|
void init_device_entry (hci_t *controller, int num);
|
||
|
|
||
|
void set_feature (usbdev_t *dev, int endp, int feature, int rtype);
|
||
|
void get_status (usbdev_t *dev, int endp, int rtype, int len, void *data);
|
||
|
int clear_stall (endpoint_t *ep);
|
||
|
|
||
|
void usb_nop_init (usbdev_t *dev);
|
||
|
void usb_hub_init (usbdev_t *dev);
|
||
|
void usb_hid_init (usbdev_t *dev);
|
||
|
void usb_msc_init (usbdev_t *dev);
|
||
|
|
||
|
int set_address (hci_t *controller, int lowspeed);
|
||
|
|
||
|
u8 *get_descriptor (usbdev_t *dev, unsigned char bmRequestType,
|
||
|
int descType, int descIdx, int langID);
|
||
|
|
||
|
static inline unsigned char
|
||
|
gen_bmRequestType (dev_req_dir dir, dev_req_type type, dev_req_recp recp)
|
||
|
{
|
||
|
return (dir << 7) | (type << 5) | recp;
|
||
|
}
|
||
|
|
||
|
#endif
|