1 #define _BSD_SOURCE /* for endian.h */ 2 3 #include <endian.h> 4 #include <errno.h> 5 #include <fcntl.h> 6 #include <stdarg.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 #include <sys/ioctl.h> 11 #include <sys/stat.h> 12 #include <sys/types.h> 13 #include <sys/poll.h> 14 #include <unistd.h> 15 #include <stdbool.h> 16 #include <sys/eventfd.h> 17 18 #include "libaio.h" 19 #define IOCB_FLAG_RESFD (1 << 0) 20 21 #include <linux/usb/functionfs.h> 22 23 #define BUF_LEN 8192 24 #define BUFS_MAX 128 25 #define AIO_MAX (BUFS_MAX*2) 26 27 /******************** Descriptors and Strings *******************************/ 28 29 static const struct { 30 struct usb_functionfs_descs_head_v2 header; 31 __le32 fs_count; 32 __le32 hs_count; 33 struct { 34 struct usb_interface_descriptor intf; 35 struct usb_endpoint_descriptor_no_audio bulk_sink; 36 struct usb_endpoint_descriptor_no_audio bulk_source; 37 } __attribute__ ((__packed__)) fs_descs, hs_descs; 38 } __attribute__ ((__packed__)) descriptors = { 39 .header = { 40 .magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2), 41 .flags = htole32(FUNCTIONFS_HAS_FS_DESC | 42 FUNCTIONFS_HAS_HS_DESC), 43 .length = htole32(sizeof(descriptors)), 44 }, 45 .fs_count = htole32(3), 46 .fs_descs = { 47 .intf = { 48 .bLength = sizeof(descriptors.fs_descs.intf), 49 .bDescriptorType = USB_DT_INTERFACE, 50 .bNumEndpoints = 2, 51 .bInterfaceClass = USB_CLASS_VENDOR_SPEC, 52 .iInterface = 1, 53 }, 54 .bulk_sink = { 55 .bLength = sizeof(descriptors.fs_descs.bulk_sink), 56 .bDescriptorType = USB_DT_ENDPOINT, 57 .bEndpointAddress = 1 | USB_DIR_IN, 58 .bmAttributes = USB_ENDPOINT_XFER_BULK, 59 }, 60 .bulk_source = { 61 .bLength = sizeof(descriptors.fs_descs.bulk_source), 62 .bDescriptorType = USB_DT_ENDPOINT, 63 .bEndpointAddress = 2 | USB_DIR_OUT, 64 .bmAttributes = USB_ENDPOINT_XFER_BULK, 65 }, 66 }, 67 .hs_count = htole32(3), 68 .hs_descs = { 69 .intf = { 70 .bLength = sizeof(descriptors.hs_descs.intf), 71 .bDescriptorType = USB_DT_INTERFACE, 72 .bNumEndpoints = 2, 73 .bInterfaceClass = USB_CLASS_VENDOR_SPEC, 74 .iInterface = 1, 75 }, 76 .bulk_sink = { 77 .bLength = sizeof(descriptors.hs_descs.bulk_sink), 78 .bDescriptorType = USB_DT_ENDPOINT, 79 .bEndpointAddress = 1 | USB_DIR_IN, 80 .bmAttributes = USB_ENDPOINT_XFER_BULK, 81 .wMaxPacketSize = htole16(512), 82 }, 83 .bulk_source = { 84 .bLength = sizeof(descriptors.hs_descs.bulk_source), 85 .bDescriptorType = USB_DT_ENDPOINT, 86 .bEndpointAddress = 2 | USB_DIR_OUT, 87 .bmAttributes = USB_ENDPOINT_XFER_BULK, 88 .wMaxPacketSize = htole16(512), 89 }, 90 }, 91 }; 92 93 #define STR_INTERFACE "AIO Test" 94 95 static const struct { 96 struct usb_functionfs_strings_head header; 97 struct { 98 __le16 code; 99 const char str1[sizeof(STR_INTERFACE)]; 100 } __attribute__ ((__packed__)) lang0; 101 } __attribute__ ((__packed__)) strings = { 102 .header = { 103 .magic = htole32(FUNCTIONFS_STRINGS_MAGIC), 104 .length = htole32(sizeof(strings)), 105 .str_count = htole32(1), 106 .lang_count = htole32(1), 107 }, 108 .lang0 = { 109 htole16(0x0409), /* en-us */ 110 STR_INTERFACE, 111 }, 112 }; 113 114 /********************** Buffer structure *******************************/ 115 116 struct io_buffer { 117 struct iocb **iocb; 118 unsigned char **buf; 119 unsigned cnt; 120 unsigned len; 121 unsigned requested; 122 }; 123 124 /******************** Endpoints handling *******************************/ 125 126 static void display_event(struct usb_functionfs_event *event) 127 { 128 static const char *const names[] = { 129 [FUNCTIONFS_BIND] = "BIND", 130 [FUNCTIONFS_UNBIND] = "UNBIND", 131 [FUNCTIONFS_ENABLE] = "ENABLE", 132 [FUNCTIONFS_DISABLE] = "DISABLE", 133 [FUNCTIONFS_SETUP] = "SETUP", 134 [FUNCTIONFS_SUSPEND] = "SUSPEND", 135 [FUNCTIONFS_RESUME] = "RESUME", 136 }; 137 switch (event->type) { 138 case FUNCTIONFS_BIND: 139 case FUNCTIONFS_UNBIND: 140 case FUNCTIONFS_ENABLE: 141 case FUNCTIONFS_DISABLE: 142 case FUNCTIONFS_SETUP: 143 case FUNCTIONFS_SUSPEND: 144 case FUNCTIONFS_RESUME: 145 printf("Event %s\n", names[event->type]); 146 } 147 } 148 149 static void handle_ep0(int ep0, bool *ready) 150 { 151 int ret; 152 struct usb_functionfs_event event; 153 154 ret = read(ep0, &event, sizeof(event)); 155 if (!ret) { 156 perror("unable to read event from ep0"); 157 return; 158 } 159 display_event(&event); 160 switch (event.type) { 161 case FUNCTIONFS_SETUP: 162 if (event.u.setup.bRequestType & USB_DIR_IN) 163 write(ep0, NULL, 0); 164 else 165 read(ep0, NULL, 0); 166 break; 167 168 case FUNCTIONFS_ENABLE: 169 *ready = true; 170 break; 171 172 case FUNCTIONFS_DISABLE: 173 *ready = false; 174 break; 175 176 default: 177 break; 178 } 179 } 180 181 void init_bufs(struct io_buffer *iobuf, unsigned n, unsigned len) 182 { 183 unsigned i; 184 iobuf->buf = malloc(n*sizeof(*iobuf->buf)); 185 iobuf->iocb = malloc(n*sizeof(*iobuf->iocb)); 186 iobuf->cnt = n; 187 iobuf->len = len; 188 iobuf->requested = 0; 189 for (i = 0; i < n; ++i) { 190 iobuf->buf[i] = malloc(len*sizeof(**iobuf->buf)); 191 iobuf->iocb[i] = malloc(sizeof(**iobuf->iocb)); 192 } 193 iobuf->cnt = n; 194 } 195 196 void delete_bufs(struct io_buffer *iobuf) 197 { 198 unsigned i; 199 for (i = 0; i < iobuf->cnt; ++i) { 200 free(iobuf->buf[i]); 201 free(iobuf->iocb[i]); 202 } 203 free(iobuf->buf); 204 free(iobuf->iocb); 205 } 206 207 int main(int argc, char *argv[]) 208 { 209 int ret; 210 unsigned i, j; 211 char *ep_path; 212 213 int ep0, ep1; 214 215 io_context_t ctx; 216 217 int evfd; 218 fd_set rfds; 219 220 struct io_buffer iobuf[2]; 221 int actual = 0; 222 bool ready; 223 224 if (argc != 2) { 225 printf("ffs directory not specified!\n"); 226 return 1; 227 } 228 229 ep_path = malloc(strlen(argv[1]) + 4 /* "/ep#" */ + 1 /* '\0' */); 230 if (!ep_path) { 231 perror("malloc"); 232 return 1; 233 } 234 235 /* open endpoint files */ 236 sprintf(ep_path, "%s/ep0", argv[1]); 237 ep0 = open(ep_path, O_RDWR); 238 if (ep0 < 0) { 239 perror("unable to open ep0"); 240 return 1; 241 } 242 if (write(ep0, &descriptors, sizeof(descriptors)) < 0) { 243 perror("unable do write descriptors"); 244 return 1; 245 } 246 if (write(ep0, &strings, sizeof(strings)) < 0) { 247 perror("unable to write strings"); 248 return 1; 249 } 250 sprintf(ep_path, "%s/ep1", argv[1]); 251 ep1 = open(ep_path, O_RDWR); 252 if (ep1 < 0) { 253 perror("unable to open ep1"); 254 return 1; 255 } 256 257 free(ep_path); 258 259 memset(&ctx, 0, sizeof(ctx)); 260 /* setup aio context to handle up to AIO_MAX requests */ 261 if (io_setup(AIO_MAX, &ctx) < 0) { 262 perror("unable to setup aio"); 263 return 1; 264 } 265 266 evfd = eventfd(0, 0); 267 if (evfd < 0) { 268 perror("unable to open eventfd"); 269 return 1; 270 } 271 272 for (i = 0; i < sizeof(iobuf)/sizeof(*iobuf); ++i) 273 init_bufs(&iobuf[i], BUFS_MAX, BUF_LEN); 274 275 while (1) { 276 FD_ZERO(&rfds); 277 FD_SET(ep0, &rfds); 278 FD_SET(evfd, &rfds); 279 280 ret = select(((ep0 > evfd) ? ep0 : evfd)+1, 281 &rfds, NULL, NULL, NULL); 282 if (ret < 0) { 283 if (errno == EINTR) 284 continue; 285 perror("select"); 286 break; 287 } 288 289 if (FD_ISSET(ep0, &rfds)) 290 handle_ep0(ep0, &ready); 291 292 /* we are waiting for function ENABLE */ 293 if (!ready) 294 continue; 295 296 /* 297 * when we're preparing new data to submit, 298 * second buffer being transmitted 299 */ 300 for (i = 0; i < sizeof(iobuf)/sizeof(*iobuf); ++i) { 301 if (iobuf[i].requested) 302 continue; 303 /* prepare requests */ 304 for (j = 0; j < iobuf[i].cnt; ++j) { 305 io_prep_pwrite(iobuf[i].iocb[j], ep1, 306 iobuf[i].buf[j], 307 iobuf[i].len, 0); 308 /* enable eventfd notification */ 309 iobuf[i].iocb[j]->u.c.flags |= IOCB_FLAG_RESFD; 310 iobuf[i].iocb[j]->u.c.resfd = evfd; 311 } 312 /* submit table of requests */ 313 ret = io_submit(ctx, iobuf[i].cnt, iobuf[i].iocb); 314 if (ret >= 0) { 315 iobuf[i].requested = ret; 316 printf("submit: %d requests buf: %d\n", ret, i); 317 } else 318 perror("unable to submit reqests"); 319 } 320 321 /* if event is ready to read */ 322 if (!FD_ISSET(evfd, &rfds)) 323 continue; 324 325 uint64_t ev_cnt; 326 ret = read(evfd, &ev_cnt, sizeof(ev_cnt)); 327 if (ret < 0) { 328 perror("unable to read eventfd"); 329 break; 330 } 331 332 struct io_event e[BUFS_MAX]; 333 /* we read aio events */ 334 ret = io_getevents(ctx, 1, BUFS_MAX, e, NULL); 335 if (ret > 0) /* if we got events */ 336 iobuf[actual].requested -= ret; 337 338 /* if all req's from iocb completed */ 339 if (!iobuf[actual].requested) 340 actual = (actual + 1)%(sizeof(iobuf)/sizeof(*iobuf)); 341 } 342 343 /* free resources */ 344 345 for (i = 0; i < sizeof(iobuf)/sizeof(*iobuf); ++i) 346 delete_bufs(&iobuf[i]); 347 io_destroy(ctx); 348 349 close(ep1); 350 close(ep0); 351 352 return 0; 353 } 354