3 * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include <linux/usb/cdc-wdm.h>
16 #include <sys/ioctl.h>
17 #include <sys/types.h>
26 #include <libubox/uloop.h>
30 size_t mbim_bufsize = 0;
31 uint8_t *mbim_buffer = NULL;
32 static struct uloop_fd mbim_fd;
33 static uint32_t expected;
36 static void mbim_msg_tout_cb(struct uloop_timeout *t)
38 fprintf(stderr, "ERROR: mbim message timeout\n");
42 static struct uloop_timeout tout = {
43 .cb = mbim_msg_tout_cb,
49 struct mbim_message_header *hdr = (struct mbim_message_header *) mbim_buffer;
52 if (le32toh(hdr->length) > mbim_bufsize) {
53 fprintf(stderr, "message too big %d\n", le32toh(hdr->length));
58 fprintf(stderr, "sending (%d): ", le32toh(hdr->length));
59 for (ret = 0; ret < le32toh(hdr->length); ret++)
60 printf("%02x ", ((uint8_t *) mbim_buffer)[ret]);
62 printf(" header_type: %04X\n", le32toh(hdr->type));
63 printf(" header_length: %04X\n", le32toh(hdr->length));
64 printf(" header_transaction: %04X\n", le32toh(hdr->transaction_id));
67 ret = write(mbim_fd.fd, mbim_buffer, le32toh(hdr->length));
69 perror("writing data failed: ");
71 expected = le32toh(hdr->type) | 0x80000000;
72 uloop_timeout_set(&tout, 15000);
78 mbim_recv(struct uloop_fd *u, unsigned int events)
80 ssize_t cnt = read(u->fd, mbim_buffer, mbim_bufsize);
81 struct mbim_message_header *hdr = (struct mbim_message_header *) mbim_buffer;
82 struct command_done_message *msg = (struct command_done_message *) (hdr + 1);
88 if (cnt < sizeof(struct mbim_message_header)) {
89 perror("failed to read() data: ");
93 printf("reading (%zu): ", cnt);
94 for (i = 0; i < cnt; i++)
95 printf("%02x ", mbim_buffer[i]);
97 printf(" header_type: %04X\n", le32toh(hdr->type));
98 printf(" header_length: %04X\n", le32toh(hdr->length));
99 printf(" header_transaction: %04X\n", le32toh(hdr->transaction_id));
102 if (le32toh(hdr->type) == expected)
103 uloop_timeout_cancel(&tout);
105 switch(le32toh(hdr->type)) {
106 case MBIM_MESSAGE_TYPE_OPEN_DONE:
107 if (current_handler->request() < 0)
108 mbim_send_close_msg();
110 case MBIM_MESSAGE_TYPE_COMMAND_DONE:
112 printf(" command_id: %04X\n", le32toh(msg->command_id));
113 printf(" status_code: %04X\n", le32toh(msg->status_code));
115 if (msg->status_code && !msg->buffer_length)
116 return_code = -le32toh(msg->status_code);
118 return_code = current_handler->response(msg->buffer, le32toh(msg->buffer_length));
121 mbim_send_close_msg();
123 case MBIM_MESSAGE_TYPE_CLOSE_DONE:
126 case MBIM_MESSAGE_TYPE_FUNCTION_ERROR:
128 mbim_send_close_msg();
135 mbim_open(const char *path)
140 mbim_fd.cb = mbim_recv;
141 mbim_fd.fd = open(path, O_RDWR);
142 if (mbim_fd.fd < 1) {
143 perror("open failed: ");
146 rc = ioctl(mbim_fd.fd, IOCTL_WDM_MAX_COMMAND, &max);
151 mbim_buffer = malloc(mbim_bufsize);
152 uloop_fd_add(&mbim_fd, ULOOP_READ);