mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	Allow specifying the GreaseWeazle serial port directly (for devices which don't
have the GreaseWeazle VID/PID).
This commit is contained in:
		
							
								
								
									
										117
									
								
								lib/usb/usb.cc
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								lib/usb/usb.cc
									
									
									
									
									
								
							| @@ -13,72 +13,87 @@ | ||||
|  | ||||
| static USB* usb = NULL; | ||||
|  | ||||
| USB::~USB() | ||||
| {} | ||||
| USB::~USB() {} | ||||
|  | ||||
| static std::unique_ptr<CandidateDevice> selectDevice() | ||||
| { | ||||
| 	auto candidates = findUsbDevices({ FLUXENGINE_ID, GREASEWEAZLE_ID }); | ||||
| 	if (candidates.size() == 0) | ||||
| 		Error() << "no devices found (is one plugged in? Do you have the appropriate " | ||||
| 					"permissions?"; | ||||
|     auto candidates = findUsbDevices({FLUXENGINE_ID, GREASEWEAZLE_ID}); | ||||
|     if (candidates.size() == 0) | ||||
|         Error() << "no devices found (is one plugged in? Do you have the " | ||||
|                    "appropriate permissions?"; | ||||
|  | ||||
| 	if (config.usb().has_serial()) | ||||
| 	{ | ||||
| 		auto wantedSerial = config.usb().serial(); | ||||
| 		for (auto& c : candidates) | ||||
| 		{ | ||||
| 			if (c->serial == wantedSerial) | ||||
| 				return std::move(c); | ||||
| 		} | ||||
| 		Error() << "serial number not found (try without one to list or autodetect devices)"; | ||||
| 	} | ||||
|     if (config.usb().has_serial()) | ||||
|     { | ||||
|         auto wantedSerial = config.usb().serial(); | ||||
|         for (auto& c : candidates) | ||||
|         { | ||||
|             if (c->serial == wantedSerial) | ||||
|                 return std::move(c); | ||||
|         } | ||||
|         Error() << "serial number not found (try without one to list or " | ||||
|                    "autodetect devices)"; | ||||
|     } | ||||
|  | ||||
| 	if (candidates.size() == 1) | ||||
| 		return std::move(candidates[0]); | ||||
|     if (candidates.size() == 1) | ||||
|         return std::move(candidates[0]); | ||||
|  | ||||
| 	std::cerr << "More than one device detected; use --usb.serial=<serial> to select one:\n"; | ||||
| 	for (const auto& c : candidates) | ||||
| 	{ | ||||
| 		std::cerr << "    "; | ||||
| 		switch (c->id) | ||||
| 		{ | ||||
| 			case FLUXENGINE_ID: | ||||
| 				std::cerr << fmt::format("FluxEngine: {}\n", c->serial); | ||||
| 				break; | ||||
|     std::cerr << "More than one device detected; use --usb.serial=<serial> to " | ||||
|                  "select one:\n"; | ||||
|     for (const auto& c : candidates) | ||||
|     { | ||||
|         std::cerr << "    "; | ||||
|         switch (c->id) | ||||
|         { | ||||
|             case FLUXENGINE_ID: | ||||
|                 std::cerr << fmt::format("FluxEngine: {}\n", c->serial); | ||||
|                 break; | ||||
|  | ||||
| 			case GREASEWEAZLE_ID: | ||||
| 				std::cerr << fmt::format("GreaseWeazle: {} on {}\n", c->serial, c->serialPort); | ||||
| 				break; | ||||
| 		} | ||||
| 	} | ||||
| 	exit(1); | ||||
|             case GREASEWEAZLE_ID: | ||||
|                 std::cerr << fmt::format( | ||||
|                     "GreaseWeazle: {} on {}\n", c->serial, c->serialPort); | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
|     exit(1); | ||||
| } | ||||
|  | ||||
| USB* get_usb_impl() | ||||
| { | ||||
| 	auto candidate = selectDevice(); | ||||
| 	switch (candidate->id) | ||||
| 	{ | ||||
| 		case FLUXENGINE_ID: | ||||
| 			std::cerr << fmt::format("Using FluxEngine {}\n", candidate->serial); | ||||
| 			return createFluxengineUsb(candidate->device); | ||||
|     /* Special case for certain configurations. */ | ||||
|  | ||||
| 		case GREASEWEAZLE_ID: | ||||
| 			std::cerr << fmt::format("Using GreaseWeazle {} on {}\n", candidate->serial, candidate->serialPort); | ||||
| 			return createGreaseWeazleUsb(candidate->serialPort, config.usb().greaseweazle()); | ||||
|     if (config.usb().has_greaseweazle() && | ||||
|         config.usb().greaseweazle().has_port()) | ||||
|     { | ||||
|         const auto& conf = config.usb().greaseweazle(); | ||||
|         std::cerr << fmt::format( | ||||
|             "Using GreaseWeazle on serial port {}\n", conf.port()); | ||||
|         return createGreaseWeazleUsb(conf.port(), conf); | ||||
|     } | ||||
|  | ||||
| 		default: | ||||
| 			std::cerr << fmt::format("Using Unknown GW Compatible {} on {}\n", candidate->serial, candidate->serialPort); | ||||
| 			GreaseWeazleProto gwconfig = config.usb().greaseweazle(); | ||||
| 			return createGreaseWeazleUsb(candidate->serialPort, gwconfig ); | ||||
| 	} | ||||
|     /* Otherwise, select a device by USB ID. */ | ||||
|  | ||||
|     auto candidate = selectDevice(); | ||||
|     switch (candidate->id) | ||||
|     { | ||||
|         case FLUXENGINE_ID: | ||||
|             std::cerr << fmt::format( | ||||
|                 "Using FluxEngine {}\n", candidate->serial); | ||||
|             return createFluxengineUsb(candidate->device); | ||||
|  | ||||
|         case GREASEWEAZLE_ID: | ||||
|             std::cerr << fmt::format("Using GreaseWeazle {} on {}\n", | ||||
|                 candidate->serial, | ||||
|                 candidate->serialPort); | ||||
|             return createGreaseWeazleUsb( | ||||
|                 candidate->serialPort, config.usb().greaseweazle()); | ||||
|  | ||||
|         default: Error() << "internal"; | ||||
|     } | ||||
| } | ||||
|  | ||||
| USB& getUsb() | ||||
| { | ||||
| 	if (!usb) | ||||
| 		usb = get_usb_impl(); | ||||
| 	return *usb; | ||||
|     if (!usb) | ||||
|         usb = get_usb_impl(); | ||||
|     return *usb; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -9,7 +9,9 @@ message GreaseWeazleProto { | ||||
| 		SHUGART = 2; | ||||
| 	}; | ||||
|  | ||||
| 	optional BusType bus_type = 1 | ||||
| 	optional string port = 1 | ||||
| 		[(help) = "GreaseWeazle serial port to use"]; | ||||
| 	optional BusType bus_type = 2 | ||||
| 		[(help) = "which FDD bus type is in use", default = IBMPC]; | ||||
| } | ||||
|  | ||||
| @@ -19,5 +21,7 @@ message UsbProto { | ||||
| 			[(help) = "serial number of FluxEngine or GreaseWeazle device to use"]; | ||||
| 	} | ||||
|  | ||||
| 	optional GreaseWeazleProto greaseweazle = 2 [(help) = "GreaseWeazle-specific options"]; | ||||
| 	oneof config { | ||||
| 		GreaseWeazleProto greaseweazle = 2 [(help) = "GreaseWeazle-specific options"]; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -9,66 +9,42 @@ | ||||
|  | ||||
| static const std::string get_serial_number(const libusbp::device& device) | ||||
| { | ||||
| 	try | ||||
| 	{ | ||||
| 		return device.get_serial_number(); | ||||
| 	} | ||||
| 	catch (const libusbp::error& e) | ||||
| 	{ | ||||
| 		if (e.has_code(LIBUSBP_ERROR_NO_SERIAL_NUMBER)) | ||||
| 			return "n/a"; | ||||
| 		throw; | ||||
| 	} | ||||
|     try | ||||
|     { | ||||
|         return device.get_serial_number(); | ||||
|     } | ||||
|     catch (const libusbp::error& e) | ||||
|     { | ||||
|         if (e.has_code(LIBUSBP_ERROR_NO_SERIAL_NUMBER)) | ||||
|             return "n/a"; | ||||
|         throw; | ||||
|     } | ||||
| } | ||||
|  | ||||
| std::vector<std::unique_ptr<CandidateDevice>> findUsbDevices(const std::set<uint32_t>& ids) | ||||
| std::vector<std::unique_ptr<CandidateDevice>> findUsbDevices( | ||||
|     const std::set<uint32_t>& ids) | ||||
| { | ||||
| 	std::vector<std::unique_ptr<CandidateDevice>> candidates; | ||||
| 	for (const auto& it : libusbp::list_connected_devices()) | ||||
| 	{ | ||||
| 		auto candidate = std::make_unique<CandidateDevice>(); | ||||
| 		candidate->device = it; | ||||
|     std::vector<std::unique_ptr<CandidateDevice>> candidates; | ||||
|     for (const auto& it : libusbp::list_connected_devices()) | ||||
|     { | ||||
|         auto candidate = std::make_unique<CandidateDevice>(); | ||||
|         candidate->device = it; | ||||
|  | ||||
| 		uint32_t id = (it.get_vendor_id() << 16) | it.get_product_id(); | ||||
| 		if (ids.contains(id)) | ||||
| 		{ | ||||
| 			candidate->id = id; | ||||
| 			candidate->serial = get_serial_number(it); | ||||
|  | ||||
| 			if (id == GREASEWEAZLE_ID) | ||||
| 			{ | ||||
| 				libusbp::serial_port port(candidate->device); | ||||
| 				candidate->serialPort = port.get_name(); | ||||
| 			} | ||||
|  | ||||
| 			candidates.push_back(std::move(candidate)); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|     if (candidates.size() == 0) { | ||||
|       for (const auto& it : libusbp::list_connected_devices()) | ||||
|         uint32_t id = (it.get_vendor_id() << 16) | it.get_product_id(); | ||||
|         if (ids.contains(id)) | ||||
|         { | ||||
|           auto candidate = std::make_unique<CandidateDevice>(); | ||||
|           candidate->device = it; | ||||
|           uint32_t id = (it.get_vendor_id() << 16) | it.get_product_id(); | ||||
|           candidate->id = id; | ||||
|           candidate->serial = get_serial_number(it); | ||||
|           printf("USB ID %04x %04x: ", it.get_vendor_id(), it.get_product_id()); | ||||
|           try | ||||
|             candidate->id = id; | ||||
|             candidate->serial = get_serial_number(it); | ||||
|  | ||||
|             if (id == GREASEWEAZLE_ID) | ||||
|             { | ||||
|               libusbp::serial_port port(candidate->device, 0, true); | ||||
|               candidate->serialPort = port.get_name(); | ||||
|               printf("generic serialPort found\n"); | ||||
|               candidates.push_back(std::move(candidate)); | ||||
|             } | ||||
|           catch(const libusbp::error & error) | ||||
|             { | ||||
|               // not a serial port! | ||||
|               printf("not a port!\n"); | ||||
|               continue; | ||||
|                 libusbp::serial_port port(candidate->device); | ||||
|                 candidate->serialPort = port.get_name(); | ||||
|             } | ||||
|  | ||||
| 		} | ||||
| 	} | ||||
| 	return candidates; | ||||
|             candidates.push_back(std::move(candidate)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return candidates; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user