summaryrefslogtreecommitdiff
path: root/mbim-dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'mbim-dev.c')
-rw-r--r--mbim-dev.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/mbim-dev.c b/mbim-dev.c
new file mode 100644
index 0000000..e5d90f9
--- /dev/null
+++ b/mbim-dev.c
@@ -0,0 +1,120 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include <libubox/uloop.h>
+
+#include "mbim.h"
+
+uint8_t mbim_buffer[MBIM_BUFFER_SIZE];
+static struct uloop_fd mbim_fd;
+static uint32_t expected;
+int no_close;
+
+static void mbim_msg_tout_cb(struct uloop_timeout *t)
+{
+ fprintf(stderr, "ERROR: mbim message timeout\n");
+ uloop_end();
+}
+
+static struct uloop_timeout tout = {
+ .cb = mbim_msg_tout_cb,
+};
+
+int
+mbim_send(void)
+{
+ struct mbim_message_header *hdr = (struct mbim_message_header *) mbim_buffer;
+ int ret = 0;
+
+ if (le32toh(hdr->length) > MBIM_BUFFER_SIZE) {
+ fprintf(stderr, "message too big %d\n", le32toh(hdr->length));
+ return -1;
+ }
+
+ if (verbose) {
+ fprintf(stderr, "sending (%d): ", le32toh(hdr->length));
+ for (ret = 0; ret < le32toh(hdr->length); ret++)
+ printf("%02x ", ((uint8_t *) mbim_buffer)[ret]);
+ printf("\n");
+ printf(" header_type: %04X\n", le32toh(hdr->type));
+ printf(" header_length: %04X\n", le32toh(hdr->length));
+ printf(" header_transaction: %04X\n", le32toh(hdr->transaction_id));
+ }
+
+ ret = write(mbim_fd.fd, mbim_buffer, le32toh(hdr->length));
+ if (!ret) {
+ perror("writing data failed: ");
+ } else {
+ expected = le32toh(hdr->type) | 0x80000000;
+ uloop_timeout_set(&tout, 15000);
+ }
+ return ret;
+}
+
+static void
+mbim_recv(struct uloop_fd *u, unsigned int events)
+{
+ ssize_t cnt = read(u->fd, mbim_buffer, MBIM_BUFFER_SIZE);
+ struct mbim_message_header *hdr = (struct mbim_message_header *) mbim_buffer;
+ struct command_message *msg = (struct command_message *) mbim_buffer;
+ int i;
+
+ if (cnt < 0)
+ return;
+
+ if (cnt < sizeof(struct mbim_message_header)) {
+ perror("failed to read() data: ");
+ return;
+ }
+ if (verbose) {
+ printf("reading (%zu): ", cnt);
+ for (i = 0; i < cnt; i++)
+ printf("%02x ", mbim_buffer[i]);
+ printf("\n");
+ printf(" header_type: %04X\n", le32toh(hdr->type));
+ printf(" header_length: %04X\n", le32toh(hdr->length));
+ printf(" header_transaction: %04X\n", le32toh(hdr->transaction_id));
+ }
+
+ if (le32toh(hdr->type) == expected)
+ uloop_timeout_cancel(&tout);
+
+ switch(le32toh(hdr->type)) {
+ case MBIM_MESSAGE_TYPE_OPEN_DONE:
+ if (current_handler->request() < 0)
+ mbim_send_close_msg();
+ break;
+ case MBIM_MESSAGE_TYPE_COMMAND_DONE:
+ return_code = current_handler->response(msg->buffer, le32toh(msg->buffer_length));
+ if (return_code < 0)
+ no_close = 0;
+ mbim_send_close_msg();
+ break;
+ case MBIM_MESSAGE_TYPE_CLOSE_DONE:
+ uloop_end();
+ break;
+ case MBIM_MESSAGE_TYPE_FUNCTION_ERROR:
+ no_close = 0;
+ mbim_send_close_msg();
+ return_code = -1;
+ break;
+ }
+}
+
+void
+mbim_open(const char *path)
+{
+ mbim_fd.cb = mbim_recv;
+ mbim_fd.fd = open(path, O_RDWR);
+ if (mbim_fd.fd < 1) {
+ perror("open failed: ");
+ exit(-1);
+ }
+ uloop_fd_add(&mbim_fd, ULOOP_READ);
+}