From f1b14bcdbdd8eddea17092b35642134adb69eae8 Mon Sep 17 00:00:00 2001 From: Nicolas VIVIEN Date: Sun, 5 Feb 2012 19:00:29 +0100 Subject: [PATCH] tools: add playbook driver switch --- debian/barry-util.install | 1 + src/probe.cc | 110 +++++++++++++++++++++++++++++++++++++++++++ src/probe.h | 22 ++++++++- tools/Makefile.am | 6 ++- tools/bplaybook.cc | 117 ++++++++++++++++++++++++++++++++++++++++++++++ udev/10-playbook.rules | 9 ++++ 6 files changed, 263 insertions(+), 2 deletions(-) create mode 100644 tools/bplaybook.cc create mode 100644 udev/10-playbook.rules diff --git a/debian/barry-util.install b/debian/barry-util.install index 202e8784..b05720eb 100644 --- a/debian/barry-util.install +++ b/debian/barry-util.install @@ -15,6 +15,7 @@ debian/tmp/usr/bin/upldif debian/tmp/usr/sbin/breset debian/tmp/usr/sbin/bcharge debian/tmp/usr/sbin/pppob +debian/tmp/usr/sbin/bplaybook debian/tmp/usr/share/man/man1/bcharge.1 debian/tmp/usr/share/man/man1/bidentify.1 debian/tmp/usr/share/man/man1/brecsum.1 diff --git a/src/probe.cc b/src/probe.cc index 9b3eda89..d4df4c41 100644 --- a/src/probe.cc +++ b/src/probe.cc @@ -19,6 +19,7 @@ root directory of this project for more details. */ +#include #include "common.h" #include "probe.h" #include "usbwrap.h" @@ -183,6 +184,7 @@ void Probe::ProbeMatching(int vendor, int product, Usb::DeviceID devid; Match match(m_devices, vendor, product, busname, devname); + while( match.next_device(devid) ) try { ProbeDevice(devid); } @@ -252,6 +254,7 @@ void Probe::ProbeDevice(Usb::DeviceID& devid) ProbeResult result; result.m_dev = devid; + result.m_class = BLACKBERRY_DB_CLASS; result.m_interface = InterfaceNumber; result.m_altsetting = InterfaceAltSetting; result.m_zeroSocketSequence = 0; @@ -536,6 +539,113 @@ int Probe::Find(const Results &results, Barry::Pin pin) return -1; } +ProbePlayBook::ProbePlayBook(const char *busname, const char *devname, + const Usb::EndpointPair *epp) + : m_fail_count(0) + , m_epp_override(epp) +{ + if( m_epp_override ) { + m_epp = *epp; + } + + // let the programmer pass in "" as well as 0 + if( busname && !strlen(busname) ) + busname = 0; + if( devname && !strlen(devname) ) + devname = 0; + + // Search for standard product ID first + ProbeMatching(VENDOR_RIM, PRODUCT_RIM_PLAYBOOK_STORAGE, busname, devname); +} + +void ProbePlayBook::ProbeDevice(Usb::DeviceID& devid) +{ + // skip if we can't properly discover device config + DeviceDescriptor desc(devid); + ConfigDescriptor* config = desc[BLACKBERRY_CONFIGURATION]; + + // search for interface class + ConfigDescriptor::base_type::iterator idi = config->begin(); + for( ; idi != config->end(); idi++ ) { + if( idi->second->GetClass() == BLACKBERRY_MASS_STORAGE_CLASS ) + break; + } + if( idi == config->end() ) { + dout("Probe: Interface with BLACKBERRY_MASS_STORAGE_CLASS (" + << BLACKBERRY_MASS_STORAGE_CLASS << ") not found."); + return; // not found + } + + unsigned char InterfaceNumber = idi->second->GetNumber(); + unsigned char InterfaceAltSetting = idi->second->GetAltSetting(); + dout("Probe: using InterfaceNumber: " << (unsigned int) InterfaceNumber << + " AltSetting: " << (unsigned int) InterfaceAltSetting); + + // check endpoint validity + EndpointPairings ep(*(*config)[InterfaceNumber]); + if( !ep.IsValid() || ep.size() == 0 ) { + dout("Probe: endpoint invalid. ep.IsValid() == " + << (ep.IsValid() ? "true" : "false") + << ", ep.size() == " + << ep.size()); + return; + } + + ProbeResult result; + result.m_dev = devid; + result.m_class = BLACKBERRY_MASS_STORAGE_CLASS; + result.m_interface = InterfaceNumber; + result.m_altsetting = InterfaceAltSetting; + result.m_zeroSocketSequence = 0; +// result.m_ep = ep; +// result.m_pin = pin; +// result.m_description = desc; +// result.m_zeroSocketSequence = zeroSocketSequence; + result.m_needClearHalt = false, + result.m_needSetAltInterface = true; + + // open device + Device dev(devid); +// dev.Reset(); +// sleep(5); + + // make sure device is available + std::string DriverName; + if (dev.IsAttachKernelDriver(InterfaceNumber)) + dev.DetachKernelDriver(InterfaceNumber); + + // make sure we're talking to the right config + unsigned char cfg; + if( !dev.GetConfiguration(cfg) ) + throw Usb::Error(dev.GetLastError(), + "Probe: GetConfiguration failed"); + if( cfg != BLACKBERRY_CONFIGURATION || MUST_SET_CONFIGURATION ) { + if( !dev.SetConfiguration(BLACKBERRY_CONFIGURATION) ) + throw Usb::Error(dev.GetLastError(), + "Probe: SetConfiguration failed"); + } + + // SCSI Mass Storage isn't interessant for a Linux users + // switch the device to network interface to be useable + char buf[2]; + dev.ControlMsg(USB_TYPE_VENDOR + USB_RECIP_DEVICE + USB_ENDPOINT_IN, + 0x00000a9, 0x000000c, 0x0000000, buf, sizeof(buf), 1000); + dev.ControlMsg(USB_TYPE_VENDOR + USB_RECIP_DEVICE + USB_ENDPOINT_IN, + 0x00000a5, 0x0000000, 0x0000001, buf, sizeof(buf), 1000); + + // open interface + Interface iface(dev, InterfaceNumber); + + iface.SetAltInterface(InterfaceAltSetting); + + ddout("Using ReadEndpoint: " << (unsigned int)result.m_ep.read); + ddout(" WriteEndpoint: " << (unsigned int)result.m_ep.write); + + // We don't add the device, since the device doesn't exist now ! + // The storage device becomes a network device :) +} + + void ProbeResult::DumpAll(std::ostream &os) const { ios_format_state state(os); diff --git a/src/probe.h b/src/probe.h index 698c4c49..cf8ed1ab 100644 --- a/src/probe.h +++ b/src/probe.h @@ -36,8 +36,10 @@ class Probe; struct BXEXPORT ProbeResult { friend class Probe; + friend class ProbePlayBook; Usb::DeviceID m_dev; + unsigned char m_class; unsigned char m_interface; unsigned char m_altsetting; Barry::Pin m_pin; @@ -91,6 +93,8 @@ BXEXPORT std::ostream& operator<< (std::ostream &os, const ProbeResult &pr); class BXEXPORT Probe { + friend class ProbePlayBook; + public: typedef std::vector Results; @@ -118,7 +122,7 @@ private: protected: void ProbeMatching(int vendor, int product, const char *busname, const char *devname); - void ProbeDevice(Usb::DeviceID& devid); + virtual void ProbeDevice(Usb::DeviceID& devid); void ProbeDeviceEndpoints(Usb::Device &dev, Usb::EndpointPairings &ed, ProbeResult &result); bool ProbePair(Usb::Device &dev, const Usb::EndpointPair &ep, uint32_t &pin, std::string &desc, uint8_t &zeroSocketSequence, @@ -155,6 +159,22 @@ public: }; +class BXEXPORT ProbePlayBook : Probe +{ +private: + int m_fail_count; + + bool m_epp_override; + +protected: + void ProbeDevice(Usb::DeviceID& devid); + +public: + ProbePlayBook(const char *busname = 0, const char *devname = 0, + const Usb::EndpointPair *epp = 0); +}; + + } // namespace Barry #endif diff --git a/tools/Makefile.am b/tools/Makefile.am index 05ad5f29..cb40ad84 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -62,7 +62,8 @@ endif sbin_PROGRAMS = \ bcharge \ breset \ - pppob + pppob \ + bplaybook libutil_a_SOURCES = util.cc libutil_a_CXXFLAGS = $(AM_CXXFLAGS) @@ -118,6 +119,9 @@ bjvmdebug_LDADD = ../src/libbarry.la $(USB_LIBRARY_LIBS) $(LTLIBINTL) bdptest_SOURCES = bdptest.cc bdptest_LDADD = ../src/libbarry.la ../src/libbarrydp.la $(LTLIBINTL) +bplaybook_SOURCES = bplaybook.cc +bplaybook_LDADD = ../src/libbarry.la $(USB_LIBRARY_LIBS) $(LTLIBINTL) + bjdwp_SOURCES = bjdwp.cc bjdwp_LDADD = ../src/libbarry.la \ ../src/libbarrydp.la \ diff --git a/tools/bplaybook.cc b/tools/bplaybook.cc new file mode 100644 index 00000000..fdcb93c1 --- /dev/null +++ b/tools/bplaybook.cc @@ -0,0 +1,117 @@ +/// +/// \file bplaybook.cc +/// bplaybook command line tool +/// + +/* + Copyright (C) 2011, Nicolas VIVIEN + Copyright (C) 2005-2011, Net Direct Inc. (http://www.netdirect.ca/) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License in the COPYING file at the + root directory of this project for more details. +*/ + + +#include +#include +#include +#include +#include "i18n.h" + +#include "barrygetopt.h" + +using namespace std; +using namespace Barry; + + +void Usage() +{ + int logical, major, minor; + const char *Version = Barry::Version(logical, major, minor); + + cerr + << "bplaybook - Command line USB Blackberry PlayBook\n" + << " Copyright 2011, Nicolas VIVIEN.\n" + << " Using: " << Version << "\n" + << "\n" + << " -h This help\n" + << " -v Dump protocol data during operation\n" + << "\n" + << endl; +} + + +int main(int argc, char *argv[], char *envp[]) +{ + INIT_I18N(PACKAGE); + + try { + bool data_dump = false; + vector params; + string iconvCharset; + + // process command line options + for(;;) { + int cmd = getopt(argc, argv, "hv"); + if( cmd == -1 ) + break; + + switch( cmd ) + { + case 'v': // data dump on + data_dump = true; + break; + + case 'h': // help + default: + Usage(); + return 0; + } + } + + argc -= optind; + argv += optind; + + if( argc != 0 ) { + cerr << "unknown arguments" << endl; + Usage(); + return 1; + } + + // Initialize the barry library. Must be called before + // anything else. + Barry::Init(data_dump); + + // Probe the USB bus for Blackberry devices and display. + // If user has specified a PIN, search for it in the + // available device list here as well + Barry::ProbePlayBook probe; + } + catch( Usb::Error &ue) { + std::cout << endl; // flush any normal output first + std::cerr << "Usb::Error caught: " << ue.what() << endl; + return 1; + } + catch( Barry::Error &se ) { + std::cout << endl; + std::cerr << "Barry::Error caught: " << se.what() << endl; + return 1; + } + catch( std::exception &e ) { + std::cout << endl; + std::cerr << "std::exception caught: " << e.what() << endl; + return 1; + } + + return 0; +} + diff --git a/udev/10-playbook.rules b/udev/10-playbook.rules new file mode 100644 index 00000000..8ab79128 --- /dev/null +++ b/udev/10-playbook.rules @@ -0,0 +1,9 @@ +# +# Blackberry PlayBook device +# + +# PlayBook device +SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ACTION=="add", \ + ATTR{idVendor}=="0fca", ATTR{idProduct}=="8020", \ + RUN="/usr/sbin/bplaybook" + -- 2.11.4.GIT