/* * GRUB -- GRand Unified Bootloader * Copyright (C) 2008 Free Software Foundation, Inc. * * GRUB 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. * * GRUB 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 GRUB. If not, see . */ #ifndef GRUB_USB_H #define GRUB_USB_H 1 #include #include #include #define GRUB_USB_MAX_CONF 8 #define GRUB_USB_MAX_IF 32 #define GRUB_USB_MAX_TOGGLE 256 typedef struct grub_usb_device *grub_usb_device_t; typedef struct grub_usb_controller *grub_usb_controller_t; typedef struct grub_usb_controller_dev *grub_usb_controller_dev_t; typedef enum { GRUB_USB_ERR_NONE, GRUB_USB_ERR_WAIT, GRUB_USB_ERR_INTERNAL, GRUB_USB_ERR_STALL, GRUB_USB_ERR_DATA, GRUB_USB_ERR_NAK, GRUB_USB_ERR_BABBLE, GRUB_USB_ERR_TIMEOUT, GRUB_USB_ERR_BITSTUFF, GRUB_USB_ERR_UNRECOVERABLE, GRUB_USB_ERR_BADDEVICE } grub_usb_err_t; typedef enum { GRUB_USB_SPEED_NONE, GRUB_USB_SPEED_LOW, GRUB_USB_SPEED_FULL, GRUB_USB_SPEED_HIGH } grub_usb_speed_t; typedef int (*grub_usb_iterate_hook_t) (grub_usb_device_t dev, void *data); typedef int (*grub_usb_controller_iterate_hook_t) (grub_usb_controller_t dev, void *data); /* Call HOOK with each device, until HOOK returns non-zero. */ int grub_usb_iterate (grub_usb_iterate_hook_t hook, void *hook_data); grub_usb_err_t grub_usb_device_initialize (grub_usb_device_t dev); grub_usb_err_t grub_usb_get_descriptor (grub_usb_device_t dev, grub_uint8_t type, grub_uint8_t index, grub_size_t size, char *data); grub_usb_err_t grub_usb_clear_halt (grub_usb_device_t dev, int endpoint); grub_usb_err_t grub_usb_set_configuration (grub_usb_device_t dev, int configuration); void grub_usb_controller_dev_register (grub_usb_controller_dev_t usb); void grub_usb_controller_dev_unregister (grub_usb_controller_dev_t usb); int grub_usb_controller_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data); grub_usb_err_t grub_usb_control_msg (grub_usb_device_t dev, grub_uint8_t reqtype, grub_uint8_t request, grub_uint16_t value, grub_uint16_t index, grub_size_t size, char *data); grub_usb_err_t grub_usb_bulk_read (grub_usb_device_t dev, struct grub_usb_desc_endp *endpoint, grub_size_t size, char *data); grub_usb_err_t grub_usb_bulk_write (grub_usb_device_t dev, struct grub_usb_desc_endp *endpoint, grub_size_t size, char *data); grub_usb_err_t grub_usb_root_hub (grub_usb_controller_t controller); /* XXX: All handled by libusb for now. */ struct grub_usb_controller_dev { /* The device name. */ const char *name; int (*iterate) (grub_usb_controller_iterate_hook_t hook, void *hook_data); grub_usb_err_t (*setup_transfer) (grub_usb_controller_t dev, grub_usb_transfer_t transfer); grub_usb_err_t (*check_transfer) (grub_usb_controller_t dev, grub_usb_transfer_t transfer, grub_size_t *actual); grub_usb_err_t (*cancel_transfer) (grub_usb_controller_t dev, grub_usb_transfer_t transfer); int (*hubports) (grub_usb_controller_t dev); grub_usb_err_t (*portstatus) (grub_usb_controller_t dev, unsigned int port, unsigned int enable); grub_usb_speed_t (*detect_dev) (grub_usb_controller_t dev, int port, int *changed); /* Per controller flag - port reset pending, don't do another reset */ grub_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 */ grub_size_t max_bulk_tds; /* The next host controller. */ struct grub_usb_controller_dev *next; }; struct grub_usb_controller { /* The underlying USB Host Controller device. */ grub_usb_controller_dev_t dev; /* Data used by the USB Host Controller Driver. */ void *data; }; struct grub_usb_interface { struct grub_usb_desc_if *descif; struct grub_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 grub_usb_device *dev, int config, int interface); void *detach_data; }; struct grub_usb_configuration { /* Configuration descriptors . */ struct grub_usb_desc_config *descconf; /* Interfaces associated to this configuration. */ struct grub_usb_interface interf[GRUB_USB_MAX_IF]; }; struct grub_usb_hub_port { grub_uint64_t soft_limit_time; grub_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 grub_usb_device { /* The device descriptor of this device. */ struct grub_usb_desc_device descdev; /* The controller the device is connected to. */ struct grub_usb_controller controller; /* Device configurations (after opening the device). */ struct grub_usb_configuration config[GRUB_USB_MAX_CONF]; /* Device address. */ int addr; /* Device speed. */ grub_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[GRUB_USB_MAX_TOGGLE]; /* Used by libusb wrapper. Schedulded for removal. */ void *data; /* Hub information. */ /* Array of children for a hub. */ grub_usb_device_t *children; /* Number of hub ports. */ unsigned nports; struct grub_usb_hub_port *ports; grub_usb_transfer_t hub_transfer; grub_uint32_t statuschange; struct grub_usb_desc_endp *hub_endpoint; /* EHCI Split Transfer information */ int split_hubport; int split_hubaddr; }; typedef enum grub_usb_ep_type { GRUB_USB_EP_CONTROL, GRUB_USB_EP_ISOCHRONOUS, GRUB_USB_EP_BULK, GRUB_USB_EP_INTERRUPT } grub_usb_ep_type_t; static inline enum grub_usb_ep_type grub_usb_get_ep_type (struct grub_usb_desc_endp *ep) { return ep->attrib & 3; } typedef enum { GRUB_USB_CLASS_NOTHERE, GRUB_USB_CLASS_AUDIO, GRUB_USB_CLASS_COMMUNICATION, GRUB_USB_CLASS_HID, GRUB_USB_CLASS_XXX, GRUB_USB_CLASS_PHYSICAL, GRUB_USB_CLASS_IMAGE, GRUB_USB_CLASS_PRINTER, GRUB_USB_CLASS_MASS_STORAGE, GRUB_USB_CLASS_HUB, GRUB_USB_CLASS_DATA_INTERFACE, GRUB_USB_CLASS_SMART_CARD, GRUB_USB_CLASS_CONTENT_SECURITY, GRUB_USB_CLASS_VIDEO } grub_usb_classes_t; typedef enum { GRUB_USBMS_SUBCLASS_BULK = 0x06, /* Experimental support for non-pure SCSI devices */ GRUB_USBMS_SUBCLASS_RBC = 0x01, GRUB_USBMS_SUBCLASS_MMC2 = 0x02, GRUB_USBMS_SUBCLASS_UFI = 0x04, GRUB_USBMS_SUBCLASS_SFF8070 = 0x05 } grub_usbms_subclass_t; typedef enum { GRUB_USBMS_PROTOCOL_BULK = 0x50, /* Experimental support for Control/Bulk/Interrupt (CBI) devices */ GRUB_USBMS_PROTOCOL_CBI = 0x00, /* CBI with interrupt */ GRUB_USBMS_PROTOCOL_CB = 0x01 /* CBI wthout interrupt */ } grub_usbms_protocol_t; static inline struct grub_usb_desc_if * grub_usb_get_config_interface (struct grub_usb_desc_config *config) { struct grub_usb_desc_if *interf; interf = (struct grub_usb_desc_if *) (sizeof (*config) + (char *) config); return interf; } typedef int (*grub_usb_attach_hook_class) (grub_usb_device_t usbdev, int configno, int interfno); struct grub_usb_attach_desc { struct grub_usb_attach_desc *next; struct grub_usb_attach_desc **prev; int class; grub_usb_attach_hook_class hook; }; void grub_usb_register_attach_hook_class (struct grub_usb_attach_desc *desc); void grub_usb_unregister_attach_hook_class (struct grub_usb_attach_desc *desc); void grub_usb_poll_devices (int wait_for_completion); void grub_usb_device_attach (grub_usb_device_t dev); grub_usb_err_t grub_usb_bulk_read_extended (grub_usb_device_t dev, struct grub_usb_desc_endp *endpoint, grub_size_t size, char *data, int timeout, grub_size_t *actual); grub_usb_transfer_t grub_usb_bulk_read_background (grub_usb_device_t dev, struct grub_usb_desc_endp *endpoint, grub_size_t size, void *data); grub_usb_err_t grub_usb_check_transfer (grub_usb_transfer_t trans, grub_size_t *actual); void grub_usb_cancel_transfer (grub_usb_transfer_t trans); void grub_ehci_init_device (volatile void *regs); void grub_ehci_pci_scan (void); #endif /* GRUB_USB_H */