/* usb/msg.h
 *
 * (c) 2002 Simtec Electronics
 *
 * Ben Dooks
 *
 * USB Message Definitions
 *
 * $Id: msg.h,v 1.43 2003/12/01 17:31:49 ben Exp $
 *
 * This Library file is part of the Simtec Electronics USB stack development
 *   suite.
 * Specific licence is granted to use this file by third parties for the
 *   development of USB device drivers.
 *
*/

#ifndef __USB_MSG_H
#define __USB_MSG_H "$Id: msg.h,v 1.43 2003/12/01 17:31:49 ben Exp $"

#ifndef __USB_DEVICE_H
#include "usb/device.h"
#endif

/* usb message system
 * ------------------
 *
 * The usb core provides a mechanism for distributing information a number
 * of interested parties. The usbmsg structure describes the basic format of
 * these messages, with a number of message classes indicating the contents
 * of the message.
 *
 * usbmsg_send can be used to send a message block described by struct usbmsg,
 * and the usbmsg_*_handler functions can control the list of receivers.
 *
 * User defined messages are allowed, as long as they keep to using class
 * codes in the range of USBMSG_CLASS_USER upwards.
 *
 * An receiver can control the class of message
*/

/** enum of the permitted message classes
@memo enum of the permitted message classes
*/
enum usbmsg_class {
    usbmsg_class_hub,
    usbmsg_class_powercap,
    usbmsg_class_newdev,
    usbmsg_class_configchange,
    usbmsg_class_claiminterface,
    usbmsg_class_pipe_exclusive,
    usbmsg_class_capacity,
    usbmsg_class_controller,
    usbmsg_class_log,
    usbmsg_class_unclaimed_dev,
    usbmsg_class_setconfig,
    usbmsg_class_prereset,
    usbmsg_class_hubreq,
    usbmsg_class_module,

    USBMSG_CLASS_MAX      /* used for various things for maximum msg class */
};

typedef enum usbmsg_class usbmsg_class_t;

/** Base for user message class codes
 *
*/
#define USBMSG_CLASS_USER     ((usbmsg_class_t)0x80000000)

/** usb message header structure
 */
struct usbmsg_hdr {
    usbmsg_class_t	class;
    size_t              size;   /* size is total size incl. header */
};

/* class usbmsg_capacity */
/** capacity types for capacity message class
    @see usbmsg_class
*/
enum usbmsg_capacity_type {
    usbmsg_capacity_claim,
    usbmsg_capacity_release,
    usbmsg_capacity_test
};


typedef enum usbmsg_capacity_type usbmsg_capacity_type_t;

/** capacity struct for capacity message class
@memo capacity struct for capacity message class
@see usbmsg_class
@see usbmsg_capacity_type
*/
struct usbmsg_capacity {
    usbmsg_capacity_type_t op;

    void *host;     /* host controller */
    long speed;
    long type;
    long maxdata;
    long repeat;    /* frame repeat */
};

/* class usbmsg_hub */
/** Message sub-types for the HUB message class

    @memo hub types for hub message class
    @see usbmsg_class
*/
enum usbmsg_hub_type {
    USBMSG_HUB_OC_OCCURED,
    USBMSG_HUB_OC_CLEARED,
    USBMSG_HUB_DEVICE_ATTACH,
    USBMSG_HUB_DEVICE_REMOVE,
    USBMSG_HUB_DEVICE_DISABLED,
    USBMSG_HUB_DEVICE_RESET
};

typedef enum usbmsg_hub_type usbmsg_hub_type_t;

/** Message data for messages in the hub message class

These messages are sent when the hub driver has detected a change in
one of the devices connected to it. An driver should pick these messages
up and examine them to see if it is for a device being controlled.

@memo hub struct for hub message class
@see usbmsg_class
@see usbmsg_hub_type
*/
struct usbmsg_hub {
    usbmsg_hub_type_t type;

    void  *controller_ref;          /* controller reference for the hub */
    void  *device_ref;              /* device refernce of the hub itself */

    int   port;
    void  *attached_ref;            /* device reference of attached device */
    int   attached_number;          /* device number connected to this port */
};


/* pipe exclusive message class */
/** pipeexclusive struct for pipeexclusive message class
    @memo pipeexclusive struct for pipeexclusive message class
    @see usbmsg_class
*/
struct usbmsg_pipeexclusive {
    void       *controller_ref;
    void       *device_ref;
    void       *default_endpoint_ref;

    int        ok;
};


/* claiminterface message class */
/** claim interface structure for claiminterface message class
    @memo claim interface structure for claiminterface message class
    @see usbmsg_class
*/
struct usbmsg_claiminterface {
    int                              ok;    /* 1 == allow, 0 = reject */
    int                              interface;
    void                             *controller_ref;
    void                             *device_ref;
};


