37eef1be714c9d0125d19dd541d0b2b52125ded6
[sdk/target/sdbd.git] / src / usb_windows.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <windows.h>
18 #include <winerror.h>
19 #include <errno.h>
20 #include <usb100.h>
21 #include <sdb_api.h>
22 #include <stdio.h>
23
24 #include "sysdeps.h"
25
26 #define   TRACE_TAG  TRACE_USB
27 #include "sdb.h"
28
29 /** Structure usb_handle describes our connection to the usb device via
30   AdbWinApi.dll. This structure is returned from usb_open() routine and
31   is expected in each subsequent call that is accessing the device.
32 */
33 struct usb_handle {
34   /// Previous entry in the list of opened usb handles
35   usb_handle *prev;
36
37   /// Next entry in the list of opened usb handles
38   usb_handle *next;
39
40   /// Handle to USB interface
41   SDBAPIHANDLE  sdb_interface;
42
43   /// Handle to USB read pipe (endpoint)
44   SDBAPIHANDLE  sdb_read_pipe;
45
46   /// Handle to USB write pipe (endpoint)
47   SDBAPIHANDLE  sdb_write_pipe;
48
49   /// Interface name
50   char*         interface_name;
51
52   /// Mask for determining when to use zero length packets
53   unsigned zero_mask;
54 };
55
56 /// Class ID assigned to the device by androidusb.sys
57 static const GUID usb_class_id = ANDROID_USB_CLASS_ID;
58
59 /// List of opened usb handles
60 static usb_handle handle_list = {
61   .prev = &handle_list,
62   .next = &handle_list,
63 };
64
65 /// Locker for the list of opened usb handles
66 SDB_MUTEX_DEFINE( usb_lock );
67
68 /// Checks if there is opened usb handle in handle_list for this device.
69 int known_device(const char* dev_name);
70
71 /// Checks if there is opened usb handle in handle_list for this device.
72 /// usb_lock mutex must be held before calling this routine.
73 int known_device_locked(const char* dev_name);
74
75 /// Registers opened usb handle (adds it to handle_list).
76 int register_new_device(usb_handle* handle);
77
78 /// Checks if interface (device) matches certain criteria
79 int recognized_device(usb_handle* handle);
80
81 /// Enumerates present and available interfaces (devices), opens new ones and
82 /// registers usb transport for them.
83 void find_devices();
84
85 /// Entry point for thread that polls (every second) for new usb interfaces.
86 /// This routine calls find_devices in infinite loop.
87 void* device_poll_thread(void* unused);
88
89 /// Initializes this module
90 void usb_init();
91
92 /// Cleans up this module
93 void usb_cleanup();
94
95 /// Opens usb interface (device) by interface (device) name.
96 usb_handle* do_usb_open(const wchar_t* interface_name);
97
98 /// Writes data to the opened usb handle
99 int usb_write(usb_handle* handle, const void* data, int len);
100
101 /// Reads data using the opened usb handle
102 int usb_read(usb_handle *handle, void* data, int len);
103
104 /// Cleans up opened usb handle
105 void usb_cleanup_handle(usb_handle* handle);
106
107 /// Cleans up (but don't close) opened usb handle
108 void usb_kick(usb_handle* handle);
109
110 /// Closes opened usb handle
111 int usb_close(usb_handle* handle);
112
113 /// Gets interface (device) name for an opened usb handle
114 const char *usb_name(usb_handle* handle);
115
116 int known_device_locked(const char* dev_name) {
117   usb_handle* usb;
118
119   if (NULL != dev_name) {
120     // Iterate through the list looking for the name match.
121     for(usb = handle_list.next; usb != &handle_list; usb = usb->next) {
122       // In Windows names are not case sensetive!
123       if((NULL != usb->interface_name) &&
124          (0 == stricmp(usb->interface_name, dev_name))) {
125         return 1;
126       }
127     }
128   }
129
130   return 0;
131 }
132
133 int known_device(const char* dev_name) {
134   int ret = 0;
135
136   if (NULL != dev_name) {
137     sdb_mutex_lock(&usb_lock);
138     ret = known_device_locked(dev_name);
139     sdb_mutex_unlock(&usb_lock);
140   }
141
142   return ret;
143 }
144
145 int register_new_device(usb_handle* handle) {
146   if (NULL == handle)
147     return 0;
148
149   sdb_mutex_lock(&usb_lock);
150
151   // Check if device is already in the list
152   if (known_device_locked(handle->interface_name)) {
153     sdb_mutex_unlock(&usb_lock);
154     return 0;
155   }
156
157   // Not in the list. Add this handle to the list.
158   handle->next = &handle_list;
159   handle->prev = handle_list.prev;
160   handle->prev->next = handle;
161   handle->next->prev = handle;
162
163   sdb_mutex_unlock(&usb_lock);
164
165   return 1;
166 }
167
168 void* device_poll_thread(void* unused) {
169   D("Created device thread\n");
170
171   while(1) {
172     find_devices();
173     sdb_sleep_ms(1000);
174   }
175
176   return NULL;
177 }
178
179 void usb_init() {
180   sdb_thread_t tid;
181
182   if(sdb_thread_create(&tid, device_poll_thread, NULL)) {
183     fatal_errno("cannot create input thread");
184   }
185 }
186
187 void usb_cleanup() {
188 }
189
190 usb_handle* do_usb_open(const wchar_t* interface_name) {
191   // Allocate our handle
192   usb_handle* ret = (usb_handle*)malloc(sizeof(usb_handle));
193   if (NULL == ret)
194     return NULL;
195
196   // Set linkers back to the handle
197   ret->next = ret;
198   ret->prev = ret;
199
200   // Create interface.
201   ret->sdb_interface = SdbCreateInterfaceByName(interface_name);
202
203   if (NULL == ret->sdb_interface) {
204     free(ret);
205     errno = GetLastError();
206     return NULL;
207   }
208
209   // Open read pipe (endpoint)
210   ret->sdb_read_pipe =
211     SdbOpenDefaultBulkReadEndpoint(ret->sdb_interface,
212                                    SdbOpenAccessTypeReadWrite,
213                                    SdbOpenSharingModeReadWrite);
214   if (NULL != ret->sdb_read_pipe) {
215     // Open write pipe (endpoint)
216     ret->sdb_write_pipe =
217       SdbOpenDefaultBulkWriteEndpoint(ret->sdb_interface,
218                                       SdbOpenAccessTypeReadWrite,
219                                       SdbOpenSharingModeReadWrite);
220     if (NULL != ret->sdb_write_pipe) {
221       // Save interface name
222       unsigned long name_len = 0;
223
224       // First get expected name length
225       SdbGetInterfaceName(ret->sdb_interface,
226                           NULL,
227                           &name_len,
228                           true);
229       if (0 != name_len) {
230         ret->interface_name = (char*)malloc(name_len);
231
232         if (NULL != ret->interface_name) {
233           // Now save the name
234           if (SdbGetInterfaceName(ret->sdb_interface,
235                                   ret->interface_name,
236                                   &name_len,
237                                   true)) {
238             // We're done at this point
239             return ret;
240           }
241         } else {
242           SetLastError(ERROR_OUTOFMEMORY);
243         }
244       }
245     }
246   }
247
248   // Something went wrong.
249   int saved_errno = GetLastError();
250   usb_cleanup_handle(ret);
251   free(ret);
252   SetLastError(saved_errno);
253
254   return NULL;
255 }
256
257 int usb_write(usb_handle* handle, const void* data, int len) {
258   unsigned long time_out = 5000;
259   unsigned long written = 0;
260   int ret;
261
262   D("usb_write %d\n", len);
263   if (NULL != handle) {
264     // Perform write
265     ret = SdbWriteEndpointSync(handle->sdb_write_pipe,
266                                (void*)data,
267                                (unsigned long)len,
268                                &written,
269                                time_out);
270     int saved_errno = GetLastError();
271
272     if (ret) {
273       // Make sure that we've written what we were asked to write
274       D("usb_write got: %ld, expected: %d\n", written, len);
275       if (written == (unsigned long)len) {
276         if(handle->zero_mask && (len & handle->zero_mask) == 0) {
277           // Send a zero length packet
278           SdbWriteEndpointSync(handle->sdb_write_pipe,
279                                (void*)data,
280                                0,
281                                &written,
282                                time_out);
283         }
284         return 0;
285       }
286     } else {
287       // assume ERROR_INVALID_HANDLE indicates we are disconnected
288       if (saved_errno == ERROR_INVALID_HANDLE)
289         usb_kick(handle);
290     }
291     errno = saved_errno;
292   } else {
293     D("usb_write NULL handle\n");
294     SetLastError(ERROR_INVALID_HANDLE);
295   }
296
297   D("usb_write failed: %d\n", errno);
298
299   return -1;
300 }
301
302 int usb_read(usb_handle *handle, void* data, int len) {
303   unsigned long time_out = 0;
304   unsigned long read = 0;
305   int ret;
306
307   D("usb_read %d\n", len);
308   if (NULL != handle) {
309     while (len > 0) {
310       int xfer = (len > 4096) ? 4096 : len;
311
312       ret = SdbReadEndpointSync(handle->sdb_read_pipe,
313                                   (void*)data,
314                                   (unsigned long)xfer,
315                                   &read,
316                                   time_out);
317       int saved_errno = GetLastError();
318       D("usb_write got: %ld, expected: %d, errno: %d\n", read, xfer, saved_errno);
319       if (ret) {
320         data += read;
321         len -= read;
322
323         if (len == 0)
324           return 0;
325       } else {
326         // assume ERROR_INVALID_HANDLE indicates we are disconnected
327         if (saved_errno == ERROR_INVALID_HANDLE)
328           usb_kick(handle);
329         break;
330       }
331       errno = saved_errno;
332     }
333   } else {
334     D("usb_read NULL handle\n");
335     SetLastError(ERROR_INVALID_HANDLE);
336   }
337
338   D("usb_read failed: %d\n", errno);
339
340   return -1;
341 }
342
343 void usb_cleanup_handle(usb_handle* handle) {
344   if (NULL != handle) {
345     if (NULL != handle->interface_name)
346       free(handle->interface_name);
347     if (NULL != handle->sdb_write_pipe)
348       SdbCloseHandle(handle->sdb_write_pipe);
349     if (NULL != handle->sdb_read_pipe)
350       SdbCloseHandle(handle->sdb_read_pipe);
351     if (NULL != handle->sdb_interface)
352       SdbCloseHandle(handle->sdb_interface);
353
354     handle->interface_name = NULL;
355     handle->sdb_write_pipe = NULL;
356     handle->sdb_read_pipe = NULL;
357     handle->sdb_interface = NULL;
358   }
359 }
360
361 void usb_kick(usb_handle* handle) {
362   if (NULL != handle) {
363     sdb_mutex_lock(&usb_lock);
364
365     usb_cleanup_handle(handle);
366
367     sdb_mutex_unlock(&usb_lock);
368   } else {
369     SetLastError(ERROR_INVALID_HANDLE);
370     errno = ERROR_INVALID_HANDLE;
371   }
372 }
373
374 int usb_close(usb_handle* handle) {
375   D("usb_close\n");
376
377   if (NULL != handle) {
378     // Remove handle from the list
379     sdb_mutex_lock(&usb_lock);
380
381     if ((handle->next != handle) && (handle->prev != handle)) {
382       handle->next->prev = handle->prev;
383       handle->prev->next = handle->next;
384       handle->prev = handle;
385       handle->next = handle;
386     }
387
388     sdb_mutex_unlock(&usb_lock);
389
390     // Cleanup handle
391     usb_cleanup_handle(handle);
392     free(handle);
393   }
394
395   return 0;
396 }
397
398 const char *usb_name(usb_handle* handle) {
399   if (NULL == handle) {
400     SetLastError(ERROR_INVALID_HANDLE);
401     errno = ERROR_INVALID_HANDLE;
402     return NULL;
403   }
404
405   return (const char*)handle->interface_name;
406 }
407
408 int recognized_device(usb_handle* handle) {
409   if (NULL == handle)
410     return 0;
411
412   // Check vendor and product id first
413   USB_DEVICE_DESCRIPTOR device_desc;
414
415   if (!SdbGetUsbDeviceDescriptor(handle->sdb_interface,
416                                  &device_desc)) {
417     return 0;
418   }
419
420   // Then check interface properties
421   USB_INTERFACE_DESCRIPTOR interf_desc;
422
423   if (!SdbGetUsbInterfaceDescriptor(handle->sdb_interface,
424                                     &interf_desc)) {
425     return 0;
426   }
427
428   // Must have two endpoints
429   if (2 != interf_desc.bNumEndpoints) {
430     return 0;
431   }
432
433   if (is_sdb_interface(device_desc.idVendor, device_desc.idProduct,
434       interf_desc.bInterfaceClass, interf_desc.bInterfaceSubClass, interf_desc.bInterfaceProtocol)) {
435
436     if(interf_desc.bInterfaceProtocol == 0x01) {
437       SdbEndpointInformation endpoint_info;
438       // assuming zero is a valid bulk endpoint ID
439       if (SdbGetEndpointInformation(handle->sdb_interface, 0, &endpoint_info)) {
440         handle->zero_mask = endpoint_info.max_packet_size - 1;
441       }
442     }
443
444     return 1;
445   }
446
447   return 0;
448 }
449
450 void find_devices() {
451         usb_handle* handle = NULL;
452   char entry_buffer[2048];
453   char interf_name[2048];
454   SdbInterfaceInfo* next_interface = (SdbInterfaceInfo*)(&entry_buffer[0]);
455   unsigned long entry_buffer_size = sizeof(entry_buffer);
456   char* copy_name;
457
458   // Enumerate all present and active interfaces.
459   SDBAPIHANDLE enum_handle =
460     SdbEnumInterfaces(usb_class_id, true, true, true);
461
462   if (NULL == enum_handle)
463     return;
464
465   while (SdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) {
466     // TODO: FIXME - temp hack converting wchar_t into char.
467     // It would be better to change AdbNextInterface so it will return
468     // interface name as single char string.
469     const wchar_t* wchar_name = next_interface->device_name;
470     for(copy_name = interf_name;
471         L'\0' != *wchar_name;
472         wchar_name++, copy_name++) {
473       *copy_name = (char)(*wchar_name);
474     }
475     *copy_name = '\0';
476
477     // Lets see if we already have this device in the list
478     if (!known_device(interf_name)) {
479       // This seems to be a new device. Open it!
480         handle = do_usb_open(next_interface->device_name);
481         if (NULL != handle) {
482         // Lets see if this interface (device) belongs to us
483         if (recognized_device(handle)) {
484           D("adding a new device %s\n", interf_name);
485           char serial_number[512];
486           unsigned long serial_number_len = sizeof(serial_number);
487           if (SdbGetSerialNumber(handle->sdb_interface,
488                                 serial_number,
489                                 &serial_number_len,
490                                 true)) {
491             // Lets make sure that we don't duplicate this device
492             if (register_new_device(handle)) {
493               register_usb_transport(handle, serial_number, 1);
494             } else {
495               D("register_new_device failed for %s\n", interf_name);
496               usb_cleanup_handle(handle);
497               free(handle);
498             }
499           } else {
500             D("cannot get serial number\n");
501             usb_cleanup_handle(handle);
502             free(handle);
503           }
504         } else {
505           usb_cleanup_handle(handle);
506           free(handle);
507         }
508       }
509     }
510
511     entry_buffer_size = sizeof(entry_buffer);
512   }
513
514   SdbCloseHandle(enum_handle);
515 }