LMS 2012
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
usb_function.c
Go to the documentation of this file.
1 /*
2  * LEGO® MINDSTORMS EV3
3  *
4  * Copyright (C) 2010-2013 The LEGO Group
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 /*
22  * This UsbFunction file is based on and inheritated from
23  * the original file (f_sourcesink.c) and work done by
24  * David Brownell
25  *
26  * >> f_sourcesink.c - USB peripheral source/sink configuration driver <<
27  *
28  * >> Copyright (C) 2003-2008 David Brownell <<
29  * >> Copyright (C) 2008 by Nokia Corporation <<
30  *
31  */
32 
33 /*
34  *
35  * HID IN/OUT Interrupt transfer FUNCTION ...
36  *
37  */
38 
39 struct f_rudolf {
40  struct usb_function function;
41 
42  struct usb_ep *in_ep;
43  struct usb_ep *out_ep;
44 };
45 
46 enum // Used for signaling the IN stuff USB-state
47 { // Data from the Brick to the HOST
49  USB_DATA_BUSY, // Ongoing USB request
50  USB_DATA_PENDING, // Data ready for X-fer, but USB busy
51  USB_DATA_READY, // Initial setting
52 };
53 
55 struct usb_ep *save_in_ep;
56 struct usb_request *save_in_req;
57 
58 #ifndef PCASM
59 static inline struct f_rudolf *func_to_rudolf(struct usb_function *f)
60 {
61  return container_of(f, struct f_rudolf, function);
62 }
63 #else
64 // Keep Eclipse happy
65 #endif
66 
67 static struct usb_interface_descriptor rudolf_intf = {
68  .bLength = sizeof rudolf_intf,
69  .bDescriptorType = USB_DT_INTERFACE,
70  .bInterfaceNumber = 0,
71  .bAlternateSetting = 0,
72  .bNumEndpoints = 2, // Just plain in and out
73  .bInterfaceClass = USB_CLASS_HID, // We go for NONE custom-driver
74  .bInterfaceSubClass = 0,
75  .bInterfaceProtocol = 0,
76  /* .iInterface = DYNAMIC */
77 };
78 
79 static struct hid_descriptor hs_hid_rudolf_desc = {
80  .bLength = sizeof hs_hid_rudolf_desc,
81  .bDescriptorType = HID_DT_HID,
82  .bcdHID = cpu_to_le16(0x0110),
83  .bCountryCode = 0x00,
84  .bNumDescriptors = 0x01, // "The one and only"
85  .desc[0].bDescriptorType = 0x22, // Report Descriptor Type - 0x22 = HID
86  .desc[0].wDescriptorLength = sizeof hs_hid_report_descriptor,
87  /*.desc[0].bDescriptorType = DYNAMIC */
88  /*.desc[0].wDescriptorLenght= DYNAMIC */
89 };
90 
91 static struct hid_descriptor fs_hid_rudolf_desc = {
92  .bLength = sizeof fs_hid_rudolf_desc,
93  .bDescriptorType = HID_DT_HID,
94  .bcdHID = cpu_to_le16(0x0110),
95  .bCountryCode = 0x00,
96  .bNumDescriptors = 0x01, // "The one and only"
97  .desc[0].bDescriptorType = 0x22, // Report Descriptor Type - 0x22 = HID
98  .desc[0].wDescriptorLength = sizeof fs_hid_report_descriptor,
99 
100 };
101 
102 /* full speed support: */
103 
104 static struct usb_endpoint_descriptor rudolf_out_fs_desc = {
105  .bLength = USB_DT_ENDPOINT_SIZE,
106  .bDescriptorType = USB_DT_ENDPOINT,
107  .bEndpointAddress = USB_DIR_OUT,
108  .bmAttributes = USB_ENDPOINT_XFER_INT,
109  .wMaxPacketSize = cpu_to_le16(64),
110  .bInterval = 1, /* 1 = 1 mSec POLL rate for FS */
111 };
112 
113 static struct usb_endpoint_descriptor rudolf_in_fs_desc = {
114  .bLength = USB_DT_ENDPOINT_SIZE,
115  .bDescriptorType = USB_DT_ENDPOINT,
116  .bEndpointAddress = USB_DIR_IN,
117  .bmAttributes = USB_ENDPOINT_XFER_INT,
118  .wMaxPacketSize = cpu_to_le16(64),
119  .bInterval = 1, /* 1 = 1 mSec POLL rate for FS */
120 };
121 
122 /* high speed support: */
123 
124 static struct usb_endpoint_descriptor rudolf_in_hs_desc = {
125  .bLength = USB_DT_ENDPOINT_SIZE,
126  .bDescriptorType = USB_DT_ENDPOINT,
127  .bEndpointAddress = USB_DIR_IN,
128  .bmAttributes = USB_ENDPOINT_XFER_INT,
129  .wMaxPacketSize = cpu_to_le16(1024),
130  .bInterval = 4, /* Calculated as :
131  * 2^(value-1) * 125uS
132  * i.e. value 1: 2^(1-1) * 125 uSec = 125 uSec
133  * - 4: 2^(4-1) * 125 uSec = 1 mSec
134  */
135 };
136 
137 static struct usb_endpoint_descriptor rudolf_out_hs_desc = {
138  .bLength = USB_DT_ENDPOINT_SIZE,
139  .bDescriptorType = USB_DT_ENDPOINT,
140  .bEndpointAddress = USB_DIR_OUT,
141  .bmAttributes = USB_ENDPOINT_XFER_INT,
142  .wMaxPacketSize = cpu_to_le16(1024),
143  .bInterval = 4, /* Calculated as :
144  * 2^(value-1) * 125uS
145  * i.e. value 1: 2^(1-1) * 125 uSec = 125 uSec
146  * - 4: 2^(4-1) * 125 uSec = 1 mSec
147  */
148 };
149 
150 static struct usb_descriptor_header *hs_rudolf_descs[] = {
151  (struct usb_descriptor_header *) &rudolf_intf,
152  (struct usb_descriptor_header *) &hs_hid_rudolf_desc,
153  (struct usb_descriptor_header *) &rudolf_in_hs_desc,
154  (struct usb_descriptor_header *) &rudolf_out_hs_desc,
155  NULL,
156 };
157 
158 static struct usb_descriptor_header *fs_rudolf_descs[] = {
159  (struct usb_descriptor_header *) &rudolf_intf,
160  (struct usb_descriptor_header *) &fs_hid_rudolf_desc,
161  (struct usb_descriptor_header *) &rudolf_in_fs_desc,
162  (struct usb_descriptor_header *) &rudolf_out_fs_desc,
163  NULL,
164 };
165 
166 /* function-specific strings: */
167 
168 static struct usb_string strings_rudolf[] = {
169  [0].s = "Xfer data to and from EV3 brick",
170  { } /* end of list */
171 };
172 
173 static struct usb_gadget_strings stringtab_rudolf = {
174  .language = 0x0409, /* en-us */
175  .strings = strings_rudolf,
176 };
177 
178 static struct usb_gadget_strings *rudolf_strings[] = {
179  &stringtab_rudolf,
180  NULL,
181 };
182 
183 /*-------------------------------------------------------------------------*/
184 
185 static int
186 f_rudolf_bind(struct usb_configuration *c, struct usb_function *f)
187 {
188  struct usb_composite_dev *cdev = c->cdev;
189  struct f_rudolf *rudolf = func_to_rudolf(f);
190  int id;
191 
192  /* allocate interface ID(s) */
193  id = usb_interface_id(c, f);
194  if (id < 0)
195  return id;
196  rudolf_intf.bInterfaceNumber = id;
197 
198  /* allocate endpoints */
199  rudolf->in_ep = usb_ep_autoconfig(cdev->gadget, &rudolf_in_fs_desc);
200  if (!rudolf->in_ep) {
201 autoconf_fail:
202  ERROR(cdev, "%s: can't autoconfigure on %s\n",
203  f->name, cdev->gadget->name);
204  return -ENODEV;
205  }
206  rudolf->in_ep->driver_data = cdev; /* claim */
207 
208  rudolf->out_ep = usb_ep_autoconfig(cdev->gadget, &rudolf_out_fs_desc);
209  if (!rudolf->out_ep)
210  goto autoconf_fail;
211  rudolf->out_ep->driver_data = cdev; /* claim */
212 
213 
214  /* support high speed hardware */
215  if (gadget_is_dualspeed(c->cdev->gadget)) {
216 
217  rudolf_in_hs_desc.bEndpointAddress =
218  rudolf_in_fs_desc.bEndpointAddress;
219  rudolf_out_hs_desc.bEndpointAddress =
220  rudolf_out_fs_desc.bEndpointAddress;
221  f->hs_descriptors = hs_rudolf_descs;
222  f->descriptors = fs_rudolf_descs;
223  }
224 
225  DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
226  gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
227  f->name, rudolf->in_ep->name, rudolf->out_ep->name);
228  return 0;
229 }
230 
231 static void
232 f_rudolf_unbind(struct usb_configuration *c, struct usb_function *f)
233 {
234  kfree(func_to_rudolf(f));
235 }
236 
237 static void usb_req_arm(struct usb_ep *ep, struct usb_request *req)
238 {
239  int status;
240 
241  if (UsbSpeed.Speed == FULL_SPEED)
242  {
243  req->length = 64;
244  req->actual = 64;
245  }
246  else
247  {
248  req->length = 1024;
249  req->actual = 1024;
250  }
251 
252  status = usb_ep_queue(ep, req, GFP_ATOMIC);
253  if (status) {
254  usb_ep_set_halt(ep);
255  /* FIXME recover later ... somehow */
256  }
257 }
258 
259 static int read_data_from_host(struct usb_request *req)
260 {
261  unsigned i;
262  u8 *buf = req->buf;
263 
264  int from_host_length = 0; // NO ACCESS LOCKS YET
265 
266  // test for actual length > 0
267 
268  for (i = 0; i < req->actual; i++, buf++)
269  {
270 
271  usb_char_buffer_out[i] = *buf;
272  from_host_length++;
273  }
274 
275  return (from_host_length);
276 }
277 
278 static void write_data_to_the_host(struct usb_ep *ep, struct usb_request *req)
279 {
280  unsigned i;
281  u8 *buf = req->buf;
282 
283  //#define DEBUG
284  #ifdef DEBUG
285  printk("WR to HOST req->length = %d\r\n", req->length);
286  #endif
287 
288  #undef DEBUG
289  //#define DEBUG
290  #ifdef DEBUG
291  printk("USB = %d, %d\r\n", usb_char_buffer_in[2], usb_char_buffer_in[3]);
292  #endif
293  #undef DEBUG
294 
295  for (i = 0; i < req->length; i++)
296  *buf++ = usb_char_buffer_in[i];
297  usb_char_in_length = 0; // Reset and ready
298 }
299 
300 static void rudolf_complete(struct usb_ep *ep, struct usb_request *req)
301 {
302  struct f_rudolf *rudolf = ep->driver_data;
303  int status = req->status;
304 
305 
306  switch ( status ) {
307 
308  case 0: /* normal completion? */
309  if (ep == rudolf->out_ep) // An OUT completion?
310  {
311  //#define DEBUG
312  #ifdef DEBUG
313  printk("Rudolf_complete OUT\n");
314  #endif
315 
316  usb_char_out_length = read_data_from_host(req);
317  usb_req_arm(ep, req);
318  }
319  else // We have an INPUT request complete
320  {
321  //#define DEBUG
322  #ifdef DEBUG
323  printk("Rudolf_complete IN\n");
324  #endif
325 
326  switch(input_state) // State of Brick data x-fer
327  {
328  case USB_DATA_READY: //should be BUSY or PENDING....
329 
330  #ifdef DEBUG
331  printk("IN_IN_IN - READY ?????\n");
332  #endif
333 
334  break;
335 
336  case USB_DATA_PENDING: //
337  // #define DEBUG
338  #ifdef DEBUG
339  printk("IN_IN_IN - PENDING settes to BUSY\n");
340  #endif
341 
343  write_data_to_the_host(ep, req);
344  usb_req_arm(ep, req); // new request
345  break;
346 
347  case USB_DATA_BUSY: //
348  #ifdef DEBUG
349  printk("IN_IN_IN - BUSY settes to READY\n");
350  #endif
351  #undef DEBUG
353  // and relax
354  break;
355 
356  case USB_DATA_IDLE: // too lazy
357  #ifdef DEBUG
358  printk("IN_IN_IN - IDLE\n");
359  #endif
360  //#undef DEBUG
361 
362  break;
363 
364  default: break; // hmmm.
365  }
366  // Reset the buffer size - Ready again
367  usb_char_in_length = 0;
368  }
369  break;
370 
371  /* this endpoint is normally active while we're configured */
372 
373  case -ESHUTDOWN: /* disconnect from host */
374  // REMOVED 26102012 (*pUsbSpeed).Speed = FULL_SPEED;
375  case -ECONNABORTED: /* hardware forced ep reset */
376  case -ECONNRESET: /* request dequeued */
377  //case -ESHUTDOWN: /* disconnect from host */
378  if (ep == rudolf->out_ep)
379  read_data_from_host(req);
380  free_ep_req(ep, req);
381  return;
382 
383  case -EOVERFLOW: /* buffer overrun on read means that
384  we didn't provide a big enough
385  buffer.
386  */
387  default:
388 //#if 1
389  // DBG(cdev, "%s complete --> %d, %d/%d\n", ep->name,
390  // status, req->actual, req->length);
391 //#endif
392  case -EREMOTEIO: /* short read */
393  break;
394  }
395 
396 }
397 
398 static int rudolf_start_ep(struct f_rudolf *rudolf, bool is_in)
399 {
400  struct usb_ep *ep;
401  struct usb_request *req;
402  int status;
403 
404  ep = is_in ? rudolf->in_ep : rudolf->out_ep;
405  req = alloc_ep_req(ep);
406  if (!req)
407  return -ENOMEM;
408 
409  req->complete = rudolf_complete;
410 
411  #ifdef DEBUG
412  printk("UsbSpeed.Speed = %d\n\r", UsbSpeed.Speed);
413  #endif
414 
415  if (UsbSpeed.Speed == FULL_SPEED)
416  {
417  #ifdef DEBUG
418  printk("rudolf_start_ep FULL\n\r");
419  #endif
420 
421  (*pUsbSpeed).Speed = FULL_SPEED;
422  req->length = 64; // Full speed max buffer size
423  req->actual = 64;
424  }
425  else
426  {
427  #ifdef DEBUG
428  printk("rudolf_start_ep HIGH\n\r");
429  #endif
430 
431  (*pUsbSpeed).Speed = HIGH_SPEED;
432  req->length = 1024; // High speed max buffer size
433  req->actual = 1024;
434  }
435 
436  if (is_in)
437  {
438  save_in_ep = ep;
439  save_in_req = req;
440 
441  #ifdef DEBUG
442  printk("req->length = %d ***** Rudolf_Start_Ep_in\n\r", req->length);
443  #endif
444 
445  // reinit_write_data(ep, req);
447  }
448  else
449  {
450  #ifdef DEBUG
451  printk("***** Rudolf_Start_Ep_out\n");
452  #endif
453  }
454 
455  status = usb_ep_queue(ep, req, GFP_ATOMIC);
456 
457  if (status) {
458  struct usb_composite_dev *cdev;
459 
460  cdev = rudolf->function.config->cdev;
461  ERROR(cdev, "start %s %s --> %d\n",
462  is_in ? "IN" : "OUT",
463  ep->name, status);
464 
465  free_ep_req(ep, req);
466  }
467 
468  return status;
469 }
470 
471 static void disable_rudolf(struct f_rudolf *rudolf)
472 {
473  struct usb_composite_dev *cdev;
474 
475  cdev = rudolf->function.config->cdev;
476  disable_endpoints(cdev, rudolf->in_ep, rudolf->out_ep);
477  VDBG(cdev, "%s disabled\n", rudolf->function.name);
478 }
479 
480 static int
481 enable_rudolf(struct usb_composite_dev *cdev, struct f_rudolf *rudolf)
482 {
483  int result = 0;
484  const struct usb_endpoint_descriptor *ep_in, *ep_out;
485  struct usb_ep *ep;
486 
487  ep_in = ep_choose(cdev->gadget, &rudolf_in_hs_desc, &rudolf_in_fs_desc);
488 
489  ep_out = ep_choose(cdev->gadget, &rudolf_out_hs_desc, &rudolf_out_fs_desc);
490 
491  ep = rudolf->in_ep;
492 
493  result = usb_ep_enable(ep, ep_in);
494 
495  if (result < 0)
496  return result;
497 
498  ep->driver_data = rudolf;
499 
500  result = rudolf_start_ep(rudolf, true);
501 
502  if (result < 0) {
503 fail:
504  ep = rudolf->in_ep;
505  usb_ep_disable(ep);
506  ep->driver_data = NULL;
507  return result;
508  }
509 
510  /* one endpoint reads (sinks) anything OUT (from the host) */
511  ep = rudolf->out_ep;
512  result = usb_ep_enable(ep, ep_out);
513 
514  if (result < 0)
515  goto fail;
516 
517  ep->driver_data = rudolf;
518 
519  result = rudolf_start_ep(rudolf, false);
520 
521  if (result < 0) {
522  usb_ep_disable(ep);
523  ep->driver_data = NULL;
524  goto fail;
525  }
526 
527  DBG(cdev, "%s enabled\n", rudolf->function.name);
528 
529  return result;
530 }
531 
532 static int f_rudolf_set_alt(struct usb_function *f,
533  unsigned intf, unsigned alt)
534 {
535  struct f_rudolf *rudolf = func_to_rudolf(f);
536  struct usb_composite_dev *cdev = f->config->cdev;
537 
538  /* we know alt is zero */
539  if (rudolf->in_ep->driver_data)
540  disable_rudolf(rudolf);
541 
542  return enable_rudolf(cdev, rudolf);
543 }
544 
545 static void f_rudolf_disable(struct usb_function *f)
546 {
547  struct f_rudolf *rudolf = func_to_rudolf(f);
548 
549  disable_rudolf(rudolf);
550 }
551 
552 /*-------------------------------------------------------------------------*/
553 
554 static int rudolf_bind_config(struct usb_configuration *c)
555 {
556  struct f_rudolf *rudolf;
557  int status;
558 
559  rudolf = kzalloc(sizeof *rudolf, GFP_KERNEL);
560  if (!rudolf)
561  return -ENOMEM;
562 
563  rudolf->function.name = "rudolf xfer";
564  rudolf->function.descriptors = hs_rudolf_descs;
565  rudolf->function.bind = f_rudolf_bind;
566  rudolf->function.unbind = f_rudolf_unbind;
567  rudolf->function.set_alt = f_rudolf_set_alt;
568  rudolf->function.disable = f_rudolf_disable;
569 
570  status = usb_add_function(c, &rudolf->function);
571  if (status)
572  kfree(rudolf);
573  return status;
574 }
575 
576 #ifndef PCASM
577 static int rudolf_setup(struct usb_configuration *c,
578  const struct usb_ctrlrequest *ctrl)
579 {
580  struct usb_request *req = c->cdev->req;
581  int value = -EOPNOTSUPP;
582  u16 w_index = le16_to_cpu(ctrl->wIndex);
583  u16 w_value = le16_to_cpu(ctrl->wValue);
584  u16 w_length = le16_to_cpu(ctrl->wLength);
585  u16 length = 0;
586 
587  /* composite driver infrastructure handles everything except
588  * the two control test requests.
589  */
590 
591  switch (ctrl->bRequest) {
592 
593  /*
594  * These are the same vendor-specific requests supported by
595  * Intel's USB 2.0 compliance test devices. We exceed that
596  * device spec by allowing multiple-packet requests.
597  *
598  * NOTE: the Control-OUT data stays in req->buf ... better
599  * would be copying it into a scratch buffer, so that other
600  * requests may safely intervene.
601  */
602 
603  case 0x5b: /* control WRITE test -- fill the buffer */
604  if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
605  goto unknown;
606  if (w_value || w_index)
607  break;
608  /* just read that many bytes into the buffer */
609  if (w_length > req->length)
610  break;
611  value = w_length;
612  break;
613  case 0x5c: /* control READ test -- return the buffer */
614  if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
615  goto unknown;
616  if (w_value || w_index)
617  break;
618  /* expect those bytes are still in the buffer; send back */
619  if (w_length > req->length)
620  break;
621  value = w_length;
622  break;
623 
624  default:
625 unknown:
626  VDBG(c->cdev,
627  "unknown control req%02x.%02x v%04x i%04x l%d\n",
628  ctrl->bRequestType, ctrl->bRequest,
629  w_value, w_index, w_length);
630  }
631 
632  //HER SKAL HID DESC SENDES!!!
633  switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
634 
635 
636  case ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8
637  | USB_REQ_GET_DESCRIPTOR):
638  switch (w_value >> 8) {
639  case HID_DT_REPORT:
640  //VDBG(cdev, "USB_REQ_GET_DESCRIPTOR: REPORT\n");
641  length = w_length;
642  length = min_t(unsigned short, length,
643  sizeof hs_hid_report_descriptor);
644  memcpy(req->buf, hs_hid_report_descriptor, length);
645  value = length;
646  goto respond;
647  break;
648 
649  default:
650  //VDBG(cdev, "Unknown decriptor request 0x%x\n",
651  // value >> 8);
652  goto stall;
653  break;
654  }
655  break;
656  default:
657  //VDBG(cdev, "Unknown request 0x%x\n",
658  // ctrl->bRequest);
659  goto stall;
660  break;
661  }
662 
663 //HERTIL
664  /* respond with data transfer or status phase? */
665 stall:
666  return -EOPNOTSUPP;
667 
668 respond:
669  if (value >= 0) {
670  VDBG(c->cdev, "source/sink req%02x.%02x v%04x i%04x l%d\n",
671  ctrl->bRequestType, ctrl->bRequest,
672  w_value, w_index, w_length);
673  req->zero = 0;
674  req->length = value;
675  value = usb_ep_queue(c->cdev->gadget->ep0, req, GFP_ATOMIC);
676  if (value < 0)
677  ERROR(c->cdev, "source/sinkc response, err %d\n",
678  value);
679  }
680 
681  /* device either stalls (value < 0) or reports success */
682  return value;
683 }
684 #else
685 // Keep Eclipse happy
686 #endif
687 
688 static struct usb_configuration rudolf_driver = {
689  .label = "rudolf driver",
690  .strings = rudolf_strings,
691  .bind = rudolf_bind_config,
692  .setup = rudolf_setup,
693  .bConfigurationValue = 1,
694  .bmAttributes = USB_CONFIG_ATT_SELFPOWER,
695  /* .iConfiguration = DYNAMIC */
696 };
697 
702 int rudolf_add(struct usb_composite_dev *cdev, bool autoresume)
703 {
704  int id;
705 
706  /* allocate string ID(s) */
707  id = usb_string_id(cdev);
708  if (id < 0)
709  return id;
710  strings_rudolf[0].id = id;
711 
712  rudolf_intf.iInterface = id;
713  rudolf_driver.iConfiguration = 1; // id;
714 
715  /* support autoresume for remote wakeup testing */
716  if (autoresume)
717  rudolf_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
718 
719  /* support OTG systems */
720  if (gadget_is_otg(cdev->gadget)) {
721  rudolf_driver.descriptors = otg_desc;
722  rudolf_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
723  }
724 
725  return usb_add_config(cdev, &rudolf_driver);
726 }
int usb_string_id(struct usb_composite_dev *cdev)
Definition: computil.c:819
unsigned autoresume
Definition: d_usbdev.c:157
int usb_char_out_length
Definition: d_usbdev.c:109
uint8_t u8
Definition: common.h:160
struct usb_ep * out_ep
Definition: usb_function.c:43
struct usb_request * save_in_req
Definition: usb_function.c:56
struct usb_ep * save_in_ep
Definition: usb_function.c:55
struct usb_function function
Definition: usb_function.c:40
int rudolf_add(struct usb_composite_dev *cdev, bool autoresume)
Definition: usb_function.c:702
int usb_add_function(struct usb_configuration *config, struct usb_function *function)
Definition: computil.c:156
USB_SPEED UsbSpeed
Definition: computil.c:44
uint16_t u16
Definition: common.h:159
void disable_endpoints(struct usb_composite_dev *cdev, struct usb_ep *in, struct usb_ep *out)
Definition: d_usbdev.c:264
#define ERROR(ErrorCode)
Definition: lms2012.c:402
void free_ep_req(struct usb_ep *ep, struct usb_request *req)
Definition: d_usbdev.c:245
struct usb_request * alloc_ep_req(struct usb_ep *ep)
Definition: d_usbdev.c:229
int usb_char_in_length
Definition: d_usbdev.c:106
int usb_interface_id(struct usb_configuration *config, struct usb_function *function)
Definition: computil.c:287
int usb_add_config(struct usb_composite_dev *cdev, struct usb_configuration *config)
Definition: computil.c:614
struct usb_ep * in_ep
Definition: usb_function.c:42
int input_state
Definition: usb_function.c:54
char usb_char_buffer_out[MAX_EP_SIZE]
Definition: d_usbdev.c:107
char usb_char_buffer_in[MAX_EP_SIZE]
Definition: d_usbdev.c:104
#define NULL