1+ //
2+ // keep_alive.c
3+ // Created by Theodore Watson on 1/23/14.
4+
5+ //This file is part of the OpenKinect Project. http://www.openkinect.org
6+ //
7+ // Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file
8+ // for details.
9+ //
10+ // This code is licensed to you under the terms of the Apache License, version
11+ // 2.0, or, at your option, the terms of the GNU General Public License,
12+ // version 2.0. See the APACHE20 and GPL20 files for the text of the licenses,
13+ // or the following URLs:
14+ // http://www.apache.org/licenses/LICENSE-2.0
15+ // http://www.gnu.org/licenses/gpl-2.0.txt
16+ //
17+ // If you redistribute this file in source form, modified or unmodified,
18+ // you may:
19+ // 1) Leave this header intact and distribute it under the same terms,
20+ // accompanying it with the APACHE20 and GPL20 files, or
21+ // 2) Delete the Apache 2.0 clause and accompany it with the GPL20 file, or
22+ // 3) Delete the GPL v2.0 clause and accompany it with the APACHE20 file
23+ // In all cases you must keep the copyright notice intact and include a copy
24+ // of the CONTRIB file.
25+ // Binary distributions must follow the binary distribution requirements of
26+ // either License.
27+
28+
29+ //Based on code provided by Drew Fisher
30+
31+ /*
32+ * Copyright 2011 Drew Fisher <drew.m.fisher@gmail.com>. All rights reserved.
33+ *
34+ * Redistribution and use in source and binary forms, with or without
35+ * modification, are permitted provided that the following conditions
36+ * are met:
37+ *
38+ * 1. Redistributions of source code must retain the above copyright
39+ * notice, this list of conditions and the following disclaimer.
40+ *
41+ * 2. Redistributions in binary form must reproduce the above copyright
42+ * notice, this list of conditions and the following disclaimer in the
43+ * documentation and/or other materials provided with the distribution.
44+ *
45+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
46+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48+ * ARE DISCLAIMED. IN NO EVENT SHALL DREW FISHER OR CONTRIBUTORS BE LIABLE
49+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55+ * SUCH DAMAGE.
56+ *
57+ * The views and conclusions contained in the software and documentation are
58+ * those of the authors and should not be interpreted as representing official
59+ * policies, either expressed or implied, of Drew Fisher.
60+ */
61+
62+
63+
64+
65+ #include "keep_alive.h"
66+ #include "freenect_internal.h"
67+
68+ #include <libusb-1.0/libusb.h>
69+ #include <stdio.h>
70+ #include <stdlib.h>
71+ #include <string.h>
72+ #include <stdint.h>
73+ #include <unistd.h> // For usleep()
74+
75+ #define le32 (X ) (X)
76+ #define LOG (...) fprintf(stderr, __VA_ARGS__)
77+
78+ static uint32_t tag_seq = 1 ;
79+ static uint32_t tag_next_ack = 1 ;
80+
81+ typedef struct {
82+ uint32_t magic ;
83+ uint32_t tag ;
84+ uint32_t status ;
85+ } motor_reply ;
86+
87+ typedef struct {
88+ uint32_t magic ;
89+ uint32_t tag ;
90+ uint32_t arg1 ;
91+ uint32_t cmd ;
92+ uint32_t arg2 ;
93+ } motor_command ;
94+
95+ static int get_reply (libusb_device_handle * dev ){
96+ unsigned char buffer [512 ];
97+ memset (buffer , 0 , 512 );
98+ int transferred = 0 ;
99+ int res = 0 ;
100+ res = libusb_bulk_transfer (dev , 0x81 , buffer , 512 , & transferred , 0 );
101+ if (res != 0 ) {
102+ LOG ("freenect_extra_keep_alive get_reply(): libusb_bulk_transfer failed: %d (transferred = %d)\n" , res , transferred );
103+ } else if (transferred != 12 ) {
104+ LOG ("freenect_extra_keep_alive get_reply(): weird - got %d bytes (expected 12)\n" , transferred );
105+ } else {
106+ motor_reply reply ;
107+ memcpy (& reply , buffer , sizeof (reply ));
108+ if (reply .magic != 0x0a6fe000 ) {
109+ LOG ("freenect_extra_keep_alive Bad magic: %08X (expected 0A6FE000\n" , reply .magic );
110+ res = -1 ;
111+ }
112+ if (reply .tag != tag_next_ack ) {
113+ LOG ("freenect_extra_keep_alive Reply tag out of order: expected %d, got %d\n" , tag_next_ack , reply .tag );
114+ res = -1 ;
115+ }
116+ if (reply .status != 0 ) {
117+ LOG ("freenect_extra_keep_alive reply status != 0: failure?\n" );
118+ res = -1 ;
119+ }
120+ tag_next_ack ++ ;
121+ // LOG("freenect_extra_keep_alive get_reply(): got %d bytes:", transferred);
122+ // int i;
123+ // for (i = 0; i < transferred; i++) {
124+ // LOG(" %02X", buffer[i]);
125+ // }
126+ // LOG("\n");
127+ }
128+ return res ;
129+ }
130+
131+ static int set_led (libusb_device_handle * dev , int state ) {
132+ int transferred = 0 ;
133+ int res = 0 ;
134+ motor_command cmd ;
135+ cmd .magic = le32 (0x06022009 );
136+ cmd .tag = le32 (tag_seq ++ );
137+ cmd .arg1 = le32 (0 );
138+ cmd .cmd = le32 (0x10 );
139+ cmd .arg2 = (uint32_t )(le32 ((int32_t )state ));
140+ unsigned char buffer [20 ];
141+ memcpy (buffer , & cmd , 20 );
142+ // Send command to set LED to solid green
143+ // LOG("About to send bulk transfer:");
144+ // int i;
145+ // for(i = 0; i < 20 ; i++) {
146+ // LOG(" %02X", buffer[i]);
147+ // }
148+ // LOG("\n");
149+ res = libusb_bulk_transfer (dev , 0x01 , buffer , 20 , & transferred , 0 );
150+ if (res != 0 ) {
151+ LOG ("freenect_extra_keep_alive set_led(): libusb_bulk_transfer failed: %d (transferred = %d)\n" , res , transferred );
152+ return res ;
153+ }
154+ return get_reply (dev );
155+ }
156+
157+ //this is for K4W or 1473 devices - pass in the PID of the audio device that needs the LED set.
158+ void freenect_extra_keep_alive (int pid ){
159+
160+ int res ;
161+ int state_to_set = 3 ;
162+
163+ libusb_context * ctx = NULL ;
164+ libusb_init (& ctx );
165+
166+ libusb_device_handle * dev = NULL ;
167+
168+ //check the default audio device
169+ dev = libusb_open_device_with_vid_pid (ctx , 0x045e , pid );
170+
171+ //K4W only:
172+ //if the firmware is uploaded the device could have a two different PIDs based on which firmware was uploaded.
173+ //so we have to check for both
174+ //note: it might be better if we pass in the PID of the camera and then find the audio device that is in the same usb tree/hub - might be more reliable when multiple devices are plugged in
175+ if ( dev == NULL && pid == PID_K4W_AUDIO ){
176+ pid = PID_K4W_AUDIO_ALT_1 ;
177+ dev = libusb_open_device_with_vid_pid (ctx , 0x045e , pid );
178+ }
179+ if ( dev == NULL && pid == PID_K4W_AUDIO_ALT_1 ){
180+ pid = PID_K4W_AUDIO_ALT_2 ;
181+ dev = libusb_open_device_with_vid_pid (ctx , 0x045e , pid );
182+ }
183+
184+ if (dev == NULL ) {
185+ LOG ("freenect extra keepAlive: Failed to open audio device\n" );
186+ libusb_exit (ctx );
187+ return ;
188+ }
189+
190+ res = libusb_claim_interface (dev , 0 );
191+ if (res != 0 ) {
192+ LOG ("freenect extra keepAlive: Failed to claim interface 1: %d\n" , res );
193+ libusb_close (dev );
194+ libusb_exit (ctx );
195+ return ;
196+ }
197+
198+ res = set_led (dev , state_to_set );
199+ if (res != 0 ) {
200+ LOG ("freenect extra keepAlive: set_led failed\n" );
201+ libusb_close (dev );
202+ libusb_exit (ctx );
203+ return ;
204+ }
205+
206+ libusb_close (dev );
207+ libusb_exit (ctx );
208+ }
0 commit comments