gbsim: Add initial i2s support.

Message ID 1427846138-19824-1-git-send-email-john.stultz@linaro.org
State New
Headers show

Commit Message

John Stultz March 31, 2015, 11:55 p.m.
Add initial i2s support. This only supports I2S SEND_DATA and some
simple I2S mgmt calls. More interesting mgmt calls that actually
provide data will be implemented in later patches.

Cc: Alex Elder <alex.elder@linaro.org>
Cc: Greg Kroah-Hartman <greg@kroah.com>
Cc: mark greer <mark.greer@animalcreek.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
 Makefile |    2 +-
 cport.c  |   13 +++++
 gbsim.h  |    4 ++
 i2s.c    |  177 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 main.c   |    1 +
 5 files changed, 196 insertions(+), 1 deletion(-)
 create mode 100644 i2s.c

Patch

diff --git a/Makefile b/Makefile
index 122530b..14f468f 100644
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,7 @@  INCS = -I$(GBDIR)
 LFLAGS = 
 LIBS = -lpthread -lusbg -lsoc
 
-SRCS = main.c gadget.c functionfs.c inotify.c manifest.c cport.c i2c.c gpio.c pwm.c
+SRCS = main.c gadget.c functionfs.c inotify.c manifest.c cport.c i2c.c gpio.c pwm.c i2s.c
 OBJS = $(SRCS:.c=.o)
 MAIN = gbsim
 
diff --git a/cport.c b/cport.c
index 71dbcdb..f63a9c1 100644
--- a/cport.c
+++ b/cport.c
@@ -31,6 +31,12 @@  static char *get_protocol(__le16 id)
 				return "I2C";
 			case GREYBUS_PROTOCOL_PWM:
 				return "PWM";
+			case GREYBUS_PROTOCOL_I2S_MGMT:
+				return "I2S_MGMT";
+			case GREYBUS_PROTOCOL_I2S_RECEIVER:
+				return "I2S_RECEIVER";
+			case GREYBUS_PROTOCOL_I2S_TRANSMITTER:
+				return "I2S_TRANSMITTER";
 			}
 		}
 	}
@@ -53,6 +59,13 @@  static void exec_subdev_handler(__le16 id, __u8 *rbuf, size_t size)
 			case GREYBUS_PROTOCOL_PWM:
 				pwm_handler(rbuf, size);
 				break;
+			case GREYBUS_PROTOCOL_I2S_MGMT:
+				i2s_mgmt_handler(rbuf, size);
+				break;
+			case GREYBUS_PROTOCOL_I2S_RECEIVER:
+			case GREYBUS_PROTOCOL_I2S_TRANSMITTER:
+				i2s_data_handler(rbuf, size);
+				break;
 			default:
 				gbsim_error("subdev handler not found for cport %d\n",
 					     id);
diff --git a/gbsim.h b/gbsim.h
index ef9c33c..1751fb8 100644
--- a/gbsim.h
+++ b/gbsim.h
@@ -286,4 +286,8 @@  void i2c_init(void);
 void pwm_handler(__u8 *, size_t);
 void pwm_init(void);
 
+void i2s_mgmt_handler(__u8 *, size_t);
+void i2s_data_handler(__u8 *, size_t);
+void i2s_init(void);
+
 bool manifest_parse(void *data, size_t size);