/* configchange messgae class */
/** configuration changed types for configchange message class
    @memo configuration changed types for configchange message class
    @see usbmsg_class
    @see usbmsg_configchange
*/
enum usbmsg_configchange_type {
    usbmsg_configchange_config,
    usbmsg_configchange_interface
};

/**  configchange structure for configchange message class
 *
 * this is broadcast when the system is about to change the configuration
 * on a given device. If the configuration is declined, then the change will
 * not go ahead.
 *
 * Typically this is sent after a device has been attached and the hub module
 * is attempting the initial configuration of a device.
 *
@memo configchange structure for configchange message class
@see usbmsg_class
@see usbmsg_configchange_type
*/
struct usbmsg_configchange {
    enum usbmsg_configchange_type    type;

    int                              ok;    /* 1 == allow, 0 = reject */
    int                              interface;
    void                             *controller_ref;
    void                             *device_ref;
};

/* poercap message class */

/** power capacity types for powercap message class
@memo power capacity types for powercap message class
@see usbmsg_class
@see usbmsg_powercap
*/
enum usbmsg_powercap_type {
    USBMSG_POWERCAP_TEST

};


typedef enum usbmsg_powercap_type usbmsg_powercap_type_t;

/** power capacity structure for powercap message class
@memo  power capacity structure for powercap message class
@see usbmsg_class
@see usbmsg_powercap_type
*/
struct usbmsg_powercap {
    usbmsg_powercap_type_t    type;

    int controller_ref;           /* TODO: get correct type */
    int device_no;

    int max_power;
    int ok;
};

/* new device class */
#define USBMSG_NEWDEV_MAX_ENDPOINT (256)

/** new device phases for new_device message class. Indicates to which phase of driver search the new device message refers.
@memo new device phases for new_device message class
@see usbmsg_class
@see usbmsg_new_device
*/
enum usbmsg_new_device_try {
    USBMSG_NEWDEV_TRY_VENDOR,
    USBMSG_NEWDEV_TRY_CLASS
};


typedef enum usbmsg_new_device_try usbmsg_new_device_try_t;

/** new device types for new_device message class
@memo new device types for new_device message class
@see usbmsg_class
@see usbmsg_new_device
*/
enum usbmsg_new_device_type {
    USBMSG_NEWDEV_CURRENTDRIVER,
    USBMSG_NEWDEV_NEWDRIVER
};


typedef enum usbmsg_new_device_type usbmsg_new_device_type_t;

/** New device structure for new_device message class
 *
 * This is sent by the system when a new device has been configured and is
 * ready for use. The message describes a single interface on the device,
 * a new message being sent for each interface the device has.
 *
@memo New device structure for new_device message class
@see usbmsg_class
@see usbmsg_new_device_type
@see usbmsg_new_device_try
*/
struct usbmsg_new_device
{
    /* the state of the driver loading request */
    usbmsg_new_device_type_t type;
    usbmsg_new_device_try_t  try;

    /* specific to this device */

    unsigned long vendor_id;
    unsigned long product_id;

  /* information about the interface being offered... */

    unsigned long interface_number;
    unsigned long interface_class;
    unsigned long interface_subclass;
    unsigned long interface_protocol;
    unsigned long interface_endpoints;

    char  *controller_name;
    char  *serial_number;

    unsigned long device_number;

    void *internal;      /* pointer to internal info (device config info), and
			  * should only be used by the hub driver. */

  /* endpoints associated with this interface. We currently do not
   * offer the default endpoint here as it is being kept by the hub
   * module. It is possible that if the default configuration has an
   * 'impossible' endpoint, then the system will ignore the
   */

    struct usb_newdev_endpoint {
	void *reference;
	int  number;
    } endpoints[USBMSG_NEWDEV_MAX_ENDPOINT];
};

/* sent by usb_controller_deregister */

/** controller types for controller message class
@memo controller types for controller message class
@see usbmsg_class
@see usbmsg_controller
*/
enum usbmsg_controller_type_e {
    USBMSG_CONTROLLER_STARTING,
    USBMSG_CONTROLLER_STOPPING
};


typedef enum usbmsg_controller_type_e usbmsg_controller_type_t;

/** Controller structure for controller message class.
@memo Controller structure for controller message class.
@see usbmsg_class
@see usbmsg_controller_type_e
*/
struct usbmsg_controller {
    usbmsg_controller_type_t  type;
    usb_hc_t                  hc;
};

enum usbmsg_log_type_e {
    USBMSG_LOG_RESTART
};

typedef enum usbmsg_log_type_e usbmsg_log_type_t;

struct usbmsg_log {
    usbmsg_log_type_t         type;
};

enum usbmsg_devmgr_type_e {
  USBMSG_DEVMGR_FIND,
  USBMSG_DEVMGR_RELEASE,
  USBMSG_DEVMGR_CLAIM,
  USBMSG_DEVMGR_DROP
};

