예제 #1
0
파일: main.c 프로젝트: Yaeger/usbmuxd
int main(int argc, char *argv[])
{
	int listenfd;
	int res = 0;
	int lfd;
	struct flock lock;
	char pids[10];

	parse_opts(argc, argv);

	argc -= optind;
	argv += optind;

	if (!foreground) {
		verbose += LL_WARNING;
		log_enable_syslog();
	} else {
		verbose += LL_NOTICE;
	}

	/* set log level to specified verbosity */
	log_level = verbose;

	usbmuxd_log(LL_NOTICE, "usbmuxd v%s starting up", PACKAGE_VERSION);
	should_exit = 0;
	should_discover = 0;

	set_signal_handlers();
	signal(SIGPIPE, SIG_IGN);

	res = lfd = open(lockfile, O_WRONLY|O_CREAT, 0644);
	if(res == -1) {
		usbmuxd_log(LL_FATAL, "Could not open lockfile");
		goto terminate;
	}
	lock.l_type = F_WRLCK;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0;
	lock.l_pid = 0;
	fcntl(lfd, F_GETLK, &lock);
	close(lfd);
	if (lock.l_type != F_UNLCK) {
		if (opt_exit) {
			if (lock.l_pid && !kill(lock.l_pid, 0)) {
				usbmuxd_log(LL_NOTICE, "Sending signal %d to instance with pid %d", exit_signal, lock.l_pid);
				res = 0;
				if (kill(lock.l_pid, exit_signal) < 0) {
					usbmuxd_log(LL_FATAL, "Could not deliver signal %d to pid %d", exit_signal, lock.l_pid);
					res = -1;
				}
				goto terminate;
			} else {
				usbmuxd_log(LL_ERROR, "Could not determine pid of the other running instance!");
				res = -1;
				goto terminate;
			}
		} else {
			if (!opt_disable_hotplug) {
				usbmuxd_log(LL_ERROR, "Another instance is already running (pid %d). exiting.", lock.l_pid);
				res = -1;
			} else {
				usbmuxd_log(LL_NOTICE, "Another instance is already running (pid %d). Telling it to check for devices.", lock.l_pid);
				if (lock.l_pid && !kill(lock.l_pid, 0)) {
					usbmuxd_log(LL_NOTICE, "Sending signal SIGUSR2 to instance with pid %d", lock.l_pid);
					res = 0;
					if (kill(lock.l_pid, SIGUSR2) < 0) {
						usbmuxd_log(LL_FATAL, "Could not deliver SIGUSR2 to pid %d", lock.l_pid);
						res = -1;
					}
				} else {
					usbmuxd_log(LL_ERROR, "Could not determine pid of the other running instance!");
					res = -1;
				}
			}
			goto terminate;
		}
	}
	unlink(lockfile);

	if (opt_exit) {
		usbmuxd_log(LL_NOTICE, "No running instance found, none killed. Exiting.");
		goto terminate;
	}

	if (!foreground) {
		if ((res = daemonize()) < 0) {
			fprintf(stderr, "usbmuxd: FATAL: Could not daemonize!\n");
			usbmuxd_log(LL_FATAL, "Could not daemonize!");
			goto terminate;
		}
	}

	// now open the lockfile and place the lock
	res = lfd = open(lockfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
	if(res < 0) {
		usbmuxd_log(LL_FATAL, "Could not open lockfile");
		goto terminate;
	}
	lock.l_type = F_WRLCK;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0;
	if ((res = fcntl(lfd, F_SETLK, &lock)) < 0) {
		usbmuxd_log(LL_FATAL, "Lockfile locking failed!");
		goto terminate;
	}
	sprintf(pids, "%d", getpid());
	if ((size_t)(res = write(lfd, pids, strlen(pids))) != strlen(pids)) {
		usbmuxd_log(LL_FATAL, "Could not write pidfile!");
		if(res >= 0)
			res = -2;
		goto terminate;
	}

	// set number of file descriptors to higher value
	struct rlimit rlim;
	getrlimit(RLIMIT_NOFILE, &rlim);
	rlim.rlim_max = 65536;
	setrlimit(RLIMIT_NOFILE, (const struct rlimit*)&rlim);

	usbmuxd_log(LL_INFO, "Creating socket");
	res = listenfd = create_socket();
	if(listenfd < 0)
		goto terminate;

#ifdef HAVE_LIBIMOBILEDEVICE
	const char* userprefdir = config_get_config_dir();
	struct stat fst;
	memset(&fst, '\0', sizeof(struct stat));
	if (stat(userprefdir, &fst) < 0) {
		if (mkdir(userprefdir, 0775) < 0) {
			usbmuxd_log(LL_FATAL, "Failed to create required directory '%s': %s", userprefdir, strerror(errno));
			res = -1;
			goto terminate;
		}
		if (stat(userprefdir, &fst) < 0) {
			usbmuxd_log(LL_FATAL, "stat() failed after creating directory '%s': %s", userprefdir, strerror(errno));
			res = -1;
			goto terminate;
		}
	}

	// make sure permission bits are set correctly
	if (fst.st_mode != 02775) {
		if (chmod(userprefdir, 02775) < 0) {
			usbmuxd_log(LL_WARNING, "chmod(%s, 02775) failed: %s", userprefdir, strerror(errno));
		}
	}
#endif

	// drop elevated privileges
	if (drop_privileges && (getuid() == 0 || geteuid() == 0)) {
		struct passwd *pw;
		if (!drop_user) {
			usbmuxd_log(LL_FATAL, "No user to drop privileges to?");
			res = -1;
			goto terminate;
		}
		pw = getpwnam(drop_user);
		if (!pw) {
			usbmuxd_log(LL_FATAL, "Dropping privileges failed, check if user '%s' exists!", drop_user);
			res = -1;
			goto terminate;
		}
		if (pw->pw_uid == 0) {
			usbmuxd_log(LL_INFO, "Not dropping privileges to root");
		} else {
#ifdef HAVE_LIBIMOBILEDEVICE
			/* make sure the non-privileged user has proper access to the config directory */
			if ((fst.st_uid != pw->pw_uid) || (fst.st_gid != pw->pw_gid)) {
				if (chown(userprefdir, pw->pw_uid, pw->pw_gid) < 0) {
					usbmuxd_log(LL_WARNING, "chown(%s, %d, %d) failed: %s", userprefdir, pw->pw_uid, pw->pw_gid, strerror(errno));
				}
			}
#endif

			if ((res = initgroups(drop_user, pw->pw_gid)) < 0) {
				usbmuxd_log(LL_FATAL, "Failed to drop privileges (cannot set supplementary groups)");
				goto terminate;
			}
			if ((res = setgid(pw->pw_gid)) < 0) {
				usbmuxd_log(LL_FATAL, "Failed to drop privileges (cannot set group ID to %d)", pw->pw_gid);
				goto terminate;
			}
			if ((res = setuid(pw->pw_uid)) < 0) {
				usbmuxd_log(LL_FATAL, "Failed to drop privileges (cannot set user ID to %d)", pw->pw_uid);
				goto terminate;
			}

			// security check
			if (setuid(0) != -1) {
				usbmuxd_log(LL_FATAL, "Failed to drop privileges properly!");
				res = -1;
				goto terminate;
			}
			if (getuid() != pw->pw_uid || getgid() != pw->pw_gid) {
				usbmuxd_log(LL_FATAL, "Failed to drop privileges properly!");
				res = -1;
				goto terminate;
			}
			usbmuxd_log(LL_NOTICE, "Successfully dropped privileges to '%s'", drop_user);
		}
	}

	client_init();
	device_init();
	usbmuxd_log(LL_INFO, "Initializing USB");
	if((res = usb_init()) < 0)
		goto terminate;

	usbmuxd_log(LL_INFO, "%d device%s detected", res, (res==1)?"":"s");

	usbmuxd_log(LL_NOTICE, "Initialization complete");

	if (report_to_parent)
		if((res = notify_parent(0)) < 0)
			goto terminate;

	if(opt_disable_hotplug) {
		usbmuxd_log(LL_NOTICE, "Automatic device discovery on hotplug disabled.");
		usb_autodiscover(0); // discovery to be triggered by new instance
	}
	if (opt_enable_exit) {
		usbmuxd_log(LL_NOTICE, "Enabled exit on SIGUSR1 if no devices are attached. Start a new instance with \"--exit\" to trigger.");
	}

	res = main_loop(listenfd);
	if(res < 0)
		usbmuxd_log(LL_FATAL, "main_loop failed");

	usbmuxd_log(LL_NOTICE, "usbmuxd shutting down");
	device_kill_connections();
	usb_shutdown();
	device_shutdown();
	client_shutdown();
	usbmuxd_log(LL_NOTICE, "Shutdown complete");

terminate:
	log_disable_syslog();

	if (res < 0)
		res = -res;
	else
		res = 0;
	if (report_to_parent)
		notify_parent(res);

	return res;
}
예제 #2
0
int main(int argc, char *argv[])
{
	int sd = -1;
	char *conf_file = NULL;
	struct mosquitto *mosq;
	struct module *md;
	struct device *dev;
	int rc;
	int i;
	
	if (!quiet) printf("Version: %s\n", version);

    signal(SIGINT, handle_signal);
    signal(SIGTERM, handle_signal);
	signal(SIGUSR1, handle_signal);
	signal(SIGUSR2, handle_signal);
	signal(SIGALRM, each_sec);
	
	for (i=1; i<argc; i++) {
		if(!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config")){
			if(i==argc-1){
                fprintf(stderr, "Error: -c argument given but no file specified.\n\n");
				print_usage(argv[0]);
                return 1;
            }else{
				conf_file = argv[i+1];
			}
			i++;
		}else if(!strcmp(argv[i], "--quiet")){
				quiet = true;
		}else{
				fprintf(stderr, "Error: Unknown option '%s'.\n",argv[i]);
				print_usage(argv[0]);
				return 1;
		}
	}
	
	if(!conf_file) {
		fprintf(stderr, "Error: No config file given.\n");
		return 1;
	}

	memset(&config, 0, sizeof(struct bridge_config));
	if(config_parse(conf_file, &config)) return 1;
	
	if (quiet) config.debug = 0;
	if (config.debug != 0) printf("Debug: %d\n", config.debug);

	if (!device_isValid_id(config.id)) {
		fprintf(stderr, "Invalid id.\n");
		return -1;
	}
	if (device_init(&bridge, config.id) == -1)
		return 1;

	mosquitto_lib_init();
	mosq = mosquitto_new(config.id, true, NULL);
	if(!mosq){
		fprintf(stderr, "Error creating mqtt instance.\n");
		switch(errno){
			case ENOMEM:
				fprintf(stderr, " out of memory.\n");
				break;
			case EINVAL:
				fprintf(stderr, " invalid id.\n");
				break;
		}
		return 1;
	}
	snprintf(gbuf, GBUF_SIZE, "%d", PROTO_ST_TIMEOUT);
	mosquitto_will_set(mosq, bridge.status_topic, strlen(gbuf), gbuf, config.mqtt_qos, MQTT_RETAIN);
	mosquitto_connect_callback_set(mosq, on_mqtt_connect);
	mosquitto_disconnect_callback_set(mosq, on_mqtt_disconnect);
	mosquitto_message_callback_set(mosq, on_mqtt_message);
	mosquitto_user_data_set(mosq, &sd);

	if (config.debug > 1) printf("Subscribe topic: %s\n", bridge.config_topic);

	rc = device_add_module(&bridge, MODULE_MQTT_ID, bridge.id);				//TODO: autogen id?
	if (rc) {
		fprintf(stderr, "Failed to add mqtt module.\n");
		return 1;
	}

	if (config.scripts_folder) {
		if (access(config.scripts_folder, R_OK )) {
			fprintf(stderr, "Couldn't open scripts folder: %s\n", config.scripts_folder);
			return 1;
		}
		rc = device_add_module(&bridge, MODULE_SCRIPT_ID, bridge.id);		//TODO: autogen id?
		if (rc) {
			fprintf(stderr, "Failed to add script module.\n");
			return 1;
		}
	}
	if (config.interface) {
		//TODO: check if interface exists
		if (access("/proc/net/dev", R_OK )) {
			fprintf(stderr, "Couldn't open /proc/net/dev\n");
			return 1;
		}
		rc = device_add_module(&bridge, MODULE_BANDWIDTH_ID, bridge.id);		//TODO: autogen id?
		if (rc) {
			fprintf(stderr, "Failed to add bandwidth module.\n");
			return 1;
		}
		bandwidth = true;
	}
	if (config.serial.port) {
		sd = serialport_init(config.serial.port, config.serial.baudrate);
		if( sd == -1 ) {
			fprintf(stderr, "Couldn't open serial port.\n");
			return 1;
		} else {
			rc = device_add_module(&bridge, MODULE_SERIAL_ID, bridge.id);		//TODO: autogen id?
			if (rc) {
				fprintf(stderr, "Failed to add serial module.\n");
				return 1;
			}
			serialport_flush(sd);
			bridge.serial_ready = true;

			if (config.debug) printf("Serial ready.\n");
		}
	}

	rc = device_add_module(&bridge, MODULE_SIGUSR1_ID, bridge.id);			//TODO: autogen id?
	if (rc) {
		fprintf(stderr, "Failed to add sigusr1 module.\n");
		return 1;
	}

	rc = device_add_module(&bridge, MODULE_SIGUSR2_ID, bridge.id);			//TODO: autogen id?
	if (rc) {
		fprintf(stderr, "Failed to add sigusr2 module.\n");
		return 1;
	}

	device_print_modules(&bridge);

	rc = mosquitto_connect(mosq, config.mqtt_host, config.mqtt_port, 60);
	if (rc) {
		fprintf(stderr, "Wrong MQTT parameters. Check your config.\n");
		return -1;
	}

	alarm(1);

	while (run) {
		if (bridge.serial_ready) {
			rc = serial_in(sd, mosq, MODULE_SERIAL_ID);
			if (rc == -1) {
				serial_hang(mosq);
			} else if (rc > 0) {
				bridge.serial_alive = ALIVE_CNT;
			}
		}

		if (user_signal) {
			if (config.debug > 1) printf("Signal - SIGUSR: %d\n", user_signal);
			signal_usr(sd, mosq);
		}

		rc = mosquitto_loop(mosq, -1, 1);
		if (run && rc) {
			if (config.debug > 2) printf("MQTT loop: %s\n", mosquitto_strerror(rc));
			usleep(100000);	// wait 100 msec
			mosquitto_reconnect(mosq);
		}

		if (every30s) {
			every30s = false;

			bridge.controller = false;
			for (i = 0; i < bridge.devices_len; i++) {
				dev = &bridge.devices[i];
				if (dev->alive) {
					dev->alive--;
					if (!dev->alive) {
						snprintf(gbuf, GBUF_SIZE, "%d,%s", PROTO_ST_TIMEOUT, dev->id);
						mqtt_publish(mosq, bridge.status_topic, gbuf);

						if (dev->md_deps->type == MODULE_MQTT && dev->type == DEVICE_TYPE_NODE) {
							snprintf(gbuf, GBUF_SIZE, "status/%s", dev->id);
							rc = mosquitto_unsubscribe(mosq, NULL, gbuf);
							if (rc)
								fprintf(stderr, "Error: MQTT unsubscribe returned: %s\n", mosquitto_strerror(rc));
						}

						if (config.debug) printf("Device timeout - id: %s\n", dev->id);
					} else {
						if (dev->type == DEVICE_TYPE_CONTROLLER)
							bridge.controller = true;
					}
				}
			}

			if (!bridge.controller)
				bridge.modules_update = false;

			if (connected) {
				snprintf(gbuf, GBUF_SIZE, "%d,%d", PROTO_ST_ALIVE, bridge.modules_len);
				mqtt_publish(mosq, bridge.status_topic, gbuf);

				if (bridge.modules_update) {
					snprintf(gbuf, GBUF_SIZE, "%d", PROTO_ST_MODULES_UP);
					if (mqtt_publish(mosq, bridge.status_topic, gbuf))
						bridge.modules_update = false;
				}

				if (bandwidth) {
					md = device_get_module(&bridge, MODULE_BANDWIDTH_ID);
					if (md) {
						if (mqtt_publish_bandwidth(mosq, md->topic) == -1)
							break;
					}
				}
			} else {
				if (config.debug != 0) printf("MQTT Offline.\n");
			}

			if (bridge.serial_alive) {
				bridge.serial_alive--;
				if (!bridge.serial_alive) {
					if (config.debug > 1) printf("Serial timeout.\n");
					serial_hang(mosq);
				}
			} else {
				if (config.serial.port && !bridge.serial_ready) {
					if (config.debug > 1) printf("Trying to reconnect serial port.\n");
					serialport_close(sd);
					sd = serialport_init(config.serial.port, config.serial.baudrate);
					if( sd == -1 )
						fprintf(stderr, "Couldn't open serial port.\n");
					else {
						serialport_flush(sd);
						bridge.serial_ready = true;
						if (config.debug) printf("Serial reopened.\n");
					}
				}
			}
		}
		usleep(20);
	}

	if (bridge.serial_ready) {
		serialport_close(sd);
	}

	mosquitto_destroy(mosq);

	mosquitto_lib_cleanup();
	config_cleanup(&config);

	printf("Exiting..\n\n");

	return 0;
}
예제 #3
0
static int pcan_usb_plugin(struct usb_interface *interface,
                           const struct usb_device_id *id)
{
	int err;
	int i, dev_ctrl_count, sizeof_if;
	struct usb_host_interface *iface_desc;
	struct usb_endpoint_descriptor *endpoint;
	struct usb_device *usb_dev = interface_to_usbdev(interface);
	struct pcan_usb_interface *usb_if;
	int (*device_init)(struct pcan_usb_interface *);

	DPRINTK(KERN_DEBUG "%s: %s(0x%04x, 0x%04x, 0x%04x)\n",
	        DEVICE_NAME, __func__,
	        usb_dev->descriptor.idVendor, usb_dev->descriptor.idProduct,
	        usb_dev->descriptor.bcdDevice);

	/* check endpoint addresses (numbers) and associated max data length */
	/* (only from setting 0) */
	/* Since USB-PRO defines also a LIN interface, should reject it when */
	/* adapter plugged: make use of endpoint addresses (no other way...) */
	iface_desc = &interface->altsetting[0];

	DPRINTK(KERN_DEBUG "%s: %s(): bNumEndpoints=%d\n",
	        DEVICE_NAME, __func__, iface_desc->desc.bNumEndpoints);

	for (i=0; i < iface_desc->desc.bNumEndpoints; i++) {
		struct usb_endpoint_descriptor *endpoint =
					&iface_desc->endpoint[i].desc;

		/*
		 * Below is the list of valid ep addreses. Any other ep address
		 * is considered as not-CAN interface address => no dev createdi
		 */
		switch (endpoint->bEndpointAddress) {
		case 0x01:
		case 0x81:
		case 0x02:
		case 0x82:
		case 0x03:
		case 0x83:
			break;
		default:
#ifdef DEBUG
			printk(KERN_INFO
			       "%s: %s(): EP address %02x not in CAN range.\n",
			       DEVICE_NAME, __func__,
			       endpoint->bEndpointAddress);
			printk(KERN_INFO
			       "%s: %s(): ignoring the whole USB interface\n",
			       DEVICE_NAME, __func__);
#endif
			return -ENODEV;
		}
	}

	/*
	 * Does not work with PCAN-USB FD (and 3.14-rc2 ...)
	 *
	 * TODO: check if we could remove this call, because according to
	 * drivers/usb/core/message.c:
	 *
	 * "Instead, the driver [..] may use usb_set_interface() on the
	 * interface it claims"
	 */
	if (usb_dev->descriptor.idProduct != PCAN_USBFD_PRODUCT_ID) {

		/* take the 1st configuration (it's default) */
		if ((err = usb_reset_configuration(usb_dev)) < 0) {
			printk(KERN_ERR
			       "%s: usb_reset_configuration() failed!\n",
			       DEVICE_NAME);
			return err;
		}
	}

	// only 1 interface is supported
	// Note: HW_USB_PRO: interface#0 for CAN, #1 for LIN
	if ((err = usb_set_interface(usb_dev, 0, 0)) < 0) {
		printk(KERN_ERR "%s: usb_set_interface() failed!\n",
		       DEVICE_NAME);
		return err;
	}

	/*
	 * Now, according to device id, create as many device as CAN
	 * controllers
	 */
	switch (usb_dev->descriptor.idProduct) {

#ifdef HW_USB_FD
	case PCAN_USBFD_PRODUCT_ID:
		dev_ctrl_count = 1;
		device_init = pcan_usbfd_init;
		break;
#endif
#ifdef HW_USB_PRO_FD
	case PCAN_USBPROFD_PRODUCT_ID:
		dev_ctrl_count = 2;
		device_init = pcan_usbfd_init;
		break;
#endif
#ifdef HW_USB_PRO
	case PCAN_USBPRO_PRODUCT_ID:
		dev_ctrl_count = 2;
		device_init = pcan_usbpro_init;
		break;
#endif
	case PCAN_USB_PRODUCT_ID:
	default:
		dev_ctrl_count = 1;
		device_init = pcan_usb_init;
		break;
	}

	printk(KERN_INFO "%s: new ", DEVICE_NAME);
	if (usb_dev->speed == USB_SPEED_HIGH)
		printk("high speed ");
	printk("usb adapter with %u CAN controller(s) detected\n",
		dev_ctrl_count);

	/* create our interface object for the USB device */
	sizeof_if = sizeof(struct pcan_usb_interface) + \
				sizeof(struct pcandev) * (dev_ctrl_count-1);

	usb_if = (struct pcan_usb_interface *)kmalloc(sizeof_if, GFP_KERNEL);
	if (!usb_if) {
		printk(KERN_ERR
		       "%s: kmalloc(%d) failed!\n", DEVICE_NAME, sizeof_if);
		return err;
	}

	memset(usb_if, '\0', sizeof_if);

	// store pointer to kernel supplied usb_dev
	usb_if->usb_dev = usb_dev;
	usb_if->usb_intf = interface;
	usb_if->dev_ctrl_count = dev_ctrl_count;

	// preset finish flags
	atomic_set(&usb_if->cmd_sync_complete, 0);
	atomic_set(&usb_if->cmd_async_complete, 1);

	// preset active URB counter
	atomic_set(&usb_if->active_urbs, 0);

	init_waitqueue_head(&usb_if->usb_wait_queue);

	/* get endpoint addresses (numbers) and associated max data length */
	/* (only from setting 0) */
#ifdef HW_USB_PRO
/*
 *      Function   Interface   Endpoints            DeviceId
 *      ---------  ---------   -----------------------------------------
 *      Control                0
 *      CAN        0                                "CAN-Device",
 *                                                  USB\VID_0c72&PID_000d&MI_00
 *                             1=Command,           bidi for both CAN_Ctrller
 *                             2=CAN-Controller 0,  rcv (IN) both CAN-Ctrller,
 *                                                  transmit (OUT) CAN-Ctrl#0,
 *                             3=CAN-Controller 1   transmit (OUT) CAN-Ctrl#1
 *      LIN        1                                "LIN-Device",
 *                                                  USB\VID_0c72&PID_000d&MI_01
 *                             4=Command,
 *                             5=Controller 0,
 *                             6=Controller 1
 */
#endif
	for (i=0; i < iface_desc->desc.bNumEndpoints; i++) {
		PCAN_ENDPOINT *pipe_addr = NULL;

		endpoint = &iface_desc->endpoint[i].desc;

		DPRINTK(KERN_DEBUG "%s: %s(): EP[%d]={addr=%d max=%d}\n",
		        DEVICE_NAME, __func__, i, endpoint->bEndpointAddress,
		        endpoint->wMaxPacketSize);

		switch (endpoint->bEndpointAddress) {
		case 0x01:
			pipe_addr = &usb_if->pipe_cmd_out;
			break;

		case 0x81:
			pipe_addr = &usb_if->pipe_cmd_in;
			break;

		case 0x02:
			switch (usb_dev->descriptor.idProduct) {
#ifdef HW_USB_FD
			case PCAN_USBFD_PRODUCT_ID:
#endif
#ifdef HW_USB_PRO_FD
			case PCAN_USBPROFD_PRODUCT_ID:
#endif
#ifdef HW_USB_PRO
			case PCAN_USBPRO_PRODUCT_ID:
#endif
			case PCAN_USB_PRODUCT_ID:
			default:
				pipe_addr = &usb_if->dev[0].port.usb.pipe_write;
				break;
			}
			break;

		case 0x82:
			pipe_addr = &usb_if->pipe_read;
			break;

		case 0x03:
			switch (usb_dev->descriptor.idProduct) {
#ifdef HW_USB_FD
			case PCAN_USBFD_PRODUCT_ID:
#endif
#ifdef HW_USB_PRO_FD
			case PCAN_USBPROFD_PRODUCT_ID:
#endif
#ifdef HW_USB_PRO
			case PCAN_USBPRO_PRODUCT_ID:
#endif
				pipe_addr = &usb_if->dev[1].port.usb.pipe_write;
				break;
			}

		case 0x83:
			/* Unused pipe for PCAN-USB-PRO */
			/* But seems that need to be reset too... */
			/* TBD */
			break;

		default:
			continue;
		}

		if (pipe_addr) {
			pipe_addr->ucNumber = endpoint->bEndpointAddress;
			pipe_addr->wDataSz  = le16_to_cpu(endpoint->wMaxPacketSize);
		}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
		usb_reset_endpoint(usb_dev, endpoint->bEndpointAddress);
#endif
	}

	/* ucRevision needs to be defined before allocating resources (PCAN-USB) */
#if defined(__LITTLE_ENDIAN)
	usb_if->ucHardcodedDevNr = (uint8_t)(usb_if->usb_dev->descriptor.bcdDevice & 0xff);
	usb_if->ucRevision = (uint8_t)(usb_if->usb_dev->descriptor.bcdDevice >> 8);
#elif defined(__BIG_ENDIAN)
	usb_if->ucHardcodedDevNr = (uint8_t)(usb_if->usb_dev->descriptor.bcdDevice >> 8);
	usb_if->ucRevision = (uint8_t)(usb_if->usb_dev->descriptor.bcdDevice & 0xff);
#else
#error "Please fix the endianness defines in <asm/byteorder.h>"
#endif

	DPRINTK(KERN_DEBUG "%s(): ucHardcodedDevNr=0x%02x ucRevision=0x%02X\n", __func__, usb_if->ucHardcodedDevNr, usb_if->ucRevision);

	if ((err = pcan_usb_allocate_resources(usb_if)))
		goto reject;

	usb_set_intfdata(interface, usb_if);

	/* call initialisation callback for entire device */
	device_init(usb_if);

	/* install the reception part for the interface */
	if (!atomic_read(&usb_if->read_data.use_count)) {
		FILL_BULK_URB(&usb_if->read_data, usb_if->usb_dev,
		              usb_rcvbulkpipe(usb_if->usb_dev,
		                              usb_if->pipe_read.ucNumber),
		              usb_if->read_buffer_addr[0],
			      usb_if->read_buffer_size,
		              pcan_usb_read_notify, usb_if);

		// submit urb
		if ((err = __usb_submit_urb(&usb_if->read_data))) {
			printk(KERN_ERR "%s: %s() can't submit! (%d)\n",
		          DEVICE_NAME, __func__, err);
			goto reject;
		}

		atomic_inc(&usb_if->active_urbs);
	}

	/* next, initialize each controller */
	for (i=0; i < usb_if->dev_ctrl_count; i++) {
		err = pcan_usb_create_dev(usb_if, i);
		if (err) {
			for (; i > 0; i--) {
				// TBD pcan_usb_delete_dev();
			}
			break;
		}
	}

reject:
	return err;
}
예제 #4
0
 void init(const char* cfg) {
   device_init(cfg);
 }