diff --git a/i2s.c b/i2s.c
new file mode 100644
index 0000000..d4d3ce9
--- /dev/null
+++ b/i2s.c
@@ -0,0 +1,177 @@ 
+/*
+ * Greybus Simulator
+ *
+ * Copyright 2014, 2015 Google Inc.
+ * Copyright 2014, 2015 Linaro Ltd.
+ *
+ * Provided under the three clause BSD license found in the LICENSE file.
+ */
+
+#include <fcntl.h>
+#include <libsoc_gpio.h>
+#include <linux/fs.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "gbsim.h"
+
+#define GB_I2S_MGMT_TYPE_PROTOCOL_VERSION               0x01
+#define GB_I2S_MGMT_TYPE_GET_SUPPORTED_CONFIGURATIONS   0x02
+#define GB_I2S_MGMT_TYPE_SET_CONFIGURATION              0x03
+#define GB_I2S_MGMT_TYPE_SET_SAMPLES_PER_MESSAGE        0x04
+#define GB_I2S_MGMT_TYPE_GET_PROCESSING_DELAY           0x05
+#define GB_I2S_MGMT_TYPE_SET_START_DELAY                0x06
+#define GB_I2S_MGMT_TYPE_ACTIVATE_CPORT                 0x07
+#define GB_I2S_MGMT_TYPE_DEACTIVATE_CPORT               0x08
+#define GB_I2S_MGMT_TYPE_REPORT_EVENT                   0x09
+
+#define GB_I2S_DATA_TYPE_SEND_DATA			0x02
+
+void i2s_mgmt_handler(__u8 *rbuf, size_t size)
+{
+	struct op_header *oph;
+	char *tbuf;
+	struct op_msg *op_req, *op_rsp;
+	struct cport_msg *cport_req, *cport_rsp;
+	size_t sz;
+
+	tbuf = malloc(4 * 1024);
+	if (!tbuf) {
+		gbsim_error("failed to allocate i2s handler tx buf\n");
+		return;
+	}
+	cport_req = (struct cport_msg *)rbuf;
+	op_req = (struct op_msg *)cport_req->data;
+	cport_rsp = (struct cport_msg *)tbuf;
+	cport_rsp->cport = cport_req->cport;
+	op_rsp = (struct op_msg *)cport_rsp->data;
+	oph = (struct op_header *)&op_req->header;
+
+	switch (oph->type) {
+	case GB_I2S_MGMT_TYPE_SET_CONFIGURATION:
+		sz = sizeof(struct op_header);
+		op_rsp->header.size = htole16((__u16)sz);
+		op_rsp->header.id = oph->id;
+
+		op_rsp->header.type = OP_RESPONSE | GB_I2S_MGMT_TYPE_SET_CONFIGURATION;
+		op_rsp->header.result = PROTOCOL_STATUS_SUCCESS;
+
+		gbsim_debug("Module %d -> AP CPort %d I2S SET_CONFIGURATION response\n  ",
+			    cport_to_module_id(cport_req->cport), cport_rsp->cport);
+		if (verbose)
+			gbsim_dump((__u8 *)op_rsp, op_rsp->header.size);
+		write(cport_in, cport_rsp, op_rsp->header.size + 1);
+		break;
+	case GB_I2S_MGMT_TYPE_SET_SAMPLES_PER_MESSAGE:
+		sz = sizeof(struct op_header);
+		op_rsp->header.size = htole16((__u16)sz);
+		op_rsp->header.id = oph->id;
+
+		op_rsp->header.type = OP_RESPONSE | GB_I2S_MGMT_TYPE_SET_SAMPLES_PER_MESSAGE;
+		op_rsp->header.result = PROTOCOL_STATUS_SUCCESS;
+
+		gbsim_debug("Module %d -> AP CPort %d I2S SET_SAMPLES_PER_MESSAGE response\n  ",
+			    cport_to_module_id(cport_req->cport), cport_rsp->cport);
+		if (verbose)
+			gbsim_dump((__u8 *)op_rsp, op_rsp->header.size);
+		write(cport_in, cport_rsp, op_rsp->header.size + 1);
+		break;
+	case GB_I2S_MGMT_TYPE_SET_START_DELAY:
+		sz = sizeof(struct op_header);
+		op_rsp->header.size = htole16((__u16)sz);
+		op_rsp->header.id = oph->id;
+
+		op_rsp->header.type = OP_RESPONSE | GB_I2S_MGMT_TYPE_SET_START_DELAY;
+		op_rsp->header.result = PROTOCOL_STATUS_SUCCESS;
+
+		gbsim_debug("Module %d -> AP CPort %d I2S SET_START_DELAY response\n  ",
+			    cport_to_module_id(cport_req->cport), cport_rsp->cport);
+		if (verbose)
+			gbsim_dump((__u8 *)op_rsp, op_rsp->header.size);
+		write(cport_in, cport_rsp, op_rsp->header.size + 1);
+		break;
+	case GB_I2S_MGMT_TYPE_ACTIVATE_CPORT:
+		sz = sizeof(struct op_header);
+		op_rsp->header.size = htole16((__u16)sz);
+		op_rsp->header.id = oph->id;
+
+		op_rsp->header.type = OP_RESPONSE | GB_I2S_MGMT_TYPE_ACTIVATE_CPORT;
+		op_rsp->header.result = PROTOCOL_STATUS_SUCCESS;
+
+		gbsim_debug("Module %d -> AP CPort %d I2S ACTIVATE_CPORT response\n  ",
+			    cport_to_module_id(cport_req->cport), cport_rsp->cport);
+		if (verbose)
+			gbsim_dump((__u8 *)op_rsp, op_rsp->header.size);
+		write(cport_in, cport_rsp, op_rsp->header.size + 1);
+		break;
+	case GB_I2S_MGMT_TYPE_DEACTIVATE_CPORT:
+		sz = sizeof(struct op_header);
+		op_rsp->header.size = htole16((__u16)sz);
+		op_rsp->header.id = oph->id;
+
+		op_rsp->header.type = OP_RESPONSE | GB_I2S_MGMT_TYPE_DEACTIVATE_CPORT;
+		op_rsp->header.result = PROTOCOL_STATUS_SUCCESS;
+
+		gbsim_debug("Module %d -> AP CPort %d I2S DEACTIVATE_CPORT response\n  ",
+			    cport_to_module_id(cport_req->cport), cport_rsp->cport);
+		if (verbose)
+			gbsim_dump((__u8 *)op_rsp, op_rsp->header.size);
+		write(cport_in, cport_rsp, op_rsp->header.size + 1);
+		break;
+	default:
+		gbsim_error("i2s mgmt operation type %02x not supported\n", oph->type);
+	}
+
+	free(tbuf);
+}
+
+
+void i2s_data_handler(__u8 *rbuf, size_t size)
+{
+	struct op_header *oph;
+	char *tbuf;
+	struct op_msg *op_req, *op_rsp;
+	struct cport_msg *cport_req, *cport_rsp;
+	size_t sz;
+
+	tbuf = malloc(4 * 1024);
+	if (!tbuf) {
+		gbsim_error("failed to allocate i2s handler tx buf\n");
+		return;
+	}
+	cport_req = (struct cport_msg *)rbuf;
+	op_req = (struct op_msg *)cport_req->data;
+	cport_rsp = (struct cport_msg *)tbuf;
+	cport_rsp->cport = cport_req->cport;
+	op_rsp = (struct op_msg *)cport_rsp->data;
+	oph = (struct op_header *)&op_req->header;
+
+	switch (oph->type) {
+	case GB_I2S_DATA_TYPE_SEND_DATA:
+		sz = sizeof(struct op_header);
+		op_rsp->header.size = htole16((__u16)sz);
+		op_rsp->header.id = oph->id;
+
+		op_rsp->header.type = OP_RESPONSE | GB_I2S_DATA_TYPE_SEND_DATA;
+		op_rsp->header.result = PROTOCOL_STATUS_SUCCESS;
+
+		gbsim_debug("Module %d -> AP CPort %d I2S SEND_DATA response\n  ",
+			    cport_to_module_id(cport_req->cport), cport_rsp->cport);
+		if (verbose)
+			gbsim_dump((__u8 *)op_rsp, op_rsp->header.size);
+		write(cport_in, cport_rsp, op_rsp->header.size + 1);
+		break;
+	default:
+		gbsim_error("i2s data operation type %02x not supported\n", oph->type);
+	}
+
+	free(tbuf);
+}
+
+void i2s_init(void)
+{
+
+}
diff --git a/main.c b/main.c
index b876421..e078332 100644
--- a/main.c
+++ b/main.c
@@ -111,6 +111,7 @@  int main(int argc, char *argv[])
 	/* Protocol handlers */
 	gpio_init();
 	i2c_init();
+	i2s_init();
 
 	ret = functionfs_loop();