/* re-map to the original definitions of these fields */
#define USBMSG_UNCLAIMED_DEV_FIND USBMSG_DEVMGR_FIND
#define USBMSG_UNCLAIMED_DEV_RELEASE USBMSG_DEVMGR_RELEASE
#define USBMSG_UNCLAIMED_DEV_CLAIM USBMSG_DEVMGR_CLAIM
#define USBMSG_UNCLAIMED_DEV_DROP USBMSG_DEVMGR_DROP

typedef enum usbmsg_devmgr_type_e usbmsg_devmgr_type_t;

#define usbmsg_unclaimed_dev_type_e usbmsg_devmgr_type_e
#define usbmsg_unclaimed_dev_type_t usbmsg_devmgr_type_t

struct usbmsg_device_filter {
  unsigned char       check_interface_class;
  unsigned char       check_interface_subclass;
  unsigned char       check_interface_protocol;
  unsigned char       check_vendor_id;
  unsigned char       check_product_id;

  int                 interface_class;
  int                 interface_subclass;
  int                 interface_protocol;
  int                 vendor_id;
  int                 product_id;
};

/* following are result codes from devmgr ops */
/** Operation completed sucessfuly */
#define USB_DEVMGR_RESULT_OK               (USB_RESULT_OK)
/** The device did not respond */
#define USB_DEVMGR_RESULT_NOT_AVAILABLE    (USB_RESULT_DEVMGR_NORESPONSE)
/** no device was found */
#define USB_DEVMGR_RESULT_NODEVICE         (USB_RESULT_DEVICE_NOT_FOUND)
/** the device was already claimed */
#define USB_DEVMGR_RESULT_ALREADYCLAIMED   (USB_RESULT_DEVMGR_ALREADYCLAIMED)
/** an invalid argument was passed */
#define USB_DEVMGR_RESULT_INVALID_ARGUMENT (USB_RESULT_INVALID_ARGUMENT)

/* map original structure name to the new one */
#define usbmsg_unclaimed_dev usbmsg_devmgr

/** message structure for unclaimed device management
@memo message structure for unclaimed device management
@see usbmsg_class
*/

struct usbmsg_devmgr {
   usbmsg_unclaimed_dev_type_t      type;

   union {
     struct {
       int                              size;
       int                              skip;
       int                              *result;
       int                              *done;
       struct usbmsg_device_filter      **filters;
       struct usbmsg_new_device         **devices;
     } find;

     struct {
       struct usbmsg_new_device         *device;
       int                              advertise;
       int                              *result;
     } release;

     struct {
       struct usbmsg_new_device         *device;
       int                              *result;
     } claim;

     struct {
       struct usbmsg_new_device         *device;
       int                              *result;
     } drop;
   } data;
};

enum usbmsg_setconfig_type_e {
  USBMSG_SETCONFIG_NONE,
  USBMSG_SETCONFIG_INTERFACE
};

typedef enum usbmsg_setconfig_type_e  usbmsg_setconfig_type_t;

/* setconfig results - will be returned in the waiting structure that
 * was passed in to the setconfig code, or direct from the message
*/

#define USB_SETCONFIG_RESULT_NOTAVAILABLE   (USB_RESULT_NOT_AVAILABLE)
#define USB_SETCONFIG_RESULT_OK             (1)
#define USB_SETCONFIG_RESULT_RUNNING        (USB_RESULT_IN_PROGRESS)
#define USB_SETCONFIG_RESULT_FAILED         (USB_RESULT_FAILED)
#define USB_SETCONFIG_RESULT_NORESOURCES    (USB_RESULT_NO_RESOURCES)

/** USB SetConfig result - unknown config type in type field
*/
#define USB_SETCONFIG_RESULT_UNKNOWN_TYPE  (USB_RESULT_INVALID_ARGUMENT)

#define USB_SETCONFIG_RESULT_DEVICENOTFOUND (USB_RESULT_DEVICE_NOT_FOUND)

/** USB Message to set configuration of a device / interface
 *
 * This message is used to change the configuartion of an specific
 * part of a device, such as selecting an alternative interface.
 *
 * Note, the waiting pointed to in the message is not duplicated, and
 * will be modified by the usb system when doing the change. The waiting
 * structure must be in globally accessible memory.
 *
 * @memo USB Message to set configuration of a device / interface
 * @see usbmsg_send
 * @see usbmsg_class
*/
struct usbmsg_setconfig {
  usbmsg_setconfig_type_t     type;

  usb_device_t                device;
  usb_wait_t                 *wait;

  union {
    /* set a specific configuration of the interface concerned */

    struct {
      int            interface;
      int            setting;
    } interface;

  } data;
};

typedef enum usbhub_req_e {
  USBHUB_REQ_RESETDEVICE
} usbhub_req_t;

