blob: 6b1b1a7cb0265cca67002e7744dd979103dcfa4d [file] [log] [blame]
Brian Silverman395d6252013-09-13 20:58:14 -07001// Copyright 2012 Google Inc. All Rights Reserved.
2//
3// Usb Endpoint Interfaces.
4
5#ifndef _GLIBUSB_GLIBUSB_ENDPOINT_H_
6#define _GLIBUSB_GLIBUSB_ENDPOINT_H_
7
8#include <stddef.h>
9#include <stdint.h>
10#include <sys/types.h>
11#include <libusb.h>
12#include <boost/bind.hpp>
13#include <boost/thread.hpp>
14#include <boost/thread/condition.hpp>
15
16#include "gbuffer.h"
17
18#ifndef MAX_ISO_BUFFER_LENGTH
19#define MAX_ISO_BUFFER_LENGTH 32768
20#endif
21
22#ifndef MAX_BULK_BUFFER_LENGTH
23#define MAX_BULK_BUFFER_LENGTH 16384
24#endif
25
26#ifndef MAX_CTRL_BUFFER_LENGTH
27#define MAX_CTRL_BUFFER_LENGTH 4096
28#endif
29
30namespace glibusb {
31
32// Provides a base-class for all endpoints.
33class Buffer;
34
35class Notification {
36 public:
37 explicit Notification(bool prenotify = false);
38 bool HasBeenNotified() const;
39 void WaitForNotification() const;
40 bool WaitForNotificationWithTimeout(int64_t milliseconds) const;
41 void Notify();
42
43 private:
44 bool HasBeenNotifiedUnlocked() const;
45
46 mutable boost::mutex mutex_;
47 mutable boost::condition notified_changed_;
48 bool notified_;
49
50 Notification(const Notification &) = delete;
51 void operator=(const Notification &) = delete;
52};
53
54
55class UsbEndpoint {
56 public:
57 // The values for Direction are defined by the USB spec and must not be
58 // modified.
59 enum DirectionType { kIn = 0x80, kOut = 0x00 };
60 enum TransferType { kControl, kBulk, kInterrupt, kIsochronous };
61 enum IoStatus { kSuccess, kFail, kTimeout, kAbort, kNoDevice, kUnknown };
62
63 // The max transfer (in bytes) that the kernel supports.
64 static const int32_t kMaxBulkTransferBytes = MAX_BULK_BUFFER_LENGTH;
65
66 virtual ~UsbEndpoint() {}
67
68 // Returns the endpoint number.
69 int endpoint_address() const {
70 return endpoint_address_and_direction_ & LIBUSB_ENDPOINT_ADDRESS_MASK;
71 }
72
73 // Returns the direction.
74 DirectionType direction() const { return direction_; }
75
76 // Returns the transfer type.
77 TransferType transfer() const { return transfer_; }
78
79 // Returns the wMaxPacketSize value for this endpoint in the
80 // active device configuration.
81 int GetMaxPacketSize() { return DoGetMaxPacketSize(); }
82
83 // Returns the maximum packet size for this endpoint that
84 // can be sent or received during one microframe.
85 int GetMaxIsoPacketSize() { return DoGetMaxIsoPacketSize(); }
86
87 protected:
88 // Constructs an endpoint with the provided tranfser type and address.
89 UsbEndpoint(DirectionType direction, TransferType transfer,
90 int endpoint_address);
91
92 // Returns the address that libusb uses to refer to the endpoint. This
93 // includes the direction as the highest bit.
94 int endpoint_address_and_direction() const {
95 return endpoint_address_and_direction_;
96 }
97
98 private:
99 virtual int DoGetMaxPacketSize() = 0;
100 virtual int DoGetMaxIsoPacketSize() = 0;
101
102 // Endpoint type and direction.
103 DirectionType direction_;
104 TransferType transfer_;
105
106 // Endpoint address.
107 int endpoint_address_and_direction_;
108
109 UsbEndpoint(const UsbEndpoint &) = delete;
110 void operator=(const UsbEndpoint &) = delete;
111};
112
113// Provides an interface to allow reading from a USB endpoint.
114class UsbInEndpoint : public UsbEndpoint {
115 public:
116 // Constructs an endpoint with the provided transfer type and address.
117 UsbInEndpoint(TransferType transfer, int endpoint_address);
118 virtual ~UsbInEndpoint() {}
119
120 // Reads into the buffer from the endpoint until the transfer limit is
121 // reached, or a zero length packet/non full packet is received.
122 // Returns true on success. Waits forever.
123 bool Read(Buffer *out);
124
125 // Reads into the buffer from the endpoint until the transfer limit is
126 // reached, or a zero length packet/non full packet is received.
127 IoStatus ReadWithTimeout(int32_t timeout_milliseconds, Buffer *out);
128
129 // Reads into the buffer from the endpoint until the length is
130 // reached, or a zero length packet/non full packet is received.
131 // Returns true on success.
132 bool ReadAtMost(uint32_t length, Buffer *out);
133
134 // Reads into the buffer from the endpoint until the length is
135 // reached, or a zero length packet/non full packet is received.
136 IoStatus ReadAtMostWithTimeout(
137 uint32_t length, int32_t timeout_milliseconds, Buffer *out);
138
139 // Reads into the buffer from the endpoint until the length is
140 // reached, or a zero length packet/non full packet is received.
141 // Cancels the request when the notification is notified.
142 IoStatus ReadAtMostWithTimeoutAndNotification(
143 uint32_t length, int32_t timeout_milliseconds, Buffer *out,
144 Notification *quit);
145
146 private:
147 // Actually executes the read, with the length, timeout, buffer, and
148 // notification.
149 virtual IoStatus DoRead(
150 uint32_t length, int32_t timeout_milliseconds, Buffer *out,
151 Notification *quit) = 0;
152
153 UsbInEndpoint(const UsbInEndpoint &) = delete;
154 void operator=(const UsbInEndpoint &) = delete;
155};
156
157// Provides an interface to allow writing to a USB endpoint.
158class UsbOutEndpoint : public UsbEndpoint {
159 public:
160 // Constructs an endpoint with the provided tranfser type and address.
161 UsbOutEndpoint(TransferType transfer, int endpoint_address);
162 virtual ~UsbOutEndpoint() {}
163
164 // Writes the buffer to the endpoint. Returns true on success.
165 bool Write(const Buffer &buffer);
166
167 // Writes the buffer to the endpoint with timeout.
168 IoStatus WriteWithTimeout(const Buffer &buffer, int timeout_milliseconds);
169
170 private:
171 // Implements the actual write.
172 virtual IoStatus DoWrite(const Buffer &buffer,
173 int32_t timeout_milliseconds) = 0;
174
175 UsbOutEndpoint(const UsbOutEndpoint &) = delete;
176 void operator=(const UsbOutEndpoint &) = delete;
177};
178
179} // namespace glibusb
180
181#endif // _GLIBUSB_GLIBUSB_ENDPOINT_H_