Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

E1000

macrumors newbie
Original poster
Jul 14, 2011
3
0
Hi everyone,

I'm a bit desperate, as I can not seem to get this to work. I'm writing an application that communicates with an PIC 18F over USB. I've got the program running so far that I can send commands. Only receiving data isn't working. I've made an object, USBController, that takes care of all the USB stuff. Here is a part of it's code (full code included at bottom), I think something goes wrong here:

Code:
//
#include <CoreFoundation/CoreFoundation.h>
#include <Carbon/Carbon.h>

#import "USBController.h"

//The callback function
static void Handle_IOHIDDeviceIOHIDReportCallback(void *context, IOReturn result, void *sender,
								IOHIDReportType report_type, uint32_t report_id,
								uint8_t *report, CFIndex report_length)
{
	printf("hello");
}

@implementation USBController

- (void)ConnectToDevice{	

//...

        IOHIDDeviceScheduleWithRunLoop(tIOHIDDeviceRefs[0], CFRunLoopGetCurrent(), runloopmode);//kCFRunLoopDefaultMode);
		
	CFIndex reportSize = 128;    // note: this should be greater than or equal to the size of the report
	uint8_t report = malloc(reportSize);
	IOHIDDeviceRegisterInputReportCallback(tIOHIDDeviceRefs[0], report, reportSize, Handle_IOHIDDeviceIOHIDReportCallback, (void*)self);

//...

}
@end

I get an "exc_bad_access" error when I send the command 0x81 to the PIC, which on that command returns the status of its input ports. I wasn't able to find any objects with Zombies. This was my stack content:

Code:
#0	0x7fffffe007c5 in __memcpy
#1	0x102709d6e in IOHIDDeviceClass::_hidReportHandlerCallback
#2	0x7fff8839468e in __CFMachPortPerform
#3	0x7fff8836c6e1 in __CFRunLoopRun
#4	0x7fff8836adbf in CFRunLoopRunSpecific
#5	0x7fff8885193a in RunCurrentEventLoopInMode
#6	0x7fff8885173f in ReceiveNextEventCommon
#7	0x7fff888515f8 in BlockUntilNextEventMatchingListInMode
#8	0x7fff861bfe64 in _DPSNextEvent
#9	0x7fff861bf7a9 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]
#10	0x7fff8618548b in -[NSApplication run]
#11	0x7fff8617e1a8 in NSApplicationMain
#12	0x100000c55 in main at main.m:13

Does somebody know what's wrong? Is there some setting I have to set to enable Callbacks? I think I followed the HID guide pretty closely, and I have the setup working when I run it with hidapi...
Thanks in advance,
Emiel

This is the complete code:

Code:
//
//  USBController.m
//  usbtest
//
//  Created by Emiel van de Ven on 27-07-11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//
#include <CoreFoundation/CoreFoundation.h>
#include <Carbon/Carbon.h>

#import "USBController.h"

//The callback function
static void Handle_IOHIDDeviceIOHIDReportCallback(void *context, IOReturn result, void *sender,
								IOHIDReportType report_type, uint32_t report_id,
								uint8_t *report, CFIndex report_length)
{
	printf("hello");
}

@implementation USBController

- (CFMutableDictionaryRef)CreateMatchingDictionary:(UInt32)VID ProductionID:(UInt32)PID {
	
    CFMutableDictionaryRef matchingDictionary = NULL;
	
    // Set up a matching dictionary to search I/O Registry by class name for all HID class devices.
    matchingDictionary = IOServiceMatching (kIOHIDDeviceKey);
	
    if (matchingDictionary != NULL)
    {
		CFNumberRef cfValue;
		
		cfValue = CFNumberCreate( kCFAllocatorDefault, kCFNumberSInt32Type, &VID );
		CFDictionaryAddValue( matchingDictionary, CFSTR("VendorID"),
							 cfValue);
		
		cfValue = CFNumberCreate( kCFAllocatorDefault, kCFNumberSInt32Type, &PID );
		CFDictionaryAddValue( matchingDictionary, CFSTR("ProductID"),
							 cfValue);
        
    }
    else
        printf ("Failed to get HID CFMutableDictionaryRef via IOServiceMatching.");
		
		//printf ("Failed to get HID CFMutableDictionaryRef via IOServiceMatching.");
    return matchingDictionary;
	
}
- (void)ConnectToDevice{	
	
	tIOHIDManagerRef = IOHIDManagerCreate( kCFAllocatorDefault, kIOHIDOptionsTypeNone );
	
	// Create a device matching dictionary
	CFDictionaryRef matchingCFDictRef = [self CreateMatchingDictionary:0x04D8 ProductionID:0x0042];
	
	// set the HID device matching dictionary
	IOHIDManagerSetDeviceMatching( tIOHIDManagerRef, matchingCFDictRef );
	
	// Now open the IO HID Manager reference
	IOReturn tIOReturn = IOHIDManagerOpen( tIOHIDManagerRef, kIOHIDOptionsTypeNone );
	
	// and copy out its devices
	CFSetRef deviceCFSetRef = IOHIDManagerCopyDevices( tIOHIDManagerRef );

	// how many devices in the set?
	CFIndex deviceIndex, deviceCount = CFSetGetCount( deviceCFSetRef );
	deviceIndex = 0;

	// allocate a block of memory to extact the device ref's from the set into
	tIOHIDDeviceRefs = calloc(deviceCount, sizeof( IOHIDDeviceRef ) );

	// now extract the device ref's from the set
	CFSetGetValues( deviceCFSetRef, (const void **) tIOHIDDeviceRefs );
	
	// open the device
	IOReturn ret = IOHIDDeviceOpen(tIOHIDDeviceRefs[0], kIOHIDOptionsTypeNone);
	if (ret == kIOReturnSuccess) {
		//schedule with runloop
		IOHIDDeviceScheduleWithRunLoop(tIOHIDDeviceRefs[0], CFRunLoopGetCurrent(), runloopmode);//kCFRunLoopDefaultMode);
		
		CFIndex reportSize = 128;    // note: this should be greater than or equal to the size of the report
		uint8_t report = malloc(reportSize);
		IOHIDDeviceRegisterInputReportCallback(tIOHIDDeviceRefs[0], report, reportSize, Handle_IOHIDDeviceIOHIDReportCallback, (void*)self);

		char data[256];
		size_t length_to_send;
		
		data[0] = 0x81; //ask for data
		length_to_send = 1;
		
		//send to device
		IOHIDDeviceSetReport(tIOHIDDeviceRefs[0],
							 kIOHIDReportTypeOutput,
							 data[0], /* Report ID*/
							 (const unsigned char*)data, length_to_send);
     }
}
@end
 
You should check the validity of the values in tIOHIDDeviceRefs

after
Code:
CFSetGetValues( deviceCFSetRef, (const void **) tIOHIDDeviceRefs );

You also do not close the device via IOHIDDeviceClose, in your code. Why?
 
The tIOHIDDeviceRefs seems to be valid, I checked it with:

Code:
if (CFGetTypeID(tIOHIDDeviceRefs[0]) == IOHIDDeviceGetTypeID()) {
        printf("valid");
}

All the closing is done in an other method of USBController. I would first like to get the opening/sending/reading part to work before focussing on closing everything..
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.