text: /*
   * Copyright (C) 2015-2017 Alibaba Group Holding Limited
   */
  
  #ifndef UMESH_HAL_H
  #define UMESH_HAL_H
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  #include <stdint.h>
  
  #include "umesh_types.h"
  
  struct umesh_hal_module_s;
  
  /**
   * Callback function when ucast frame send done
   *
   * @param[out] context The context
   * @param[in]  frame   The frame that has been sent
   * @param[out] error   The error code for this sent frame
   */
  typedef void (*umesh_handle_sent_ucast_t)(void *context,
                                            frame_t *frame, int error);
  
  /**
   * Callback function when bcast frame send done
   *
   * @param[out] context The context
   * @param[in]  frame   The frame that has been sent
   * @param[out] error   The error code for this sent frame
   */
  typedef void (*umesh_handle_sent_bcast_t)(void *context,
                                            frame_t *frame, int error);
  
  /**
   * Callback function when frame received
   *
   * @param[out] context The context
   * @param[in]  frame      The received frame
   * @param[out] frame_info The frame info that needs by uppder layer
   * @param[out] error      The error code for this received data frame
   */
  typedef void (*umesh_handle_received_frame_t)(void *context, frame_t *frame,
                                                frame_info_t *frame_info,
                                                int error);
  
  /**
   * Callback function when received commands
   *
   * @param[in] buf    The received commands
   * @param[in] length The commands length
   */
  typedef void (*umesh_cli_input_t)(const uint8_t *buf, uint16_t length);
  
  typedef struct umesh_hal_module_s {
      hal_module_base_t base;
      media_type_t type;
      umesh_handle_received_frame_t receiver;
  
      int (*umesh_hal_init)(struct umesh_hal_module_s *module, void *config);
      int (*umesh_hal_enable)(struct umesh_hal_module_s *module);
      int (*umesh_hal_disable)(struct umesh_hal_module_s *module);
  
      /* send ucast frame */
      int (*umesh_hal_send_ucast_request)(struct umesh_hal_module_s *module,
                                          frame_t *frame, mac_address_t *dest,
                                          umesh_handle_sent_ucast_t sent,
                                          void *context);
      /* send bcast frame */
      int (*umesh_hal_send_bcast_request)(struct umesh_hal_module_s *module,
                                          frame_t *frame,
                                          umesh_handle_sent_bcast_t sent,
                                          void *context);
  
      /* register call back when received packet */
      int (*umesh_hal_register_receiver)(struct umesh_hal_module_s *module,
                                         umesh_handle_received_frame_t received, void *context);
  
      /* request low layer to transmit beacons intervally*/
      int (*umesh_hal_get_bcast_mtu)(struct umesh_hal_module_s *module);
      int (*umesh_hal_get_ucast_mtu)(struct umesh_hal_module_s *module);
  
      int (*umesh_hal_set_channel)(struct umesh_hal_module_s *module, uint8_t channel);
      int (*umesh_hal_get_channel)(struct umesh_hal_module_s *module);
      int (*umesh_hal_get_chnlist)(struct umesh_hal_module_s *module, const uint8_t **chnlist);
  
      int (*umesh_hal_set_txpower)(struct umesh_hal_module_s *module, int8_t txpower);
      int (*umesh_hal_get_txpower)(struct umesh_hal_module_s *module);
  
      int (*umesh_hal_set_extnetid)(struct umesh_hal_module_s *module,
                                    const umesh_extnetid_t *extnetid);
      void (*umesh_hal_get_extnetid)(struct umesh_hal_module_s *module,
                                     umesh_extnetid_t *extnetid);
      const mac_address_t *(*umesh_hal_get_mac_address)(
          struct umesh_hal_module_s *module);
  
      int (*umesh_hal_set_key)(struct umesh_hal_module_s *module,
                               uint8_t index, uint8_t *key, uint8_t length);
      int (*umesh_hal_is_sec_enabled)(struct umesh_hal_module_s *module);
  
      const frame_stats_t *(*umesh_hal_get_stats)(struct umesh_hal_module_s *module);
  } umesh_hal_module_t;
  
  /**
   * Initialize all registed HAL modules.
   *
   * @return
   *     Initalization result, 0 if success, nonzero if fail
   */
  int hal_umesh_init(void);
  
  /**
   * Get the defaut umesh HAL
   *
   * The system may have more than 1 mesh HAL instances.
   *
   * @return
   *     Instance pointer or NULL
   */
  umesh_hal_module_t *hal_umesh_get_default_module(void);
  
  /**
   * Get the next umesh HAL
   *
   * The system may have more than 1 mesh HAL instances.
   *
   * @return
   *     Instance pointer or NULL
   */
  umesh_hal_module_t *hal_umesh_get_next_module(umesh_hal_module_t *cur);
  
  /**
   * Register one or more mesh instances to HAL.
   *
   * @param[in] module The HAL module to be registered
   */
  void hal_umesh_register_module(umesh_hal_module_t *module);
  
  /**
   * Enable a umesh HAL module, which usually powers on its hardware
   *
   * @param[in] module The HAL module to be operated; if NULL, the default module will be operated
   *
   * @return
   *     Enable result, 0 if success, -1 if fail
   */
  int hal_umesh_enable(umesh_hal_module_t *module);
  
  /**
   * Disable a umesh HAL module, which usually power off its hardware
   *
   * @param[in] module The HAL module to be operated; if NULL, the default module will be operated
   *
   * @return
   *     Disable result, 0 if success, -1 if fail
   */
  int hal_umesh_disable(umesh_hal_module_t *module);
  
  /**
   * Send HAL ucast frame request
   *
   * @param[in] module  The HAL module to send data to; if NULL, the default module will be used
   * @param[in] frame   The frame buffer that contains the data
   * @param[in] dest    The destination of this frame.
   * @param[in] sent    The callback function to be called after hardware send data finish
   * @param[in] context The context
   *
   * @return
   *     Send frame request result, 0 if success, -1 if fail
   */
  int hal_umesh_send_ucast_request(umesh_hal_module_t *module,
                                   frame_t *frame, mac_address_t *dest,
                                   umesh_handle_sent_ucast_t sent, void *context);
  
  /**
   * Send HAL bcast frame request
   *
   * @param[in] module  The HAL module to send data to; if NULL, the default module will be used
   * @param[in] frame   The frame buffer that contains the data
   * @param[in] sent    The callback function to be called after hardware send data finish
   * @param[in] context The context
   *
   * @return
   *     Send frame request result, 0 if success, -1 if fail
   */
  int hal_umesh_send_bcast_request(umesh_hal_module_t *module,
                                   frame_t *frame,
                                   umesh_handle_sent_bcast_t sent, void *context);
  
  /**
   * Register data frame receiver callback function
   *
   * @param[in] module   The HAL module to receive data from; if NULL, the default module will be used
   * @param[in] received The callback function to be called after hardware received data
   * @param[in] context  The context
   *
   * @return
   *     Register receiver result, 0 if success, -1 if fail
   */
  int hal_umesh_register_receiver(umesh_hal_module_t *module,
                                  umesh_handle_received_frame_t received, void *context);
  
  /**
   * Request HAL to send beacons
   *
   * @param[in] module       The HAL module to send data to; if NULL, the default module will be used
   * @param[in] frame        The frame buffer that contains the data and config information
   * @param[in] dest         The destination of this frame.
   * @param[in] max_interval The max interval that low layer needs to transmit beacon
   *
   * @return
   *     The result, 0 if success, -1 if fail
   */
  int hal_umesh_start_beacons(umesh_hal_module_t *module,
                              frame_t *frame, mac_address_t *dest,
                              uint16_t max_interval);
  
  /**
   * Stop HAL to send beacons
   *
   * @param[in] module The HAL module to send data to; if NULL, the default module will be used
   *
   * @return
   *     The result, 0 if success, -1 if fail
   */
  int hal_umesh_stop_beacons(umesh_hal_module_t *module);
  
  /**
   * Set HAL broadcast MTU, MTU is normally decided by HAL.
   *
   * @param[in] module The HAL module to be operated; if NULL, the default module will be operated
   * @param[in] mtu    The MTU to be set
   *
   * @return
   *     Set media configuration result, 0 if success, -1 if fail
   */
  int hal_umesh_set_bcast_mtu(umesh_hal_module_t *module, uint16_t mtu);
  
  /**
   * Get HAL broadcast MTU
   *
   * @param[in] module The HAL module to be operated; if NULL, the default module will be operated
   *
   * @return
   *     The MTU, -1 if fail
   */
  int hal_umesh_get_bcast_mtu(umesh_hal_module_t *module);
  
  /**
   * Set HAL unicast MTU, MTU is normally decided by HAL.
   *
   * @param[in] module The HAL module to be operated; if NULL, the default module will be operated
   * @param[in] mtu    The MTU to be set
   *
   * @return
   *     Set media configuration result, 0 if success, -1 if fail
   */
  int hal_umesh_set_ucast_mtu(umesh_hal_module_t *module, uint16_t mtu);
  
  /**
   * Get HAL unicast MTU
   *
   * @param[in] module The HAL module to be operated; if NULL, the default module will be operated
   *
   * @return
   *     The MTU, -1 if fail
   */
  int hal_umesh_get_ucast_mtu(umesh_hal_module_t *module);
  
  /**
   * Set channel
   *
   * @param[in] module  The HAL module to be operated; if NULL, the default module will be operated
   * @param[in] channel The channel to be set
   *
   * @return
   *     Set media configuration result, 0 if success, -1 if fail
   */
  int hal_umesh_set_channel(umesh_hal_module_t *module, uint8_t channel);
  
  /**
   * Get channel
   *
   * @param[in] module The HAL module to be operated; if NULL, the default module will be operated
   *
   * @return
   *     The channel, -1 if fail
   */
  int hal_umesh_get_channel(umesh_hal_module_t *module);
  
  /**
   * Get channel list
   *
   * @param[in] module  The HAL module to be operated; if NULL, the default module will be operated
   * @param[in] chnlist Pointer to store the unicast channel list
   *
   * @return
   *     The number of unicast channels, -1 if fail
   */
  int hal_umesh_get_chnlist(umesh_hal_module_t *module, const uint8_t **chnlist);
  
  /**
   * Set transmit power
   *
   * @param[in] module  The HAL module to be operated; if NULL, the default module will be operated
   * @param[in] txpower The transmit power to be set
   *
   * @return
   *     Set media configuration result, 0 if success, -1 if fail
   */
  int hal_umesh_set_txpower(umesh_hal_module_t *module, int8_t txpower);
  
  /**
   * Get transmit power
   *
   * @param[in] module The HAL module to be operated; if NULL, the default module will be operated
   *
   * @return
   *     The transmit power, -1 if fail
   */
  int hal_umesh_get_txpower(umesh_hal_module_t *module);
  
  /**
   * Set extension meshnetid
   *
   * @param[in] module   The HAL module to be operated; if NULL, the default module will be operated
   * @param[in] extnetid The extension meshnetid to be set
   *
   * @return
   *     Set media configuration result, 0 if success, -1 if fail
   */
  int hal_umesh_set_extnetid(umesh_hal_module_t *module,
                             const umesh_extnetid_t *extnetid);
  
  /**
   * Get extension meshnetid
   *
   * @param[in] module   The HAL module to be operated; if NULL, the default module will be operated
   * @param[in] extnetid The extension meshnetid to be get
   *
   */
  void hal_umesh_get_extnetid(umesh_hal_module_t *module,
                              umesh_extnetid_t *extnetid);
  
  /**
   * Set HAL mac address.
   *
   * @param[in] module The HAL module to be operated; if NULL, the default module will be operated
   * @param[in] addr   The mac address to be set
   *
   * @return
   *     Set media configuration result, 0 if success, -1 if fail
   */
  int hal_umesh_set_mac_address(umesh_hal_module_t *module,
                                const mac_address_t *addr);
  
  /**
   * Get HAL mac address.
   *
   * @param[in] module The HAL module to be operated; if NULL, the default module will be operated
   *
   * @return
   *     The mac address, NULL if fail
   */
  const mac_address_t *hal_umesh_get_mac_address(umesh_hal_module_t *module);
  
  /**
   * Set HAL encryption key.
   *
   * @param[in] module The HAL module to be operated; if NULL, the default module will be operated
   * @param[in] index  The key index
   * @param[in] key    The pointer to the encryption key
   * @param[in] length The key length, default value is 16
   *
   * @return
   *     Set result, 0 if success, -1 if fail
   */
  int hal_umesh_set_key(struct umesh_hal_module_s *module,
                        uint8_t index, uint8_t *key, uint8_t length);
  
  /**
   * Check whether security is enabled or not by the specified HAL.
   *
   * @param[in] module The HAL module to be operated; if NULL, the default module will be operated
   *
   * @return
   *     Security state, 0 if disabled, 1 if enabled
   */
  int hal_umesh_is_sec_enabled(struct umesh_hal_module_s *module);
  
  /**
   * Read umesh HAL frame stats.
   *
   * @param[in] module The HAL module to be operated; if NULL, the default module will be operated
   *
   * @return
   *     The HAL frame stats, NULL if fail
   */
  const frame_stats_t *hal_umesh_get_stats(umesh_hal_module_t *module);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif /* UMESH_HAL_H */
  