Skip to content

Commit

Permalink
Support composite devices more directly. (Closes #2.)
Browse files Browse the repository at this point in the history
  • Loading branch information
jwise committed Nov 16, 2012
1 parent 6341957 commit 4f85661
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 85 deletions.
19 changes: 17 additions & 2 deletions HoRNDIS-Info.plist
Expand Up @@ -26,12 +26,12 @@
<string>1.0.0d1</string>
<key>IOKitPersonalities</key>
<dict>
<key>HoRNDIS</key>
<key>HoRNDISDevice</key>
<dict>
<key>CFBundleIdentifier</key>
<string>com.joshuawise.kexts.HoRNDIS</string>
<key>IOClass</key>
<string>HoRNDIS</string>
<string>AppleUSBComposite</string>
<key>IOProviderClass</key>
<string>IOUSBDevice</string>
<key>bDeviceClass</key>
Expand All @@ -41,6 +41,21 @@
<key>bDeviceProtocol</key>
<integer>0</integer>
</dict>
<key>HoRNDISComposite</key>
<dict>
<key>CFBundleIdentifier</key>
<string>com.joshuawise.kexts.HoRNDIS</string>
<key>IOClass</key>
<string>HoRNDISUSBInterface</string>
<key>IOProviderClass</key>
<string>IOUSBInterface</string>
<key>bInterfaceClass</key>
<integer>224</integer>
<key>bInterfaceProtocol</key>
<integer>3</integer>
<key>bInterfaceSubClass</key>
<integer>1</integer>
</dict>
</dict>
<key>OSBundleLibraries</key>
<dict>
Expand Down
99 changes: 17 additions & 82 deletions HoRNDIS.cpp
Expand Up @@ -39,6 +39,7 @@
#define super IOEthernetController

OSDefineMetaClassAndStructors(HoRNDIS, IOEthernetController);
OSDefineMetaClassAndStructors(HoRNDISUSBInterface, HoRNDIS);
OSDefineMetaClassAndStructors(HoRNDISInterface, IOEthernetInterface);

bool HoRNDIS::init(OSDictionary *properties) {
Expand Down Expand Up @@ -70,38 +71,30 @@ bool HoRNDIS::init(OSDictionary *properties) {

/***** Driver setup and teardown language *****/

bool HoRNDIS::start(IOService *provider) {
int cfg;
int rc;

LOG(V_DEBUG, "starting up");
if(!super::start(provider))
return false;
bool HoRNDISUSBInterface::start(IOService *provider) {
IOUSBInterface *intf;

fpDevice = OSDynamicCast(IOUSBDevice, provider);
if(!fpDevice) {
stop(provider);
intf = OSDynamicCast(IOUSBInterface, provider);
if (!intf) {
LOG(V_ERROR, "cast to IOUSBInterface failed?");
return false;
}

fpDevice = intf->GetDevice();

return HoRNDIS::start(provider);
}

bool HoRNDIS::start(IOService *provider) {
LOG(V_DEBUG, "starting up");
if(!super::start(provider))
return false;

/* Take control of the device before configuring. */
if (!fpDevice->open(this)) {
if (!fpDevice) {
stop(provider);
return false;
}

/* Initialize and set the appropriate device configuration. */
cfg = probeConfigurations();
if (cfg < 0)
goto bailout;

rc = fpDevice->SetConfiguration(this, cfg);
if (rc != kIOReturnSuccess) {
LOG(V_ERROR, "SetConfiguration on RNDIS config failed?");
return false;;
}

/* Now do the rest of the work to actually bring it up... */
if (!openInterfaces())
goto bailout;
if (!rndisInit())
Expand Down Expand Up @@ -142,11 +135,6 @@ void HoRNDIS::stop(IOService *provider) {
fDataInterface = NULL;
}

if (fpDevice) {
fpDevice->close(this);
fpDevice = NULL;
}

if (fMediumDict) {
fMediumDict->release();
fMediumDict = NULL;
Expand All @@ -155,59 +143,6 @@ void HoRNDIS::stop(IOService *provider) {
super::stop(provider);
}

/* Find and activate an RNDIS-looking interface. XXX: wish I could include that in configureDevice, below... */
int HoRNDIS::probeConfigurations() {
int i;
int ncfgs = fpDevice->GetNumConfigurations();

/* XXX: Should probe the string descriptors to make sure that they match with Linux's RNDIS gadget strings; binding to arbitrary RNDIS devices probably won't work. */

LOG(V_DEBUG, "%d possible configs", ncfgs);

for (i = 0; i < ncfgs; i++) {
IOUSBFindInterfaceRequest req;
const IOUSBConfigurationDescriptor *cd;
IOUSBInterfaceDescriptor *intf;
IOReturn ior;

LOG(V_DEBUG, "checking configuration %d", i);

cd = fpDevice->GetFullConfigurationDescriptor(i);
if (!cd) {
LOG(V_ERROR, "error retrieving configuration descriptor");
continue;
}

req.bInterfaceClass = 0xE0;
req.bInterfaceSubClass = 0x01;
req.bInterfaceProtocol = 0x03;
req.bAlternateSetting = kIOUSBFindInterfaceDontCare;
ior = fpDevice->FindNextInterfaceDescriptor(cd, NULL, &req, &intf);
if (ior != kIOReturnSuccess) {
LOG(V_DEBUG, "no control interface for configuration");
continue;
}

req.bInterfaceClass = 0x0A;
req.bInterfaceSubClass = 0x00;
req.bInterfaceProtocol = 0x00;
req.bAlternateSetting = kIOUSBFindInterfaceDontCare;
ior = fpDevice->FindNextInterfaceDescriptor(cd, intf, &req, &intf);
if (ior != kIOReturnSuccess) {
LOG(V_DEBUG, "no data interface for configuration");
continue;
}

LOG(V_DEBUG, "interface descriptor found");

/* Okay, we found it -- all set! */
return cd->bConfigurationValue;
}

LOG(V_ERROR, "no RNDIS configuration that I can drive");
return -1;
}

bool HoRNDIS::openInterfaces() {
IOUSBFindInterfaceRequest req;
IOUSBFindEndpointRequest epReq;
Expand Down
8 changes: 7 additions & 1 deletion HoRNDIS.h
Expand Up @@ -271,7 +271,6 @@ class HoRNDIS : public IOEthernetController {
bool allocateResources(void);
void releaseResources(void);
bool openInterfaces();
int probeConfigurations();
bool createNetworkInterface(void);
UInt32 outputPacket(mbuf_t pkt, void *param);
IOReturn clearPipeStall(IOUSBPipe *thePipe);
Expand All @@ -298,6 +297,13 @@ class HoRNDIS : public IOEthernetController {
virtual IONetworkInterface *createInterface();
};

/* If there are other ways to get access to a device, we probably want them here. */
class HoRNDISUSBInterface : public HoRNDIS {
OSDeclareDefaultStructors(HoRNDISUSBInterface);
public:
virtual bool start(IOService *provider);
};

class HoRNDISInterface : public IOEthernetInterface {
OSDeclareDefaultStructors(HoRNDISInterface);
public:
Expand Down

0 comments on commit 4f85661

Please sign in to comment.