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);
		}
	}
}
Exemple #4
0
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"));
}