int CompassSensor::enable(int32_t handle, int en) { unsigned int flags = en ? 1 : 0; int fd, ret = 0; char buf[50]; D("CompassSensor - %s, flags = %d, mEnabled = %d", __func__, flags, mEnabled); if (flags == mEnabled) return 0; if ((fd = SensorBase::openFile(mConfig->activate_path, O_RDWR)) < 0) { E("CompassSensor: Open device file failed, possible path: %s!", mConfig->activate_path); return -1; } if (flags == 1 && mEnabled == 0) { mCalDataFile = open(mConfig->config_path, O_RDWR | O_CREAT, S_IRWXU); if (mCalDataFile > -1) { struct flock lock; lock.l_type = F_WRLCK; lock.l_start = 0; lock.l_whence = SEEK_SET; lock.l_len = 0; if (fcntl(mCalDataFile, F_SETLK, &lock) < 0) E("CompassSensor - calibration file lock fail"); readCalibrationData(); filter_index = -1; } } else if (flags == 0 && mEnabled == 1) { if (mCalDataFile > -1) { struct flock lock; lock.l_type = F_UNLCK; lock.l_start = 0; lock.l_whence = SEEK_SET; lock.l_len = 0; if (fcntl(mCalDataFile, F_SETLK, &lock) < 0) E("CompassSensor - calibration file unlock fail"); storeCalibrationData(); close(mCalDataFile); } } buf[1] = 0; buf[0] = flags ? '1' : '0'; ret = write(fd, buf, sizeof(buf)); if (ret > 0) { mEnabled = flags; ret = 0; } close(fd); return ret; }
/* Main function, contains kernel driver event loop */ int main(int argc, char **argv) { char* devname = 0; int doDaemonize = 1; int doWait = 0; int clickMode = 2; int i; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "--debug") == 0) { doDaemonize = 0; debugMode = 1; } else if (strcmp(argv[i], "--wait") == 0) { doWait = 1; } else if (strcmp(argv[i], "--click=first") == 0) { clickMode = 0; } else if (strcmp(argv[i], "--click=second") == 0) { clickMode = 1; } else if (strcmp(argv[i], "--click=center") == 0) { clickMode = 2; } else { devname = argv[i]; } } initGestures(clickMode); if (doDaemonize) { daemonize(); } if (doWait) { /* Wait until all necessary things are loaded */ sleep(10); } /* Connect to X server */ if ((display = XOpenDisplay(NULL)) == NULL) { fprintf(stderr, "Couldn't connect to X server\n"); exit(1); } /* Read X data */ screenNum = DefaultScreen(display); root = RootWindow(display, screenNum); // realDisplayWidth = DisplayWidth(display, screenNum); // realDisplayHeight = DisplayHeight(display, screenNum); WM_CLASS = XInternAtom(display, "WM_CLASS", 0); /* Get notified about new windows */ XSelectInput(display, root, StructureNotifyMask | SubstructureNotifyMask); //TODO load blacklist and profiles from file(s) /* Device file name */ if (devname == 0) { devname = "/dev/twofingtouch"; } /* Try to read from device file */ int fileDesc; if ((fileDesc = open(devname, O_RDONLY)) < 0) { perror("twofing"); return 1; } fd_set fileDescSet; FD_ZERO(&fileDescSet); int eventQueueDesc = XConnectionNumber(display); while (1) { /* Perform initialization at beginning and after module has been re-loaded */ int rd, i; struct input_event ev[64]; char name[256] = "Unknown"; /* Read device name */ ioctl(fileDesc, EVIOCGNAME(sizeof(name)), name); printf("Input device name: \"%s\"\n", name); //TODO activate again? //XSetErrorHandler(invalidWindowHandler); int opcode, event, error; if (!XQueryExtension(display, "RANDR", &opcode, &event, &error)) { printf("X RANDR extension not available.\n"); XCloseDisplay(display); exit(1); } /* Which version of XRandR? We support 1.3 */ int major = 1, minor = 3; if (!XRRQueryVersion(display, &major, &minor)) { printf("XRandR version not available.\n"); XCloseDisplay(display); exit(1); } else if(!(major>1 || (major == 1 && minor >= 3))) { printf("XRandR 1.3 not available. Server supports %d.%d\n", major, minor); XCloseDisplay(display); exit(1); } /* XInput Extension available? */ if (!XQueryExtension(display, "XInputExtension", &opcode, &event, &error)) { printf("X Input extension not available.\n"); XCloseDisplay(display); exit(1); } /* Which version of XI2? We support 2.1 */ major = 2; minor = 1; if (XIQueryVersion(display, &major, &minor) == BadRequest) { printf("XI 2.1 not available. Server supports %d.%d\n", major, minor); XCloseDisplay(display); exit(1); } screenWidth = XDisplayWidth(display, screenNum); screenHeight = XDisplayHeight(display, screenNum); int n; XIDeviceInfo *info = XIQueryDevice(display, XIAllDevices, &n); if (!info) { printf("No XInput devices available\n"); exit(1); } /* Go through input devices and look for that with the same name as the given device */ int devindex; for (devindex = 0; devindex < n; devindex++) { if (info[devindex].use == XIMasterPointer || info[devindex].use == XIMasterKeyboard) continue; if (strcmp(info[devindex].name, name) == 0) { deviceID = info[devindex].deviceid; break; } } if (deviceID == -1) { printf("Input device not found in XInput device list.\n"); exit(1); } XIFreeDeviceInfo(info); if(debugMode) printf("XInput device id is %i.\n", deviceID); /* Prepare by reading calibration */ readCalibrationData(1); /* Receive device property change events */ XIEventMask device_mask2; unsigned char mask_data2[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; device_mask2.deviceid = deviceID; device_mask2.mask_len = sizeof(mask_data2); device_mask2.mask = mask_data2; XISetMask(device_mask2.mask, XI_PropertyEvent); XISetMask(device_mask2.mask, XI_ButtonPress); //XISetMask(device_mask2.mask, XI_TouchBegin); //XISetMask(device_mask2.mask, XI_TouchUpdate); //XISetMask(device_mask2.mask, XI_TouchEnd); XISelectEvents(display, root, &device_mask2, 1); /* Recieve events when screen size changes */ XRRSelectInput(display, root, RRScreenChangeNotifyMask); /* Receive touch events */ /* Needed for XTest to work correctly */ XTestGrabControl(display, True); /* Needed for some reason to receive events */ /* XGrabPointer(display, root, False, 0, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); XUngrabPointer(display, CurrentTime);*/ grab(display, deviceID); printf("Reading input from device ... (interrupt to exit)\n"); /* We perform raw event reading here as X touch events don't seem too reliable */ int currentSlot = 0; /* If we use the legacy protocol, we collect all data of one finger into tempFingerInfo and set it to the correct slot once MT_SYNC occurs. */ FingerInfo tempFingerInfo = { .rawX=0, .rawY=0, .rawZ=0, .id = -1, .slotUsed = 0, .setThisTime = 0 }; while (1) { FD_SET(fileDesc, &fileDescSet); FD_SET(eventQueueDesc, &fileDescSet); select(MAX(fileDesc, eventQueueDesc) + 1, &fileDescSet, NULL, NULL, getEasingStepTimeVal()); checkEasingStep(); if(FD_ISSET(fileDesc, &fileDescSet)) { rd = read(fileDesc, ev, sizeof(struct input_event) * 64); if (rd < (int) sizeof(struct input_event)) { printf("Data stream stopped\n"); break; } for (i = 0; i < rd / sizeof(struct input_event); i++) { if (ev[i].type == EV_SYN) { if (0 == ev[i].code) { // Ev_Sync event end /* All finger data received, so process now. */ if(useLegacyProtocol) { /* Clear slots not set this time */ int i; for(i = 0; i < 2; i++) { if(fingerInfos[i].setThisTime) { fingerInfos[i].setThisTime = 0; } else { /* Clear slot */ fingerInfos[i].slotUsed = 0; } } tempFingerInfo.slotUsed = 0; } processFingers(); } else if (2 == ev[i].code) { // MT_Sync : Multitouch event end if(!useLegacyProtocol) { /* This messsage indicates we use legacy protocol, so switch */ useLegacyProtocol = 1; currentSlot = -1; tempFingerInfo.slotUsed = 0; if(debugMode) printf("Switch to legacy protocol.\n"); } else { if(tempFingerInfo.slotUsed) { /* Finger info for one finger collected in tempFingerInfo, so save it to fingerInfos. */ /* Look for slot to put the data into by looking at the tracking ids */ int index = -1; int i; for(i = 0; i < 2; i++) { if(fingerInfos[i].slotUsed && fingerInfos[i].id == tempFingerInfo.id) { index = i; break; } } if(index == -1) { for(i = 0; i < 2; i++) { if(!fingerInfos[i].slotUsed) { /* "Empty" slot, so we can add it. */ index = i; fingerInfos[i].id = tempFingerInfo.id; fingerInfos[i].slotUsed = 1; break; } } } if(index != -1) { /* Copy temporary data to slot */ fingerInfos[index].setThisTime = 1; fingerInfos[index].rawX = tempFingerInfo.rawX; fingerInfos[index].rawY = tempFingerInfo.rawY; fingerInfos[index].rawZ = tempFingerInfo.rawZ; } } } } } else if (ev[i].type == EV_MSC && (ev[i].code == MSC_RAW || ev[i].code == MSC_SCAN)) { } else if (ev[i].code == 47) { currentSlot = ev[i].value; if(currentSlot < 0 || currentSlot > 1) currentSlot = -1; } else { /* Set finger info values for current finger */ if (ev[i].code == 57) { /* ABS_MT_TRACKING_ID */ if(currentSlot != -1) { if(ev[i].value == -1) { fingerInfos[currentSlot].slotUsed = 0; } else { fingerInfos[currentSlot].id = ev[i].value; fingerInfos[currentSlot].slotUsed = 1; } } else if(useLegacyProtocol) { tempFingerInfo.id = ev[i].value; tempFingerInfo.slotUsed = 1; } }; if (ev[i].code == 53) { if(currentSlot != -1) { fingerInfos[currentSlot].rawX = ev[i].value; } else if(useLegacyProtocol) { tempFingerInfo.rawX = ev[i].value; } }; if (ev[i].code == 54) { if(currentSlot != -1) { fingerInfos[currentSlot].rawY = ev[i].value; } else if(useLegacyProtocol) { tempFingerInfo.rawY = ev[i].value; } }; if (ev[i].code == 58) { if(currentSlot != -1) { fingerInfos[currentSlot].rawZ = ev[i].value; } else if(useLegacyProtocol) { tempFingerInfo.rawZ = ev[i].value; } }; } } } if(FD_ISSET(eventQueueDesc, &fileDescSet)) { handleXEvent(); } } /* Stream stopped, probably because module has been unloaded */ close(fileDesc); /* Clean up */ releaseButton(); ungrab(display, deviceID); /* Wait until device file is there again */ while ((fileDesc = open(devname, O_RDONLY)) < 0) { sleep(1); } } }
/* X thread that processes X events in parallel to kernel device loop */ void handleXEvent() { XEvent ev; XNextEvent(display, &ev); //if(debugMode) printf("Handle event\n"); if (XGetEventData(display, &(ev.xcookie))) { XGenericEventCookie *cookie = &(ev.xcookie); // Touch events don't work right now //if (cookie->evtype == XI_TouchBegin) { // if(debugMode) printf("Touch begin\n"); //} else if (cookie->evtype == XI_TouchUpdate) { // if(debugMode) printf("Touch update\n"); //} else if (cookie->evtype == XI_TouchEnd) { // if(debugMode) printf("Touch end\n"); if (cookie->evtype == XI_Motion) { if(debugMode) printf("Motion event\n"); //int r = XIAllowEvents(display, deviceID, XIReplayDevice, CurrentTime); //printf("XIAllowEvents result: %i\n", r); } else if (cookie->evtype == XI_PropertyEvent) { /* Device properties changed -> recalibrate. */ if(debugMode) printf("Device properties changed.\n"); readCalibrationData(0); } else if(cookie->evtype == XI_ButtonPress) { if(debugMode) printf("Button Press\n"); //int r = XIAllowEvents(display, deviceID, XIReplayDevice, CurrentTime); //printf("XIAllowEvents result: %i\n", r); } // In an ideal world, the following would work. But unfortunately the touch events // delivered by evdev are often crap on the eGalax screen, with missing events when there // should be some. So we still have to read directly from the input device, as bad as that is. //if (cookie->evtype == XI_TouchBegin || cookie->evtype == XI_TouchUpdate || cookie->evtype == XI_TouchEnd) { // XIDeviceEvent * devEvt = (XIDeviceEvent*) cookie->data; // printf("Detail: %i\n", devEvt->detail); // printf("Mask[0]: %i\n", (int) devEvt->valuators.mask[0]); // // /* Look for slot to put the data into by looking at the tracking ids */ // int index = -1; // int i; // for(i = 0; i < 2; i++) { // if(fingerInfos[i].id == devEvt->detail) { // index = i; // break; // } // } // // /* No slot for this id found, look for free one */ // if(index == -1) { // for(i = 0; i < 2; i++) { // if(!fingerInfos[i].slotUsed) { // /* "Empty" slot, so we can add it. */ // index = i; // fingerInfos[i].id = devEvt->detail; // break; // } // } // } // // /* We have found a slot */ // if(index != -1) { // fingerInfos[index].slotUsed = (cookie->evtype != XI_TouchEnd ? 1 : 0); // // i = 0; // if((devEvt->valuators.mask[0] & 1) == 1) // { // fingerInfos[index].rawX = (int) devEvt->valuators.values[i++]; // } // if((devEvt->valuators.mask[0] & 2) == 2) // { // fingerInfos[index].rawY = (int) devEvt->valuators.values[i++]; // } // if((devEvt->valuators.mask[0] & 4) == 4) // { // fingerInfos[index].rawZ = (int) devEvt->valuators.values[i++]; // } // } // // processFingers(); //} XFreeEventData(display, &(ev.xcookie)); } else { if(ev.type == 101) { /* Why isn't this magic constant explained anywhere?? */ setScreenSize((XRRScreenChangeNotifyEvent *) &ev); } } }
void USBDevice_::attach() { DEBUG_OUT(F("USB - attach\r\n")); uint8_t oldSREG = SREG; // save int flag cli(); // NO recursion USB_INTCTRLA = 0; USB_INTCTRLB = 0; USB_INTFLAGSACLR = 0xff; // clear all int flags USB_INTFLAGSBCLR = 0x3; // clear all int flags _usbConfiguration = 0; // enable the USB clock using the 32mhz RC oscillator // assume either slow (6mhz) or fast (48mhz) // and of course the pre-scaler must be assigned accordingly // Also, assume that the oscillator is *SET UP* *PROPERLY* already, and // that all I have to do is configure the PLL to run at 48Mhz // setting up the PLL - source is RC32M 'divided by 4' then multiplied by 6 for 48Mhz USB_CTRLA = 0; // shut down USB USB_CTRLB = 0; // detach D- and D+ // CCP = CCP_IOREG_gc; // is this needed? see D manual, sect 3.14.1 (protected I/O) CLK_USBCTRL = 0; // shut off USB clock // CCP = CCP_IOREG_gc; // is this needed? see D manual, sect 3.14.1 (protected I/O) OSC_CTRL &= ~(OSC_PLLEN_bm); // disable PLL osc // TODO; use 32Mhz clock as 48Mhz, shifting system clock to the PLL at 32Mhz ? #ifdef USE_RC2M OSC_CTRL |= OSC_RC2MEN_bm; // enable 2M osc while(!(OSC_STATUS & OSC_RC2MRDY_bm)) // wait for 2M RC osc to be 'ready' { // TODO: timeout? } // now config PLL and USB clock stuff // 2Mhz as the source, multiplicatino factor of 24 = 48Mhz OSC_PLLCTRL = OSC_PLLSRC_RC2M_gc | 24; // 24 times the 2Mhz frequency // TODO: set up the calibration PLL for 2Mhz ? #else // USE_RC2M // 32Mhz (divided by 4, so it's 8Mhz) as the source // multiplication factor of 6 - result = 48Mhz OSC_PLLCTRL = OSC_PLLSRC_RC32M_gc | 6; // 6 times the 8Mhz frequency #endif // USE_RC2M // CCP = CCP_IOREG_gc; // is this needed? see D manual, sect 3.14.1 (protected I/O) OSC_CTRL |= OSC_PLLEN_bm; // re-enable PLL while(!(OSC_STATUS & OSC_PLLRDY_bm)) // wait for PLL to be 'ready' { // TODO: timeout? } // protected I/O reg // CCP = CCP_IOREG_gc; // is this needed? see D manual, sect 3.14.1 (protected I/O) #ifdef FAST_USB /* note this is 12Mbit operation, 'FULL' speed, not 'HIGH' speed 480Mbit */ CLK_USBCTRL = CLK_USBSRC_PLL_gc; // use PLL (divide by 1, no division) #else // SLOW CLK_USBCTRL = CLK_USBSRC_PLL_gc // use PLL | CLK_USBPSDIV_8_gc; // divide by 8 for 6mhz operation (12Mhz? see 7.3.6 which says 12Mhz or 48Mhz) #endif // FAST_USB or SLOW // CCP = CCP_IOREG_gc; // is this needed? see D manual, sect 3.14.1 (protected I/O) CLK_USBCTRL |= CLK_USBEN_bm; // enable bit // assign CAL register from product signatures (4.17.17,18) USB_CAL0 = readCalibrationData((uint8_t)(uint16_t)&PRODSIGNATURES_USBCAL0); // docs say 'CALL' USB_CAL1 = readCalibrationData((uint8_t)(uint16_t)&PRODSIGNATURES_USBCAL1); // docs say 'CALH' // DEBUG_OUT(F("CalData = ")); // DEBUG_OUT((uint32_t) USB_CAL0); // DEBUG_OUT(F(",")); // DEBUG_OUT((uint32_t) USB_CAL1); // DEBUG_OUT(F("\r\n")); // set the max # of endpoints, speed, and 'store frame number' flags USB_CTRLA = MAXEP /* max # of endpoints minus 1 */ #ifdef FAST_USB | USB_SPEED_bm /* all ahead 'FULL' - aka 'FULL' speed ahead! */ #endif // FAST_USB | USB_STFRNUM_bm // store the frame number // TODO: FIFO ? ; memset(&epData, 0, sizeof(epData)); // debug code - remove later //#ifdef A1U_SERIES // if((uint16_t)(uint8_t *)&(epData.endpoint[0]) & 15) // { // DEBUG_OUT(F("WRONG ALIGNMENT\r\n")); // return; // } //#endif // A1U_SERIES USB_EPPTR = (uint16_t)(uint8_t *)&(epData.endpoint[0]); // set 'EP Data' pointer to THIS address USB_ADDR = 0; // set USB address to 0 (default before 'SETUP') // LAST of all, enable interrupts USB_INTCTRLB = USB_TRNIE_bm | USB_SETUPIE_bm; // enable 'transaction complete' and 'setup' interrupts USB_INTCTRLA = USB_SOFIE_bm // enable the start of frame interrupt | USB_BUSEVIE_bm // 'bus event' interrupt - suspend, resume, reset // for the RESET event, RESETIF will be set (20.14.11 in AU manual) | USB_INTLVL0_bm | USB_INTLVL1_bm; // int level 3 // NOW enable the USB USB_CTRLA |= USB_ENABLE_bm; SREG = oldSREG; // restore int flags // __builtin_avr_delay_cycles(F_CPU / 2); // delay approximately 100 msec // attach the wiring for D- and D+ USB_CTRLB = USB_ATTACH_bm; // attach D- and D+ (also enables pullup resistors based on speed) // on the 128A1U, this is PD6 (D-) and PD7 (D+) [YMMV on the other processors] // this is partly why it's good to use PORTC for the primary SPI, TWI, etc. // since PORTD gets used for 'other things', but it's STILL ok to use PD2,3 as a serial port // and so the default pin config works pretty well. #if 0 /* old code for mega */ UHWCON = 0x01; // power internal reg USBCON = (1<<USBE)|(1<<FRZCLK); // clock frozen, usb enabled #if F_CPU == 16000000UL PLLCSR = 0x12; // Need 16 MHz xtal #elif F_CPU == 8000000UL PLLCSR = 0x02; // Need 8 MHz xtal #endif while (!(PLLCSR & (1<<PLOCK))) // wait for lock pll ; // Some tests on specific versions of macosx (10.7.3), reported some // strange behaviuors when the board is reset using the serial // port touch at 1200 bps. This delay fixes this behaviour. delay(1); USBCON = ((1<<USBE)|(1<<OTGPADE)); // start USB clock UDIEN = (1<<EORSTE)|(1<<SOFE); // Enable interrupts for EOR (End of Reset) and SOF (start of frame) UDCON = 0; // enable attach resistor #endif // 0 #ifdef TX_RX_LED_INIT TX_RX_LED_INIT; #endif // TX_RX_LED_INIT DEBUG_OUT(F("USB Attach (done)\r\n")); }