blob: 5f841ffcce2d18d8fed8999d88b16dd38cb9ba5a [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
2 * f_rdp.c -- USB ramdump driver
3 * (C) Copyright 2017 ASR Microelectronics (Shanghai) Co., Ltd.
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: GPL-2.0+
7 */
8
9#include <errno.h>
10#include <common.h>
11#include <malloc.h>
12#include <version.h>
13#include <linux/usb/ch9.h>
14#include <linux/usb/gadget.h>
15#include <linux/usb/composite.h>
16#include <linux/compiler.h>
17#include <asm/sizes.h>
18
19#ifdef CONFIG_RAMDUMP
20#include <../../../board/Marvell/common/ramdump.h>
21#endif
22
23#define DATA_BLOCK_LEN (512 * 7)
24#define USB_REG_BUF_LEN (256)
25#define DWC3_USB_REG_BUF_LEN (512)
26
27struct rd_ram_desc {
28 unsigned signature;
29 unsigned long textsize;
30 unsigned long addr;
31 unsigned long datasize;
32};
33
34struct rdp_dev {
35 struct usb_gadget *gadget;
36 struct usb_request *req;
37 struct usb_ep *in_ep, *out_ep;
38 struct usb_request *in_req, *out_req;
39 unsigned char configuration_done;
40 unsigned char rxdata;
41 unsigned char txdata;
42};
43
44struct f_rdp {
45 struct usb_function usb_function;
46 struct rdp_dev *dev;
47};
48
49static struct usb_interface_descriptor rdp_intf_data = {
50 .bLength = sizeof(rdp_intf_data),
51 .bDescriptorType = USB_DT_INTERFACE,
52 .bNumEndpoints = 2,
53 .bInterfaceClass = 0xff,
54 .bInterfaceSubClass = 0xff,
55 .bInterfaceProtocol = 0xff,
56};
57
58static struct usb_endpoint_descriptor fs_in_desc = {
59 .bLength = USB_DT_ENDPOINT_SIZE,
60 .bDescriptorType = USB_DT_ENDPOINT,
61
62 .bEndpointAddress = USB_DIR_IN,
63 .bmAttributes = USB_ENDPOINT_XFER_BULK,
64};
65
66static struct usb_endpoint_descriptor fs_out_desc = {
67 .bLength = USB_DT_ENDPOINT_SIZE,
68 .bDescriptorType = USB_DT_ENDPOINT,
69
70 .bEndpointAddress = USB_DIR_OUT,
71 .bmAttributes = USB_ENDPOINT_XFER_BULK,
72};
73
74static struct usb_endpoint_descriptor hs_in_desc = {
75 .bLength = USB_DT_ENDPOINT_SIZE,
76 .bDescriptorType = USB_DT_ENDPOINT,
77
78 .bmAttributes = USB_ENDPOINT_XFER_BULK,
79 .wMaxPacketSize = __constant_cpu_to_le16(512),
80};
81
82static struct usb_endpoint_descriptor hs_out_desc = {
83 .bLength = USB_DT_ENDPOINT_SIZE,
84 .bDescriptorType = USB_DT_ENDPOINT,
85
86 .bmAttributes = USB_ENDPOINT_XFER_BULK,
87 .wMaxPacketSize = __constant_cpu_to_le16(512),
88};
89
90static const struct usb_descriptor_header *hs_rdp_data_function[] = {
91 (struct usb_descriptor_header *)&rdp_intf_data,
92 (struct usb_descriptor_header *)&hs_in_desc,
93 (struct usb_descriptor_header *)&hs_out_desc,
94 NULL,
95};
96static const struct usb_descriptor_header *fs_rdp_data_function[] = {
97 (struct usb_descriptor_header *)&rdp_intf_data,
98 (struct usb_descriptor_header *)&fs_in_desc,
99 (struct usb_descriptor_header *)&fs_out_desc,
100 NULL,
101};
102
103static struct f_rdp *rdp_func;
104static inline struct f_rdp *func_to_rdp(struct usb_function *f)
105{
106 return container_of(f, struct f_rdp, usb_function);
107}
108
109static inline struct usb_endpoint_descriptor *
110ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
111 struct usb_endpoint_descriptor *fs)
112{
113 printf("dualspeed(g): %d, g->speed: 0x%x\n",
114 gadget_is_dualspeed(g), g->speed);
115
116 if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
117 return hs;
118 return fs;
119}
120
121//#define RDP_DEBUG_MODE
122#ifdef RDP_DEBUG_MODE
123#define log_debug(fmt,args...) printf(fmt ,##args)
124#else
125#define log_debug(fmt,args...) do {}while(0)
126#endif
127
128/*-------------------------------------------------------------------------*/
129__weak int host_os_is_linux(void) {return true;}
130__weak int host_os_is_known(void) {return false;}
131
132static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
133{
134 struct usb_request *req;
135
136 req = usb_ep_alloc_request(ep, 0);
137 if (!req)
138 return req;
139
140 req->length = length;
141 req->buf = memalign(64, length);
142 if (!req->buf) {
143 usb_ep_free_request(ep, req);
144 req = NULL;
145 }
146
147 return req;
148}
149
150static int rdp_rx_data(void)
151{
152 struct rdp_dev *dev = rdp_func->dev;
153 int rx_data_len, status;
154 /* int delay_us = (2000 * 1000 / 50); */
155
156#if defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_GADGET_DWC2_OTG)
157 rx_data_len = dev->out_req->length = DWC3_USB_REG_BUF_LEN;
158#else
159 rx_data_len = dev->out_req->length = USB_REG_BUF_LEN;
160#endif
161 log_debug("dev->out_req->length:%d dev->rxdata:%d, dev->out_req->buf: 0x%x\n",
162 dev->out_req->length, dev->rxdata, (u32)dev->out_req->buf);
163
164 status = usb_ep_queue(dev->out_ep, dev->out_req, 0);
165 if (status) {
166 error("kill %s: resubmit %d bytes --> %d",
167 dev->out_ep->name, dev->out_req->length, status);
168 usb_ep_set_halt(dev->out_ep);
169 return -EAGAIN;
170 }
171
172 while (!dev->rxdata/* && (delay_us--) */) {
173 udelay(50);
174#ifdef CONFIG_USB_DWC3
175 dwc3_uboot_handle_interrupt(0);
176#else
177 usb_gadget_handle_interrupts();
178#endif
179 if (ctrlc())
180 return -1;
181 }
182 /*
183 if (delay_us <= 0) {
184 printf("waiting for Host request timeout\n");
185 return -1;
186 }
187 */
188 dev->rxdata = 0;
189 printf("usb rcv %d bytes\n", dev->out_req->actual);
190
191 return 0;
192}
193
194void rdp_tx_data(unsigned char *data, int len)
195{
196 struct rdp_dev *dev = rdp_func->dev;
197 unsigned char *ptr = dev->in_req->buf;
198 int status;
199
200 memcpy(ptr, data, len);
201
202 dev->in_req->length = len;
203
204 log_debug("%s: dev->in_req->length:%d to_cpy:%d\n", __func__,
205 dev->in_req->length, sizeof(data));
206
207 status = usb_ep_queue(dev->in_ep, dev->in_req, 0);
208 if (status) {
209 error("kill %s: resubmit %d bytes --> %d",
210 dev->in_ep->name, dev->in_req->length, status);
211 usb_ep_set_halt(dev->in_ep);
212 }
213
214 /* Wait until tx interrupt received */
215 while (!dev->txdata) {
216#ifdef CONFIG_USB_DWC3
217 dwc3_uboot_handle_interrupt(0);
218#else
219 usb_gadget_handle_interrupts();
220#endif
221 }
222
223 dev->txdata = 0;
224}
225
226void rdp_tx_data_ptr(unsigned char *data, int len)
227{
228 struct rdp_dev *dev = rdp_func->dev;
229 unsigned char *ptr = dev->in_req->buf;
230 unsigned length = dev->in_req->length;
231 int status;
232
233 dev->in_req->length = len;
234 dev->in_req->buf = data;
235
236 log_debug("%s: buf: 0x%x, len: %d\n", __func__,
237 dev->in_req->buf, dev->in_req->length);
238
239 status = usb_ep_queue(dev->in_ep, dev->in_req, 0);
240 if (status) {
241 error("kill %s: resubmit %d bytes --> %d",
242 dev->in_ep->name, dev->in_req->length, status);
243 usb_ep_set_halt(dev->in_ep);
244 }
245
246 /* Wait until tx interrupt received */
247 while (!dev->txdata) {
248#ifdef CONFIG_USB_DWC3
249 dwc3_uboot_handle_interrupt(0);
250#else
251 usb_gadget_handle_interrupts();
252#endif
253 }
254
255 dev->txdata = 0;
256 dev->in_req->buf = ptr;
257 dev->in_req->length = length;
258}
259
260static void rdp_rx_tx_complete(struct usb_ep *ep, struct usb_request *req)
261{
262 struct rdp_dev *dev = rdp_func->dev;
263 int status = req->status;
264
265 log_debug("%s: ep_ptr:%p, req_ptr:%p\n", __func__, ep, req);
266 switch (status) {
267 case 0:
268 if (ep == dev->out_ep)
269 dev->rxdata = 1;
270 else
271 dev->txdata = 1;
272
273 break;
274
275 /* this endpoint is normally active while we're configured */
276 case -ECONNABORTED: /* hardware forced ep reset */
277 case -ECONNRESET: /* request dequeued */
278 case -ESHUTDOWN: /* disconnect from host */
279 case -EREMOTEIO: /* short read */
280 case -EOVERFLOW:
281 error("ERROR:%d", status);
282 break;
283 }
284
285 log_debug("%s complete --> %d, %d/%d\n", ep->name,
286 status, req->actual, req->length);
287}
288
289static struct usb_request *rdp_start_ep(struct usb_ep *ep)
290{
291 struct usb_request *req;
292
293#if defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_GADGET_DWC2_OTG)
294 req = alloc_ep_req(ep, DWC3_USB_REG_BUF_LEN);
295#else
296 req = alloc_ep_req(ep, USB_REG_BUF_LEN);
297#endif
298
299 log_debug("%s: ep:%p req:%p\n", __func__, ep, req);
300
301 if (!req)
302 return NULL;
303
304 memset(req->buf, 0, req->length);
305 req->complete = rdp_rx_tx_complete;
306
307 return req;
308}
309
310static void rdp_setup_complete(struct usb_ep *ep, struct usb_request *req)
311{
312 if (req->status || req->actual != req->length)
313 log_debug("setup complete --> %d, %d/%d\n",
314 req->status, req->actual, req->length);
315}
316
317static int
318rdp_func_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
319{
320 struct rdp_dev *dev = rdp_func->dev;
321 struct usb_request *req = dev->req;
322 struct usb_gadget *gadget = dev->gadget;
323 int value = 0;
324
325 u16 len = le16_to_cpu(ctrl->wLength);
326
327 log_debug("Req_Type: 0x%x Req: 0x%x wValue: 0x%x wIndex: 0x%x wLen: 0x%x\n",
328 ctrl->bRequestType, ctrl->bRequest, ctrl->wValue, ctrl->wIndex,
329 ctrl->wLength);
330
331 return value;
332}
333
334int rdp_init(int rdp_type)
335{
336 int timeout;
337 int loops = 1;
338
339 struct rdp_dev *dev = rdp_func->dev;
340 struct usb_gadget *gadget = dev->gadget;
341
342#ifdef CONFIG_DUMP2PC_IN_UBOOT
343 printf("ramdump: CONFIG_DUMP2PC_IN_UBOOT enabled\n");
344#endif
345
346 if (!usb_vbus_is_online()) {
347 udc_disconnect();
348 printf("vbus offline, return and boot to linux\n");
349 return 0;
350 }
351
352 /* Wait for a device enumeration and configuration settings */
353 printf("waiting for enum done....\n");
354 timeout = (2500 * 1000 / 50); //waiting for 3s
355 while (!dev->configuration_done && (timeout--)) {
356#ifdef CONFIG_USB_DWC3
357 dwc3_uboot_handle_interrupt(0);
358#else
359 usb_gadget_handle_interrupts();
360#endif
361 udelay(50);
362 /*
363 * do not wait for handshaking with non-linux os, as handshake is
364 * is only needed with CPE version rdp_transfer
365 */
366 if (!host_os_is_linux() && host_os_is_known()) {
367 udc_disconnect();
368 printf("returns to rdp for non-linux os\n");
369 return 0;
370 }
371 }
372 if (timeout <= 0) {
373 printf("waiting for enum done2....\n");
374 while(loops--) {
375 usb_gadget_disconnect(gadget);
376 udelay(50);
377 usb_gadget_connect(gadget);
378 timeout = (5000 * 1000 / 50); //waiting for 3s
379 while (!dev->configuration_done && (timeout--)) {
380#ifdef CONFIG_USB_DWC3
381 dwc3_uboot_handle_interrupt(0);
382#else
383 usb_gadget_handle_interrupts();
384#endif
385 udelay(50);
386 /*
387 * do not wait for handshaking with non-linux os, as handshake is
388 * is only needed with CPE version rdp_transfer
389 */
390 if (!host_os_is_linux() && host_os_is_known()) {
391 udc_disconnect();
392 printf("returns with non-linux os\n");
393 return 0;
394 }
395 }
396
397 if (timeout > 0)
398 break;
399
400 /* force to quit the while loop if linux is detected */
401 if (host_os_is_linux() && timeout <= 0) {
402 timeout = 1;
403 break;
404 }
405
406 if (ctrlc())
407 return -1;
408 }
409 }
410
411 if (timeout <= 0) {
412 printf("usb enum timeout\n");
413 return -1;
414 }
415 printf("usb enum done....\n");
416
417 if (!host_os_is_linux()) {
418 udc_disconnect();
419 printf("returns with non-linux os\n");
420 return 0;
421 }
422
423 /* wait for HOST request */
424 if (rdp_rx_data() < 0) {
425 printf("%s: rdp_rx_data failed!\n", __func__);
426 return -1;
427 }
428
429 if (!strncmp((char *)dev->out_req->buf, "rdp_upload", strlen("rdp_upload"))) {
430 puts("get rdp_upload\n");
431 udelay(30 * 1000); /* 30 ms */
432 } else {
433 puts("err reply\n");
434 return -1;
435 }
436
437 if (rdp_type == RDP_RAMDUMP) {
438 printf("send rdp_ramdump to AP\n");
439 //send text to host
440 rdp_tx_data("rdp_ramdump", 11);
441 } else {
442 printf("send rdp_cpassert to AP\n");
443 //send text to host
444 rdp_tx_data("rdp_cpassert", 12);
445 }
446
447 return 0;
448}
449
450int rdp_process_data(struct rd_ram_desc *desc)
451{
452 unsigned char * addr = desc->addr;
453 struct rdp_dev *dev = rdp_func->dev;
454 u32 data_len = desc->datasize;
455 u32 data_in_len = 0, idx = 0;
456 u32 total_data_len = 0;
457 int need_zero_pkt = 0;
458
459 printf("send rdp_done to AP\n");
460 //send text to host
461 rdp_tx_data("rdp_done", 8);
462
463 /* wait for HOST to request text */
464 printf("getting rdp_text\n");
465 if (rdp_rx_data() < 0) {
466 printf("%s: rdp_rx_data err!\n", __func__);
467 return -1;
468 }
469 if (!strncmp((char *)dev->out_req->buf, "rdp_text", strlen("rdp_text"))) {
470 puts("get rdp_text\n");
471 udelay(30 * 1000); /* 30 ms */
472 } else {
473 puts("Wrong reply\n");
474 return -1;
475 }
476 printf("data addr: 0x%x %d\n", addr, desc->textsize);
477 rdp_tx_data(addr, desc->textsize);
478 total_data_len += desc->textsize;
479
480 /* wait for HOST to request data */
481 printf("Getting rdp_data\n");
482 if (rdp_rx_data() < 0) {
483 printf("%s: rdp_rx_data err!\n", __func__);
484 return -1;
485 }
486 if (!strncmp((char *)dev->out_req->buf, "rdp_data", strlen("rdp_data"))) {
487 puts("get rdp_data\n");
488 udelay(30 * 1000); /* 30 ms */
489 } else {
490 puts("Wrong reply\n");
491 return -1;
492 }
493
494 //rdp_tx_data(&data_len, sizeof(data_len));
495 need_zero_pkt = ((data_len % DATA_BLOCK_LEN) == 0);
496 addr = addr + desc->textsize;
497 printf("data addr: 0x%x\n", addr);
498 while(data_len) {
499 if (data_len >= DATA_BLOCK_LEN) {
500 rdp_tx_data_ptr(addr + data_in_len, DATA_BLOCK_LEN);
501 data_in_len += DATA_BLOCK_LEN;
502 data_len -= DATA_BLOCK_LEN;
503 total_data_len += DATA_BLOCK_LEN;
504 } else {
505 rdp_tx_data_ptr(addr + data_in_len, data_len);
506 data_in_len += data_len;
507 total_data_len += data_len;
508 data_len = 0;
509 }
510 idx++;
511 if ((idx % 3000) == 0)
512 printf("sending 0x%x bytes now\n", idx * DATA_BLOCK_LEN);
513 }
514
515 if (need_zero_pkt) {
516 printf("zero pkt\n");
517 rdp_tx_data_ptr(addr, 0);
518 }
519
520 printf("!! tx data done - total: 0x%x bytes, left: 0x%x bytes\n\n",
521 total_data_len, data_len);
522 udc_disconnect();
523 mdelay(3000);
524 return 0;
525}
526
527int rdp_process_cpassert_data(u8 *data_addr, int size)
528{
529 unsigned char * addr = data_addr;
530 u32 data_len = size;
531 struct rdp_dev *dev = rdp_func->dev;
532 u32 data_in_len = 0, idx = 0, total_data_len = 0;
533 int need_zero_pkt = 0;
534
535 printf("send rdp_cp_done to AP\n");
536 //send text to host
537 rdp_tx_data("rdp_cp_done", 11);
538
539 need_zero_pkt = ((size % DATA_BLOCK_LEN) == 0);
540 /* wait for HOST to request text */
541 printf("Getting rdp_cpassert\n");
542 if (rdp_rx_data() < 0) {
543 printf("%s: rdp_rx_data err!\n", __func__);
544 return -1;
545 }
546 if (!strncmp((char *)dev->out_req->buf, "rdp_cpassert", strlen("rdp_cpassert"))) {
547 puts("get rdp_cpassert\n");
548 udelay(30 * 1000); /* 30 ms */
549 } else {
550 puts("Wrong reply\n");
551 return -1;
552 }
553
554 printf("cpassert data addr: 0x%x, size: 0x%x\n", addr, data_len);
555 while(data_len) {
556 if (data_len >= DATA_BLOCK_LEN) {
557 rdp_tx_data_ptr(addr + data_in_len, DATA_BLOCK_LEN);
558 data_in_len += DATA_BLOCK_LEN;
559 data_len -= DATA_BLOCK_LEN;
560 total_data_len += DATA_BLOCK_LEN;
561 } else {
562 rdp_tx_data_ptr(addr + data_in_len, data_len);
563 data_in_len += data_len;
564 total_data_len += data_len;
565 data_len = 0;
566 }
567 idx++;
568 if ((idx % 3000) == 0)
569 printf("sending 0x%x bytes now\n", idx * DATA_BLOCK_LEN);
570 }
571 if (need_zero_pkt) {
572 printf("zero pkt\n");
573 rdp_tx_data_ptr(addr, 0);
574 }
575
576 printf("!! CPASSERT tx data done - total: 0x%x bytes, left: 0x%x bytes\n\n",
577 total_data_len, data_len);
578 udelay(10000);
579 return 0;
580}
581
582int rdp_give_cpassert_extra_files(u8 *data_addr, int size)
583{
584 unsigned char * addr = data_addr;
585 u32 data_len = size;
586 struct rdp_dev *dev = rdp_func->dev;
587 u32 data_in_len = 0, idx = 0, total_data_len = 0;
588 int need_zero_pkt = 0;
589
590 need_zero_pkt = ((size % DATA_BLOCK_LEN) == 0);
591 /* wait for HOST to request text */
592 printf("Getting cpassert ext dump req\n");
593 if (rdp_rx_data() < 0) {
594 printf("%s: rdp_rx_data err!\n", __func__);
595 return -1;
596 }
597 if (!strncmp((char *)dev->out_req->buf, "cpassert_extra_dump", strlen("cpassert_extra_dump"))) {
598 puts("get cpassert_extra_dump\n");
599 udelay(30 * 1000); /* 30 ms */
600 } else {
601 puts("Wrong request, check rdp_transfer tool version\n");
602 return -1;
603 }
604
605 printf("cpassert extra data hdr: 0x%x, size: 0x%x\n", addr, data_len);
606 while(data_len) {
607 if (data_len >= DATA_BLOCK_LEN) {
608 rdp_tx_data_ptr(addr + data_in_len, DATA_BLOCK_LEN);
609 data_in_len += DATA_BLOCK_LEN;
610 data_len -= DATA_BLOCK_LEN;
611 total_data_len += DATA_BLOCK_LEN;
612 } else {
613 rdp_tx_data_ptr(addr + data_in_len, data_len);
614 data_in_len += data_len;
615 total_data_len += data_len;
616 data_len = 0;
617 }
618 idx++;
619 if ((idx % 3000) == 0)
620 printf("sending 0x%x bytes now\n", idx * DATA_BLOCK_LEN);
621 }
622 if (need_zero_pkt) {
623 printf("zero pkt\n");
624 rdp_tx_data_ptr(addr, 0);
625 }
626
627 printf("!! cpassert extra data done - total: 0x%x bytes, left: 0x%x bytes\n\n",
628 total_data_len, data_len);
629 udelay(10000);
630 return 0;
631}
632
633static int rdp_func_bind(struct usb_configuration *c, struct usb_function *f)
634{
635 struct usb_gadget *gadget = c->cdev->gadget;
636 struct f_rdp *f_rdp = func_to_rdp(f);
637 struct rdp_dev *dev;
638 struct usb_ep *ep;
639 int status;
640
641 rdp_func = f_rdp;
642 //dev = memalign(64, sizeof(*dev));
643 dev = malloc(sizeof(*dev));
644 if (!dev)
645 return -ENOMEM;
646
647 memset(dev, 0, sizeof(*dev));
648 dev->gadget = gadget;
649 f_rdp->dev = dev;
650
651 log_debug("%s: usb_configuration: 0x%p usb_function: 0x%p\n",
652 __func__, c, f);
653 log_debug("f_rdp: 0x%p dev: 0x%p\n", f_rdp, dev);
654
655 dev->req = usb_ep_alloc_request(gadget->ep0, 0);
656 if (!dev->req) {
657 status = -ENOMEM;
658 goto fail;
659 }
660
661#if defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_GADGET_DWC2_OTG)
662 dev->req->buf = memalign(64, DWC3_USB_REG_BUF_LEN);
663#else
664 dev->req->buf = memalign(64, USB_REG_BUF_LEN);
665#endif
666
667 if (!dev->req->buf) {
668 status = -ENOMEM;
669 goto fail;
670 }
671
672 dev->req->complete = rdp_setup_complete;
673
674 status = usb_interface_id(c, f);
675
676 if (status < 0)
677 goto fail;
678
679 rdp_intf_data.bInterfaceNumber = status;
680
681 usb_ep_autoconfig_reset(gadget);
682 /* allocate instance-specific endpoints */
683 ep = usb_ep_autoconfig(gadget, &fs_in_desc);
684 if (!ep) {
685 status = -ENODEV;
686 goto fail;
687 }
688
689 if (gadget_is_dualspeed(gadget)) {
690 log_debug("%s: gadget is dualspeed, fs_in_desc.bEndpointAddress: 0x%x\n",
691 __func__, (u32)fs_in_desc.bEndpointAddress);
692 hs_in_desc.bEndpointAddress =
693 fs_in_desc.bEndpointAddress;
694 }
695
696 dev->in_ep = ep;
697 ep->driver_data = ep; /* claim */
698
699 ep = usb_ep_autoconfig(gadget, &fs_out_desc);
700 if (!ep) {
701 status = -ENODEV;
702 goto fail;
703 }
704
705 if (gadget_is_dualspeed(gadget))
706 hs_out_desc.bEndpointAddress =
707 fs_out_desc.bEndpointAddress;
708
709 dev->out_ep = ep;
710 ep->driver_data = ep; /* claim */
711
712 if (gadget_is_dualspeed(gadget)) {
713 f->hs_descriptors = (struct usb_descriptor_header **)
714 &hs_rdp_data_function;
715
716 if (!f->hs_descriptors)
717 goto fail;
718
719 f->descriptors = (struct usb_descriptor_header **)
720 &fs_rdp_data_function;
721
722 if (!f->descriptors)
723 goto fail;
724 }
725
726 log_debug("%s: in_ep:%p in_req:%p\n", __func__,
727 dev->in_ep, dev->in_req);
728 log_debug("%s: out_ep:%p out_req:%p\n", __func__,
729 dev->out_ep, dev->out_req);
730 return 0;
731
732 fail:
733 log_debug("%s: failed\n", __func__);
734 free(dev);
735 return status;
736}
737
738static void free_ep_req(struct usb_ep *ep, struct usb_request *req)
739{
740 free(req->buf);
741 usb_ep_free_request(ep, req);
742}
743
744static void rdp_unbind(struct usb_configuration *c, struct usb_function *f)
745{
746 struct f_rdp *f_rdp = func_to_rdp(f);
747 struct rdp_dev *dev = f_rdp->dev;
748
749 free(dev);
750 memset(rdp_func, 0, sizeof(*rdp_func));
751 rdp_func = NULL;
752}
753
754static void rdp_func_disable(struct usb_function *f)
755{
756 struct f_rdp *f_rdp = func_to_rdp(f);
757 struct rdp_dev *dev = f_rdp->dev;
758
759 log_debug("%s:\n", __func__);
760
761 /* Avoid freeing memory when ep is still claimed */
762 if (dev->in_ep->driver_data) {
763 free_ep_req(dev->in_ep, dev->in_req);
764 usb_ep_disable(dev->in_ep);
765 dev->in_ep->driver_data = NULL;
766 }
767
768 if (dev->out_ep->driver_data) {
769 dev->out_req->buf = NULL;
770 usb_ep_free_request(dev->out_ep, dev->out_req);
771 usb_ep_disable(dev->out_ep);
772 dev->out_ep->driver_data = NULL;
773 }
774}
775
776static int rdp_eps_setup(struct usb_function *f)
777{
778 struct usb_composite_dev *cdev = f->config->cdev;
779 struct usb_gadget *gadget = cdev->gadget;
780 struct rdp_dev *dev = rdp_func->dev;
781 struct usb_endpoint_descriptor *d;
782 struct usb_request *req;
783 struct usb_ep *ep;
784 int result;
785
786 ep = dev->in_ep;
787 d = ep_desc(gadget, &hs_in_desc, &fs_in_desc);
788 log_debug("in bEndpointAddress: 0x%x\n", d->bEndpointAddress);
789
790 result = usb_ep_enable(ep, d);
791 if (result)
792 goto exit;
793
794 ep->driver_data = cdev; /* claim */
795 req = rdp_start_ep(ep);
796 if (!req) {
797 usb_ep_disable(ep);
798 result = -EIO;
799 goto exit;
800 }
801 dev->in_req = req;
802
803 ep = dev->out_ep;
804 d = ep_desc(gadget, &hs_out_desc, &fs_out_desc);
805 log_debug("bEndpointAddress: 0x%x\n", d->bEndpointAddress);
806
807 result = usb_ep_enable(ep, d);
808 if (result)
809 goto exit;
810
811 ep->driver_data = cdev; /* claim */
812 req = rdp_start_ep(ep);
813 if (!req) {
814 usb_ep_disable(ep);
815 result = -EIO;
816 goto exit;
817 }
818 dev->out_req = req;
819
820 exit:
821 return result;
822}
823
824static int rdp_func_set_alt(struct usb_function *f,
825 unsigned intf, unsigned alt)
826{
827 struct rdp_dev *dev = rdp_func->dev;
828 int result;
829
830 log_debug("%s: func: %s intf: %d alt: %d\n",
831 __func__, f->name, intf, alt);
832
833 switch (intf) {
834 case 0:
835 log_debug("%s: intf == 0\n", __func__);
836 result = rdp_eps_setup(f);
837 if (result)
838 error("%s: EPs setup failed!", __func__);
839 dev->configuration_done = 1;
840 break;
841 default:
842 printf("%s: error interface!", __func__);
843 }
844
845 return 0;
846}
847
848static int rdp_func_init(struct usb_configuration *c)
849{
850 struct f_rdp *f_rdp;
851 int status;
852
853 log_debug("%s: cdev: 0x%p\n", __func__, c->cdev);
854
855 //f_rdp = memalign(64, sizeof(*f_rdp));
856 f_rdp = malloc(sizeof(*f_rdp));
857 if (!f_rdp) {
858 printf("%s: alloc f_rdp failed\n", __func__);
859 return -ENOMEM;
860 }
861 memset(f_rdp, 0, sizeof(*f_rdp));
862
863 f_rdp->usb_function.name = "f_rdp";
864 f_rdp->usb_function.bind = rdp_func_bind;
865 f_rdp->usb_function.unbind = rdp_unbind;
866 f_rdp->usb_function.setup = rdp_func_setup;
867 f_rdp->usb_function.set_alt = rdp_func_set_alt;
868 f_rdp->usb_function.disable = rdp_func_disable;
869
870 status = usb_add_function(c, &f_rdp->usb_function);
871 if (status)
872 free(f_rdp);
873
874 return status;
875}
876
877int rdp_add(struct usb_configuration *c)
878{
879 log_debug("%s:\n", __func__);
880 return rdp_func_init(c);
881}