15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file. 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "device/test/usb_test_gadget.h" 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <string> 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <vector> 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/command_line.h" 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/compiler_specific.h" 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/files/file.h" 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/files/file_path.h" 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/logging.h" 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/macros.h" 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/memory/ref_counted.h" 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/path_service.h" 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/process/process.h" 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/run_loop.h" 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/stringprintf.h" 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/utf_string_conversions.h" 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/threading/platform_thread.h" 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/time/time.h" 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "device/usb/usb_device.h" 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "device/usb/usb_device_handle.h" 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "device/usb/usb_service.h" 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/proxy/proxy_service.h" 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/url_request/url_fetcher.h" 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h" 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/url_request/url_request_context.h" 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/url_request/url_request_context_builder.h" 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "url/gurl.h" 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using ::base::PlatformThread; 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using ::base::TimeDelta; 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace device { 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace { 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const char kCommandLineSwitch[] = "enable-gadget-tests"; 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const int kClaimRetries = 100; // 5 seconds 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const int kDisconnectRetries = 100; // 5 seconds 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const int kRetryPeriod = 50; // 0.05 seconds 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const int kReconnectRetries = 100; // 5 seconds 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const int kUpdateRetries = 100; // 5 seconds 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)struct UsbTestGadgetConfiguration { 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) UsbTestGadget::Type type; 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char* http_resource; 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint16 product_id; 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const struct UsbTestGadgetConfiguration kConfigurations[] = { 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci {UsbTestGadget::DEFAULT, "/unconfigure", 0x58F0}, 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci {UsbTestGadget::KEYBOARD, "/keyboard/configure", 0x58F1}, 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci {UsbTestGadget::MOUSE, "/mouse/configure", 0x58F2}, 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci {UsbTestGadget::HID_ECHO, "/hid_echo/configure", 0x58F3}, 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci {UsbTestGadget::ECHO, "/echo/configure", 0x58F4}, 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class UsbTestGadgetImpl : public UsbTestGadget { 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual ~UsbTestGadgetImpl(); 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual bool Unclaim() OVERRIDE; 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual bool Disconnect() OVERRIDE; 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual bool Reconnect() OVERRIDE; 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual bool SetType(Type type) OVERRIDE; 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual UsbDevice* GetDevice() const OVERRIDE; 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual std::string GetSerialNumber() const OVERRIDE; 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) protected: 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) UsbTestGadgetImpl(); 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private: 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<net::URLFetcher> CreateURLFetcher( 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const GURL& url, 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::URLFetcher::RequestType request_type, 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::URLFetcherDelegate* delegate); 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int SimplePOSTRequest(const GURL& url, const std::string& form_data); 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool FindUnclaimed(); 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool GetVersion(std::string* version); 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool Update(); 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool FindClaimed(); 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool ReadLocalVersion(std::string* version); 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool ReadLocalPackage(std::string* package); 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool ReadFile(const base::FilePath& file_path, std::string* content); 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) class Delegate : public net::URLFetcherDelegate { 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Delegate() {} 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual ~Delegate() {} 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void WaitForCompletion() { 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) run_loop_.Run(); 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE { 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) run_loop_.Quit(); 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private: 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::RunLoop run_loop_; 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Delegate); 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }; 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<UsbDevice> device_; 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string device_address_; 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<net::URLRequestContext> request_context_; 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string session_id_; 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) UsbService* usb_service_; 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) friend class UsbTestGadget; 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(UsbTestGadgetImpl); 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool UsbTestGadget::IsTestEnabled() { 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::CommandLine* command_line = CommandLine::ForCurrentProcess(); 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return command_line->HasSwitch(kCommandLineSwitch); 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)scoped_ptr<UsbTestGadget> UsbTestGadget::Claim() { 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<UsbTestGadgetImpl> gadget(new UsbTestGadgetImpl); 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int retries = kClaimRetries; 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while (!gadget->FindUnclaimed()) { 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (--retries == 0) { 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(ERROR) << "Failed to find an unclaimed device."; 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return scoped_ptr<UsbTestGadget>(); 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PlatformThread::Sleep(TimeDelta::FromMilliseconds(kRetryPeriod)); 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(1) << "It took " << (kClaimRetries - retries) 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << " retries to find an unclaimed device."; 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return gadget.PassAs<UsbTestGadget>(); 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)UsbTestGadgetImpl::UsbTestGadgetImpl() { 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::URLRequestContextBuilder context_builder; 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) context_builder.set_proxy_service(net::ProxyService::CreateDirect()); 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) request_context_.reset(context_builder.Build()); 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::ProcessId process_id = base::Process::Current().pid(); 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) session_id_ = base::StringPrintf( 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "%s:%p", base::HexEncode(&process_id, sizeof(process_id)).c_str(), this); 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci usb_service_ = UsbService::GetInstance(NULL); 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)UsbTestGadgetImpl::~UsbTestGadgetImpl() { 1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!device_address_.empty()) { 1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Unclaim(); 1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)UsbDevice* UsbTestGadgetImpl::GetDevice() const { 1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return device_.get(); 1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::string UsbTestGadgetImpl::GetSerialNumber() const { 1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return device_address_; 1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)scoped_ptr<net::URLFetcher> UsbTestGadgetImpl::CreateURLFetcher( 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const GURL& url, net::URLFetcher::RequestType request_type, 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::URLFetcherDelegate* delegate) { 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<net::URLFetcher> url_fetcher( 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::URLFetcher::Create(url, request_type, delegate)); 1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) url_fetcher->SetRequestContext( 1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new net::TrivialURLRequestContextGetter( 1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) request_context_.get(), 1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::MessageLoop::current()->message_loop_proxy())); 1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return url_fetcher.PassAs<net::URLFetcher>(); 1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int UsbTestGadgetImpl::SimplePOSTRequest(const GURL& url, 1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& form_data) { 1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Delegate delegate; 1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<net::URLFetcher> url_fetcher = 1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CreateURLFetcher(url, net::URLFetcher::POST, &delegate); 1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) url_fetcher->SetUploadData("application/x-www-form-urlencoded", form_data); 1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) url_fetcher->Start(); 1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delegate.WaitForCompletion(); 1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return url_fetcher->GetResponseCode(); 1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool UsbTestGadgetImpl::FindUnclaimed() { 2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::vector<scoped_refptr<UsbDevice> > devices; 2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) usb_service_->GetDevices(&devices); 2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (std::vector<scoped_refptr<UsbDevice> >::const_iterator iter = 2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) devices.begin(); iter != devices.end(); ++iter) { 2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const scoped_refptr<UsbDevice> &device = *iter; 2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (device->vendor_id() == 0x18D1 && device->product_id() == 0x58F0) { 2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::string16 serial_utf16; 2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!device->GetSerialNumber(&serial_utf16)) { 2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue; 2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string serial = base::UTF16ToUTF8(serial_utf16); 2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const GURL url("http://" + serial + "/claim"); 2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string form_data = base::StringPrintf( 2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "session_id=%s", 2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::EscapeUrlEncodedData(session_id_, true).c_str()); 2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int response_code = SimplePOSTRequest(url, form_data); 2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (response_code == 200) { 2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_address_ = serial; 2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_ = device; 2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The device is probably claimed by another process. 2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (response_code != 403) { 2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(WARNING) << "Unexpected HTTP " << response_code << " from /claim."; 2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string local_version; 2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string version; 2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!ReadLocalVersion(&local_version) || 2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) !GetVersion(&version)) { 2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (version == local_version) { 2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return Update(); 2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool UsbTestGadgetImpl::GetVersion(std::string* version) { 2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Delegate delegate; 2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const GURL url("http://" + device_address_ + "/version"); 2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<net::URLFetcher> url_fetcher = 2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CreateURLFetcher(url, net::URLFetcher::GET, &delegate); 2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) url_fetcher->Start(); 2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delegate.WaitForCompletion(); 2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int response_code = url_fetcher->GetResponseCode(); 2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (response_code != 200) { 2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(2) << "Unexpected HTTP " << response_code << " from /version."; 2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) STLClearObject(version); 2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!url_fetcher->GetResponseAsString(version)) { 2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(2) << "Failed to read body from /version."; 2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool UsbTestGadgetImpl::Update() { 2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string version; 2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!ReadLocalVersion(&version)) { 2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(INFO) << "Updating " << device_address_ << " to " << version << "..."; 2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Delegate delegate; 2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const GURL url("http://" + device_address_ + "/update"); 2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<net::URLFetcher> url_fetcher = 2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CreateURLFetcher(url, net::URLFetcher::POST, &delegate); 2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string mime_header = 2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::StringPrintf( 2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "--foo\r\n" 2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Content-Disposition: form-data; name=\"file\"; " 2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "filename=\"usb_gadget-%s.zip\"\r\n" 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Content-Type: application/octet-stream\r\n" 2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "\r\n", version.c_str()); 2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string mime_footer("\r\n--foo--\r\n"); 2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string package; 2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!ReadLocalPackage(&package)) { 2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) url_fetcher->SetUploadData("multipart/form-data; boundary=foo", 2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mime_header + package + mime_footer); 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) url_fetcher->Start(); 2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delegate.WaitForCompletion(); 3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int response_code = url_fetcher->GetResponseCode(); 3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (response_code != 200) { 3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(ERROR) << "Unexpected HTTP " << response_code << " from /update."; 3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int retries = kUpdateRetries; 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string new_version; 3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while (!GetVersion(&new_version) || new_version != version) { 3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (--retries == 0) { 3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(ERROR) << "Device not responding with new version."; 3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PlatformThread::Sleep(TimeDelta::FromMilliseconds(kRetryPeriod)); 3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(1) << "It took " << (kUpdateRetries - retries) 3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << " retries to see the new version."; 3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Release the old reference to the device and try to open a new one. 3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_ = NULL; 3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) retries = kReconnectRetries; 3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while (!FindClaimed()) { 3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (--retries == 0) { 3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(ERROR) << "Failed to find updated device."; 3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PlatformThread::Sleep(TimeDelta::FromMilliseconds(kRetryPeriod)); 3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(1) << "It took " << (kReconnectRetries - retries) 3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << " retries to find the updated device."; 3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool UsbTestGadgetImpl::FindClaimed() { 3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CHECK(!device_.get()); 3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string expected_serial = GetSerialNumber(); 3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::vector<scoped_refptr<UsbDevice> > devices; 3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) usb_service_->GetDevices(&devices); 3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (std::vector<scoped_refptr<UsbDevice> >::iterator iter = 3445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) devices.begin(); iter != devices.end(); ++iter) { 3455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<UsbDevice> &device = *iter; 3465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (device->vendor_id() == 0x18D1) { 3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const uint16 product_id = device->product_id(); 3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool found = false; 3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (size_t i = 0; i < arraysize(kConfigurations); ++i) { 3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (product_id == kConfigurations[i].product_id) { 3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) found = true; 3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!found) { 3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue; 3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::string16 serial_utf16; 3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!device->GetSerialNumber(&serial_utf16)) { 3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue; 3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string serial = base::UTF16ToUTF8(serial_utf16); 3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (serial != expected_serial) { 3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue; 3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_ = device; 3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool UsbTestGadgetImpl::ReadLocalVersion(std::string* version) { 3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::FilePath file_path; 3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CHECK(PathService::Get(base::DIR_EXE, &file_path)); 3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) file_path = file_path.AppendASCII("usb_gadget.zip.md5"); 3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ReadFile(file_path, version); 3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool UsbTestGadgetImpl::ReadLocalPackage(std::string* package) { 3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::FilePath file_path; 3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CHECK(PathService::Get(base::DIR_EXE, &file_path)); 3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) file_path = file_path.AppendASCII("usb_gadget.zip"); 3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ReadFile(file_path, package); 3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool UsbTestGadgetImpl::ReadFile(const base::FilePath& file_path, 3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string* content) { 3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ); 3975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!file.IsValid()) { 3985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(ERROR) << "Cannot open " << file_path.MaybeAsASCII() << ": " 3995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << base::File::ErrorToString(file.error_details()); 4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 4015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) STLClearObject(content); 4045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int rv; 4055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) do { 4065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) char buf[4096]; 4075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rv = file.ReadAtCurrentPos(buf, sizeof buf); 4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (rv == -1) { 4095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(ERROR) << "Cannot read " << file_path.MaybeAsASCII() << ": " 4105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << base::File::ErrorToString(file.error_details()); 4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 4125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) content->append(buf, rv); 4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } while (rv > 0); 4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 4175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool UsbTestGadgetImpl::Unclaim() { 4205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(1) << "Releasing the device at " << device_address_ << "."; 4215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const GURL url("http://" + device_address_ + "/unclaim"); 4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int response_code = SimplePOSTRequest(url, ""); 4245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (response_code != 200) { 4265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(ERROR) << "Unexpected HTTP " << response_code << " from /unclaim."; 4275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 4285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 4305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 4315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool UsbTestGadgetImpl::SetType(Type type) { 4335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const struct UsbTestGadgetConfiguration* config = NULL; 4345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (size_t i = 0; i < arraysize(kConfigurations); ++i) { 4355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (kConfigurations[i].type == type) { 4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) config = &kConfigurations[i]; 4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CHECK(config); 4405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const GURL url("http://" + device_address_ + config->http_resource); 4425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int response_code = SimplePOSTRequest(url, ""); 4435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (response_code != 200) { 4455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(ERROR) << "Unexpected HTTP " << response_code 4465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << " from " << config->http_resource << "."; 4475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 4485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Release the old reference to the device and try to open a new one. 4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int retries = kReconnectRetries; 4525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while (true) { 4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_ = NULL; 4545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (FindClaimed() && device_->product_id() == config->product_id) { 4555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 4565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (--retries == 0) { 4585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(ERROR) << "Failed to find updated device."; 4595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 4605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PlatformThread::Sleep(TimeDelta::FromMilliseconds(kRetryPeriod)); 4625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(1) << "It took " << (kReconnectRetries - retries) 4645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << " retries to find the updated device."; 4655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 4675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 4685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool UsbTestGadgetImpl::Disconnect() { 4705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const GURL url("http://" + device_address_ + "/disconnect"); 4715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int response_code = SimplePOSTRequest(url, ""); 4725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (response_code != 200) { 4745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(ERROR) << "Unexpected HTTP " << response_code << " from /disconnect."; 4755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 4765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Release the old reference to the device and wait until it can't be found. 4795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int retries = kDisconnectRetries; 4805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while (true) { 4815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_ = NULL; 4825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!FindClaimed()) { 4835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 4845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (--retries == 0) { 4865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(ERROR) << "Device did not disconnect."; 4875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 4885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PlatformThread::Sleep(TimeDelta::FromMilliseconds(kRetryPeriod)); 4905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(1) << "It took " << (kDisconnectRetries - retries) 4925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << " retries for the device to disconnect."; 4935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 4955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 4965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool UsbTestGadgetImpl::Reconnect() { 4985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const GURL url("http://" + device_address_ + "/reconnect"); 4995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int response_code = SimplePOSTRequest(url, ""); 5005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (response_code != 200) { 5025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(ERROR) << "Unexpected HTTP " << response_code << " from /reconnect."; 5035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 5045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 5055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int retries = kDisconnectRetries; 5075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while (true) { 5085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (FindClaimed()) { 5095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 5105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 5115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (--retries == 0) { 5125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(ERROR) << "Device did not reconnect."; 5135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 5145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 5155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PlatformThread::Sleep(TimeDelta::FromMilliseconds(kRetryPeriod)); 5165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 5175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(1) << "It took " << (kDisconnectRetries - retries) 5185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << " retries for the device to reconnect."; 5195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 5215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 5225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace device 524