2 * This file is part of the DSLogic project.
6 #include "hardware/DSLogic/dslogic.h"
20 #include <ddk/usbiodef.h>
34 static void dev_list_add(struct libusbhp_t *h, const char *path,
35 unsigned short vid, unsigned short pid)
37 struct dev_list_t *dev =
38 (struct dev_list_t*)malloc(sizeof(struct dev_list_t));
39 dev->path = strdup(path);
44 struct dev_list_t *p = h->devlist;
57 static int dev_list_remove(struct libusbhp_t *h, const char *path)
59 struct dev_list_t *p = h->devlist;
62 if(!strcmp(p->path, path)) {
70 if(!strcmp(p->next->path, path)) {
71 struct dev_list_t *pp = p->next;
85 static int dev_list_find(struct libusbhp_t *h, const char *path,
86 unsigned short *vid, unsigned short *pid)
88 struct dev_list_t *p = h->devlist;
90 if(!strcmp(p->path, path)) {
104 SR_PRIV LRESULT CALLBACK WinProcCallback(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
106 struct libusbhp_t *h = (struct libusbhp_t*)GetWindowLong(hwnd, GWL_USERDATA);
109 case WM_DEVICECHANGE:
111 PDEV_BROADCAST_HDR phdr = (PDEV_BROADCAST_HDR)lp;
113 if(!phdr || phdr->dbch_devicetype != DBT_DEVTYP_DEVICEINTERFACE) break;
115 PDEV_BROADCAST_DEVICEINTERFACE devif =
116 (PDEV_BROADCAST_DEVICEINTERFACE)lp;
118 HDEVINFO devinfolist = SetupDiCreateDeviceInfoList(NULL, NULL);
120 SP_DEVICE_INTERFACE_DATA devifdata;
121 memset(&devifdata, 0, sizeof(devifdata));
122 devifdata.cbSize = sizeof(devifdata);
123 BOOL b = SetupDiOpenDeviceInterface(devinfolist, devif->dbcc_name, 0,
127 SP_DEVICE_INTERFACE_DETAIL_DATA devdetaildata;
128 memset(&devdetaildata, 0, sizeof(devdetaildata));
129 devdetaildata.cbSize = sizeof(devdetaildata);
131 SP_DEVINFO_DATA devinfodata;
132 memset(&devinfodata, 0, sizeof(devinfodata));
133 devinfodata.cbSize = sizeof(devinfodata);
134 b = SetupDiGetDeviceInterfaceDetail(devinfolist, &devifdata,
136 sizeof(devdetaildata),
137 &required, &devinfodata);
139 TCHAR deviceidw[1024];
140 b = SetupDiGetDeviceInstanceIdW(devinfolist, &devinfodata, deviceidw,
141 sizeof(deviceidw), NULL);
145 //wcstombs_s(&sz, deviceid, deviceidw, sizeof(deviceid) - 1);
146 wcstombs(deviceid, deviceidw, sizeof(deviceid) - 1);
148 char *vid = strstr(deviceid, "VID_");
149 if(vid != NULL) vid += 4;
151 char *pid = strstr(deviceid, "PID_");
152 if(pid != NULL) pid += 4;
154 struct libusbhp_device_t *device = NULL;
158 (struct libusbhp_device_t*)malloc(sizeof(struct libusbhp_device_t));
163 device->idProduct = (unsigned short)strtol(pid, NULL, 16);
168 device->idVendor = (unsigned short)strtol(vid, NULL, 16);
171 if ((device->idVendor == supported_fx2[0].vid) &&
172 (device->idProduct == supported_fx2[0].pid)) {
174 case DBT_DEVICEARRIVAL:
175 if(h->attach) h->attach(device, h->user_data);
177 case DBT_DEVICEREMOVECOMPLETE:
178 if(h->detach) h->detach(device, h->user_data);
180 case DBT_DEVNODES_CHANGED:
186 if(device) free(device);
193 return DefWindowProc(hwnd, msg, wp, lp);
197 SR_API int libusbhp_init(struct libusbhp_t **handle)
199 struct libusbhp_t *h = (struct libusbhp_t *)malloc(sizeof(struct libusbhp_t));
208 // create the udev object
209 h->hotplug = udev_new();
212 printf("Cannot create udev object\n");
217 // create the udev monitor
218 h->hotplug_monitor = udev_monitor_new_from_netlink(h->hotplug, "udev");
220 // start receiving hotplug events
221 udev_monitor_filter_add_match_subsystem_devtype(h->hotplug_monitor,
222 "usb", "usb_device");
223 udev_monitor_enable_receiving(h->hotplug_monitor);
225 struct udev_enumerate *de = udev_enumerate_new (h->hotplug);
226 udev_enumerate_add_match_subsystem(de, "usb");
227 udev_enumerate_scan_devices(de);
229 struct udev_list_entry *lst = udev_enumerate_get_list_entry(de);
231 struct udev_device *dev =
232 udev_device_new_from_syspath(h->hotplug,
233 udev_list_entry_get_name(lst));
235 if(udev_device_get_devnode(dev)) {
236 unsigned short idVendor =
237 strtol(udev_device_get_sysattr_value(dev, "idVendor"), NULL, 16);
238 unsigned short idProduct =
239 strtol(udev_device_get_sysattr_value(dev, "idProduct"), NULL, 16);
241 dev_list_add(h, udev_device_get_devnode(dev), idVendor, idProduct);
244 udev_device_unref(dev);
246 lst = udev_list_entry_get_next(lst);
249 udev_enumerate_unref(de);
254 memset(&h->wcex, 0, sizeof(h->wcex));
255 h->wcex.cbSize = sizeof(WNDCLASSEX);
256 h->wcex.lpfnWndProc = WinProcCallback;
257 h->wcex.hInstance = GetModuleHandle(NULL);
258 h->wcex.lpszClassName = TEXT("UsbHotplugClass");
259 h->wcex.cbWndExtra = sizeof(struct libusbhp_t*); // Size of data.
261 RegisterClassEx(&h->wcex);
264 CreateWindowEx(0, h->wcex.lpszClassName, TEXT("UsbHotplug"), 0, 0, 0, 0,
265 0, 0, NULL, GetModuleHandle(NULL), NULL);
267 SetWindowLong(h->hwnd, GWL_USERDATA, (LONG)h);
270 DEV_BROADCAST_DEVICEINTERFACE *filter =
271 (DEV_BROADCAST_DEVICEINTERFACE*)malloc(sizeof(DEV_BROADCAST_DEVICEINTERFACE));
273 memset(filter, 0, sizeof(DEV_BROADCAST_DEVICEINTERFACE));
274 filter->dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
275 filter->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
276 filter->dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
279 RegisterDeviceNotification(h->hwnd, filter, DEVICE_NOTIFY_WINDOW_HANDLE);
281 if(h->hDeviceNotify == 0) {
282 //printf("RegisterDeviceNotification error\n");
292 SR_API void libusbhp_exit(struct libusbhp_t *h)
295 // destroy the udev monitor
296 udev_monitor_unref(h->hotplug_monitor);
298 // destroy the udev object
299 udev_unref(h->hotplug);
303 UnregisterDeviceNotification(h->hDeviceNotify);
304 DestroyWindow(h->hwnd);
305 UnregisterClass(h->wcex.lpszClassName, h->wcex.hInstance);
311 SR_API int libusbhp_handle_events_timeout(struct libusbhp_t *h, struct timeval *tv)
313 int ms = tv->tv_sec * 1000 + tv->tv_usec / 1000;
316 // create the poll item
317 struct pollfd items[1];
318 items[0].fd = udev_monitor_get_fd(h->hotplug_monitor);
319 items[0].events = POLLIN;
320 items[0].revents = 0;
322 // while there are hotplug events to process
323 while(poll(items, 1, ms) > 0) {
324 // receive the relevant device
325 struct udev_device* dev = udev_monitor_receive_device(h->hotplug_monitor);
327 // error receiving device, skip it
331 if(!strcmp(udev_device_get_action(dev), "add")) {
332 struct libusbhp_device_t device;
335 strtol(udev_device_get_sysattr_value(dev, "idVendor"), NULL, 16);
337 strtol(udev_device_get_sysattr_value(dev, "idProduct"), NULL, 16);
339 dev_list_add(h, udev_device_get_devnode(dev),
340 device.idVendor, device.idProduct);
342 if(h->attach) h->attach(&device, h->user_data);
345 if(!strcmp(udev_device_get_action(dev), "remove")) {
346 struct libusbhp_device_t device;
348 int res = dev_list_find(h, udev_device_get_devnode(dev),
349 &device.idVendor, &device.idProduct);
352 if(h->detach) h->detach(NULL, h->user_data);
354 dev_list_remove(h, udev_device_get_devnode(dev));
355 if(h->detach) h->detach(&device, h->user_data);
359 // destroy the relevant device
360 udev_device_unref(dev);
363 items[0].revents = 0;
368 UINT_PTR timer = SetTimer(h->hwnd, 0, ms, NULL);
371 int ret = GetMessage(&msg, NULL, 0, 0);
373 if(ret <= 0) return 0;
375 TranslateMessage(&msg);
376 DispatchMessage(&msg);
378 KillTimer(h->hwnd, timer);
384 SR_API void libusbhp_register_hotplug_listeners(struct libusbhp_t *handle,
385 libusbhp_hotplug_cb_fn connected_cb,
386 libusbhp_hotplug_cb_fn disconnected_cb,
389 handle->attach = connected_cb;
390 handle->detach = disconnected_cb;
391 handle->user_data = user_data;