e5d90f9f270ad1f7f856a80b76b293632bf2e538
[project/umbim.git] / mbim-dev.c
1 #include <sys/types.h>
2 #include <sys/stat.h>
3
4 #include <fcntl.h>
5 #include <unistd.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <stdint.h>
9
10 #include <libubox/uloop.h>
11
12 #include "mbim.h"
13
14 uint8_t mbim_buffer[MBIM_BUFFER_SIZE];
15 static struct uloop_fd mbim_fd;
16 static uint32_t expected;
17 int no_close;
18
19 static void mbim_msg_tout_cb(struct uloop_timeout *t)
20 {
21         fprintf(stderr, "ERROR: mbim message timeout\n");
22         uloop_end();
23 }
24
25 static struct uloop_timeout tout = {
26         .cb = mbim_msg_tout_cb,
27 };
28
29 int
30 mbim_send(void)
31 {
32         struct mbim_message_header *hdr = (struct mbim_message_header *) mbim_buffer;
33         int ret = 0;
34
35         if (le32toh(hdr->length) > MBIM_BUFFER_SIZE) {
36                 fprintf(stderr, "message too big %d\n", le32toh(hdr->length));
37                 return -1;
38         }
39
40         if (verbose) {
41                 fprintf(stderr, "sending (%d): ", le32toh(hdr->length));
42                 for (ret = 0; ret < le32toh(hdr->length); ret++)
43                         printf("%02x ", ((uint8_t *) mbim_buffer)[ret]);
44                 printf("\n");
45                 printf("  header_type: %04X\n", le32toh(hdr->type));
46                 printf("  header_length: %04X\n", le32toh(hdr->length));
47                 printf("  header_transaction: %04X\n", le32toh(hdr->transaction_id));
48         }
49
50         ret = write(mbim_fd.fd, mbim_buffer, le32toh(hdr->length));
51         if (!ret) {
52                 perror("writing data failed: ");
53         } else {
54                 expected = le32toh(hdr->type) | 0x80000000;
55                 uloop_timeout_set(&tout, 15000);
56         }
57         return ret;
58 }
59
60 static void
61 mbim_recv(struct uloop_fd *u, unsigned int events)
62 {
63         ssize_t cnt = read(u->fd, mbim_buffer, MBIM_BUFFER_SIZE);
64         struct mbim_message_header *hdr = (struct mbim_message_header *) mbim_buffer;
65         struct command_message *msg = (struct command_message *) mbim_buffer;
66         int i;
67
68         if (cnt < 0)
69                 return;
70
71         if (cnt < sizeof(struct mbim_message_header)) {
72                 perror("failed to read() data: ");
73                 return;
74         }
75         if (verbose) {
76                 printf("reading (%zu): ", cnt);
77                 for (i = 0; i < cnt; i++)
78                         printf("%02x ", mbim_buffer[i]);
79                 printf("\n");
80                 printf("  header_type: %04X\n", le32toh(hdr->type));
81                 printf("  header_length: %04X\n", le32toh(hdr->length));
82                 printf("  header_transaction: %04X\n", le32toh(hdr->transaction_id));
83         }
84
85         if (le32toh(hdr->type) == expected)
86                 uloop_timeout_cancel(&tout);
87
88         switch(le32toh(hdr->type)) {
89         case MBIM_MESSAGE_TYPE_OPEN_DONE:
90                 if (current_handler->request() < 0)
91                         mbim_send_close_msg();
92                 break;
93         case MBIM_MESSAGE_TYPE_COMMAND_DONE:
94                 return_code = current_handler->response(msg->buffer, le32toh(msg->buffer_length));
95                 if (return_code < 0)
96                         no_close = 0;
97                 mbim_send_close_msg();
98                 break;
99         case MBIM_MESSAGE_TYPE_CLOSE_DONE:
100                 uloop_end();
101                 break;
102         case MBIM_MESSAGE_TYPE_FUNCTION_ERROR:
103                 no_close = 0;
104                 mbim_send_close_msg();
105                 return_code = -1;
106                 break;
107         }
108 }
109
110 void
111 mbim_open(const char *path)
112 {
113         mbim_fd.cb = mbim_recv;
114         mbim_fd.fd = open(path, O_RDWR);
115         if (mbim_fd.fd < 1) {
116                 perror("open failed: ");
117                 exit(-1);
118         }
119         uloop_fd_add(&mbim_fd, ULOOP_READ);
120 }