• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/umbim/mbim-dev.c

  1 /*
  2  * umbim
  3  * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
  4  *
  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
  8  *
  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.
 13  */
 14 
 15 #include <linux/usb/cdc-wdm.h>
 16 #include <sys/ioctl.h>
 17 #include <sys/types.h>
 18 #include <sys/stat.h>
 19 
 20 #include <fcntl.h>
 21 #include <unistd.h>
 22 #include <stdlib.h>
 23 #include <stdio.h>
 24 #include <stdint.h>
 25 
 26 #include <libubox/uloop.h>
 27 
 28 #include "mbim.h"
 29 
 30 
 31 #ifdef LIBQMI_MBIM_PROXY
 32 #include <sys/socket.h>
 33 #include <sys/un.h>
 34 #include "data/mbim-service-proxy-control.h"
 35 
 36 uint8_t proxy_control[16] = { 0x83, 0x8c, 0xf7, 0xfb, 0x8d, 0x0d, 0x4d, 0x7f, 0x87, 0x1e, 0xd7, 0x1d, 0xbe, 0xfb, 0xb3, 0x9b };
 37 #endif
 38 
 39 size_t mbim_bufsize = 0;
 40 uint8_t *mbim_buffer = NULL;
 41 static struct uloop_fd mbim_fd;
 42 static uint32_t expected;
 43 int no_close;
 44 
 45 static void mbim_msg_tout_cb(struct uloop_timeout *t)
 46 {
 47         fprintf(stderr, "ERROR: mbim message timeout\n");
 48         mbim_end();
 49 }
 50 
 51 static struct uloop_timeout tout = {
 52         .cb = mbim_msg_tout_cb,
 53 };
 54 
 55 int
 56 mbim_send(void)
 57 {
 58         struct mbim_message_header *hdr = (struct mbim_message_header *) mbim_buffer;
 59         unsigned int ret = 0;
 60 
 61         if (le32toh(hdr->length) > mbim_bufsize) {
 62                 fprintf(stderr, "message too big %d\n", le32toh(hdr->length));
 63                 return -1;
 64         }
 65 
 66         if (verbose) {
 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]);
 70                 printf("\n");
 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));
 74         }
 75 
 76         ret = write(mbim_fd.fd, mbim_buffer, le32toh(hdr->length));
 77         if (!ret) {
 78                 perror("writing data failed: ");
 79         } else {
 80                 expected = le32toh(hdr->type) | 0x80000000;
 81                 uloop_timeout_set(&tout, 15000);
 82         }
 83         return ret;
 84 }
 85 
 86 static void
 87 mbim_recv(struct uloop_fd *u, unsigned int events)
 88 {
 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);
 92         int i;
 93 
 94         if (cnt < 0)
 95                 return;
 96 
 97         if (cnt < (ssize_t) sizeof(struct mbim_message_header)) {
 98                 perror("failed to read() data: ");
 99                 return;
100         }
101         if (verbose) {
102                 printf("reading (%zu): ", cnt);
103                 for (i = 0; i < cnt; i++)
104                         printf("%02x ", mbim_buffer[i]);
105                 printf("\n");
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));
109         }
110 
111         if (le32toh(hdr->type) == expected)
112                 uloop_timeout_cancel(&tout);
113 
114         switch(le32toh(hdr->type)) {
115         case MBIM_MESSAGE_TYPE_OPEN_DONE:
116                 if (current_handler->request() < 0)
117                         mbim_send_close_msg();
118                 break;
119         case MBIM_MESSAGE_TYPE_COMMAND_DONE:
120                 if (verbose) {
121                         printf("  command_id: %04X\n", le32toh(msg->command_id));
122                         printf("  status_code: %04X\n", le32toh(msg->status_code));
123                 }
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))
128                         break;
129 #endif
130                 else
131                         return_code = current_handler->response(msg->buffer, le32toh(msg->buffer_length));
132                 if (return_code < 0)
133                         no_close = 0;
134                 mbim_send_close_msg();
135                 break;
136         case MBIM_MESSAGE_TYPE_CLOSE_DONE:
137                 mbim_end();
138                 break;
139         case MBIM_MESSAGE_TYPE_FUNCTION_ERROR:
140                 no_close = 0;
141                 mbim_send_close_msg();
142                 return_code = -1;
143                 break;
144         }
145 }
146 
147 void
148 mbim_open(const char *path)
149 {
150         __u16 max;
151         int rc;
152 
153         mbim_fd.cb = mbim_recv;
154         mbim_fd.fd = open(path, O_RDWR);
155         if (mbim_fd.fd < 1) {
156                 perror("open failed: ");
157                 exit(-1);
158         }
159         rc = ioctl(mbim_fd.fd, IOCTL_WDM_MAX_COMMAND, &max);
160         if (!rc)
161                 mbim_bufsize = max;
162         else
163                 mbim_bufsize = 512;
164         mbim_buffer = malloc(mbim_bufsize);
165         uloop_fd_add(&mbim_fd, ULOOP_READ);
166 }
167 
168 #ifdef LIBQMI_MBIM_PROXY
169 static int
170 mbim_send_proxy_msg(const char *path)
171 {
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();
179 }
180 
181 void
182 mbim_proxy_open(const char *path)
183 {
184         struct sockaddr_un addr = { .sun_family = AF_UNIX, .sun_path = "\0mbim-proxy" };
185 
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: ");
190                 exit(-1);
191         }
192         if (connect(mbim_fd.fd, (struct sockaddr *)&addr, 13)) {
193                 perror("failed to connect to mbim-proxy: ");
194                 exit(-1);
195         }
196         mbim_bufsize = 512; // FIXME
197         mbim_buffer = malloc(mbim_bufsize);
198         uloop_fd_add(&mbim_fd, ULOOP_READ);
199         no_close = 1;
200         mbim_send_proxy_msg(path);
201 }
202 #endif
203 
204 void
205 mbim_end(void)
206 {
207         if (mbim_buffer) {
208                 free(mbim_buffer);
209                 mbim_bufsize = 0;
210                 mbim_buffer = NULL;
211         }
212         uloop_end();
213 }
214 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt