/* * VAS_EBOOT -- GRand Unified Bootloader * Copyright (C) 2008 Free Software Foundation, Inc. * * VAS_EBOOT is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * VAS_EBOOT is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with VAS_EBOOT. If not, see . */ #ifndef VAS_EBOOT_USB_H #define VAS_EBOOT_USB_H 1 #include #include #include #define VAS_EBOOT_USB_MAX_CONF 8 #define VAS_EBOOT_USB_MAX_IF 32 #define VAS_EBOOT_USB_MAX_TOGGLE 256 typedef struct VasEBoot_usb_device *VasEBoot_usb_device_t; typedef struct VasEBoot_usb_controller *VasEBoot_usb_controller_t; typedef struct VasEBoot_usb_controller_dev *VasEBoot_usb_controller_dev_t; typedef enum { VAS_EBOOT_USB_ERR_NONE, VAS_EBOOT_USB_ERR_WAIT, VAS_EBOOT_USB_ERR_INTERNAL, VAS_EBOOT_USB_ERR_STALL, VAS_EBOOT_USB_ERR_DATA, VAS_EBOOT_USB_ERR_NAK, VAS_EBOOT_USB_ERR_BABBLE, VAS_EBOOT_USB_ERR_TIMEOUT, VAS_EBOOT_USB_ERR_BITSTUFF, VAS_EBOOT_USB_ERR_UNRECOVERABLE, VAS_EBOOT_USB_ERR_BADDEVICE } VasEBoot_usb_err_t; typedef enum { VAS_EBOOT_USB_SPEED_NONE, VAS_EBOOT_USB_SPEED_LOW, VAS_EBOOT_USB_SPEED_FULL, VAS_EBOOT_USB_SPEED_HIGH } VasEBoot_usb_speed_t; typedef int (*VasEBoot_usb_iterate_hook_t) (VasEBoot_usb_device_t dev, void *data); typedef int (*VasEBoot_usb_controller_iterate_hook_t) (VasEBoot_usb_controller_t dev, void *data); /* Call HOOK with each device, until HOOK returns non-zero. */ int VasEBoot_usb_iterate (VasEBoot_usb_iterate_hook_t hook, void *hook_data); VasEBoot_usb_err_t VasEBoot_usb_device_initialize (VasEBoot_usb_device_t dev); VasEBoot_usb_err_t VasEBoot_usb_get_descriptor (VasEBoot_usb_device_t dev, VasEBoot_uint8_t type, VasEBoot_uint8_t index, VasEBoot_size_t size, char *data); VasEBoot_usb_err_t VasEBoot_usb_clear_halt (VasEBoot_usb_device_t dev, int endpoint); VasEBoot_usb_err_t VasEBoot_usb_set_configuration (VasEBoot_usb_device_t dev, int configuration); void VasEBoot_usb_controller_dev_register (VasEBoot_usb_controller_dev_t usb); void VasEBoot_usb_controller_dev_unregister (VasEBoot_usb_controller_dev_t usb); int VasEBoot_usb_controller_iterate (VasEBoot_usb_controller_iterate_hook_t hook, void *hook_data); VasEBoot_usb_err_t VasEBoot_usb_control_msg (VasEBoot_usb_device_t dev, VasEBoot_uint8_t reqtype, VasEBoot_uint8_t request, VasEBoot_uint16_t value, VasEBoot_uint16_t index, VasEBoot_size_t size, char *data); VasEBoot_usb_err_t VasEBoot_usb_bulk_read (VasEBoot_usb_device_t dev, struct VasEBoot_usb_desc_endp *endpoint, VasEBoot_size_t size, char *data); VasEBoot_usb_err_t VasEBoot_usb_bulk_write (VasEBoot_usb_device_t dev, struct VasEBoot_usb_desc_endp *endpoint, VasEBoot_size_t size, char *data); VasEBoot_usb_err_t VasEBoot_usb_root_hub (VasEBoot_usb_controller_t controller); /* XXX: All handled by libusb for now. */ struct VasEBoot_usb_controller_dev { /* The device name. */ const char *name; int (*iterate) (VasEBoot_usb_controller_iterate_hook_t hook, void *hook_data); VasEBoot_usb_err_t (*setup_transfer) (VasEBoot_usb_controller_t dev, VasEBoot_usb_transfer_t transfer); VasEBoot_usb_err_t (*check_transfer) (VasEBoot_usb_controller_t dev, VasEBoot_usb_transfer_t transfer, VasEBoot_size_t *actual); VasEBoot_usb_err_t (*cancel_transfer) (VasEBoot_usb_controller_t dev, VasEBoot_usb_transfer_t transfer); int (*hubports) (VasEBoot_usb_controller_t dev); VasEBoot_usb_err_t (*portstatus) (VasEBoot_usb_controller_t dev, unsigned int port, unsigned int enable); VasEBoot_usb_speed_t (*detect_dev) (VasEBoot_usb_controller_t dev, int port, int *changed); /* Per controller flag - port reset pending, don't do another reset */ VasEBoot_uint64_t pending_reset; /* Max. number of transfer descriptors used per one bulk transfer */ /* The reason is to prevent "exhausting" of TD by large bulk */ /* transfer - number of TD is limited in USB host driver */ /* Value is calculated/estimated in driver - some TDs should be */ /* reserved for posible concurrent control or "interrupt" transfers */ VasEBoot_size_t max_bulk_tds; /* The next host controller. */ struct VasEBoot_usb_controller_dev *next; }; struct VasEBoot_usb_controller { /* The underlying USB Host Controller device. */ VasEBoot_usb_controller_dev_t dev; /* Data used by the USB Host Controller Driver. */ void *data; }; struct VasEBoot_usb_interface { struct VasEBoot_usb_desc_if *descif; struct VasEBoot_usb_desc_endp *descendp; /* A driver is handling this interface. Do we need to support multiple drivers for single interface? */ int attached; void (*detach_hook) (struct VasEBoot_usb_device *dev, int config, int interface); void *detach_data; }; struct VasEBoot_usb_configuration { /* Configuration descriptors . */ struct VasEBoot_usb_desc_config *descconf; /* Interfaces associated to this configuration. */ struct VasEBoot_usb_interface interf[VAS_EBOOT_USB_MAX_IF]; }; struct VasEBoot_usb_hub_port { VasEBoot_uint64_t soft_limit_time; VasEBoot_uint64_t hard_limit_time; enum { PORT_STATE_NORMAL = 0, PORT_STATE_WAITING_FOR_STABLE_POWER = 1, PORT_STATE_FAILED_DEVICE = 2, PORT_STATE_STABLE_POWER = 3, } state; }; struct VasEBoot_usb_device { /* The device descriptor of this device. */ struct VasEBoot_usb_desc_device descdev; /* The controller the device is connected to. */ struct VasEBoot_usb_controller controller; /* Device configurations (after opening the device). */ struct VasEBoot_usb_configuration config[VAS_EBOOT_USB_MAX_CONF]; /* Device address. */ int addr; /* Device speed. */ VasEBoot_usb_speed_t speed; /* All descriptors are read if this is set to 1. */ int initialized; /* Data toggle values (used for bulk transfers only). */ int toggle[VAS_EBOOT_USB_MAX_TOGGLE]; /* Used by libusb wrapper. Schedulded for removal. */ void *data; /* Hub information. */ /* Array of children for a hub. */ VasEBoot_usb_device_t *children; /* Number of hub ports. */ unsigned nports; struct VasEBoot_usb_hub_port *ports; VasEBoot_usb_transfer_t hub_transfer; VasEBoot_uint32_t statuschange; struct VasEBoot_usb_desc_endp *hub_endpoint; /* EHCI Split Transfer information */ int split_hubport; int split_hubaddr; }; typedef enum VasEBoot_usb_ep_type { VAS_EBOOT_USB_EP_CONTROL, VAS_EBOOT_USB_EP_ISOCHRONOUS, VAS_EBOOT_USB_EP_BULK, VAS_EBOOT_USB_EP_INTERRUPT } VasEBoot_usb_ep_type_t; static inline enum VasEBoot_usb_ep_type VasEBoot_usb_get_ep_type (struct VasEBoot_usb_desc_endp *ep) { return ep->attrib & 3; } typedef enum { VAS_EBOOT_USB_CLASS_NOTHERE, VAS_EBOOT_USB_CLASS_AUDIO, VAS_EBOOT_USB_CLASS_COMMUNICATION, VAS_EBOOT_USB_CLASS_HID, VAS_EBOOT_USB_CLASS_XXX, VAS_EBOOT_USB_CLASS_PHYSICAL, VAS_EBOOT_USB_CLASS_IMAGE, VAS_EBOOT_USB_CLASS_PRINTER, VAS_EBOOT_USB_CLASS_MASS_STORAGE, VAS_EBOOT_USB_CLASS_HUB, VAS_EBOOT_USB_CLASS_DATA_INTERFACE, VAS_EBOOT_USB_CLASS_SMART_CARD, VAS_EBOOT_USB_CLASS_CONTENT_SECURITY, VAS_EBOOT_USB_CLASS_VIDEO } VasEBoot_usb_classes_t; typedef enum { VAS_EBOOT_USBMS_SUBCLASS_BULK = 0x06, /* Experimental support for non-pure SCSI devices */ VAS_EBOOT_USBMS_SUBCLASS_RBC = 0x01, VAS_EBOOT_USBMS_SUBCLASS_MMC2 = 0x02, VAS_EBOOT_USBMS_SUBCLASS_UFI = 0x04, VAS_EBOOT_USBMS_SUBCLASS_SFF8070 = 0x05 } VasEBoot_usbms_subclass_t; typedef enum { VAS_EBOOT_USBMS_PROTOCOL_BULK = 0x50, /* Experimental support for Control/Bulk/Interrupt (CBI) devices */ VAS_EBOOT_USBMS_PROTOCOL_CBI = 0x00, /* CBI with interrupt */ VAS_EBOOT_USBMS_PROTOCOL_CB = 0x01 /* CBI wthout interrupt */ } VasEBoot_usbms_protocol_t; static inline struct VasEBoot_usb_desc_if * VasEBoot_usb_get_config_interface (struct VasEBoot_usb_desc_config *config) { struct VasEBoot_usb_desc_if *interf; interf = (struct VasEBoot_usb_desc_if *) (sizeof (*config) + (char *) config); return interf; } typedef int (*VasEBoot_usb_attach_hook_class) (VasEBoot_usb_device_t usbdev, int configno, int interfno); struct VasEBoot_usb_attach_desc { struct VasEBoot_usb_attach_desc *next; struct VasEBoot_usb_attach_desc **prev; int class; VasEBoot_usb_attach_hook_class hook; }; void VasEBoot_usb_register_attach_hook_class (struct VasEBoot_usb_attach_desc *desc); void VasEBoot_usb_unregister_attach_hook_class (struct VasEBoot_usb_attach_desc *desc); void VasEBoot_usb_poll_devices (int wait_for_completion); void VasEBoot_usb_device_attach (VasEBoot_usb_device_t dev); VasEBoot_usb_err_t VasEBoot_usb_bulk_read_extended (VasEBoot_usb_device_t dev, struct VasEBoot_usb_desc_endp *endpoint, VasEBoot_size_t size, char *data, int timeout, VasEBoot_size_t *actual); VasEBoot_usb_transfer_t VasEBoot_usb_bulk_read_background (VasEBoot_usb_device_t dev, struct VasEBoot_usb_desc_endp *endpoint, VasEBoot_size_t size, void *data); VasEBoot_usb_err_t VasEBoot_usb_check_transfer (VasEBoot_usb_transfer_t trans, VasEBoot_size_t *actual); void VasEBoot_usb_cancel_transfer (VasEBoot_usb_transfer_t trans); void VasEBoot_ehci_init_device (volatile void *regs); void VasEBoot_ehci_pci_scan (void); #endif /* VAS_EBOOT_USB_H */