Mercurial > hg > hid-usb-to-ir
annotate hid-usb-to-ir.c @ 4:4f66576cd77a default tip
add README
| author | Peter Meerwald <p.meerwald@bct-electronic.com> |
|---|---|
| date | Thu, 03 Jan 2013 13:12:08 +0100 |
| parents | 95b8b8a0b2d0 |
| children |
| rev | line source |
|---|---|
| 0 | 1 /* |
| 2 * Demo program for the Silabs IR Gesture USB Reference Design, | |
| 3 * http://www.silabs.com/products/sensors/Pages/HID-USB-to-IR-Reference-Design.aspx | |
| 4 * | |
| 5 * Reads the part number of the cp2112 bridge, | |
| 6 * http://www.silabs.com/products/interface/usbtouart/Pages/HID-USB-to-SMBus-Bridge.aspx, | |
| 7 * and the part/revision/sequencer version of the si1143 via SMBus/I2C, | |
| 8 * finally lets the four blue LEDs dance :). | |
| 9 * | |
| 10 * Copyright (c) 2012 Peter Meerwald, <pmeerw@pmeerw.net> | |
| 11 * Released under GPLv3 license, see http://www.gnu.org/licenses/gpl-3.0.html. | |
| 12 * | |
| 13 * Depends on the HID API multi-platform library, available from | |
| 14 * http://www.signal11.us/oss/hidapi/. | |
| 15 * | |
| 16 * Build with | |
| 17 * gcc -Wall -g -o hid-usb-to-ir hid-usb-to-ir.c `pkg-config hidapi-hidraw --libs` | |
| 18 * | |
| 19 * May need root permission to access USB device (or appropriate udev rule). | |
| 20 * | |
| 21 * Based upon information from Silabs AN495 v0.2. | |
| 22 */ | |
| 23 | |
| 24 #include <stdio.h> | |
| 25 #include <stdlib.h> | |
| 26 #include <string.h> | |
| 27 #include <unistd.h> | |
| 28 #include "hidapi/hidapi.h" | |
| 29 | |
| 30 #define SI114X_SLAVE_ADDR 0x5a | |
|
2
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
31 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
32 #define SI114x_REG_PART_ID 0x00 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
33 #define SI114x_REG_REV_ID 0x01 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
34 #define SI114x_REG_SEQ_ID 0x02 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
35 #define SI114X_REG_HWKEY 0x07 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
36 #define SI114X_REG_MEAS_RATE 0x08 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
37 #define SI114X_REG_ALS_RATE 0x09 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
38 #define SI114X_REG_PS_RATE 0x0a |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
39 #define SI114X_REG_PS_LED21 0x0f |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
40 #define SI114X_REG_PS_LED3 0x10 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
41 #define SI114X_REG_PARAM_WR 0x17 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
42 #define SI114X_REG_COMMAND 0x18 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
43 #define SI114X_REG_ALSVIS_DATA0 0x22 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
44 #define SI114X_REG_ALSVIS_DATA1 0x23 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
45 #define SI114X_REG_ALSIR_DATA0 0x24 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
46 #define SI114X_REG_ALSIR_DATA1 0x25 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
47 #define SI114X_REG_PS1_DATA0 0x26 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
48 #define SI114X_REG_PS1_DATA1 0x27 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
49 #define SI114X_REG_PS2_DATA0 0x28 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
50 #define SI114X_REG_PS2_DATA1 0x29 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
51 #define SI114X_REG_PS3_DATA0 0x2a |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
52 #define SI114X_REG_PS3_DATA1 0x2b |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
53 #define SI114X_REG_AUX_DATA0 0x2c |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
54 #define SI114X_REG_AUX_DATA1 0x2d |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
55 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
56 /* Commands for COMMAND */ |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
57 #define SI114X_CMD_NOP 0x00 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
58 #define SI114X_CMD_RESET 0x01 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
59 #define SI114X_CMD_BUSADDR 0x02 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
60 #define SI114X_CMD_PS_FORCE 0x05 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
61 #define SI114X_CMD_ALS_FORCE 0x06 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
62 #define SI114X_CMD_PSALS_FORCE 0x07 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
63 #define SI114X_CMD_PS_PAUSE 0x09 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
64 #define SI114X_CMD_ALS_PAUSE 0x0a |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
65 #define SI114X_CMD_PSALS_PAUSE 0x0b |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
66 #define SI114X_CMD_PS_AUTO 0x0d |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
67 #define SI114X_CMD_ALS_AUTO 0x0e |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
68 #define SI114X_CMD_PSALS_AUTO 0x0f |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
69 #define SI114X_CMD_PARAM_QUERY 0x80 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
70 #define SI114X_CMD_PARAM_SET 0xa0 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
71 #define SI114X_CMD_PARAM_AND 0xc0 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
72 #define SI114X_CMD_PARAM_OR 0xe0 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
73 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
74 /* Parameter offsets */ |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
75 #define SI114X_PARAM_CHLIST 0x01 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
76 #define SI114X_PARAM_PSLED12_SELECT 0x02 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
77 #define SI114X_PARAM_PSLED3_SELECT 0x03 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
78 #define SI114X_PARAM_PS_ADC_COUNTER 0x0a |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
79 #define SI114X_PARAM_PS_ADC_GAIN 0x0b |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
80 #define SI114X_PARAM_PS_ADC_MISC 0x0c |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
81 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
82 /* Channel enable masks for CHLIST parameter */ |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
83 #define SI114X_CHLIST_EN_PS1 0x01 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
84 #define SI114X_CHLIST_EN_PS2 0x02 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
85 #define SI114X_CHLIST_EN_PS3 0x04 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
86 #define SI114X_CHLIST_EN_ALSVIS 0x10 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
87 #define SI114X_CHLIST_EN_ALSIR 0x20 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
88 #define SI114X_CHLIST_EN_AUX 0x40 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
89 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
90 /* Measurement rate settings */ |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
91 #define SI114X_MEAS_RATE_FORCED 0x00 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
92 #define SI114X_MEAS_RATE_10MS 0x84 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
93 #define SI114X_MEAS_RATE_20MS 0x94 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
94 #define SI114X_MEAS_RATE_100MS 0xb9 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
95 #define SI114X_MEAS_RATE_496MS 0xdf |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
96 #define SI114X_MEAS_RATE_1984MS 0xff |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
97 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
98 /* ALS rate settings relative to measurement rate */ |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
99 #define SI114X_ALS_RATE_OFF 0x00 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
100 #define SI114X_ALS_RATE_1X 0x08 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
101 #define SI114X_ALS_RATE_10X 0x32 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
102 #define SI114X_ALS_RATE_100X 0x69 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
103 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
104 /* PS rate settings relative to measurement rate */ |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
105 #define SI114X_PS_RATE_OFF 0x00 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
106 #define SI114X_PS_RATE_1X 0x08 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
107 #define SI114X_PS_RATE_10X 0x32 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
108 #define SI114X_PS_RATE_100X 0x69 |
| 0 | 109 |
| 110 #define CP2112_GETSET_GPIO_CONFIG 0x02 | |
| 111 #define CP2112_GET_GPIO 0x03 | |
| 112 #define CP2112_SET_GPIO 0x04 | |
| 113 #define CP2122_GET_VERSION_INFO 0x05 | |
| 114 #define CP2112_GETSET_SMBUS_CONFIG 0x06 | |
| 115 #define CP2112_DATA_WRITE_READ_REQ 0x11 | |
| 116 #define CP2112_DATA_READ_RESP 0x13 | |
| 117 #define CP2112_DATA_WRITE 0x14 | |
| 118 #define CP2112_TRANSFER_STATUS_REQ 0x15 | |
| 119 #define CP2112_TRANSFER_STATUS_RESP 0x16 | |
| 120 | |
| 121 #define CP2112_LED_DOWN 0x01 /* LED DS2, GPIO 0 */ | |
| 122 #define CP2112_LED_UP 0x02 /* LED DS3, GPIO 1 */ | |
| 123 #define CP2112_LED_RIGHT 0x08 /* LED DS8, GPIO 3 */ | |
| 124 #define CP2112_LED_LEFT 0x80 /* LED DS4, GPIO 7 */ | |
| 125 #define CP2112_LEDS_MASK (CP2112_LED_DOWN | CP2112_LED_UP | \ | |
| 126 CP2112_LED_RIGHT | CP2112_LED_LEFT) | |
| 127 | |
| 128 /* get cp2112 part number and version */ | |
| 129 static int cp2112_get_version(hid_device *hd, unsigned char data[2]) { | |
| 130 unsigned char buf[3] = { CP2122_GET_VERSION_INFO, }; | |
| 131 | |
| 132 int ret = hid_get_feature_report(hd, buf, sizeof(buf)); | |
| 133 if (ret < 0) { | |
| 134 fprintf(stderr, "hid_get_feature_report() failed: %ls\n", | |
| 135 hid_error(hd)); | |
| 136 return -1; | |
| 137 } | |
| 138 | |
| 139 data[0] = buf[1]; /* part number */ | |
| 140 data[1] = buf[2]; /* version */ | |
| 141 | |
| 142 return 0; | |
| 143 } | |
| 144 | |
| 145 /* configures cp2112 to automatically send read data, see AN495 section 4.6 */ | |
| 146 static int cp2112_set_auto_send_read(hid_device *hd, int on_off) { | |
| 147 unsigned char buf[14] = { CP2112_GETSET_SMBUS_CONFIG, }; | |
| 148 int ret = hid_get_feature_report(hd, buf, sizeof(buf)); | |
| 149 if (ret < 0) { | |
| 150 fprintf(stderr, "hid_get_feature_report() failed: %ls\n", | |
| 151 hid_error(hd)); | |
| 152 return -1; | |
| 153 } | |
| 154 | |
| 155 buf[6] = on_off; | |
| 156 | |
| 157 ret = hid_send_feature_report(hd, buf, sizeof(buf)); | |
| 158 if (ret < 0) { | |
| 159 fprintf(stderr, "hid_send_feature_report() failed: %ls\n", | |
| 160 hid_error(hd)); | |
| 161 return -1; | |
| 162 } | |
| 163 | |
| 164 return 0; | |
| 165 } | |
| 166 | |
| 167 /* see if the cp2112 is idle */ | |
| 168 static int cp2112_is_idle(hid_device *hd) { | |
| 169 unsigned char status_req[2] = { CP2112_TRANSFER_STATUS_REQ, 0x01, }; | |
| 170 if (hid_write(hd, status_req, sizeof(status_req)) < 0) { | |
| 171 fprintf(stderr, "hid_write() failed: %ls\n", | |
| 172 hid_error(hd)); | |
| 173 return -1; | |
| 174 } | |
| 175 | |
| 176 unsigned char status_resp[7] = { 0x00, }; | |
| 177 if (hid_read(hd, status_resp, sizeof(status_resp)) < 0) { | |
| 178 fprintf(stderr, "hid_read() failed: %ls\n", | |
| 179 hid_error(hd)); | |
| 180 return -1; | |
| 181 } | |
| 182 | |
| 183 if (status_resp[0] == CP2112_TRANSFER_STATUS_RESP) { | |
| 184 if (status_resp[1] == 0x00) /* is idle? */ | |
| 185 return 1; | |
| 186 } | |
| 187 | |
| 188 return 0; | |
| 189 } | |
| 190 | |
| 191 /* write a data byte to register reg of the si1143 */ | |
| 192 static int cp2112_write_byte(hid_device *hd, unsigned char reg, unsigned char data) { | |
| 193 /* 0x5a is the 7-bit SMBus slave address of the si1143 */ | |
| 194 unsigned char buf_out[5] = { CP2112_DATA_WRITE, SI114X_SLAVE_ADDR<<1, 0x02, }; | |
| 195 buf_out[3] = reg; | |
| 196 buf_out[4] = data; | |
| 197 int ret = hid_write(hd, buf_out, sizeof(buf_out)); | |
| 198 if (ret < 0) { | |
| 199 fprintf(stderr, "hid_write() failed: %ls\n", | |
| 200 hid_error(hd)); | |
| 201 return -1; | |
| 202 } | |
| 203 | |
| 204 return 0; | |
| 205 } | |
| 206 | |
|
2
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
207 static int cp2112_write_param_byte(hid_device *hd, unsigned char param, unsigned char data) { |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
208 if (cp2112_write_byte(hd, SI114X_REG_PARAM_WR, data) < 0) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
209 return -1; |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
210 if (cp2112_write_byte(hd, SI114X_REG_COMMAND, param | SI114X_CMD_PARAM_SET) < 0) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
211 return -1; |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
212 return 0; |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
213 } |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
214 |
| 0 | 215 /* read a data byte from register reg of the si1143 */ |
| 216 static int cp2112_read_byte(hid_device *hd, unsigned char reg, unsigned char data[1]) { | |
| 217 /* 0x5a is the 7-bit SMBus slave address of the si1143 */ | |
| 218 unsigned char buf_out[6] = { CP2112_DATA_WRITE_READ_REQ, | |
| 219 SI114X_SLAVE_ADDR<<1, 0x00, 0x01, 0x01, }; | |
| 220 buf_out[5] = reg; | |
| 221 int ret = hid_write(hd, buf_out, sizeof(buf_out)); | |
| 222 if (ret < 0) { | |
| 223 fprintf(stderr, "hid_write() failed: %ls\n", | |
| 224 hid_error(hd)); | |
| 225 return -1; | |
| 226 } | |
| 227 | |
| 228 /* FIXME: may loop forever, error handling needed */ | |
| 229 while (1) { | |
| 230 | |
| 231 unsigned char buf_in[8] = { 0x00, }; | |
| 232 ret = hid_read(hd, buf_in, sizeof(buf_in)); | |
| 233 if (ret < 0) { | |
| 234 fprintf(stderr, "hid_read_() failed: %ls\n", | |
| 235 hid_error(hd)); | |
| 236 return -1; | |
| 237 } | |
| 238 | |
| 239 | |
|
2
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
240 if (buf_in[0] == CP2112_TRANSFER_STATUS_REQ) |
| 0 | 241 continue; |
| 242 | |
| 243 if (buf_in[0] == CP2112_DATA_READ_RESP) { | |
| 244 if (buf_in[1] == 0x02 && buf_in[2] == 0x00) | |
| 245 continue; /* no data yet */ | |
| 246 if (buf_in[1] == 0x02 && buf_in[2] == 0x01) { | |
| 247 data[0] = buf_in[3]; /* data available */ | |
| 248 return 0; | |
| 249 } | |
| 250 } | |
| 251 } | |
| 252 | |
| 253 return -1; | |
| 254 } | |
| 255 | |
|
2
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
256 static int cp2112_read_word(hid_device *hd, unsigned char reg, unsigned short data[1]) { |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
257 unsigned char lsb, msb; |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
258 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
259 if (cp2112_read_byte(hd, reg, &lsb) < 0) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
260 return -1; |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
261 if (cp2112_read_byte(hd, reg+1, &msb) < 0) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
262 return -1; |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
263 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
264 data[0] = (msb << 8) | lsb; |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
265 return 0; |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
266 } |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
267 |
| 0 | 268 /* configure cp2112 GPIO pins */ |
| 269 static int cp2112_config_gpio(hid_device *hd) { | |
| 270 unsigned char buf[5] = { CP2112_GETSET_GPIO_CONFIG, }; | |
| 271 int ret = hid_get_feature_report(hd, buf, sizeof(buf)); | |
| 272 if (ret < 0) { | |
| 273 fprintf(stderr, "hid_get_feature_report() failed: %ls\n", | |
| 274 hid_error(hd)); | |
| 275 return -1; | |
| 276 } | |
| 277 | |
| 278 buf[1] = 0x8b; /* output direction for GPIOs 0, 1, 3, 7 */ | |
| 279 buf[2] = 0x8b; /* push-pull for GPIOs 0, 1, 3, 7 */ | |
| 280 buf[3] = 0x00; /* no special functions, i.e. use pins as GPIO */ | |
| 281 | |
| 282 ret = hid_send_feature_report(hd, buf, sizeof(buf)); | |
| 283 if (ret < 0) { | |
| 284 fprintf(stderr, "hid_send_feature_report() failed: %ls\n", | |
| 285 hid_error(hd)); | |
| 286 return -1; | |
| 287 } | |
| 288 | |
| 289 return 0; | |
| 290 } | |
| 291 | |
| 292 /* set cp2112 GPIO pins */ | |
| 293 static int cp2112_set_gpio(hid_device *hd, unsigned char mask, unsigned char value) { | |
| 294 unsigned char buf[3] = { CP2112_SET_GPIO, }; | |
| 295 | |
| 296 buf[1] = ~value; /* set GPIO pins: 0 .. turn LED on, 1 .. off */ | |
| 297 buf[2] = mask; /* mask of pins to set, ignore others */ | |
| 298 | |
| 299 int ret = hid_send_feature_report(hd, buf, sizeof(buf)); | |
| 300 if (ret < 0) { | |
| 301 fprintf(stderr, "hid_send_feature_report() failed: %ls\n", | |
| 302 hid_error(hd)); | |
| 303 return -1; | |
| 304 } | |
| 305 | |
| 306 return 0; | |
| 307 } | |
| 308 | |
| 309 int main() { | |
| 310 if (hid_init() < 0) { | |
| 311 fprintf(stderr, "hid_init() failed, exit.\n"); | |
| 312 exit(EXIT_FAILURE); | |
| 313 } | |
| 314 | |
| 315 /* open Silabs IR Gesture USB reference design by USB product:vendor id */ | |
| 316 hid_device *hd = hid_open(0x10c4, 0xea90, NULL); | |
| 317 if (hd == NULL) { | |
| 318 fprintf(stderr, "hid_open() failed\n"); | |
| 319 exit(EXIT_FAILURE); | |
| 320 } | |
| 321 | |
| 322 unsigned char version_data[2]; | |
| 323 if (cp2112_get_version(hd, version_data) < 0) | |
| 324 exit(EXIT_FAILURE); | |
| 325 printf("cp2112 part number 0x%02x, device version %d\n", | |
| 326 version_data[0], version_data[1]); | |
| 327 | |
| 328 if (cp2112_set_auto_send_read(hd, 1) < 0) | |
| 329 exit(EXIT_FAILURE); | |
| 330 | |
| 331 /* write 0x17 to si114x HW_KEY register as per datasheet */ | |
|
2
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
332 if (cp2112_write_byte(hd, SI114X_REG_HWKEY, 0x17) < 0) |
| 0 | 333 exit(EXIT_FAILURE); |
| 334 | |
| 335 unsigned char part, rev, seq; | |
|
2
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
336 if (cp2112_read_byte(hd, SI114x_REG_PART_ID, &part) < 0) |
| 0 | 337 exit(EXIT_FAILURE); |
| 338 | |
|
2
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
339 if (cp2112_read_byte(hd, SI114x_REG_REV_ID, &rev) < 0) |
| 0 | 340 exit(EXIT_FAILURE); |
| 341 | |
|
2
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
342 if (cp2112_read_byte(hd, SI114x_REG_SEQ_ID, &seq) < 0) |
| 0 | 343 exit(EXIT_FAILURE); |
| 344 printf("si114x part number 0x%02x, revision 0x%02x, sequencer 0x%02x\n", | |
| 345 part, rev, seq); | |
| 346 | |
|
2
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
347 if (cp2112_write_byte(hd, SI114X_REG_COMMAND, SI114X_CMD_RESET) < 0) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
348 exit(EXIT_FAILURE); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
349 usleep(20000); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
350 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
351 if (cp2112_write_byte(hd, SI114X_REG_HWKEY, 0x17) < 0) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
352 exit(EXIT_FAILURE); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
353 usleep(20000); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
354 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
355 cp2112_is_idle(hd); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
356 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
357 /* set LED currents to maximum */ |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
358 if (cp2112_write_byte(hd, SI114X_REG_PS_LED3, 0x04)) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
359 exit(EXIT_FAILURE); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
360 if (cp2112_write_byte(hd, SI114X_REG_PS_LED21, 0x32)) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
361 exit(EXIT_FAILURE); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
362 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
363 if (cp2112_write_param_byte(hd, SI114X_PARAM_PS_ADC_MISC, 0x00 | 0x04)) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
364 exit(EXIT_FAILURE); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
365 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
366 if (cp2112_write_param_byte(hd, SI114X_PARAM_PSLED12_SELECT, 0x21)) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
367 exit(EXIT_FAILURE); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
368 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
369 if (cp2112_write_param_byte(hd, SI114X_PARAM_PSLED3_SELECT, 0x04)) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
370 exit(EXIT_FAILURE); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
371 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
372 if (cp2112_write_param_byte(hd, SI114X_PARAM_CHLIST, |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
373 SI114X_CHLIST_EN_ALSVIS | |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
374 SI114X_CHLIST_EN_PS3 | |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
375 SI114X_CHLIST_EN_PS2 | |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
376 SI114X_CHLIST_EN_PS1)) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
377 exit(EXIT_FAILURE); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
378 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
379 if (cp2112_write_param_byte(hd, SI114X_PARAM_PS_ADC_GAIN, 0x01)) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
380 exit(EXIT_FAILURE); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
381 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
382 if (cp2112_write_param_byte(hd, SI114X_PARAM_PS_ADC_COUNTER, 0x06 << 4)) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
383 exit(EXIT_FAILURE); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
384 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
385 /* in autonomous mode, wakeup every 100 ms */ |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
386 if (cp2112_write_byte(hd, SI114X_REG_MEAS_RATE, SI114X_MEAS_RATE_100MS)) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
387 exit(EXIT_FAILURE); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
388 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
389 /* measure ALS every time device wakes up */ |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
390 if (cp2112_write_byte(hd, SI114X_REG_ALS_RATE, SI114X_ALS_RATE_1X)) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
391 exit(EXIT_FAILURE); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
392 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
393 /* measure proximity every time device wakes up */ |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
394 if (cp2112_write_byte(hd, SI114X_REG_PS_RATE, SI114X_PS_RATE_1X)) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
395 exit(EXIT_FAILURE); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
396 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
397 if (cp2112_write_byte(hd, SI114X_REG_COMMAND, SI114X_CMD_PSALS_AUTO)) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
398 exit(EXIT_FAILURE); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
399 |
| 0 | 400 cp2112_is_idle(hd); |
| 401 | |
| 402 if (cp2112_config_gpio(hd) < 0) | |
| 403 exit(EXIT_FAILURE); | |
| 404 | |
| 405 while (1) { | |
|
2
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
406 unsigned short als, ps1, ps2, ps3; |
| 0 | 407 if (cp2112_set_gpio(hd, CP2112_LEDS_MASK, CP2112_LED_DOWN) < 0) |
| 408 exit(EXIT_FAILURE); | |
| 409 usleep(50*1000); | |
| 410 if (cp2112_set_gpio(hd, CP2112_LEDS_MASK, CP2112_LED_RIGHT) < 0) | |
| 411 exit(EXIT_FAILURE); | |
| 412 usleep(50*1000); | |
| 413 if (cp2112_set_gpio(hd, CP2112_LEDS_MASK, CP2112_LED_UP) < 0) | |
| 414 exit(EXIT_FAILURE); | |
| 415 usleep(50*1000); | |
| 416 if (cp2112_set_gpio(hd, CP2112_LEDS_MASK, CP2112_LED_LEFT) < 0) | |
| 417 exit(EXIT_FAILURE); | |
| 418 usleep(50*1000); | |
|
2
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
419 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
420 if (cp2112_read_word(hd, SI114X_REG_ALSVIS_DATA0, &als) < 0) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
421 exit(EXIT_FAILURE); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
422 if (cp2112_read_word(hd, SI114X_REG_PS1_DATA0, &ps1) < 0) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
423 exit(EXIT_FAILURE); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
424 if (cp2112_read_word(hd, SI114X_REG_PS2_DATA0, &ps2) < 0) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
425 exit(EXIT_FAILURE); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
426 if (cp2112_read_word(hd, SI114X_REG_PS3_DATA0, &ps3) < 0) |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
427 exit(EXIT_FAILURE); |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
428 |
|
95b8b8a0b2d0
add proximity measurement
Peter Meerwald <p.meerwald@bct-electronic.com>
parents:
0
diff
changeset
|
429 printf("%d %d %d %d\n", ps1, ps2, ps3, als); |
| 0 | 430 } |
| 431 | |
| 432 /* never get here */ | |
| 433 printf("done\n"); | |
| 434 | |
| 435 hid_close(hd); | |
| 436 hid_exit(); | |
| 437 | |
| 438 return EXIT_SUCCESS; | |
| 439 } |