struct usbmsg_hubreq {
  usb_device_t       device;
  usbhub_req_t       req;
  usb_wait_t        *wait;

  union {
    struct {
      unsigned int flags;
    } reset;
  } params;
};


struct usbmsg_module_def {
  const char         *name;        /* name */
  const char         *info;        /* full module info, build date, etc */
  const char         *osname;      /* os name */
  unsigned int        id;          /* unique id */
  unsigned int        version;     /* version, *100 */
};

#define USBMOD_CORE             (0x01)
#define USBMOD_HUB              (0x02)
#define USBMOD_HIDCORE          (0x03)
#define USBMOD_ISP1161          (0x04)
#define USBMOD_PRINTER          (0x05)
#define USBMOD_LIBRARY          (0x06)
#define USBMOD_JOYSTICK_CORE    (0x07)
#define USBMOD_JOYSTICK_GENERIC (0x08)

/** Request field for usbmsg_module
 *
 * @see usbmsg_module
*/

enum usbmsg_module_req {
  USBMSG_MODULE_STARTING,
  USBMSG_MODULE_STARTED,
  USBMSG_MODULE_FINALISING,
  USBMSG_MODULE_FINALISED,
  USBMSG_MODULE_LIST
};

/** usbmsg_module_list
 *
 * this is formed when the usbmsg_module is sent with request of 
 * USBMSG_MODULE_LIST is issued. It is the caller's responsibility to
 * free the list. The order of the items returned is not guaranteed.
 *
 * @see USBMSG_MODULE_LIST
 * @see usbmsg_module
 * @see usb_free
 */


struct usbmsg_module_list {
  struct usbmsg_module_list *next;
  struct usbmsg_module_def *def;
};

/** USB Msg - Module information and status
 *
 * This is sent by various parts of the USB system when modules start
 * or stop. This can also be sent by any application that wants to know
 * about which usb modules have been loaded by the system.
*/

struct usbmsg_module {
  enum usbmsg_module_req  req;

  union {
    struct usbmsg_module_list  *list;
    struct usbmsg_module_def    def;
  } data;
};


/** USB message union for all represented message classes.</para>
<para>This union is the datatype used for passing messages back and forth in the USB messaging system.
@memo USB message union for all represented message classes
@see usbmsg_hdr
@see usbmsg_hub
@see usbmsg_powercap
@see usbmsg_new_device
@see usbmsg_capacity
@see usbmsg_configchange
@see usbmsg_pipeexclusive
@see usbmsg_claiminterface
@see usbmsg_controller
@see usbmsg_devmgr
@see usbmsg_setconfig
@see usbmsg_module
*/
struct usbmsg {
    struct usbmsg_hdr    hdr;

    union {
	struct usbmsg_hub            hub;
	struct usbmsg_powercap       powercap;
	struct usbmsg_new_device     *newdev;
	struct usbmsg_capacity       capacity;
	struct usbmsg_configchange   cfgchange;
	struct usbmsg_pipeexclusive  pipe_exclusive;
	struct usbmsg_claiminterface claim_interface;
	struct usbmsg_controller     controller;
        struct usbmsg_log            log;
        struct usbmsg_unclaimed_dev  unclaimed_dev;
        struct usbmsg_setconfig      set_config;
        struct usbmsg_hubreq         hub_req;
        struct usbmsg_module         mod;
        void                         *user_ptr;
    } data;
};

/** Send a message to the USB system.
@memo Send a message to the USB system.
@param msg The message to send.
@return returns 0 for unclaimed or 1 if claimed
*/
extern int usbmsg_send(struct usbmsg *msg);

/** typedef for message handler function
@memo typedef for message handler function
 */
typedef int (*usbmsg_handler_t)(struct usbmsg *msg, void *);

/** Register a message handler with USB system
@memo Register a message handler with USB system
 */
extern int usbmsg_register_handler(usbmsg_handler_t , void *);

/** De register a message handler with USB system
@memo De register a message handler with USB system
*/
extern int usbmsg_deregister_handler(usbmsg_handler_t , void *);

/** Adds a message class filter to a handler. Used to enable a handler to only recive messages it wants to process.
@memo Adds a message class filter to a handler.
@param handler pointer to message handler as used when registering handler.
@param pw private word as passed when registering handler.
@param msgclass message class to apply filter to.
@param enable 0 indicates message class is not passed to the caller 1 indicates message class will be passed to the caller.
 */
extern int usbmsg_filter(usbmsg_handler_t handler, void * pw, usbmsg_class_t msgclass, int enable);

/** sets the filter for all message types. Used for enabling and disabling messages going to a handler altogether.
@memo sets the filter for all message types
*/
extern int usbmsg_filterall(usbmsg_handler_t, void *, int);

#endif /* __USB_MSH_H */
