| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "modules/webusb/USBDevice.h" | 5 #include "modules/webusb/USBDevice.h" |
| 6 | 6 |
| 7 #include "bindings/core/v8/CallbackPromiseAdapter.h" | 7 #include "bindings/core/v8/CallbackPromiseAdapter.h" |
| 8 #include "bindings/core/v8/ScriptPromise.h" | 8 #include "bindings/core/v8/ScriptPromise.h" |
| 9 #include "bindings/core/v8/ScriptPromiseResolver.h" | 9 #include "bindings/core/v8/ScriptPromiseResolver.h" |
| 10 #include "bindings/core/v8/ToV8.h" | 10 #include "bindings/core/v8/ToV8.h" |
| 11 #include "core/dom/DOMArrayBuffer.h" | 11 #include "core/dom/DOMArrayBuffer.h" |
| 12 #include "core/dom/DOMArrayBufferView.h" | 12 #include "core/dom/DOMArrayBufferView.h" |
| 13 #include "core/dom/DOMException.h" | 13 #include "core/dom/DOMException.h" |
| 14 #include "core/dom/ExceptionCode.h" | 14 #include "core/dom/ExceptionCode.h" |
| 15 #include "modules/webusb/USBConfiguration.h" | 15 #include "modules/webusb/USBConfiguration.h" |
| 16 #include "modules/webusb/USBControlTransferParameters.h" | 16 #include "modules/webusb/USBControlTransferParameters.h" |
| 17 #include "modules/webusb/USBError.h" | 17 #include "modules/webusb/USBError.h" |
| 18 #include "modules/webusb/USBInTransferResult.h" | 18 #include "modules/webusb/USBInTransferResult.h" |
| 19 #include "modules/webusb/USBIsochronousInTransferResult.h" | 19 #include "modules/webusb/USBIsochronousInTransferResult.h" |
| 20 #include "modules/webusb/USBIsochronousOutTransferResult.h" | 20 #include "modules/webusb/USBIsochronousOutTransferResult.h" |
| 21 #include "modules/webusb/USBOutTransferResult.h" | 21 #include "modules/webusb/USBOutTransferResult.h" |
| 22 #include "public/platform/modules/webusb/WebUSBTransferInfo.h" | 22 #include "public/platform/modules/webusb/WebUSBTransferInfo.h" |
| 23 #include "wtf/Assertions.h" | 23 #include "wtf/Assertions.h" |
| 24 | 24 |
| 25 namespace blink { | 25 namespace blink { |
| 26 | 26 |
| 27 namespace { | 27 namespace { |
| 28 | 28 |
| 29 const char kDeviceStateChangeInProgress[] = "An operation that changes the devic
e state is in progress."; | 29 const char kDeviceStateChangeInProgress[] = "An operation that changes the devic
e state is in progress."; |
| 30 const char kInterfaceNotFound[] = "The interface number provided is not supporte
d by the device in its current configuration."; |
| 31 const char kInterfaceStateChangeInProgress[] = "An operation that changes interf
ace state is in progress."; |
| 30 const char kOpenRequired[] = "The device must be opened first."; | 32 const char kOpenRequired[] = "The device must be opened first."; |
| 31 | 33 |
| 32 DOMException* convertControlTransferParameters( | 34 DOMException* convertControlTransferParameters( |
| 33 WebUSBDevice::TransferDirection direction, | 35 WebUSBDevice::TransferDirection direction, |
| 34 const USBControlTransferParameters& parameters, | 36 const USBControlTransferParameters& parameters, |
| 35 WebUSBDevice::ControlTransferParameters* webParameters) | 37 WebUSBDevice::ControlTransferParameters* webParameters) |
| 36 { | 38 { |
| 37 webParameters->direction = direction; | 39 webParameters->direction = direction; |
| 38 | 40 |
| 39 if (parameters.requestType() == "standard") | 41 if (parameters.requestType() == "standard") |
| 40 webParameters->type = WebUSBDevice::RequestType::Standard; | 42 webParameters->type = WebUSBDevice::RequestType::Standard; |
| 41 else if (parameters.requestType() == "class") | 43 else if (parameters.requestType() == "class") |
| 42 webParameters->type = WebUSBDevice::RequestType::Class; | 44 webParameters->type = WebUSBDevice::RequestType::Class; |
| 43 else if (parameters.requestType() == "vendor") | 45 else if (parameters.requestType() == "vendor") |
| 44 webParameters->type = WebUSBDevice::RequestType::Vendor; | 46 webParameters->type = WebUSBDevice::RequestType::Vendor; |
| 45 else | 47 else |
| 46 return DOMException::create(TypeMismatchError, "The control transfer req
uestType parameter is invalid."); | 48 return DOMException::create(TypeMismatchError, "The control transfer req
uestType parameter is invalid."); |
| 47 | 49 |
| 50 // TODO(reillyg): Check for interface and endpoint availability if that is |
| 51 // the control transfer target. |
| 48 if (parameters.recipient() == "device") | 52 if (parameters.recipient() == "device") |
| 49 webParameters->recipient = WebUSBDevice::RequestRecipient::Device; | 53 webParameters->recipient = WebUSBDevice::RequestRecipient::Device; |
| 50 else if (parameters.recipient() == "interface") | 54 else if (parameters.recipient() == "interface") |
| 51 webParameters->recipient = WebUSBDevice::RequestRecipient::Interface; | 55 webParameters->recipient = WebUSBDevice::RequestRecipient::Interface; |
| 52 else if (parameters.recipient() == "endpoint") | 56 else if (parameters.recipient() == "endpoint") |
| 53 webParameters->recipient = WebUSBDevice::RequestRecipient::Endpoint; | 57 webParameters->recipient = WebUSBDevice::RequestRecipient::Endpoint; |
| 54 else if (parameters.recipient() == "other") | 58 else if (parameters.recipient() == "other") |
| 55 webParameters->recipient = WebUSBDevice::RequestRecipient::Other; | 59 webParameters->recipient = WebUSBDevice::RequestRecipient::Other; |
| 56 else | 60 else |
| 57 return DOMException::create(TypeMismatchError, "The control transfer rec
ipient parameter is invalid."); | 61 return DOMException::create(TypeMismatchError, "The control transfer rec
ipient parameter is invalid."); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 83 : m_device(device) | 87 : m_device(device) |
| 84 , m_resolver(resolver) | 88 , m_resolver(resolver) |
| 85 , m_desiredState(desiredState) | 89 , m_desiredState(desiredState) |
| 86 { | 90 { |
| 87 } | 91 } |
| 88 | 92 |
| 89 void onSuccess() override | 93 void onSuccess() override |
| 90 { | 94 { |
| 91 if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContex
t()->activeDOMObjectsAreStopped()) | 95 if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContex
t()->activeDOMObjectsAreStopped()) |
| 92 return; | 96 return; |
| 93 if (m_device) | 97 m_device->onDeviceOpenedOrClosed(m_desiredState); |
| 94 m_device->onDeviceOpenedOrClosed(m_desiredState); | |
| 95 m_resolver->resolve(); | 98 m_resolver->resolve(); |
| 96 } | 99 } |
| 97 | 100 |
| 98 void onError(const WebUSBError& e) override | 101 void onError(const WebUSBError& e) override |
| 99 { | 102 { |
| 100 if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContex
t()->activeDOMObjectsAreStopped()) | 103 if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContex
t()->activeDOMObjectsAreStopped()) |
| 101 return; | 104 return; |
| 102 if (m_device) | 105 m_device->onDeviceOpenedOrClosed(!m_desiredState); |
| 103 m_device->onDeviceOpenedOrClosed(!m_desiredState); | |
| 104 m_resolver->reject(USBError::take(m_resolver, e)); | 106 m_resolver->reject(USBError::take(m_resolver, e)); |
| 105 } | 107 } |
| 106 | 108 |
| 107 private: | 109 private: |
| 108 WeakPersistent<USBDevice> m_device; | 110 Persistent<USBDevice> m_device; |
| 109 Persistent<ScriptPromiseResolver> m_resolver; | 111 Persistent<ScriptPromiseResolver> m_resolver; |
| 110 bool m_desiredState; // true: open, false: closed | 112 bool m_desiredState; // true: open, false: closed |
| 111 }; | 113 }; |
| 112 | 114 |
| 113 class SelectConfigurationPromiseAdapter : public WebCallbacks<void, const WebUSB
Error&> { | 115 class SelectConfigurationPromiseAdapter : public WebCallbacks<void, const WebUSB
Error&> { |
| 114 public: | 116 public: |
| 115 SelectConfigurationPromiseAdapter(USBDevice* device, ScriptPromiseResolver*
resolver, int configurationIndex) | 117 SelectConfigurationPromiseAdapter(USBDevice* device, ScriptPromiseResolver*
resolver, size_t configurationIndex) |
| 116 : m_device(device) | 118 : m_device(device) |
| 117 , m_resolver(resolver) | 119 , m_resolver(resolver) |
| 118 , m_configurationIndex(configurationIndex) | 120 , m_configurationIndex(configurationIndex) |
| 119 { | 121 { |
| 120 } | 122 } |
| 121 | 123 |
| 122 void onSuccess() override | 124 void onSuccess() override |
| 123 { | 125 { |
| 124 if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContex
t()->activeDOMObjectsAreStopped()) | 126 if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContex
t()->activeDOMObjectsAreStopped()) |
| 125 return; | 127 return; |
| 126 if (m_device) | 128 m_device->onConfigurationSelected(true /* success */, m_configurationInd
ex); |
| 127 m_device->onConfigurationSelected(true /* success */, m_configuratio
nIndex); | |
| 128 m_resolver->resolve(); | 129 m_resolver->resolve(); |
| 129 } | 130 } |
| 130 | 131 |
| 131 void onError(const WebUSBError& e) override | 132 void onError(const WebUSBError& e) override |
| 132 { | 133 { |
| 133 if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContex
t()->activeDOMObjectsAreStopped()) | 134 if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContex
t()->activeDOMObjectsAreStopped()) |
| 134 return; | 135 return; |
| 135 if (m_device) | 136 m_device->onConfigurationSelected(false /* failure */, m_configurationIn
dex); |
| 136 m_device->onConfigurationSelected(false /* failure */, m_configurati
onIndex); | |
| 137 m_resolver->reject(USBError::take(m_resolver, e)); | 137 m_resolver->reject(USBError::take(m_resolver, e)); |
| 138 } | 138 } |
| 139 | 139 |
| 140 private: | 140 private: |
| 141 WeakPersistent<USBDevice> m_device; | 141 Persistent<USBDevice> m_device; |
| 142 Persistent<ScriptPromiseResolver> m_resolver; | 142 Persistent<ScriptPromiseResolver> m_resolver; |
| 143 int m_configurationIndex; | 143 size_t m_configurationIndex; |
| 144 }; |
| 145 |
| 146 class ClaimInterfacePromiseAdapter : public WebCallbacks<void, const WebUSBError
&> { |
| 147 public: |
| 148 ClaimInterfacePromiseAdapter(USBDevice* device, ScriptPromiseResolver* resol
ver, size_t interfaceIndex, bool desiredState) |
| 149 : m_device(device) |
| 150 , m_resolver(resolver) |
| 151 , m_interfaceIndex(interfaceIndex) |
| 152 , m_desiredState(desiredState) |
| 153 { |
| 154 } |
| 155 |
| 156 void onSuccess() override |
| 157 { |
| 158 if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContex
t()->activeDOMObjectsAreStopped()) |
| 159 return; |
| 160 m_device->onInterfaceClaimedOrUnclaimed(m_desiredState, m_interfaceIndex
); |
| 161 m_resolver->resolve(); |
| 162 } |
| 163 |
| 164 void onError(const WebUSBError& e) override |
| 165 { |
| 166 if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContex
t()->activeDOMObjectsAreStopped()) |
| 167 return; |
| 168 m_device->onInterfaceClaimedOrUnclaimed(!m_desiredState, m_interfaceInde
x); |
| 169 m_resolver->reject(USBError::take(m_resolver, e)); |
| 170 } |
| 171 |
| 172 private: |
| 173 Persistent<USBDevice> m_device; |
| 174 Persistent<ScriptPromiseResolver> m_resolver; |
| 175 size_t m_interfaceIndex; |
| 176 bool m_desiredState; // true: claimed, false: unclaimed |
| 144 }; | 177 }; |
| 145 | 178 |
| 146 class InputTransferResult { | 179 class InputTransferResult { |
| 147 WTF_MAKE_NONCOPYABLE(InputTransferResult); | 180 WTF_MAKE_NONCOPYABLE(InputTransferResult); |
| 148 public: | 181 public: |
| 149 using WebType = OwnPtr<WebUSBTransferInfo>; | 182 using WebType = OwnPtr<WebUSBTransferInfo>; |
| 150 | 183 |
| 151 static USBInTransferResult* take(ScriptPromiseResolver*, PassOwnPtr<WebUSBTr
ansferInfo> webTransferInfo) | 184 static USBInTransferResult* take(ScriptPromiseResolver*, PassOwnPtr<WebUSBTr
ansferInfo> webTransferInfo) |
| 152 { | 185 { |
| 153 ASSERT(webTransferInfo->status.size() == 1); | 186 ASSERT(webTransferInfo->status.size() == 1); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 USBDevice* USBDevice::take(ScriptPromiseResolver* resolver, PassOwnPtr<WebUSBDev
ice> device) | 275 USBDevice* USBDevice::take(ScriptPromiseResolver* resolver, PassOwnPtr<WebUSBDev
ice> device) |
| 243 { | 276 { |
| 244 return USBDevice::create(device, resolver->getExecutionContext()); | 277 return USBDevice::create(device, resolver->getExecutionContext()); |
| 245 } | 278 } |
| 246 | 279 |
| 247 USBDevice::USBDevice(PassOwnPtr<WebUSBDevice> device, ExecutionContext* context) | 280 USBDevice::USBDevice(PassOwnPtr<WebUSBDevice> device, ExecutionContext* context) |
| 248 : ContextLifecycleObserver(context) | 281 : ContextLifecycleObserver(context) |
| 249 , m_device(device) | 282 , m_device(device) |
| 250 , m_opened(false) | 283 , m_opened(false) |
| 251 , m_deviceStateChangeInProgress(false) | 284 , m_deviceStateChangeInProgress(false) |
| 285 , m_configurationIndex(-1) |
| 252 { | 286 { |
| 253 m_configurationIndex = findConfigurationIndex(info().activeConfiguration); | 287 int configurationIndex = findConfigurationIndex(info().activeConfiguration); |
| 288 if (configurationIndex != -1) |
| 289 onConfigurationSelected(true /* success */, configurationIndex); |
| 254 } | 290 } |
| 255 | 291 |
| 256 void USBDevice::onDeviceOpenedOrClosed(bool opened) | 292 void USBDevice::onDeviceOpenedOrClosed(bool opened) |
| 257 { | 293 { |
| 258 m_opened = opened; | 294 m_opened = opened; |
| 259 m_deviceStateChangeInProgress = false; | 295 m_deviceStateChangeInProgress = false; |
| 260 } | 296 } |
| 261 | 297 |
| 262 void USBDevice::onConfigurationSelected(bool success, int configurationIndex) | 298 void USBDevice::onConfigurationSelected(bool success, size_t configurationIndex) |
| 263 { | 299 { |
| 264 if (success) | 300 if (success) { |
| 265 m_configurationIndex = configurationIndex; | 301 m_configurationIndex = configurationIndex; |
| 302 size_t numInterfaces = info().configurations[m_configurationIndex].inter
faces.size(); |
| 303 m_claimedInterfaces.clearAll(); |
| 304 m_claimedInterfaces.resize(numInterfaces); |
| 305 m_interfaceStateChangeInProgress.clearAll(); |
| 306 m_interfaceStateChangeInProgress.resize(numInterfaces); |
| 307 } |
| 266 m_deviceStateChangeInProgress = false; | 308 m_deviceStateChangeInProgress = false; |
| 267 } | 309 } |
| 268 | 310 |
| 311 void USBDevice::onInterfaceClaimedOrUnclaimed(bool claimed, size_t interfaceInde
x) |
| 312 { |
| 313 if (claimed) |
| 314 m_claimedInterfaces.set(interfaceIndex); |
| 315 else |
| 316 m_claimedInterfaces.clear(interfaceIndex); |
| 317 m_interfaceStateChangeInProgress.clear(interfaceIndex); |
| 318 } |
| 319 |
| 320 bool USBDevice::isInterfaceClaimed(size_t configurationIndex, size_t interfaceIn
dex) const |
| 321 { |
| 322 return m_configurationIndex != -1 && static_cast<size_t>(m_configurationInde
x) == configurationIndex && m_claimedInterfaces.get(interfaceIndex); |
| 323 } |
| 324 |
| 269 USBConfiguration* USBDevice::configuration() const | 325 USBConfiguration* USBDevice::configuration() const |
| 270 { | 326 { |
| 271 if (m_configurationIndex != -1) | 327 if (m_configurationIndex != -1) |
| 272 return USBConfiguration::create(this, m_configurationIndex); | 328 return USBConfiguration::create(this, m_configurationIndex); |
| 273 return nullptr; | 329 return nullptr; |
| 274 } | 330 } |
| 275 | 331 |
| 276 HeapVector<Member<USBConfiguration>> USBDevice::configurations() const | 332 HeapVector<Member<USBConfiguration>> USBDevice::configurations() const |
| 277 { | 333 { |
| 278 HeapVector<Member<USBConfiguration>> configurations; | 334 HeapVector<Member<USBConfiguration>> configurations; |
| 279 size_t numConfigurations = info().configurations.size(); | 335 size_t numConfigurations = info().configurations.size(); |
| 280 for (size_t i = 0; i < numConfigurations; ++i) | 336 for (size_t i = 0; i < numConfigurations; ++i) |
| 281 configurations.append(USBConfiguration::create(this, i)); | 337 configurations.append(USBConfiguration::create(this, i)); |
| 282 return configurations; | 338 return configurations; |
| 283 } | 339 } |
| 284 | 340 |
| 285 ScriptPromise USBDevice::open(ScriptState* scriptState) | 341 ScriptPromise USBDevice::open(ScriptState* scriptState) |
| 286 { | 342 { |
| 287 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 343 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 288 ScriptPromise promise = resolver->promise(); | 344 ScriptPromise promise = resolver->promise(); |
| 289 if (m_deviceStateChangeInProgress) { | 345 if (ensureNoDeviceOrInterfaceChangeInProgress(resolver)) { |
| 290 resolver->reject(DOMException::create(InvalidStateError, kDeviceStateCha
ngeInProgress)); | 346 if (m_opened) { |
| 291 } else if (m_opened) { | 347 resolver->resolve(); |
| 292 resolver->resolve(); | 348 } else { |
| 293 } else { | 349 m_deviceStateChangeInProgress = true; |
| 294 m_deviceStateChangeInProgress = true; | 350 m_device->open(new OpenClosePromiseAdapter(this, resolver, true /* o
pen */)); |
| 295 m_device->open(new OpenClosePromiseAdapter(this, resolver, true /* open
*/)); | 351 } |
| 296 } | 352 } |
| 297 return promise; | 353 return promise; |
| 298 } | 354 } |
| 299 | 355 |
| 300 ScriptPromise USBDevice::close(ScriptState* scriptState) | 356 ScriptPromise USBDevice::close(ScriptState* scriptState) |
| 301 { | 357 { |
| 302 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 358 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 303 ScriptPromise promise = resolver->promise(); | 359 ScriptPromise promise = resolver->promise(); |
| 304 if (m_deviceStateChangeInProgress) { | 360 if (ensureNoDeviceOrInterfaceChangeInProgress(resolver)) { |
| 305 resolver->reject(DOMException::create(InvalidStateError, kDeviceStateCha
ngeInProgress)); | 361 if (!m_opened) { |
| 306 } else if (!m_opened) { | 362 resolver->resolve(); |
| 307 resolver->resolve(); | 363 } else { |
| 308 } else { | 364 m_deviceStateChangeInProgress = true; |
| 309 m_deviceStateChangeInProgress = true; | 365 m_device->close(new OpenClosePromiseAdapter(this, resolver, false /*
closed */)); |
| 310 m_device->close(new OpenClosePromiseAdapter(this, resolver, false /* clo
sed */)); | 366 } |
| 311 } | 367 } |
| 312 return promise; | 368 return promise; |
| 313 } | 369 } |
| 314 | 370 |
| 315 ScriptPromise USBDevice::selectConfiguration(ScriptState* scriptState, uint8_t c
onfigurationValue) | 371 ScriptPromise USBDevice::selectConfiguration(ScriptState* scriptState, uint8_t c
onfigurationValue) |
| 316 { | 372 { |
| 317 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 373 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 318 ScriptPromise promise = resolver->promise(); | 374 ScriptPromise promise = resolver->promise(); |
| 319 if (!m_opened) { | 375 if (ensureNoDeviceOrInterfaceChangeInProgress(resolver)) { |
| 320 resolver->reject(DOMException::create(InvalidStateError, kOpenRequired))
; | 376 if (!m_opened) { |
| 321 } else if (m_deviceStateChangeInProgress) { | 377 resolver->reject(DOMException::create(InvalidStateError, kOpenRequir
ed)); |
| 322 resolver->reject(DOMException::create(InvalidStateError, kDeviceStateCha
ngeInProgress)); | |
| 323 } else { | |
| 324 int configurationIndex = findConfigurationIndex(configurationValue); | |
| 325 if (configurationIndex == -1) { | |
| 326 resolver->reject(DOMException::create(NotFoundError, "The configurat
ion value provided is not supported by the device.")); | |
| 327 } else if (m_configurationIndex == configurationIndex) { | |
| 328 resolver->resolve(); | |
| 329 } else { | 378 } else { |
| 330 m_deviceStateChangeInProgress = true; | 379 int configurationIndex = findConfigurationIndex(configurationValue); |
| 331 m_device->setConfiguration(configurationValue, new SelectConfigurati
onPromiseAdapter(this, resolver, configurationIndex)); | 380 if (configurationIndex == -1) { |
| 381 resolver->reject(DOMException::create(NotFoundError, "The config
uration value provided is not supported by the device.")); |
| 382 } else if (m_configurationIndex == configurationIndex) { |
| 383 resolver->resolve(); |
| 384 } else { |
| 385 m_deviceStateChangeInProgress = true; |
| 386 m_device->setConfiguration(configurationValue, new SelectConfigu
rationPromiseAdapter(this, resolver, configurationIndex)); |
| 387 } |
| 332 } | 388 } |
| 333 } | 389 } |
| 334 return promise; | 390 return promise; |
| 335 } | 391 } |
| 336 | 392 |
| 337 ScriptPromise USBDevice::claimInterface(ScriptState* scriptState, uint8_t interf
aceNumber) | 393 ScriptPromise USBDevice::claimInterface(ScriptState* scriptState, uint8_t interf
aceNumber) |
| 338 { | 394 { |
| 339 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 395 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 340 ScriptPromise promise = resolver->promise(); | 396 ScriptPromise promise = resolver->promise(); |
| 341 if (ensureDeviceConfigured(resolver)) | 397 if (ensureDeviceConfigured(resolver)) { |
| 342 m_device->claimInterface(interfaceNumber, new CallbackPromiseAdapter<voi
d, USBError>(resolver)); | 398 int interfaceIndex = findInterfaceIndex(interfaceNumber); |
| 399 if (interfaceIndex == -1) { |
| 400 resolver->reject(DOMException::create(NotFoundError, kInterfaceNotFo
und)); |
| 401 } else if (m_interfaceStateChangeInProgress.get(interfaceIndex)) { |
| 402 resolver->reject(DOMException::create(InvalidStateError, kInterfaceS
tateChangeInProgress)); |
| 403 } else if (m_claimedInterfaces.get(interfaceIndex)) { |
| 404 resolver->resolve(); |
| 405 } else { |
| 406 m_interfaceStateChangeInProgress.set(interfaceIndex); |
| 407 m_device->claimInterface(interfaceNumber, new ClaimInterfacePromiseA
dapter(this, resolver, interfaceIndex, true /* claim */)); |
| 408 } |
| 409 } |
| 343 return promise; | 410 return promise; |
| 344 } | 411 } |
| 345 | 412 |
| 346 ScriptPromise USBDevice::releaseInterface(ScriptState* scriptState, uint8_t inte
rfaceNumber) | 413 ScriptPromise USBDevice::releaseInterface(ScriptState* scriptState, uint8_t inte
rfaceNumber) |
| 347 { | 414 { |
| 348 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 415 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 349 ScriptPromise promise = resolver->promise(); | 416 ScriptPromise promise = resolver->promise(); |
| 350 if (ensureDeviceConfigured(resolver)) | 417 if (ensureDeviceConfigured(resolver)) { |
| 351 m_device->releaseInterface(interfaceNumber, new CallbackPromiseAdapter<v
oid, USBError>(resolver)); | 418 int interfaceIndex = findInterfaceIndex(interfaceNumber); |
| 419 if (interfaceIndex == -1) { |
| 420 resolver->reject(DOMException::create(NotFoundError, "The interface
number provided is not supported by the device in its current configuration.")); |
| 421 } else if (m_interfaceStateChangeInProgress.get(interfaceIndex)) { |
| 422 resolver->reject(DOMException::create(InvalidStateError, kInterfaceS
tateChangeInProgress)); |
| 423 } else if (!m_claimedInterfaces.get(interfaceIndex)) { |
| 424 resolver->resolve(); |
| 425 } else { |
| 426 m_interfaceStateChangeInProgress.set(interfaceIndex); |
| 427 m_device->releaseInterface(interfaceNumber, new ClaimInterfacePromis
eAdapter(this, resolver, interfaceIndex, false /* release */)); |
| 428 } |
| 429 } |
| 352 return promise; | 430 return promise; |
| 353 } | 431 } |
| 354 | 432 |
| 355 ScriptPromise USBDevice::setInterface(ScriptState* scriptState, uint8_t interfac
eNumber, uint8_t alternateSetting) | 433 ScriptPromise USBDevice::setInterface(ScriptState* scriptState, uint8_t interfac
eNumber, uint8_t alternateSetting) |
| 356 { | 434 { |
| 357 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 435 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 358 ScriptPromise promise = resolver->promise(); | 436 ScriptPromise promise = resolver->promise(); |
| 359 if (ensureDeviceConfigured(resolver)) | 437 if (ensureInterfaceClaimed(interfaceNumber, resolver)) |
| 360 m_device->setInterface(interfaceNumber, alternateSetting, new CallbackPr
omiseAdapter<void, USBError>(resolver)); | 438 m_device->setInterface(interfaceNumber, alternateSetting, new CallbackPr
omiseAdapter<void, USBError>(resolver)); |
| 361 return promise; | 439 return promise; |
| 362 } | 440 } |
| 363 | 441 |
| 364 ScriptPromise USBDevice::controlTransferIn(ScriptState* scriptState, const USBCo
ntrolTransferParameters& setup, unsigned length) | 442 ScriptPromise USBDevice::controlTransferIn(ScriptState* scriptState, const USBCo
ntrolTransferParameters& setup, unsigned length) |
| 365 { | 443 { |
| 366 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 444 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 367 ScriptPromise promise = resolver->promise(); | 445 ScriptPromise promise = resolver->promise(); |
| 368 if (ensureDeviceConfigured(resolver)) { | 446 if (ensureDeviceConfigured(resolver)) { |
| 369 WebUSBDevice::ControlTransferParameters parameters; | 447 WebUSBDevice::ControlTransferParameters parameters; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 if (error) { | 479 if (error) { |
| 402 resolver->reject(error); | 480 resolver->reject(error); |
| 403 } else { | 481 } else { |
| 404 BufferSource buffer(data); | 482 BufferSource buffer(data); |
| 405 m_device->controlTransfer(parameters, buffer.data(), buffer.size(),
0, new CallbackPromiseAdapter<OutputTransferResult, USBError>(resolver)); | 483 m_device->controlTransfer(parameters, buffer.data(), buffer.size(),
0, new CallbackPromiseAdapter<OutputTransferResult, USBError>(resolver)); |
| 406 } | 484 } |
| 407 } | 485 } |
| 408 return promise; | 486 return promise; |
| 409 } | 487 } |
| 410 | 488 |
| 411 ScriptPromise USBDevice::clearHalt(ScriptState* scriptState, uint8_t endpointNum
ber) | 489 ScriptPromise USBDevice::clearHalt(ScriptState* scriptState, String direction, u
int8_t endpointNumber) |
| 412 { | 490 { |
| 413 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 491 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 414 ScriptPromise promise = resolver->promise(); | 492 ScriptPromise promise = resolver->promise(); |
| 415 if (ensureDeviceConfigured(resolver)) | 493 if (ensureEndpointAvailable(direction == "in", endpointNumber, resolver)) |
| 416 m_device->clearHalt(endpointNumber, new CallbackPromiseAdapter<void, USB
Error>(resolver)); | 494 m_device->clearHalt(endpointNumber, new CallbackPromiseAdapter<void, USB
Error>(resolver)); |
| 417 return promise; | 495 return promise; |
| 418 } | 496 } |
| 419 | 497 |
| 420 ScriptPromise USBDevice::transferIn(ScriptState* scriptState, uint8_t endpointNu
mber, unsigned length) | 498 ScriptPromise USBDevice::transferIn(ScriptState* scriptState, uint8_t endpointNu
mber, unsigned length) |
| 421 { | 499 { |
| 422 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 500 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 423 ScriptPromise promise = resolver->promise(); | 501 ScriptPromise promise = resolver->promise(); |
| 424 if (ensureDeviceConfigured(resolver)) | 502 if (ensureEndpointAvailable(true /* in */, endpointNumber, resolver)) |
| 425 m_device->transfer(WebUSBDevice::TransferDirection::In, endpointNumber,
nullptr, length, 0, new CallbackPromiseAdapter<InputTransferResult, USBError>(re
solver)); | 503 m_device->transfer(WebUSBDevice::TransferDirection::In, endpointNumber,
nullptr, length, 0, new CallbackPromiseAdapter<InputTransferResult, USBError>(re
solver)); |
| 426 return promise; | 504 return promise; |
| 427 } | 505 } |
| 428 | 506 |
| 429 ScriptPromise USBDevice::transferOut(ScriptState* scriptState, uint8_t endpointN
umber, const ArrayBufferOrArrayBufferView& data) | 507 ScriptPromise USBDevice::transferOut(ScriptState* scriptState, uint8_t endpointN
umber, const ArrayBufferOrArrayBufferView& data) |
| 430 { | 508 { |
| 431 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 509 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 432 ScriptPromise promise = resolver->promise(); | 510 ScriptPromise promise = resolver->promise(); |
| 433 if (ensureDeviceConfigured(resolver)) { | 511 if (ensureEndpointAvailable(false /* out */, endpointNumber, resolver)) { |
| 434 BufferSource buffer(data); | 512 BufferSource buffer(data); |
| 435 m_device->transfer(WebUSBDevice::TransferDirection::Out, endpointNumber,
buffer.data(), buffer.size(), 0, new CallbackPromiseAdapter<OutputTransferResul
t, USBError>(resolver)); | 513 m_device->transfer(WebUSBDevice::TransferDirection::Out, endpointNumber,
buffer.data(), buffer.size(), 0, new CallbackPromiseAdapter<OutputTransferResul
t, USBError>(resolver)); |
| 436 } | 514 } |
| 437 return promise; | 515 return promise; |
| 438 } | 516 } |
| 439 | 517 |
| 440 ScriptPromise USBDevice::isochronousTransferIn(ScriptState* scriptState, uint8_t
endpointNumber, Vector<unsigned> packetLengths) | 518 ScriptPromise USBDevice::isochronousTransferIn(ScriptState* scriptState, uint8_t
endpointNumber, Vector<unsigned> packetLengths) |
| 441 { | 519 { |
| 442 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 520 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 443 ScriptPromise promise = resolver->promise(); | 521 ScriptPromise promise = resolver->promise(); |
| 444 if (ensureDeviceConfigured(resolver)) | 522 if (ensureEndpointAvailable(true /* in */, endpointNumber, resolver)) |
| 445 m_device->isochronousTransfer(WebUSBDevice::TransferDirection::In, endpo
intNumber, nullptr, 0, packetLengths, 0, new CallbackPromiseAdapter<IsochronousI
nputTransferResult, USBError>(resolver)); | 523 m_device->isochronousTransfer(WebUSBDevice::TransferDirection::In, endpo
intNumber, nullptr, 0, packetLengths, 0, new CallbackPromiseAdapter<IsochronousI
nputTransferResult, USBError>(resolver)); |
| 446 return promise; | 524 return promise; |
| 447 } | 525 } |
| 448 | 526 |
| 449 ScriptPromise USBDevice::isochronousTransferOut(ScriptState* scriptState, uint8_
t endpointNumber, const ArrayBufferOrArrayBufferView& data, Vector<unsigned> pac
ketLengths) | 527 ScriptPromise USBDevice::isochronousTransferOut(ScriptState* scriptState, uint8_
t endpointNumber, const ArrayBufferOrArrayBufferView& data, Vector<unsigned> pac
ketLengths) |
| 450 { | 528 { |
| 451 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 529 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 452 ScriptPromise promise = resolver->promise(); | 530 ScriptPromise promise = resolver->promise(); |
| 453 if (ensureDeviceConfigured(resolver)) { | 531 if (ensureEndpointAvailable(false /* out */, endpointNumber, resolver)) { |
| 454 BufferSource buffer(data); | 532 BufferSource buffer(data); |
| 455 m_device->isochronousTransfer(WebUSBDevice::TransferDirection::Out, endp
ointNumber, buffer.data(), buffer.size(), packetLengths, 0, new CallbackPromiseA
dapter<IsochronousOutputTransferResult, USBError>(resolver)); | 533 m_device->isochronousTransfer(WebUSBDevice::TransferDirection::Out, endp
ointNumber, buffer.data(), buffer.size(), packetLengths, 0, new CallbackPromiseA
dapter<IsochronousOutputTransferResult, USBError>(resolver)); |
| 456 } | 534 } |
| 457 return promise; | 535 return promise; |
| 458 } | 536 } |
| 459 | 537 |
| 460 ScriptPromise USBDevice::reset(ScriptState* scriptState) | 538 ScriptPromise USBDevice::reset(ScriptState* scriptState) |
| 461 { | 539 { |
| 462 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 540 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
| 463 ScriptPromise promise = resolver->promise(); | 541 ScriptPromise promise = resolver->promise(); |
| 464 if (!m_opened) | 542 if (ensureNoDeviceOrInterfaceChangeInProgress(resolver)) { |
| 465 resolver->reject(DOMException::create(InvalidStateError, kOpenRequired))
; | 543 if (!m_opened) |
| 466 else if (m_deviceStateChangeInProgress) | 544 resolver->reject(DOMException::create(InvalidStateError, kOpenRequir
ed)); |
| 467 resolver->reject(DOMException::create(InvalidStateError, kDeviceStateCha
ngeInProgress)); | 545 else |
| 468 else | 546 m_device->reset(new CallbackPromiseAdapter<void, USBError>(resolver)
); |
| 469 m_device->reset(new CallbackPromiseAdapter<void, USBError>(resolver)); | 547 } |
| 470 return promise; | 548 return promise; |
| 471 } | 549 } |
| 472 | 550 |
| 473 void USBDevice::contextDestroyed() | 551 void USBDevice::contextDestroyed() |
| 474 { | 552 { |
| 475 if (m_opened) | 553 if (m_opened) |
| 476 m_device->close(new WebUSBDeviceCloseCallbacks()); | 554 m_device->close(new WebUSBDeviceCloseCallbacks()); |
| 477 } | 555 } |
| 478 | 556 |
| 479 DEFINE_TRACE(USBDevice) | 557 DEFINE_TRACE(USBDevice) |
| 480 { | 558 { |
| 481 ContextLifecycleObserver::trace(visitor); | 559 ContextLifecycleObserver::trace(visitor); |
| 482 } | 560 } |
| 483 | 561 |
| 484 int USBDevice::findConfigurationIndex(uint8_t configurationValue) const | 562 int USBDevice::findConfigurationIndex(uint8_t configurationValue) const |
| 485 { | 563 { |
| 486 const auto& configurations = info().configurations; | 564 const auto& configurations = info().configurations; |
| 487 for (size_t i = 0; i < configurations.size(); ++i) { | 565 for (size_t i = 0; i < configurations.size(); ++i) { |
| 488 if (configurations[i].configurationValue == configurationValue) | 566 if (configurations[i].configurationValue == configurationValue) |
| 489 return i; | 567 return i; |
| 490 } | 568 } |
| 491 return -1; | 569 return -1; |
| 492 } | 570 } |
| 493 | 571 |
| 572 int USBDevice::findInterfaceIndex(uint8_t interfaceNumber) const |
| 573 { |
| 574 ASSERT(m_configurationIndex != -1); |
| 575 const auto& interfaces = info().configurations[m_configurationIndex].interfa
ces; |
| 576 for (size_t i = 0; i < interfaces.size(); ++i) { |
| 577 if (interfaces[i].interfaceNumber == interfaceNumber) |
| 578 return i; |
| 579 } |
| 580 return -1; |
| 581 } |
| 582 |
| 583 bool USBDevice::ensureNoDeviceOrInterfaceChangeInProgress(ScriptPromiseResolver*
resolver) const |
| 584 { |
| 585 if (m_deviceStateChangeInProgress) { |
| 586 resolver->reject(DOMException::create(InvalidStateError, kDeviceStateCha
ngeInProgress)); |
| 587 } else if (anyInterfaceChangeInProgress()) { |
| 588 resolver->reject(DOMException::create(InvalidStateError, kInterfaceState
ChangeInProgress)); |
| 589 } else { |
| 590 return true; |
| 591 } |
| 592 return false; |
| 593 } |
| 594 |
| 494 bool USBDevice::ensureDeviceConfigured(ScriptPromiseResolver* resolver) const | 595 bool USBDevice::ensureDeviceConfigured(ScriptPromiseResolver* resolver) const |
| 495 { | 596 { |
| 496 if (!m_opened) { | 597 if (!m_opened) { |
| 497 resolver->reject(DOMException::create(InvalidStateError, kOpenRequired))
; | 598 resolver->reject(DOMException::create(InvalidStateError, kOpenRequired))
; |
| 498 } else if (m_deviceStateChangeInProgress) { | 599 } else if (m_deviceStateChangeInProgress) { |
| 499 resolver->reject(DOMException::create(InvalidStateError, kDeviceStateCha
ngeInProgress)); | 600 resolver->reject(DOMException::create(InvalidStateError, kDeviceStateCha
ngeInProgress)); |
| 500 } else if (m_configurationIndex == -1) { | 601 } else if (m_configurationIndex == -1) { |
| 501 resolver->reject(DOMException::create(InvalidStateError, "The device mus
t have a configuration selected.")); | 602 resolver->reject(DOMException::create(InvalidStateError, "The device mus
t have a configuration selected.")); |
| 502 } else { | 603 } else { |
| 503 return true; | 604 return true; |
| 504 } | 605 } |
| 505 return false; | 606 return false; |
| 506 } | 607 } |
| 507 | 608 |
| 609 bool USBDevice::ensureInterfaceClaimed(uint8_t interfaceNumber, ScriptPromiseRes
olver* resolver) const |
| 610 { |
| 611 if (!ensureDeviceConfigured(resolver)) |
| 612 return false; |
| 613 int interfaceIndex = findInterfaceIndex(interfaceNumber); |
| 614 if (interfaceIndex == -1) { |
| 615 resolver->reject(DOMException::create(NotFoundError, kInterfaceNotFound)
); |
| 616 } else if (m_interfaceStateChangeInProgress.get(interfaceIndex)) { |
| 617 resolver->reject(DOMException::create(InvalidStateError, kInterfaceState
ChangeInProgress)); |
| 618 } else if (!m_claimedInterfaces.get(interfaceIndex)) { |
| 619 resolver->reject(DOMException::create(InvalidStateError, "The specified
interface has not been claimed.")); |
| 620 } else { |
| 621 return true; |
| 622 } |
| 623 return false; |
| 624 } |
| 625 |
| 626 bool USBDevice::ensureEndpointAvailable(bool inTransfer, uint8_t endpointNumber,
ScriptPromiseResolver* resolver) const |
| 627 { |
| 628 // TODO(reillyg): Check endpoint availability once Blink is tracking which |
| 629 // alternate interfaces are selected. |
| 630 return ensureDeviceConfigured(resolver); |
| 631 } |
| 632 |
| 633 bool USBDevice::anyInterfaceChangeInProgress() const |
| 634 { |
| 635 for (size_t i = 0; i < m_interfaceStateChangeInProgress.size(); ++i) { |
| 636 if (m_interfaceStateChangeInProgress.quickGet(i)) |
| 637 return true; |
| 638 } |
| 639 return false; |
| 640 } |
| 641 |
| 508 } // namespace blink | 642 } // namespace blink |
| OLD | NEW |