root / hw / baum.c @ c76ee25d
History | View | Annotate | Download (19.9 kB)
1 | 2e4d9fb1 | aurel32 | /*
|
---|---|---|---|
2 | 2e4d9fb1 | aurel32 | * QEMU Baum Braille Device
|
3 | 2e4d9fb1 | aurel32 | *
|
4 | 2e4d9fb1 | aurel32 | * Copyright (c) 2008 Samuel Thibault
|
5 | 2e4d9fb1 | aurel32 | *
|
6 | 2e4d9fb1 | aurel32 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 | 2e4d9fb1 | aurel32 | * of this software and associated documentation files (the "Software"), to deal
|
8 | 2e4d9fb1 | aurel32 | * in the Software without restriction, including without limitation the rights
|
9 | 2e4d9fb1 | aurel32 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 | 2e4d9fb1 | aurel32 | * copies of the Software, and to permit persons to whom the Software is
|
11 | 2e4d9fb1 | aurel32 | * furnished to do so, subject to the following conditions:
|
12 | 2e4d9fb1 | aurel32 | *
|
13 | 2e4d9fb1 | aurel32 | * The above copyright notice and this permission notice shall be included in
|
14 | 2e4d9fb1 | aurel32 | * all copies or substantial portions of the Software.
|
15 | 2e4d9fb1 | aurel32 | *
|
16 | 2e4d9fb1 | aurel32 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 | 2e4d9fb1 | aurel32 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 | 2e4d9fb1 | aurel32 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19 | 2e4d9fb1 | aurel32 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 | 2e4d9fb1 | aurel32 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 | 2e4d9fb1 | aurel32 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22 | 2e4d9fb1 | aurel32 | * THE SOFTWARE.
|
23 | 2e4d9fb1 | aurel32 | */
|
24 | 2e4d9fb1 | aurel32 | #include "qemu-common.h" |
25 | 2e4d9fb1 | aurel32 | #include "qemu-char.h" |
26 | 2e4d9fb1 | aurel32 | #include "qemu-timer.h" |
27 | 2e4d9fb1 | aurel32 | #include "usb.h" |
28 | c78eae61 | aurel32 | #include "baum.h" |
29 | 2e4d9fb1 | aurel32 | #include <assert.h> |
30 | 2e4d9fb1 | aurel32 | #include <brlapi.h> |
31 | 2e4d9fb1 | aurel32 | #include <brlapi_constants.h> |
32 | 2e4d9fb1 | aurel32 | #include <brlapi_keycodes.h> |
33 | 2e4d9fb1 | aurel32 | #ifdef CONFIG_SDL
|
34 | 2e4d9fb1 | aurel32 | #include <SDL/SDL_syswm.h> |
35 | 2e4d9fb1 | aurel32 | #endif
|
36 | 2e4d9fb1 | aurel32 | |
37 | 2e4d9fb1 | aurel32 | #if 0
|
38 | 2e4d9fb1 | aurel32 | #define DPRINTF(fmt, ...) \
|
39 | 2e4d9fb1 | aurel32 | printf(fmt, ## __VA_ARGS__)
|
40 | 2e4d9fb1 | aurel32 | #else
|
41 | 2e4d9fb1 | aurel32 | #define DPRINTF(fmt, ...)
|
42 | 2e4d9fb1 | aurel32 | #endif
|
43 | 2e4d9fb1 | aurel32 | |
44 | 2e4d9fb1 | aurel32 | #define ESC 0x1B |
45 | 2e4d9fb1 | aurel32 | |
46 | 2e4d9fb1 | aurel32 | #define BAUM_REQ_DisplayData 0x01 |
47 | 2e4d9fb1 | aurel32 | #define BAUM_REQ_GetVersionNumber 0x05 |
48 | 2e4d9fb1 | aurel32 | #define BAUM_REQ_GetKeys 0x08 |
49 | 2e4d9fb1 | aurel32 | #define BAUM_REQ_SetMode 0x12 |
50 | 2e4d9fb1 | aurel32 | #define BAUM_REQ_SetProtocol 0x15 |
51 | 2e4d9fb1 | aurel32 | #define BAUM_REQ_GetDeviceIdentity 0x84 |
52 | 2e4d9fb1 | aurel32 | #define BAUM_REQ_GetSerialNumber 0x8A |
53 | 2e4d9fb1 | aurel32 | |
54 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_CellCount 0x01 |
55 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_VersionNumber 0x05 |
56 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_ModeSetting 0x11 |
57 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_CommunicationChannel 0x16 |
58 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_PowerdownSignal 0x17 |
59 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_HorizontalSensors 0x20 |
60 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_VerticalSensors 0x21 |
61 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_RoutingKeys 0x22 |
62 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_Switches 0x23 |
63 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_TopKeys 0x24 |
64 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_HorizontalSensor 0x25 |
65 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_VerticalSensor 0x26 |
66 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_RoutingKey 0x27 |
67 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_FrontKeys6 0x28 |
68 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_BackKeys6 0x29 |
69 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_CommandKeys 0x2B |
70 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_FrontKeys10 0x2C |
71 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_BackKeys10 0x2D |
72 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_EntryKeys 0x33 |
73 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_JoyStick 0x34 |
74 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_ErrorCode 0x40 |
75 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_InfoBlock 0x42 |
76 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_DeviceIdentity 0x84 |
77 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_SerialNumber 0x8A |
78 | 2e4d9fb1 | aurel32 | #define BAUM_RSP_BluetoothName 0x8C |
79 | 2e4d9fb1 | aurel32 | |
80 | 2e4d9fb1 | aurel32 | #define BAUM_TL1 0x01 |
81 | 2e4d9fb1 | aurel32 | #define BAUM_TL2 0x02 |
82 | 2e4d9fb1 | aurel32 | #define BAUM_TL3 0x04 |
83 | 2e4d9fb1 | aurel32 | #define BAUM_TR1 0x08 |
84 | 2e4d9fb1 | aurel32 | #define BAUM_TR2 0x10 |
85 | 2e4d9fb1 | aurel32 | #define BAUM_TR3 0x20 |
86 | 2e4d9fb1 | aurel32 | |
87 | 2e4d9fb1 | aurel32 | #define BUF_SIZE 256 |
88 | 2e4d9fb1 | aurel32 | |
89 | 2e4d9fb1 | aurel32 | typedef struct { |
90 | 2e4d9fb1 | aurel32 | CharDriverState *chr; |
91 | 2e4d9fb1 | aurel32 | |
92 | 2e4d9fb1 | aurel32 | brlapi_handle_t *brlapi; |
93 | 2e4d9fb1 | aurel32 | int brlapi_fd;
|
94 | 2e4d9fb1 | aurel32 | int x, y;
|
95 | 2e4d9fb1 | aurel32 | |
96 | 2e4d9fb1 | aurel32 | uint8_t in_buf[BUF_SIZE]; |
97 | 2e4d9fb1 | aurel32 | uint8_t in_buf_used; |
98 | 2e4d9fb1 | aurel32 | uint8_t out_buf[BUF_SIZE]; |
99 | 2e4d9fb1 | aurel32 | uint8_t out_buf_used, out_buf_ptr; |
100 | 2e4d9fb1 | aurel32 | |
101 | 2e4d9fb1 | aurel32 | QEMUTimer *cellCount_timer; |
102 | 2e4d9fb1 | aurel32 | } BaumDriverState; |
103 | 2e4d9fb1 | aurel32 | |
104 | 2e4d9fb1 | aurel32 | /* Let's assume NABCC by default */
|
105 | 2e4d9fb1 | aurel32 | static const uint8_t nabcc_translation[256] = { |
106 | 2e4d9fb1 | aurel32 | [0] = ' ', |
107 | 2e4d9fb1 | aurel32 | #ifndef BRLAPI_DOTS
|
108 | 2e4d9fb1 | aurel32 | #define BRLAPI_DOTS(d1,d2,d3,d4,d5,d6,d7,d8) \
|
109 | 2e4d9fb1 | aurel32 | ((d1?BRLAPI_DOT1:0)|\
|
110 | 2e4d9fb1 | aurel32 | (d2?BRLAPI_DOT2:0)|\
|
111 | 2e4d9fb1 | aurel32 | (d3?BRLAPI_DOT3:0)|\
|
112 | 2e4d9fb1 | aurel32 | (d4?BRLAPI_DOT4:0)|\
|
113 | 2e4d9fb1 | aurel32 | (d5?BRLAPI_DOT5:0)|\
|
114 | 2e4d9fb1 | aurel32 | (d6?BRLAPI_DOT6:0)|\
|
115 | 2e4d9fb1 | aurel32 | (d7?BRLAPI_DOT7:0)|\
|
116 | 2e4d9fb1 | aurel32 | (d8?BRLAPI_DOT8:0))
|
117 | 2e4d9fb1 | aurel32 | #endif
|
118 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,0,0,0,0,0,0)] = 'a', |
119 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,0,0,0,0,0,0)] = 'b', |
120 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,0,1,0,0,0,0)] = 'c', |
121 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,0,1,1,0,0,0)] = 'd', |
122 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,0,0,1,0,0,0)] = 'e', |
123 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,0,1,0,0,0,0)] = 'f', |
124 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,0,1,1,0,0,0)] = 'g', |
125 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,0,0,1,0,0,0)] = 'h', |
126 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,0,1,0,0,0,0)] = 'i', |
127 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,0,1,1,0,0,0)] = 'j', |
128 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,1,0,0,0,0,0)] = 'k', |
129 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,1,0,0,0,0,0)] = 'l', |
130 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,1,1,0,0,0,0)] = 'm', |
131 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,1,1,1,0,0,0)] = 'n', |
132 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,1,0,1,0,0,0)] = 'o', |
133 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,1,1,0,0,0,0)] = 'p', |
134 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,1,1,1,0,0,0)] = 'q', |
135 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,1,0,1,0,0,0)] = 'r', |
136 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,1,1,0,0,0,0)] = 's', |
137 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,1,1,1,0,0,0)] = 't', |
138 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,1,0,0,1,0,0)] = 'u', |
139 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,1,0,0,1,0,0)] = 'v', |
140 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,0,1,1,1,0,0)] = 'w', |
141 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,1,1,0,1,0,0)] = 'x', |
142 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,1,1,1,1,0,0)] = 'y', |
143 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,1,0,1,1,0,0)] = 'z', |
144 | 2e4d9fb1 | aurel32 | |
145 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,0,0,0,0,1,0)] = 'A', |
146 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,0,0,0,0,1,0)] = 'B', |
147 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,0,1,0,0,1,0)] = 'C', |
148 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,0,1,1,0,1,0)] = 'D', |
149 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,0,0,1,0,1,0)] = 'E', |
150 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,0,1,0,0,1,0)] = 'F', |
151 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,0,1,1,0,1,0)] = 'G', |
152 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,0,0,1,0,1,0)] = 'H', |
153 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,0,1,0,0,1,0)] = 'I', |
154 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,0,1,1,0,1,0)] = 'J', |
155 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,1,0,0,0,1,0)] = 'K', |
156 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,1,0,0,0,1,0)] = 'L', |
157 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,1,1,0,0,1,0)] = 'M', |
158 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,1,1,1,0,1,0)] = 'N', |
159 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,1,0,1,0,1,0)] = 'O', |
160 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,1,1,0,0,1,0)] = 'P', |
161 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,1,1,1,0,1,0)] = 'Q', |
162 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,1,0,1,0,1,0)] = 'R', |
163 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,1,1,0,0,1,0)] = 'S', |
164 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,1,1,1,0,1,0)] = 'T', |
165 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,1,0,0,1,1,0)] = 'U', |
166 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,1,0,0,1,1,0)] = 'V', |
167 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,0,1,1,1,1,0)] = 'W', |
168 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,1,1,0,1,1,0)] = 'X', |
169 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,1,1,1,1,1,0)] = 'Y', |
170 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,1,0,1,1,1,0)] = 'Z', |
171 | 2e4d9fb1 | aurel32 | |
172 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,0,1,0,1,1,0,0)] = '0', |
173 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,0,0,0,0,0,0)] = '1', |
174 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,1,0,0,0,0,0)] = '2', |
175 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,0,0,1,0,0,0)] = '3', |
176 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,0,0,1,1,0,0)] = '4', |
177 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,0,0,0,1,0,0)] = '5', |
178 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,1,0,1,0,0,0)] = '6', |
179 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,1,0,1,1,0,0)] = '7', |
180 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,1,0,0,1,0,0)] = '8', |
181 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,0,1,0,1,0,0,0)] = '9', |
182 | 2e4d9fb1 | aurel32 | |
183 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,0,0,1,0,1,0,0)] = '.', |
184 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,0,1,1,0,1,0,0)] = '+', |
185 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,0,1,0,0,1,0,0)] = '-', |
186 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,0,0,0,1,0,0)] = '*', |
187 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,0,1,1,0,0,0,0)] = '/', |
188 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,1,0,1,1,0,0)] = '(', |
189 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,1,1,1,1,0,0)] = ')', |
190 | 2e4d9fb1 | aurel32 | |
191 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,1,1,0,1,0,0)] = '&', |
192 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,0,1,1,1,1,0,0)] = '#', |
193 | 2e4d9fb1 | aurel32 | |
194 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,0,0,0,0,1,0,0)] = ',', |
195 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,0,0,0,1,1,0,0)] = ';', |
196 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,0,0,1,1,0,0)] = ':', |
197 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,1,1,0,1,0,0)] = '!', |
198 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,0,1,1,1,0,0)] = '?', |
199 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,0,0,0,1,0,0,0)] = '"', |
200 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,0,1,0,0,0,0,0)] ='\'', |
201 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,0,0,1,0,0,0,0)] = '`', |
202 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,0,0,1,1,0,1,0)] = '^', |
203 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,0,0,1,1,0,0,0)] = '~', |
204 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,0,1,0,1,1,0)] = '[', |
205 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,0,1,1,1,1,0)] = ']', |
206 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,1,0,1,0,1,0,0)] = '{', |
207 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,0,1,1,1,0,0)] = '}', |
208 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,1,1,1,1,0,0)] = '=', |
209 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,0,0,0,1,0,0)] = '<', |
210 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,0,1,1,1,0,0,0)] = '>', |
211 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,0,1,0,1,0,0)] = '$', |
212 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,0,0,1,0,1,0,0)] = '%', |
213 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,0,0,1,0,0,1,0)] = '@', |
214 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,0,0,1,1,0,0)] = '|', |
215 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(1,1,0,0,1,1,1,0)] ='\\', |
216 | 2e4d9fb1 | aurel32 | [BRLAPI_DOTS(0,0,0,1,1,1,0,0)] = '_', |
217 | 2e4d9fb1 | aurel32 | }; |
218 | 2e4d9fb1 | aurel32 | |
219 | 2e4d9fb1 | aurel32 | /* The serial port can receive more of our data */
|
220 | 2e4d9fb1 | aurel32 | static void baum_accept_input(struct CharDriverState *chr) |
221 | 2e4d9fb1 | aurel32 | { |
222 | 2e4d9fb1 | aurel32 | BaumDriverState *baum = chr->opaque; |
223 | 2e4d9fb1 | aurel32 | int room, first;
|
224 | 2e4d9fb1 | aurel32 | |
225 | 2e4d9fb1 | aurel32 | if (!baum->out_buf_used)
|
226 | 2e4d9fb1 | aurel32 | return;
|
227 | 2e4d9fb1 | aurel32 | room = qemu_chr_can_read(chr); |
228 | 2e4d9fb1 | aurel32 | if (!room)
|
229 | 2e4d9fb1 | aurel32 | return;
|
230 | 2e4d9fb1 | aurel32 | if (room > baum->out_buf_used)
|
231 | 2e4d9fb1 | aurel32 | room = baum->out_buf_used; |
232 | 2e4d9fb1 | aurel32 | |
233 | 2e4d9fb1 | aurel32 | first = BUF_SIZE - baum->out_buf_ptr; |
234 | 2e4d9fb1 | aurel32 | if (room > first) {
|
235 | 2e4d9fb1 | aurel32 | qemu_chr_read(chr, baum->out_buf + baum->out_buf_ptr, first); |
236 | 2e4d9fb1 | aurel32 | baum->out_buf_ptr = 0;
|
237 | 2e4d9fb1 | aurel32 | baum->out_buf_used -= first; |
238 | 2e4d9fb1 | aurel32 | room -= first; |
239 | 2e4d9fb1 | aurel32 | } |
240 | 2e4d9fb1 | aurel32 | qemu_chr_read(chr, baum->out_buf + baum->out_buf_ptr, room); |
241 | 2e4d9fb1 | aurel32 | baum->out_buf_ptr += room; |
242 | 2e4d9fb1 | aurel32 | baum->out_buf_used -= room; |
243 | 2e4d9fb1 | aurel32 | } |
244 | 2e4d9fb1 | aurel32 | |
245 | 2e4d9fb1 | aurel32 | /* We want to send a packet */
|
246 | 2e4d9fb1 | aurel32 | static void baum_write_packet(BaumDriverState *baum, const uint8_t *buf, int len) |
247 | 2e4d9fb1 | aurel32 | { |
248 | 2e4d9fb1 | aurel32 | uint8_t io_buf[1 + 2 * len], *cur = io_buf; |
249 | 2e4d9fb1 | aurel32 | int room;
|
250 | 2e4d9fb1 | aurel32 | *cur++ = ESC; |
251 | 2e4d9fb1 | aurel32 | while (len--)
|
252 | 2e4d9fb1 | aurel32 | if ((*cur++ = *buf++) == ESC)
|
253 | 2e4d9fb1 | aurel32 | *cur++ = ESC; |
254 | 2e4d9fb1 | aurel32 | room = qemu_chr_can_read(baum->chr); |
255 | 2e4d9fb1 | aurel32 | len = cur - io_buf; |
256 | 2e4d9fb1 | aurel32 | if (len <= room) {
|
257 | 2e4d9fb1 | aurel32 | /* Fits */
|
258 | 2e4d9fb1 | aurel32 | qemu_chr_read(baum->chr, io_buf, len); |
259 | 2e4d9fb1 | aurel32 | } else {
|
260 | 2e4d9fb1 | aurel32 | int first;
|
261 | 2e4d9fb1 | aurel32 | uint8_t out; |
262 | 2e4d9fb1 | aurel32 | /* Can't fit all, send what can be, and store the rest. */
|
263 | 2e4d9fb1 | aurel32 | qemu_chr_read(baum->chr, io_buf, room); |
264 | 2e4d9fb1 | aurel32 | len -= room; |
265 | 2e4d9fb1 | aurel32 | cur = io_buf + room; |
266 | 2e4d9fb1 | aurel32 | if (len > BUF_SIZE - baum->out_buf_used) {
|
267 | 2e4d9fb1 | aurel32 | /* Can't even store it, drop the previous data... */
|
268 | 2e4d9fb1 | aurel32 | assert(len <= BUF_SIZE); |
269 | 2e4d9fb1 | aurel32 | baum->out_buf_used = 0;
|
270 | 2e4d9fb1 | aurel32 | baum->out_buf_ptr = 0;
|
271 | 2e4d9fb1 | aurel32 | } |
272 | 2e4d9fb1 | aurel32 | out = baum->out_buf_ptr; |
273 | 2e4d9fb1 | aurel32 | baum->out_buf_used += len; |
274 | 2e4d9fb1 | aurel32 | first = BUF_SIZE - baum->out_buf_ptr; |
275 | 2e4d9fb1 | aurel32 | if (len > first) {
|
276 | 2e4d9fb1 | aurel32 | memcpy(baum->out_buf + out, cur, first); |
277 | 2e4d9fb1 | aurel32 | out = 0;
|
278 | 2e4d9fb1 | aurel32 | len -= first; |
279 | 2e4d9fb1 | aurel32 | cur += first; |
280 | 2e4d9fb1 | aurel32 | } |
281 | 2e4d9fb1 | aurel32 | memcpy(baum->out_buf + out, cur, len); |
282 | 2e4d9fb1 | aurel32 | } |
283 | 2e4d9fb1 | aurel32 | } |
284 | 2e4d9fb1 | aurel32 | |
285 | 2e4d9fb1 | aurel32 | /* Called when the other end seems to have a wrong idea of our display size */
|
286 | 2e4d9fb1 | aurel32 | static void baum_cellCount_timer_cb(void *opaque) |
287 | 2e4d9fb1 | aurel32 | { |
288 | 2e4d9fb1 | aurel32 | BaumDriverState *baum = opaque; |
289 | 2e4d9fb1 | aurel32 | uint8_t cell_count[] = { BAUM_RSP_CellCount, baum->x * baum->y }; |
290 | 2e4d9fb1 | aurel32 | DPRINTF("Timeout waiting for DisplayData, sending cell count\n");
|
291 | 2e4d9fb1 | aurel32 | baum_write_packet(baum, cell_count, sizeof(cell_count));
|
292 | 2e4d9fb1 | aurel32 | } |
293 | 2e4d9fb1 | aurel32 | |
294 | 2e4d9fb1 | aurel32 | /* Try to interpret a whole incoming packet */
|
295 | 2e4d9fb1 | aurel32 | static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len) |
296 | 2e4d9fb1 | aurel32 | { |
297 | 2e4d9fb1 | aurel32 | const uint8_t *cur = buf;
|
298 | 2e4d9fb1 | aurel32 | uint8_t req = 0;
|
299 | 2e4d9fb1 | aurel32 | |
300 | 2e4d9fb1 | aurel32 | if (!len--)
|
301 | 2e4d9fb1 | aurel32 | return 0; |
302 | 2e4d9fb1 | aurel32 | if (*cur++ != ESC) {
|
303 | 2e4d9fb1 | aurel32 | while (*cur != ESC) {
|
304 | 2e4d9fb1 | aurel32 | if (!len--)
|
305 | 2e4d9fb1 | aurel32 | return 0; |
306 | 2e4d9fb1 | aurel32 | cur++; |
307 | 2e4d9fb1 | aurel32 | } |
308 | 2e4d9fb1 | aurel32 | DPRINTF("Dropped %d bytes!\n", cur - buf);
|
309 | 2e4d9fb1 | aurel32 | } |
310 | 2e4d9fb1 | aurel32 | |
311 | 2e4d9fb1 | aurel32 | #define EAT(c) do {\ |
312 | 2e4d9fb1 | aurel32 | if (!len--) \
|
313 | 2e4d9fb1 | aurel32 | return 0; \ |
314 | 2e4d9fb1 | aurel32 | if ((c = *cur++) == ESC) { \
|
315 | 2e4d9fb1 | aurel32 | if (!len--) \
|
316 | 2e4d9fb1 | aurel32 | return 0; \ |
317 | 2e4d9fb1 | aurel32 | if (*cur++ != ESC) { \
|
318 | 2e4d9fb1 | aurel32 | DPRINTF("Broken packet %#2x, tossing\n", req); \
|
319 | 2e4d9fb1 | aurel32 | if (qemu_timer_pending(baum->cellCount_timer)) { \
|
320 | 2e4d9fb1 | aurel32 | qemu_del_timer(baum->cellCount_timer); \ |
321 | 2e4d9fb1 | aurel32 | baum_cellCount_timer_cb(baum); \ |
322 | 2e4d9fb1 | aurel32 | } \ |
323 | 2e4d9fb1 | aurel32 | return (cur - 2 - buf); \ |
324 | 2e4d9fb1 | aurel32 | } \ |
325 | 2e4d9fb1 | aurel32 | } \ |
326 | 2e4d9fb1 | aurel32 | } while (0) |
327 | 2e4d9fb1 | aurel32 | |
328 | 2e4d9fb1 | aurel32 | EAT(req); |
329 | 2e4d9fb1 | aurel32 | switch (req) {
|
330 | 2e4d9fb1 | aurel32 | case BAUM_REQ_DisplayData:
|
331 | 2e4d9fb1 | aurel32 | { |
332 | 2e4d9fb1 | aurel32 | uint8_t cells[baum->x * baum->y], c; |
333 | 2e4d9fb1 | aurel32 | uint8_t text[baum->x * baum->y]; |
334 | 2e4d9fb1 | aurel32 | uint8_t zero[baum->x * baum->y]; |
335 | 2e4d9fb1 | aurel32 | int cursor = BRLAPI_CURSOR_OFF;
|
336 | 2e4d9fb1 | aurel32 | int i;
|
337 | 2e4d9fb1 | aurel32 | |
338 | 2e4d9fb1 | aurel32 | /* Allow 100ms to complete the DisplayData packet */
|
339 | 2e4d9fb1 | aurel32 | qemu_mod_timer(baum->cellCount_timer, qemu_get_clock(vm_clock) + ticks_per_sec / 10);
|
340 | 2e4d9fb1 | aurel32 | for (i = 0; i < baum->x * baum->y ; i++) { |
341 | 2e4d9fb1 | aurel32 | EAT(c); |
342 | 2e4d9fb1 | aurel32 | cells[i] = c; |
343 | 2e4d9fb1 | aurel32 | if ((c & (BRLAPI_DOT7|BRLAPI_DOT8))
|
344 | 2e4d9fb1 | aurel32 | == (BRLAPI_DOT7|BRLAPI_DOT8)) { |
345 | 2e4d9fb1 | aurel32 | cursor = i + 1;
|
346 | 2e4d9fb1 | aurel32 | c &= ~(BRLAPI_DOT7|BRLAPI_DOT8); |
347 | 2e4d9fb1 | aurel32 | } |
348 | 2e4d9fb1 | aurel32 | if (!(c = nabcc_translation[c]))
|
349 | 2e4d9fb1 | aurel32 | c = '?';
|
350 | 2e4d9fb1 | aurel32 | text[i] = c; |
351 | 2e4d9fb1 | aurel32 | } |
352 | 2e4d9fb1 | aurel32 | qemu_del_timer(baum->cellCount_timer); |
353 | 2e4d9fb1 | aurel32 | |
354 | 2e4d9fb1 | aurel32 | memset(zero, 0, sizeof(zero)); |
355 | 2e4d9fb1 | aurel32 | |
356 | 2e4d9fb1 | aurel32 | brlapi_writeArguments_t wa = { |
357 | 2e4d9fb1 | aurel32 | .displayNumber = BRLAPI_DISPLAY_DEFAULT, |
358 | 2e4d9fb1 | aurel32 | .regionBegin = 1,
|
359 | 2e4d9fb1 | aurel32 | .regionSize = baum->x * baum->y, |
360 | 2e4d9fb1 | aurel32 | .text = text, |
361 | 2e4d9fb1 | aurel32 | .textSize = baum->x * baum->y, |
362 | 2e4d9fb1 | aurel32 | .andMask = zero, |
363 | 2e4d9fb1 | aurel32 | .orMask = cells, |
364 | 2e4d9fb1 | aurel32 | .cursor = cursor, |
365 | 2e4d9fb1 | aurel32 | .charset = "ISO-8859-1",
|
366 | 2e4d9fb1 | aurel32 | }; |
367 | 2e4d9fb1 | aurel32 | |
368 | 2e4d9fb1 | aurel32 | if (brlapi__write(baum->brlapi, &wa) == -1) |
369 | 2e4d9fb1 | aurel32 | brlapi_perror("baum brlapi_write");
|
370 | 2e4d9fb1 | aurel32 | break;
|
371 | 2e4d9fb1 | aurel32 | } |
372 | 2e4d9fb1 | aurel32 | case BAUM_REQ_SetMode:
|
373 | 2e4d9fb1 | aurel32 | { |
374 | 2e4d9fb1 | aurel32 | uint8_t mode, setting; |
375 | 2e4d9fb1 | aurel32 | DPRINTF("SetMode\n");
|
376 | 2e4d9fb1 | aurel32 | EAT(mode); |
377 | 2e4d9fb1 | aurel32 | EAT(setting); |
378 | 2e4d9fb1 | aurel32 | /* ignore */
|
379 | 2e4d9fb1 | aurel32 | break;
|
380 | 2e4d9fb1 | aurel32 | } |
381 | 2e4d9fb1 | aurel32 | case BAUM_REQ_SetProtocol:
|
382 | 2e4d9fb1 | aurel32 | { |
383 | 2e4d9fb1 | aurel32 | uint8_t protocol; |
384 | 2e4d9fb1 | aurel32 | DPRINTF("SetProtocol\n");
|
385 | 2e4d9fb1 | aurel32 | EAT(protocol); |
386 | 2e4d9fb1 | aurel32 | /* ignore */
|
387 | 2e4d9fb1 | aurel32 | break;
|
388 | 2e4d9fb1 | aurel32 | } |
389 | 2e4d9fb1 | aurel32 | case BAUM_REQ_GetDeviceIdentity:
|
390 | 2e4d9fb1 | aurel32 | { |
391 | 2e4d9fb1 | aurel32 | uint8_t identity[17] = { BAUM_RSP_DeviceIdentity,
|
392 | 2e4d9fb1 | aurel32 | 'B','a','u','m',' ','V','a','r','i','o' }; |
393 | 2e4d9fb1 | aurel32 | DPRINTF("GetDeviceIdentity\n");
|
394 | 2e4d9fb1 | aurel32 | identity[11] = '0' + baum->x / 10; |
395 | 2e4d9fb1 | aurel32 | identity[12] = '0' + baum->x % 10; |
396 | 2e4d9fb1 | aurel32 | baum_write_packet(baum, identity, sizeof(identity));
|
397 | 2e4d9fb1 | aurel32 | break;
|
398 | 2e4d9fb1 | aurel32 | } |
399 | 2e4d9fb1 | aurel32 | case BAUM_REQ_GetVersionNumber:
|
400 | 2e4d9fb1 | aurel32 | { |
401 | 2e4d9fb1 | aurel32 | uint8_t version[] = { BAUM_RSP_VersionNumber, 1 }; /* ? */ |
402 | 2e4d9fb1 | aurel32 | DPRINTF("GetVersionNumber\n");
|
403 | 2e4d9fb1 | aurel32 | baum_write_packet(baum, version, sizeof(version));
|
404 | 2e4d9fb1 | aurel32 | break;
|
405 | 2e4d9fb1 | aurel32 | } |
406 | 2e4d9fb1 | aurel32 | case BAUM_REQ_GetSerialNumber:
|
407 | 2e4d9fb1 | aurel32 | { |
408 | 2e4d9fb1 | aurel32 | uint8_t serial[] = { BAUM_RSP_SerialNumber, |
409 | 2e4d9fb1 | aurel32 | '0','0','0','0','0','0','0','0' }; |
410 | 2e4d9fb1 | aurel32 | DPRINTF("GetSerialNumber\n");
|
411 | 2e4d9fb1 | aurel32 | baum_write_packet(baum, serial, sizeof(serial));
|
412 | 2e4d9fb1 | aurel32 | break;
|
413 | 2e4d9fb1 | aurel32 | } |
414 | 2e4d9fb1 | aurel32 | case BAUM_REQ_GetKeys:
|
415 | 2e4d9fb1 | aurel32 | { |
416 | 2e4d9fb1 | aurel32 | DPRINTF("Get%0#2x\n", req);
|
417 | 2e4d9fb1 | aurel32 | /* ignore */
|
418 | 2e4d9fb1 | aurel32 | break;
|
419 | 2e4d9fb1 | aurel32 | } |
420 | 2e4d9fb1 | aurel32 | default:
|
421 | 2e4d9fb1 | aurel32 | DPRINTF("unrecognized request %0#2x\n", req);
|
422 | 2e4d9fb1 | aurel32 | do
|
423 | 2e4d9fb1 | aurel32 | if (!len--)
|
424 | 2e4d9fb1 | aurel32 | return 0; |
425 | 2e4d9fb1 | aurel32 | while (*cur++ != ESC);
|
426 | 2e4d9fb1 | aurel32 | cur--; |
427 | 2e4d9fb1 | aurel32 | break;
|
428 | 2e4d9fb1 | aurel32 | } |
429 | 2e4d9fb1 | aurel32 | return cur - buf;
|
430 | 2e4d9fb1 | aurel32 | } |
431 | 2e4d9fb1 | aurel32 | |
432 | 2e4d9fb1 | aurel32 | /* The other end is writing some data. Store it and try to interpret */
|
433 | 2e4d9fb1 | aurel32 | static int baum_write(CharDriverState *chr, const uint8_t *buf, int len) |
434 | 2e4d9fb1 | aurel32 | { |
435 | 2e4d9fb1 | aurel32 | BaumDriverState *baum = chr->opaque; |
436 | 2e4d9fb1 | aurel32 | int tocopy, cur, eaten, orig_len = len;
|
437 | 2e4d9fb1 | aurel32 | |
438 | 2e4d9fb1 | aurel32 | if (!len)
|
439 | 2e4d9fb1 | aurel32 | return 0; |
440 | 2e4d9fb1 | aurel32 | if (!baum->brlapi)
|
441 | 2e4d9fb1 | aurel32 | return len;
|
442 | 2e4d9fb1 | aurel32 | |
443 | 2e4d9fb1 | aurel32 | while (len) {
|
444 | 2e4d9fb1 | aurel32 | /* Complete our buffer as much as possible */
|
445 | 2e4d9fb1 | aurel32 | tocopy = len; |
446 | 2e4d9fb1 | aurel32 | if (tocopy > BUF_SIZE - baum->in_buf_used)
|
447 | 2e4d9fb1 | aurel32 | tocopy = BUF_SIZE - baum->in_buf_used; |
448 | 2e4d9fb1 | aurel32 | |
449 | 2e4d9fb1 | aurel32 | memcpy(baum->in_buf + baum->in_buf_used, buf, tocopy); |
450 | 2e4d9fb1 | aurel32 | baum->in_buf_used += tocopy; |
451 | 2e4d9fb1 | aurel32 | buf += tocopy; |
452 | 2e4d9fb1 | aurel32 | len -= tocopy; |
453 | 2e4d9fb1 | aurel32 | |
454 | 2e4d9fb1 | aurel32 | /* Interpret it as much as possible */
|
455 | 2e4d9fb1 | aurel32 | cur = 0;
|
456 | 2e4d9fb1 | aurel32 | while (cur < baum->in_buf_used &&
|
457 | 2e4d9fb1 | aurel32 | (eaten = baum_eat_packet(baum, baum->in_buf + cur, baum->in_buf_used - cur))) |
458 | 2e4d9fb1 | aurel32 | cur += eaten; |
459 | 2e4d9fb1 | aurel32 | |
460 | 2e4d9fb1 | aurel32 | /* Shift the remainder */
|
461 | 2e4d9fb1 | aurel32 | if (cur) {
|
462 | 2e4d9fb1 | aurel32 | memmove(baum->in_buf, baum->in_buf + cur, baum->in_buf_used - cur); |
463 | 2e4d9fb1 | aurel32 | baum->in_buf_used -= cur; |
464 | 2e4d9fb1 | aurel32 | } |
465 | 2e4d9fb1 | aurel32 | |
466 | 2e4d9fb1 | aurel32 | /* And continue if any data left */
|
467 | 2e4d9fb1 | aurel32 | } |
468 | 2e4d9fb1 | aurel32 | return orig_len;
|
469 | 2e4d9fb1 | aurel32 | } |
470 | 2e4d9fb1 | aurel32 | |
471 | 2e4d9fb1 | aurel32 | /* The other end sent us some event */
|
472 | 2e4d9fb1 | aurel32 | static void baum_send_event(CharDriverState *chr, int event) |
473 | 2e4d9fb1 | aurel32 | { |
474 | 2e4d9fb1 | aurel32 | BaumDriverState *baum = chr->opaque; |
475 | 2e4d9fb1 | aurel32 | switch (event) {
|
476 | 2e4d9fb1 | aurel32 | case CHR_EVENT_BREAK:
|
477 | 2e4d9fb1 | aurel32 | break;
|
478 | 2e4d9fb1 | aurel32 | case CHR_EVENT_RESET:
|
479 | 2e4d9fb1 | aurel32 | /* Reset state */
|
480 | 2e4d9fb1 | aurel32 | baum->in_buf_used = 0;
|
481 | 2e4d9fb1 | aurel32 | break;
|
482 | 2e4d9fb1 | aurel32 | } |
483 | 2e4d9fb1 | aurel32 | } |
484 | 2e4d9fb1 | aurel32 | |
485 | 2e4d9fb1 | aurel32 | /* Send the key code to the other end */
|
486 | 2e4d9fb1 | aurel32 | static void baum_send_key(BaumDriverState *baum, uint8_t type, uint8_t value) { |
487 | 2e4d9fb1 | aurel32 | uint8_t packet[] = { type, value }; |
488 | 2e4d9fb1 | aurel32 | DPRINTF("writing key %x %x\n", type, value);
|
489 | 2e4d9fb1 | aurel32 | baum_write_packet(baum, packet, sizeof(packet));
|
490 | 2e4d9fb1 | aurel32 | } |
491 | 2e4d9fb1 | aurel32 | |
492 | 2e4d9fb1 | aurel32 | /* We got some data on the BrlAPI socket */
|
493 | 2e4d9fb1 | aurel32 | static void baum_chr_read(void *opaque) |
494 | 2e4d9fb1 | aurel32 | { |
495 | 2e4d9fb1 | aurel32 | BaumDriverState *baum = opaque; |
496 | 2e4d9fb1 | aurel32 | brlapi_keyCode_t code; |
497 | 2e4d9fb1 | aurel32 | int ret;
|
498 | 2e4d9fb1 | aurel32 | if (!baum->brlapi)
|
499 | 2e4d9fb1 | aurel32 | return;
|
500 | 2e4d9fb1 | aurel32 | while ((ret = brlapi__readKey(baum->brlapi, 0, &code)) == 1) { |
501 | 2e4d9fb1 | aurel32 | DPRINTF("got key %"BRLAPI_PRIxKEYCODE"\n", code); |
502 | 2e4d9fb1 | aurel32 | /* Emulate */
|
503 | 2e4d9fb1 | aurel32 | switch (code & BRLAPI_KEY_TYPE_MASK) {
|
504 | 2e4d9fb1 | aurel32 | case BRLAPI_KEY_TYPE_CMD:
|
505 | 2e4d9fb1 | aurel32 | switch (code & BRLAPI_KEY_CMD_BLK_MASK) {
|
506 | 2e4d9fb1 | aurel32 | case BRLAPI_KEY_CMD_ROUTE:
|
507 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_RoutingKey, (code & BRLAPI_KEY_CMD_ARG_MASK)+1);
|
508 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_RoutingKey, 0);
|
509 | 2e4d9fb1 | aurel32 | break;
|
510 | 2e4d9fb1 | aurel32 | case 0: |
511 | 2e4d9fb1 | aurel32 | switch (code & BRLAPI_KEY_CMD_ARG_MASK) {
|
512 | 2e4d9fb1 | aurel32 | case BRLAPI_KEY_CMD_FWINLT:
|
513 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2); |
514 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, 0);
|
515 | 2e4d9fb1 | aurel32 | break;
|
516 | 2e4d9fb1 | aurel32 | case BRLAPI_KEY_CMD_FWINRT:
|
517 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR2); |
518 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, 0);
|
519 | 2e4d9fb1 | aurel32 | break;
|
520 | 2e4d9fb1 | aurel32 | case BRLAPI_KEY_CMD_LNUP:
|
521 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR1); |
522 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, 0);
|
523 | 2e4d9fb1 | aurel32 | break;
|
524 | 2e4d9fb1 | aurel32 | case BRLAPI_KEY_CMD_LNDN:
|
525 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR3); |
526 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, 0);
|
527 | 2e4d9fb1 | aurel32 | break;
|
528 | 2e4d9fb1 | aurel32 | case BRLAPI_KEY_CMD_TOP:
|
529 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TR1); |
530 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, 0);
|
531 | 2e4d9fb1 | aurel32 | break;
|
532 | 2e4d9fb1 | aurel32 | case BRLAPI_KEY_CMD_BOT:
|
533 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL3|BAUM_TR3); |
534 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, 0);
|
535 | 2e4d9fb1 | aurel32 | break;
|
536 | 2e4d9fb1 | aurel32 | case BRLAPI_KEY_CMD_TOP_LEFT:
|
537 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1); |
538 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, 0);
|
539 | 2e4d9fb1 | aurel32 | break;
|
540 | 2e4d9fb1 | aurel32 | case BRLAPI_KEY_CMD_BOT_LEFT:
|
541 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR3); |
542 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, 0);
|
543 | 2e4d9fb1 | aurel32 | break;
|
544 | 2e4d9fb1 | aurel32 | case BRLAPI_KEY_CMD_HOME:
|
545 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1|BAUM_TR3); |
546 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, 0);
|
547 | 2e4d9fb1 | aurel32 | break;
|
548 | 2e4d9fb1 | aurel32 | case BRLAPI_KEY_CMD_PREFMENU:
|
549 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TL3|BAUM_TR1); |
550 | 2e4d9fb1 | aurel32 | baum_send_key(baum, BAUM_RSP_TopKeys, 0);
|
551 | 2e4d9fb1 | aurel32 | break;
|
552 | 2e4d9fb1 | aurel32 | } |
553 | 2e4d9fb1 | aurel32 | } |
554 | 2e4d9fb1 | aurel32 | break;
|
555 | 2e4d9fb1 | aurel32 | case BRLAPI_KEY_TYPE_SYM:
|
556 | 2e4d9fb1 | aurel32 | break;
|
557 | 2e4d9fb1 | aurel32 | } |
558 | 2e4d9fb1 | aurel32 | } |
559 | 2e4d9fb1 | aurel32 | if (ret == -1 && (brlapi_errno != BRLAPI_ERROR_LIBCERR || errno != EINTR)) { |
560 | 2e4d9fb1 | aurel32 | brlapi_perror("baum: brlapi_readKey");
|
561 | 2e4d9fb1 | aurel32 | brlapi__closeConnection(baum->brlapi); |
562 | 2e4d9fb1 | aurel32 | free(baum->brlapi); |
563 | 2e4d9fb1 | aurel32 | baum->brlapi = NULL;
|
564 | 2e4d9fb1 | aurel32 | } |
565 | 2e4d9fb1 | aurel32 | } |
566 | 2e4d9fb1 | aurel32 | |
567 | 2e4d9fb1 | aurel32 | CharDriverState *chr_baum_init(void)
|
568 | 2e4d9fb1 | aurel32 | { |
569 | 2e4d9fb1 | aurel32 | BaumDriverState *baum; |
570 | 2e4d9fb1 | aurel32 | CharDriverState *chr; |
571 | 2e4d9fb1 | aurel32 | brlapi_handle_t *handle; |
572 | 2e4d9fb1 | aurel32 | #ifdef CONFIG_SDL
|
573 | 2e4d9fb1 | aurel32 | SDL_SysWMinfo info; |
574 | 2e4d9fb1 | aurel32 | #endif
|
575 | 2e4d9fb1 | aurel32 | int tty;
|
576 | 2e4d9fb1 | aurel32 | |
577 | 2e4d9fb1 | aurel32 | baum = qemu_mallocz(sizeof(BaumDriverState));
|
578 | 2e4d9fb1 | aurel32 | if (!baum)
|
579 | 2e4d9fb1 | aurel32 | return NULL; |
580 | 2e4d9fb1 | aurel32 | |
581 | 2e4d9fb1 | aurel32 | baum->chr = chr = qemu_mallocz(sizeof(CharDriverState));
|
582 | 2e4d9fb1 | aurel32 | if (!chr)
|
583 | 2e4d9fb1 | aurel32 | goto fail_baum;
|
584 | 2e4d9fb1 | aurel32 | |
585 | 2e4d9fb1 | aurel32 | chr->opaque = baum; |
586 | 2e4d9fb1 | aurel32 | chr->chr_write = baum_write; |
587 | 2e4d9fb1 | aurel32 | chr->chr_send_event = baum_send_event; |
588 | 2e4d9fb1 | aurel32 | chr->chr_accept_input = baum_accept_input; |
589 | 2e4d9fb1 | aurel32 | |
590 | 2e4d9fb1 | aurel32 | handle = qemu_mallocz(brlapi_getHandleSize()); |
591 | 2e4d9fb1 | aurel32 | if (!handle)
|
592 | 2e4d9fb1 | aurel32 | goto fail_chr;
|
593 | 2e4d9fb1 | aurel32 | baum->brlapi = handle; |
594 | 2e4d9fb1 | aurel32 | |
595 | 2e4d9fb1 | aurel32 | baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL); |
596 | 2e4d9fb1 | aurel32 | if (baum->brlapi_fd == -1) { |
597 | 2e4d9fb1 | aurel32 | brlapi_perror("baum_init: brlapi_openConnection");
|
598 | 2e4d9fb1 | aurel32 | goto fail_handle;
|
599 | 2e4d9fb1 | aurel32 | } |
600 | 2e4d9fb1 | aurel32 | |
601 | 2e4d9fb1 | aurel32 | baum->cellCount_timer = qemu_new_timer(vm_clock, baum_cellCount_timer_cb, baum); |
602 | 2e4d9fb1 | aurel32 | |
603 | 2e4d9fb1 | aurel32 | if (brlapi__getDisplaySize(handle, &baum->x, &baum->y) == -1) { |
604 | 2e4d9fb1 | aurel32 | brlapi_perror("baum_init: brlapi_getDisplaySize");
|
605 | 2e4d9fb1 | aurel32 | goto fail;
|
606 | 2e4d9fb1 | aurel32 | } |
607 | 2e4d9fb1 | aurel32 | |
608 | 2e4d9fb1 | aurel32 | #ifdef CONFIG_SDL
|
609 | 2e4d9fb1 | aurel32 | memset(&info, 0, sizeof(info)); |
610 | 2e4d9fb1 | aurel32 | SDL_VERSION(&info.version); |
611 | 2e4d9fb1 | aurel32 | if (SDL_GetWMInfo(&info))
|
612 | 2e4d9fb1 | aurel32 | tty = info.info.x11.wmwindow; |
613 | 2e4d9fb1 | aurel32 | else
|
614 | 2e4d9fb1 | aurel32 | #endif
|
615 | 2e4d9fb1 | aurel32 | tty = BRLAPI_TTY_DEFAULT; |
616 | 2e4d9fb1 | aurel32 | |
617 | 2e4d9fb1 | aurel32 | if (brlapi__enterTtyMode(handle, tty, NULL) == -1) { |
618 | 2e4d9fb1 | aurel32 | brlapi_perror("baum_init: brlapi_enterTtyMode");
|
619 | 2e4d9fb1 | aurel32 | goto fail;
|
620 | 2e4d9fb1 | aurel32 | } |
621 | 2e4d9fb1 | aurel32 | |
622 | 2e4d9fb1 | aurel32 | qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
|
623 | 2e4d9fb1 | aurel32 | |
624 | 2e4d9fb1 | aurel32 | qemu_chr_reset(chr); |
625 | 2e4d9fb1 | aurel32 | |
626 | 2e4d9fb1 | aurel32 | return chr;
|
627 | 2e4d9fb1 | aurel32 | |
628 | 2e4d9fb1 | aurel32 | fail:
|
629 | 2e4d9fb1 | aurel32 | qemu_free_timer(baum->cellCount_timer); |
630 | 2e4d9fb1 | aurel32 | brlapi__closeConnection(handle); |
631 | 2e4d9fb1 | aurel32 | fail_handle:
|
632 | 2e4d9fb1 | aurel32 | free(handle); |
633 | 2e4d9fb1 | aurel32 | fail_chr:
|
634 | 2e4d9fb1 | aurel32 | free(chr); |
635 | 2e4d9fb1 | aurel32 | fail_baum:
|
636 | 2e4d9fb1 | aurel32 | free(baum); |
637 | 2e4d9fb1 | aurel32 | return NULL; |
638 | 2e4d9fb1 | aurel32 | } |
639 | 2e4d9fb1 | aurel32 | |
640 | 2e4d9fb1 | aurel32 | USBDevice *usb_baum_init(void)
|
641 | 2e4d9fb1 | aurel32 | { |
642 | 2e4d9fb1 | aurel32 | /* USB Product ID of Super Vario 40 */
|
643 | 2e4d9fb1 | aurel32 | return usb_serial_init("productid=FE72:braille"); |
644 | 2e4d9fb1 | aurel32 | } |