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
);