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>
31 #ifdef LIBQMI_MBIM_PROXY
32 #include <sys/socket.h>
34 #include "data/mbim-service-proxy-control.h"
36 uint8_t proxy_control
[16] = { 0x83, 0x8c, 0xf7, 0xfb, 0x8d, 0x0d, 0x4d, 0x7f, 0x87, 0x1e, 0xd7, 0x1d, 0xbe, 0xfb, 0xb3, 0x9b };
39 size_t mbim_bufsize
= 0;
40 uint8_t *mbim_buffer
= NULL
;
41 static struct uloop_fd mbim_fd
;
42 static uint32_t expected
;
45 static void mbim_msg_tout_cb(struct uloop_timeout
*t
)
47 fprintf(stderr
, "ERROR: mbim message timeout\n");
51 static struct uloop_timeout tout
= {
52 .cb
= mbim_msg_tout_cb
,
58 struct mbim_message_header
*hdr
= (struct mbim_message_header
*) mbim_buffer
;
61 if (le32toh(hdr
->length
) > mbim_bufsize
) {
62 fprintf(stderr
, "message too big %d\n", le32toh(hdr
->length
));
67 fprintf(stderr
, "sending (%d): ", le32toh(hdr
->length
));
68 for (ret
= 0; ret
< le32toh(hdr
->length
); ret
++)
69 printf("%02x ", ((uint8_t *) mbim_buffer
)[ret
]);
71 printf(" header_type: %04X\n", le32toh(hdr
->type
));
72 printf(" header_length: %04X\n", le32toh(hdr
->length
));
73 printf(" header_transaction: %04X\n", le32toh(hdr
->transaction_id
));
76 ret
= write(mbim_fd
.fd
, mbim_buffer
, le32toh(hdr
->length
));
78 perror("writing data failed: ");
80 expected
= le32toh(hdr
->type
) | 0x80000000;
81 uloop_timeout_set(&tout
, 15000);
87 mbim_recv(struct uloop_fd
*u
, unsigned int events
)
89 ssize_t cnt
= read(u
->fd
, mbim_buffer
, mbim_bufsize
);
90 struct mbim_message_header
*hdr
= (struct mbim_message_header
*) mbim_buffer
;
91 struct command_done_message
*msg
= (struct command_done_message
*) (hdr
+ 1);
97 if (cnt
< sizeof(struct mbim_message_header
)) {
98 perror("failed to read() data: ");
102 printf("reading (%zu): ", cnt
);
103 for (i
= 0; i
< cnt
; i
++)
104 printf("%02x ", mbim_buffer
[i
]);
106 printf(" header_type: %04X\n", le32toh(hdr
->type
));
107 printf(" header_length: %04X\n", le32toh(hdr
->length
));
108 printf(" header_transaction: %04X\n", le32toh(hdr
->transaction_id
));
111 if (le32toh(hdr
->type
) == expected
)
112 uloop_timeout_cancel(&tout
);
114 switch(le32toh(hdr
->type
)) {
115 case MBIM_MESSAGE_TYPE_OPEN_DONE
:
116 if (current_handler
->request() < 0)
117 mbim_send_close_msg();
119 case MBIM_MESSAGE_TYPE_COMMAND_DONE
:
121 printf(" command_id: %04X\n", le32toh(msg
->command_id
));
122 printf(" status_code: %04X\n", le32toh(msg
->status_code
));
124 if (msg
->status_code
&& !msg
->buffer_length
)
125 return_code
= -le32toh(msg
->status_code
);
126 #ifdef LIBQMI_MBIM_PROXY
127 else if (le32toh(msg
->command_id
) == MBIM_CMD_PROXY_CONTROL_CONFIGURATION
&& !memcmp(msg
->service_id
, proxy_control
, 16))
131 return_code
= current_handler
->response(msg
->buffer
, le32toh(msg
->buffer_length
));
134 mbim_send_close_msg();
136 case MBIM_MESSAGE_TYPE_CLOSE_DONE
:
139 case MBIM_MESSAGE_TYPE_FUNCTION_ERROR
:
141 mbim_send_close_msg();
148 mbim_open(const char *path
)
153 mbim_fd
.cb
= mbim_recv
;
154 mbim_fd
.fd
= open(path
, O_RDWR
);
155 if (mbim_fd
.fd
< 1) {
156 perror("open failed: ");
159 rc
= ioctl(mbim_fd
.fd
, IOCTL_WDM_MAX_COMMAND
, &max
);
164 mbim_buffer
= malloc(mbim_bufsize
);
165 uloop_fd_add(&mbim_fd
, ULOOP_READ
);
168 #ifdef LIBQMI_MBIM_PROXY
170 mbim_send_proxy_msg(const char *path
)
172 struct mbim_proxy_control_configuration_s
*p
=
173 (struct mbim_proxy_control_configuration_s
*) mbim_setup_command_msg(proxy_control
,
174 MBIM_MESSAGE_COMMAND_TYPE_SET
, MBIM_CMD_PROXY_CONTROL_CONFIGURATION
,
175 sizeof(struct mbim_proxy_control_configuration_s
));
176 mbim_encode_string(&p
->devicepath
, (char *)path
);
177 p
->timeout
= htole32(30); // FIXME: hard coded timeout
178 return mbim_send_command_msg();
182 mbim_proxy_open(const char *path
)
184 struct sockaddr_un addr
= { .sun_family
= AF_UNIX
, .sun_path
= "\0mbim-proxy" };
186 mbim_fd
.cb
= mbim_recv
;
187 mbim_fd
.fd
= socket(PF_UNIX
, SOCK_STREAM
, 0);
188 if (mbim_fd
.fd
< 1) {
189 perror("socket failed: ");
192 if (connect(mbim_fd
.fd
, (struct sockaddr
*)&addr
, 13)) {
193 perror("failed to connect to mbim-proxy: ");
196 mbim_bufsize
= 512; // FIXME
197 mbim_buffer
= malloc(mbim_bufsize
);
198 uloop_fd_add(&mbim_fd
, ULOOP_READ
);
200 mbim_send_proxy_msg(path
);