diff options
author | Hans-Christoph Steiner <eighthave@users.sourceforge.net> | 2008-03-10 21:50:43 +0000 |
---|---|---|
committer | IOhannes m zmölnig <zmoelnig@iem.at> | 2015-10-14 15:08:25 +0200 |
commit | da3f6b1d47080e0162944834d18017c9a691c0b1 (patch) | |
tree | 7a694aa59e70926112eca729716fbcaa655b6508 /wiiremote/wiiremote.c | |
parent | 71d377c64cf05eb5726e4ec803dc8288bf4c8357 (diff) |
moved wiiremote to aka.wiiremote to reflect the name of the Max/MSP object.
This is a direct port, so it makes sense to have the same name.
svn path=/trunk/externals/io/; revision=9551
Diffstat (limited to 'wiiremote/wiiremote.c')
-rw-r--r-- | wiiremote/wiiremote.c | 1087 |
1 files changed, 0 insertions, 1087 deletions
diff --git a/wiiremote/wiiremote.c b/wiiremote/wiiremote.c deleted file mode 100644 index 481085e..0000000 --- a/wiiremote/wiiremote.c +++ /dev/null @@ -1,1087 +0,0 @@ -// wiiremote.c -// Copyright by Masayuki Akamatsu -// Based on "DarwiinRemote" by Hiroaki Kimura - -#include "wiiremote.h" -#include <unistd.h> - -// this type is used a lot (data array): -typedef unsigned char darr[]; - -#define kTrial 10 -#define kWait 10000 -// the unit of kWait is microseconds, thus 10000 means 10ms - -#define kWiiIRPixelsWidth 1024.0 -#define kWiiIRPixelsHeight 768.0 - - -Boolean requestUpdates(WiiRemoteRef wiiremote); -void myEventListener(IOBluetoothL2CAPChannelRef channel, void *refCon, IOBluetoothL2CAPChannelEvent *event); - - -//-------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------- - -void wiiremote_init(WiiRemoteRef wiiremote) -{ - wiiremote->inquiry = nil; - wiiremote->device = nil; - wiiremote->ichan = nil; - wiiremote->cchan = nil; - - wiiremote->address = nil; - - wiiremote->accX = 0x10; - wiiremote->accY = 0x10; - wiiremote->accZ = 0x10; - wiiremote->buttonData = 0; - - wiiremote->lowZ = 0; - wiiremote->lowX = 0; - wiiremote->leftPoint = -1; - wiiremote->tracking = false; - - wiiremote->batteryLevel = 0; - - wiiremote->readingRegister = false; - wiiremote->isMotionSensorEnabled = false; - wiiremote->isVibrationEnabled = false; - wiiremote->isIRSensorEnabled = false; - wiiremote->wiiIRMode = kWiiIRModeExtended; - wiiremote->isExpansionPortEnabled = false; - wiiremote->isExpansionPortAttached = false; - wiiremote->expType = WiiExpNotAttached; - - wiiremote->isLED1Illuminated = false; - wiiremote->isLED2Illuminated = false; - wiiremote->isLED3Illuminated = false; - wiiremote->isLED4Illuminated = false; - - wiiremote->nAccX = 0x10; - wiiremote->nAccY = 0x10; - wiiremote->nAccZ = 0x10; - wiiremote->nButtonData = 0; - - wiiremote->nLowZ = 0; - wiiremote->nLowX = 0; - -} - -//-------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------- - -Boolean openCChan(WiiRemoteRef wiiremote) -{ - short i; - IOReturn ret; - - // open L2CAPChannel : BluetoothL2CAPPSM = 17 - for (i=0; i<kTrial; i++) - { - ret = IOBluetoothDeviceOpenL2CAPChannelSync(wiiremote->device, &(wiiremote->cchan), 17, myEventListener, (void *)wiiremote); - if ( ret == kIOReturnSuccess) - break; - usleep(kWait); // wait 10ms - } - if (i==kTrial) - { - wiiremote->cchan = nil; - IOBluetoothDeviceCloseConnection(wiiremote->device); - return false; - } - IOBluetoothObjectRetain(wiiremote->cchan); - - return (ret==kIOReturnSuccess); -} - -Boolean openIChan(WiiRemoteRef wiiremote) -{ - short i; - IOReturn ret; - - // open L2CAPChannel : BluetoothL2CAPPSM = 19 - for (i=0; i<kTrial; i++) - { - ret = IOBluetoothDeviceOpenL2CAPChannelSync(wiiremote->device, &(wiiremote->ichan), 19, myEventListener, (void *)wiiremote); - if ( ret == kIOReturnSuccess) - break; - usleep(kWait); // wait 10ms - } - if (i==kTrial) - { - wiiremote->ichan = nil; - IOBluetoothL2CAPChannelCloseChannel(wiiremote->cchan); - IOBluetoothObjectRelease(wiiremote->cchan); - IOBluetoothDeviceCloseConnection(wiiremote->device); - return false; - } - IOBluetoothObjectRetain(wiiremote->ichan); - - return (ret==kIOReturnSuccess); -} - -//-------------------------------------------------------------------------------------------- - -Boolean sendCommand(WiiRemoteRef wiiremote, unsigned char *data, unsigned short length) -{ - unsigned char buf[40]; - IOReturn ret; - int i; - - memset(buf,0,40); - buf[0] = 0x52; - memcpy(buf+1, data, length); - if (buf[1] == 0x16) - length=23; - else - length++; - - usleep(kWait); // wait 10ms // Done to make sure commands don't happen too fast. - - for (i = 0; i<kTrial; i++) - { - ret = IOBluetoothL2CAPChannelWriteSync(wiiremote->cchan, buf, length); - if (ret == kIOReturnSuccess) - break; - usleep(kWait); - } - - if (ret != kIOReturnSuccess) - wiiremote_disconnect(wiiremote); - - return (ret==kIOReturnSuccess); -} - -Boolean writeData(WiiRemoteRef wiiremote, const unsigned char *data, unsigned long address, unsigned short length) -{ - unsigned char cmd[22]; - int i; - unsigned long addr = address; - - - for(i=0 ; i<length ; i++) - cmd[i+6] = data[i]; - - for(;i<16 ; i++) - cmd[i+6]= 0; - - cmd[0] = 0x16; - cmd[1] = (addr>>24) & 0xFF; - cmd[2] = (addr>>16) & 0xFF; - cmd[3] = (addr>> 8) & 0xFF; - cmd[4] = (addr>> 0) & 0xFF; - cmd[5] = length; - - // and of course the vibration flag, as usual - if (wiiremote->isVibrationEnabled) cmd[1] |= 0x01; - - data = cmd; - - return sendCommand(wiiremote, cmd, 22); -} - -Boolean readData(WiiRemoteRef wiiremote, unsigned long address, unsigned short length) -{ - - unsigned char cmd[7]; - unsigned long addr = address; - unsigned short len = length; - - cmd[0] = 0x17; - cmd[1] = (addr>>24)&0xFF; - cmd[2] = (addr>>16)&0xFF; - cmd[3] = (addr>> 8)&0xFF; - cmd[4] = (addr>> 0)&0xFF; - - cmd[5] = (len >> 8)&0xFF; - cmd[6] = (len >> 0)&0xFF; - - if (wiiremote->isVibrationEnabled) cmd[1] |= 0x01; - if (cmd[1] & 0x02) wiiremote->readingRegister = true; - - return sendCommand(wiiremote, cmd, 7); -} - -//-------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------- - -void checkDevice(WiiRemoteRef wiiremote, IOBluetoothDeviceRef device) -{ - post("checkDevice"); - CFStringRef name; - CFStringRef address; - - if (wiiremote_isconnected(wiiremote)) - return; - - name = IOBluetoothDeviceGetName(device); - address = IOBluetoothDeviceGetAddressString(device); - if (name != nil && address != nil) - { - if (CFStringCompare(name, CFSTR("Nintendo RVL-CNT-01"), 0) == kCFCompareEqualTo) - { - if ( CFStringGetLength(wiiremote->address) == 0 - || CFStringCompare(address, wiiremote->address, kCFCompareCaseInsensitive) == kCFCompareEqualTo) - { - wiiremote->device = IOBluetoothObjectRetain(device); - if ( wiiremote_connect(wiiremote) == false ) - wiiremote_disconnect(wiiremote); - } - } - } -} - -void myFoundFunc(void *refCon, IOBluetoothDeviceInquiryRef inquiry, IOBluetoothDeviceRef device) -{ - post("myFoundFunc"); - checkDevice((WiiRemoteRef)refCon, device); -} - -void myUpdatedFunc(void *refCon, IOBluetoothDeviceInquiryRef inquiry, IOBluetoothDeviceRef device, uint32_t devicesRemaining) -{ - post("myUpdatedFunc"); - - checkDevice((WiiRemoteRef)refCon, device); -} - -void myCompleteFunc(void *refCon, IOBluetoothDeviceInquiryRef inquiry, IOReturn error, Boolean aborted) -{ - post("myCompleteFunc"); - - if (aborted) return; // called by stop ;) - - if (error != kIOReturnSuccess) - { - wiiremote_stopsearch((WiiRemoteRef)refCon); - return; - } -#ifdef PD - // PD doesn't use the Carbon loop, so we have to manually control it - CFRunLoopStop( CFRunLoopGetCurrent() ); -#endif -} - -//-------------------------------------------------------------------------------------------- - -Boolean wiiremote_isconnected(WiiRemoteRef wiiremote) -{ - Boolean result; - - result = wiiremote->device != nil && IOBluetoothDeviceIsConnected(wiiremote->device); - return result; -} - -Boolean wiiremote_search(WiiRemoteRef wiiremote, char *address) -{ - post("wiiremote_search"); - IOReturn ret; - - if (wiiremote->inquiry != nil) - return true; - - wiiremote->inquiry = IOBluetoothDeviceInquiryCreateWithCallbackRefCon((void *)wiiremote); - IOBluetoothDeviceInquirySetDeviceFoundCallback(wiiremote->inquiry, myFoundFunc); - IOBluetoothDeviceInquirySetDeviceNameUpdatedCallback(wiiremote->inquiry, myUpdatedFunc); - IOBluetoothDeviceInquirySetCompleteCallback(wiiremote->inquiry, myCompleteFunc); - - if (wiiremote->address != nil) - CFRelease(wiiremote->address); - wiiremote->address = CFStringCreateWithCString(nil, address, kCFStringEncodingMacRoman); - - ret = IOBluetoothDeviceInquiryStart(wiiremote->inquiry); - if (ret != kIOReturnSuccess) - { - IOBluetoothDeviceInquiryDelete(wiiremote->inquiry); - wiiremote->inquiry = nil; - return false; - } -#ifdef PD - CFRunLoopRun(); // PD doesn't use the Carbon loop, so we have to manually control it -#endif - return true; -} - -Boolean wiiremote_stopsearch(WiiRemoteRef wiiremote) -{ - post("wiiremote_stopsearch"); - IOReturn ret; - - if (wiiremote->inquiry == nil) - { - return true; // already stopped - } - - ret = IOBluetoothDeviceInquiryStop(wiiremote->inquiry); - - if (ret != kIOReturnSuccess && ret != kIOReturnNotPermitted) - { - // kIOReturnNotPermitted is if it's already stopped - } - - IOBluetoothDeviceInquiryDelete(wiiremote->inquiry); - wiiremote->inquiry = nil; - - return (ret==kIOReturnSuccess); -} - -//-------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------- - -unsigned char decrypt(unsigned char data) -{ - return (data ^ 0x17) + 0x17; -} - -//-------------------------------------------------------------------------------------------- - -/** -* Handle report 0x21 (Read Data) from wiimote. - * dp[0] = Bluetooth header - * dp[1] = (0x21) Report/Channel ID - * dp[2] = Wiimote Buttons - * dp[3] = Wiimote Buttons - * dp[4] = High 4 bits = payload size; Low 4 bits = Error flag (0 = all good) - * dp[5] = Offset of memory read - * dp[6] = Offset of memory read - * dp[7+] = the Data. - **/ - -void handleRAMData(WiiRemoteRef wiiremote, unsigned char *dp, size_t dataLength) -{ - // specify attached expasion device - if ((dp[5] == 0x00) && (dp[6] == 0xF0)) - { - if (decrypt(dp[21]) == 0x00) - { - wiiremote->expType = WiiNunchuk; - } - else - if (decrypt(dp[21]) == 0x01) - { - wiiremote->expType = WiiClassicController; - } - else - { - wiiremote->expType = WiiExpNotAttached; - } - // initExpPort = NO; - return; - } - - // wiimote calibration data - if (!wiiremote->readingRegister && dp[5] == 0x00 && dp[6] == 0x20) - { - wiiremote->wiiCalibData.accX_zero = dp[7]; - wiiremote->wiiCalibData.accY_zero = dp[8]; - wiiremote->wiiCalibData.accZ_zero = dp[9]; - - //dp[10] - unknown/unused - - wiiremote->wiiCalibData.accX_1g = dp[11]; - wiiremote->wiiCalibData.accY_1g = dp[12]; - wiiremote->wiiCalibData.accZ_1g = dp[13]; - return; - } - - // expansion device calibration data. - if (wiiremote->readingRegister && dp[5] == 0x00 && dp[6] == 0x20) - { - if (wiiremote->expType == WiiNunchuk) - { - //nunchuk calibration data - wiiremote->nunchukCalibData.accX_zero = decrypt(dp[7]); - wiiremote->nunchukCalibData.accY_zero = decrypt(dp[8]); - wiiremote->nunchukCalibData.accZ_zero = decrypt(dp[9]); - - wiiremote->nunchukCalibData.accX_1g = decrypt(dp[11]); - wiiremote->nunchukCalibData.accY_1g = decrypt(dp[12]); - wiiremote->nunchukCalibData.accZ_1g = decrypt(dp[13]); - - wiiremote->nunchukJoyStickCalibData.x_max = decrypt(dp[15]); - wiiremote->nunchukJoyStickCalibData.x_min = decrypt(dp[16]); - wiiremote->nunchukJoyStickCalibData.x_center = decrypt(dp[17]); - - wiiremote->nunchukJoyStickCalibData.y_max = decrypt(dp[18]); - wiiremote->nunchukJoyStickCalibData.y_min = decrypt(dp[19]); - wiiremote->nunchukJoyStickCalibData.y_center = decrypt(dp[20]); - - return; - } - else - if (wiiremote->expType == WiiClassicController) - { - //classic controller calibration data (probably) - } - } - - // wii remote buttons - wiiremote->buttonData = ((short)dp[2] << 8) + dp[3]; -} - -void handleStatusReport(WiiRemoteRef wiiremote, unsigned char *dp, size_t dataLength) -{ - wiiremote->batteryLevel = (double)dp[7]; - wiiremote->batteryLevel /= (double)0xC0; // C0 = fully charged. - - if ((dp[4] & 0x02)) //some device attached to Wiimote - { - wiiremote->isExpansionPortAttached = true; - // initExpPort = YES; - - Boolean ret = writeData(wiiremote, (darr){0x00}, 0x04A40040, 1); // Initialize the device - - if (ret == false) - { - wiiremote->isExpansionPortAttached = false; - return; - } - - usleep(kWait); // Give the write a chance to be processed. - - ret = readData(wiiremote, 0x04A400F0, 16); // read expansion device type - if (ret == false) - { - wiiremote->isExpansionPortAttached = false; - } - } - else - { // unplugged - wiiremote->isExpansionPortAttached = false; - wiiremote->expType = WiiExpNotAttached; - } - - if (dp[4] & 0x10) - wiiremote->isLED1Illuminated = true; - else - wiiremote->isLED1Illuminated = false; - - if (dp[4] & 0x20) - wiiremote->isLED2Illuminated = true; - else - wiiremote->isLED2Illuminated = false; - - if (dp[4] & 0x40) - wiiremote->isLED3Illuminated = true; - else - wiiremote->isLED3Illuminated = false; - - if (dp[4] & 0x80) - wiiremote->isLED4Illuminated = true; - else - wiiremote->isLED4Illuminated = false; -} - -void handleExtensionData(WiiRemoteRef wiiremote, unsigned char *dp, size_t dataLength) -{ - unsigned char startByte; - - switch (dp[1]) { - case 0x34 : - startByte = 4; - break; - case 0x35 : - startByte = 7; - break; - case 0x36 : - startByte = 14; - break; - case 0x37 : - startByte = 17; - break; - default: - return; // This shouldn't ever happen. - break; - } - - if (wiiremote->expType == WiiNunchuk) - { - wiiremote->nStickX = decrypt(dp[startByte]); - wiiremote->nStickY = decrypt(dp[startByte +1]); - wiiremote->nAccX = decrypt(dp[startByte +2]); - wiiremote->nAccY = decrypt(dp[startByte +3]); - wiiremote->nAccZ = decrypt(dp[startByte +4]); - wiiremote->nButtonData = decrypt(dp[startByte +5]); - - wiiremote->nLowZ = wiiremote->nLowZ * .9 + wiiremote->nAccZ * .1; - wiiremote->nLowX = wiiremote->nLowX * .9 + wiiremote->nAccX * .1; - - float absx = abs(wiiremote->nLowX - 128); - float absz = abs(wiiremote->nLowZ - 128); - - if (wiiremote->nOrientation == 0 || wiiremote->nOrientation == 2) absx -= 5; - if (wiiremote->nOrientation == 1 || wiiremote->nOrientation == 3) absz -= 5; - - if (absz >= absx) - { - if (absz > 5) - wiiremote->nOrientation = (wiiremote->nLowZ > 128) ? 0 : 2; - } - else - { - if (absx > 5) - wiiremote->nOrientation = (wiiremote->nLowX > 128) ? 3 : 1; - } - } - else - if (wiiremote->expType == WiiClassicController) - { - wiiremote->cButtonData = (unsigned short)(decrypt(dp[startByte + 4]) << 8) + decrypt(dp[startByte + 5]); - wiiremote->cButtonData = ~wiiremote->cButtonData; // bit reverse - - wiiremote->cStickX1 = decrypt(dp[startByte]) & 0x3F; - wiiremote->cStickY1 = decrypt(dp[startByte + 1]) & 0x3F; - - wiiremote->cStickX2 = (((decrypt(dp[startByte +0]) & 0xC0) >> 3) | - ((decrypt(dp[startByte +1]) & 0xC0) >> 5) | - ((decrypt(dp[startByte +2]) & 0x80) >> 7)) & 0x1F; - wiiremote->cStickY2 = decrypt(dp[startByte + 2]) & 0x1F; - - wiiremote->cAnalogL = (((decrypt(dp[startByte +2]) & 0x60) >> 2) | - ((decrypt(dp[startByte +3]) & 0xE0) >> 5)) & 0x1F; - wiiremote->cAnalogR = decrypt(dp[startByte + 3]) & 0x1F; - } -} - -void handleIRData(WiiRemoteRef wiiremote, unsigned char *dp, size_t dataLength) -{ - int i; - - if (dp[1] == 0x33) - { // 12 IR bytes - int startByte = 0; - for(i=0 ; i < 4 ; i++) - { - startByte = 7 + 3 * i; - wiiremote->irData[i].x = (dp[startByte +0] | ((dp[startByte +2] & 0x30) << 4)) & 0x3FF; - wiiremote->irData[i].y = (dp[startByte +1] | ((dp[startByte +2] & 0xC0) << 2)) & 0x3FF; - wiiremote->irData[i].s = dp[startByte +2] & 0x0F; - } - } - else - { // 10 IR bytes - int shift = (dp[1] == 0x36) ? 4 : 7; - int startByte = 0; - for (i=0; i < 2; i++) { - startByte = shift + 5 * i; - wiiremote->irData[2*i].x = (dp[startByte +0] | ((dp[startByte +2] & 0x30) << 4)) & 0x3FF; - wiiremote->irData[2*i].y = (dp[startByte +1] | ((dp[startByte +2] & 0xC0) << 2)) & 0x3FF; - wiiremote->irData[2*i].s = ((wiiremote->irData[2*i].x == wiiremote->irData[2*i].y) && (wiiremote->irData[2*i].x == 0x3FF)) ? 0x0F : 0x05; // No size is given in 10 byte report. - - wiiremote->irData[(2*i)+1].x = (dp[startByte +3] | ((dp[startByte +2] & 0x03) << 8)) & 0x3FF; - wiiremote->irData[(2*i)+1].y = (dp[startByte +4] | ((dp[startByte +2] & 0x0C) << 6)) & 0x3FF; - wiiremote->irData[(2*i)+1].s = ((wiiremote->irData[(2*i)+1].x == wiiremote->irData[(2*i)+1].y) && (wiiremote->irData[(2*i)+1].x == 0x3FF)) ? 0x0F : 0x05; // No size is given in 10 byte report. - } - } - - int p1 = -1; - int p2 = -1; - // we should modify this loop to take the points with the lowest s (the brightest ones) - for (i=0 ; i<4 ; i++) { - if (p1 == -1) { - if (wiiremote->irData [i].s < 0x0F) - p1 = i; - } else { - if (wiiremote->irData [i].s < 0x0F) { - p2 = i; - break; - } - } - } - - double ox, oy; - if ((p1 > -1) && (p2 > -1)) - { - int l = wiiremote->leftPoint; - if (wiiremote->leftPoint == -1) - { - switch (wiiremote->orientation) - { - case 0: l = (wiiremote->irData[p1].x < wiiremote->irData[p2].x) ? 0 : 1; break; - case 1: l = (wiiremote->irData[p1].y > wiiremote->irData[p2].y) ? 0 : 1; break; - case 2: l = (wiiremote->irData[p1].x > wiiremote->irData[p2].x) ? 0 : 1; break; - case 3: l = (wiiremote->irData[p1].y < wiiremote->irData[p2].y) ? 0 : 1; break; - } - - wiiremote->leftPoint = l; - } - - int r = 1-l; - - double dx = wiiremote->irData[r].x - wiiremote->irData[l].x; - double dy = wiiremote->irData[r].y - wiiremote->irData[l].y; - double d = hypot (dx, dy); - - dx /= d; - dy /= d; - - double cx = (wiiremote->irData[l].x + wiiremote->irData[r].x)/kWiiIRPixelsWidth - 1; - double cy = (wiiremote->irData[l].y + wiiremote->irData[r].y)/kWiiIRPixelsHeight - 1; - - ox = -dy*cy-dx*cx; - oy = -dx*cy+dy*cx; - - // cam: - // Compensate for distance. There must be fewer than 0.75*768 pixels between the spots for this to work. - // In other words, you have to be far enough away from the sensor bar for the two spots to have enough - // space on the image sensor to travel without one of the points going off the image. - // note: it is working very well ... - double gain = 4; - if (d < (0.75 * kWiiIRPixelsHeight)) - gain = 1 / (1 - d/kWiiIRPixelsHeight); - - ox *= gain; - oy *= gain; - - wiiremote->angle = atan2(dy, dx); - wiiremote->tracking = true; - } - else - { - ox = oy = -100; - wiiremote->leftPoint = -1; // not tracking - wiiremote->angle = -100; - wiiremote->tracking = false; - } - - wiiremote->posX = ox; - wiiremote->posY = oy; -} - -void handleButtonReport(WiiRemoteRef wiiremote, unsigned char *dp, size_t dataLength) -{ - // wiimote buttons - wiiremote->buttonData = ((short)dp[2] << 8) + dp[3]; - - // report contains extension data - switch (dp[1]) - { - case 0x34 : - case 0x35 : - case 0x36 : - case 0x37 : - handleExtensionData(wiiremote, dp, dataLength); - break; - } - - // report contains IR data - if (dp[1] & 0x02) - { - handleIRData(wiiremote, dp, dataLength); - } - - // report contains motion sensor data - if (dp[1] & 0x01) - { - wiiremote->accX = dp[4]; - wiiremote->accY = dp[5]; - wiiremote->accZ = dp[6]; - - wiiremote->lowZ = wiiremote->lowZ * 0.9 + wiiremote->accZ * 0.1; - wiiremote->lowX = wiiremote->lowX * 0.9 + wiiremote->accX * 0.1; - - float absx = abs(wiiremote->lowX-128); - float absz = abs(wiiremote->lowZ-128); - - if (wiiremote->orientation == 0 || wiiremote->orientation == 2) absx -= 5; - if (wiiremote->orientation == 1 || wiiremote->orientation == 3) absz -= 5; - - if (absz >= absx) - { - if (absz > 5) - wiiremote->orientation = (wiiremote->lowZ > 128)?0:2; - } - else - { - if (absx > 5) - wiiremote->orientation = (wiiremote->lowX > 128)?3:1; - } - } -} - -//-------------------------------------------------------------------------------------------- - - void myDataListener(IOBluetoothL2CAPChannelRef channel, void *dataPointer, UInt16 dataLength, void *refCon) -{ - WiiRemoteRef wiiremote = (WiiRemoteRef)refCon; - unsigned char* dp = (unsigned char*)dataPointer; - - if (!wiiremote->device) - return; - - //controller status (expansion port and battery level data) - received when report 0x15 sent to Wiimote (getCurrentStatus:) or status of expansion port changes. - if (dp[1] == 0x20 && dataLength >= 8) - { - handleStatusReport(wiiremote, dp, dataLength); - requestUpdates(wiiremote); // Make sure we keep getting state change reports. - return; - } - - if (dp[1] == 0x21) - { - handleRAMData(wiiremote, dp, dataLength); - return; - } - - if (dp[1] == 0x22) - { // Write data response - //NSLog(@"Write data response: %00x %00x %00x %00x", dp[2], dp[3], dp[4], dp[5]); - return; - } - - // report contains button info - if ((dp[1] & 0xF0) == 0x30) - { - handleButtonReport(wiiremote, dp, dataLength); - } -} - -void myEventListener(IOBluetoothL2CAPChannelRef channel, void *refCon, IOBluetoothL2CAPChannelEvent *event) -{ - if (event->eventType == kIOBluetoothL2CAPChannelEventTypeData) - { - // In thise case: - // event->u.newData.dataPtr is a pointer to the block of data received. - // event->u.newData.dataSize is the size of the block of data. - myDataListener(channel, event->u.data.dataPtr, event->u.data.dataSize, refCon); - } - else - if (event->eventType == kIOBluetoothL2CAPChannelEventTypeClosed) - { - // In this case: - // event->u.terminatedChannel is the channel that was terminated. It can be converted in an IOBluetoothL2CAPChannel - // object with [IOBluetoothL2CAPChannel withL2CAPChannelRef:]. (see below). - } -} - -void myDisconnectedFunc(void * refCon, IOBluetoothUserNotificationRef inRef, IOBluetoothObjectRef objectRef) -{ - CFStringRef itsAddress, myAddress; - - itsAddress = IOBluetoothDeviceGetAddressString(objectRef); - if (itsAddress != nil) - { - myAddress = IOBluetoothDeviceGetAddressString(((WiiRemoteRef)refCon)->device); - if (myAddress != nil) - { - if (CFStringCompare(itsAddress, myAddress, 0) == kCFCompareEqualTo) - { - wiiremote_disconnect((WiiRemoteRef)refCon); - } - CFRelease(myAddress); - } - CFRelease(itsAddress); - } -} - -//-------------------------------------------------------------------------------------------- - -void wiiremote_getaddress(WiiRemoteRef wiiremote, char *address) -{ - CFStringRef cfstring; - - cfstring = IOBluetoothDeviceGetAddressString(wiiremote->device); - CFStringGetCString(cfstring, address, 32, kCFStringEncodingMacRoman); - CFRelease(cfstring); - -} - -//-------------------------------------------------------------------------------------------- - -Boolean wiiremote_connect(WiiRemoteRef wiiremote) -{ - IOReturn ret; - Boolean result; - short i; - - if (wiiremote->device == nil) - return false; - - // connect the device - for (i=0; i<kTrial; i++) - { - ret = IOBluetoothDeviceOpenConnection(wiiremote->device, nil, nil); - if ( ret == kIOReturnSuccess) - break; - usleep(kWait); // wait 10ms - } - if (i==kTrial) - return false; - - wiiremote->disconnectNotification = IOBluetoothDeviceRegisterForDisconnectNotification(wiiremote->device, myDisconnectedFunc, (void *)wiiremote); - - // performs an SDP query - for (i=0; i<kTrial; i++) - { - ret = IOBluetoothDevicePerformSDPQuery(wiiremote->device, nil, nil); - if ( ret == kIOReturnSuccess) - break; - usleep(kWait); // wait 10ms - } - if (i==kTrial) - return false; - - result = openCChan(wiiremote); - result = openIChan(wiiremote); - - if (result) - { - result = wiiremote_led(wiiremote, wiiremote->isLED1Illuminated, wiiremote->isLED2Illuminated, wiiremote->isLED3Illuminated, wiiremote->isLED4Illuminated); - } - - if (result == false) - { - wiiremote_disconnect(wiiremote); - return result; - } - - wiiremote_getstatus(wiiremote); - requestUpdates(wiiremote); - - readData(wiiremote, 0x0020, 7); // Get Accelerometer callibration data - - return true; -} - - -Boolean wiiremote_disconnect(WiiRemoteRef wiiremote) -{ - short i = 0; - - if (wiiremote->cchan) - { - if (IOBluetoothDeviceIsConnected(wiiremote->device)) - { - for (i=0; i<kTrial; i++) - { - if (IOBluetoothL2CAPChannelCloseChannel(wiiremote->cchan) == kIOReturnSuccess) - break; - usleep(kWait); // wait 10ms - } - } - if (i==kTrial) return false; - IOBluetoothObjectRelease(wiiremote->cchan); - wiiremote->cchan = nil; - } - - if (wiiremote->ichan) - { - if (IOBluetoothDeviceIsConnected(wiiremote->device)) - { - for (i=0; i<kTrial; i++) - { - if (IOBluetoothL2CAPChannelCloseChannel(wiiremote->ichan) == kIOReturnSuccess) - break; - } - } - if (i==kTrial) return false; - IOBluetoothObjectRelease(wiiremote->ichan); - wiiremote->ichan = nil; - } - - if (wiiremote->device) - { - if (IOBluetoothDeviceIsConnected(wiiremote->device)) - { - for (i=0; i<kTrial; i++) - { - if (IOBluetoothDeviceCloseConnection(wiiremote->device) == kIOReturnSuccess) - break; - } - } - if (i==kTrial) return false; - IOBluetoothObjectRelease(wiiremote->device); - wiiremote->device = nil; - } - - if (wiiremote->disconnectNotification != nil) - { - IOBluetoothUserNotificationUnregister(wiiremote->disconnectNotification); - wiiremote->disconnectNotification = nil; - } - - return true; -} - -//-------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------- - -Boolean requestUpdates(WiiRemoteRef wiiremote) -{ - Boolean result; - - // Set the report type the Wiimote should send. - unsigned char cmd[] = {0x12, 0x02, 0x30}; // Just buttons. - - if (wiiremote->isVibrationEnabled) cmd[1] |= 0x01; - - /* - There are numerous status report types that can be requested. - The IR reports must be matched with the data format set when initializing the IR camera: - 0x36, 0x37 - 10 IR bytes go with Basic mode - 0x33 - 12 IR bytes go with Extended mode - 0x3e/0x3f - 36 IR bytes go with Full mode - - The Nunchuk and Classic controller use 6 bytes to report their state, so the reports that - give more extension bytes don't provide any more info. - - Buttons | Accelerometer | IR | Extension - --------------------+-------------------+-----------+------------- - 0x30: Core Buttons | | | - 0x31: Core Buttons | Accelerometer | | - 0x32: Core Buttons | | | 8 bytes - 0x33: Core Buttons | Accelerometer | 12 bytes | - 0x34: Core Buttons | | | 19 bytes - 0x35: Core Buttons | Accelerometer | | 16 bytes - 0x36: Core Buttons | | 10 bytes | 9 bytes - 0x37: Core Buttons | Accelerometer | 10 bytes | 6 bytes - ?? 0x38: Core Buttons and Accelerometer with 16 IR bytes ?? - 0x3d: | | | 21 bytes - - 0x3e / 0x3f: Interleaved Core Buttons and Accelerometer with 16/36 IR bytes - - */ - - if (wiiremote->isIRSensorEnabled) - { - if (wiiremote->isExpansionPortEnabled) - { - cmd[2] = 0x36; // Buttons, 10 IR Bytes, 9 Extension Bytes - wiiremote->wiiIRMode = kWiiIRModeBasic; - } - else - { - cmd[2] = 0x33; // Buttons, Accelerometer, and 12 IR Bytes. - wiiremote->wiiIRMode = kWiiIRModeExtended; - } - - // Set IR Mode - writeData(wiiremote, (darr){ wiiremote->wiiIRMode }, 0x04B00033, 1); - usleep(kWait); // wait 10ms - } - else - { - if (wiiremote->isExpansionPortEnabled) - { - cmd[2] = 0x34; // Buttons, 19 Extension Bytes - } - else - { - cmd[2] = 0x30; // Buttons - } - } - - if (wiiremote->isMotionSensorEnabled) cmd[2] |= 0x01; // Add Accelerometer - - usleep(kWait); // wait 10ms - result = sendCommand(wiiremote, cmd, 3); - - return(result); -} - -//-------------------------------------------------------------------------------------------- - -Boolean wiiremote_motionsensor(WiiRemoteRef wiiremote, Boolean enabled) -{ - wiiremote->isMotionSensorEnabled = enabled; - return requestUpdates(wiiremote); -} - -Boolean wiiremote_vibration(WiiRemoteRef wiiremote, Boolean enabled) -{ - - wiiremote->isVibrationEnabled = enabled; - return requestUpdates(wiiremote); -} - -Boolean wiiremote_led(WiiRemoteRef wiiremote, Boolean enabled1, Boolean enabled2, Boolean enabled3, Boolean enabled4) -{ - unsigned char cmd[] = {0x11, 0x00}; - if (wiiremote->isVibrationEnabled) cmd[1] |= 0x01; - if (enabled1) cmd[1] |= 0x10; - if (enabled2) cmd[1] |= 0x20; - if (enabled3) cmd[1] |= 0x40; - if (enabled4) cmd[1] |= 0x80; - - wiiremote->isLED1Illuminated = enabled1; - wiiremote->isLED2Illuminated = enabled2; - wiiremote->isLED3Illuminated = enabled3; - wiiremote->isLED4Illuminated = enabled4; - - return sendCommand(wiiremote, cmd, 2); -} - -Boolean wiiremote_expansion(WiiRemoteRef wiiremote, Boolean enabled) -{ - wiiremote->isExpansionPortEnabled = enabled; - if (wiiremote->isExpansionPortAttached == false) - { - wiiremote->isExpansionPortEnabled = false; - } - else - { - readData(wiiremote, 0x04A40020, 16); //get calbdata - } - - return requestUpdates(wiiremote); -} - -Boolean wiiremote_irsensor(WiiRemoteRef wiiremote, Boolean enabled) -{ - Boolean ret; - - wiiremote->isIRSensorEnabled = enabled; - - // ir enable 1 - unsigned char cmd[] = {0x13, 0x00}; - if (wiiremote->isVibrationEnabled) cmd[1] |= 0x01; - if (wiiremote->isIRSensorEnabled) cmd[1] |= 0x04; - if ((ret = sendCommand(wiiremote, cmd, 2)) == false) - return ret; - usleep(kWait); - - // set register 0x1a (ir enable 2) - unsigned char cmd2[] = {0x1a, 0x00}; - if (enabled) cmd2[1] |= 0x04; - if ((ret = sendCommand(wiiremote, cmd2, 2)) == false) - return ret; - usleep(kWait); - - if(enabled) - { - // based on marcan's method, found on wiili wiki: - // tweaked to include some aspects of cliff's setup procedure in the hopes - // of it actually turning on 100% of the time (was seeing 30-40% failure rate before) - // the sleeps help it it seems - usleep(kWait); - if ((ret = writeData(wiiremote, (darr){0x01}, 0x04B00030, 1)) == false) return ret; - usleep(kWait); - if ((ret = writeData(wiiremote, (darr){0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0xC0}, 0x04B00000, 9)) == false) return ret; - usleep(kWait); - if ((ret = writeData(wiiremote, (darr){0x40, 0x00}, 0x04B0001A, 2)) == false) return ret; - usleep(kWait); - if ((ret = writeData(wiiremote, (darr){0x08}, 0x04B00030, 1)) == false) return ret; - usleep(kWait); - - requestUpdates(wiiremote); - } - else - { - // probably should do some writes to power down the camera, save battery - // but don't know how yet. - - ret = wiiremote_motionsensor(wiiremote, wiiremote->isMotionSensorEnabled); - ret = wiiremote_vibration(wiiremote, wiiremote->isVibrationEnabled); - ret = wiiremote_expansion(wiiremote, wiiremote->isExpansionPortEnabled); - } - - return ret; -} - -Boolean wiiremote_getstatus(WiiRemoteRef wiiremote) -{ - unsigned char cmd[] = {0x15, 0x00}; - return sendCommand(wiiremote, cmd, 2); -} - - |