Merge "LE: Add limited advertising duration capability (1/3)" into lmp-dev
diff --git a/include/hardware/audio.h b/include/hardware/audio.h
index 95111dd..59fb9a3 100644
--- a/include/hardware/audio.h
+++ b/include/hardware/audio.h
@@ -94,6 +94,12 @@
#define AUDIO_PARAMETER_VALUE_TTY_HCO "tty_hco"
#define AUDIO_PARAMETER_VALUE_TTY_FULL "tty_full"
+/* Hearing Aid Compatibility - Telecoil (HAC-T) mode on/off
+ Strings must be in sync with CallFeaturesSetting.java */
+#define AUDIO_PARAMETER_KEY_HAC "HACSetting"
+#define AUDIO_PARAMETER_VALUE_HAC_ON "ON"
+#define AUDIO_PARAMETER_VALUE_HAC_OFF "OFF"
+
/* A2DP sink address set by framework */
#define AUDIO_PARAMETER_A2DP_SINK_ADDRESS "a2dp_sink_address"
@@ -106,16 +112,17 @@
/* Bluetooth SCO wideband */
#define AUDIO_PARAMETER_KEY_BT_SCO_WB "bt_wbs"
+
/**
* audio stream parameters
*/
-#define AUDIO_PARAMETER_STREAM_ROUTING "routing" // audio_devices_t
-#define AUDIO_PARAMETER_STREAM_FORMAT "format" // audio_format_t
-#define AUDIO_PARAMETER_STREAM_CHANNELS "channels" // audio_channel_mask_t
-#define AUDIO_PARAMETER_STREAM_FRAME_COUNT "frame_count" // size_t
-#define AUDIO_PARAMETER_STREAM_INPUT_SOURCE "input_source" // audio_source_t
-#define AUDIO_PARAMETER_STREAM_SAMPLING_RATE "sampling_rate" // uint32_t
+#define AUDIO_PARAMETER_STREAM_ROUTING "routing" /* audio_devices_t */
+#define AUDIO_PARAMETER_STREAM_FORMAT "format" /* audio_format_t */
+#define AUDIO_PARAMETER_STREAM_CHANNELS "channels" /* audio_channel_mask_t */
+#define AUDIO_PARAMETER_STREAM_FRAME_COUNT "frame_count" /* size_t */
+#define AUDIO_PARAMETER_STREAM_INPUT_SOURCE "input_source" /* audio_source_t */
+#define AUDIO_PARAMETER_STREAM_SAMPLING_RATE "sampling_rate" /* uint32_t */
/* Query supported formats. The response is a '|' separated list of strings from
* audio_format_t enum e.g: "sup_formats=AUDIO_FORMAT_PCM_16_BIT" */
@@ -127,6 +134,11 @@
* "sup_sampling_rates=44100|48000" */
#define AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES "sup_sampling_rates"
+/* Get the HW synchronization source used for an output stream.
+ * Return a valid source (positive integer) or AUDIO_HW_SYNC_INVALID if an error occurs
+ * or no HW sync source is used. */
+#define AUDIO_PARAMETER_STREAM_HW_AV_SYNC "hw_av_sync"
+
/**
* audio codec parameters
*/
@@ -146,18 +158,6 @@
/**************************************/
-/* common audio stream configuration parameters
- * You should memset() the entire structure to zero before use to
- * ensure forward compatibility
- */
-struct audio_config {
- uint32_t sample_rate;
- audio_channel_mask_t channel_mask;
- audio_format_t format;
- audio_offload_info_t offload_info;
-};
-typedef struct audio_config audio_config_t;
-
/* common audio stream parameters and operations */
struct audio_stream {
@@ -563,13 +563,21 @@
size_t (*get_input_buffer_size)(const struct audio_hw_device *dev,
const struct audio_config *config);
- /** This method creates and opens the audio hardware output stream */
+ /** This method creates and opens the audio hardware output stream.
+ * The "address" parameter qualifies the "devices" audio device type if needed.
+ * The format format depends on the device type:
+ * - Bluetooth devices use the MAC address of the device in the form "00:11:22:AA:BB:CC"
+ * - USB devices use the ALSA card and device numbers in the form "card=X;device=Y"
+ * - Other devices may use a number or any other string.
+ */
+
int (*open_output_stream)(struct audio_hw_device *dev,
audio_io_handle_t handle,
audio_devices_t devices,
audio_output_flags_t flags,
struct audio_config *config,
- struct audio_stream_out **stream_out);
+ struct audio_stream_out **stream_out,
+ const char *address);
void (*close_output_stream)(struct audio_hw_device *dev,
struct audio_stream_out* stream_out);
@@ -580,7 +588,9 @@
audio_devices_t devices,
struct audio_config *config,
struct audio_stream_in **stream_in,
- audio_input_flags_t flags);
+ audio_input_flags_t flags,
+ const char *address,
+ audio_source_t source);
void (*close_input_stream)(struct audio_hw_device *dev,
struct audio_stream_in *stream_in);
diff --git a/include/hardware/bluetooth.h b/include/hardware/bluetooth.h
index 4d38ff7..74cd1fc 100644
--- a/include/hardware/bluetooth.h
+++ b/include/hardware/bluetooth.h
@@ -98,6 +98,15 @@
uint8_t pin[16];
} __attribute__((packed))bt_pin_code_t;
+typedef struct {
+ uint8_t status;
+ uint8_t ctrl_state; /* stack reported state */
+ uint64_t tx_time; /* in ms */
+ uint64_t rx_time; /* in ms */
+ uint64_t idle_time; /* in ms */
+ uint64_t energy_used; /* a product of mA, V and ms */
+} __attribute__((packed))bt_activity_energy_info;
+
/** Bluetooth Adapter Discovery state */
typedef enum {
BT_DISCOVERY_STOPPED,
@@ -139,7 +148,9 @@
uint8_t rpa_offload_supported;
uint8_t max_irk_list_size;
uint8_t max_adv_filter_supported;
- uint8_t scan_result_storage_size;
+ uint8_t scan_result_storage_size_lobyte;
+ uint8_t scan_result_storage_size_hibyte;
+ uint8_t activity_energy_info_supported;
}bt_local_le_features_t;
/* Bluetooth Adapter and Remote Device property types */
@@ -345,6 +356,15 @@
* This callback shall be invoked whenever the le_tx_test, le_rx_test or le_test_end is invoked
* The num_packets is valid only for le_test_end command */
typedef void (*le_test_mode_callback)(bt_status_t status, uint16_t num_packets);
+
+/** Callback invoked when energy details are obtained */
+/* Ctrl_state-Current controller state-Active-1,scan-2,or idle-3 state as defined by HCI spec.
+ * If the ctrl_state value is 0, it means the API call failed
+ * Time values-In milliseconds as returned by the controller
+ * Energy used-Value as returned by the controller
+ * Status-Provides the status of the read_energy_info API call */
+typedef void (*energy_info_callback)(bt_activity_energy_info *energy_info);
+
/** TODO: Add callbacks for Link Up/Down and other generic
* notifications/callbacks */
@@ -364,6 +384,7 @@
callback_thread_event thread_evt_cb;
dut_mode_recv_callback dut_mode_recv_cb;
le_test_mode_callback le_test_mode_cb;
+ energy_info_callback energy_info_cb;
} bt_callbacks_t;
typedef void (*alarm_cb)(void *data);
@@ -459,7 +480,7 @@
int (*cancel_discovery)(void);
/** Create Bluetooth Bonding */
- int (*create_bond)(const bt_bdaddr_t *bd_addr);
+ int (*create_bond)(const bt_bdaddr_t *bd_addr, int transport);
/** Remove Bond */
int (*remove_bond)(const bt_bdaddr_t *bd_addr);
@@ -507,6 +528,11 @@
* This should be called immediately after a successful |init|.
*/
int (*set_os_callouts)(bt_os_callouts_t *callouts);
+
+ /** Read Energy info details - return value indicates BT_STATUS_SUCCESS or BT_STATUS_NOT_READY
+ * Success indicates that the VSC command was sent to controller
+ */
+ int (*read_energy_info)();
} bt_interface_t;
/** TODO: Need to add APIs for Service Discovery, Service authorization and
diff --git a/include/hardware/bt_gatt_client.h b/include/hardware/bt_gatt_client.h
index 295f5c8..8073dd1 100644
--- a/include/hardware/bt_gatt_client.h
+++ b/include/hardware/bt_gatt_client.h
@@ -170,10 +170,6 @@
/** Callback invoked when a scan filter configuration command has completed */
typedef void (*scan_filter_status_callback)(int enable, int client_if, int status);
-/** Track ADV VSE callback invoked when tracked device is found or lost */
-typedef void (*track_adv_event_callback)(int client_if, int filt_index, int addr_type,
- bt_bdaddr_t* bda, int adv_state);
-
/** Callback invoked when multi-adv enable operation has completed */
typedef void (*multi_adv_enable_callback)(int client_if, int status);
@@ -205,6 +201,9 @@
/** Callback invoked when batchscan storage threshold limit is crossed */
typedef void (*batchscan_threshold_callback)(int client_if);
+/** Track ADV VSE callback invoked when tracked device is found or lost */
+typedef void (*track_adv_event_callback)(int client_if, int filt_index, int addr_type,
+ bt_bdaddr_t* bda, int adv_state);
typedef struct {
register_client_callback register_client_cb;
diff --git a/include/hardware/camera_common.h b/include/hardware/camera_common.h
index 0ee929e..322ed93 100644
--- a/include/hardware/camera_common.h
+++ b/include/hardware/camera_common.h
@@ -268,8 +268,29 @@
/**
* Common methods of the camera module. This *must* be the first member of
* camera_module as users of this structure will cast a hw_module_t to
- * camera_module pointer in contexts where it's known the hw_module_t references a
- * camera_module.
+ * camera_module pointer in contexts where it's known the hw_module_t
+ * references a camera_module.
+ *
+ * The return values for common.methods->open for camera_module are:
+ *
+ * 0: On a successful open of the camera device.
+ *
+ * -ENODEV: The camera device cannot be opened due to an internal
+ * error.
+ *
+ * -EINVAL: The input arguments are invalid, i.e. the id is invalid,
+ * and/or the module is invalid.
+ *
+ * -EBUSY: The camera device was already opened for this camera id
+ * (by using this method or open_legacy),
+ * regardless of the device HAL version it was opened as.
+ *
+ * -EUSERS: The maximal number of camera devices that can be
+ * opened concurrently were opened already, either by
+ * this method or the open_legacy method.
+ *
+ * All other return values from common.methods->open will be treated as
+ * -ENODEV.
*/
hw_module_t common;
@@ -293,6 +314,15 @@
* Return the static camera information for a given camera device. This
* information may not change for a camera device.
*
+ * Return values:
+ *
+ * 0: On a successful operation
+ *
+ * -ENODEV: The information cannot be provided due to an internal
+ * error.
+ *
+ * -EINVAL: The input arguments are invalid, i.e. the id is invalid,
+ * and/or the module is invalid.
*/
int (*get_camera_info)(int camera_id, struct camera_info *info);
@@ -315,6 +345,15 @@
*
* Valid to be called by the framework.
*
+ * Return values:
+ *
+ * 0: On a successful operation
+ *
+ * -ENODEV: The operation cannot be completed due to an internal
+ * error.
+ *
+ * -EINVAL: The input arguments are invalid, i.e. the callbacks are
+ * null
*/
int (*set_callbacks)(const camera_module_callbacks_t *callbacks);
diff --git a/include/hardware/gps.h b/include/hardware/gps.h
index 5747faa..eb44d5c 100644
--- a/include/hardware/gps.h
+++ b/include/hardware/gps.h
@@ -110,6 +110,10 @@
#define GPS_CAPABILITY_ON_DEMAND_TIME 0x0000010
/** GPS supports Geofencing */
#define GPS_CAPABILITY_GEOFENCING 0x0000020
+/** GPS supports Measurements */
+#define GPS_CAPABILITY_MEASUREMENTS 0x0000040
+/** GPS supports Navigation Messages */
+#define GPS_CAPABILITY_NAV_MESSAGES 0x0000080
/** Flags used to specify which aiding data to delete
when calling delete_aiding_data(). */
@@ -1690,7 +1694,7 @@
/**
* The length of the data (in bytes) contained in the current message.
* If this value is different from zero, 'data' must point to an array of the same size.
- * i.e. for L1 C/A the size of the sub-frame will be 40 bytes (10 words).
+ * e.g. for L1 C/A the size of the sub-frame will be 40 bytes (10 words, 30 bits/word).
*
* This is a Mandatory value.
*/
@@ -1699,6 +1703,9 @@
/**
* The data of the reported GPS message.
* The bytes (or words) specified using big endian format (MSB first).
+ *
+ * For L1 C/A, each subframe contains 10 30-bit GPS words. Each GPS word (30 bits) should be
+ * fitted into the last 30 bits in a 4-byte word (skip B31 and B32), with MSB first.
*/
uint8_t* data;
diff --git a/include/hardware/gralloc.h b/include/hardware/gralloc.h
index e7d0103..91e2f69 100644
--- a/include/hardware/gralloc.h
+++ b/include/hardware/gralloc.h
@@ -124,6 +124,9 @@
*/
GRALLOC_USAGE_PROTECTED = 0x00004000,
+ /* buffer may be used as a cursor */
+ GRALLOC_USAGE_CURSOR = 0x00008000,
+
/* implementation-specific private usage flags */
GRALLOC_USAGE_PRIVATE_0 = 0x10000000,
GRALLOC_USAGE_PRIVATE_1 = 0x20000000,
diff --git a/include/hardware/hdmi_cec.h b/include/hardware/hdmi_cec.h
index 646dc45..95c0c4e 100644
--- a/include/hardware/hdmi_cec.h
+++ b/include/hardware/hdmi_cec.h
@@ -339,7 +339,7 @@
* some reason. HAL implementation should take the situation into account
* so as not to wait forever for the message to get sent out.
*
- * It should not try retransmission because it's handled by upper layer.
+ * It should try retransmission at least once as specified in the standard.
*
* Returns error code. See HDMI_RESULT_SUCCESS, HDMI_RESULT_NACK, and
* HDMI_RESULT_BUSY.
diff --git a/include/hardware/hwcomposer.h b/include/hardware/hwcomposer.h
index af04181..3dfb4fd 100644
--- a/include/hardware/hwcomposer.h
+++ b/include/hardware/hwcomposer.h
@@ -141,6 +141,13 @@
* as a solid color since the platform is not currently able to composite
* sideband layers with the GPU. This may be improved in future
* versions of the platform.
+ *
+ *
+ * HWC_CURSOR_OVERLAY
+ * Set by the HWC implementation during (*prepare)(), this value
+ * indicates the layer's composition will now be handled by the HWC.
+ * Additionally, the client can now asynchronously update the on-screen
+ * position of this layer using the setCursorPositionAsync() api.
*/
int32_t compositionType;
@@ -505,11 +512,12 @@
* (*prepare)() can be called more than once, the last call prevails.
*
* The HWC responds by setting the compositionType field in each layer to
- * either HWC_FRAMEBUFFER or HWC_OVERLAY. In the former case, the
- * composition for the layer is handled by SurfaceFlinger with OpenGL ES,
- * in the later case, the HWC will have to handle the layer's composition.
- * compositionType and hints are preserved between (*prepare)() calles
- * unless the HWC_GEOMETRY_CHANGED flag is set.
+ * either HWC_FRAMEBUFFER, HWC_OVERLAY, or HWC_CURSOR_OVERLAY. For the
+ * HWC_FRAMEBUFFER type, composition for the layer is handled by
+ * SurfaceFlinger with OpenGL ES. For the latter two overlay types,
+ * the HWC will have to handle the layer's composition. compositionType
+ * and hints are preserved between (*prepare)() calles unless the
+ * HWC_GEOMETRY_CHANGED flag is set.
*
* (*prepare)() is called with HWC_GEOMETRY_CHANGED to indicate that the
* list's geometry has changed, that is, when more than just the buffer's
@@ -751,11 +759,37 @@
*/
int (*setActiveConfig)(struct hwc_composer_device_1* dev, int disp,
int index);
+ /*
+ * Asynchronously update the location of the cursor layer.
+ *
+ * Within the standard prepare()/set() composition loop, the client
+ * (surfaceflinger) can request that a given layer uses dedicated cursor
+ * composition hardware by specifiying the HWC_IS_CURSOR_LAYER flag. Only
+ * one layer per display can have this flag set. If the layer is suitable
+ * for the platform's cursor hardware, hwcomposer will return from prepare()
+ * a composition type of HWC_CURSOR_OVERLAY for that layer. This indicates
+ * not only that the client is not responsible for compositing that layer,
+ * but also that the client can continue to update the position of that layer
+ * after a call to set(). This can reduce the visible latency of mouse
+ * movement to visible, on-screen cursor updates. Calls to
+ * setCursorPositionAsync() may be made from a different thread doing the
+ * prepare()/set() composition loop, but care must be taken to not interleave
+ * calls of setCursorPositionAsync() between calls of set()/prepare().
+ *
+ * Notes:
+ * - Only one layer per display can be specified as a cursor layer with
+ * HWC_IS_CURSOR_LAYER.
+ * - hwcomposer will only return one layer per display as HWC_CURSOR_OVERLAY
+ * - This returns 0 on success or -errno on error.
+ * - This field is optional for HWC_DEVICE_API_VERSION_1_4 and later. It
+ * should be null for previous versions.
+ */
+ int (*setCursorPositionAsync)(struct hwc_composer_device_1 *dev, int disp, int x_pos, int y_pos);
/*
* Reserved for future use. Must be NULL.
*/
- void* reserved_proc[2];
+ void* reserved_proc[1];
} hwc_composer_device_1_t;
diff --git a/include/hardware/hwcomposer_defs.h b/include/hardware/hwcomposer_defs.h
index d24bc9d..9a52436 100644
--- a/include/hardware/hwcomposer_defs.h
+++ b/include/hardware/hwcomposer_defs.h
@@ -77,6 +77,16 @@
* by SurfaceFlinger (just as if compositionType was set to HWC_OVERLAY).
*/
HWC_SKIP_LAYER = 0x00000001,
+
+ /*
+ * HWC_IS_CURSOR_LAYER is set by surfaceflinger to indicate that this
+ * layer is being used as a cursor on this particular display, and that
+ * surfaceflinger can potentially perform asynchronous position updates for
+ * this layer. If a call to prepare() returns HWC_CURSOR_OVERLAY for the
+ * composition type of this layer, then the hwcomposer will allow async
+ * position updates to this layer via setCursorPositionAsync().
+ */
+ HWC_IS_CURSOR_LAYER = 0x00000002
};
/*
@@ -100,8 +110,13 @@
/* this layer's contents are taken from a sideband buffer stream.
* Added in HWC_DEVICE_API_VERSION_1_4. */
HWC_SIDEBAND = 4,
-};
+ /* this layer's composition will be handled by hwcomposer by dedicated
+ cursor overlay hardware. hwcomposer will also all async position updates
+ of this layer outside of the normal prepare()/set() loop. Added in
+ HWC_DEVICE_API_VERSION_1_4. */
+ HWC_CURSOR_OVERLAY = 5
+ };
/*
* hwc_layer_t::blending values
*/
diff --git a/include/hardware/mcu.h b/include/hardware/mcu.h
deleted file mode 100644
index 6fe2cfe..0000000
--- a/include/hardware/mcu.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_INCLUDE_HARDWARE_MCU_H
-#define ANDROID_INCLUDE_HARDWARE_MCU_H
-
-#include <stdint.h>
-#include <sys/cdefs.h>
-#include <sys/types.h>
-
-#include <hardware/hardware.h>
-
-__BEGIN_DECLS
-
-#define MCU_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1)
-
-/*
- * The id of this module
- */
-#define MCU_HARDWARE_MODULE_ID "mcu"
-
-/*
- * MCU message keys passed to (*sendMessage)
- */
-#define MCU_PARAMETER_MSG_ENABLE_MCU "enable_mcu"
-
-/*
- * MCU message values passed to (*sendMessage)
- */
-#define MCU_PARAMETER_ARG_ON "on"
-#define MCU_PARAMETER_ARG_OFF "off"
-
-/*
- * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
- * and the fields of this data structure must begin with hw_module_t
- * followed by module specific information.
- */
-typedef struct mcu_module {
- struct hw_module_t common;
-
- /*
- * (*init)() performs MCU module setup actions at runtime startup, such
- * as to initialize an external MCU. This is called only by the MCU HAL
- * instance loaded by PowerManagerService.
- *
- * Returns 0 on success or -errno on error.
- */
- int (*init)(struct mcu_module *module);
-
- /*
- * (*sendMessage)() passes a message/argument pair to the MCU to execute
- * a function. msg is NULL-terminated. If arg is text, then arg_len must
- * reflect the string length. result is a heap-allocated buffer that the
- * caller must free. If there is no result, then *result will be NULL and
- * *result_len will be 0.
- *
- * Returns 0 on success or -errno in case of error (for example, if the
- * MCU does not support the specified message.)
- *
- */
- int (*sendMessage)(struct mcu_module *module, const char *msg,
- const void *arg, size_t arg_len, void **result,
- size_t *result_len);
-
-} mcu_module_t;
-
-__END_DECLS
-
-#endif // ANDROID_INCLUDE_HARDWARE_MCU_H
diff --git a/include/hardware/nfc.h b/include/hardware/nfc.h
index 0a8ed72..58d33d9 100644
--- a/include/hardware/nfc.h
+++ b/include/hardware/nfc.h
@@ -53,6 +53,7 @@
* 9) Core NCI stack calls close()
*/
#define NFC_NCI_HARDWARE_MODULE_ID "nfc_nci"
+#define NFC_NCI_BCM2079X_HARDWARE_MODULE_ID "nfc_nci.bcm2079x"
#define NFC_NCI_CONTROLLER "nci"
/*
diff --git a/include/hardware/sensors.h b/include/hardware/sensors.h
index ec68b2b..339508a 100644
--- a/include/hardware/sensors.h
+++ b/include/hardware/sensors.h
@@ -205,13 +205,39 @@
#define SENSOR_TYPE_META_DATA (0)
/*
+ * Wake up sensors.
+ * Each sensor may have either or both a wake-up and a non-wake variant.
+ * When registered in batch mode, wake-up sensors will wake up the AP when
+ * their FIFOs are full or when the batch timeout expires. A separate FIFO has
+ * to be maintained for wake up sensors and non wake up sensors. The non wake-up
+ * sensors need to overwrite their FIFOs when they are full till the AP wakes up
+ * and the wake-up sensors will wake-up the AP when their FIFOs are full or when
+ * the batch timeout expires without losing events. Wake-up and non wake-up variants
+ * of each sensor can be activated at different rates independently of each other.
+ *
+ * Note: Proximity sensor and significant motion sensor which were defined in previous
+ * releases are also wake-up sensors and should be treated as such. Wake-up one-shot
+ * sensors like SIGNIFICANT_MOTION cannot be batched, hence the text about batch above
+ * doesn't apply to them. See the definitions of SENSOR_TYPE_PROXIMITY and
+ * SENSOR_TYPE_SIGNIFICANT_MOTION for more info.
+ *
+ * Set SENSOR_FLAG_WAKE_UP flag for all wake-up sensors.
+ *
+ * For example, A device can have two sensors both of SENSOR_TYPE_ACCELEROMETER and
+ * one of them can be a wake_up sensor (with SENSOR_FLAG_WAKE_UP flag set) and the other
+ * can be a regular non wake_up sensor. Both of these sensors must be activated/deactivated
+ * independently of the other.
+ */
+
+/*
* SENSOR_TYPE_ACCELEROMETER
* reporting-mode: continuous
- * wake-up sensor: no
*
* All values are in SI units (m/s^2) and measure the acceleration of the
* device minus the force of gravity.
*
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
*/
#define SENSOR_TYPE_ACCELEROMETER (1)
#define SENSOR_STRING_TYPE_ACCELEROMETER "android.sensor.accelerometer"
@@ -219,11 +245,12 @@
/*
* SENSOR_TYPE_GEOMAGNETIC_FIELD
* reporting-mode: continuous
- * wake-up sensor: no
*
* All values are in micro-Tesla (uT) and measure the geomagnetic
* field in the X, Y and Z axis.
*
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
*/
#define SENSOR_TYPE_GEOMAGNETIC_FIELD (2)
#define SENSOR_TYPE_MAGNETIC_FIELD SENSOR_TYPE_GEOMAGNETIC_FIELD
@@ -232,12 +259,14 @@
/*
* SENSOR_TYPE_ORIENTATION
* reporting-mode: continuous
- * wake-up sensor: no
*
* All values are angles in degrees.
*
* Orientation sensors return sensor events for all 3 axes at a constant
* rate defined by setDelay().
+ *
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
*/
#define SENSOR_TYPE_ORIENTATION (3)
#define SENSOR_STRING_TYPE_ORIENTATION "android.sensor.orientation"
@@ -245,10 +274,12 @@
/*
* SENSOR_TYPE_GYROSCOPE
* reporting-mode: continuous
- * wake-up sensor: no
*
* All values are in radians/second and measure the rate of rotation
* around the X, Y and Z axis.
+ *
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
*/
#define SENSOR_TYPE_GYROSCOPE (4)
#define SENSOR_STRING_TYPE_GYROSCOPE "android.sensor.gyroscope"
@@ -256,9 +287,10 @@
/*
* SENSOR_TYPE_LIGHT
* reporting-mode: on-change
- * wake-up sensor: no
*
* The light sensor value is returned in SI lux units.
+ *
+ * Both wake-up and non wake-up versions are useful.
*/
#define SENSOR_TYPE_LIGHT (5)
#define SENSOR_STRING_TYPE_LIGHT "android.sensor.light"
@@ -266,9 +298,11 @@
/*
* SENSOR_TYPE_PRESSURE
* reporting-mode: continuous
- * wake-up sensor: no
*
* The pressure sensor return the athmospheric pressure in hectopascal (hPa)
+ *
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
*/
#define SENSOR_TYPE_PRESSURE (6)
#define SENSOR_STRING_TYPE_PRESSURE "android.sensor.pressure"
@@ -280,8 +314,11 @@
/*
* SENSOR_TYPE_PROXIMITY
* reporting-mode: on-change
- * wake-up sensor: yes (set SENSOR_FLAG_WAKE_UP flag)
*
+ * The proximity sensor which turns the screen off and back on during calls is the
+ * wake-up proximity sensor. Implement wake-up proximity sensor before implementing
+ * a non wake-up proximity sensor. For the wake-up proximity sensor set the flag
+ * SENSOR_FLAG_WAKE_UP.
* The value corresponds to the distance to the nearest object in centimeters.
*/
#define SENSOR_TYPE_PROXIMITY (8)
@@ -290,10 +327,12 @@
/*
* SENSOR_TYPE_GRAVITY
* reporting-mode: continuous
- * wake-up sensor: no
*
* A gravity output indicates the direction of and magnitude of gravity in
* the devices's coordinates.
+ *
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
*/
#define SENSOR_TYPE_GRAVITY (9)
#define SENSOR_STRING_TYPE_GRAVITY "android.sensor.gravity"
@@ -301,10 +340,12 @@
/*
* SENSOR_TYPE_LINEAR_ACCELERATION
* reporting-mode: continuous
- * wake-up sensor: no
*
* Indicates the linear acceleration of the device in device coordinates,
* not including gravity.
+ *
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
*/
#define SENSOR_TYPE_LINEAR_ACCELERATION (10)
#define SENSOR_STRING_TYPE_LINEAR_ACCELERATION "android.sensor.linear_acceleration"
@@ -313,10 +354,12 @@
/*
* SENSOR_TYPE_ROTATION_VECTOR
* reporting-mode: continuous
- * wake-up sensor: no
*
* The rotation vector symbolizes the orientation of the device relative to the
* East-North-Up coordinates frame.
+ *
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
*/
#define SENSOR_TYPE_ROTATION_VECTOR (11)
#define SENSOR_STRING_TYPE_ROTATION_VECTOR "android.sensor.rotation_vector"
@@ -324,10 +367,11 @@
/*
* SENSOR_TYPE_RELATIVE_HUMIDITY
* reporting-mode: on-change
- * wake-up sensor: no
*
* A relative humidity sensor measures relative ambient air humidity and
* returns a value in percent.
+ *
+ * Both wake-up and non wake-up versions are useful.
*/
#define SENSOR_TYPE_RELATIVE_HUMIDITY (12)
#define SENSOR_STRING_TYPE_RELATIVE_HUMIDITY "android.sensor.relative_humidity"
@@ -335,9 +379,10 @@
/*
* SENSOR_TYPE_AMBIENT_TEMPERATURE
* reporting-mode: on-change
- * wake-up sensor: no
*
* The ambient (room) temperature in degree Celsius.
+ *
+ * Both wake-up and non wake-up versions are useful.
*/
#define SENSOR_TYPE_AMBIENT_TEMPERATURE (13)
#define SENSOR_STRING_TYPE_AMBIENT_TEMPERATURE "android.sensor.ambient_temperature"
@@ -345,10 +390,12 @@
/*
* SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED
* reporting-mode: continuous
- * wake-up sensor: no
*
* Similar to SENSOR_TYPE_MAGNETIC_FIELD, but the hard iron calibration is
* reported separately instead of being included in the measurement.
+ *
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
*/
#define SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED (14)
#define SENSOR_STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED "android.sensor.magnetic_field_uncalibrated"
@@ -356,10 +403,12 @@
/*
* SENSOR_TYPE_GAME_ROTATION_VECTOR
* reporting-mode: continuous
- * wake-up sensor: no
*
* Similar to SENSOR_TYPE_ROTATION_VECTOR, but not using the geomagnetic
* field.
+ *
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
*/
#define SENSOR_TYPE_GAME_ROTATION_VECTOR (15)
#define SENSOR_STRING_TYPE_GAME_ROTATION_VECTOR "android.sensor.game_rotation_vector"
@@ -367,10 +416,12 @@
/*
* SENSOR_TYPE_GYROSCOPE_UNCALIBRATED
* reporting-mode: continuous
- * wake-up sensor: no
*
* All values are in radians/second and measure the rate of rotation
* around the X, Y and Z axis.
+ *
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
*/
#define SENSOR_TYPE_GYROSCOPE_UNCALIBRATED (16)
#define SENSOR_STRING_TYPE_GYROSCOPE_UNCALIBRATED "android.sensor.gyroscope_uncalibrated"
@@ -378,10 +429,12 @@
/*
* SENSOR_TYPE_SIGNIFICANT_MOTION
* reporting-mode: one-shot
- * wake-up sensor: yes (set SENSOR_FLAG_WAKE_UP flag)
*
* A sensor of this type triggers an event each time significant motion
* is detected and automatically disables itself.
+ * For Significant Motion sensor to be useful, it must be defined as a
+ * wake-up sensor. (set SENSOR_FLAG_WAKE_UP). Implement the wake-up significant motion
+ * sensor. A non wake-up version is not useful.
* The only allowed value to return is 1.0.
*/
@@ -391,11 +444,12 @@
/*
* SENSOR_TYPE_STEP_DETECTOR
* reporting-mode: special
- * wake-up sensor: no
*
* A sensor of this type triggers an event each time a step is taken
* by the user. The only allowed value to return is 1.0 and an event
* is generated for each step.
+ *
+ * Both wake-up and non wake-up versions are useful.
*/
#define SENSOR_TYPE_STEP_DETECTOR (18)
@@ -405,11 +459,13 @@
/*
* SENSOR_TYPE_STEP_COUNTER
* reporting-mode: on-change
- * wake-up sensor: no
*
* A sensor of this type returns the number of steps taken by the user since
* the last reboot while activated. The value is returned as a uint64_t and is
* reset to zero only on a system / android reboot.
+ *
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
*/
#define SENSOR_TYPE_STEP_COUNTER (19)
@@ -418,10 +474,12 @@
/*
* SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR
* reporting-mode: continuous
- * wake-up sensor: no
*
* Similar to SENSOR_TYPE_ROTATION_VECTOR, but using a magnetometer instead
* of using a gyroscope.
+ *
+ * Implement the non-wake-up version of this sensor and implement the wake-up
+ * version if the system possesses a wake up fifo.
*/
#define SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR (20)
#define SENSOR_STRING_TYPE_GEOMAGNETIC_ROTATION_VECTOR "android.sensor.geomagnetic_rotation_vector"
@@ -429,7 +487,6 @@
/*
* SENSOR_TYPE_HEART_RATE
* reporting-mode: on-change
- * wake-up sensor: no
*
* A sensor of this type returns the current heart rate.
* The events contain the current heart rate in beats per minute (BPM) and the
@@ -443,96 +500,15 @@
* mode for more information.
*
* sensor_t.requiredPermission must be set to SENSOR_PERMISSION_BODY_SENSORS.
+ *
+ * Both wake-up and non wake-up versions are useful.
*/
#define SENSOR_TYPE_HEART_RATE (21)
#define SENSOR_STRING_TYPE_HEART_RATE "android.sensor.heart_rate"
/*
- * SENSOR_TYPE_NON_WAKE_UP_PROXIMITY_SENSOR
- * Same as proximity_sensor but does not wake up the AP from suspend mode.
- * wake-up sensor: no
- */
-#define SENSOR_TYPE_NON_WAKE_UP_PROXIMITY_SENSOR (22)
-#define SENSOR_STRING_TYPE_NON_WAKE_UP_PROXIMITY_SENSOR "android.sensor.non_wake_up_proximity_sensor"
-
-/*
- * The sensors below are wake_up variants of the base sensor types defined
- * above. When registered in batch mode, these sensors will wake up the AP when
- * their FIFOs are full or when the batch timeout expires. A separate FIFO has
- * to be maintained for wake up sensors and non wake up sensors. The non wake-up
- * sensors need to overwrite their FIFOs when they are full till the AP wakes up
- * and the wake-up sensors will wake-up the AP when their FIFOs are full or when
- * the batch timeout expires without losing events.
- * Note: Sensors of type SENSOR_TYPE_PROXIMITY are also wake up sensors and
- * should be treated as such. Wake-up one-shot sensors like SIGNIFICANT_MOTION
- * cannot be batched, hence the text about batch above doesn't apply to them.
- *
- * Define these sensors only if:
- * 1) batching is supported.
- * 2) wake-up and non wake-up variants of each sensor can be activated at
- * different rates.
- *
- * wake-up sensor: yes
- * Set SENSOR_FLAG_WAKE_UP flag for all these sensors.
- */
-#define SENSOR_TYPE_WAKE_UP_ACCELEROMETER (23)
-#define SENSOR_STRING_TYPE_WAKE_UP_ACCELEROMETER "android.sensor.wake_up_accelerometer"
-
-#define SENSOR_TYPE_WAKE_UP_MAGNETIC_FIELD (24)
-#define SENSOR_STRING_TYPE_WAKE_UP_MAGNETIC_FIELD "android.sensor.wake_up_magnetic_field"
-
-#define SENSOR_TYPE_WAKE_UP_ORIENTATION (25)
-#define SENSOR_STRING_TYPE_WAKE_UP_ORIENTATION "android.sensor.wake_up_orientation"
-
-#define SENSOR_TYPE_WAKE_UP_GYROSCOPE (26)
-#define SENSOR_STRING_TYPE_WAKE_UP_GYROSCOPE "android.sensor.wake_up_gyroscope"
-
-#define SENSOR_TYPE_WAKE_UP_LIGHT (27)
-#define SENSOR_STRING_TYPE_WAKE_UP_LIGHT "android.sensor.wake_up_light"
-
-#define SENSOR_TYPE_WAKE_UP_PRESSURE (28)
-#define SENSOR_STRING_TYPE_WAKE_UP_PRESSURE "android.sensor.wake_up_pressure"
-
-#define SENSOR_TYPE_WAKE_UP_GRAVITY (29)
-#define SENSOR_STRING_TYPE_WAKE_UP_GRAVITY "android.sensor.wake_up_gravity"
-
-#define SENSOR_TYPE_WAKE_UP_LINEAR_ACCELERATION (30)
-#define SENSOR_STRING_TYPE_WAKE_UP_LINEAR_ACCELERATION "android.sensor.wake_up_linear_acceleration"
-
-#define SENSOR_TYPE_WAKE_UP_ROTATION_VECTOR (31)
-#define SENSOR_STRING_TYPE_WAKE_UP_ROTATION_VECTOR "android.sensor.wake_up_rotation_vector"
-
-#define SENSOR_TYPE_WAKE_UP_RELATIVE_HUMIDITY (32)
-#define SENSOR_STRING_TYPE_WAKE_UP_RELATIVE_HUMIDITY "android.sensor.wake_up_relative_humidity"
-
-#define SENSOR_TYPE_WAKE_UP_AMBIENT_TEMPERATURE (33)
-#define SENSOR_STRING_TYPE_WAKE_UP_AMBIENT_TEMPERATURE "android.sensor.wake_up_ambient_temperature"
-
-#define SENSOR_TYPE_WAKE_UP_MAGNETIC_FIELD_UNCALIBRATED (34)
-#define SENSOR_STRING_TYPE_WAKE_UP_MAGNETIC_FIELD_UNCALIBRATED "android.sensor.wake_up_magnetic_field_uncalibrated"
-
-#define SENSOR_TYPE_WAKE_UP_GAME_ROTATION_VECTOR (35)
-#define SENSOR_STRING_TYPE_WAKE_UP_GAME_ROTATION_VECTOR "android.sensor.wake_up_game_rotation_vector"
-
-#define SENSOR_TYPE_WAKE_UP_GYROSCOPE_UNCALIBRATED (36)
-#define SENSOR_STRING_TYPE_WAKE_UP_GYROSCOPE_UNCALIBRATED "android.sensor.wake_up_gyroscope_uncalibrated"
-
-#define SENSOR_TYPE_WAKE_UP_STEP_DETECTOR (37)
-#define SENSOR_STRING_TYPE_WAKE_UP_STEP_DETECTOR "android.sensor.wake_up_step_detector"
-
-#define SENSOR_TYPE_WAKE_UP_STEP_COUNTER (38)
-#define SENSOR_STRING_TYPE_WAKE_UP_STEP_COUNTER "android.sensor.wake_up_step_counter"
-
-#define SENSOR_TYPE_WAKE_UP_GEOMAGNETIC_ROTATION_VECTOR (39)
-#define SENSOR_STRING_TYPE_WAKE_UP_GEOMAGNETIC_ROTATION_VECTOR "android.sensor.wake_up_geomagnetic_rotation_vector"
-
-#define SENSOR_TYPE_WAKE_UP_HEART_RATE (40)
-#define SENSOR_STRING_TYPE_WAKE_UP_HEART_RATE "android.sensor.wake_up_heart_rate"
-
-/*
* SENSOR_TYPE_WAKE_UP_TILT_DETECTOR
* reporting-mode: special (setDelay has no impact)
- * wake-up sensor: yes (set SENSOR_FLAG_WAKE_UP flag)
*
* A sensor of this type generates an event each time a tilt event is detected. A tilt event
* should be generated if the direction of the 2-seconds window average gravity changed by at least
@@ -552,14 +528,15 @@
* sensor that should allow the AP to go into suspend mode. Do not emulate this sensor in the HAL.
* Like other wake up sensors, the driver is expected to a hold a wake_lock with a timeout of 200 ms
* while reporting this event. The only allowed return value is 1.0.
+ *
+ * Implement only the wake-up version of this sensor.
*/
-#define SENSOR_TYPE_WAKE_UP_TILT_DETECTOR (41)
-#define SENSOR_STRING_TYPE_WAKE_UP_TILT_DETECTOR "android.sensor.wake_up_tilt_detector"
+#define SENSOR_TYPE_TILT_DETECTOR (22)
+#define SENSOR_STRING_TYPE_TILT_DETECTOR "android.sensor.tilt_detector"
/*
* SENSOR_TYPE_WAKE_GESTURE
* reporting-mode: one-shot
- * wake-up sensor: yes (set SENSOR_FLAG_WAKE_UP flag)
*
* A sensor enabling waking up the device based on a device specific motion.
*
@@ -573,14 +550,15 @@
* the manufacturer of the device.
* This sensor must be low power, as it is likely to be activated 24/7.
* The only allowed value to return is 1.0.
+ *
+ * Implement only the wake-up version of this sensor.
*/
-#define SENSOR_TYPE_WAKE_GESTURE (42)
+#define SENSOR_TYPE_WAKE_GESTURE (23)
#define SENSOR_STRING_TYPE_WAKE_GESTURE "android.sensor.wake_gesture"
/*
* SENSOR_TYPE_GLANCE_GESTURE
* reporting-mode: one-shot
- * wake-up sensor: yes (set SENSOR_FLAG_WAKE_UP flag)
*
* A sensor enabling briefly turning the screen on to enable the user to
* glance content on screen based on a specific motion. The device should
@@ -598,20 +576,23 @@
* the manufacturer of the device.
* This sensor must be low power, as it is likely to be activated 24/7.
* The only allowed value to return is 1.0.
+ *
+ * Implement only the wake-up version of this sensor.
*/
-#define SENSOR_TYPE_GLANCE_GESTURE (43)
+#define SENSOR_TYPE_GLANCE_GESTURE (24)
#define SENSOR_STRING_TYPE_GLANCE_GESTURE "android.sensor.glance_gesture"
/**
* SENSOR_TYPE_PICK_UP_GESTURE
* reporting-mode: one-shot
- * wake-up sensor: yes (set SENSOR_FLAG_WAKE_UP flag)
*
* A sensor of this type triggers when the device is picked up regardless of wherever is was
* before (desk, pocket, bag). The only allowed return value is 1.0.
* This sensor de-activates itself immediately after it triggers.
+ *
+ * Implement only the wake-up version of this sensor.
*/
-#define SENSOR_TYPE_PICK_UP_GESTURE (43)
+#define SENSOR_TYPE_PICK_UP_GESTURE (25)
#define SENSOR_STRING_TYPE_PICK_UP_GESTURE "android.sensor.pick_up_gesture"
/**
diff --git a/modules/Android.mk b/modules/Android.mk
index c903eee..0725d3e 100644
--- a/modules/Android.mk
+++ b/modules/Android.mk
@@ -1,4 +1,4 @@
hardware_modules := gralloc hwcomposer audio nfc nfc-nci local_time \
power usbaudio audio_remote_submix camera consumerir sensors vibrator \
- mcu tv_input fingerprint
+ tv_input fingerprint
include $(call all-named-subdir-makefiles,$(hardware_modules))
diff --git a/modules/audio/audio_hw.c b/modules/audio/audio_hw.c
index ef070c1..18c0e59 100644
--- a/modules/audio/audio_hw.c
+++ b/modules/audio/audio_hw.c
@@ -218,7 +218,8 @@
audio_devices_t devices,
audio_output_flags_t flags,
struct audio_config *config,
- struct audio_stream_out **stream_out)
+ struct audio_stream_out **stream_out,
+ const char *address __unused)
{
struct stub_audio_device *ladev = (struct stub_audio_device *)dev;
struct stub_stream_out *out;
@@ -328,7 +329,9 @@
audio_devices_t devices,
struct audio_config *config,
struct audio_stream_in **stream_in,
- audio_input_flags_t flags __unused)
+ audio_input_flags_t flags __unused,
+ const char *address __unused,
+ audio_source_t source __unused)
{
struct stub_audio_device *ladev = (struct stub_audio_device *)dev;
struct stub_stream_in *in;
diff --git a/modules/audio_remote_submix/audio_hw.cpp b/modules/audio_remote_submix/audio_hw.cpp
index 9e824b1..014da8e 100644
--- a/modules/audio_remote_submix/audio_hw.cpp
+++ b/modules/audio_remote_submix/audio_hw.cpp
@@ -1188,7 +1188,8 @@
audio_devices_t devices,
audio_output_flags_t flags,
struct audio_config *config,
- struct audio_stream_out **stream_out)
+ struct audio_stream_out **stream_out,
+ const char *address __unused)
{
struct submix_audio_device * const rsxadev = audio_hw_device_get_submix_audio_device(dev);
ALOGV("adev_open_output_stream()");
@@ -1374,7 +1375,9 @@
audio_devices_t devices,
struct audio_config *config,
struct audio_stream_in **stream_in,
- audio_input_flags_t flags __unused)
+ audio_input_flags_t flags __unused,
+ const char *address __unused,
+ audio_source_t source __unused)
{
struct submix_audio_device *rsxadev = audio_hw_device_get_submix_audio_device(dev);
struct submix_stream_in *in;
diff --git a/modules/mcu/Android.mk b/modules/mcu/Android.mk
deleted file mode 100644
index ec40e3a..0000000
--- a/modules/mcu/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (C) 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := mcu.default
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SRC_FILES := mcu.c
-LOCAL_SHARED_LIBRARIES := liblog
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/modules/mcu/mcu.c b/modules/mcu/mcu.c
deleted file mode 100644
index 47300f9..0000000
--- a/modules/mcu/mcu.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#define LOG_TAG "Legacy MCU HAL"
-#include <utils/Log.h>
-
-#include <hardware/hardware.h>
-#include <hardware/mcu.h>
-
-static int mcu_init(struct mcu_module *module)
-{
- return 0;
-}
-
-static int mcu_send_message(struct mcu_module *module, const char *msg,
- const void *arg, size_t arg_len, void **result,
- size_t *result_len)
-{
- return 0;
-}
-
-static struct hw_module_methods_t mcu_module_methods = {
- .open = NULL,
-};
-
-struct mcu_module HAL_MODULE_INFO_SYM = {
- .common = {
- .tag = HARDWARE_MODULE_TAG,
- .module_api_version = MCU_MODULE_API_VERSION_0_1,
- .hal_api_version = HARDWARE_HAL_API_VERSION,
- .id = MCU_HARDWARE_MODULE_ID,
- .name = "Default MCU HAL",
- .author = "The Android Open Source Project",
- .methods = &mcu_module_methods,
- },
-
- .init = mcu_init,
- .sendMessage = mcu_send_message,
-};
diff --git a/modules/soundtrigger/sound_trigger_hw.c b/modules/soundtrigger/sound_trigger_hw.c
index b78a0d1..e7f9baf 100644
--- a/modules/soundtrigger/sound_trigger_hw.c
+++ b/modules/soundtrigger/sound_trigger_hw.c
@@ -38,6 +38,7 @@
false, // capture_transition
0, // max_buffer_ms
false, // concurrent_capture
+ false, // trigger_in_event
0 // power_consumption_mw
};
@@ -51,7 +52,6 @@
pthread_t callback_thread;
pthread_mutex_t lock;
pthread_cond_t cond;
-
};
@@ -78,9 +78,9 @@
event->common.status = RECOGNITION_STATUS_SUCCESS;
event->common.type = SOUND_MODEL_TYPE_KEYPHRASE;
event->common.model = stdev->model_handle;
- event->key_phrase_in_capture = false;
event->num_phrases = 1;
event->phrase_extras[0].recognition_modes = RECOGNITION_MODE_VOICE_TRIGGER;
+ event->phrase_extras[0].confidence_level = 100;
event->phrase_extras[0].num_levels = 1;
event->phrase_extras[0].levels[0].level = 100;
event->phrase_extras[0].levels[0].user_id = 0;
diff --git a/modules/usbaudio/Android.mk b/modules/usbaudio/Android.mk
index 89c498b..ec8a8c0 100644
--- a/modules/usbaudio/Android.mk
+++ b/modules/usbaudio/Android.mk
@@ -19,7 +19,11 @@
LOCAL_MODULE := audio.usb.default
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SRC_FILES := \
- audio_hw.c
+ audio_hw.c \
+ alsa_device_profile.c \
+ alsa_device_proxy.c \
+ logging.c \
+ format.c
LOCAL_C_INCLUDES += \
external/tinyalsa/include \
$(call include-path-for, audio-utils)
diff --git a/modules/usbaudio/alsa_device_profile.c b/modules/usbaudio/alsa_device_profile.c
new file mode 100644
index 0000000..f214eab
--- /dev/null
+++ b/modules/usbaudio/alsa_device_profile.c
@@ -0,0 +1,476 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "alsa_device_profile"
+/*#define LOG_NDEBUG 0*/
+/*#define LOG_PCM_PARAMS 0*/
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <log/log.h>
+
+#include "alsa_device_profile.h"
+#include "format.h"
+#include "logging.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+/*TODO - Evaluate if this value should/can be retrieved from a device-specific property */
+#define BUFF_DURATION_MS 5
+
+#define DEFAULT_PERIOD_SIZE 1024
+
+static const char * const format_string_map[] = {
+ "AUDIO_FORMAT_PCM_16_BIT", /* "PCM_FORMAT_S16_LE", */
+ "AUDIO_FORMAT_PCM_32_BIT", /* "PCM_FORMAT_S32_LE", */
+ "AUDIO_FORMAT_PCM_8_BIT", /* "PCM_FORMAT_S8", */
+ "AUDIO_FORMAT_PCM_8_24_BIT", /* "PCM_FORMAT_S24_LE", */
+ "AUDIO_FORMAT_PCM_24_BIT_PACKED"/* "PCM_FORMAT_S24_3LE" */
+};
+
+static const unsigned const format_byte_size_map[] = {
+ 2, /* PCM_FORMAT_S16_LE */
+ 4, /* PCM_FORMAT_S32_LE */
+ 1, /* PCM_FORMAT_S8 */
+ 4, /* PCM_FORMAT_S24_LE */
+ 3, /* PCM_FORMAT_S24_3LE */
+};
+
+extern int8_t const pcm_format_value_map[50];
+
+/* sort these highest -> lowest (to default to best quality) */
+static const unsigned std_sample_rates[] =
+ {48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000};
+
+void profile_init(alsa_device_profile* profile, int direction)
+{
+ profile->card = profile->device = -1;
+ profile->direction = direction;
+
+ /* Fill the attribute arrays with invalid values */
+ size_t index;
+ for (index = 0; index < ARRAY_SIZE(profile->formats); index++) {
+ profile->formats[index] = PCM_FORMAT_INVALID;
+ }
+
+ for (index = 0; index < ARRAY_SIZE(profile->sample_rates); index++) {
+ profile->sample_rates[index] = 0;
+ }
+
+ for (index = 0; index < ARRAY_SIZE(profile->channel_counts); index++) {
+ profile->channel_counts[index] = 0;
+ }
+
+ profile->min_period_size = profile->max_period_size = 0;
+ profile->min_channel_count = profile->max_channel_count = DEFAULT_CHANNEL_COUNT;
+
+ profile->is_valid = false;
+}
+
+bool profile_is_initialized(alsa_device_profile* profile)
+{
+ return profile->card >= 0 && profile->device >= 0;
+}
+
+bool profile_is_valid(alsa_device_profile* profile) {
+ return profile->is_valid;
+}
+
+/*
+ * Returns the supplied value rounded up to the next even multiple of 16
+ */
+static unsigned int round_to_16_mult(unsigned int size)
+{
+ return (size + 15) & ~15; // 0xFFFFFFF0;
+}
+
+/*
+ * Returns the system defined minimum period size based on the supplied sample rate.
+ */
+unsigned profile_calc_min_period_size(alsa_device_profile* profile, unsigned sample_rate)
+{
+ ALOGV("profile_calc_min_period_size(%p, rate:%d)", profile, sample_rate);
+ if (profile == NULL) {
+ return DEFAULT_PERIOD_SIZE;
+ } else {
+ unsigned num_sample_frames = (sample_rate * BUFF_DURATION_MS) / 1000;
+ if (num_sample_frames < profile->min_period_size) {
+ num_sample_frames = profile->min_period_size;
+ }
+ return round_to_16_mult(num_sample_frames) * 2;
+ }
+}
+
+unsigned int profile_get_period_size(alsa_device_profile* profile, unsigned sample_rate)
+{
+ // return profile->default_config.period_size;
+ unsigned int period_size = profile_calc_min_period_size(profile, sample_rate);
+ ALOGV("profile_get_period_size(rate:%d) = %d", sample_rate, period_size);
+ return period_size;
+}
+
+/*
+ * Sample Rate
+ */
+unsigned profile_get_default_sample_rate(alsa_device_profile* profile)
+{
+ /*
+ * TODO this won't be right in general. we should store a preferred rate as we are scanning.
+ * But right now it will return the highest rate, which may be correct.
+ */
+ return profile_is_valid(profile) ? profile->sample_rates[0] : DEFAULT_SAMPLE_RATE;
+}
+
+bool profile_is_sample_rate_valid(alsa_device_profile* profile, unsigned rate)
+{
+ if (profile_is_valid(profile)) {
+ size_t index;
+ for (index = 0; profile->sample_rates[index] != 0; index++) {
+ if (profile->sample_rates[index] == rate) {
+ return true;
+ }
+ }
+
+ return false;
+ } else {
+ return rate == DEFAULT_SAMPLE_RATE;
+ }
+}
+
+/*
+ * Format
+ */
+enum pcm_format profile_get_default_format(alsa_device_profile* profile)
+{
+ /*
+ * TODO this won't be right in general. we should store a preferred format as we are scanning.
+ */
+ return profile_is_valid(profile) ? profile->formats[0] : DEFAULT_SAMPLE_FORMAT;
+}
+
+bool profile_is_format_valid(alsa_device_profile* profile, enum pcm_format fmt) {
+ if (profile_is_valid(profile)) {
+ size_t index;
+ for (index = 0; profile->formats[index] != PCM_FORMAT_INVALID; index++) {
+ if (profile->formats[index] == fmt) {
+ return true;
+ }
+ }
+
+ return false;
+ } else {
+ return fmt == DEFAULT_SAMPLE_FORMAT;
+ }
+}
+
+/*
+ * Channels
+ */
+unsigned profile_get_default_channel_count(alsa_device_profile* profile)
+{
+ return profile_is_valid(profile) ? profile->channel_counts[0] : DEFAULT_CHANNEL_COUNT;
+}
+
+bool profile_is_channel_count_valid(alsa_device_profile* profile, unsigned count)
+{
+ if (profile_is_initialized(profile)) {
+ return count >= profile->min_channel_count && count <= profile->max_channel_count;
+ } else {
+ return count == DEFAULT_CHANNEL_COUNT;
+ }
+}
+
+static bool profile_test_sample_rate(alsa_device_profile* profile, unsigned rate)
+{
+ struct pcm_config config = profile->default_config;
+ config.rate = rate;
+
+ bool works = false; /* let's be pessimistic */
+ struct pcm * pcm = pcm_open(profile->card, profile->device,
+ profile->direction, &config);
+
+ if (pcm != NULL) {
+ works = pcm_is_ready(pcm);
+ pcm_close(pcm);
+ }
+
+ return works;
+}
+
+static unsigned profile_enum_sample_rates(alsa_device_profile* profile, unsigned min, unsigned max)
+{
+ unsigned num_entries = 0;
+ unsigned index;
+
+ for (index = 0; index < ARRAY_SIZE(std_sample_rates) &&
+ num_entries < ARRAY_SIZE(profile->sample_rates) - 1;
+ index++) {
+ if (std_sample_rates[index] >= min && std_sample_rates[index] <= max
+ && profile_test_sample_rate(profile, std_sample_rates[index])) {
+ profile->sample_rates[num_entries++] = std_sample_rates[index];
+ }
+ }
+
+ return num_entries; /* return # of supported rates */
+}
+
+static unsigned profile_enum_sample_formats(alsa_device_profile* profile, struct pcm_mask * mask)
+{
+ const int num_slots = ARRAY_SIZE(mask->bits);
+ const int bits_per_slot = sizeof(mask->bits[0]) * 8;
+
+ const int table_size = ARRAY_SIZE(pcm_format_value_map);
+
+ int slot_index, bit_index, table_index;
+ table_index = 0;
+ int num_written = 0;
+ for (slot_index = 0; slot_index < num_slots && table_index < table_size;
+ slot_index++) {
+ unsigned bit_mask = 1;
+ for (bit_index = 0;
+ bit_index < bits_per_slot && table_index < table_size;
+ bit_index++) {
+ if ((mask->bits[slot_index] & bit_mask) != 0) {
+ enum pcm_format format = pcm_format_value_map[table_index];
+ /* Never return invalid (unrecognized) or 8-bit */
+ if (format != PCM_FORMAT_INVALID && format != PCM_FORMAT_S8) {
+ profile->formats[num_written++] = format;
+ if (num_written == ARRAY_SIZE(profile->formats) - 1) {
+ /* leave at least one PCM_FORMAT_INVALID at the end */
+ return num_written;
+ }
+ }
+ }
+ bit_mask <<= 1;
+ table_index++;
+ }
+ }
+
+ return num_written;
+}
+
+static unsigned profile_enum_channel_counts(alsa_device_profile* profile, unsigned min, unsigned max)
+{
+ static const unsigned std_channel_counts[] = {8, 4, 2, 1};
+
+ unsigned num_counts = 0;
+ unsigned index;
+ /* TODO write a profile_test_channel_count() */
+ /* Ensure there is at least one invalid channel count to terminate the channel counts array */
+ for (index = 0; index < ARRAY_SIZE(std_channel_counts) &&
+ num_counts < ARRAY_SIZE(profile->channel_counts) - 1;
+ index++) {
+ /* TODO Do we want a channel counts test? */
+ if (std_channel_counts[index] >= min && std_channel_counts[index] <= max /* &&
+ profile_test_channel_count(profile, std_channel_counts[index])*/) {
+ profile->channel_counts[num_counts++] = std_channel_counts[index];
+ }
+ }
+
+ return num_counts; /* return # of supported counts */
+}
+
+/*
+ * Reads and decodes configuration info from the specified ALSA card/device.
+ */
+static int read_alsa_device_config(alsa_device_profile * profile, struct pcm_config * config)
+{
+ ALOGV("usb:audio_hw - read_alsa_device_config(c:%d d:%d t:0x%X)",
+ profile->card, profile->device, profile->direction);
+
+ if (profile->card < 0 || profile->device < 0) {
+ return -EINVAL;
+ }
+
+ struct pcm_params * alsa_hw_params =
+ pcm_params_get(profile->card, profile->device, profile->direction);
+ if (alsa_hw_params == NULL) {
+ return -EINVAL;
+ }
+
+ profile->min_period_size = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_SIZE);
+ profile->max_period_size = pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_SIZE);
+
+ profile->min_channel_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
+ profile->max_channel_count = pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS);
+
+ int ret = 0;
+
+ /*
+ * This Logging will be useful when testing new USB devices.
+ */
+#ifdef LOG_PCM_PARAMS
+ log_pcm_params(alsa_hw_params);
+#endif
+
+ config->channels = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
+ config->rate = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE);
+ config->period_size = profile_calc_min_period_size(profile, config->rate);
+ config->period_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS);
+ config->format = get_pcm_format_for_mask(pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT));
+#ifdef LOG_PCM_PARAMS
+ log_pcm_config(config, "read_alsa_device_config");
+#endif
+ if (config->format == PCM_FORMAT_INVALID) {
+ ret = -EINVAL;
+ }
+
+ pcm_params_free(alsa_hw_params);
+
+ return ret;
+}
+
+bool profile_read_device_info(alsa_device_profile* profile)
+{
+ if (!profile_is_initialized(profile)) {
+ return false;
+ }
+
+ /* let's get some defaults */
+ read_alsa_device_config(profile, &profile->default_config);
+ ALOGV("default_config chans:%d rate:%d format:%d count:%d size:%d",
+ profile->default_config.channels, profile->default_config.rate,
+ profile->default_config.format, profile->default_config.period_count,
+ profile->default_config.period_size);
+
+ struct pcm_params * alsa_hw_params = pcm_params_get(profile->card,
+ profile->device,
+ profile->direction);
+ if (alsa_hw_params == NULL) {
+ return false;
+ }
+
+ /* Formats */
+ struct pcm_mask * format_mask = pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT);
+ profile_enum_sample_formats(profile, format_mask);
+
+ /* Channels */
+ profile_enum_channel_counts(
+ profile, pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS),
+ pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS));
+
+ /* Sample Rates */
+ profile_enum_sample_rates(
+ profile, pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE),
+ pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE));
+
+ profile->is_valid = true;
+
+ return true;
+}
+
+char * profile_get_sample_rate_strs(alsa_device_profile* profile)
+{
+ char buffer[128];
+ buffer[0] = '\0';
+ int buffSize = ARRAY_SIZE(buffer);
+
+ char numBuffer[32];
+
+ int numEntries = 0;
+ unsigned index;
+ for (index = 0; profile->sample_rates[index] != 0; index++) {
+ if (numEntries++ != 0) {
+ strncat(buffer, "|", buffSize);
+ }
+ snprintf(numBuffer, sizeof(numBuffer), "%u", profile->sample_rates[index]);
+ strncat(buffer, numBuffer, buffSize);
+ }
+
+ return strdup(buffer);
+}
+
+char * profile_get_format_strs(alsa_device_profile* profile)
+{
+ /* TODO remove this hack when we have support for input in non PCM16 formats */
+ if (profile->direction == PCM_IN) {
+ return strdup("AUDIO_FORMAT_PCM_16_BIT");
+ }
+
+ char buffer[128];
+ buffer[0] = '\0';
+ int buffSize = ARRAY_SIZE(buffer);
+
+ int numEntries = 0;
+ unsigned index = 0;
+ for (index = 0; profile->formats[index] != PCM_FORMAT_INVALID; index++) {
+ if (numEntries++ != 0) {
+ strncat(buffer, "|", buffSize);
+ }
+ strncat(buffer, format_string_map[profile->formats[index]], buffSize);
+ }
+
+ return strdup(buffer);
+}
+
+char * profile_get_channel_count_strs(alsa_device_profile* profile)
+{
+ static const char * const out_chans_strs[] = {
+ /* 0 */"AUDIO_CHANNEL_NONE", /* will never be taken as this is a terminator */
+ /* 1 */"AUDIO_CHANNEL_OUT_MONO",
+ /* 2 */"AUDIO_CHANNEL_OUT_STEREO",
+ /* 3 */ /* "AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_FRONT_CENTER" */ NULL,
+ /* 4 */"AUDIO_CHANNEL_OUT_QUAD",
+ /* 5 */ /* "AUDIO_CHANNEL_OUT_QUAD|AUDIO_CHANNEL_OUT_FRONT_CENTER" */ NULL,
+ /* 6 */"AUDIO_CHANNEL_OUT_5POINT1",
+ /* 7 */ /* "AUDIO_CHANNEL_OUT_5POINT1|AUDIO_CHANNEL_OUT_BACK_CENTER" */ NULL,
+ /* 8 */"AUDIO_CHANNEL_OUT_7POINT1",
+ /* channel counts greater than this not considered */
+ };
+
+ static const char * const in_chans_strs[] = {
+ /* 0 */"AUDIO_CHANNEL_NONE", /* will never be taken as this is a terminator */
+ /* 1 */"AUDIO_CHANNEL_IN_MONO",
+ /* 2 */"AUDIO_CHANNEL_IN_STEREO",
+ /* channel counts greater than this not considered */
+ };
+
+ const bool isOutProfile = profile->direction == PCM_OUT;
+ const char * const * const names_array = isOutProfile ? out_chans_strs : in_chans_strs;
+ const size_t names_size = isOutProfile ? ARRAY_SIZE(out_chans_strs)
+ : ARRAY_SIZE(in_chans_strs);
+
+ char buffer[256]; /* caution, may need to be expanded */
+ buffer[0] = '\0';
+ const int buffer_size = ARRAY_SIZE(buffer);
+ int num_entries = 0;
+ bool stereo_allowed = false;
+ unsigned index;
+ unsigned channel_count;
+
+ for (index = 0; (channel_count = profile->channel_counts[index]) != 0; index++) {
+ stereo_allowed = stereo_allowed || channel_count == 2;
+ if (channel_count < names_size && names_array[channel_count] != NULL) {
+ if (num_entries++ != 0) {
+ strncat(buffer, "|", buffer_size);
+ }
+ strncat(buffer, names_array[channel_count], buffer_size);
+ }
+ }
+ /* emulated modes:
+ * always expose stereo as we can emulate it for PCM_OUT
+ */
+ if (!stereo_allowed && isOutProfile) {
+ if (num_entries++ != 0) {
+ strncat(buffer, "|", buffer_size);
+ }
+ strncat(buffer, names_array[2], buffer_size); /* stereo */
+ }
+ return strdup(buffer);
+}
diff --git a/modules/usbaudio/alsa_device_profile.h b/modules/usbaudio/alsa_device_profile.h
new file mode 100644
index 0000000..b75e1dc
--- /dev/null
+++ b/modules/usbaudio/alsa_device_profile.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_ALSA_DEVICE_PROFILE_H
+#define ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_ALSA_DEVICE_PROFILE_H
+
+#include <stdbool.h>
+
+#include <tinyalsa/asoundlib.h>
+
+#define MAX_PROFILE_FORMATS 6 /* We long support the 5 standard formats defined
+ * in asound.h, so we just need this to be 1 more
+ * than that */
+#define MAX_PROFILE_SAMPLE_RATES 10 /* this number needs to be 1 more than the number of
+ * standard formats in std_sample_rates[]
+ * (in alsa_device_profile.c) */
+#define MAX_PROFILE_CHANNEL_COUNTS 5 /* this number need to be 1 more than the number of
+ * standard channel formats in std_channel_counts[]
+ * (in alsa_device_profile.c) */
+
+#define DEFAULT_SAMPLE_RATE 44100
+#define DEFAULT_SAMPLE_FORMAT PCM_FORMAT_S16_LE
+#define DEFAULT_CHANNEL_COUNT 2
+
+typedef struct {
+ int card;
+ int device;
+ int direction; /* PCM_OUT or PCM_IN */
+
+ enum pcm_format formats[MAX_PROFILE_FORMATS];
+
+ unsigned sample_rates[MAX_PROFILE_SAMPLE_RATES];
+
+ unsigned channel_counts[MAX_PROFILE_CHANNEL_COUNTS];
+
+ bool is_valid;
+
+ /* read from the hardware device */
+ struct pcm_config default_config;
+
+ unsigned min_period_size;
+ unsigned max_period_size;
+
+ unsigned min_channel_count;
+ unsigned max_channel_count;
+} alsa_device_profile;
+
+void profile_init(alsa_device_profile* profile, int direction);
+bool profile_is_initialized(alsa_device_profile* profile);
+bool profile_is_valid(alsa_device_profile* profile);
+
+bool profile_read_device_info(alsa_device_profile* profile);
+
+/* Audio Config Strings Methods */
+char * profile_get_sample_rate_strs(alsa_device_profile* profile);
+char * profile_get_format_strs(alsa_device_profile* profile);
+char * profile_get_channel_count_strs(alsa_device_profile* profile);
+
+/* Sample Rate Methods */
+unsigned profile_get_default_sample_rate(alsa_device_profile* profile);
+bool profile_is_sample_rate_valid(alsa_device_profile* profile, unsigned rate);
+
+/* Format Methods */
+enum pcm_format profile_get_default_format(alsa_device_profile* profile);
+bool profile_is_format_valid(alsa_device_profile* profile, enum pcm_format fmt);
+
+/* Channel Methods */
+unsigned profile_get_default_channel_count(alsa_device_profile* profile);
+bool profile_is_channel_count_valid(alsa_device_profile* profile, unsigned count);
+
+/* Utility */
+unsigned profile_calc_min_period_size(alsa_device_profile* profile, unsigned sample_rate);
+unsigned int profile_get_period_size(alsa_device_profile* profile, unsigned sample_rate);
+
+#endif /* ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_ALSA_DEVICE_PROFILE_H */
diff --git a/modules/usbaudio/alsa_device_proxy.c b/modules/usbaudio/alsa_device_proxy.c
new file mode 100644
index 0000000..b887d1d
--- /dev/null
+++ b/modules/usbaudio/alsa_device_proxy.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "alsa_device_proxy"
+/*#define LOG_NDEBUG 0*/
+/*#define LOG_PCM_PARAMS 0*/
+
+#include <log/log.h>
+
+#include "alsa_device_proxy.h"
+
+#include "logging.h"
+
+#define DEFAULT_PERIOD_SIZE 1024
+#define DEFAULT_PERIOD_COUNT 2
+
+//void proxy_init(alsa_device_proxy * proxy)
+//{
+// proxy->profile = NULL;
+//
+// proxy->alsa_config.format = DEFAULT_SAMPLE_FORMAT;
+// proxy->alsa_config.rate = DEFAULT_SAMPLE_RATE;
+// proxy->alsa_config.channels = DEFAULT_CHANNEL_COUNT;
+//
+// proxy->alsa_config.period_size = DEFAULT_PERIOD_SIZE;
+// proxy->alsa_config.period_count = DEFAULT_PERIOD_COUNT;
+//
+// proxy->pcm = NULL;
+//}
+
+void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile,
+ struct pcm_config * config)
+{
+ ALOGV("proxy_prepare()");
+
+ proxy->profile = profile;
+
+#if LOG_PCM_PARAMS
+ log_pcm_config(config, "proxy_setup()");
+#endif
+
+ proxy->alsa_config.format =
+ config->format != PCM_FORMAT_INVALID && profile_is_format_valid(profile, config->format)
+ ? config->format : profile->default_config.format;
+ proxy->alsa_config.rate =
+ config->rate != 0 && profile_is_sample_rate_valid(profile, config->rate)
+ ? config->rate : profile->default_config.rate;
+ proxy->alsa_config.channels =
+ config->channels != 0 && profile_is_channel_count_valid(profile, config->channels)
+ ? config->channels : profile->default_config.channels;
+
+ proxy->alsa_config.period_count = profile->default_config.period_count;
+ proxy->alsa_config.period_size =
+ profile_get_period_size(proxy->profile, proxy->alsa_config.rate);
+
+ proxy->pcm = NULL;
+}
+
+int proxy_open(alsa_device_proxy * proxy)
+{
+ alsa_device_profile* profile = proxy->profile;
+
+ ALOGV("proxy_open(card:%d device:%d %s)", profile->card, profile->device,
+ profile->direction == PCM_OUT ? "PCM_OUT" : "PCM_IN");
+
+ proxy->pcm = pcm_open(profile->card, profile->device, profile->direction, &proxy->alsa_config);
+ if (proxy->pcm == NULL) {
+ return -ENOMEM;
+ }
+
+ if (!pcm_is_ready(proxy->pcm)) {
+ ALOGE("[%s] proxy_open() pcm_open() failed: %s", LOG_TAG, pcm_get_error(proxy->pcm));
+#ifdef LOG_PCM_PARAMS
+ log_pcm_config(&proxy->alsa_config, "config");
+#endif
+ pcm_close(proxy->pcm);
+ proxy->pcm = NULL;
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void proxy_close(alsa_device_proxy * proxy)
+{
+ pcm_close(proxy->pcm);
+ proxy->pcm = NULL;
+}
+
+/*
+ * Sample Rate
+ */
+unsigned proxy_get_sample_rate(const alsa_device_proxy * proxy)
+{
+ return proxy->alsa_config.rate;
+}
+
+/*
+ * Format
+ */
+enum pcm_format proxy_get_format(const alsa_device_proxy * proxy)
+{
+ return proxy->alsa_config.format;
+}
+
+/*
+ * Channel Count
+ */
+unsigned proxy_get_channel_count(const alsa_device_proxy * proxy)
+{
+ return proxy->alsa_config.channels;
+}
+
+/*
+ * Other
+ */
+unsigned int proxy_get_period_size(const alsa_device_proxy * proxy)
+{
+ return proxy->alsa_config.period_size;
+}
+
+unsigned int proxy_get_period_count(const alsa_device_proxy * proxy)
+{
+ return proxy->alsa_config.period_count;
+}
+
+unsigned proxy_get_latency(const alsa_device_proxy * proxy)
+{
+ return (proxy_get_period_size(proxy) * proxy_get_period_count(proxy) * 1000)
+ / proxy_get_sample_rate(proxy);
+}
+
+/*
+ * I/O
+ */
+int proxy_write(const alsa_device_proxy * proxy, const void *data, unsigned int count)
+{
+ return pcm_write(proxy->pcm, data, count);
+}
+
+int proxy_read(const alsa_device_proxy * proxy, void *data, unsigned int count)
+{
+ return pcm_read(proxy->pcm, data, count);
+}
diff --git a/modules/usbaudio/alsa_device_proxy.h b/modules/usbaudio/alsa_device_proxy.h
new file mode 100644
index 0000000..f090c56
--- /dev/null
+++ b/modules/usbaudio/alsa_device_proxy.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_ALSA_DEVICE_PROXY_H
+#define ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_ALSA_DEVICE_PROXY_H
+
+#include <tinyalsa/asoundlib.h>
+
+#include "alsa_device_profile.h"
+
+typedef struct {
+ alsa_device_profile* profile;
+
+ struct pcm_config alsa_config;
+
+ struct pcm * pcm;
+} alsa_device_proxy;
+
+void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile * profile,
+ struct pcm_config * config);
+
+unsigned proxy_get_sample_rate(const alsa_device_proxy * proxy);
+enum pcm_format proxy_get_format(const alsa_device_proxy * proxy);
+unsigned proxy_get_channel_count(const alsa_device_proxy * proxy);
+
+unsigned int proxy_get_period_size(const alsa_device_proxy * proxy);
+
+unsigned proxy_get_latency(const alsa_device_proxy * proxy);
+
+int proxy_open(alsa_device_proxy * proxy);
+void proxy_close(alsa_device_proxy * proxy);
+
+int proxy_write(const alsa_device_proxy * proxy, const void *data, unsigned int count);
+int proxy_read(const alsa_device_proxy * proxy, void *data, unsigned int count);
+
+#endif /* ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_ALSA_DEVICE_PROXY_H */
diff --git a/modules/usbaudio/audio_hw.c b/modules/usbaudio/audio_hw.c
index 05f0d2b..22d5e0f 100644
--- a/modules/usbaudio/audio_hw.c
+++ b/modules/usbaudio/audio_hw.c
@@ -16,7 +16,6 @@
#define LOG_TAG "usb_audio_hw"
/*#define LOG_NDEBUG 0*/
-/*#define LOG_PCM_PARAMS 0*/
#include <errno.h>
#include <inttypes.h>
@@ -39,46 +38,22 @@
#include <audio_utils/channels.h>
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-
-/* This is the default configuration to hand to The Framework on the initial
- * adev_open_output_stream(). Actual device attributes will be used on the subsequent
- * adev_open_output_stream() after the card and device number have been set in out_set_parameters()
+/* FOR TESTING:
+ * Set k_force_channels to force the number of channels to present to AudioFlinger.
+ * 0 disables (this is default: present the device channels to AudioFlinger).
+ * 2 forces to legacy stereo mode.
+ *
+ * Others values can be tried (up to 8).
+ * TODO: AudioFlinger cannot support more than 8 active output channels
+ * at this time, so limiting logic needs to be put here or communicated from above.
*/
-#define OUT_PERIOD_SIZE 1024
-#define OUT_PERIOD_COUNT 4
-#define OUT_SAMPLING_RATE 44100
+static const unsigned k_force_channels = 0;
-struct pcm_config default_alsa_out_config = {
- .channels = 2,
- .rate = OUT_SAMPLING_RATE,
- .period_size = OUT_PERIOD_SIZE,
- .period_count = OUT_PERIOD_COUNT,
- .format = PCM_FORMAT_S16_LE,
-};
+#include "alsa_device_profile.h"
+#include "alsa_device_proxy.h"
+#include "logging.h"
-/*
- * Input defaults. See comment above.
- */
-#define IN_PERIOD_SIZE 1024
-#define IN_PERIOD_COUNT 4
-#define IN_SAMPLING_RATE 44100
-
-struct pcm_config default_alsa_in_config = {
- .channels = 2,
- .rate = IN_SAMPLING_RATE,
- .period_size = IN_PERIOD_SIZE,
- .period_count = IN_PERIOD_COUNT,
- .format = PCM_FORMAT_S16_LE,
- .start_threshold = 1,
- .stop_threshold = (IN_PERIOD_SIZE * IN_PERIOD_COUNT),
-};
-
-struct audio_device_profile {
- int card;
- int device;
- int direction; /* PCM_OUT or PCM_IN */
-};
+#define DEFAULT_INPUT_BUFFER_SIZE_MS 20
struct audio_device {
struct audio_hw_device hw_device;
@@ -86,10 +61,10 @@
pthread_mutex_t lock; /* see note below on mutex acquisition order */
/* output */
- struct audio_device_profile out_profile;
+ alsa_device_profile out_profile;
/* input */
- struct audio_device_profile in_profile;
+ alsa_device_profile in_profile;
bool standby;
};
@@ -98,49 +73,39 @@
struct audio_stream_out stream;
pthread_mutex_t lock; /* see note below on mutex acquisition order */
- struct pcm *pcm; /* state of the stream */
bool standby;
- struct audio_device *dev; /* hardware information */
- struct audio_device_profile * profile;
+ struct audio_device *dev; /* hardware information - only using this for the lock */
+ alsa_device_profile * profile;
+ alsa_device_proxy proxy; /* state of the stream */
+
+ unsigned hal_channel_count; /* channel count exposed to AudioFlinger.
+ * This may differ from the device channel count when
+ * the device is not compatible with AudioFlinger
+ * capabilities, e.g. exposes too many channels or
+ * too few channels. */
void * conversion_buffer; /* any conversions are put into here
* they could come from here too if
* there was a previous conversion */
size_t conversion_buffer_size; /* in bytes */
};
-/*
- * Output Configuration Cache
- * FIXME(pmclean) This is not reentrant. Should probably be moved into the stream structure.
- */
-static struct pcm_config cached_output_hardware_config;
-static bool output_hardware_config_is_cached = false;
-
struct stream_in {
struct audio_stream_in stream;
pthread_mutex_t lock; /* see note below on mutex acquisition order */
- struct pcm *pcm;
bool standby;
- struct audio_device *dev;
+ struct audio_device *dev; /* hardware information - only using this for the lock */
- struct audio_device_profile * profile;
+ alsa_device_profile * profile;
+ alsa_device_proxy proxy; /* state of the stream */
- struct audio_config hal_pcm_config;
+ // not used?
+ // struct audio_config hal_pcm_config;
- /* this is the format the framework thinks it's using. We may need to convert from the actual
- * (24-bit, 32-bit?) format to this theoretical (framework, probably 16-bit)
- * format in in_read() */
- enum pcm_format input_framework_format;
-
-// struct resampler_itfe *resampler;
-// struct resampler_buffer_provider buf_provider;
-
- int read_status;
-
- // We may need to read more data from the device in order to data reduce to 16bit, 4chan */
+ /* We may need to read more data from the device in order to data reduce to 16bit, 4chan */
void * conversion_buffer; /* any conversions are put into here
* they could come from here too if
* there was a previous conversion */
@@ -148,17 +113,6 @@
};
/*
- * Input Configuration Cache
- * FIXME(pmclean) This is not reentrant. Should probably be moved into the stream structure
- * but that will involve changes in The Framework.
- */
-static struct pcm_config cached_input_hardware_config;
-static bool input_hardware_config_is_cached = false;
-
-/*
- * Utility
- */
-/*
* Data Conversions
*/
/*
@@ -226,465 +180,49 @@
return num_in_samples * 2;
}
-/*
- * ALSA Utilities
- */
-/*TODO This table and the function that uses it should be moved to a utilities module (probably) */
-/*
- * Maps bit-positions in a pcm_mask to the corresponding AUDIO_ format string.
- */
-static const char * const format_string_map[] = {
- "AUDIO_FORMAT_PCM_8_BIT", /* 00 - SNDRV_PCM_FORMAT_S8 */
- "AUDIO_FORMAT_PCM_8_BIT", /* 01 - SNDRV_PCM_FORMAT_U8 */
- "AUDIO_FORMAT_PCM_16_BIT", /* 02 - SNDRV_PCM_FORMAT_S16_LE */
- NULL, /* 03 - SNDRV_PCM_FORMAT_S16_BE */
- NULL, /* 04 - SNDRV_PCM_FORMAT_U16_LE */
- NULL, /* 05 - SNDRV_PCM_FORMAT_U16_BE */
- "AUDIO_FORMAT_PCM_24_BIT_PACKED", /* 06 - SNDRV_PCM_FORMAT_S24_LE */
- NULL, /* 07 - SNDRV_PCM_FORMAT_S24_BE */
- NULL, /* 08 - SNDRV_PCM_FORMAT_U24_LE */
- NULL, /* 09 - SNDRV_PCM_FORMAT_U24_BE */
- "AUDIO_FORMAT_PCM_32_BIT", /* 10 - SNDRV_PCM_FORMAT_S32_LE */
- NULL, /* 11 - SNDRV_PCM_FORMAT_S32_BE */
- NULL, /* 12 - SNDRV_PCM_FORMAT_U32_LE */
- NULL, /* 13 - SNDRV_PCM_FORMAT_U32_BE */
- "AUDIO_FORMAT_PCM_FLOAT", /* 14 - SNDRV_PCM_FORMAT_FLOAT_LE */
- NULL, /* 15 - SNDRV_PCM_FORMAT_FLOAT_BE */
- NULL, /* 16 - SNDRV_PCM_FORMAT_FLOAT64_LE */
- NULL, /* 17 - SNDRV_PCM_FORMAT_FLOAT64_BE */
- NULL, /* 18 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE */
- NULL, /* 19 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE */
- NULL, /* 20 - SNDRV_PCM_FORMAT_MU_LAW */
- NULL, /* 21 - SNDRV_PCM_FORMAT_A_LAW */
- NULL, /* 22 - SNDRV_PCM_FORMAT_IMA_ADPCM */
- NULL, /* 23 - SNDRV_PCM_FORMAT_MPEG */
- NULL, /* 24 - SNDRV_PCM_FORMAT_GSM */
- NULL, NULL, NULL, NULL, NULL, NULL, /* 25 -> 30 (not assigned) */
- NULL, /* 31 - SNDRV_PCM_FORMAT_SPECIAL */
- "AUDIO_FORMAT_PCM_24_BIT_PACKED", /* 32 - SNDRV_PCM_FORMAT_S24_3LE */ /* ??? */
- NULL, /* 33 - SNDRV_PCM_FORMAT_S24_3BE */
- NULL, /* 34 - SNDRV_PCM_FORMAT_U24_3LE */
- NULL, /* 35 - SNDRV_PCM_FORMAT_U24_3BE */
- NULL, /* 36 - SNDRV_PCM_FORMAT_S20_3LE */
- NULL, /* 37 - SNDRV_PCM_FORMAT_S20_3BE */
- NULL, /* 38 - SNDRV_PCM_FORMAT_U20_3LE */
- NULL, /* 39 - SNDRV_PCM_FORMAT_U20_3BE */
- NULL, /* 40 - SNDRV_PCM_FORMAT_S18_3LE */
- NULL, /* 41 - SNDRV_PCM_FORMAT_S18_3BE */
- NULL, /* 42 - SNDRV_PCM_FORMAT_U18_3LE */
- NULL, /* 43 - SNDRV_PCM_FORMAT_U18_3BE */
- NULL, /* 44 - SNDRV_PCM_FORMAT_G723_24 */
- NULL, /* 45 - SNDRV_PCM_FORMAT_G723_24_1B */
- NULL, /* 46 - SNDRV_PCM_FORMAT_G723_40 */
- NULL, /* 47 - SNDRV_PCM_FORMAT_G723_40_1B */
- NULL, /* 48 - SNDRV_PCM_FORMAT_DSD_U8 */
- NULL /* 49 - SNDRV_PCM_FORMAT_DSD_U16_LE */
-};
-
-/*
- * Generate string containing a bar ("|") delimited list of AUDIO_ formats specified in
- * the mask parameter.
- *
- */
-static char* get_format_str_for_mask(struct pcm_mask* mask)
+static char * device_get_parameters(alsa_device_profile * profile, const char * keys)
{
- char buffer[256];
- int buffer_size = sizeof(buffer) / sizeof(buffer[0]);
- buffer[0] = '\0';
+ ALOGV("usb:audio_hw::device_get_parameters() keys:%s", keys);
- int num_slots = sizeof(mask->bits) / sizeof(mask->bits[0]);
- int bits_per_slot = sizeof(mask->bits[0]) * 8;
-
- const char* format_str = NULL;
- int table_size = sizeof(format_string_map)/sizeof(format_string_map[0]);
-
- int slot_index, bit_index, table_index;
- table_index = 0;
- int num_written = 0;
- for (slot_index = 0; slot_index < num_slots; slot_index++) {
- unsigned bit_mask = 1;
- for (bit_index = 0; bit_index < bits_per_slot; bit_index++) {
- if ((mask->bits[slot_index] & bit_mask) != 0) {
- format_str = table_index < table_size
- ? format_string_map[table_index]
- : NULL;
- if (format_str != NULL) {
- if (num_written != 0) {
- num_written += snprintf(buffer + num_written,
- buffer_size - num_written, "|");
- }
- num_written += snprintf(buffer + num_written, buffer_size - num_written,
- "%s", format_str);
- }
- }
- bit_mask <<= 1;
- table_index++;
- }
+ if (profile->card < 0 || profile->device < 0) {
+ return strdup("");
}
- return strdup(buffer);
-}
+ struct str_parms *query = str_parms_create_str(keys);
+ struct str_parms *result = str_parms_create();
-/*
- * Maps from bit position in pcm_mask to AUDIO_ format constants.
- */
-static audio_format_t const format_value_map[] = {
- AUDIO_FORMAT_PCM_8_BIT, /* 00 - SNDRV_PCM_FORMAT_S8 */
- AUDIO_FORMAT_PCM_8_BIT, /* 01 - SNDRV_PCM_FORMAT_U8 */
- AUDIO_FORMAT_PCM_16_BIT, /* 02 - SNDRV_PCM_FORMAT_S16_LE */
- AUDIO_FORMAT_INVALID, /* 03 - SNDRV_PCM_FORMAT_S16_BE */
- AUDIO_FORMAT_INVALID, /* 04 - SNDRV_PCM_FORMAT_U16_LE */
- AUDIO_FORMAT_INVALID, /* 05 - SNDRV_PCM_FORMAT_U16_BE */
- AUDIO_FORMAT_INVALID, /* 06 - SNDRV_PCM_FORMAT_S24_LE */
- AUDIO_FORMAT_INVALID, /* 07 - SNDRV_PCM_FORMAT_S24_BE */
- AUDIO_FORMAT_INVALID, /* 08 - SNDRV_PCM_FORMAT_U24_LE */
- AUDIO_FORMAT_INVALID, /* 09 - SNDRV_PCM_FORMAT_U24_BE */
- AUDIO_FORMAT_PCM_32_BIT, /* 10 - SNDRV_PCM_FORMAT_S32_LE */
- AUDIO_FORMAT_INVALID, /* 11 - SNDRV_PCM_FORMAT_S32_BE */
- AUDIO_FORMAT_INVALID, /* 12 - SNDRV_PCM_FORMAT_U32_LE */
- AUDIO_FORMAT_INVALID, /* 13 - SNDRV_PCM_FORMAT_U32_BE */
- AUDIO_FORMAT_PCM_FLOAT, /* 14 - SNDRV_PCM_FORMAT_FLOAT_LE */
- AUDIO_FORMAT_INVALID, /* 15 - SNDRV_PCM_FORMAT_FLOAT_BE */
- AUDIO_FORMAT_INVALID, /* 16 - SNDRV_PCM_FORMAT_FLOAT64_LE */
- AUDIO_FORMAT_INVALID, /* 17 - SNDRV_PCM_FORMAT_FLOAT64_BE */
- AUDIO_FORMAT_INVALID, /* 18 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE */
- AUDIO_FORMAT_INVALID, /* 19 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE */
- AUDIO_FORMAT_INVALID, /* 20 - SNDRV_PCM_FORMAT_MU_LAW */
- AUDIO_FORMAT_INVALID, /* 21 - SNDRV_PCM_FORMAT_A_LAW */
- AUDIO_FORMAT_INVALID, /* 22 - SNDRV_PCM_FORMAT_IMA_ADPCM */
- AUDIO_FORMAT_INVALID, /* 23 - SNDRV_PCM_FORMAT_MPEG */
- AUDIO_FORMAT_INVALID, /* 24 - SNDRV_PCM_FORMAT_GSM */
- AUDIO_FORMAT_INVALID, /* 25 -> 30 (not assigned) */
- AUDIO_FORMAT_INVALID,
- AUDIO_FORMAT_INVALID,
- AUDIO_FORMAT_INVALID,
- AUDIO_FORMAT_INVALID,
- AUDIO_FORMAT_INVALID,
- AUDIO_FORMAT_INVALID, /* 31 - SNDRV_PCM_FORMAT_SPECIAL */
- AUDIO_FORMAT_PCM_24_BIT_PACKED, /* 32 - SNDRV_PCM_FORMAT_S24_3LE */
- AUDIO_FORMAT_INVALID, /* 33 - SNDRV_PCM_FORMAT_S24_3BE */
- AUDIO_FORMAT_INVALID, /* 34 - SNDRV_PCM_FORMAT_U24_3LE */
- AUDIO_FORMAT_INVALID, /* 35 - SNDRV_PCM_FORMAT_U24_3BE */
- AUDIO_FORMAT_INVALID, /* 36 - SNDRV_PCM_FORMAT_S20_3LE */
- AUDIO_FORMAT_INVALID, /* 37 - SNDRV_PCM_FORMAT_S20_3BE */
- AUDIO_FORMAT_INVALID, /* 38 - SNDRV_PCM_FORMAT_U20_3LE */
- AUDIO_FORMAT_INVALID, /* 39 - SNDRV_PCM_FORMAT_U20_3BE */
- AUDIO_FORMAT_INVALID, /* 40 - SNDRV_PCM_FORMAT_S18_3LE */
- AUDIO_FORMAT_INVALID, /* 41 - SNDRV_PCM_FORMAT_S18_3BE */
- AUDIO_FORMAT_INVALID, /* 42 - SNDRV_PCM_FORMAT_U18_3LE */
- AUDIO_FORMAT_INVALID, /* 43 - SNDRV_PCM_FORMAT_U18_3BE */
- AUDIO_FORMAT_INVALID, /* 44 - SNDRV_PCM_FORMAT_G723_24 */
- AUDIO_FORMAT_INVALID, /* 45 - SNDRV_PCM_FORMAT_G723_24_1B */
- AUDIO_FORMAT_INVALID, /* 46 - SNDRV_PCM_FORMAT_G723_40 */
- AUDIO_FORMAT_INVALID, /* 47 - SNDRV_PCM_FORMAT_G723_40_1B */
- AUDIO_FORMAT_INVALID, /* 48 - SNDRV_PCM_FORMAT_DSD_U8 */
- AUDIO_FORMAT_INVALID /* 49 - SNDRV_PCM_FORMAT_DSD_U16_LE */
-};
-
-/*
- * Returns true if mask indicates support for PCM_16.
- */
-static bool mask_has_pcm_16(struct pcm_mask* mask) {
- return (mask->bits[0] & 0x0004) != 0;
-}
-
-static audio_format_t get_format_for_mask(struct pcm_mask* mask)
-{
- int num_slots = sizeof(mask->bits)/ sizeof(mask->bits[0]);
- int bits_per_slot = sizeof(mask->bits[0]) * 8;
-
- int table_size = sizeof(format_value_map) / sizeof(format_value_map[0]);
-
- int slot_index, bit_index, table_index;
- table_index = 0;
- int num_written = 0;
- for (slot_index = 0; slot_index < num_slots; slot_index++) {
- unsigned bit_mask = 1;
- for (bit_index = 0; bit_index < bits_per_slot; bit_index++) {
- if ((mask->bits[slot_index] & bit_mask) != 0) {
- /* just return the first one */
- return table_index < table_size
- ? format_value_map[table_index]
- : AUDIO_FORMAT_INVALID;
- }
- bit_mask <<= 1;
- table_index++;
- }
+ /* These keys are from hardware/libhardware/include/audio.h */
+ /* supported sample rates */
+ if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
+ char* rates_list = profile_get_sample_rate_strs(profile);
+ str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
+ rates_list);
+ free(rates_list);
}
- return AUDIO_FORMAT_INVALID;
-}
-
-/*
- * Maps from bit position in pcm_mask to PCM_ format constants.
- */
-static int8_t const pcm_format_value_map[] = {
- PCM_FORMAT_S8, /* 00 - SNDRV_PCM_FORMAT_S8 */
- PCM_FORMAT_INVALID, /* 01 - SNDRV_PCM_FORMAT_U8 */
- PCM_FORMAT_S16_LE, /* 02 - SNDRV_PCM_FORMAT_S16_LE */
- PCM_FORMAT_INVALID, /* 03 - SNDRV_PCM_FORMAT_S16_BE */
- PCM_FORMAT_INVALID, /* 04 - SNDRV_PCM_FORMAT_U16_LE */
- PCM_FORMAT_INVALID, /* 05 - SNDRV_PCM_FORMAT_U16_BE */
- PCM_FORMAT_S24_3LE, /* 06 - SNDRV_PCM_FORMAT_S24_LE */
- PCM_FORMAT_INVALID, /* 07 - SNDRV_PCM_FORMAT_S24_BE */
- PCM_FORMAT_INVALID, /* 08 - SNDRV_PCM_FORMAT_U24_LE */
- PCM_FORMAT_INVALID, /* 09 - SNDRV_PCM_FORMAT_U24_BE */
- PCM_FORMAT_S32_LE, /* 10 - SNDRV_PCM_FORMAT_S32_LE */
- PCM_FORMAT_INVALID, /* 11 - SNDRV_PCM_FORMAT_S32_BE */
- PCM_FORMAT_INVALID, /* 12 - SNDRV_PCM_FORMAT_U32_LE */
- PCM_FORMAT_INVALID, /* 13 - SNDRV_PCM_FORMAT_U32_BE */
- PCM_FORMAT_INVALID, /* 14 - SNDRV_PCM_FORMAT_FLOAT_LE */
- PCM_FORMAT_INVALID, /* 15 - SNDRV_PCM_FORMAT_FLOAT_BE */
- PCM_FORMAT_INVALID, /* 16 - SNDRV_PCM_FORMAT_FLOAT64_LE */
- PCM_FORMAT_INVALID, /* 17 - SNDRV_PCM_FORMAT_FLOAT64_BE */
- PCM_FORMAT_INVALID, /* 18 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE */
- PCM_FORMAT_INVALID, /* 19 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE */
- PCM_FORMAT_INVALID, /* 20 - SNDRV_PCM_FORMAT_MU_LAW */
- PCM_FORMAT_INVALID, /* 21 - SNDRV_PCM_FORMAT_A_LAW */
- PCM_FORMAT_INVALID, /* 22 - SNDRV_PCM_FORMAT_IMA_ADPCM */
- PCM_FORMAT_INVALID, /* 23 - SNDRV_PCM_FORMAT_MPEG */
- PCM_FORMAT_INVALID, /* 24 - SNDRV_PCM_FORMAT_GSM */
- PCM_FORMAT_INVALID, /* 25 -> 30 (not assigned) */
- PCM_FORMAT_INVALID,
- PCM_FORMAT_INVALID,
- PCM_FORMAT_INVALID,
- PCM_FORMAT_INVALID,
- PCM_FORMAT_INVALID,
- PCM_FORMAT_INVALID, /* 31 - SNDRV_PCM_FORMAT_SPECIAL */
- PCM_FORMAT_S24_3LE, /* 32 - SNDRV_PCM_FORMAT_S24_3LE */ /* ??? */
- PCM_FORMAT_INVALID, /* 33 - SNDRV_PCM_FORMAT_S24_3BE */
- PCM_FORMAT_INVALID, /* 34 - SNDRV_PCM_FORMAT_U24_3LE */
- PCM_FORMAT_INVALID, /* 35 - SNDRV_PCM_FORMAT_U24_3BE */
- PCM_FORMAT_INVALID, /* 36 - SNDRV_PCM_FORMAT_S20_3LE */
- PCM_FORMAT_INVALID, /* 37 - SNDRV_PCM_FORMAT_S20_3BE */
- PCM_FORMAT_INVALID, /* 38 - SNDRV_PCM_FORMAT_U20_3LE */
- PCM_FORMAT_INVALID, /* 39 - SNDRV_PCM_FORMAT_U20_3BE */
- PCM_FORMAT_INVALID, /* 40 - SNDRV_PCM_FORMAT_S18_3LE */
- PCM_FORMAT_INVALID, /* 41 - SNDRV_PCM_FORMAT_S18_3BE */
- PCM_FORMAT_INVALID, /* 42 - SNDRV_PCM_FORMAT_U18_3LE */
- PCM_FORMAT_INVALID, /* 43 - SNDRV_PCM_FORMAT_U18_3BE */
- PCM_FORMAT_INVALID, /* 44 - SNDRV_PCM_FORMAT_G723_24 */
- PCM_FORMAT_INVALID, /* 45 - SNDRV_PCM_FORMAT_G723_24_1B */
- PCM_FORMAT_INVALID, /* 46 - SNDRV_PCM_FORMAT_G723_40 */
- PCM_FORMAT_INVALID, /* 47 - SNDRV_PCM_FORMAT_G723_40_1B */
- PCM_FORMAT_INVALID, /* 48 - SNDRV_PCM_FORMAT_DSD_U8 */
- PCM_FORMAT_INVALID /* 49 - SNDRV_PCM_FORMAT_DSD_U16_LE */
-};
-
-/*
- * Scans the provided format mask and returns the first non-8 bit sample
- * format supported by the devices.
- */
-static int get_pcm_format_for_mask(struct pcm_mask* mask) {
- int num_slots = sizeof(mask->bits)/ sizeof(mask->bits[0]);
- int bits_per_slot = sizeof(mask->bits[0]) * 8;
-
- int table_size = ARRAY_SIZE(pcm_format_value_map);
-
- int slot_index, bit_index, table_index;
- table_index = 0;
- int num_written = 0;
- for (slot_index = 0; slot_index < num_slots && table_index < table_size; slot_index++) {
- unsigned bit_mask = 1;
- for (bit_index = 0; bit_index < bits_per_slot && table_index < table_size; bit_index++) {
- if ((mask->bits[slot_index] & bit_mask) != 0) {
- /* TODO - we don't want a low-level function to be making this decision */
- if (table_index != 0) { /* Don't pick 8-bit */
- /* just return the first one */
- return (int)pcm_format_value_map[table_index];
- }
- }
- bit_mask <<= 1;
- table_index++;
- }
+ /* supported channel counts */
+ if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
+ char* channels_list = profile_get_channel_count_strs(profile);
+ str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_CHANNELS,
+ channels_list);
+ free(channels_list);
}
- return PCM_FORMAT_INVALID;
-}
-
-static bool test_out_sample_rate(struct audio_device_profile* dev_profile, unsigned rate) {
- struct pcm_config local_config = cached_output_hardware_config;
- local_config.rate = rate;
-
- bool works = false; /* let's be pessimistic */
- struct pcm * pcm =
- pcm_open(dev_profile->card, dev_profile->device, dev_profile->direction, &local_config);
-
- if (pcm != NULL) {
- works = pcm_is_ready(pcm);
- pcm_close(pcm);
+ /* supported sample formats */
+ if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
+ char * format_params = profile_get_format_strs(profile);
+ str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS,
+ format_params);
+ free(format_params);
}
+ str_parms_destroy(query);
- return works;
-}
+ char* result_str = str_parms_to_str(result);
+ str_parms_destroy(result);
-/* sort these highest -> lowest */
-static const unsigned std_sample_rates[] =
- {48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000};
+ ALOGV("usb:audio_hw::device_get_parameters = %s", result_str);
-static char* enum_std_sample_rates(struct audio_device_profile* dev_profile,
- unsigned min, unsigned max)
-{
- char buffer[128];
- buffer[0] = '\0';
- int buffSize = ARRAY_SIZE(buffer);
-
- char numBuffer[32];
-
- int numEntries = 0;
- unsigned index;
- for(index = 0; index < ARRAY_SIZE(std_sample_rates); index++) {
- if (std_sample_rates[index] >= min && std_sample_rates[index] <= max &&
- test_out_sample_rate(dev_profile, std_sample_rates[index])) {
- if (numEntries++ != 0) {
- strncat(buffer, "|", buffSize);
- }
- snprintf(numBuffer, sizeof(numBuffer), "%u", std_sample_rates[index]);
- strncat(buffer, numBuffer, buffSize);
- }
- }
-
- return strdup(buffer);
-}
-
-/*
- * Logging
- */
-static void log_pcm_mask(const char* mask_name, struct pcm_mask* mask) {
- char buff[512];
- char bit_buff[32];
- int buffSize = sizeof(buff)/sizeof(buff[0]);
-
- buff[0] = '\0';
-
- int num_slots = sizeof(mask->bits) / sizeof(mask->bits[0]);
- int bits_per_slot = sizeof(mask->bits[0]) * 8;
-
- int slot_index, bit_index;
- strcat(buff, "[");
- for (slot_index = 0; slot_index < num_slots; slot_index++) {
- unsigned bit_mask = 1;
- for (bit_index = 0; bit_index < bits_per_slot; bit_index++) {
- strcat(buff, (mask->bits[slot_index] & bit_mask) != 0 ? "1" : "0");
- bit_mask <<= 1;
- }
- if (slot_index < num_slots - 1) {
- strcat(buff, ",");
- }
- }
- strcat(buff, "]");
-
- ALOGV("usb:audio_hw - %s mask:%s", mask_name, buff);
-}
-
-static void log_pcm_params(struct pcm_params * alsa_hw_params) {
- ALOGV("usb:audio_hw - PCM_PARAM_SAMPLE_BITS min:%u, max:%u",
- pcm_params_get_min(alsa_hw_params, PCM_PARAM_SAMPLE_BITS),
- pcm_params_get_max(alsa_hw_params, PCM_PARAM_SAMPLE_BITS));
- ALOGV("usb:audio_hw - PCM_PARAM_FRAME_BITS min:%u, max:%u",
- pcm_params_get_min(alsa_hw_params, PCM_PARAM_FRAME_BITS),
- pcm_params_get_max(alsa_hw_params, PCM_PARAM_FRAME_BITS));
- log_pcm_mask("PCM_PARAM_FORMAT", pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT));
- log_pcm_mask("PCM_PARAM_SUBFORMAT", pcm_params_get_mask(alsa_hw_params, PCM_PARAM_SUBFORMAT));
- ALOGV("usb:audio_hw - PCM_PARAM_CHANNELS min:%u, max:%u",
- pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS),
- pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS));
- ALOGV("usb:audio_hw - PCM_PARAM_RATE min:%u, max:%u",
- pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE),
- pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE));
- ALOGV("usb:audio_hw - PCM_PARAM_PERIOD_TIME min:%u, max:%u",
- pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_TIME),
- pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_TIME));
- ALOGV("usb:audio_hw - PCM_PARAM_PERIOD_SIZE min:%u, max:%u",
- pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_SIZE),
- pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_SIZE));
- ALOGV("usb:audio_hw - PCM_PARAM_PERIOD_BYTES min:%u, max:%u",
- pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_BYTES),
- pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_BYTES));
- ALOGV("usb:audio_hw - PCM_PARAM_PERIODS min:%u, max:%u",
- pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS),
- pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIODS));
- ALOGV("usb:audio_hw - PCM_PARAM_BUFFER_TIME min:%u, max:%u",
- pcm_params_get_min(alsa_hw_params, PCM_PARAM_BUFFER_TIME),
- pcm_params_get_max(alsa_hw_params, PCM_PARAM_BUFFER_TIME));
- ALOGV("usb:audio_hw - PCM_PARAM_BUFFER_SIZE min:%u, max:%u",
- pcm_params_get_min(alsa_hw_params, PCM_PARAM_BUFFER_SIZE),
- pcm_params_get_max(alsa_hw_params, PCM_PARAM_BUFFER_SIZE));
- ALOGV("usb:audio_hw - PCM_PARAM_BUFFER_BYTES min:%u, max:%u",
- pcm_params_get_min(alsa_hw_params, PCM_PARAM_BUFFER_BYTES),
- pcm_params_get_max(alsa_hw_params, PCM_PARAM_BUFFER_BYTES));
- ALOGV("usb:audio_hw - PCM_PARAM_TICK_TIME min:%u, max:%u",
- pcm_params_get_min(alsa_hw_params, PCM_PARAM_TICK_TIME),
- pcm_params_get_max(alsa_hw_params, PCM_PARAM_TICK_TIME));
-}
-
-/*
- * Returns the supplied value rounded up to the next even multiple of 16
- */
-static unsigned int round_to_16_mult(unsigned int size) {
- return (size + 15) & 0xFFFFFFF0;
-}
-
-/*TODO - Evaluate if this value should/can be retrieved from a device-specific property */
-#define MIN_BUFF_TIME 5 /* milliseconds */
-
-/*
- * Returns the system defined minimum period size based on the supplied sample rate
- */
-static unsigned int calc_min_period_size(unsigned int sample_rate) {
- unsigned int period_size = (sample_rate * MIN_BUFF_TIME) / 1000;
- return round_to_16_mult(period_size);
-}
-
-/*
- * Reads and decodes configuration info from the specified ALSA card/device
- */
-static int read_alsa_device_config(struct audio_device_profile * dev_profile,
- struct pcm_config * config)
-{
- ALOGV("usb:audio_hw - read_alsa_device_config(c:%d d:%d t:0x%X)",
- dev_profile->card, dev_profile->device, dev_profile->direction);
-
- if (dev_profile->card < 0 || dev_profile->device < 0) {
- return -EINVAL;
- }
-
- struct pcm_params * alsa_hw_params =
- pcm_params_get(dev_profile->card, dev_profile->device, dev_profile->direction);
- if (alsa_hw_params == NULL) {
- return -EINVAL;
- }
-
- int ret = 0;
-
- /*
- * This Logging will be useful when testing new USB devices.
- */
-#ifdef LOG_PCM_PARAMS
- log_pcm_params(alsa_hw_params);
-#endif
-
- config->channels = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
- config->rate = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE);
- config->period_size = pcm_params_get_min(alsa_hw_params, PCM_PARAM_BUFFER_SIZE);
- /* round this up to a multiple of 16 */
- config->period_size = round_to_16_mult(config->period_size);
- /* make sure it is above a minimum value to minimize jitter */
- unsigned int min_period_size = calc_min_period_size(config->rate);
- if (config->period_size < min_period_size) {
- config->period_size = min_period_size;
- }
- config->period_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS);
-
- int format = get_pcm_format_for_mask(pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT));
- if (format == PCM_FORMAT_INVALID) {
- ret = -EINVAL;
- } else {
- config->format = format;
- }
-
- pcm_params_free(alsa_hw_params);
- return ret;
+ return result_str;
}
/*
@@ -695,10 +233,14 @@
* following order: hw device > out stream
*/
-/* Helper functions */
+/*
+ * OUT functions
+ */
static uint32_t out_get_sample_rate(const struct audio_stream *stream)
{
- return cached_output_hardware_config.rate;
+ uint32_t rate = proxy_get_sample_rate(&((struct stream_out*)stream)->proxy);
+ ALOGV("out_get_sample_rate() = %d", rate);
+ return rate;
}
static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
@@ -708,26 +250,33 @@
static size_t out_get_buffer_size(const struct audio_stream *stream)
{
- return cached_output_hardware_config.period_size *
- audio_stream_out_frame_size((const struct audio_stream_out *)stream);
+ const struct stream_out* out = (const struct stream_out*)stream;
+ size_t buffer_size =
+ proxy_get_period_size(&out->proxy) * audio_stream_out_frame_size(&(out->stream));
+ ALOGV("out_get_buffer_size() = %zu", buffer_size);
+ return buffer_size;
}
static uint32_t out_get_channels(const struct audio_stream *stream)
{
- // Always Stero for now. We will do *some* conversions in this HAL.
- /* TODO When AudioPolicyManager & AudioFlinger supports arbitrary channels
- rewrite this to return the ACTUAL channel format */
- return AUDIO_CHANNEL_OUT_STEREO;
+ const struct stream_out *out = (const struct stream_out*)stream;
+ return audio_channel_out_mask_from_count(out->hal_channel_count);
}
static audio_format_t out_get_format(const struct audio_stream *stream)
{
- return audio_format_from_pcm_format(cached_output_hardware_config.format);
+ /* Note: The HAL doesn't do any FORMAT conversion at this time. It
+ * Relies on the framework to provide data in the specified format.
+ * This could change in the future.
+ */
+ alsa_device_proxy * proxy = &((struct stream_out*)stream)->proxy;
+ audio_format_t format = audio_format_from_pcm_format(proxy_get_format(proxy));
+ ALOGV("out_get_format() = %d", format);
+ return format;
}
static int out_set_format(struct audio_stream *stream, audio_format_t format)
{
- cached_output_hardware_config.format = pcm_format_from_audio_format(format);
return 0;
}
@@ -739,8 +288,7 @@
pthread_mutex_lock(&out->lock);
if (!out->standby) {
- pcm_close(out->pcm);
- out->pcm = NULL;
+ proxy_close(&out->proxy);
out->standby = true;
}
@@ -760,34 +308,43 @@
ALOGV("usb:audio_hw::out out_set_parameters() keys:%s", kvpairs);
struct stream_out *out = (struct stream_out *)stream;
- struct str_parms *parms;
+
char value[32];
int param_val;
int routing = 0;
int ret_value = 0;
+ int card = -1;
+ int device = -1;
- parms = str_parms_create_str(kvpairs);
+ struct str_parms * parms = str_parms_create_str(kvpairs);
pthread_mutex_lock(&out->dev->lock);
pthread_mutex_lock(&out->lock);
- bool recache_device_params = false;
param_val = str_parms_get_str(parms, "card", value, sizeof(value));
- if (param_val >= 0) {
- out->profile->card = atoi(value);
- recache_device_params = true;
- }
+ if (param_val >= 0)
+ card = atoi(value);
param_val = str_parms_get_str(parms, "device", value, sizeof(value));
- if (param_val >= 0) {
- out->profile->device = atoi(value);
- recache_device_params = true;
- }
+ if (param_val >= 0)
+ device = atoi(value);
- if (recache_device_params && out->profile->card >= 0 && out->profile->device >= 0) {
- ret_value = read_alsa_device_config(out->profile, &cached_output_hardware_config);
- output_hardware_config_is_cached = (ret_value == 0);
+ if ((card >= 0) && (card != out->profile->card) &&
+ (device >= 0) && (device != out->profile->device)) {
+ /* cannot read pcm device info if playback is active */
+ if (!out->standby)
+ ret_value = -ENOSYS;
+ else {
+ int saved_card = out->profile->card;
+ int saved_device = out->profile->device;
+ out->profile->card = card;
+ out->profile->device = device;
+ ret_value = profile_read_device_info(out->profile) ? 0 : -EINVAL;
+ if (ret_value != 0) {
+ out->profile->card = saved_card;
+ out->profile->device = saved_device;
+ }
+ }
}
-
pthread_mutex_unlock(&out->lock);
pthread_mutex_unlock(&out->dev->lock);
str_parms_destroy(parms);
@@ -795,78 +352,9 @@
return ret_value;
}
-static char * device_get_parameters(struct audio_device_profile * dev_profile, const char *keys)
-{
- ALOGV("usb:audio_hw::device_get_parameters() keys:%s", keys);
-
- if (dev_profile->card < 0 || dev_profile->device < 0) {
- return strdup("");
- }
-
- unsigned min, max;
-
- struct str_parms *query = str_parms_create_str(keys);
- struct str_parms *result = str_parms_create();
-
- int num_written = 0;
- char buffer[256];
- int buffer_size = sizeof(buffer) / sizeof(buffer[0]);
- char* result_str = NULL;
-
- struct pcm_params * alsa_hw_params =
- pcm_params_get(dev_profile->card, dev_profile->device, dev_profile->direction);
-
- // These keys are from hardware/libhardware/include/audio.h
- // supported sample rates
- if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
- min = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE);
- max = pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE);
-
- char* rates_list = enum_std_sample_rates(dev_profile, min, max);
- str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, rates_list);
- free(rates_list);
- } // AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES
-
- // supported channel counts
- if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
- // TODO remove this hack when it is superceeded by proper multi-channel support
- str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_CHANNELS,
- dev_profile->direction == PCM_OUT
- ? "AUDIO_CHANNEL_OUT_STEREO"
- : "AUDIO_CHANNEL_IN_STEREO");
- } // AUDIO_PARAMETER_STREAM_SUP_CHANNELS
-
- // supported sample formats
- if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
- // TODO remove this hack when we have support for input in non PCM16 formats
- if (dev_profile->direction == PCM_IN) {
- str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS, "AUDIO_FORMAT_PCM_16_BIT");
- } else {
- struct pcm_mask * format_mask = pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT);
- char * format_params = get_format_str_for_mask(format_mask);
- str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS, format_params);
- free(format_params);
- }
- } // AUDIO_PARAMETER_STREAM_SUP_FORMATS
-
- pcm_params_free(alsa_hw_params);
-
- result_str = str_parms_to_str(result);
-
- // done with these...
- str_parms_destroy(query);
- str_parms_destroy(result);
-
- ALOGV("usb:audio_hw::device_get_parameters = %s", result_str);
-
- return result_str;
-}
-
static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
{
- ALOGV("usb:audio_hw::out out_get_parameters() keys:%s", keys);
-
- struct stream_out *out = (struct stream_out *) stream;
+ struct stream_out *out = (struct stream_out *)stream;
pthread_mutex_lock(&out->dev->lock);
pthread_mutex_lock(&out->lock);
@@ -880,13 +368,8 @@
static uint32_t out_get_latency(const struct audio_stream_out *stream)
{
- // struct stream_out *out = (struct stream_out *) stream;
-
- /*TODO Do we need a term here for the USB latency (as reported in the USB descriptors)? */
- uint32_t latency = (cached_output_hardware_config.period_size
- * cached_output_hardware_config.period_count * 1000)
- / out_get_sample_rate(&stream->common);
- return latency;
+ alsa_device_proxy * proxy = &((struct stream_out*)stream)->proxy;
+ return proxy_get_latency(proxy);
}
static int out_set_volume(struct audio_stream_out *stream, float left, float right)
@@ -897,25 +380,10 @@
/* must be called with hw device and output stream mutexes locked */
static int start_output_stream(struct stream_out *out)
{
- int return_val = 0;
-
ALOGV("usb:audio_hw::out start_output_stream(card:%d device:%d)",
out->profile->card, out->profile->device);
- out->pcm = pcm_open(out->profile->card, out->profile->device, PCM_OUT,
- &cached_output_hardware_config);
-
- if (out->pcm == NULL) {
- return -ENOMEM;
- }
-
- if (out->pcm && !pcm_is_ready(out->pcm)) {
- ALOGE("audio_hw audio_hw pcm_open() failed: %s", pcm_get_error(out->pcm));
- pcm_close(out->pcm);
- return -ENOMEM;
- }
-
- return 0;
+ return proxy_open(&out->proxy);
}
static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes)
@@ -928,53 +396,48 @@
if (out->standby) {
ret = start_output_stream(out);
if (ret != 0) {
+ pthread_mutex_unlock(&out->dev->lock);
goto err;
}
out->standby = false;
}
+ pthread_mutex_unlock(&out->dev->lock);
- // Setup conversion buffer
- // compute maximum potential buffer size.
- // * 2 for stereo -> quad conversion
- // * 3/2 for 16bit -> 24 bit conversion
- size_t required_conversion_buffer_size = (bytes * 3 * 2) / 2;
- if (required_conversion_buffer_size > out->conversion_buffer_size) {
- /* TODO Remove this when AudioPolicyManger/AudioFlinger support arbitrary formats
- (and do these conversions themselves) */
- out->conversion_buffer_size = required_conversion_buffer_size;
- out->conversion_buffer = realloc(out->conversion_buffer, out->conversion_buffer_size);
- }
+ alsa_device_proxy* proxy = &out->proxy;
const void * write_buff = buffer;
int num_write_buff_bytes = bytes;
-
- /*
- * Num Channels conversion
- */
- int num_device_channels = cached_output_hardware_config.channels;
- int num_req_channels = 2; /* always, for now */
+ const int num_device_channels = proxy_get_channel_count(proxy); /* what we told alsa */
+ const int num_req_channels = out->hal_channel_count; /* what we told AudioFlinger */
if (num_device_channels != num_req_channels) {
- audio_format_t audio_format = out_get_format(&(out->stream.common));
- unsigned sample_size_in_bytes = audio_bytes_per_sample(audio_format);
+ /* allocate buffer */
+ const size_t required_conversion_buffer_size =
+ bytes * num_device_channels / num_req_channels;
+ if (required_conversion_buffer_size > out->conversion_buffer_size) {
+ out->conversion_buffer_size = required_conversion_buffer_size;
+ out->conversion_buffer = realloc(out->conversion_buffer,
+ out->conversion_buffer_size);
+ }
+ /* convert data */
+ const audio_format_t audio_format = out_get_format(&(out->stream.common));
+ const unsigned sample_size_in_bytes = audio_bytes_per_sample(audio_format);
num_write_buff_bytes =
- adjust_channels(write_buff, num_req_channels,
- out->conversion_buffer, num_device_channels,
- sample_size_in_bytes, num_write_buff_bytes);
+ adjust_channels(write_buff, num_req_channels,
+ out->conversion_buffer, num_device_channels,
+ sample_size_in_bytes, num_write_buff_bytes);
write_buff = out->conversion_buffer;
}
if (write_buff != NULL && num_write_buff_bytes != 0) {
- pcm_write(out->pcm, write_buff, num_write_buff_bytes);
+ proxy_write(&out->proxy, write_buff, num_write_buff_bytes);
}
pthread_mutex_unlock(&out->lock);
- pthread_mutex_unlock(&out->dev->lock);
return bytes;
err:
pthread_mutex_unlock(&out->lock);
- pthread_mutex_unlock(&out->dev->lock);
if (ret != 0) {
usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
out_get_sample_rate(&stream->common));
@@ -988,6 +451,13 @@
return -EINVAL;
}
+static int out_get_presentation_position(const struct audio_stream_out *stream,
+ uint64_t *frames, struct timespec *timestamp)
+{
+ /* FIXME - This needs to be implemented */
+ return -EINVAL;
+}
+
static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
{
return 0;
@@ -1008,7 +478,8 @@
audio_devices_t devices,
audio_output_flags_t flags,
struct audio_config *config,
- struct audio_stream_out **stream_out)
+ struct audio_stream_out **stream_out,
+ const char *address __unused)
{
ALOGV("usb:audio_hw::out adev_open_output_stream() handle:0x%X, device:0x%X, flags:0x%X",
handle, devices, flags);
@@ -1021,7 +492,7 @@
if (!out)
return -ENOMEM;
- // setup function pointers
+ /* setup function pointers */
out->stream.common.get_sample_rate = out_get_sample_rate;
out->stream.common.set_sample_rate = out_set_sample_rate;
out->stream.common.get_buffer_size = out_get_buffer_size;
@@ -1038,41 +509,70 @@
out->stream.set_volume = out_set_volume;
out->stream.write = out_write;
out->stream.get_render_position = out_get_render_position;
+ out->stream.get_presentation_position = out_get_presentation_position;
out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
out->dev = adev;
- out->profile = &(adev->out_profile);
- out->profile->direction = PCM_OUT;
+ out->profile = &adev->out_profile;
- if (output_hardware_config_is_cached) {
- config->sample_rate = cached_output_hardware_config.rate;
+ // build this to hand to the alsa_device_proxy
+ struct pcm_config proxy_config;
- config->format = audio_format_from_pcm_format(cached_output_hardware_config.format);
+ int ret = 0;
- config->channel_mask =
- audio_channel_out_mask_from_count(cached_output_hardware_config.channels);
- if (config->channel_mask != AUDIO_CHANNEL_OUT_STEREO) {
- // Always report STEREO for now. AudioPolicyManagerBase/AudioFlinger dont' understand
- // formats with more channels, so we won't get chosen (say with a 4-channel DAC).
- /*TODO remove this when the above restriction is removed. */
- config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
- }
+ /* Rate */
+ if (config->sample_rate == 0) {
+ proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(out->profile);
+ } else if (profile_is_sample_rate_valid(out->profile, config->sample_rate)) {
+ proxy_config.rate = config->sample_rate;
} else {
- cached_output_hardware_config = default_alsa_out_config;
-
- config->format = out_get_format(&out->stream.common);
- config->channel_mask = out_get_channels(&out->stream.common);
- config->sample_rate = out_get_sample_rate(&out->stream.common);
+ proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(out->profile);
+ ret = -EINVAL;
}
+ /* Format */
+ if (config->format == AUDIO_FORMAT_DEFAULT) {
+ proxy_config.format = profile_get_default_format(out->profile);
+ config->format = audio_format_from_pcm_format(proxy_config.format);
+ } else {
+ enum pcm_format fmt = pcm_format_from_audio_format(config->format);
+ if (profile_is_format_valid(out->profile, fmt)) {
+ proxy_config.format = fmt;
+ } else {
+ proxy_config.format = profile_get_default_format(out->profile);
+ config->format = audio_format_from_pcm_format(proxy_config.format);
+ ret = -EINVAL;
+ }
+ }
+
+ /* Channels */
+ unsigned proposed_channel_count = profile_get_default_channel_count(out->profile);
+ if (k_force_channels) {
+ proposed_channel_count = k_force_channels;
+ } else if (config->channel_mask != AUDIO_CHANNEL_NONE) {
+ proposed_channel_count = audio_channel_count_from_out_mask(config->channel_mask);
+ }
+ /* we can expose any channel count mask, and emulate internally. */
+ config->channel_mask = audio_channel_out_mask_from_count(proposed_channel_count);
+ out->hal_channel_count = proposed_channel_count;
+ /* no validity checks are needed as proxy_prepare() forces channel_count to be valid.
+ * and we emulate any channel count discrepancies in out_write(). */
+ proxy_config.channels = proposed_channel_count;
+
+ proxy_prepare(&out->proxy, out->profile, &proxy_config);
+
+ /* TODO The retry mechanism isn't implemented in AudioPolicyManager/AudioFlinger. */
+ ret = 0;
+
out->conversion_buffer = NULL;
out->conversion_buffer_size = 0;
out->standby = true;
*stream_out = &out->stream;
- return 0;
+
+ return ret;
err_open:
free(out);
@@ -1086,16 +586,416 @@
ALOGV("usb:audio_hw::out adev_close_output_stream()");
struct stream_out *out = (struct stream_out *)stream;
- // Close the pcm device
+ /* Close the pcm device */
out_standby(&stream->common);
free(out->conversion_buffer);
+
out->conversion_buffer = NULL;
out->conversion_buffer_size = 0;
free(stream);
}
+static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
+ const struct audio_config *config)
+{
+ /* TODO This needs to be calculated based on format/channels/rate */
+ return 320;
+}
+
+/*
+ * IN functions
+ */
+static uint32_t in_get_sample_rate(const struct audio_stream *stream)
+{
+ uint32_t rate = proxy_get_sample_rate(&((const struct stream_in *)stream)->proxy);
+ ALOGV("in_get_sample_rate() = %d", rate);
+ return rate;
+}
+
+static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
+{
+ ALOGV("in_set_sample_rate(%d) - NOPE", rate);
+ return -ENOSYS;
+}
+
+static size_t in_get_buffer_size(const struct audio_stream *stream)
+{
+ const struct stream_in * in = ((const struct stream_in*)stream);
+ size_t buffer_size =
+ proxy_get_period_size(&in->proxy) * audio_stream_in_frame_size(&(in->stream));
+ ALOGV("in_get_buffer_size() = %zd", buffer_size);
+
+ return buffer_size;
+}
+
+static uint32_t in_get_channels(const struct audio_stream *stream)
+{
+ /* TODO Here is the code we need when we support arbitrary channel counts
+ * alsa_device_proxy * proxy = ((struct stream_in*)stream)->proxy;
+ * unsigned channel_count = proxy_get_channel_count(proxy);
+ * uint32_t channel_mask = audio_channel_in_mask_from_count(channel_count);
+ * ALOGV("in_get_channels() = 0x%X count:%d", channel_mask, channel_count);
+ * return channel_mask;
+ */
+ /* TODO When AudioPolicyManager & AudioFlinger supports arbitrary channels
+ rewrite this to return the ACTUAL channel format */
+ return AUDIO_CHANNEL_IN_STEREO;
+}
+
+static audio_format_t in_get_format(const struct audio_stream *stream)
+{
+ /* TODO Here is the code we need when we support arbitrary input formats
+ * alsa_device_proxy * proxy = ((struct stream_in*)stream)->proxy;
+ * audio_format_t format = audio_format_from_pcm_format(proxy_get_format(proxy));
+ * ALOGV("in_get_format() = %d", format);
+ * return format;
+ */
+ /* Input only supports PCM16 */
+ /* TODO When AudioPolicyManager & AudioFlinger supports arbitrary input formats
+ rewrite this to return the ACTUAL channel format (above) */
+ return AUDIO_FORMAT_PCM_16_BIT;
+}
+
+static int in_set_format(struct audio_stream *stream, audio_format_t format)
+{
+ ALOGV("in_set_format(%d) - NOPE", format);
+
+ return -ENOSYS;
+}
+
+static int in_standby(struct audio_stream *stream)
+{
+ struct stream_in *in = (struct stream_in *)stream;
+
+ pthread_mutex_lock(&in->dev->lock);
+ pthread_mutex_lock(&in->lock);
+
+ if (!in->standby) {
+ proxy_close(&in->proxy);
+ in->standby = true;
+ }
+
+ pthread_mutex_unlock(&in->lock);
+ pthread_mutex_unlock(&in->dev->lock);
+
+ return 0;
+}
+
+static int in_dump(const struct audio_stream *stream, int fd)
+{
+ return 0;
+}
+
+static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
+{
+ ALOGV("usb: audio_hw::in in_set_parameters() keys:%s", kvpairs);
+
+ struct stream_in *in = (struct stream_in *)stream;
+
+ char value[32];
+ int param_val;
+ int routing = 0;
+ int ret_value = 0;
+ int card = -1;
+ int device = -1;
+
+ struct str_parms * parms = str_parms_create_str(kvpairs);
+
+ pthread_mutex_lock(&in->dev->lock);
+ pthread_mutex_lock(&in->lock);
+
+ /* Card/Device */
+ param_val = str_parms_get_str(parms, "card", value, sizeof(value));
+ if (param_val >= 0)
+ card = atoi(value);
+
+ param_val = str_parms_get_str(parms, "device", value, sizeof(value));
+ if (param_val >= 0)
+ device = atoi(value);
+
+ if ((card >= 0) && (card != in->profile->card) &&
+ (device >= 0) && (device != in->profile->device)) {
+ /* cannot read pcm device info if playback is active */
+ if (!in->standby)
+ ret_value = -ENOSYS;
+ else {
+ int saved_card = in->profile->card;
+ int saved_device = in->profile->device;
+ in->profile->card = card;
+ in->profile->device = device;
+ ret_value = profile_read_device_info(in->profile) ? 0 : -EINVAL;
+ if (ret_value != 0) {
+ in->profile->card = saved_card;
+ in->profile->device = saved_device;
+ }
+ }
+ }
+
+ pthread_mutex_unlock(&in->lock);
+ pthread_mutex_unlock(&in->dev->lock);
+
+ str_parms_destroy(parms);
+
+ return ret_value;
+}
+
+static char * in_get_parameters(const struct audio_stream *stream, const char *keys)
+{
+ struct stream_in *in = (struct stream_in *)stream;
+
+ pthread_mutex_lock(&in->dev->lock);
+ pthread_mutex_lock(&in->lock);
+
+ char * params_str = device_get_parameters(in->profile, keys);
+
+ pthread_mutex_unlock(&in->lock);
+ pthread_mutex_unlock(&in->dev->lock);
+
+ return params_str;
+}
+
+static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
+{
+ return 0;
+}
+
+static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
+{
+ return 0;
+}
+
+static int in_set_gain(struct audio_stream_in *stream, float gain)
+{
+ return 0;
+}
+
+/* must be called with hw device and output stream mutexes locked */
+static int start_input_stream(struct stream_in *in)
+{
+ ALOGV("usb:audio_hw::start_input_stream(card:%d device:%d)",
+ in->profile->card, in->profile->device);
+
+ return proxy_open(&in->proxy);
+}
+
+/* TODO mutex stuff here (see out_write) */
+static ssize_t in_read(struct audio_stream_in *stream, void* buffer, size_t bytes)
+{
+ size_t num_read_buff_bytes = 0;
+ void * read_buff = buffer;
+ void * out_buff = buffer;
+
+ struct stream_in * in = (struct stream_in *)stream;
+
+ pthread_mutex_lock(&in->dev->lock);
+ pthread_mutex_lock(&in->lock);
+ if (in->standby) {
+ if (start_input_stream(in) != 0) {
+ pthread_mutex_unlock(&in->dev->lock);
+ goto err;
+ }
+ in->standby = false;
+ }
+ pthread_mutex_unlock(&in->dev->lock);
+
+
+ alsa_device_profile * profile = in->profile;
+
+ /*
+ * OK, we need to figure out how much data to read to be able to output the requested
+ * number of bytes in the HAL format (16-bit, stereo).
+ */
+ num_read_buff_bytes = bytes;
+ int num_device_channels = proxy_get_channel_count(&in->proxy);
+ int num_req_channels = 2; /* always, for now */
+
+ if (num_device_channels != num_req_channels) {
+ num_read_buff_bytes = (num_device_channels * num_read_buff_bytes) / num_req_channels;
+ }
+
+ enum pcm_format format = proxy_get_format(&in->proxy);
+ if (format == PCM_FORMAT_S24_3LE) {
+ /* 24-bit USB device */
+ num_read_buff_bytes = (3 * num_read_buff_bytes) / 2;
+ } else if (format == PCM_FORMAT_S32_LE) {
+ /* 32-bit USB device */
+ num_read_buff_bytes = num_read_buff_bytes * 2;
+ }
+
+ /* Setup/Realloc the conversion buffer (if necessary). */
+ if (num_read_buff_bytes != bytes) {
+ if (num_read_buff_bytes > in->conversion_buffer_size) {
+ /*TODO Remove this when AudioPolicyManger/AudioFlinger support arbitrary formats
+ (and do these conversions themselves) */
+ in->conversion_buffer_size = num_read_buff_bytes;
+ in->conversion_buffer = realloc(in->conversion_buffer, in->conversion_buffer_size);
+ }
+ read_buff = in->conversion_buffer;
+ }
+
+ if (proxy_read(&in->proxy, read_buff, num_read_buff_bytes) == 0) {
+ /*
+ * Do any conversions necessary to send the data in the format specified to/by the HAL
+ * (but different from the ALSA format), such as 24bit ->16bit, or 4chan -> 2chan.
+ */
+ if (format != PCM_FORMAT_S16_LE) {
+ /* we need to convert */
+ if (num_device_channels != num_req_channels) {
+ out_buff = read_buff;
+ }
+
+ if (format == PCM_FORMAT_S24_3LE) {
+ num_read_buff_bytes =
+ convert_24_3_to_16(read_buff, num_read_buff_bytes / 3, out_buff);
+ } else if (format == PCM_FORMAT_S32_LE) {
+ num_read_buff_bytes =
+ convert_32_to_16(read_buff, num_read_buff_bytes / 4, out_buff);
+ } else {
+ goto err;
+ }
+ }
+
+ if (num_device_channels != num_req_channels) {
+ // ALOGV("chans dev:%d req:%d", num_device_channels, num_req_channels);
+
+ out_buff = buffer;
+ /* Num Channels conversion */
+ if (num_device_channels != num_req_channels) {
+ audio_format_t audio_format = in_get_format(&(in->stream.common));
+ unsigned sample_size_in_bytes = audio_bytes_per_sample(audio_format);
+
+ num_read_buff_bytes =
+ adjust_channels(read_buff, num_device_channels,
+ out_buff, num_req_channels,
+ sample_size_in_bytes, num_read_buff_bytes);
+ }
+ }
+ }
+
+err:
+ pthread_mutex_unlock(&in->lock);
+
+ return num_read_buff_bytes;
+}
+
+static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
+{
+ return 0;
+}
+
+static int adev_open_input_stream(struct audio_hw_device *dev,
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ struct audio_config *config,
+ struct audio_stream_in **stream_in,
+ audio_input_flags_t flags __unused,
+ const char *address __unused,
+ audio_source_t source __unused)
+{
+ ALOGV("usb: in adev_open_input_stream() rate:%" PRIu32 ", chanMask:0x%" PRIX32 ", fmt:%" PRIu8,
+ config->sample_rate, config->channel_mask, config->format);
+
+ struct stream_in *in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
+ int ret = 0;
+
+ if (in == NULL)
+ return -ENOMEM;
+
+ /* setup function pointers */
+ in->stream.common.get_sample_rate = in_get_sample_rate;
+ in->stream.common.set_sample_rate = in_set_sample_rate;
+ in->stream.common.get_buffer_size = in_get_buffer_size;
+ in->stream.common.get_channels = in_get_channels;
+ in->stream.common.get_format = in_get_format;
+ in->stream.common.set_format = in_set_format;
+ in->stream.common.standby = in_standby;
+ in->stream.common.dump = in_dump;
+ in->stream.common.set_parameters = in_set_parameters;
+ in->stream.common.get_parameters = in_get_parameters;
+ in->stream.common.add_audio_effect = in_add_audio_effect;
+ in->stream.common.remove_audio_effect = in_remove_audio_effect;
+
+ in->stream.set_gain = in_set_gain;
+ in->stream.read = in_read;
+ in->stream.get_input_frames_lost = in_get_input_frames_lost;
+
+ in->dev = (struct audio_device *)dev;
+
+ in->profile = &in->dev->in_profile;
+
+ struct pcm_config proxy_config;
+
+ /* Rate */
+ if (config->sample_rate == 0) {
+ proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(in->profile);
+ } else if (profile_is_sample_rate_valid(in->profile, config->sample_rate)) {
+ proxy_config.rate = config->sample_rate;
+ } else {
+ proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(in->profile);
+ ret = -EINVAL;
+ }
+
+ /* Format */
+ /* until the framework supports format conversion, just take what it asks for
+ * i.e. AUDIO_FORMAT_PCM_16_BIT */
+ if (config->format == AUDIO_FORMAT_DEFAULT) {
+ /* just return AUDIO_FORMAT_PCM_16_BIT until the framework supports other input
+ * formats */
+ config->format = AUDIO_FORMAT_PCM_16_BIT;
+ proxy_config.format = PCM_FORMAT_S16_LE;
+ } else if (config->format == AUDIO_FORMAT_PCM_16_BIT) {
+ /* Always accept AUDIO_FORMAT_PCM_16_BIT until the framework supports other input
+ * formats */
+ proxy_config.format = PCM_FORMAT_S16_LE;
+ } else {
+ /* When the framework support other formats, validate here */
+ config->format = AUDIO_FORMAT_PCM_16_BIT;
+ proxy_config.format = PCM_FORMAT_S16_LE;
+ ret = -EINVAL;
+ }
+
+ if (config->channel_mask == AUDIO_CHANNEL_NONE) {
+ /* just return AUDIO_CHANNEL_IN_STEREO until the framework supports other input
+ * formats */
+ config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
+
+ } else if (config->channel_mask != AUDIO_CHANNEL_IN_STEREO) {
+ /* allow only stereo capture for now */
+ config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
+ ret = -EINVAL;
+ }
+ // proxy_config.channels = 0; /* don't change */
+ proxy_config.channels = profile_get_default_channel_count(in->profile);
+
+ proxy_prepare(&in->proxy, in->profile, &proxy_config);
+
+ in->standby = true;
+
+ in->conversion_buffer = NULL;
+ in->conversion_buffer_size = 0;
+
+ *stream_in = &in->stream;
+
+ return ret;
+}
+
+static void adev_close_input_stream(struct audio_hw_device *dev, struct audio_stream_in *stream)
+{
+ struct stream_in *in = (struct stream_in *)stream;
+
+ /* Close the pcm device */
+ in_standby(&stream->common);
+
+ free(in->conversion_buffer);
+
+ free(stream);
+}
+
+/*
+ * ADEV Functions
+ */
static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
{
return 0;
@@ -1136,375 +1036,6 @@
return -ENOSYS;
}
-static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
- const struct audio_config *config)
-{
- return 0;
-}
-
-/* Helper functions */
-static uint32_t in_get_sample_rate(const struct audio_stream *stream)
-{
- return cached_input_hardware_config.rate;
-}
-
-static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
-{
- return -ENOSYS;
-}
-
-static size_t in_get_buffer_size(const struct audio_stream *stream)
-{
- size_t buffer_size = cached_input_hardware_config.period_size *
- audio_stream_in_frame_size((const struct audio_stream_in *)stream);
- ALOGV("usb: in_get_buffer_size() = %zu", buffer_size);
- return buffer_size;
-}
-
-static uint32_t in_get_channels(const struct audio_stream *stream)
-{
- // just report stereo for now
- return AUDIO_CHANNEL_IN_STEREO;
-}
-
-static audio_format_t in_get_format(const struct audio_stream *stream)
-{
- const struct stream_in * in_stream = (const struct stream_in *)stream;
-
- ALOGV("in_get_format() = %d -> %d", in_stream->input_framework_format,
- audio_format_from_pcm_format(in_stream->input_framework_format));
- /* return audio_format_from_pcm_format(cached_input_hardware_config.format); */
- return audio_format_from_pcm_format(in_stream->input_framework_format);
-}
-
-static int in_set_format(struct audio_stream *stream, audio_format_t format)
-{
- return -ENOSYS;
-}
-
-static int in_standby(struct audio_stream *stream)
-{
- struct stream_in *in = (struct stream_in *) stream;
-
- pthread_mutex_lock(&in->dev->lock);
- pthread_mutex_lock(&in->lock);
-
- if (!in->standby) {
- pcm_close(in->pcm);
- in->pcm = NULL;
- in->standby = true;
- }
-
- pthread_mutex_unlock(&in->lock);
- pthread_mutex_unlock(&in->dev->lock);
-
- return 0;
-}
-
-static int in_dump(const struct audio_stream *stream, int fd)
-{
- return 0;
-}
-
-static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
-{
- ALOGV("usb: audio_hw::in in_set_parameters() keys:%s", kvpairs);
-
- struct stream_in *in = (struct stream_in *)stream;
- struct str_parms *parms;
- char value[32];
- int param_val;
- int routing = 0;
- int ret_value = 0;
-
- parms = str_parms_create_str(kvpairs);
- pthread_mutex_lock(&in->dev->lock);
- pthread_mutex_lock(&in->lock);
-
- bool recache_device_params = false;
-
- // Card/Device
- param_val = str_parms_get_str(parms, "card", value, sizeof(value));
- if (param_val >= 0) {
- in->profile->card = atoi(value);
- recache_device_params = true;
- }
-
- param_val = str_parms_get_str(parms, "device", value, sizeof(value));
- if (param_val >= 0) {
- in->profile->device = atoi(value);
- recache_device_params = true;
- }
-
- if (recache_device_params && in->profile->card >= 0 && in->profile->device >= 0) {
- ret_value = read_alsa_device_config(in->profile, &cached_input_hardware_config);
- input_hardware_config_is_cached = (ret_value == 0);
- }
-
- pthread_mutex_unlock(&in->lock);
- pthread_mutex_unlock(&in->dev->lock);
- str_parms_destroy(parms);
-
- return ret_value;
-}
-
-static char * in_get_parameters(const struct audio_stream *stream, const char *keys) {
- ALOGV("usb:audio_hw::in in_get_parameters() keys:%s", keys);
-
- struct stream_in *in = (struct stream_in *)stream;
- pthread_mutex_lock(&in->dev->lock);
- pthread_mutex_lock(&in->lock);
-
- char * params_str = device_get_parameters(in->profile, keys);
-
- pthread_mutex_unlock(&in->lock);
- pthread_mutex_unlock(&in->dev->lock);
-
- return params_str;
-}
-
-static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
-{
- return 0;
-}
-
-static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
-{
- return 0;
-}
-
-static int in_set_gain(struct audio_stream_in *stream, float gain)
-{
- return 0;
-}
-
-/* must be called with hw device and output stream mutexes locked */
-static int start_input_stream(struct stream_in *in) {
- int return_val = 0;
-
- ALOGV("usb:audio_hw::start_input_stream(card:%d device:%d)",
- in->profile->card, in->profile->device);
-
- in->pcm = pcm_open(in->profile->card, in->profile->device, PCM_IN,
- &cached_input_hardware_config);
- if (in->pcm == NULL) {
- ALOGE("usb:audio_hw pcm_open() in->pcm == NULL");
- return -ENOMEM;
- }
-
- if (in->pcm && !pcm_is_ready(in->pcm)) {
- ALOGE("usb:audio_hw audio_hw pcm_open() failed: %s", pcm_get_error(in->pcm));
- pcm_close(in->pcm);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-/* TODO mutex stuff here (see out_write) */
-static ssize_t in_read(struct audio_stream_in *stream, void* buffer, size_t bytes)
-{
- size_t num_read_buff_bytes = 0;
- void * read_buff = buffer;
- void * out_buff = buffer;
-
- struct stream_in * in = (struct stream_in *) stream;
-
- pthread_mutex_lock(&in->dev->lock);
- pthread_mutex_lock(&in->lock);
-
- if (in->standby) {
- if (start_input_stream(in) != 0) {
- goto err;
- }
- in->standby = false;
- }
-
- // OK, we need to figure out how much data to read to be able to output the requested
- // number of bytes in the HAL format (16-bit, stereo).
- num_read_buff_bytes = bytes;
- int num_device_channels = cached_input_hardware_config.channels;
- int num_req_channels = 2; /* always, for now */
-
- if (num_device_channels != num_req_channels) {
- num_read_buff_bytes = (num_device_channels * num_read_buff_bytes) / num_req_channels;
- }
-
- /* Assume (for now) that in->input_framework_format == PCM_FORMAT_S16_LE */
- if (cached_input_hardware_config.format == PCM_FORMAT_S24_3LE) {
- /* 24-bit USB device */
- num_read_buff_bytes = (3 * num_read_buff_bytes) / 2;
- } else if (cached_input_hardware_config.format == PCM_FORMAT_S32_LE) {
- /* 32-bit USB device */
- num_read_buff_bytes = num_read_buff_bytes * 2;
- }
-
- // Setup/Realloc the conversion buffer (if necessary).
- if (num_read_buff_bytes != bytes) {
- if (num_read_buff_bytes > in->conversion_buffer_size) {
- /*TODO Remove this when AudioPolicyManger/AudioFlinger support arbitrary formats
- (and do these conversions themselves) */
- in->conversion_buffer_size = num_read_buff_bytes;
- in->conversion_buffer = realloc(in->conversion_buffer, in->conversion_buffer_size);
- }
- read_buff = in->conversion_buffer;
- }
-
- if (pcm_read(in->pcm, read_buff, num_read_buff_bytes) == 0) {
- /*
- * Do any conversions necessary to send the data in the format specified to/by the HAL
- * (but different from the ALSA format), such as 24bit ->16bit, or 4chan -> 2chan.
- */
- if (cached_input_hardware_config.format != PCM_FORMAT_S16_LE) {
- // we need to convert
- if (num_device_channels != num_req_channels) {
- out_buff = read_buff;
- }
-
- if (cached_input_hardware_config.format == PCM_FORMAT_S24_3LE) {
- num_read_buff_bytes =
- convert_24_3_to_16(read_buff, num_read_buff_bytes / 3, out_buff);
- } else if (cached_input_hardware_config.format == PCM_FORMAT_S32_LE) {
- num_read_buff_bytes =
- convert_32_to_16(read_buff, num_read_buff_bytes / 4, out_buff);
- }
- else {
- goto err;
- }
- }
-
- if (num_device_channels != num_req_channels) {
- out_buff = buffer;
- /* Num Channels conversion */
- if (num_device_channels != num_req_channels) {
- audio_format_t audio_format = in_get_format(&(in->stream.common));
- unsigned sample_size_in_bytes = audio_bytes_per_sample(audio_format);
-
- num_read_buff_bytes =
- adjust_channels(read_buff, num_device_channels,
- out_buff, num_req_channels,
- sample_size_in_bytes, num_read_buff_bytes);
- }
- }
- }
-
-err:
- pthread_mutex_unlock(&in->lock);
- pthread_mutex_unlock(&in->dev->lock);
-
- return num_read_buff_bytes;
-}
-
-static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
-{
- return 0;
-}
-
-static int adev_open_input_stream(struct audio_hw_device *dev,
- audio_io_handle_t handle,
- audio_devices_t devices,
- struct audio_config *config,
- struct audio_stream_in **stream_in,
- audio_input_flags_t flags __unused)
-{
- ALOGV("usb: in adev_open_input_stream() rate:%" PRIu32 ", chanMask:0x%" PRIX32 ", fmt:%" PRIu8,
- config->sample_rate, config->channel_mask, config->format);
-
- struct stream_in *in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
- int ret = 0;
-
- if (in == NULL)
- return -ENOMEM;
-
- // setup function pointers
- in->stream.common.get_sample_rate = in_get_sample_rate;
- in->stream.common.set_sample_rate = in_set_sample_rate;
- in->stream.common.get_buffer_size = in_get_buffer_size;
- in->stream.common.get_channels = in_get_channels;
- in->stream.common.get_format = in_get_format;
- in->stream.common.set_format = in_set_format;
- in->stream.common.standby = in_standby;
- in->stream.common.dump = in_dump;
- in->stream.common.set_parameters = in_set_parameters;
- in->stream.common.get_parameters = in_get_parameters;
- in->stream.common.add_audio_effect = in_add_audio_effect;
- in->stream.common.remove_audio_effect = in_remove_audio_effect;
-
- in->stream.set_gain = in_set_gain;
- in->stream.read = in_read;
- in->stream.get_input_frames_lost = in_get_input_frames_lost;
-
- in->input_framework_format = PCM_FORMAT_S16_LE;
-
- in->dev = (struct audio_device *)dev;
-
- in->profile = &(in->dev->in_profile);
- in->profile->direction = PCM_IN;
-
- if (!input_hardware_config_is_cached) {
- // just return defaults until we can actually query the device.
- cached_input_hardware_config = default_alsa_in_config;
- }
-
- /* Rate */
- /* TODO Check that the requested rate is valid for the connected device */
- if (config->sample_rate == 0) {
- config->sample_rate = cached_input_hardware_config.rate;
- } else {
- cached_input_hardware_config.rate = config->sample_rate;
- }
-
- /* Format */
- /* until the framework supports format conversion, just take what it asks for
- * i.e. AUDIO_FORMAT_PCM_16_BIT */
- /* config->format = audio_format_from_pcm_format(cached_input_hardware_config.format); */
- if (config->format == AUDIO_FORMAT_DEFAULT) {
- /* just return AUDIO_FORMAT_PCM_16_BIT until the framework supports other input
- * formats */
- config->format = AUDIO_FORMAT_PCM_16_BIT;
- } else if (config->format == AUDIO_FORMAT_PCM_16_BIT) {
- /* Always accept AUDIO_FORMAT_PCM_16_BIT until the framework supports other input
- * formats */
- } else {
- /* When the framework support other formats, validate here */
- config->format = AUDIO_FORMAT_PCM_16_BIT;
- ret = -EINVAL;
- }
-
- /* don't change the cached_input_hardware_config, we will open it as what it is and
- * convert as necessary */
- if (config->channel_mask == AUDIO_CHANNEL_NONE) {
- /* just return AUDIO_CHANNEL_IN_STEREO until the framework supports other input
- * formats */
- config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
- } else if (config->channel_mask != AUDIO_CHANNEL_IN_STEREO) {
- /* allow only stereo capture for now */
- config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
- ret = -EINVAL;
- }
-
- in->standby = true;
-
- in->conversion_buffer = NULL;
- in->conversion_buffer_size = 0;
-
- *stream_in = &in->stream;
-
- return ret;
-}
-
-static void adev_close_input_stream(struct audio_hw_device *dev, struct audio_stream_in *stream)
-{
- struct stream_in *in = (struct stream_in *)stream;
-
- // Close the pcm device
- in_standby(&stream->common);
-
- free(in->conversion_buffer);
-
- free(stream);
-}
-
static int adev_dump(const audio_hw_device_t *device, int fd)
{
return 0;
@@ -1515,9 +1046,6 @@
struct audio_device *adev = (struct audio_device *)device;
free(device);
- output_hardware_config_is_cached = false;
- input_hardware_config_is_cached = false;
-
return 0;
}
@@ -1530,9 +1058,12 @@
if (!adev)
return -ENOMEM;
+ profile_init(&adev->out_profile, PCM_OUT);
+ profile_init(&adev->in_profile, PCM_IN);
+
adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
- adev->hw_device.common.module = (struct hw_module_t *) module;
+ adev->hw_device.common.module = (struct hw_module_t *)module;
adev->hw_device.common.close = adev_close;
adev->hw_device.init_check = adev_init_check;
diff --git a/modules/usbaudio/format.c b/modules/usbaudio/format.c
new file mode 100644
index 0000000..6aac1d3
--- /dev/null
+++ b/modules/usbaudio/format.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "usb_profile"
+/*#define LOG_NDEBUG 0*/
+
+#include "format.h"
+
+#include <tinyalsa/asoundlib.h>
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+/*
+ * Maps from bit position in pcm_mask to AUDIO_ format constants.
+ */
+static audio_format_t const format_value_map[] = {
+ AUDIO_FORMAT_PCM_8_BIT, /* 00 - SNDRV_PCM_FORMAT_S8 */
+ AUDIO_FORMAT_PCM_8_BIT, /* 01 - SNDRV_PCM_FORMAT_U8 */
+ AUDIO_FORMAT_PCM_16_BIT, /* 02 - SNDRV_PCM_FORMAT_S16_LE */
+ AUDIO_FORMAT_INVALID, /* 03 - SNDRV_PCM_FORMAT_S16_BE */
+ AUDIO_FORMAT_INVALID, /* 04 - SNDRV_PCM_FORMAT_U16_LE */
+ AUDIO_FORMAT_INVALID, /* 05 - SNDRV_PCM_FORMAT_U16_BE */
+ AUDIO_FORMAT_INVALID, /* 06 - SNDRV_PCM_FORMAT_S24_LE */
+ AUDIO_FORMAT_INVALID, /* 07 - SNDRV_PCM_FORMAT_S24_BE */
+ AUDIO_FORMAT_INVALID, /* 08 - SNDRV_PCM_FORMAT_U24_LE */
+ AUDIO_FORMAT_INVALID, /* 09 - SNDRV_PCM_FORMAT_U24_BE */
+ AUDIO_FORMAT_PCM_32_BIT, /* 10 - SNDRV_PCM_FORMAT_S32_LE */
+ AUDIO_FORMAT_INVALID, /* 11 - SNDRV_PCM_FORMAT_S32_BE */
+ AUDIO_FORMAT_INVALID, /* 12 - SNDRV_PCM_FORMAT_U32_LE */
+ AUDIO_FORMAT_INVALID, /* 13 - SNDRV_PCM_FORMAT_U32_BE */
+ AUDIO_FORMAT_PCM_FLOAT, /* 14 - SNDRV_PCM_FORMAT_FLOAT_LE */
+ AUDIO_FORMAT_INVALID, /* 15 - SNDRV_PCM_FORMAT_FLOAT_BE */
+ AUDIO_FORMAT_INVALID, /* 16 - SNDRV_PCM_FORMAT_FLOAT64_LE */
+ AUDIO_FORMAT_INVALID, /* 17 - SNDRV_PCM_FORMAT_FLOAT64_BE */
+ AUDIO_FORMAT_INVALID, /* 18 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE */
+ AUDIO_FORMAT_INVALID, /* 19 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE */
+ AUDIO_FORMAT_INVALID, /* 20 - SNDRV_PCM_FORMAT_MU_LAW */
+ AUDIO_FORMAT_INVALID, /* 21 - SNDRV_PCM_FORMAT_A_LAW */
+ AUDIO_FORMAT_INVALID, /* 22 - SNDRV_PCM_FORMAT_IMA_ADPCM */
+ AUDIO_FORMAT_INVALID, /* 23 - SNDRV_PCM_FORMAT_MPEG */
+ AUDIO_FORMAT_INVALID, /* 24 - SNDRV_PCM_FORMAT_GSM */
+ AUDIO_FORMAT_INVALID, /* 25 -> 30 (not assigned) */
+ AUDIO_FORMAT_INVALID,
+ AUDIO_FORMAT_INVALID,
+ AUDIO_FORMAT_INVALID,
+ AUDIO_FORMAT_INVALID,
+ AUDIO_FORMAT_INVALID,
+ AUDIO_FORMAT_INVALID, /* 31 - SNDRV_PCM_FORMAT_SPECIAL */
+ AUDIO_FORMAT_PCM_24_BIT_PACKED, /* 32 - SNDRV_PCM_FORMAT_S24_3LE */
+ AUDIO_FORMAT_INVALID, /* 33 - SNDRV_PCM_FORMAT_S24_3BE */
+ AUDIO_FORMAT_INVALID, /* 34 - SNDRV_PCM_FORMAT_U24_3LE */
+ AUDIO_FORMAT_INVALID, /* 35 - SNDRV_PCM_FORMAT_U24_3BE */
+ AUDIO_FORMAT_INVALID, /* 36 - SNDRV_PCM_FORMAT_S20_3LE */
+ AUDIO_FORMAT_INVALID, /* 37 - SNDRV_PCM_FORMAT_S20_3BE */
+ AUDIO_FORMAT_INVALID, /* 38 - SNDRV_PCM_FORMAT_U20_3LE */
+ AUDIO_FORMAT_INVALID, /* 39 - SNDRV_PCM_FORMAT_U20_3BE */
+ AUDIO_FORMAT_INVALID, /* 40 - SNDRV_PCM_FORMAT_S18_3LE */
+ AUDIO_FORMAT_INVALID, /* 41 - SNDRV_PCM_FORMAT_S18_3BE */
+ AUDIO_FORMAT_INVALID, /* 42 - SNDRV_PCM_FORMAT_U18_3LE */
+ AUDIO_FORMAT_INVALID, /* 43 - SNDRV_PCM_FORMAT_U18_3BE */
+ AUDIO_FORMAT_INVALID, /* 44 - SNDRV_PCM_FORMAT_G723_24 */
+ AUDIO_FORMAT_INVALID, /* 45 - SNDRV_PCM_FORMAT_G723_24_1B */
+ AUDIO_FORMAT_INVALID, /* 46 - SNDRV_PCM_FORMAT_G723_40 */
+ AUDIO_FORMAT_INVALID, /* 47 - SNDRV_PCM_FORMAT_G723_40_1B */
+ AUDIO_FORMAT_INVALID, /* 48 - SNDRV_PCM_FORMAT_DSD_U8 */
+ AUDIO_FORMAT_INVALID /* 49 - SNDRV_PCM_FORMAT_DSD_U16_LE */
+};
+
+audio_format_t get_format_for_mask(struct pcm_mask* mask)
+{
+ int num_slots = sizeof(mask->bits) / sizeof(mask->bits[0]);
+ int bits_per_slot = sizeof(mask->bits[0]) * 8;
+
+ int table_size = sizeof(format_value_map) / sizeof(format_value_map[0]);
+
+ int slot_index, bit_index, table_index;
+ table_index = 0;
+ int num_written = 0;
+ for (slot_index = 0; slot_index < num_slots; slot_index++) {
+ unsigned bit_mask = 1;
+ for (bit_index = 0; bit_index < bits_per_slot; bit_index++) {
+ /* don't return b-bit formats even if they are supported */
+ if (table_index >= 2 && (mask->bits[slot_index] & bit_mask) != 0) {
+ /* just return the first one */
+ return table_index < table_size
+ ? format_value_map[table_index]
+ : AUDIO_FORMAT_INVALID;
+ }
+ bit_mask <<= 1;
+ table_index++;
+ }
+ }
+
+ return AUDIO_FORMAT_INVALID;
+}
+
+/*
+ * Maps from bit position in pcm_mask to PCM_ format constants.
+ */
+int8_t const pcm_format_value_map[50] = {
+ PCM_FORMAT_S8, /* 00 - SNDRV_PCM_FORMAT_S8 */
+ PCM_FORMAT_INVALID, /* 01 - SNDRV_PCM_FORMAT_U8 */
+ PCM_FORMAT_S16_LE, /* 02 - SNDRV_PCM_FORMAT_S16_LE */
+ PCM_FORMAT_INVALID, /* 03 - SNDRV_PCM_FORMAT_S16_BE */
+ PCM_FORMAT_INVALID, /* 04 - SNDRV_PCM_FORMAT_U16_LE */
+ PCM_FORMAT_INVALID, /* 05 - SNDRV_PCM_FORMAT_U16_BE */
+ PCM_FORMAT_S24_3LE, /* 06 - SNDRV_PCM_FORMAT_S24_LE */
+ PCM_FORMAT_INVALID, /* 07 - SNDRV_PCM_FORMAT_S24_BE */
+ PCM_FORMAT_INVALID, /* 08 - SNDRV_PCM_FORMAT_U24_LE */
+ PCM_FORMAT_INVALID, /* 09 - SNDRV_PCM_FORMAT_U24_BE */
+ PCM_FORMAT_S32_LE, /* 10 - SNDRV_PCM_FORMAT_S32_LE */
+ PCM_FORMAT_INVALID, /* 11 - SNDRV_PCM_FORMAT_S32_BE */
+ PCM_FORMAT_INVALID, /* 12 - SNDRV_PCM_FORMAT_U32_LE */
+ PCM_FORMAT_INVALID, /* 13 - SNDRV_PCM_FORMAT_U32_BE */
+ PCM_FORMAT_INVALID, /* 14 - SNDRV_PCM_FORMAT_FLOAT_LE */
+ PCM_FORMAT_INVALID, /* 15 - SNDRV_PCM_FORMAT_FLOAT_BE */
+ PCM_FORMAT_INVALID, /* 16 - SNDRV_PCM_FORMAT_FLOAT64_LE */
+ PCM_FORMAT_INVALID, /* 17 - SNDRV_PCM_FORMAT_FLOAT64_BE */
+ PCM_FORMAT_INVALID, /* 18 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE */
+ PCM_FORMAT_INVALID, /* 19 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE */
+ PCM_FORMAT_INVALID, /* 20 - SNDRV_PCM_FORMAT_MU_LAW */
+ PCM_FORMAT_INVALID, /* 21 - SNDRV_PCM_FORMAT_A_LAW */
+ PCM_FORMAT_INVALID, /* 22 - SNDRV_PCM_FORMAT_IMA_ADPCM */
+ PCM_FORMAT_INVALID, /* 23 - SNDRV_PCM_FORMAT_MPEG */
+ PCM_FORMAT_INVALID, /* 24 - SNDRV_PCM_FORMAT_GSM */
+ PCM_FORMAT_INVALID, /* 25 -> 30 (not assigned) */
+ PCM_FORMAT_INVALID,
+ PCM_FORMAT_INVALID,
+ PCM_FORMAT_INVALID,
+ PCM_FORMAT_INVALID,
+ PCM_FORMAT_INVALID,
+ PCM_FORMAT_INVALID, /* 31 - SNDRV_PCM_FORMAT_SPECIAL */
+ PCM_FORMAT_S24_3LE, /* 32 - SNDRV_PCM_FORMAT_S24_3LE */ /* ??? */
+ PCM_FORMAT_INVALID, /* 33 - SNDRV_PCM_FORMAT_S24_3BE */
+ PCM_FORMAT_INVALID, /* 34 - SNDRV_PCM_FORMAT_U24_3LE */
+ PCM_FORMAT_INVALID, /* 35 - SNDRV_PCM_FORMAT_U24_3BE */
+ PCM_FORMAT_INVALID, /* 36 - SNDRV_PCM_FORMAT_S20_3LE */
+ PCM_FORMAT_INVALID, /* 37 - SNDRV_PCM_FORMAT_S20_3BE */
+ PCM_FORMAT_INVALID, /* 38 - SNDRV_PCM_FORMAT_U20_3LE */
+ PCM_FORMAT_INVALID, /* 39 - SNDRV_PCM_FORMAT_U20_3BE */
+ PCM_FORMAT_INVALID, /* 40 - SNDRV_PCM_FORMAT_S18_3LE */
+ PCM_FORMAT_INVALID, /* 41 - SNDRV_PCM_FORMAT_S18_3BE */
+ PCM_FORMAT_INVALID, /* 42 - SNDRV_PCM_FORMAT_U18_3LE */
+ PCM_FORMAT_INVALID, /* 43 - SNDRV_PCM_FORMAT_U18_3BE */
+ PCM_FORMAT_INVALID, /* 44 - SNDRV_PCM_FORMAT_G723_24 */
+ PCM_FORMAT_INVALID, /* 45 - SNDRV_PCM_FORMAT_G723_24_1B */
+ PCM_FORMAT_INVALID, /* 46 - SNDRV_PCM_FORMAT_G723_40 */
+ PCM_FORMAT_INVALID, /* 47 - SNDRV_PCM_FORMAT_G723_40_1B */
+ PCM_FORMAT_INVALID, /* 48 - SNDRV_PCM_FORMAT_DSD_U8 */
+ PCM_FORMAT_INVALID /* 49 - SNDRV_PCM_FORMAT_DSD_U16_LE */
+};
+
+/*
+ * Scans the provided format mask and returns the first non-8 bit sample
+ * format supported by the devices.
+ */
+enum pcm_format get_pcm_format_for_mask(struct pcm_mask* mask)
+{
+ int num_slots = ARRAY_SIZE(mask->bits);
+ int bits_per_slot = sizeof(mask->bits[0]) * 8;
+
+ int table_size = ARRAY_SIZE(pcm_format_value_map);
+
+ int slot_index, bit_index, table_index;
+ table_index = 0;
+ int num_written = 0;
+ for (slot_index = 0; slot_index < num_slots && table_index < table_size; slot_index++) {
+ unsigned bit_mask = 1;
+ for (bit_index = 0; bit_index < bits_per_slot && table_index < table_size; bit_index++) {
+ /* skip any 8-bit formats */
+ if (table_index >= 2 && (mask->bits[slot_index] & bit_mask) != 0) {
+ /* just return the first one which will be at least 16-bit */
+ return (int)pcm_format_value_map[table_index];
+ }
+ bit_mask <<= 1;
+ table_index++;
+ }
+ }
+
+ return PCM_FORMAT_INVALID;
+}
diff --git a/modules/usbaudio/format.h b/modules/usbaudio/format.h
new file mode 100644
index 0000000..e23935e
--- /dev/null
+++ b/modules/usbaudio/format.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_FORMAT_H
+#define ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_FORMAT_H
+
+#include <system/audio.h>
+
+#include <tinyalsa/asoundlib.h>
+
+audio_format_t get_format_for_mask(struct pcm_mask* mask);
+enum pcm_format get_pcm_format_for_mask(struct pcm_mask* mask);
+
+#endif /* ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_FORMAT_H */
diff --git a/modules/usbaudio/logging.c b/modules/usbaudio/logging.c
new file mode 100644
index 0000000..0a05511
--- /dev/null
+++ b/modules/usbaudio/logging.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "usb_logging"
+/*#define LOG_NDEBUG 0*/
+
+#include <string.h>
+
+#include <log/log.h>
+
+#include "logging.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+/*
+ * Logging
+ */
+void log_pcm_mask(const char* mask_name, struct pcm_mask* mask)
+{
+ const size_t num_slots = ARRAY_SIZE(mask->bits);
+ const size_t bits_per_slot = (sizeof(mask->bits[0]) * 8);
+ const size_t chars_per_slot = (bits_per_slot + 1); /* comma */
+
+ const size_t BUFF_SIZE =
+ (num_slots * chars_per_slot + 2 + 1); /* brackets and null-terminator */
+ char buff[BUFF_SIZE];
+ buff[0] = '\0';
+
+ size_t slot_index, bit_index;
+ strcat(buff, "[");
+ for (slot_index = 0; slot_index < num_slots; slot_index++) {
+ unsigned bit_mask = 1;
+ for (bit_index = 0; bit_index < bits_per_slot; bit_index++) {
+ strcat(buff, (mask->bits[slot_index] & bit_mask) != 0 ? "1" : "0");
+ bit_mask <<= 1;
+ }
+ if (slot_index < num_slots - 1) {
+ strcat(buff, ",");
+ }
+ }
+ strcat(buff, "]");
+
+ ALOGV("%s: mask:%s", mask_name, buff);
+}
+
+void log_pcm_params(struct pcm_params * alsa_hw_params)
+{
+ ALOGV("usb:audio_hw - PCM_PARAM_SAMPLE_BITS min:%u, max:%u",
+ pcm_params_get_min(alsa_hw_params, PCM_PARAM_SAMPLE_BITS),
+ pcm_params_get_max(alsa_hw_params, PCM_PARAM_SAMPLE_BITS));
+ ALOGV("usb:audio_hw - PCM_PARAM_FRAME_BITS min:%u, max:%u",
+ pcm_params_get_min(alsa_hw_params, PCM_PARAM_FRAME_BITS),
+ pcm_params_get_max(alsa_hw_params, PCM_PARAM_FRAME_BITS));
+ log_pcm_mask("PCM_PARAM_FORMAT",
+ pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT));
+ log_pcm_mask("PCM_PARAM_SUBFORMAT",
+ pcm_params_get_mask(alsa_hw_params, PCM_PARAM_SUBFORMAT));
+ ALOGV("usb:audio_hw - PCM_PARAM_CHANNELS min:%u, max:%u",
+ pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS),
+ pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS));
+ ALOGV("usb:audio_hw - PCM_PARAM_RATE min:%u, max:%u",
+ pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE),
+ pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE));
+ ALOGV("usb:audio_hw - PCM_PARAM_PERIOD_TIME min:%u, max:%u",
+ pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_TIME),
+ pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_TIME));
+ ALOGV("usb:audio_hw - PCM_PARAM_PERIOD_SIZE min:%u, max:%u",
+ pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_SIZE),
+ pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_SIZE));
+ ALOGV("usb:audio_hw - PCM_PARAM_PERIOD_BYTES min:%u, max:%u",
+ pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIOD_BYTES),
+ pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIOD_BYTES));
+ ALOGV("usb:audio_hw - PCM_PARAM_PERIODS min:%u, max:%u",
+ pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS),
+ pcm_params_get_max(alsa_hw_params, PCM_PARAM_PERIODS));
+ ALOGV("usb:audio_hw - PCM_PARAM_BUFFER_TIME min:%u, max:%u",
+ pcm_params_get_min(alsa_hw_params, PCM_PARAM_BUFFER_TIME),
+ pcm_params_get_max(alsa_hw_params, PCM_PARAM_BUFFER_TIME));
+ ALOGV("usb:audio_hw - PCM_PARAM_BUFFER_SIZE min:%u, max:%u",
+ pcm_params_get_min(alsa_hw_params, PCM_PARAM_BUFFER_SIZE),
+ pcm_params_get_max(alsa_hw_params, PCM_PARAM_BUFFER_SIZE));
+ ALOGV("usb:audio_hw - PCM_PARAM_BUFFER_BYTES min:%u, max:%u",
+ pcm_params_get_min(alsa_hw_params, PCM_PARAM_BUFFER_BYTES),
+ pcm_params_get_max(alsa_hw_params, PCM_PARAM_BUFFER_BYTES));
+ ALOGV("usb:audio_hw - PCM_PARAM_TICK_TIME min:%u, max:%u",
+ pcm_params_get_min(alsa_hw_params, PCM_PARAM_TICK_TIME),
+ pcm_params_get_max(alsa_hw_params, PCM_PARAM_TICK_TIME));
+}
+
+void log_pcm_config(struct pcm_config * config, const char* label) {
+ ALOGV("log_pcm_config() - %s", label);
+ ALOGV(" channels:%d", config->channels);
+ ALOGV(" rate:%d", config->rate);
+ ALOGV(" period_size:%d", config->period_size);
+ ALOGV(" period_count:%d", config->period_count);
+ ALOGV(" format:%d", config->format);
+#if 0
+ /* Values to use for the ALSA start, stop and silence thresholds. Setting
+ * any one of these values to 0 will cause the default tinyalsa values to be
+ * used instead. Tinyalsa defaults are as follows.
+ *
+ * start_threshold : period_count * period_size
+ * stop_threshold : period_count * period_size
+ * silence_threshold : 0
+ */
+ unsigned int start_threshold;
+ unsigned int stop_threshold;
+ unsigned int silence_threshold;
+
+ /* Minimum number of frames available before pcm_mmap_write() will actually
+ * write into the kernel buffer. Only used if the stream is opened in mmap mode
+ * (pcm_open() called with PCM_MMAP flag set). Use 0 for default.
+ */
+ int avail_min;
+#endif
+}
diff --git a/modules/usbaudio/logging.h b/modules/usbaudio/logging.h
new file mode 100644
index 0000000..b5640ed
--- /dev/null
+++ b/modules/usbaudio/logging.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_LOGGING_H
+#define ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_LOGGING_H
+
+#include <tinyalsa/asoundlib.h>
+
+void log_pcm_mask(const char* mask_name, struct pcm_mask* mask);
+void log_pcm_params(struct pcm_params * alsa_hw_params);
+void log_pcm_config(struct pcm_config * config, const char* label);
+
+#endif /* ANDROID_HARDWARE_LIBHARDWARE_MODULES_USBAUDIO_LOGGING_H */
diff --git a/tests/camera2/CameraBurstTests.cpp b/tests/camera2/CameraBurstTests.cpp
index 65ff460..58763de 100644
--- a/tests/camera2/CameraBurstTests.cpp
+++ b/tests/camera2/CameraBurstTests.cpp
@@ -311,7 +311,8 @@
* $ setenv CAMERA2_TEST_VARIABLE_BURST_DUMP_FRAMES 1
* $ /data/nativetest/camera2_test/camera2_test --gtest_filter="*VariableBurst"
*/
-TEST_F(CameraBurstTest, VariableBurst) {
+// Disable this test for now, as we need cleanup the usage of the deprecated tag quite a bit.
+TEST_F(CameraBurstTest, DISABLED_VariableBurst) {
TEST_EXTENSION_FORKING_INIT;
diff --git a/tests/camera2/CameraModuleFixture.h b/tests/camera2/CameraModuleFixture.h
index acf41e1..0bb0e7d 100644
--- a/tests/camera2/CameraModuleFixture.h
+++ b/tests/camera2/CameraModuleFixture.h
@@ -97,6 +97,8 @@
*device = new Camera2Device(cameraID);
break;
case CAMERA_DEVICE_API_VERSION_3_0:
+ case CAMERA_DEVICE_API_VERSION_3_1:
+ case CAMERA_DEVICE_API_VERSION_3_2:
*device = new Camera3Device(cameraID);
break;
default:
diff --git a/tests/camera2/CameraMultiStreamTests.cpp b/tests/camera2/CameraMultiStreamTests.cpp
index 536b656..066f4ee 100644
--- a/tests/camera2/CameraMultiStreamTests.cpp
+++ b/tests/camera2/CameraMultiStreamTests.cpp
@@ -467,7 +467,8 @@
*
* 2. Manual control(gain/exposure) of mutiple burst capture.
*/
-TEST_F(CameraMultiStreamTest, MultiBurst) {
+// Disable this test for now, as we need cleanup the usage of the deprecated tag quite a bit.
+TEST_F(CameraMultiStreamTest, DISABLED_MultiBurst) {
TEST_EXTENSION_FORKING_INIT;
diff --git a/tests/hardware/struct-offset.cpp b/tests/hardware/struct-offset.cpp
index 2354408..a7ff797 100644
--- a/tests/hardware/struct-offset.cpp
+++ b/tests/hardware/struct-offset.cpp
@@ -169,7 +169,8 @@
CHECK_MEMBER_AT(hwc_composer_device_1_t, getDisplayAttributes, 96, 184);
CHECK_MEMBER_AT(hwc_composer_device_1_t, getActiveConfig, 100, 192);
CHECK_MEMBER_AT(hwc_composer_device_1_t, setActiveConfig, 104, 200);
- CHECK_MEMBER_AT(hwc_composer_device_1_t, reserved_proc, 108, 208);
+ CHECK_MEMBER_AT(hwc_composer_device_1_t, setCursorPositionAsync, 108, 208);
+ CHECK_MEMBER_AT(hwc_composer_device_1_t, reserved_proc, 112, 216);
//Types defined in gralloc.h
CHECK_MEMBER_AT(gralloc_module_t, common, 0, 0);